summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CREDITS8
-rw-r--r--Documentation/cciss.txt3
-rw-r--r--Documentation/cdrom/packet-writing.txt3
-rw-r--r--Documentation/feature-removal-schedule.txt14
-rw-r--r--Documentation/filesystems/00-INDEX2
-rw-r--r--Documentation/filesystems/umsdos.txt100
-rw-r--r--Documentation/kernel-parameters.txt6
-rw-r--r--Documentation/networking/pktgen.txt291
-rw-r--r--Documentation/power/devices.txt88
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt54
-rw-r--r--Documentation/x86_64/boot-options.txt40
-rw-r--r--MAINTAINERS37
-rw-r--r--Makefile4
-rw-r--r--arch/arm/Kconfig19
-rw-r--r--arch/arm/boot/compressed/Makefile4
-rw-r--r--arch/arm/boot/compressed/head-sharpsl.S92
-rw-r--r--arch/arm/common/Makefile1
-rw-r--r--arch/arm/common/amba.c2
-rw-r--r--arch/arm/common/locomo.c2
-rw-r--r--arch/arm/common/sa1111.c2
-rw-r--r--arch/arm/common/scoop.c134
-rw-r--r--arch/arm/kernel/irq.c129
-rw-r--r--arch/arm/kernel/semaphore.c2
-rw-r--r--arch/arm/kernel/smp.c20
-rw-r--r--arch/arm/lib/io-readsw-armv4.S87
-rw-r--r--arch/arm/lib/io-writesw-armv4.S62
-rw-r--r--arch/arm/mach-ixp4xx/coyote-pci.c1
-rw-r--r--arch/arm/mach-ixp4xx/coyote-setup.c1
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-pci.c1
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c1
-rw-r--r--arch/arm/mach-ixp4xx/ixdpg425-pci.c1
-rw-r--r--arch/arm/mach-ixp4xx/prpmc1100-pci.c1
-rw-r--r--arch/arm/mach-ixp4xx/prpmc1100-setup.c1
-rw-r--r--arch/arm/mach-pxa/Kconfig20
-rw-r--r--arch/arm/mach-pxa/Makefile1
-rw-r--r--arch/arm/mach-pxa/corgi.c165
-rw-r--r--arch/arm/mach-pxa/corgi_ssp.c247
-rw-r--r--arch/arm/mach-s3c2410/cpu.h26
-rw-r--r--arch/arm/mach-s3c2410/irq.c4
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c8
-rw-r--r--arch/arm/mach-s3c2410/mach-h1940.c6
-rw-r--r--arch/arm/mach-s3c2410/mach-rx3715.c7
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c5
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c8
-rw-r--r--arch/arm/mach-s3c2410/s3c2410.c5
-rw-r--r--arch/arm/mach-s3c2410/s3c2410.h16
-rw-r--r--arch/arm/mach-s3c2410/s3c2440-dsc.c5
-rw-r--r--arch/arm/mach-s3c2410/s3c2440.h21
-rw-r--r--arch/arm/mach-s3c2410/time.c2
-rw-r--r--arch/arm/mm/init.c1
-rw-r--r--arch/arm/mm/mm-armv.c1
-rw-r--r--arch/i386/Kconfig2
-rw-r--r--arch/i386/kernel/apic.c15
-rw-r--r--arch/i386/kernel/cpu/amd.c17
-rw-r--r--arch/i386/kernel/cpu/common.c54
-rw-r--r--arch/i386/kernel/cpu/intel.c45
-rw-r--r--arch/i386/kernel/cpu/mtrr/generic.c2
-rw-r--r--arch/i386/kernel/cpu/proc.c17
-rw-r--r--arch/i386/kernel/dmi_scan.c10
-rw-r--r--arch/i386/kernel/kprobes.c19
-rw-r--r--arch/i386/kernel/signal.c6
-rw-r--r--arch/i386/kernel/smpboot.c1
-rw-r--r--arch/i386/mm/ioremap.c6
-rw-r--r--arch/i386/mm/pageattr.c28
-rw-r--r--arch/i386/pci/fixup.c14
-rw-r--r--arch/i386/pci/irq.c18
-rw-r--r--arch/ia64/Kconfig24
-rw-r--r--arch/ia64/Kconfig.debug2
-rw-r--r--arch/ia64/Makefile2
-rw-r--r--arch/ia64/configs/sn2_defconfig51
-rw-r--r--arch/ia64/defconfig51
-rw-r--r--arch/ia64/hp/common/Makefile2
-rw-r--r--arch/ia64/hp/common/hwsw_iommu.c185
-rw-r--r--arch/ia64/hp/common/sba_iommu.c2
-rw-r--r--arch/ia64/hp/sim/simeth.c8
-rw-r--r--arch/ia64/hp/zx1/Makefile2
-rw-r--r--arch/ia64/hp/zx1/hpzx1_swiotlb_machvec.c3
-rw-r--r--arch/ia64/ia32/sys_ia32.c4
-rw-r--r--arch/ia64/kernel/Makefile1
-rw-r--r--arch/ia64/kernel/acpi.c2
-rw-r--r--arch/ia64/kernel/domain.c1
-rw-r--r--arch/ia64/kernel/head.S22
-rw-r--r--arch/ia64/kernel/mca.c1
-rw-r--r--arch/ia64/kernel/setup.c25
-rw-r--r--arch/ia64/kernel/topology.c1
-rw-r--r--arch/ia64/lib/swiotlb.c16
-rw-r--r--arch/ia64/pci/pci.c136
-rw-r--r--arch/ia64/sn/kernel/bte_error.c11
-rw-r--r--arch/ia64/sn/kernel/io_init.c7
-rw-r--r--arch/ia64/sn/kernel/setup.c9
-rw-r--r--arch/ia64/sn/kernel/sn2/prominfo_proc.c1
-rw-r--r--arch/ia64/sn/kernel/sn2/sn2_smp.c1
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c7
-rw-r--r--arch/ia64/sn/pci/pci_dma.c64
-rw-r--r--arch/m32r/Kconfig2
-rw-r--r--arch/m32r/kernel/entry.S90
-rw-r--r--arch/m32r/kernel/signal.c187
-rw-r--r--arch/m32r/mm/init.c3
-rw-r--r--arch/m68k/apollo/dn_debug.c22
-rw-r--r--arch/m68k/configs/amiga_defconfig9
-rw-r--r--arch/m68k/configs/apollo_defconfig9
-rw-r--r--arch/m68k/configs/atari_defconfig9
-rw-r--r--arch/m68k/configs/bvme6000_defconfig9
-rw-r--r--arch/m68k/configs/hp300_defconfig9
-rw-r--r--arch/m68k/configs/mac_defconfig9
-rw-r--r--arch/m68k/configs/mvme147_defconfig9
-rw-r--r--arch/m68k/configs/mvme16x_defconfig9
-rw-r--r--arch/m68k/configs/q40_defconfig9
-rw-r--r--arch/m68k/configs/sun3_defconfig9
-rw-r--r--arch/m68k/configs/sun3x_defconfig9
-rw-r--r--arch/m68k/defconfig9
-rw-r--r--arch/m68k/sun3x/sun3x_ksyms.c13
-rw-r--r--arch/mips/kernel/irixelf.c11
-rw-r--r--arch/mips/vr41xx/common/bcu.c1
-rw-r--r--arch/mips/vr41xx/common/pmu.c1
-rw-r--r--arch/parisc/kernel/binfmt_elf32.c6
-rw-r--r--arch/ppc/kernel/idle.c7
-rw-r--r--arch/ppc/kernel/perfmon.c1
-rw-r--r--arch/ppc/mm/init.c1
-rw-r--r--arch/ppc64/Kconfig11
-rw-r--r--arch/ppc64/kernel/binfmt_elf32.c6
-rw-r--r--arch/ppc64/kernel/entry.S7
-rw-r--r--arch/ppc64/kernel/kprobes.c2
-rw-r--r--arch/ppc64/kernel/maple_pci.c3
-rw-r--r--arch/ppc64/kernel/misc.S20
-rw-r--r--arch/ppc64/kernel/pSeries_iommu.c16
-rw-r--r--arch/ppc64/kernel/pSeries_pci.c1
-rw-r--r--arch/ppc64/kernel/pSeries_smp.c56
-rw-r--r--arch/ppc64/kernel/pacaData.c6
-rw-r--r--arch/ppc64/kernel/pci.c33
-rw-r--r--arch/ppc64/kernel/pci.h4
-rw-r--r--arch/ppc64/kernel/pci_dn.c33
-rw-r--r--arch/ppc64/kernel/pmac_pci.c2
-rw-r--r--arch/ppc64/kernel/ppc_ksyms.c1
-rw-r--r--arch/ppc64/kernel/process.c48
-rw-r--r--arch/ppc64/kernel/rtas-proc.c12
-rw-r--r--arch/ppc64/kernel/rtasd.c2
-rw-r--r--arch/ppc64/kernel/smp.c28
-rw-r--r--arch/ppc64/kernel/time.c78
-rw-r--r--arch/ppc64/kernel/traps.c5
-rw-r--r--arch/ppc64/kernel/xics.c17
-rw-r--r--arch/ppc64/mm/init.c1
-rw-r--r--arch/ppc64/mm/numa.c23
-rw-r--r--arch/ppc64/oprofile/op_model_power4.c2
-rw-r--r--arch/ppc64/oprofile/op_model_rs64.c2
-rw-r--r--arch/ppc64/xmon/setjmp.S73
-rw-r--r--arch/ppc64/xmon/setjmp.c77
-rw-r--r--arch/ppc64/xmon/xmon.c24
-rw-r--r--arch/s390/Kconfig7
-rw-r--r--arch/s390/kernel/binfmt_elf32.c9
-rw-r--r--arch/s390/kernel/entry.S135
-rw-r--r--arch/s390/kernel/entry64.S128
-rw-r--r--arch/s390/kernel/irq.c8
-rw-r--r--arch/s390/kernel/time.c42
-rw-r--r--arch/s390/kernel/vtime.c111
-rw-r--r--arch/sparc64/Kconfig10
-rw-r--r--arch/sparc64/defconfig21
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c14
-rw-r--r--arch/sparc64/kernel/binfmt_elf32.c6
-rw-r--r--arch/sparc64/kernel/pci_psycho.c6
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c3
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c6
-rw-r--r--arch/sparc64/lib/find_bit.c5
-rw-r--r--arch/um/Kconfig7
-rw-r--r--arch/um/Kconfig_arch16
-rw-r--r--arch/um/Kconfig_char11
-rw-r--r--arch/um/Kconfig_i38620
-rw-r--r--arch/um/Kconfig_x86_6411
-rw-r--r--arch/um/Makefile20
-rw-r--r--arch/um/Makefile-i3868
-rw-r--r--arch/um/Makefile-x86_6435
-rw-r--r--arch/um/defconfig4
-rw-r--r--arch/um/drivers/Makefile3
-rw-r--r--arch/um/drivers/chan_kern.c4
-rw-r--r--arch/um/drivers/cow.h5
-rw-r--r--arch/um/drivers/cow_sys.h4
-rw-r--r--arch/um/drivers/cow_user.c6
-rw-r--r--arch/um/drivers/line.c31
-rw-r--r--arch/um/drivers/mconsole_kern.c11
-rw-r--r--arch/um/drivers/mmapper_kern.c2
-rw-r--r--arch/um/drivers/ubd_kern.c10
-rw-r--r--arch/um/drivers/ubd_user.c2
-rw-r--r--arch/um/include/process.h2
-rw-r--r--arch/um/include/registers.h27
-rw-r--r--arch/um/include/sysdep-i386/ptrace.h45
-rw-r--r--arch/um/include/sysdep-i386/signal.h25
-rw-r--r--arch/um/include/sysdep-i386/syscalls.h71
-rw-r--r--arch/um/include/sysdep-ppc/syscalls.h7
-rw-r--r--arch/um/include/sysdep-x86_64/checksum.h151
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h260
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace_user.h69
-rw-r--r--arch/um/include/sysdep-x86_64/sigcontext.h49
-rw-r--r--arch/um/include/sysdep-x86_64/signal.h27
-rw-r--r--arch/um/include/sysdep-x86_64/syscalls.h96
-rw-r--r--arch/um/include/um_uaccess.h14
-rw-r--r--arch/um/include/uml_uaccess.h2
-rw-r--r--arch/um/kernel/checksum.c12
-rw-r--r--arch/um/kernel/exec_kern.c10
-rw-r--r--arch/um/kernel/exitcode.c2
-rw-r--r--arch/um/kernel/irq.c14
-rw-r--r--arch/um/kernel/mem.c14
-rw-r--r--arch/um/kernel/mem_user.c4
-rw-r--r--arch/um/kernel/physmem.c7
-rw-r--r--arch/um/kernel/process.c8
-rw-r--r--arch/um/kernel/process_kern.c20
-rw-r--r--arch/um/kernel/ptrace.c44
-rw-r--r--arch/um/kernel/signal_kern.c41
-rw-r--r--arch/um/kernel/signal_user.c1
-rw-r--r--arch/um/kernel/skas/Makefile2
-rw-r--r--arch/um/kernel/skas/include/ptrace-skas.h57
-rw-r--r--arch/um/kernel/skas/include/skas.h3
-rw-r--r--arch/um/kernel/skas/mem.c5
-rw-r--r--arch/um/kernel/skas/process.c93
-rw-r--r--arch/um/kernel/skas/process_kern.c8
-rw-r--r--arch/um/kernel/skas/tlb.c150
-rw-r--r--arch/um/kernel/skas/trap_user.c1
-rw-r--r--arch/um/kernel/skas/uaccess.c48
-rw-r--r--arch/um/kernel/skas/util/Makefile2
-rw-r--r--arch/um/kernel/skas/util/mk_ptregs-i386.c (renamed from arch/um/kernel/skas/util/mk_ptregs.c)4
-rw-r--r--arch/um/kernel/skas/util/mk_ptregs-x86_64.c68
-rw-r--r--arch/um/kernel/smp.c6
-rw-r--r--arch/um/kernel/sys_call_table.c450
-rw-r--r--arch/um/kernel/syscall_kern.c129
-rw-r--r--arch/um/kernel/time_kern.c25
-rw-r--r--arch/um/kernel/tlb.c16
-rw-r--r--arch/um/kernel/trap_kern.c8
-rw-r--r--arch/um/kernel/trap_user.c22
-rw-r--r--arch/um/kernel/tt/Makefile5
-rw-r--r--arch/um/kernel/tt/gdb.c8
-rw-r--r--arch/um/kernel/tt/ptproxy/proxy.c8
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c1
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.c1
-rw-r--r--arch/um/kernel/tt/syscall_kern.c93
-rw-r--r--arch/um/kernel/tt/tlb.c160
-rw-r--r--arch/um/kernel/tt/tracer.c1
-rw-r--r--arch/um/kernel/tt/trap_user.c1
-rw-r--r--arch/um/kernel/tt/uaccess.c12
-rw-r--r--arch/um/kernel/um_arch.c5
-rw-r--r--arch/um/os-Linux/Makefile7
-rw-r--r--arch/um/os-Linux/elf_aux.c1
-rw-r--r--arch/um/os-Linux/signal.c48
-rw-r--r--arch/um/os-Linux/sys-i386/Makefile11
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c115
-rw-r--r--arch/um/os-Linux/sys-x86_64/Makefile11
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c82
-rw-r--r--arch/um/os-Linux/user_syms.c8
-rw-r--r--arch/um/sys-i386/Makefile2
-rw-r--r--arch/um/sys-i386/delay.c14
-rw-r--r--arch/um/sys-i386/ldt.c14
-rw-r--r--arch/um/sys-i386/ptrace.c24
-rw-r--r--arch/um/sys-i386/sigcontext.c3
-rw-r--r--arch/um/sys-i386/signal.c2
-rw-r--r--arch/um/sys-i386/syscalls.c134
-rw-r--r--arch/um/sys-x86_64/Makefile39
-rw-r--r--arch/um/sys-x86_64/bugs.c122
-rw-r--r--arch/um/sys-x86_64/delay.c26
-rw-r--r--arch/um/sys-x86_64/fault.c23
-rw-r--r--arch/um/sys-x86_64/mem.c25
-rw-r--r--arch/um/sys-x86_64/ptrace.c138
-rw-r--r--arch/um/sys-x86_64/ptrace_user.c64
-rw-r--r--arch/um/sys-x86_64/sigcontext.c39
-rw-r--r--arch/um/sys-x86_64/signal.c276
-rw-r--r--arch/um/sys-x86_64/syscalls.c191
-rw-r--r--arch/um/sys-x86_64/sysrq.c49
-rw-r--r--arch/um/sys-x86_64/util/Makefile10
-rw-r--r--arch/um/sys-x86_64/util/mk_sc.c58
-rw-r--r--arch/um/sys-x86_64/util/mk_thread_kern.c21
-rw-r--r--arch/um/sys-x86_64/util/mk_thread_user.c30
-rw-r--r--arch/x86_64/Kconfig2
-rw-r--r--arch/x86_64/Makefile2
-rw-r--r--arch/x86_64/defconfig120
-rw-r--r--arch/x86_64/ia32/ia32_aout.c12
-rw-r--r--arch/x86_64/ia32/ia32_signal.c6
-rw-r--r--arch/x86_64/ia32/ia32entry.S4
-rw-r--r--arch/x86_64/kernel/aperture.c14
-rw-r--r--arch/x86_64/kernel/apic.c5
-rw-r--r--arch/x86_64/kernel/genapic.c7
-rw-r--r--arch/x86_64/kernel/head.S2
-rw-r--r--arch/x86_64/kernel/head64.c13
-rw-r--r--arch/x86_64/kernel/io_apic.c7
-rw-r--r--arch/x86_64/kernel/mce.c18
-rw-r--r--arch/x86_64/kernel/mpparse.c11
-rw-r--r--arch/x86_64/kernel/setup.c59
-rw-r--r--arch/x86_64/kernel/signal.c8
-rw-r--r--arch/x86_64/lib/io.c8
-rw-r--r--arch/x86_64/lib/old-checksum.c33
-rw-r--r--arch/x86_64/mm/init.c54
-rw-r--r--arch/x86_64/mm/ioremap.c10
-rw-r--r--arch/x86_64/mm/k8topology.c23
-rw-r--r--arch/x86_64/mm/numa.c10
-rw-r--r--arch/x86_64/mm/pageattr.c26
-rw-r--r--arch/x86_64/mm/srat.c19
-rw-r--r--drivers/acpi/processor_idle.c10
-rw-r--r--drivers/base/platform.c2
-rw-r--r--drivers/base/power/power.h6
-rw-r--r--drivers/base/power/runtime.c4
-rw-r--r--drivers/base/power/suspend.c8
-rw-r--r--drivers/block/Kconfig1
-rw-r--r--drivers/block/cciss.c17
-rw-r--r--drivers/block/cfq-iosched.c6
-rw-r--r--drivers/block/deadline-iosched.c10
-rw-r--r--drivers/block/elevator.c7
-rw-r--r--drivers/block/ll_rw_blk.c51
-rw-r--r--drivers/block/noop-iosched.c8
-rw-r--r--drivers/block/pktcdvd.c10
-rw-r--r--drivers/block/scsi_ioctl.c3
-rw-r--r--drivers/bluetooth/bcm203x.c8
-rw-r--r--drivers/bluetooth/bfusb.c8
-rw-r--r--drivers/bluetooth/bluecard_cs.c6
-rw-r--r--drivers/bluetooth/bt3c_cs.c6
-rw-r--r--drivers/bluetooth/btuart_cs.c6
-rw-r--r--drivers/bluetooth/dtl1_cs.c6
-rw-r--r--drivers/bluetooth/hci_bcsp.c4
-rw-r--r--drivers/bluetooth/hci_ldisc.c13
-rw-r--r--drivers/bluetooth/hci_usb.c13
-rw-r--r--drivers/char/agp/Kconfig2
-rw-r--r--drivers/char/esp.c2
-rw-r--r--drivers/char/genrtc.c2
-rw-r--r--drivers/char/ip2/fip_firm.h2
-rw-r--r--drivers/char/ip2/i2cmd.c59
-rw-r--r--drivers/char/ip2/i2cmd.h17
-rw-r--r--drivers/char/ip2/i2lib.c2
-rw-r--r--drivers/char/ip2main.c5
-rw-r--r--drivers/char/keyboard.c20
-rw-r--r--drivers/char/lp.c4
-rw-r--r--drivers/char/n_hdlc.c4
-rw-r--r--drivers/char/n_tty.c4
-rw-r--r--drivers/char/pcmcia/synclink_cs.c33
-rw-r--r--drivers/char/pty.c2
-rw-r--r--drivers/char/random.c750
-rw-r--r--drivers/char/rio/cdproto.h55
-rw-r--r--drivers/char/rsf16fmi.h13
-rw-r--r--drivers/char/selection.c44
-rw-r--r--drivers/char/synclink.c311
-rw-r--r--drivers/char/tipar.c4
-rw-r--r--drivers/char/toshiba.c2
-rw-r--r--drivers/char/tty_io.c28
-rw-r--r--drivers/char/tty_ioctl.c2
-rw-r--r--drivers/char/vc_screen.c60
-rw-r--r--drivers/char/vt.c428
-rw-r--r--drivers/char/vt_ioctl.c2
-rw-r--r--drivers/ide/ide-cd.c68
-rw-r--r--drivers/ide/ide.c2
-rw-r--r--drivers/ide/legacy/ide-cs.c4
-rw-r--r--drivers/input/mouse/synaptics.h2
-rw-r--r--drivers/isdn/hardware/avm/avm_cs.c9
-rw-r--r--drivers/isdn/hisax/avma1_cs.c9
-rw-r--r--drivers/isdn/hisax/elsa_cs.c6
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c9
-rw-r--r--drivers/isdn/hisax/teles_cs.c6
-rw-r--r--drivers/message/i2o/pci.c2
-rw-r--r--drivers/mmc/Kconfig2
-rw-r--r--drivers/mtd/chips/jedec_probe.c20
-rw-r--r--drivers/mtd/maps/pcmciamtd.c31
-rw-r--r--drivers/mtd/maps/scx200_docflash.c9
-rw-r--r--drivers/net/3c515.c2
-rw-r--r--drivers/net/3c59x.c252
-rw-r--r--drivers/net/8139too.c3
-rw-r--r--drivers/net/Kconfig1
-rw-r--r--drivers/net/arcnet/arcnet.c3
-rw-r--r--drivers/net/e1000/e1000_ethtool.c2
-rw-r--r--drivers/net/e1000/e1000_main.c4
-rw-r--r--drivers/net/eepro.c144
-rw-r--r--drivers/net/ibm_emac/ibm_emac.h2
-rw-r--r--drivers/net/ibm_emac/ibm_emac_core.c15
-rw-r--r--drivers/net/ibm_emac/ibm_emac_phy.c19
-rw-r--r--drivers/net/ixgb/ixgb.h25
-rw-r--r--drivers/net/ixgb/ixgb_ee.c192
-rw-r--r--drivers/net/ixgb/ixgb_ethtool.c518
-rw-r--r--drivers/net/ixgb/ixgb_hw.c231
-rw-r--r--drivers/net/ixgb/ixgb_hw.h50
-rw-r--r--drivers/net/ixgb/ixgb_ids.h21
-rw-r--r--drivers/net/ixgb/ixgb_main.c707
-rw-r--r--drivers/net/ixgb/ixgb_osdep.h10
-rw-r--r--drivers/net/ixgb/ixgb_param.c316
-rw-r--r--drivers/net/pcmcia/3c574_cs.c5
-rw-r--r--drivers/net/pcmcia/3c589_cs.c5
-rw-r--r--drivers/net/pcmcia/axnet_cs.c5
-rw-r--r--drivers/net/pcmcia/com20020_cs.c5
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c5
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c5
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c5
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c5
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c5
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c6
-rw-r--r--drivers/net/s2io.c22
-rw-r--r--drivers/net/s2io.h4
-rw-r--r--drivers/net/smc-ultra.c2
-rw-r--r--drivers/net/smc91x.c16
-rw-r--r--drivers/net/tun.c3
-rw-r--r--drivers/net/wireless/airo.c20
-rw-r--r--drivers/net/wireless/airo_cs.c13
-rw-r--r--drivers/net/wireless/atmel_cs.c23
-rw-r--r--drivers/net/wireless/netwave_cs.c7
-rw-r--r--drivers/net/wireless/orinoco.c203
-rw-r--r--drivers/net/wireless/orinoco_cs.c11
-rw-r--r--drivers/net/wireless/ray_cs.c5
-rw-r--r--drivers/net/wireless/wavelan_cs.c2
-rw-r--r--drivers/net/wireless/wl3501_cs.c14
-rw-r--r--drivers/parport/parport_cs.c6
-rw-r--r--drivers/pci/pci-driver.c2
-rw-r--r--drivers/pcmcia/Kconfig21
-rw-r--r--drivers/pcmcia/Makefile4
-rw-r--r--drivers/pcmcia/bulkmem.c218
-rw-r--r--drivers/pcmcia/cardbus.c45
-rw-r--r--drivers/pcmcia/cistpl.c50
-rw-r--r--drivers/pcmcia/cs.c417
-rw-r--r--drivers/pcmcia/cs_internal.h46
-rw-r--r--drivers/pcmcia/ds.c1061
-rw-r--r--drivers/pcmcia/hd64465_ss.c1
-rw-r--r--drivers/pcmcia/i82092.c1
-rw-r--r--drivers/pcmcia/i82365.c1
-rw-r--r--drivers/pcmcia/m32r_cfc.c1
-rw-r--r--drivers/pcmcia/m32r_pcc.c1
-rw-r--r--drivers/pcmcia/pcmcia_compat.c20
-rw-r--r--drivers/pcmcia/pd6729.c271
-rw-r--r--drivers/pcmcia/pd6729.h6
-rw-r--r--drivers/pcmcia/rsrc_mgr.c856
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c816
-rw-r--r--drivers/pcmcia/soc_common.c1
-rw-r--r--drivers/pcmcia/tcic.c3
-rw-r--r--drivers/pcmcia/ti113x.h11
-rw-r--r--drivers/pcmcia/yenta_socket.c10
-rw-r--r--drivers/sbus/sbus.c8
-rw-r--r--drivers/scsi/aacraid/commsup.c27
-rw-r--r--drivers/scsi/aic7xxx/aic7770_osm.c12
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h2
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c91
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.c4
-rw-r--r--drivers/scsi/constants.c24
-rw-r--r--drivers/scsi/fd_mcs.c58
-rw-r--r--drivers/scsi/fd_mcs.h37
-rw-r--r--drivers/scsi/gdth.c954
-rw-r--r--drivers/scsi/gdth_kcompat.h21
-rw-r--r--drivers/scsi/gdth_proc.c287
-rw-r--r--drivers/scsi/gdth_proc.h6
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c142
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h1
-rw-r--r--drivers/scsi/ipr.c28
-rw-r--r--drivers/scsi/lasi700.c22
-rw-r--r--drivers/scsi/lasi700.h49
-rw-r--r--drivers/scsi/osst.c851
-rw-r--r--drivers/scsi/osst.h15
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c6
-rw-r--r--drivers/scsi/pcmcia/fdomain_stub.c6
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c5
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c6
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c1
-rw-r--r--drivers/scsi/qla1280.c22
-rw-r--r--drivers/scsi/sata_sil.c2
-rw-r--r--drivers/scsi/scsi.c22
-rw-r--r--drivers/scsi/scsi_lib.c18
-rw-r--r--drivers/scsi/scsi_transport_fc.c36
-rw-r--r--drivers/scsi/scsi_transport_spi.c91
-rw-r--r--drivers/scsi/sd.c7
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_conf.h8
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_defs.h34
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw.c4
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c83
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.h34
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c469
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h72
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_malloc.c2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_misc.c98
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.c39
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.h6
-rw-r--r--drivers/scsi/sym53c8xx_comm.h2
-rw-r--r--drivers/scsi/zalon.c21
-rw-r--r--drivers/serial/serial_cs.c6
-rw-r--r--drivers/telephony/ixj_pcmcia.c6
-rw-r--r--drivers/video/matrox/matroxfb_base.c2
-rw-r--r--fs/Kconfig46
-rw-r--r--fs/Makefile1
-rw-r--r--fs/attr.c7
-rw-r--r--fs/binfmt_aout.c19
-rw-r--r--fs/binfmt_elf.c45
-rw-r--r--fs/bio.c29
-rw-r--r--fs/buffer.c8
-rw-r--r--fs/coda/cnode.c2
-rw-r--r--fs/coda/dir.c60
-rw-r--r--fs/coda/file.c2
-rw-r--r--fs/coda/inode.c2
-rw-r--r--fs/coda/psdev.c17
-rw-r--r--fs/coda/sysctl.c56
-rw-r--r--fs/coda/upcall.c29
-rw-r--r--fs/direct-io.c13
-rw-r--r--fs/dquot.c8
-rw-r--r--fs/efs/super.c20
-rw-r--r--fs/exec.c1
-rw-r--r--fs/ext2/xattr.c24
-rw-r--r--fs/ext2/xattr.h7
-rw-r--r--fs/ext3/balloc.c2
-rw-r--r--fs/ext3/dir.c2
-rw-r--r--fs/ext3/inode.c4
-rw-r--r--fs/ext3/resize.c4
-rw-r--r--fs/ext3/super.c45
-rw-r--r--fs/ext3/xattr.c242
-rw-r--r--fs/ext3/xattr.h8
-rw-r--r--fs/fs-writeback.c15
-rw-r--r--fs/hugetlbfs/inode.c8
-rw-r--r--fs/isofs/compress.c1
-rw-r--r--fs/jbd/commit.c3
-rw-r--r--fs/libfs.c1
-rw-r--r--fs/open.c3
-rw-r--r--fs/proc/array.c22
-rw-r--r--fs/proc/base.c2
-rw-r--r--fs/proc/kcore.c3
-rw-r--r--fs/proc/proc_misc.c60
-rw-r--r--fs/proc/proc_tty.c4
-rw-r--r--fs/quota.c2
-rw-r--r--fs/quota_v2.c2
-rw-r--r--fs/readdir.c5
-rw-r--r--fs/reiserfs/fix_node.c5
-rw-r--r--fs/smbfs/ChangeLog160
-rw-r--r--fs/smbfs/inode.c2
-rw-r--r--fs/smbfs/proc.c6
-rw-r--r--fs/smbfs/proto.h5
-rw-r--r--fs/smbfs/request.c6
-rw-r--r--fs/umsdos/Makefile13
-rw-r--r--fs/umsdos/README-WIP.txt114
-rw-r--r--fs/umsdos/dir.c810
-rw-r--r--fs/umsdos/emd.c660
-rw-r--r--fs/umsdos/inode.c483
-rw-r--r--fs/umsdos/ioctl.c446
-rw-r--r--fs/umsdos/mangle.c522
-rw-r--r--fs/umsdos/namei.c1124
-rw-r--r--fs/umsdos/rdir.c248
-rw-r--r--fs/umsdos/specs289
-rw-r--r--include/asm-alpha/cputime.h6
-rw-r--r--include/asm-alpha/io_trivial.h4
-rw-r--r--include/asm-arm/arch-pxa/corgi.h135
-rw-r--r--include/asm-arm/arch-s3c2410/entry-macro.S33
-rw-r--r--include/asm-arm/arch-s3c2410/timex.h16
-rw-r--r--include/asm-arm/cpu.h1
-rw-r--r--include/asm-arm/cputime.h6
-rw-r--r--include/asm-arm/hardware/scoop.h47
-rw-r--r--include/asm-arm/mach/irq.h14
-rw-r--r--include/asm-arm/processor.h1
-rw-r--r--include/asm-arm/smp.h9
-rw-r--r--include/asm-arm/tlb.h2
-rw-r--r--include/asm-arm26/cputime.h6
-rw-r--r--include/asm-cris/cputime.h6
-rw-r--r--include/asm-generic/cputime.h64
-rw-r--r--include/asm-h8300/cputime.h6
-rw-r--r--include/asm-i386/cpufeature.h6
-rw-r--r--include/asm-i386/cputime.h6
-rw-r--r--include/asm-i386/processor.h8
-rw-r--r--include/asm-ia64/cputime.h6
-rw-r--r--include/asm-ia64/machvec.h26
-rw-r--r--include/asm-ia64/machvec_hpzx1_swiotlb.h43
-rw-r--r--include/asm-ia64/machvec_init.h3
-rw-r--r--include/asm-ia64/machvec_sn2.h6
-rw-r--r--include/asm-ia64/numnodes.h2
-rw-r--r--include/asm-ia64/pci.h14
-rw-r--r--include/asm-ia64/sn/sn_sal.h50
-rw-r--r--include/asm-m32r/cputime.h6
-rw-r--r--include/asm-m32r/unistd.h241
-rw-r--r--include/asm-m68k/atari_SCCserial.h67
-rw-r--r--include/asm-m68k/cputime.h6
-rw-r--r--include/asm-m68knommu/cputime.h6
-rw-r--r--include/asm-mips/cputime.h6
-rw-r--r--include/asm-parisc/cputime.h6
-rw-r--r--include/asm-ppc/cputime.h6
-rw-r--r--include/asm-ppc/reg.h1
-rw-r--r--include/asm-ppc64/bug.h2
-rw-r--r--include/asm-ppc64/cputime.h6
-rw-r--r--include/asm-ppc64/machdep.h3
-rw-r--r--include/asm-ppc64/pci-bridge.h23
-rw-r--r--include/asm-ppc64/processor.h4
-rw-r--r--include/asm-ppc64/rtas.h2
-rw-r--r--include/asm-ppc64/smp.h2
-rw-r--r--include/asm-ppc64/spinlock.h2
-rw-r--r--include/asm-ppc64/system.h1
-rw-r--r--include/asm-ppc64/thread_info.h6
-rw-r--r--include/asm-ppc64/tlbflush.h3
-rw-r--r--include/asm-ppc64/xics.h5
-rw-r--r--include/asm-s390/cputime.h168
-rw-r--r--include/asm-s390/hardirq.h1
-rw-r--r--include/asm-s390/lowcore.h47
-rw-r--r--include/asm-s390/system.h18
-rw-r--r--include/asm-s390/timer.h2
-rw-r--r--include/asm-sh/cputime.h6
-rw-r--r--include/asm-sh64/cputime.h6
-rw-r--r--include/asm-sparc/cputime.h6
-rw-r--r--include/asm-sparc64/bitops.h3
-rw-r--r--include/asm-sparc64/cputime.h6
-rw-r--r--include/asm-um/apic.h4
-rw-r--r--include/asm-um/archparam-i386.h11
-rw-r--r--include/asm-um/archparam-ppc.h4
-rw-r--r--include/asm-um/archparam-x86_64.h62
-rw-r--r--include/asm-um/calling.h9
-rw-r--r--include/asm-um/cputime.h6
-rw-r--r--include/asm-um/dwarf2.h11
-rw-r--r--include/asm-um/elf.h5
-rw-r--r--include/asm-um/fixmap.h7
-rw-r--r--include/asm-um/module-x86_64.h30
-rw-r--r--include/asm-um/page.h106
-rw-r--r--include/asm-um/pda.h31
-rw-r--r--include/asm-um/pgalloc.h24
-rw-r--r--include/asm-um/pgtable-2level.h83
-rw-r--r--include/asm-um/pgtable-3level.h172
-rw-r--r--include/asm-um/pgtable.h238
-rw-r--r--include/asm-um/prctl.h6
-rw-r--r--include/asm-um/processor-i386.h3
-rw-r--r--include/asm-um/processor-x86_64.h33
-rw-r--r--include/asm-um/ptrace-generic.h6
-rw-r--r--include/asm-um/ptrace-x86_64.h75
-rw-r--r--include/asm-um/sigcontext-x86_64.h (renamed from arch/um/kernel/tt/include/ptrace-tt.h)14
-rw-r--r--include/asm-um/system-x86_64.h23
-rw-r--r--include/asm-um/thread_info.h2
-rw-r--r--include/asm-um/uaccess.h4
-rw-r--r--include/asm-um/vm-flags-i386.h14
-rw-r--r--include/asm-um/vm-flags-x86_64.h33
-rw-r--r--include/asm-v850/cputime.h6
-rw-r--r--include/asm-x86_64/cputime.h6
-rw-r--r--include/asm-x86_64/hw_irq.h2
-rw-r--r--include/asm-x86_64/ia32_unistd.h6
-rw-r--r--include/asm-x86_64/io.h6
-rw-r--r--include/asm-x86_64/msr.h3
-rw-r--r--include/asm-x86_64/numa.h2
-rw-r--r--include/asm-x86_64/proto.h2
-rw-r--r--include/asm-x86_64/uaccess.h2
-rw-r--r--include/asm-x86_64/unistd.h12
-rw-r--r--include/linux/arcdevice.h1
-rw-r--r--include/linux/blkdev.h1
-rw-r--r--include/linux/coda.h4
-rw-r--r--include/linux/coda_proc.h21
-rw-r--r--include/linux/coda_psdev.h2
-rw-r--r--include/linux/console_struct.h3
-rw-r--r--include/linux/device.h2
-rw-r--r--include/linux/efs_vh.h17
-rw-r--r--include/linux/ext3_fs.h10
-rw-r--r--include/linux/ext3_jbd.h2
-rw-r--r--include/linux/fs.h4
-rw-r--r--include/linux/hardirq.h18
-rw-r--r--include/linux/in6.h2
-rw-r--r--include/linux/interrupt.h30
-rw-r--r--include/linux/kernel_stat.h20
-rw-r--r--include/linux/list.h48
-rw-r--r--include/linux/lp.h6
-rw-r--r--include/linux/mm.h1
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--include/linux/netfilter.h4
-rw-r--r--include/linux/netfilter_arp/arp_tables.h6
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h28
-rw-r--r--include/linux/netfilter_ipv4/ipt_LOG.h3
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h6
-rw-r--r--include/linux/netfilter_ipv6/ip6t_LOG.h3
-rw-r--r--include/linux/netlink.h1
-rw-r--r--include/linux/netpoll.h1
-rw-r--r--include/linux/nodemask.h9
-rw-r--r--include/linux/pci_ids.h2
-rw-r--r--include/linux/pkt_cls.h3
-rw-r--r--include/linux/pm.h103
-rw-r--r--include/linux/ptrace.h1
-rw-r--r--include/linux/rtnetlink.h6
-rw-r--r--include/linux/sched.h17
-rw-r--r--include/linux/sctp.h2
-rw-r--r--include/linux/security.h25
-rw-r--r--include/linux/selection.h23
-rw-r--r--include/linux/skbuff.h5
-rw-r--r--include/linux/slab.h1
-rw-r--r--include/linux/socket.h1
-rw-r--r--include/linux/umsdos_fs.h182
-rw-r--r--include/linux/umsdos_fs.p100
-rw-r--r--include/linux/umsdos_fs_i.h58
-rw-r--r--include/linux/vmalloc.h1
-rw-r--r--include/net/addrconf.h1
-rw-r--r--include/net/ax25.h1
-rw-r--r--include/net/bluetooth/hci_core.h2
-rw-r--r--include/net/bluetooth/l2cap.h27
-rw-r--r--include/net/bluetooth/rfcomm.h50
-rw-r--r--include/net/bluetooth/sco.h7
-rw-r--r--include/net/dn.h2
-rw-r--r--include/net/dn_fib.h1
-rw-r--r--include/net/ip_vs.h2
-rw-r--r--include/net/ipv6.h2
-rw-r--r--include/net/iw_handler.h3
-rw-r--r--include/net/pkt_act.h31
-rw-r--r--include/net/pkt_cls.h188
-rw-r--r--include/net/sctp/command.h13
-rw-r--r--include/net/sctp/constants.h8
-rw-r--r--include/net/sctp/sctp.h24
-rw-r--r--include/net/sctp/sm.h69
-rw-r--r--include/net/sctp/structs.h37
-rw-r--r--include/net/sctp/tsnmap.h16
-rw-r--r--include/net/sctp/ulpevent.h2
-rw-r--r--include/net/sctp/ulpqueue.h1
-rw-r--r--include/net/sock.h7
-rw-r--r--include/net/tc_act/tc_pedit.h2
-rw-r--r--include/pcmcia/bulkmem.h28
-rw-r--r--include/pcmcia/ciscode.h25
-rw-r--r--include/pcmcia/cisreg.h25
-rw-r--r--include/pcmcia/cistpl.h25
-rw-r--r--include/pcmcia/cs.h53
-rw-r--r--include/pcmcia/cs_types.h25
-rw-r--r--include/pcmcia/ds.h65
-rw-r--r--include/pcmcia/mem_op.h25
-rw-r--r--include/pcmcia/ss.h53
-rw-r--r--include/scsi/scsi_dbg.h3
-rw-r--r--include/scsi/scsi_device.h2
-rw-r--r--include/scsi/scsi_transport_fc.h22
-rw-r--r--include/sound/ac97_codec.h1
-rw-r--r--include/sound/version.h4
-rw-r--r--kernel/acct.c2
-rw-r--r--kernel/audit.c2
-rw-r--r--kernel/auditsc.c2
-rw-r--r--kernel/compat.c14
-rw-r--r--kernel/cpu.c4
-rw-r--r--kernel/exit.c31
-rw-r--r--kernel/fork.c14
-rw-r--r--kernel/itimer.c57
-rw-r--r--kernel/module.c3
-rw-r--r--kernel/power/swsusp.c13
-rw-r--r--kernel/ptrace.c50
-rw-r--r--kernel/sched.c168
-rw-r--r--kernel/signal.c35
-rw-r--r--kernel/softirq.c1
-rw-r--r--kernel/sys.c34
-rw-r--r--kernel/timer.c65
-rw-r--r--lib/Kconfig.debug2
-rw-r--r--mm/memory.c4
-rw-r--r--mm/mmap.c145
-rw-r--r--mm/oom_kill.c3
-rw-r--r--mm/page_alloc.c2
-rw-r--r--mm/readahead.c2
-rw-r--r--mm/swapfile.c99
-rw-r--r--net/802/psnap.c2
-rw-r--r--net/802/tr.c2
-rw-r--r--net/appletalk/aarp.c2
-rw-r--r--net/appletalk/ddp.c9
-rw-r--r--net/atm/br2684.c2
-rw-r--r--net/atm/common.c2
-rw-r--r--net/atm/resources.c2
-rw-r--r--net/ax25/af_ax25.c14
-rw-r--r--net/ax25/ax25_addr.c20
-rw-r--r--net/ax25/ax25_dev.c2
-rw-r--r--net/ax25/ax25_iface.c6
-rw-r--r--net/ax25/ax25_out.c2
-rw-r--r--net/ax25/ax25_route.c2
-rw-r--r--net/ax25/ax25_uid.c2
-rw-r--r--net/bluetooth/cmtp/capi.c28
-rw-r--r--net/bluetooth/cmtp/cmtp.h1
-rw-r--r--net/bluetooth/hci_conn.c2
-rw-r--r--net/bluetooth/hci_core.c8
-rw-r--r--net/bluetooth/hci_sock.c10
-rw-r--r--net/bluetooth/hidp/core.c170
-rw-r--r--net/bluetooth/hidp/hidp.h45
-rw-r--r--net/bluetooth/l2cap.c20
-rw-r--r--net/bluetooth/rfcomm/core.c39
-rw-r--r--net/bluetooth/rfcomm/sock.c54
-rw-r--r--net/bluetooth/rfcomm/tty.c2
-rw-r--r--net/bluetooth/sco.c5
-rw-r--r--net/bridge/br_netfilter.c33
-rw-r--r--net/bridge/netfilter/ebt_limit.c2
-rw-r--r--net/bridge/netfilter/ebt_log.c2
-rw-r--r--net/bridge/netfilter/ebt_ulog.c4
-rw-r--r--net/compat.c5
-rw-r--r--net/core/datagram.c19
-rw-r--r--net/core/dev.c19
-rw-r--r--net/core/dst.c4
-rw-r--r--net/core/dv.c25
-rw-r--r--net/core/gen_estimator.c2
-rw-r--r--net/core/iovec.c23
-rw-r--r--net/core/link_watch.c2
-rw-r--r--net/core/neighbour.c2
-rw-r--r--net/core/netfilter.c8
-rw-r--r--net/core/netpoll.c9
-rw-r--r--net/core/pktgen.c3771
-rw-r--r--net/core/rtnetlink.c43
-rw-r--r--net/core/sock.c17
-rw-r--r--net/core/wireless.c2
-rw-r--r--net/decnet/af_decnet.c8
-rw-r--r--net/decnet/dn_dev.c6
-rw-r--r--net/decnet/dn_fib.c19
-rw-r--r--net/decnet/dn_neigh.c8
-rw-r--r--net/decnet/dn_route.c8
-rw-r--r--net/decnet/dn_rules.c7
-rw-r--r--net/decnet/dn_table.c2
-rw-r--r--net/decnet/dn_timer.c47
-rw-r--r--net/econet/af_econet.c2
-rw-r--r--net/ipv4/af_inet.c2
-rw-r--r--net/ipv4/devinet.c4
-rw-r--r--net/ipv4/fib_hash.c2
-rw-r--r--net/ipv4/fib_rules.c7
-rw-r--r--net/ipv4/fib_semantics.c4
-rw-r--r--net/ipv4/inetpeer.c6
-rw-r--r--net/ipv4/ip_fragment.c2
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/ip_sockglue.c2
-rw-r--r--net/ipv4/ipconfig.c2
-rw-r--r--net/ipv4/ipip.c2
-rw-r--r--net/ipv4/ipmr.c4
-rw-r--r--net/ipv4/ipvs/ip_vs_core.c26
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c10
-rw-r--r--net/ipv4/ipvs/ip_vs_est.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_tcp.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_udp.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_sched.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_sync.c4
-rw-r--r--net/ipv4/netfilter/arp_tables.c15
-rw-r--r--net/ipv4/netfilter/arptable_filter.c3
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c26
-rw-r--r--net/ipv4/netfilter/ip_nat_snmp_basic.c2
-rw-r--r--net/ipv4/netfilter/ip_queue.c2
-rw-r--r--net/ipv4/netfilter/ip_tables.c78
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c10
-rw-r--r--net/ipv4/netfilter/ipt_limit.c2
-rw-r--r--net/ipv4/netfilter/ipt_recent.c2
-rw-r--r--net/ipv4/netfilter/iptable_filter.c26
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c22
-rw-r--r--net/ipv4/netfilter/iptable_raw.c22
-rw-r--r--net/ipv4/protocol.c2
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/route.c6
-rw-r--r--net/ipv4/tcp.c5
-rw-r--r--net/ipv4/tcp_minisocks.c2
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv6/addrconf.c17
-rw-r--r--net/ipv6/af_inet6.c2
-rw-r--r--net/ipv6/anycast.c6
-rw-r--r--net/ipv6/exthdrs.c77
-rw-r--r--net/ipv6/icmp.c2
-rw-r--r--net/ipv6/ip6_fib.c4
-rw-r--r--net/ipv6/ip6_flowlabel.c4
-rw-r--r--net/ipv6/ip6_output.c4
-rw-r--r--net/ipv6/ip6_tunnel.c2
-rw-r--r--net/ipv6/ipv6_sockglue.c2
-rw-r--r--net/ipv6/ipv6_syms.c2
-rw-r--r--net/ipv6/mcast.c34
-rw-r--r--net/ipv6/netfilter/ip6_queue.c2
-rw-r--r--net/ipv6/netfilter/ip6_tables.c23
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c10
-rw-r--r--net/ipv6/netfilter/ip6t_limit.c2
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c3
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c7
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c3
-rw-r--r--net/ipv6/protocol.c2
-rw-r--r--net/ipv6/raw.c2
-rw-r--r--net/ipv6/reassembly.c2
-rw-r--r--net/ipv6/route.c6
-rw-r--r--net/ipv6/sit.c6
-rw-r--r--net/ipv6/sysctl_net_ipv6.c2
-rw-r--r--net/ipv6/xfrm6_tunnel.c2
-rw-r--r--net/ipx/af_ipx.c2
-rw-r--r--net/ipx/ipx_route.c2
-rw-r--r--net/irda/ircomm/ircomm_event.c2
-rw-r--r--net/irda/ircomm/ircomm_tty_attach.c2
-rw-r--r--net/key/af_key.c4
-rw-r--r--net/lapb/lapb_iface.c2
-rw-r--r--net/llc/llc_core.c2
-rw-r--r--net/netlink/af_netlink.c40
-rw-r--r--net/netrom/af_netrom.c2
-rw-r--r--net/netrom/nr_route.c4
-rw-r--r--net/packet/af_packet.c2
-rw-r--r--net/rose/af_rose.c2
-rw-r--r--net/rose/rose_route.c6
-rw-r--r--net/rxrpc/krxiod.c4
-rw-r--r--net/rxrpc/krxsecd.c2
-rw-r--r--net/rxrpc/krxtimod.c2
-rw-r--r--net/rxrpc/transport.c2
-rw-r--r--net/sched/Kconfig16
-rw-r--r--net/sched/act_api.c620
-rw-r--r--net/sched/cls_api.c205
-rw-r--r--net/sched/cls_fw.c137
-rw-r--r--net/sched/cls_route.c344
-rw-r--r--net/sched/cls_rsvp.h102
-rw-r--r--net/sched/cls_tcindex.c373
-rw-r--r--net/sched/cls_u32.c140
-rw-r--r--net/sched/estimator.c2
-rw-r--r--net/sched/gact.c144
-rw-r--r--net/sched/ipt.c295
-rw-r--r--net/sched/mirred.c182
-rw-r--r--net/sched/pedit.c160
-rw-r--r--net/sched/police.c170
-rw-r--r--net/sched/sch_api.c7
-rw-r--r--net/sched/sch_atm.c4
-rw-r--r--net/sched/sch_cbq.c5
-rw-r--r--net/sched/sch_dsmark.c3
-rw-r--r--net/sched/sch_generic.c2
-rw-r--r--net/sched/sch_gred.c15
-rw-r--r--net/sched/sch_hfsc.c3
-rw-r--r--net/sched/sch_htb.c4
-rw-r--r--net/sched/sch_red.c2
-rw-r--r--net/sched/sch_tbf.c2
-rw-r--r--net/sctp/associola.c83
-rw-r--r--net/sctp/bind_addr.c17
-rw-r--r--net/sctp/chunk.c8
-rw-r--r--net/sctp/command.c23
-rw-r--r--net/sctp/debug.c20
-rw-r--r--net/sctp/endpointola.c56
-rw-r--r--net/sctp/input.c102
-rw-r--r--net/sctp/inqueue.c39
-rw-r--r--net/sctp/ipv6.c26
-rw-r--r--net/sctp/objcnt.c2
-rw-r--r--net/sctp/outqueue.c15
-rw-r--r--net/sctp/proc.c2
-rw-r--r--net/sctp/protocol.c36
-rw-r--r--net/sctp/sm_make_chunk.c159
-rw-r--r--net/sctp/sm_sideeffect.c68
-rw-r--r--net/sctp/sm_statefuns.c475
-rw-r--r--net/sctp/sm_statetable.c50
-rw-r--r--net/sctp/socket.c142
-rw-r--r--net/sctp/ssnmap.c7
-rw-r--r--net/sctp/transport.c67
-rw-r--r--net/sctp/tsnmap.c39
-rw-r--r--net/sctp/ulpevent.c17
-rw-r--r--net/sctp/ulpqueue.c21
-rw-r--r--net/socket.c2
-rw-r--r--net/sunrpc/auth.c2
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c2
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c2
-rw-r--r--net/sunrpc/cache.c6
-rw-r--r--net/sunrpc/pmap_clnt.c2
-rw-r--r--net/sunrpc/sched.c2
-rw-r--r--net/sunrpc/svcauth.c2
-rw-r--r--net/unix/af_unix.c2
-rw-r--r--net/wanrouter/af_wanpipe.c2
-rw-r--r--net/x25/af_x25.c2
-rw-r--r--net/x25/x25_link.c2
-rw-r--r--net/x25/x25_route.c2
-rw-r--r--net/xfrm/xfrm_policy.c6
-rw-r--r--net/xfrm/xfrm_state.c10
-rw-r--r--security/Kconfig1
-rw-r--r--security/commoncap.c81
-rw-r--r--security/dummy.c70
-rw-r--r--security/selinux/hooks.c218
-rw-r--r--security/selinux/include/objsec.h6
-rw-r--r--sound/core/ioctl32/ioctl32.c89
-rw-r--r--sound/core/rawmidi.c4
-rw-r--r--sound/pci/ac97/ac97_codec.c16
-rw-r--r--sound/pci/ac97/ac97_patch.c9
-rw-r--r--sound/pci/atiixp.c36
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c1
-rw-r--r--sound/pci/ca0106/ca0106_proc.c1
-rw-r--r--sound/pci/intel8x0.c20
-rw-r--r--sound/pci/mixart/mixart.c4
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c12
-rw-r--r--sound/pcmcia/vx/vx_entry.c11
-rw-r--r--sound/pcmcia/vx/vxpocket.c2
-rw-r--r--sound/pcmcia/vx/vxpocket.h1
941 files changed, 21871 insertions, 20392 deletions
diff --git a/CREDITS b/CREDITS
index 7a8edb5f7dd0..6147a4ea921e 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2936,10 +2936,10 @@ S: 03600 Karkkila
S: Finland
N: Deepak Saxena
-E: deepak@csociety.purdue.edu
+E: dsaxena@plexity.net
D: I2O kernel layer (config, block, core, pci, net). I2O disk support for LILO
-D: XScale(IOP310) porting
-S: Tempe, Arizona
+D: XScale(IOP, IXP) porting and other random ARM bits
+S: Portland, OR
N: Eric Schenk
E: Eric.Schenk@dna.lth.se
@@ -3344,7 +3344,7 @@ D: Amiga Buddha and Catweasel chipset IDE
D: Atari Falcon chipset IDE
D: Amiga Gayle chipset IDE
D: mipsel NEC DDB Vrc-5074
-S: Holsbeeksesteenweg 166
+S: Emiel Vlieberghlaan 2A/21
S: B-3010 Kessel-Lo
S: Belgium
diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt
index aadd46fc3001..74589c53a0c4 100644
--- a/Documentation/cciss.txt
+++ b/Documentation/cciss.txt
@@ -14,8 +14,7 @@ This driver is known to work with the following cards:
* SA 6400
* SA 6400 U320 Expansion Module
* SA 6i
- * SA 6422
- * SA V100
+ * SA P600
If nodes are not already created in the /dev/cciss directory, run as root:
diff --git a/Documentation/cdrom/packet-writing.txt b/Documentation/cdrom/packet-writing.txt
index d34fcbca9f27..b402e4c949da 100644
--- a/Documentation/cdrom/packet-writing.txt
+++ b/Documentation/cdrom/packet-writing.txt
@@ -43,6 +43,8 @@ shall implement "true random writes with 2KB granularity", which means
that it should be possible to put any filesystem with a block size >=
2KB on such a disc. For example, it should be possible to do:
+ # dvd+rw-format /dev/hdc (only needed if the disc has never
+ been formatted)
# mkudffs /dev/hdc
# mount /dev/hdc /cdrom -t udf -o rw,noatime
@@ -54,6 +56,7 @@ writes are not 32KB aligned.
Both problems can be solved by using the pktcdvd driver, which always
generates aligned writes.
+ # dvd+rw-format /dev/hdc
# pktsetup dev_name /dev/hdc
# mkudffs /dev/pktcdvd/dev_name
# mount /dev/pktcdvd/dev_name /cdrom -t udf -o rw,noatime
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index eb555b0bc844..190819531324 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -17,10 +17,18 @@ Who: Greg Kroah-Hartman <greg@kroah.com>
---------------------------
-What: /proc/sys/cpu and the sysctl interface to cpufreq (2.4.x interfaces)
+What: /proc/sys/cpu/*, sysctl and /proc/cpufreq interfaces to cpufreq (2.4.x interfaces)
When: January 2005
Files: drivers/cpufreq/: cpufreq_userspace.c, proc_intf.c
- function calls throughout the kernel tree
-Why: Deprecated, has been replaced/superseded by (what?)....
+Why: /proc/sys/cpu/* has been deprecated since inclusion of cpufreq into
+ the main kernel tree. It bloats /proc/ unnecessarily and doesn't work
+ well with the "governor"-based design of cpufreq.
+ /proc/cpufreq/* has also been deprecated for a long time and was only
+ meant for usage during 2.5. until the new sysfs-based interface became
+ ready. It has an inconsistent interface which doesn't work well with
+ userspace setting the frequency. The output from /proc/cpufreq/* can
+ be emulated using "cpufreq-info --proc" (cpufrequtils).
+ Both interfaces are superseded by the cpufreq interface in
+ /sys/devices/system/cpu/cpu%n/cpufreq/.
Who: Dominik Brodowski <linux@brodo.de>
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
index 6cf8082f605b..bcfbab899b37 100644
--- a/Documentation/filesystems/00-INDEX
+++ b/Documentation/filesystems/00-INDEX
@@ -42,8 +42,6 @@ udf.txt
- info and mount options for the UDF filesystem.
ufs.txt
- info on the ufs filesystem.
-umsdos.txt
- - info on the umsdos extensions to the msdos filesystem.
vfat.txt
- info on using the VFAT filesystem used in Windows NT and Windows 95
vfs.txt
diff --git a/Documentation/filesystems/umsdos.txt b/Documentation/filesystems/umsdos.txt
deleted file mode 100644
index c253708f3466..000000000000
--- a/Documentation/filesystems/umsdos.txt
+++ /dev/null
@@ -1,100 +0,0 @@
-Firstly, let me say that UMSDOS is going through some major code changes,
-and has some KNOWN BUGS (and quite a few unknown :-). Please read
-fs/umsdos/README-WIP.txt for more information on current status. Thanks.
-
-----------------------------------------------------------------------------
-Very short explanation for the impatient!
-
-Umsdos is a file system driver that run on top the MSDOS fs driver.
-It is written by Jacques Gelinas (jacques@solucorp.qc.ca)
-and is currently maintained by Matija Nalis (mnalis@jagor.srce.hr)
-
-Umsdos is not a file system per se, but a twist to make a boring
-one into a useful one.
-
-It gives you:
-
- long file names
- Permissions and owners
- Links
- Special files (devices, pipes...)
- All that is needed to be a linux root fs.
-
-There is plenty of documentation on it in the source. A formatted document
-made from those comments is available from
-sunsite.unc.edu:/pub/Linux/system/Filesystems/umsdos.
-
-You mount a DOS partition like this:
-
-mount -t umsdos /dev/hda3 /mnt
- ^
----------|
-
-All options are passed to the msdos drivers. Option like uid,gid etc are
-given to msdos.
-
-The default behavior of Umsdos is to do the same thing as the msdos driver
-mostly passing commands to it without much processing. Again, this is
-the default. After doing the mount on a DOS partition, nothing special
-happens. This is why all mount options are passed to the msdos fs driver.
-
-Umsdos uses a special DOS file --linux-.--- to store the information
-which can't be handled by the normal MS-DOS filesystem. This is the trick.
-
---linux-.--- is optional. There is one per directory.
-
-**** If --linux-.--- is missing, then Umsdos process the directory the
- same way the msdos driver does. Short file names, no goodies, default
- owner and permissions. So each directory may have or not this
- --linux-.---
-
-Now, how to get those --linux-.---.
-
-\begin joke_section
-
- Well send me a directory content
- and I will send you one customised for you.
- $5 per directory. Add any applicable taxes.
-\end joke_section
-
-A utility umssync creates those. The kernel maintains them. It is available
-from the same directory above (sunsite) in the file umsdos_progs-0.7.tar.gz.
-A compiled version is available in umsdos_progs-0.7.bin.tar.gz.
-
-So in our example, after mounting mnt, we do
-
- umssync .
-
-This will promote this directory (a recursive option is available) to full
-umsdos capabilities (long name, etc.). However, an "ls -l" before and after
-won't show much difference. The files which were there are still there, but
-now you can do all this:
-
- chmod 644 *
- chown you.your_group *
- ls >THIS_IS.A.VERY.LONG.NAME
- ln -s toto tata
- ls -l
-
-Once a directory is promoted, all subdirectories created will inherit that
-promotion.
-
-What happens if you boot DOS and create files in those promoted directories ?
-Umsdos won't notice new files, but will signal removed files (it won't crash).
-Using umssync in /etc/rc will make sure the DOS directory is in sync with
-the --linux-.---.
-
-It is a good idea to put the following command in your RC file just
-after the "mount -a":
-
- mount -a
- /sbin/umssync -i+ -c+ -r99 /umsdos_mount_point
-
- (You put one for each umsdos mount point in the fstab)
-
-This will ensure nice operation. A umsdos.fsck is in the making,
-so you will be allowed to manage umsdos partitions in the same way
-other filesystems are, using the generic fsck front end.
-
-Hope this helps!
-
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 26f119c12940..b6a0c0fc50df 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -673,7 +673,11 @@ running once the system is up.
mac53c9x= [HW,SCSI]
Format: <num_esps>,<disconnect>,<nosync>,<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
-
+
+ machvec= [IA64]
+ Force the use of a particular machine-vector (machvec) in a generic
+ kernel. Example: machvec=hpzx1_swiotlb
+
mad16= [HW,OSS]
Format: <io>,<irq>,<dma>,<dma16>,<mpu_io>,<mpu_irq>,<joystick>
diff --git a/Documentation/networking/pktgen.txt b/Documentation/networking/pktgen.txt
index 99c1485d7b4a..cc4b4d04129c 100644
--- a/Documentation/networking/pktgen.txt
+++ b/Documentation/networking/pktgen.txt
@@ -1,77 +1,214 @@
-How to use the Linux packet generator module.
-
-1. Enable CONFIG_NET_PKTGEN to compile and build pktgen.o, install it
- in the place where insmod may find it.
-2. Cut script "ipg" (see below).
-3. Edit script to set preferred device and destination IP address.
-3a. Create more scripts for different interfaces. Up to thirty-two
- pktgen processes can be configured and run at once by using the
- 32 /proc/net/pktgen/pg* files.
-4. Run in shell: ". ipg"
-5. After this two commands are defined:
- A. "pg" to start generator and to get results.
- B. "pgset" to change generator parameters. F.e.
- pgset "clone_skb 100" sets the number of copies of the same packet
- will be sent before a new packet is allocated
- pgset "clone_skb 0" use multiple SKBs for packet generation
- pgset "pkt_size 9014" sets packet size to 9014
- pgset "frags 5" packet will consist of 5 fragments
- pgset "count 200000" sets number of packets to send, set to zero
- for continuous sends until explicitly
- stopped.
- pgset "ipg 5000" sets artificial gap inserted between packets
- to 5000 nanoseconds
- pgset "dst 10.0.0.1" sets IP destination address
- (BEWARE! This generator is very aggressive!)
- pgset "dst_min 10.0.0.1" Same as dst
- pgset "dst_max 10.0.0.254" Set the maximum destination IP.
- pgset "src_min 10.0.0.1" Set the minimum (or only) source IP.
- pgset "src_max 10.0.0.254" Set the maximum source IP.
- pgset "dstmac 00:00:00:00:00:00" sets MAC destination address
- pgset "srcmac 00:00:00:00:00:00" sets MAC source address
- pgset "src_mac_count 1" Sets the number of MACs we'll range through. The
- 'minimum' MAC is what you set with srcmac.
- pgset "dst_mac_count 1" Sets the number of MACs we'll range through. The
- 'minimum' MAC is what you set with dstmac.
- pgset "flag [name]" Set a flag to determine behaviour. Current flags
- are: IPSRC_RND #IP Source is random (between min/max),
- IPDST_RND, UDPSRC_RND,
- UDPDST_RND, MACSRC_RND, MACDST_RND
- pgset "udp_src_min 9" set UDP source port min, If < udp_src_max, then
- cycle through the port range.
- pgset "udp_src_max 9" set UDP source port max.
- pgset "udp_dst_min 9" set UDP destination port min, If < udp_dst_max, then
- cycle through the port range.
- pgset "udp_dst_max 9" set UDP destination port max.
- pgset stop aborts injection
-
- Also, ^C aborts generator.
-
----- cut here
-
-#! /bin/sh
-
-modprobe pktgen
-
-PGDEV=/proc/net/pktgen/pg0
-
-function pgset() {
- local result
-
- echo $1 > $PGDEV
-
- result=`cat $PGDEV | fgrep "Result: OK:"`
- if [ "$result" = "" ]; then
- cat $PGDEV | fgrep Result:
- fi
-}
-
-function pg() {
- echo inject > $PGDEV
- cat $PGDEV
-}
-
-pgset "odev eth0"
-pgset "dst 0.0.0.0"
-
----- cut here
+
+
+ HOWTO for the linux packet generator
+ ------------------------------------
+
+Date: 041221
+
+Enable CONFIG_NET_PKTGEN to compile and build pktgen.o either in kernel
+or as module. Module is preferred. insmod pktgen if needed. Once running
+pktgen creates a thread on each CPU where each thread has affinty it's CPU.
+Monitoring and controlling is done via /proc. Easiest to select a suitable
+a sample script and configure.
+
+On a dual CPU:
+
+ps aux | grep pkt
+root 129 0.3 0.0 0 0 ? SW 2003 523:20 [pktgen/0]
+root 130 0.3 0.0 0 0 ? SW 2003 509:50 [pktgen/1]
+
+
+For montoring and control pktgen creates:
+ /proc/net/pktgen/pgctrl
+ /proc/net/pktgen/kpktgend_X
+ /proc/net/pktgen/ethX
+
+
+Viewing threads
+===============
+/proc/net/pktgen/kpktgend_0
+Name: kpktgend_0 max_before_softirq: 10000
+Running:
+Stopped: eth1
+Result: OK: max_before_softirq=10000
+
+Most important the devices assigend to thread. Note! A device can only belong
+to one thread.
+
+
+Viewing devices
+===============
+
+Parm section holds configured info. Current hold running stats.
+Result is printed after run or after interruption. Example:
+
+/proc/net/pktgen/eth1
+
+Params: count 10000000 min_pkt_size: 60 max_pkt_size: 60
+ frags: 0 delay: 0 clone_skb: 1000000 ifname: eth1
+ flows: 0 flowlen: 0
+ dst_min: 10.10.11.2 dst_max:
+ src_min: src_max:
+ src_mac: 00:00:00:00:00:00 dst_mac: 00:04:23:AC:FD:82
+ udp_src_min: 9 udp_src_max: 9 udp_dst_min: 9 udp_dst_max: 9
+ src_mac_count: 0 dst_mac_count: 0
+ Flags:
+Current:
+ pkts-sofar: 10000000 errors: 39664
+ started: 1103053986245187us stopped: 1103053999346329us idle: 880401us
+ seq_num: 10000011 cur_dst_mac_offset: 0 cur_src_mac_offset: 0
+ cur_saddr: 0x10a0a0a cur_daddr: 0x20b0a0a
+ cur_udp_dst: 9 cur_udp_src: 9
+ flows: 0
+Result: OK: 13101142(c12220741+d880401) usec, 10000000 (60byte,0frags)
+ 763292pps 390Mb/sec (390805504bps) errors: 39664
+
+Confguring threads and devices
+==============================
+This is done via the /proc interface easiest done via pgset in the scripts
+
+Examples:
+
+ pgset "clone_skb 1" sets the number of copies of the same packet
+ pgset "clone_skb 0" use single SKB for all transmits
+ pgset "pkt_size 9014" sets packet size to 9014
+ pgset "frags 5" packet will consist of 5 fragments
+ pgset "count 200000" sets number of packets to send, set to zero
+ for continious sends untill explicitl stopped.
+
+ pgset "delay 5000" adds delay to hard_start_xmit(). nanoseconds
+
+ pgset "dst 10.0.0.1" sets IP destination address
+ (BEWARE! This generator is very aggressive!)
+
+ pgset "dst_min 10.0.0.1" Same as dst
+ pgset "dst_max 10.0.0.254" Set the maximum destination IP.
+ pgset "src_min 10.0.0.1" Set the minimum (or only) source IP.
+ pgset "src_max 10.0.0.254" Set the maximum source IP.
+ pgset "dst6 fec0::1" IPV6 destination address
+ pgset "src6 fec0::2" IPV6 source address
+ pgset "dstmac 00:00:00:00:00:00" sets MAC destination address
+ pgset "srcmac 00:00:00:00:00:00" sets MAC source address
+
+ pgset "src_mac_count 1" Sets the number of MACs we'll range through.
+ The 'minimum' MAC is what you set with srcmac.
+
+ pgset "dst_mac_count 1" Sets the number of MACs we'll range through.
+ The 'minimum' MAC is what you set with dstmac.
+
+ pgset "flag [name]" Set a flag to determine behaviour. Current flags
+ are: IPSRC_RND #IP Source is random (between min/max),
+ IPDST_RND, UDPSRC_RND,
+ UDPDST_RND, MACSRC_RND, MACDST_RND
+
+ pgset "udp_src_min 9" set UDP source port min, If < udp_src_max, then
+ cycle through the port range.
+
+ pgset "udp_src_max 9" set UDP source port max.
+ pgset "udp_dst_min 9" set UDP destination port min, If < udp_dst_max, then
+ cycle through the port range.
+ pgset "udp_dst_max 9" set UDP destination port max.
+
+ pgset stop aborts injection. Also, ^C aborts generator.
+
+
+Example scripts
+===============
+
+A collection of small tutorial scripts for pktgen is in expamples dir.
+
+pktgen.conf-1-1 # 1 CPU 1 dev
+pktgen.conf-1-2 # 1 CPU 2 dev
+pktgen.conf-2-1 # 2 CPU's 1 dev
+pktgen.conf-2-2 # 2 CPU's 2 dev
+pktgen.conf-1-1-rdos # 1 CPU 1 dev w. route DoS
+pktgen.conf-1-1-ip6 # 1 CPU 1 dev ipv6
+pktgen.conf-1-1-ip6-rdos # 1 CPU 1 dev ipv6 w. route DoS
+pktgen.conf-1-1-flows # 1 CPU 1 dev multiple flows.
+
+Run in shell: ./pktgen.conf-X-Y It does all the setup including sending.
+
+
+Interrupt affinity
+===================
+Note when adding devices to a specific CPU there good idea to also assign
+/proc/irq/XX/smp_affinity so the TX-interrupts gets bound to the same CPU.
+as this reduces cache bouncing when freeing skb's.
+
+
+Current commands and configuration options
+==========================================
+
+** Pgcontrol commands:
+
+start
+stop
+
+** Thread commands:
+
+add_device
+rem_device_all
+max_before_softirq
+
+
+** Device commands:
+
+count
+clone_skb
+debug
+
+frags
+delay
+
+src_mac_count
+dst_mac_count
+
+pkt_size
+min_pkt_size
+max_pkt_size
+
+udp_src_min
+udp_src_max
+
+udp_dst_min
+udp_dst_max
+
+flag
+ IPSRC_RND
+ TXSIZE_RND
+ IPDST_RND
+ UDPSRC_RND
+ UDPDST_RND
+ MACSRC_RND
+ MACDST_RND
+
+dst_min
+dst_max
+
+src_min
+src_max
+
+dst_mac
+src_mac
+
+clear_counters
+
+dst6
+src6
+
+flows
+flowlen
+
+References:
+ftp://robur.slu.se/pub/Linux/net-development/pktgen-testing/
+ftp://robur.slu.se/pub/Linux/net-development/pktgen-testing/examples/
+
+Paper from Linux-Kongress in Erlangen 2004.
+ftp://robur.slu.se/pub/Linux/net-development/pktgen-testing/pktgen_paper.pdf
+
+Thanks to:
+Grant Grundler for testing on IA-64 and parisc, Harald Welte, Lennert Buytenhek
+Stephen Hemminger, Andi Kleen, Dave Miller and many others.
+
+
+Good luck with the linux net-development. \ No newline at end of file
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index 435ea29bb676..2b2a3a6f96e2 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -118,6 +118,94 @@ will fail.
There is currently no way to know what states a device or driver
supports a priori. This will change in the future.
+pm_message_t meaning
+
+pm_message_t has two fields. event ("major"), and flags. If driver
+does not know event code, it aborts the request, returning error. Some
+drivers may need to deal with special cases based on the actual type
+of suspend operation being done at the system level. This is why
+there are flags.
+
+Event codes are:
+
+ON -- no need to do anything except special cases like broken
+HW.
+
+# NOTIFICATION -- pretty much same as ON?
+
+FREEZE -- stop DMA and interrupts, and be prepared to reinit HW from
+scratch. That probably means stop accepting upstream requests, the
+actual policy of what to do with them beeing specific to a given
+driver. It's acceptable for a network driver to just drop packets
+while a block driver is expected to block the queue so no request is
+lost. (Use IDE as an example on how to do that). FREEZE requires no
+power state change, and it's expected for drivers to be able to
+quickly transition back to operating state.
+
+SUSPEND -- like FREEZE, but also put hardware into low-power state. If
+there's need to distinguish several levels of sleep, additional flag
+is probably best way to do that.
+
+Transitions are only from a resumed state to a suspended state, never
+between 2 suspended states. (ON -> FREEZE or ON -> SUSPEND can happen,
+FREEZE -> SUSPEND or SUSPEND -> FREEZE can not).
+
+All events are:
+
+[NOTE NOTE NOTE: If you are driver author, you should not care; you
+should only look at event, and ignore flags.]
+
+#Prepare for suspend -- userland is still running but we are going to
+#enter suspend state. This gives drivers chance to load firmware from
+#disk and store it in memory, or do other activities taht require
+#operating userland, ability to kmalloc GFP_KERNEL, etc... All of these
+#are forbiden once the suspend dance is started.. event = ON, flags =
+#PREPARE_TO_SUSPEND
+
+Apm standby -- prepare for APM event. Quiesce devices to make life
+easier for APM BIOS. event = FREEZE, flags = APM_STANDBY
+
+Apm suspend -- same as APM_STANDBY, but it we should probably avoid
+spinning down disks. event = FREEZE, flags = APM_SUSPEND
+
+System halt, reboot -- quiesce devices to make life easier for BIOS. event
+= FREEZE, flags = SYSTEM_HALT or SYSTEM_REBOOT
+
+System shutdown -- at least disks need to be spun down, or data may be
+lost. Quiesce devices, just to make life easier for BIOS. event =
+FREEZE, flags = SYSTEM_SHUTDOWN
+
+Kexec -- turn off DMAs and put hardware into some state where new
+kernel can take over. event = FREEZE, flags = KEXEC
+
+Powerdown at end of swsusp -- very similar to SYSTEM_SHUTDOWN, except wake
+may need to be enabled on some devices. This actually has at least 3
+subtypes, system can reboot, enter S4 and enter S5 at the end of
+swsusp. event = FREEZE, flags = SWSUSP and one of SYSTEM_REBOOT,
+SYSTEM_SHUTDOWN, SYSTEM_S4
+
+Suspend to ram -- put devices into low power state. event = SUSPEND,
+flags = SUSPEND_TO_RAM
+
+Freeze for swsusp snapshot -- stop DMA and interrupts. No need to put
+devices into low power mode, but you must be able to reinitialize
+device from scratch in resume method. This has two flavors, its done
+once on suspending kernel, once on resuming kernel. event = FREEZE,
+flags = DURING_SUSPEND or DURING_RESUME
+
+Device detach requested from /sys -- deinitialize device; proably same as
+SYSTEM_SHUTDOWN, I do not understand this one too much. probably event
+= FREEZE, flags = DEV_DETACH.
+
+#These are not really events sent:
+#
+#System fully on -- device is working normally; this is probably never
+#passed to suspend() method... event = ON, flags = 0
+#
+#Ready after resume -- userland is now running, again. Time to free any
+#memory you ate during prepare to suspend... event = ON, flags =
+#READY_AFTER_RESUME
+#
Driver Detach Power Management
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index c2ea934104ed..23fbf00f14be 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -184,6 +184,8 @@ Module parameters
Module for ATI IXP 150/200/250 AC97 controllers.
ac97_clock - AC'97 clock (defalut = 48000)
+ ac97_quirk - AC'97 workaround for strange hardware
+ See the description of intel8x0 module for details.
spdif_aclink - S/PDIF transfer over AC-link (default = 1)
This module supports up to 8 cards and autoprobe.
@@ -680,16 +682,21 @@ Module parameters
* ALi m5455
ac97_clock - AC'97 codec clock base (0 = auto-detect)
- ac97_quirk - AC'97 workaround for strange hardware (-1 = default)
- -1 = default, don't override
- 0 = disable
- 1 = use headphone control as master
- 2 = swap headphone and master controls
- 3 = for AD1985, turn on OMS bit and use headphone
- 4 = for ALC65x, turn on the jack sense mode
- 5 = inverted EAPD implementation
- buggy_irq - Enable workaround for buggy interrupts on some
- motherboards (default off)
+ ac97_quirk - AC'97 workaround for strange hardware
+ The following strings are accepted:
+ default = don't override the default setting
+ disable = disable the quirk
+ hp_only = use headphone control as master
+ swap_hp = swap headphone and master controls
+ swap_surround = swap master and surround controls
+ ad_shring = for AD1985, turn on OMS bit and use headphone
+ alc_jack = for ALC65x, turn on the jack sense mode
+ inv_eapd = inverted EAPD implementation
+ mute_led = bind EAPD bit for turning on/off mute LED
+ For backward compatibility, the corresponding integer
+ value -1, 0, ... are accepted, too.
+ buggy_irq - Enable workaround for buggy interrupts on some
+ motherboards (default off)
Module supports autoprobe and multiple bus-master chips (max 8).
@@ -1402,18 +1409,21 @@ In this example, the interwave card is always loaded as the first card
ALSA PCM devices to OSS devices mapping
=======================================
-/dev/snd/pcmC0D0 -> /dev/audio0 (/dev/audio) -> minor 4
-/dev/snd/pcmC0D0 -> /dev/dsp0 (/dev/dsp) -> minor 3
-/dev/snd/pcmC0D1 -> /dev/adsp0 (/dev/adsp) -> minor 12
-/dev/snd/pcmC1D0 -> /dev/audio1 -> minor 4+16 = 20
-/dev/snd/pcmC1D0 -> /dev/dsp1 -> minor 3+16 = 19
-/dev/snd/pcmC1D1 -> /dev/adsp1 -> minor 12+16 = 28
-/dev/snd/pcmC2D0 -> /dev/audio2 -> minor 4+32 = 36
-/dev/snd/pcmC2D0 -> /dev/dsp2 -> minor 3+32 = 39
-/dev/snd/pcmC2D1 -> /dev/adsp2 -> minor 12+32 = 44
-
-The first number from /dev/snd/pcmC{X}D{Y} expression means soundcard number
-and second means device number.
+/dev/snd/pcmC0D0[c|p] -> /dev/audio0 (/dev/audio) -> minor 4
+/dev/snd/pcmC0D0[c|p] -> /dev/dsp0 (/dev/dsp) -> minor 3
+/dev/snd/pcmC0D1[c|p] -> /dev/adsp0 (/dev/adsp) -> minor 12
+/dev/snd/pcmC1D0[c|p] -> /dev/audio1 -> minor 4+16 = 20
+/dev/snd/pcmC1D0[c|p] -> /dev/dsp1 -> minor 3+16 = 19
+/dev/snd/pcmC1D1[c|p] -> /dev/adsp1 -> minor 12+16 = 28
+/dev/snd/pcmC2D0[c|p] -> /dev/audio2 -> minor 4+32 = 36
+/dev/snd/pcmC2D0[c|p] -> /dev/dsp2 -> minor 3+32 = 39
+/dev/snd/pcmC2D1[c|p] -> /dev/adsp2 -> minor 12+32 = 44
+
+The first number from /dev/snd/pcmC{X}D{Y}[c|p] expression means
+soundcard number and second means device number. The ALSA devices
+have either 'c' or 'p' suffix indicating the direction, capture and
+playback, respectively.
+
Please note that the device mapping above may be varied via the module
options of snd-pcm-oss module.
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index d12607071491..44b6eea60ece 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -14,8 +14,6 @@ Machine check
APICs
apic Use IO-APIC. Default
- Unless you have an NVidia or VIA/Uniprocessor board.
- Then it defaults to off.
noapic Don't use the IO-APIC.
@@ -25,6 +23,8 @@ APICs
pirq=... See Documentation/i386/IO-APIC.txt
+ noapictimer Don't set up the APIC timer
+
Early Console
syntax: earlyprintk=vga
@@ -61,6 +61,9 @@ Timing
This is useful when you use a panic=... timeout and need the box
quickly up again.
+ nohpet
+ Don't use the HPET timer.
+
Idle loop
idle=poll
@@ -74,7 +77,7 @@ Rebooting
reboot=b[ios] | t[riple] | k[bd] [, [w]arm | [c]old]
bios Use the CPU reboto vector for warm reset
warm Don't set the cold reboot flag
- cold Set the cold reboto flag
+ cold Set the cold reboot flag
triple Force a triple fault (init)
kbd Use the keyboard controller. cold reset (default)
@@ -83,6 +86,11 @@ Rebooting
Disadvantage is that not all hardware will be completely reinitialized
on reboot so there may be boot problems on some systems.
+ reboot=force
+
+ Don't stop other CPUs on reboot. This can make reboot more reliable
+ in some cases.
+
Non Executable Mappings
noexec=on|off
@@ -102,6 +110,9 @@ NUMA
numa=off Only set up a single NUMA node spanning all memory.
+ numa=noacpi Don't parse the SRAT table for NUMA setup
+
+ numa=fake=X Fake X nodes and ignore NUMA setup of the actual machine.
ACPI
@@ -110,6 +121,12 @@ ACPI
interpreter
acpi=force Force ACPI on (currently not needed)
+ acpi=strict Disable out of spec ACPI workarounds.
+
+ acpi_sci={edge,level,high,low} Set up ACPI SCI interrupt.
+
+ acpi=noirq Don't route interrupts
+
PCI
pci=off Don't use PCI
@@ -119,6 +136,7 @@ PCI
pci=assign-busses Assign busses
pci=irqmask=MASK Set PCI interrupt mask to MASK
pci=lastbus=NUMBER Scan upto NUMBER busses, no matter what the mptable says.
+ pci=noacpi Don't use ACPI to set up PCI interrupt routing.
IOMMU
@@ -144,3 +162,19 @@ IOMMU
pages Prereserve that many 128K pages for the software IO bounce buffering.
force Force all IO through the software TLB.
+
+Debugging
+
+ oops=panic Always panic on oopses. Default is to just kill the process,
+ but there is a small probability of deadlocking the machine.
+ This will also cause panics on machine check exceptions.
+ Useful together with panic=30 to trigger a reboot.
+
+ kstack=N Print that many words from the kernel stack in oops dumps.
+
+Misc
+
+ noreplacement Don't replace instructions with more appropiate ones
+ for the CPU. This may be useful on asymmetric MP systems
+ where some CPU have less capabilities than the others.
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 3d25b37db0bb..3bd8bd417abb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -287,6 +287,11 @@ P: Dave Gilbert
M: linux@treblig.org
S: Maintained
+ARM/CORGI MACHINE SUPPORT
+P: Richard Purdie
+M: rpurdie@rpsys.net
+S: Maintained
+
ARM/PLEB SUPPORT
P: Peter Chubb
M: pleb@gelato.unsw.edu.au
@@ -725,8 +730,8 @@ W: http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
S: Maintained
DISKQUOTA:
-P: Marco van Wieringen
-M: mvw@planets.elm.net
+P: Jan Kara
+M: jack@suse.cz
L: linux-kernel@vger.kernel.org
S: Maintained
@@ -1181,13 +1186,6 @@ M: john.ronciak@intel.com
W: http://sourceforge.net/projects/e1000/
S: Supported
-INTERMEZZO FILE SYSTEM
-P: Cluster File Systems
-M: intermezzo-devel@lists.sf.net
-W: http://www.inter-mezzo.org/
-L: intermezzo-discuss@lists.sourceforge.net
-S: Maintained
-
IOC3 DRIVER
P: Ralf Baechle
M: ralf@linux-mips.org
@@ -1990,6 +1988,20 @@ L: linux-visws-devel@lists.sf.net
W: http://linux-visws.sf.net
S: Maintained for 2.6.
+SIMTEC EB110ATX (Chalice CATS)
+P: Ben Dooks
+P: Vincent Sanders
+M: support@simtec.co.uk
+W: http://www.simtec.co.uk/products/EB110ATX/
+S: Supported
+
+SIMTEC EB2410ITX (BAST)
+P: Ben Dooks
+P: Vincent Sanders
+M: support@simtec.co.uk
+W: http://www.simtec.co.uk/products/EB2410ITX/
+S: Supported
+
SIS 5513 IDE CONTROLLER DRIVER
P: Lionel Bouton
M: Lionel.Bouton@inet6.fr
@@ -2246,13 +2258,6 @@ L: linux_udf@hpesjro.fc.hp.com
W: http://linux-udf.sourceforge.net
S: Maintained
-UMSDOS FILESYSTEM
-P: Matija Nalis
-M: Matija Nalis <mnalis-umsdos@voyager.hr>
-L: linux-kernel@vger.kernel.org
-W: http://linux.voyager.hr/umsdos/
-S: Maintained
-
UNIFORM CDROM DRIVER
P: Jens Axboe
M: axboe@suse.de
diff --git a/Makefile b/Makefile
index 3c7e1afc4a5b..46ed11f4a448 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
-SUBLEVEL = 10
-EXTRAVERSION =
+SUBLEVEL = 11
+EXTRAVERSION =-rc1
NAME=Woozy Numbat
# *DOCUMENTATION*
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e93530a40b8c..1fddb764b485 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -234,6 +234,11 @@ config SHARP_LOCOMO
depends on SA1100_COLLIE
default y
+config SHARP_SCOOP
+ bool
+ depends on PXA_SHARPSL
+ default y
+
config FORCE_MAX_ZONEORDER
int
depends on SA1111
@@ -413,20 +418,6 @@ config XIP_PHYS_ADDR
be linked for and stored to. This address is dependent on your
own flash usage.
- Please note that, if you're using MTD, you must use a flash chip
- that is NOT handled by MTD or the flash will be turned into non
- data mode for status and query purposes which will instantaneously
- crash the kernel.
-
- MTD can however be used with a XIP kernel on the same flash chip
- but only if the flash memory supports multiple partitions in
- hardware, like with the Intel K3 flash parts, and only if the
- kernel is not stored within the firrst hardware partition of the
- chip.
-
- In any case, make sure that MTD support is configured out for
- the first attempt.
-
if (ARCH_SA1100 || ARCH_INTEGRATOR)
source "drivers/cpufreq/Kconfig"
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 55fcbb7af199..6b505ce41a75 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -46,6 +46,10 @@ ifeq ($(CONFIG_CPU_XSCALE),y)
OBJS += head-xscale.o
endif
+ifeq ($(CONFIG_PXA_SHARPSL),y)
+OBJS += head-sharpsl.o
+endif
+
ifeq ($(CONFIG_DEBUG_ICEDCC),y)
OBJS += ice-dcc.o
endif
diff --git a/arch/arm/boot/compressed/head-sharpsl.S b/arch/arm/boot/compressed/head-sharpsl.S
new file mode 100644
index 000000000000..d6bf8a2b090d
--- /dev/null
+++ b/arch/arm/boot/compressed/head-sharpsl.S
@@ -0,0 +1,92 @@
+/*
+ * linux/arch/arm/boot/compressed/head-sharpsl.S
+ *
+ * Copyright (C) 2004-2005 Richard Purdie <rpurdie@rpsys.net>
+ *
+ * Sharp's bootloader doesn't pass any kind of machine ID
+ * so we have to figure out the machine for ourselves...
+ *
+ * Support for Poodle, Corgi (SL-C700), Shepherd (SL-C750)
+ * and Husky (SL-C760).
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/mach-types.h>
+
+#ifndef CONFIG_PXA_SHARPSL
+#error What am I doing here...
+#endif
+
+ .section ".start", "ax"
+
+__SharpSL_start:
+
+ ldr r1, .W100ADDR @ Base address of w100 chip + regs offset
+
+ mov r6, #0x31 @ Load Magic Init value
+ str r6, [r1, #0x280] @ to SCRATCH_UMSK
+ mov r5, #0x3000
+.W100LOOP:
+ subs r5, r5, #1
+ bne .W100LOOP
+ mov r6, #0x30 @ Load 2nd Magic Init value
+ str r6, [r1, #0x280] @ to SCRATCH_UMSK
+
+ ldr r6, [r1, #0] @ Load Chip ID
+ ldr r3, .W100ID
+ ldr r7, .POODLEID
+ cmp r6, r3
+ bne .SHARPEND @ We have no w100 - Poodle
+
+ mrc p15, 0, r6, c0, c0 @ Get Processor ID
+ and r6, r6, #0xffffff00
+ ldr r7, .CORGIID
+ ldr r3, .PXA255ID
+ cmp r6, r3
+ blo .SHARPEND @ We have a PXA250 - Corgi
+
+ mov r1, #0x0c000000 @ Base address of NAND chip
+ ldrb r3, [r1, #24] @ Load FLASHCTL
+ bic r3, r3, #0x11 @ SET NCE
+ orr r3, r3, #0x0a @ SET CLR + FLWP
+ strb r3, [r1, #24] @ Save to FLASHCTL
+ mov r2, #0x90 @ Command "readid"
+ strb r2, [r1, #20] @ Save to FLASHIO
+ bic r3, r3, #2 @ CLR CLE
+ orr r3, r3, #4 @ SET ALE
+ strb r3, [r1, #24] @ Save to FLASHCTL
+ mov r2, #0 @ Address 0x00
+ strb r2, [r1, #20] @ Save to FLASHIO
+ bic r3, r3, #4 @ CLR ALE
+ strb r3, [r1, #24] @ Save to FLASHCTL
+.SHARP1:
+ ldrb r3, [r1, #24] @ Load FLASHCTL
+ tst r3, #32 @ Is chip ready?
+ beq .SHARP1
+ ldrb r2, [r1, #20] @ NAND Manufacturer ID
+ ldrb r3, [r1, #20] @ NAND Chip ID
+ ldr r7, .SHEPHERDID
+ cmp r3, #0x76 @ 64MiB flash
+ beq .SHARPEND @ We have Shepherd
+ ldr r7, .HUSKYID @ Must be Husky
+ b .SHARPEND
+
+.PXA255ID:
+ .word 0x69052d00 @ PXA255 Processor ID
+.W100ID:
+ .word 0x57411002 @ w100 Chip ID
+.W100ADDR:
+ .word 0x08010000 @ w100 Chip ID Reg Address
+.POODLEID:
+ .word MACH_TYPE_POODLE
+.CORGIID:
+ .word MACH_TYPE_CORGI
+.SHEPHERDID:
+ .word MACH_TYPE_SHEPHERD
+.HUSKYID:
+ .word MACH_TYPE_HUSKY
+.SHARPEND:
+
+
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 5b9f9eddddec..ba4a9d3957cc 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o
obj-$(CONFIG_DMABOUNCE) += dmabounce.o
obj-$(CONFIG_TIMER_ACORN) += time-acorn.o
obj-$(CONFIG_SHARP_LOCOMO) += locomo.o
+obj-$(CONFIG_SHARP_SCOOP) += scoop.o
diff --git a/arch/arm/common/amba.c b/arch/arm/common/amba.c
index b5f5c6d2cb62..a0507f8c33fe 100644
--- a/arch/arm/common/amba.c
+++ b/arch/arm/common/amba.c
@@ -59,7 +59,7 @@ static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf,
#define amba_hotplug NULL
#endif
-static int amba_suspend(struct device *dev, u32 state)
+static int amba_suspend(struct device *dev, pm_message_t state)
{
struct amba_driver *drv = to_amba_driver(dev->driver);
int ret = 0;
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index b86e288c678c..34c8cf33ad9a 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -668,7 +668,7 @@ static int locomo_match(struct device *_dev, struct device_driver *_drv)
return dev->devid == drv->devid;
}
-static int locomo_bus_suspend(struct device *dev, u32 state)
+static int locomo_bus_suspend(struct device *dev, pm_message_t state)
{
struct locomo_dev *ldev = LOCOMO_DEV(dev);
struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 32839b819c34..c90939341db1 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -1193,7 +1193,7 @@ static int sa1111_match(struct device *_dev, struct device_driver *_drv)
return dev->devid == drv->devid;
}
-static int sa1111_bus_suspend(struct device *dev, u32 state)
+static int sa1111_bus_suspend(struct device *dev, pm_message_t state)
{
struct sa1111_dev *sadev = SA1111_DEV(dev);
struct sa1111_driver *drv = SA1111_DRV(dev->driver);
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
new file mode 100644
index 000000000000..dd41da34b0c9
--- /dev/null
+++ b/arch/arm/common/scoop.c
@@ -0,0 +1,134 @@
+/*
+ * Support code for the SCOOP interface found on various Sharp PDAs
+ *
+ * Copyright (c) 2004 Richard Purdie
+ *
+ * Based on code written by Sharp/Lineo for 2.4 kernels
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/device.h>
+#include <asm/io.h>
+#include <asm/hardware/scoop.h>
+
+static void __iomem *scoop_io_base;
+
+#define SCOOP_REG(adr) (*(volatile unsigned short*)(scoop_io_base+(adr)))
+
+void reset_scoop(void)
+{
+ SCOOP_REG(SCOOP_MCR) = 0x0100; // 00
+ SCOOP_REG(SCOOP_CDR) = 0x0000; // 04
+ SCOOP_REG(SCOOP_CPR) = 0x0000; // 0C
+ SCOOP_REG(SCOOP_CCR) = 0x0000; // 10
+ SCOOP_REG(SCOOP_IMR) = 0x0000; // 18
+ SCOOP_REG(SCOOP_IRM) = 0x00FF; // 14
+ SCOOP_REG(SCOOP_ISR) = 0x0000; // 1C
+ SCOOP_REG(SCOOP_IRM) = 0x0000;
+}
+
+static spinlock_t scoop_lock = SPIN_LOCK_UNLOCKED;
+static u32 scoop_gpwr;
+
+unsigned short set_scoop_gpio(unsigned short bit)
+{
+ unsigned short gpio_bit;
+ unsigned long flag;
+
+ spin_lock_irqsave(&scoop_lock, flag);
+ gpio_bit = SCOOP_REG(SCOOP_GPWR) | bit;
+ SCOOP_REG(SCOOP_GPWR) = gpio_bit;
+ spin_unlock_irqrestore(&scoop_lock, flag);
+
+ return gpio_bit;
+}
+
+unsigned short reset_scoop_gpio(unsigned short bit)
+{
+ unsigned short gpio_bit;
+ unsigned long flag;
+
+ spin_lock_irqsave(&scoop_lock, flag);
+ gpio_bit = SCOOP_REG(SCOOP_GPWR) & ~bit;
+ SCOOP_REG(SCOOP_GPWR) = gpio_bit;
+ spin_unlock_irqrestore(&scoop_lock, flag);
+
+ return gpio_bit;
+}
+
+EXPORT_SYMBOL(set_scoop_gpio);
+EXPORT_SYMBOL(reset_scoop_gpio);
+
+unsigned short read_scoop_reg(unsigned short reg)
+{
+ return SCOOP_REG(reg);
+}
+
+void write_scoop_reg(unsigned short reg, unsigned short data)
+{
+ SCOOP_REG(reg)=data;
+}
+
+EXPORT_SYMBOL(reset_scoop);
+EXPORT_SYMBOL(read_scoop_reg);
+EXPORT_SYMBOL(write_scoop_reg);
+
+static int scoop_suspend(struct device *dev, uint32_t state, uint32_t level)
+{
+ if (level == SUSPEND_POWER_DOWN) {
+ scoop_gpwr = SCOOP_REG(SCOOP_GPWR);
+ SCOOP_REG(SCOOP_GPWR) = 0;
+ }
+ return 0;
+}
+
+static int scoop_resume(struct device *dev, uint32_t level)
+{
+ if (level == RESUME_POWER_ON) {
+ SCOOP_REG(SCOOP_GPWR) = scoop_gpwr;
+ }
+ return 0;
+}
+
+int __init scoop_probe(struct device *dev)
+{
+ struct scoop_config *inf;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!mem)
+ return -EINVAL;
+
+ inf = dev->platform_data;
+ scoop_io_base = ioremap(mem->start, 0x1000);
+ if (!scoop_io_base)
+ return -ENOMEM;
+
+ SCOOP_REG(SCOOP_MCR) = 0x0140;
+
+ reset_scoop();
+
+ SCOOP_REG(SCOOP_GPCR) = inf->io_dir & 0xffff;
+ SCOOP_REG(SCOOP_GPWR) = inf->io_out & 0xffff;
+
+ return 0;
+}
+
+static struct device_driver scoop_driver = {
+ .name = "sharp-scoop",
+ .bus = &platform_bus_type,
+ .probe = scoop_probe,
+ .suspend = scoop_suspend,
+ .resume = scoop_resume,
+};
+
+int __init scoop_init(void)
+{
+ return driver_register(&scoop_driver);
+}
+
+subsys_initcall(scoop_init);
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 5b35e76c3ce4..5e0656e88918 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -32,6 +32,7 @@
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/kallsyms.h>
+#include <linux/proc_fs.h>
#include <asm/irq.h>
#include <asm/system.h>
@@ -85,6 +86,23 @@ static struct irqdesc bad_irq_desc = {
.disable_depth = 1,
};
+#ifdef CONFIG_SMP
+void synchronize_irq(unsigned int irq)
+{
+ struct irqdesc *desc = irq_desc + irq;
+
+ while (desc->running)
+ barrier();
+}
+EXPORT_SYMBOL(synchronize_irq);
+
+#define smp_set_running(desc) do { desc->running = 1; } while (0)
+#define smp_clear_running(desc) do { desc->running = 0; } while (0)
+#else
+#define smp_set_running(desc) do { } while (0)
+#define smp_clear_running(desc) do { } while (0)
+#endif
+
/**
* disable_irq_nosync - disable an irq without waiting
* @irq: Interrupt to disable
@@ -232,6 +250,9 @@ unlock:
#ifdef CONFIG_ARCH_ACORN
show_fiq_list(p, v);
#endif
+#ifdef CONFIG_SMP
+ show_ipi_list(p);
+#endif
seq_printf(p, "Err: %10lu\n", irq_err_count);
}
return 0;
@@ -329,18 +350,22 @@ void
do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
struct irqaction *action;
- const int cpu = smp_processor_id();
+ const unsigned int cpu = smp_processor_id();
desc->triggered = 1;
kstat_cpu(cpu).irqs[irq]++;
+ smp_set_running(desc);
+
action = desc->action;
if (action) {
int ret = __do_irq(irq, action, regs);
if (ret != IRQ_HANDLED)
report_bad_irq(irq, regs, desc, ret);
}
+
+ smp_clear_running(desc);
}
/*
@@ -350,7 +375,7 @@ do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
void
do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
- const int cpu = smp_processor_id();
+ const unsigned int cpu = smp_processor_id();
desc->triggered = 1;
@@ -414,7 +439,7 @@ void
do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
struct irqaction *action;
- const int cpu = smp_processor_id();
+ const unsigned int cpu = smp_processor_id();
desc->triggered = 1;
@@ -426,6 +451,8 @@ do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
if (likely(!desc->disable_depth)) {
kstat_cpu(cpu).irqs[irq]++;
+ smp_set_running(desc);
+
/*
* Return with this interrupt masked if no action
*/
@@ -440,6 +467,8 @@ do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
!check_irq_lock(desc, irq, regs)))
desc->chip->unmask(irq);
}
+
+ smp_clear_running(desc);
}
}
@@ -878,8 +907,97 @@ out:
EXPORT_SYMBOL(probe_irq_off);
+#ifdef CONFIG_SMP
+static void route_irq(struct irqdesc *desc, unsigned int irq, unsigned int cpu)
+{
+ pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->cpu, cpu);
+
+ spin_lock_irq(&irq_controller_lock);
+ desc->cpu = cpu;
+ desc->chip->set_cpu(desc, irq, cpu);
+ spin_unlock_irq(&irq_controller_lock);
+}
+
+#ifdef CONFIG_PROC_FS
+static int
+irq_affinity_read_proc(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ struct irqdesc *desc = irq_desc + ((int)data);
+ int len = cpumask_scnprintf(page, count, desc->affinity);
+
+ if (count - len < 2)
+ return -EINVAL;
+ page[len++] = '\n';
+ page[len] = '\0';
+
+ return len;
+}
+
+static int
+irq_affinity_write_proc(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ unsigned int irq = (unsigned int)data;
+ struct irqdesc *desc = irq_desc + irq;
+ cpumask_t affinity, tmp;
+ int ret = -EIO;
+
+ if (!desc->chip->set_cpu)
+ goto out;
+
+ ret = cpumask_parse(buffer, count, affinity);
+ if (ret)
+ goto out;
+
+ cpus_and(tmp, affinity, cpu_online_map);
+ if (cpus_empty(tmp)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ desc->affinity = affinity;
+ route_irq(desc, irq, first_cpu(tmp));
+ ret = count;
+
+ out:
+ return ret;
+}
+#endif
+#endif
+
void __init init_irq_proc(void)
{
+#if defined(CONFIG_SMP) && defined(CONFIG_PROC_FS)
+ struct proc_dir_entry *dir;
+ int irq;
+
+ dir = proc_mkdir("irq", 0);
+ if (!dir)
+ return;
+
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ struct proc_dir_entry *entry;
+ struct irqdesc *desc;
+ char name[16];
+
+ desc = irq_desc + irq;
+ memset(name, 0, sizeof(name));
+ snprintf(name, sizeof(name) - 1, "%u", irq);
+
+ desc->procdir = proc_mkdir(name, dir);
+ if (!desc->procdir)
+ continue;
+
+ entry = create_proc_entry("smp_affinity", 0600, desc->procdir);
+ if (entry) {
+ entry->nlink = 1;
+ entry->data = (void *)irq;
+ entry->read_proc = irq_affinity_read_proc;
+ entry->write_proc = irq_affinity_write_proc;
+ }
+ }
+#endif
}
void __init init_IRQ(void)
@@ -888,6 +1006,11 @@ void __init init_IRQ(void)
extern void init_dma(void);
int irq;
+#ifdef CONFIG_SMP
+ bad_irq_desc.affinity = CPU_MASK_ALL;
+ bad_irq_desc.cpu = smp_processor_id();
+#endif
+
for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) {
*desc = bad_irq_desc;
INIT_LIST_HEAD(&desc->pend);
diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
index c232d37772de..02cc6793417f 100644
--- a/arch/arm/kernel/semaphore.c
+++ b/arch/arm/kernel/semaphore.c
@@ -178,7 +178,7 @@ int __down_trylock(struct semaphore * sem)
* registers (r0 to r3 and lr), but not ip, as we use it as a return
* value in some cases..
*/
-asm(" .section .sched.text \n\
+asm(" .section .sched.text,\"ax\" \n\
.align 5 \n\
.globl __down_failed \n\
__down_failed: \n\
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 9c7874cebb43..9f0079305449 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -17,16 +17,16 @@
#include <linux/profile.h>
#include <linux/errno.h>
#include <linux/mm.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
#include <linux/seq_file.h>
#include <asm/atomic.h>
+#include <asm/cacheflush.h>
#include <asm/cpu.h>
#include <asm/processor.h>
-#include <asm/smp.h>
-#include <asm/ptrace.h>
-
-#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
+#include <asm/ptrace.h>
/*
* bitmask of present and online CPUs.
@@ -42,6 +42,7 @@ cpumask_t cpu_online_map;
*/
struct ipi_data {
spinlock_t lock;
+ unsigned long ipi_count;
unsigned long bits;
};
@@ -242,12 +243,12 @@ int smp_call_function(void (*func)(void *info), void *info, int retry,
void show_ipi_list(struct seq_file *p)
{
- int cpu;
+ unsigned int cpu;
- seq_printf(p, "IPI: ");
+ seq_puts(p, "IPI:");
for_each_online_cpu(cpu)
- seq_printf(p, "%10lu ", per_cpu(cpu_data, cpu).ipi_count);
+ seq_printf(p, " %10lu", per_cpu(ipi_data, cpu).ipi_count);
seq_putc(p, '\n');
}
@@ -316,12 +317,11 @@ static void ipi_cpu_stop(unsigned int cpu)
void do_IPI(unsigned int ipimask, struct pt_regs *regs)
{
unsigned int cpu = smp_processor_id();
+ struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
- per_cpu(cpu_data, cpu).ipi_count++;
+ ipi->ipi_count++;
if (ipimask & (1 << 0)) {
- struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
-
for (;;) {
unsigned long msgs;
diff --git a/arch/arm/lib/io-readsw-armv4.S b/arch/arm/lib/io-readsw-armv4.S
index 28c8a351119c..c92b66ecbe86 100644
--- a/arch/arm/lib/io-readsw-armv4.S
+++ b/arch/arm/lib/io-readsw-armv4.S
@@ -18,25 +18,14 @@
#endif
.endm
-.insw_bad_alignment:
- adr r0, .insw_bad_align_msg
- mov r2, lr
- b panic
-.insw_bad_align_msg:
- .asciz "insw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
- .align
-
-.insw_align: tst r1, #1
- bne .insw_bad_alignment
-
- ldrh r3, [r0]
- strh r3, [r1], #2
-
- subs r2, r2, #1
- RETINSTR(moveq, pc, lr)
+.insw_align: movs ip, r1, lsl #31
+ bne .insw_noalign
+ ldrh ip, [r0]
+ sub r2, r2, #1
+ strh ip, [r1], #2
ENTRY(__raw_readsw)
- teq r2, #0 @ do we have to check for the zero len?
+ teq r2, #0
moveq pc, lr
tst r1, #3
bne .insw_align
@@ -62,14 +51,10 @@ ENTRY(__raw_readsw)
ldrh lr, [r0]
pack ip, ip, lr
- stmia r1!, {r3 - r5, ip}
-
subs r2, r2, #8
+ stmia r1!, {r3 - r5, ip}
bpl .insw_8_lp
- tst r2, #7
- LOADREGS(eqfd, sp!, {r4, r5, pc})
-
.no_insw_8: tst r2, #4
beq .no_insw_4
@@ -83,17 +68,63 @@ ENTRY(__raw_readsw)
stmia r1!, {r3, r4}
-.no_insw_4: tst r2, #2
- beq .no_insw_2
+.no_insw_4: movs r2, r2, lsl #31
+ bcc .no_insw_2
ldrh r3, [r0]
ldrh ip, [r0]
pack r3, r3, ip
-
str r3, [r1], #4
-.no_insw_2: tst r2, #1
- ldrneh r3, [r0]
+.no_insw_2: ldrneh r3, [r0]
strneh r3, [r1]
- LOADREGS(fd, sp!, {r4, r5, pc})
+ ldmfd sp!, {r4, r5, pc}
+
+#ifdef __ARMEB__
+#define _BE_ONLY_(code...) code
+#define _LE_ONLY_(code...)
+#define push_hbyte0 lsr #8
+#define pull_hbyte1 lsl #24
+#else
+#define _BE_ONLY_(code...)
+#define _LE_ONLY_(code...) code
+#define push_hbyte0 lsl #24
+#define pull_hbyte1 lsr #8
+#endif
+
+.insw_noalign: stmfd sp!, {r4, lr}
+ ldrccb ip, [r1, #-1]!
+ bcc 1f
+
+ ldrh ip, [r0]
+ sub r2, r2, #1
+ _BE_ONLY_( mov ip, ip, ror #8 )
+ strb ip, [r1], #1
+ _LE_ONLY_( mov ip, ip, lsr #8 )
+ _BE_ONLY_( mov ip, ip, lsr #24 )
+
+1: subs r2, r2, #2
+ bmi 3f
+ _BE_ONLY_( mov ip, ip, lsl #24 )
+
+2: ldrh r3, [r0]
+ ldrh r4, [r0]
+ subs r2, r2, #2
+ orr ip, ip, r3, lsl #8
+ orr ip, ip, r4, push_hbyte0
+ str ip, [r1], #4
+ mov ip, r4, pull_hbyte1
+ bpl 2b
+
+ _BE_ONLY_( mov ip, ip, lsr #24 )
+
+3: tst r2, #1
+ strb ip, [r1], #1
+ ldrneh ip, [r0]
+ _BE_ONLY_( movne ip, ip, ror #8 )
+ strneb ip, [r1], #1
+ _LE_ONLY_( movne ip, ip, lsr #8 )
+ _BE_ONLY_( movne ip, ip, lsr #24 )
+ strneb ip, [r1]
+ ldmfd sp!, {r4, pc}
diff --git a/arch/arm/lib/io-writesw-armv4.S b/arch/arm/lib/io-writesw-armv4.S
index a4a444e11ba3..6d1d7c27806e 100644
--- a/arch/arm/lib/io-writesw-armv4.S
+++ b/arch/arm/lib/io-writesw-armv4.S
@@ -22,27 +22,17 @@
#endif
.endm
-.outsw_bad_alignment:
- adr r0, .outsw_bad_align_msg
- mov r2, lr
- b panic
-.outsw_bad_align_msg:
- .asciz "outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
- .align
-
-.outsw_align: tst r1, #1
- bne .outsw_bad_alignment
+.outsw_align: movs ip, r1, lsl #31
+ bne .outsw_noalign
ldrh r3, [r1], #2
+ sub r2, r2, #1
strh r3, [r0]
- subs r2, r2, #1
- RETINSTR(moveq, pc, lr)
-
ENTRY(__raw_writesw)
- teq r2, #0 @ do we have to check for the zero len?
+ teq r2, #0
moveq pc, lr
- tst r1, #3
+ ands r3, r1, #3
bne .outsw_align
stmfd sp!, {r4, r5, lr}
@@ -51,16 +41,13 @@ ENTRY(__raw_writesw)
bmi .no_outsw_8
.outsw_8_lp: ldmia r1!, {r3, r4, r5, ip}
+ subs r2, r2, #8
outword r3
outword r4
outword r5
outword ip
- subs r2, r2, #8
bpl .outsw_8_lp
- tst r2, #7
- LOADREGS(eqfd, sp!, {r4, r5, pc})
-
.no_outsw_8: tst r2, #4
beq .no_outsw_4
@@ -68,14 +55,41 @@ ENTRY(__raw_writesw)
outword r3
outword ip
-.no_outsw_4: tst r2, #2
- beq .no_outsw_2
+.no_outsw_4: movs r2, r2, lsl #31
+ bcc .no_outsw_2
ldr r3, [r1], #4
outword r3
-.no_outsw_2: tst r2, #1
- ldrneh r3, [r1]
+.no_outsw_2: ldrneh r3, [r1]
strneh r3, [r0]
- LOADREGS(fd, sp!, {r4, r5, pc})
+ ldmfd sp!, {r4, r5, pc}
+
+#ifdef __ARMEB__
+#define pull_hbyte0 lsl #8
+#define push_hbyte1 lsr #24
+#else
+#define pull_hbyte0 lsr #24
+#define push_hbyte1 lsl #8
+#endif
+
+.outsw_noalign: ldr r3, [r1, -r3]!
+ subcs r2, r2, #1
+ bcs 2f
+ subs r2, r2, #2
+ bmi 3f
+
+1: mov ip, r3, lsr #8
+ strh ip, [r0]
+2: mov ip, r3, pull_hbyte0
+ ldr r3, [r1, #4]!
+ subs r2, r2, #2
+ orr ip, ip, r3, push_hbyte1
+ strh ip, [r0]
+ bpl 2b
+
+3: tst r2, #1
+2: movne ip, r3, lsr #8
+ strneh ip, [r0]
+ mov pc, lr
diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c
index b46c743516a9..afafb42ae129 100644
--- a/arch/arm/mach-ixp4xx/coyote-pci.c
+++ b/arch/arm/mach-ixp4xx/coyote-pci.c
@@ -14,6 +14,7 @@
*
*/
+#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 651ff67a5754..1d06d364c34e 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -8,6 +8,7 @@
* Author: Deepak Saxena <dsaxena@plexity.net>
*/
+#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/serial.h>
diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c
index 2b8d2c731f18..c2ab9ebb5980 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c
@@ -14,6 +14,7 @@
*
*/
+#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/init.h>
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index 4aafd8e6e98a..77006d96aacf 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -8,6 +8,7 @@
* Author: Deepak Saxena <dsaxena@plexity.net>
*/
+#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/serial.h>
diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
index 0f9043362a60..ce4563f00676 100644
--- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
@@ -13,6 +13,7 @@
*
*/
+#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
diff --git a/arch/arm/mach-ixp4xx/prpmc1100-pci.c b/arch/arm/mach-ixp4xx/prpmc1100-pci.c
index a0aed9ca3834..9ee0ab9dac3a 100644
--- a/arch/arm/mach-ixp4xx/prpmc1100-pci.c
+++ b/arch/arm/mach-ixp4xx/prpmc1100-pci.c
@@ -19,6 +19,7 @@
*
*/
+#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/init.h>
diff --git a/arch/arm/mach-ixp4xx/prpmc1100-setup.c b/arch/arm/mach-ixp4xx/prpmc1100-setup.c
index 68f679a41528..ed4281565bcd 100644
--- a/arch/arm/mach-ixp4xx/prpmc1100-setup.c
+++ b/arch/arm/mach-ixp4xx/prpmc1100-setup.c
@@ -8,6 +8,7 @@
* Author: Deepak Saxena <dsaxena@plexity.net>
*/
+#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/serial.h>
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index bb28824d8cd1..f09e49d30efa 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -18,10 +18,30 @@ config ARCH_PXA_IDP
bool "Accelent Xscale IDP"
select PXA25x
+config PXA_SHARPSL
+ bool "SHARP SL-C7xx Models (Corgi, Shepherd and Husky)"
+ select PXA25x
+ help
+ Say Y here if you intend to run this kernel on a
+ Sharp SL-C700 (Corgi), SL-C750 (Shepherd) or a
+ Sharp SL-C760 (Husky) handheld computer.
+
endchoice
endmenu
+config MACH_CORGI
+ bool "Enable Sharp SL-C700 (Corgi) Support"
+ depends PXA_SHARPSL
+
+config MACH_SHEPHERD
+ bool "Enable Sharp SL-C750 (Shepherd) Support"
+ depends PXA_SHARPSL
+
+config MACH_HUSKY
+ bool "Enable Sharp SL-C760 (Husky) Support"
+ depends PXA_SHARPSL
+
config PXA25x
bool
help
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 23c51e388a91..d480bd54c95d 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_PXA27x) += pxa27x.o
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
+obj-$(CONFIG_PXA_SHARPSL) += corgi.o corgi_ssp.o ssp.o
# Support for blinky lights
led-y := leds.o
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
new file mode 100644
index 000000000000..716643c7df2a
--- /dev/null
+++ b/arch/arm/mach-pxa/corgi.c
@@ -0,0 +1,165 @@
+/*
+ * Support for Sharp SL-C7xx PDAs
+ * Models: SL-C700 (Corgi), SL-C750 (Shepherd), SL-C760 (Husky)
+ *
+ * Copyright (c) 2004-2005 Richard Purdie
+ *
+ * Based on Sharp's 2.4 kernel patches/lubbock.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irq.h>
+#include <asm/arch/corgi.h>
+
+#include <asm/hardware/scoop.h>
+
+#include "generic.h"
+
+extern void corgi_ssp_lcdtg_send (u8 adrs, u8 data);
+
+static void __init corgi_init_irq(void)
+{
+ pxa_init_irq();
+}
+
+static struct resource corgi_scoop_resources[] = {
+ [0] = {
+ .start = 0x10800000,
+ .end = 0x10800fff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct scoop_config corgi_scoop_setup = {
+ .io_dir = CORGI_SCOOP_IO_DIR,
+ .io_out = CORGI_SCOOP_IO_OUT,
+};
+
+static struct platform_device corgiscoop_device = {
+ .name = "sharp-scoop",
+ .id = -1,
+ .dev = {
+ .platform_data = &corgi_scoop_setup,
+ },
+ .num_resources = ARRAY_SIZE(corgi_scoop_resources),
+ .resource = corgi_scoop_resources,
+};
+
+static struct platform_device corgissp_device = {
+ .name = "corgi-ssp",
+ .id = -1,
+};
+
+static struct platform_device *devices[] __initdata = {
+ &corgiscoop_device,
+ &corgissp_device,
+};
+
+static struct sharpsl_flash_param_info sharpsl_flash_param;
+
+void corgi_get_param(void)
+{
+ sharpsl_flash_param.comadj_keyword = readl(FLASH_MEM_BASE + FLASH_COMADJ_MAGIC_ADR);
+ sharpsl_flash_param.comadj = readl(FLASH_MEM_BASE + FLASH_COMADJ_DATA_ADR);
+
+ sharpsl_flash_param.phad_keyword = readl(FLASH_MEM_BASE + FLASH_PHAD_MAGIC_ADR);
+ sharpsl_flash_param.phadadj = readl(FLASH_MEM_BASE + FLASH_PHAD_DATA_ADR);
+}
+
+static void __init corgi_init(void)
+{
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+static void __init fixup_corgi(struct machine_desc *desc,
+ struct tag *tags, char **cmdline, struct meminfo *mi)
+{
+ corgi_get_param();
+ mi->nr_banks=1;
+ mi->bank[0].start = 0xa0000000;
+ mi->bank[0].node = 0;
+ if (machine_is_corgi())
+ mi->bank[0].size = (32*1024*1024);
+ else
+ mi->bank[0].size = (64*1024*1024);
+}
+
+static struct map_desc corgi_io_desc[] __initdata = {
+/* virtual physical length */
+/* { 0xf1000000, 0x08000000, 0x01000000, MT_DEVICE },*/ /* LCDC (readable for Qt driver) */
+/* { 0xef700000, 0x10800000, 0x00001000, MT_DEVICE },*/ /* SCOOP */
+ { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */
+};
+
+static void __init corgi_map_io(void)
+{
+ pxa_map_io();
+ iotable_init(corgi_io_desc,ARRAY_SIZE(corgi_io_desc));
+
+ /* setup sleep mode values */
+ PWER = 0x00000002;
+ PFER = 0x00000000;
+ PRER = 0x00000002;
+ PGSR0 = 0x0158C000;
+ PGSR1 = 0x00FF0080;
+ PGSR2 = 0x0001C004;
+ /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
+ PCFR |= PCFR_OPDE;
+}
+
+#ifdef CONFIG_MACH_CORGI
+MACHINE_START(CORGI, "SHARP Corgi")
+ BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
+ FIXUP(fixup_corgi)
+ MAPIO(corgi_map_io)
+ INITIRQ(corgi_init_irq)
+ .init_machine = corgi_init,
+ .timer = &pxa_timer,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_SHEPHERD
+MACHINE_START(SHEPHERD, "SHARP Shepherd")
+ BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
+ FIXUP(fixup_corgi)
+ MAPIO(corgi_map_io)
+ INITIRQ(corgi_init_irq)
+ .init_machine = corgi_init,
+ .timer = &pxa_timer,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_HUSKY
+MACHINE_START(HUSKY, "SHARP Husky")
+ BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
+ FIXUP(fixup_corgi)
+ MAPIO(corgi_map_io)
+ INITIRQ(corgi_init_irq)
+ .init_machine = corgi_init,
+ .timer = &pxa_timer,
+MACHINE_END
+#endif
+
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
new file mode 100644
index 000000000000..1d2a881f3b7e
--- /dev/null
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -0,0 +1,247 @@
+/*
+ * SSP control code for Sharp Corgi devices
+ *
+ * Copyright (c) 2004 Richard Purdie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <asm/hardware.h>
+
+#include <asm/arch/ssp.h>
+#include <asm/arch/corgi.h>
+#include <asm/arch/pxa-regs.h>
+
+static spinlock_t corgi_ssp_lock = SPIN_LOCK_UNLOCKED;
+static struct ssp_dev corgi_ssp_dev;
+static struct ssp_state corgi_ssp_state;
+
+/*
+ * There are three devices connected to the SSP interface:
+ * 1. A touchscreen controller (TI ADS7846 compatible)
+ * 2. An LCD contoller (with some Backlight functionality)
+ * 3. A battery moinitoring IC (Maxim MAX1111)
+ *
+ * Each device uses a different speed/mode of communication.
+ *
+ * The touchscreen is very sensitive and the most frequently used
+ * so the port is left configured for this.
+ *
+ * Devices are selected using Chip Selects on GPIOs.
+ */
+
+/*
+ * ADS7846 Routines
+ */
+unsigned long corgi_ssp_ads7846_putget(ulong data)
+{
+ unsigned long ret,flag;
+
+ spin_lock_irqsave(&corgi_ssp_lock, flag);
+ GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+
+ ssp_write_word(&corgi_ssp_dev,data);
+ ret = ssp_read_word(&corgi_ssp_dev);
+
+ GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+ spin_unlock_irqrestore(&corgi_ssp_lock, flag);
+
+ return ret;
+}
+
+/*
+ * NOTE: These functions should always be called in interrupt context
+ * and use the _lock and _unlock functions. They are very time sensitive.
+ */
+void corgi_ssp_ads7846_lock(void)
+{
+ spin_lock(&corgi_ssp_lock);
+ GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+}
+
+void corgi_ssp_ads7846_unlock(void)
+{
+ GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+ spin_unlock(&corgi_ssp_lock);
+}
+
+void corgi_ssp_ads7846_put(ulong data)
+{
+ ssp_write_word(&corgi_ssp_dev,data);
+}
+
+unsigned long corgi_ssp_ads7846_get(void)
+{
+ return ssp_read_word(&corgi_ssp_dev);
+}
+
+EXPORT_SYMBOL(corgi_ssp_ads7846_putget);
+EXPORT_SYMBOL(corgi_ssp_ads7846_lock);
+EXPORT_SYMBOL(corgi_ssp_ads7846_unlock);
+EXPORT_SYMBOL(corgi_ssp_ads7846_put);
+EXPORT_SYMBOL(corgi_ssp_ads7846_get);
+
+
+/*
+ * LCD/Backlight Routines
+ */
+unsigned long corgi_ssp_dac_put(ulong data)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&corgi_ssp_lock, flag);
+ GPCR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
+
+ ssp_disable(&corgi_ssp_dev);
+ ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), SSCR1_SPH, 0, SSCR0_SerClkDiv(76));
+ ssp_enable(&corgi_ssp_dev);
+
+ ssp_write_word(&corgi_ssp_dev,data);
+ /* Read null data back from device to prevent SSP overflow */
+ ssp_read_word(&corgi_ssp_dev);
+
+ ssp_disable(&corgi_ssp_dev);
+ ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+ ssp_enable(&corgi_ssp_dev);
+ GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
+ spin_unlock_irqrestore(&corgi_ssp_lock, flag);
+
+ return 0;
+}
+
+void corgi_ssp_lcdtg_send(u8 adrs, u8 data)
+{
+ corgi_ssp_dac_put(((adrs & 0x07) << 5) | (data & 0x1f));
+}
+
+void corgi_ssp_blduty_set(int duty)
+{
+ corgi_ssp_lcdtg_send(0x02,duty);
+}
+
+EXPORT_SYMBOL(corgi_ssp_lcdtg_send);
+EXPORT_SYMBOL(corgi_ssp_blduty_set);
+
+/*
+ * Max1111 Routines
+ */
+int corgi_ssp_max1111_get(ulong data)
+{
+ unsigned long flag;
+ int voltage,voltage1,voltage2;
+
+ spin_lock_irqsave(&corgi_ssp_lock, flag);
+ GPCR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
+ ssp_disable(&corgi_ssp_dev);
+ ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(8));
+ ssp_enable(&corgi_ssp_dev);
+
+ udelay(1);
+
+ /* TB1/RB1 */
+ ssp_write_word(&corgi_ssp_dev,data);
+ ssp_read_word(&corgi_ssp_dev); /* null read */
+
+ /* TB12/RB2 */
+ ssp_write_word(&corgi_ssp_dev,0);
+ voltage1=ssp_read_word(&corgi_ssp_dev);
+
+ /* TB13/RB3*/
+ ssp_write_word(&corgi_ssp_dev,0);
+ voltage2=ssp_read_word(&corgi_ssp_dev);
+
+ ssp_disable(&corgi_ssp_dev);
+ ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+ ssp_enable(&corgi_ssp_dev);
+ GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
+ spin_unlock_irqrestore(&corgi_ssp_lock, flag);
+
+ if (voltage1 & 0xc0 || voltage2 & 0x3f)
+ voltage = -1;
+ else
+ voltage = ((voltage1 << 2) & 0xfc) | ((voltage2 >> 6) & 0x03);
+
+ return voltage;
+}
+
+EXPORT_SYMBOL(corgi_ssp_max1111_get);
+
+/*
+ * Support Routines
+ */
+int __init corgi_ssp_probe(struct device *dev)
+{
+ int ret;
+
+ /* Chip Select - Disable All */
+ GPDR0 |= GPIO_bit(CORGI_GPIO_LCDCON_CS); /* output */
+ GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */
+ GPDR0 |= GPIO_bit(CORGI_GPIO_MAX1111_CS); /* output */
+ GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/
+ GPDR0 |= GPIO_bit(CORGI_GPIO_ADS7846_CS); /* output */
+ GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/
+
+ ret=ssp_init(&corgi_ssp_dev,1);
+
+ if (ret)
+ printk(KERN_ERR "Unable to register SSP handler!\n");
+ else {
+ ssp_disable(&corgi_ssp_dev);
+ ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+ ssp_enable(&corgi_ssp_dev);
+ }
+
+ return ret;
+}
+
+static int corgi_ssp_remove(struct device *dev)
+{
+ ssp_exit(&corgi_ssp_dev);
+ return 0;
+}
+
+static int corgi_ssp_suspend(struct device *dev, u32 state, u32 level)
+{
+ if (level == SUSPEND_POWER_DOWN) {
+ ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state);
+ }
+ return 0;
+}
+
+static int corgi_ssp_resume(struct device *dev, u32 level)
+{
+ if (level == RESUME_POWER_ON) {
+ GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */
+ GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/
+ GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/
+ ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
+ ssp_enable(&corgi_ssp_dev);
+ }
+ return 0;
+}
+
+static struct device_driver corgissp_driver = {
+ .name = "corgi-ssp",
+ .bus = &platform_bus_type,
+ .probe = corgi_ssp_probe,
+ .remove = corgi_ssp_remove,
+ .suspend = corgi_ssp_suspend,
+ .resume = corgi_ssp_resume,
+};
+
+int __init corgi_ssp_init(void)
+{
+ return driver_register(&corgissp_driver);
+}
+
+arch_initcall(corgi_ssp_init);
diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
index 7c90dab27098..d7b2c61d11c6 100644
--- a/arch/arm/mach-s3c2410/cpu.h
+++ b/arch/arm/mach-s3c2410/cpu.h
@@ -13,6 +13,7 @@
* 24-Aug-2004 BJD Start of generic S3C24XX support
* 18-Oct-2004 BJD Moved board struct into this file
* 04-Jan-2005 BJD New uart initialisation
+ * 10-Jan-2005 BJD Moved generic init here, specific to cpu headers
*/
#define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE }
@@ -26,25 +27,9 @@
/* forward declaration */
struct s3c2410_uartcfg;
-#ifdef CONFIG_CPU_S3C2410
-extern int s3c2410_init(void);
-extern void s3c2410_map_io(struct map_desc *mach_desc, int size);
-extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-#else
-#define s3c2410_init_uarts NULL
-#define s3c2410_map_io NULL
-#define s3c2410_init NULL
-#endif
+/* core initialisation functions */
-#ifdef CONFIG_CPU_S3C2440
-extern int s3c2440_init(void);
-extern void s3c2440_map_io(struct map_desc *mach_desc, int size);
-extern void s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-#else
-#define s3c2440_init_uarts NULL
-#define s3c2440_map_io NULL
-#define s3c2440_init NULL
-#endif
+extern void s3c24xx_init_irq(void);
extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
@@ -65,3 +50,8 @@ struct s3c24xx_board {
};
extern void s3c24xx_set_board(struct s3c24xx_board *board);
+
+/* timer for 2410/2440 */
+
+struct sys_timer;
+extern struct sys_timer s3c24xx_timer;
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index a8a48f743047..6b0b93e5aa41 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -628,12 +628,12 @@ s3c_irq_demux_uart2(unsigned int irq,
s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
}
-/* s3c2410_init_irq
+/* s3c24xx_init_irq
*
* Initialise S3C2410 IRQ system
*/
-void __init s3c2410_init_irq(void)
+void __init s3c24xx_init_irq(void)
{
unsigned long pend;
unsigned long last;
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 3126b641248d..a6c05555445f 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -20,7 +20,8 @@
* 18-Jan-2003 BJD Added serial port configuration
* 05-Oct-2004 BJD Power management code
* 04-Nov-2004 BJD Updated serial port clocks
- * 04-Jan-2004 BJD New uart init call
+ * 04-Jan-2006 BJD New uart init call
+ * 10-Jan-2005 BJD Removed include of s3c2410.h
*/
#include <linux/kernel.h>
@@ -48,7 +49,6 @@
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-mem.h>
-#include "s3c2410.h"
#include "clock.h"
#include "devs.h"
#include "cpu.h"
@@ -270,7 +270,7 @@ void __init bast_map_io(void)
void __init bast_init_irq(void)
{
- s3c2410_init_irq();
+ s3c24xx_init_irq();
}
#ifdef CONFIG_PM
@@ -307,5 +307,5 @@ MACHINE_START(BAST, "Simtec-BAST")
MAPIO(bast_map_io)
INITIRQ(bast_init_irq)
.init_machine = bast_init_machine,
- .timer = &s3c2410_timer,
+ .timer = &s3c24xx_timer,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index ae200e86833b..9044d287e03a 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -21,6 +21,7 @@
* 18-Oct-2004 BJD Updated new board structure name
* 04-Nov-2004 BJD Change for new serial clock
* 04-Jan-2005 BJD Updated uart init call
+ * 10-Jan-2005 BJD Removed include of s3c2410.h
*/
#include <linux/kernel.h>
@@ -45,7 +46,6 @@
#include <linux/serial_core.h>
-#include "s3c2410.h"
#include "clock.h"
#include "devs.h"
#include "cpu.h"
@@ -109,7 +109,7 @@ void __init h1940_map_io(void)
void __init h1940_init_irq(void)
{
- s3c2410_init_irq();
+ s3c24xx_init_irq();
}
@@ -119,5 +119,5 @@ MACHINE_START(H1940, "IPAQ-H1940")
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(h1940_map_io)
INITIRQ(h1940_init_irq)
- .timer = &s3c2410_timer,
+ .timer = &s3c24xx_timer,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
index 763aeaf6be44..38241c908bbd 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2410/mach-rx3715.c
@@ -12,6 +12,7 @@
* Modifications:
* 16-Sep-2004 BJD Copied from mach-h1940.c
* 25-Oct-2004 BJD Updates for 2.6.10-rc1
+ * 10-Jan-2005 BJD Removed include of s3c2410.h s3c2440.h
*/
#include <linux/kernel.h>
@@ -38,8 +39,6 @@
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
-#include "s3c2410.h"
-#include "s3c2440.h"
#include "clock.h"
#include "devs.h"
#include "cpu.h"
@@ -101,7 +100,7 @@ void __init rx3715_map_io(void)
void __init rx3715_init_irq(void)
{
- s3c2410_init_irq();
+ s3c24xx_init_irq();
}
#ifdef CONFIG_PM
@@ -120,5 +119,5 @@ MACHINE_START(RX3715, "IPAQ-RX3715")
MAPIO(rx3715_map_io)
INITIRQ(rx3715_init_irq)
INIT_MACHINE(rx3715_init_machine)
- .timer = &s3c2410_timer,
+ .timer = &s3c24xx_timer,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 16f9d59cd65b..ac95647362f6 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -46,7 +46,6 @@
#include <asm/arch/regs-serial.h>
-#include "s3c2410.h"
#include "devs.h"
#include "cpu.h"
@@ -104,7 +103,7 @@ void __init smdk2410_map_io(void)
void __init smdk2410_init_irq(void)
{
- s3c2410_init_irq();
+ s3c24xx_init_irq();
}
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
@@ -114,7 +113,7 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(smdk2410_map_io)
INITIRQ(smdk2410_init_irq)
- .timer = &s3c2410_timer,
+ .timer = &s3c24xx_timer,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index 2804fe5a0be5..47108f13f652 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -18,7 +18,8 @@
* 05-Apr-2004 BJD Copied to make mach-vr1000.c
* 18-Oct-2004 BJD Updated board struct
* 04-Nov-2004 BJD Clock and serial configuration update
- * 04-Jan-2004 BJD Updated uart init call
+ * 04-Jan-2005 BJD Updated uart init call
+ * 10-Jan-2005 BJD Removed include of s3c2410.h
*/
#include <linux/kernel.h>
@@ -43,7 +44,6 @@
//#include <asm/debug-ll.h>
#include <asm/arch/regs-serial.h>
-#include "s3c2410.h"
#include "clock.h"
#include "devs.h"
#include "cpu.h"
@@ -212,7 +212,7 @@ void __init vr1000_map_io(void)
void __init vr1000_init_irq(void)
{
- s3c2410_init_irq();
+ s3c24xx_init_irq();
}
MACHINE_START(VR1000, "Thorcom-VR1000")
@@ -221,5 +221,5 @@ MACHINE_START(VR1000, "Thorcom-VR1000")
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(vr1000_map_io)
INITIRQ(vr1000_init_irq)
- .timer = &s3c2410_timer,
+ .timer = &s3c24xx_timer,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index 66a34913c0a9..0d0fb36d7b58 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-s3c2410/s3c2410.c
*
- * Copyright (c) 2003,2004 Simtec Electronics
+ * Copyright (c) 2003-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* http://www.simtec.co.uk/products/EB2410ITX/
@@ -17,6 +17,7 @@
* 21-Aug-2004 BJD Added new struct s3c2410_board handler
* 28-Sep-2004 BJD Updates for new serial port bits
* 04-Nov-2004 BJD Updated UART configuration process
+ * 10-Jan-2004 BJD Removed s3c2410_clock_tick_rate
*/
#include <linux/kernel.h>
@@ -42,8 +43,6 @@
#include "cpu.h"
#include "clock.h"
-int s3c2410_clock_tick_rate = 12*1000*1000; /* current timers at 12MHz */
-
/* Initial IO mappings */
static struct map_desc s3c2410_iodesc[] __initdata = {
diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h
index d13c300a7de4..93f7a27e3cb8 100644
--- a/arch/arm/mach-s3c2410/s3c2410.h
+++ b/arch/arm/mach-s3c2410/s3c2410.h
@@ -1,7 +1,7 @@
/* arch/arm/mach-s3c2410/s3c2410.h
*
* Copyright (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Ben Dooks <ben@simtec.co.uk>
*
* Header file for s3c2410 machine directory
*
@@ -15,13 +15,19 @@
* 04-Sep-2004 BJD Added s3c2410_init_uarts() call
* 17-Oct-2004 BJD Moved board out to cpu
* 04-Jan-2005 BJD Changed uart init
+ * 10-Jan-2005 BJD Removed timer to cpu.h, moved 2410 specific bits here
*/
-extern void s3c2410_map_io(struct map_desc *, int count);
+#ifdef CONFIG_CPU_S3C2410
-extern void s3c2410_init_irq(void);
+extern int s3c2410_init(void);
-struct sys_timer;
-extern struct sys_timer s3c2410_timer;
+extern void s3c2410_map_io(struct map_desc *mach_desc, int size);
+extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+#else
+#define s3c2410_init_uarts NULL
+#define s3c2410_map_io NULL
+#define s3c2410_init NULL
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c2440-dsc.c b/arch/arm/mach-s3c2410/s3c2440-dsc.c
index bc11fbfb2526..50ccc673ff05 100644
--- a/arch/arm/mach-s3c2410/s3c2440-dsc.c
+++ b/arch/arm/mach-s3c2410/s3c2440-dsc.c
@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-s3c2410/s3c2440-dsc.c
*
- * Copyright (c) 2004 Simtec Electronics
+ * Copyright (c) 2004-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Samsung S3C2440 Drive Strength Control support
@@ -12,6 +12,7 @@
* Modifications:
* 29-Aug-2004 BJD Start of drive-strength control
* 09-Nov-2004 BJD Added symbol export
+ * 11-Jan-2005 BJD Include fix
*/
#include <linux/kernel.h>
@@ -31,8 +32,8 @@
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-dsc.h>
-#include "s3c2440.h"
#include "cpu.h"
+#include "s3c2440.h"
int s3c2440_set_dsc(unsigned int pin, unsigned int value)
{
diff --git a/arch/arm/mach-s3c2410/s3c2440.h b/arch/arm/mach-s3c2410/s3c2440.h
index 4eb19a879763..760cee377c88 100644
--- a/arch/arm/mach-s3c2410/s3c2440.h
+++ b/arch/arm/mach-s3c2410/s3c2440.h
@@ -1,7 +1,7 @@
/* arch/arm/mach-s3c2410/s3c2440.h
*
- * Copyright (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2004-2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* Header file for s3c2440 cpu support
*
@@ -12,9 +12,20 @@
* Modifications:
* 24-Aug-2004 BJD Start of S3C2440 CPU support
* 04-Nov-2004 BJD Added s3c2440_init_uarts()
- * 04-Jan-2004 BJD Moved uart init to cpu code
+ * 04-Jan-2005 BJD Moved uart init to cpu code
+ * 10-Jan-2005 BJD Moved 2440 specific init here
*/
-extern void s3c2440_init_irq(void);
+#ifdef CONFIG_CPU_S3C2440
-extern void s3c2440_init_time(void);
+extern int s3c2440_init(void);
+
+extern void s3c2440_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+#else
+#define s3c2440_init_uarts NULL
+#define s3c2440_map_io NULL
+#define s3c2440_init NULL
+#endif
diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c
index ccd16044354e..715d65a40341 100644
--- a/arch/arm/mach-s3c2410/time.c
+++ b/arch/arm/mach-s3c2410/time.c
@@ -232,7 +232,7 @@ static void __init s3c2410_timer_init (void)
setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
}
-struct sys_timer s3c2410_timer = {
+struct sys_timer s3c24xx_timer = {
.init = s3c2410_timer_init,
.offset = s3c2410_gettimeoffset,
.resume = s3c2410_timer_setup
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index e2437813cbb7..e9c99c2f12b7 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/mman.h>
+#include <linux/nodemask.h>
#include <linux/initrd.h>
#include <asm/mach-types.h>
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 9c1cd177fb93..a9c9c33dfbc3 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/highmem.h>
+#include <linux/nodemask.h>
#include <asm/pgalloc.h>
#include <asm/page.h>
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index cae9d38b5c9f..674791c81502 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -519,7 +519,7 @@ config PREEMPT
config PREEMPT_BKL
bool "Preempt The Big Kernel Lock"
- depends on PREEMPT || SMP
+ depends on PREEMPT
default y
help
This option reduces the latency of the kernel by making the
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index df8900b1f167..406f5a93d01b 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -877,23 +877,18 @@ static unsigned int __init get_8254_timer_count(void)
/* next tick in 8254 can be caught by catching timer wraparound */
static void __init wait_8254_wraparound(void)
{
- unsigned int curr_count, prev_count=~0;
- int delta;
+ unsigned int curr_count, prev_count;
curr_count = get_8254_timer_count();
-
do {
prev_count = curr_count;
curr_count = get_8254_timer_count();
- delta = curr_count-prev_count;
- /*
- * This limit for delta seems arbitrary, but it isn't, it's
- * slightly above the level of error a buggy Mercury/Neptune
- * chipset timer can cause.
- */
+ /* workaround for broken Mercury/Neptune */
+ if (prev_count >= curr_count + 0x100)
+ curr_count = get_8254_timer_count();
- } while (delta < 300);
+ } while (prev_count >= curr_count);
}
/*
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 091b98ae93b6..ae94585d0445 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -188,6 +188,23 @@ static void __init init_amd(struct cpuinfo_x86 *c)
}
display_cacheinfo(c);
+ detect_ht(c);
+
+#ifdef CONFIG_X86_HT
+ /* AMD dual core looks like HT but isn't really. Hide it from the
+ scheduler. This works around problems with the domain scheduler.
+ Also probably gives slightly better scheduling and disables
+ SMT nice which is harmful on dual core.
+ TBD tune the domain scheduler for dual core. */
+ if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
+ smp_num_siblings = 1;
+#endif
+
+ if (cpuid_eax(0x80000000) >= 0x80000008) {
+ c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
+ if (c->x86_num_cores & (c->x86_num_cores - 1))
+ c->x86_num_cores = 1;
+ }
}
static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index aef962cac862..b619be984d5a 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -10,6 +10,11 @@
#include <asm/msr.h>
#include <asm/io.h>
#include <asm/mmu_context.h>
+#ifdef CONFIG_X86_LOCAL_APIC
+#include <asm/mpspec.h>
+#include <asm/apic.h>
+#include <mach_apic.h>
+#endif
#include "cpu.h"
@@ -274,8 +279,10 @@ void __init generic_identify(struct cpuinfo_x86 * c)
/* AMD-defined flags: level 0x80000001 */
xlvl = cpuid_eax(0x80000000);
if ( (xlvl & 0xffff0000) == 0x80000000 ) {
- if ( xlvl >= 0x80000001 )
+ if ( xlvl >= 0x80000001 ) {
c->x86_capability[1] = cpuid_edx(0x80000001);
+ c->x86_capability[6] = cpuid_ecx(0x80000001);
+ }
if ( xlvl >= 0x80000004 )
get_model_name(c); /* Default name */
}
@@ -321,6 +328,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
c->x86_model = c->x86_mask = 0; /* So far unknown... */
c->x86_vendor_id[0] = '\0'; /* Unset */
c->x86_model_id[0] = '\0'; /* Unset */
+ c->x86_num_cores = 1;
memset(&c->x86_capability, 0, sizeof c->x86_capability);
if (!have_cpuid_p()) {
@@ -429,6 +437,50 @@ void __init dodgy_tsc(void)
cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data);
}
+#ifdef CONFIG_X86_HT
+void __init detect_ht(struct cpuinfo_x86 *c)
+{
+ u32 eax, ebx, ecx, edx;
+ int index_lsb, index_msb, tmp;
+ int cpu = smp_processor_id();
+
+ if (!cpu_has(c, X86_FEATURE_HT))
+ return;
+
+ cpuid(1, &eax, &ebx, &ecx, &edx);
+ smp_num_siblings = (ebx & 0xff0000) >> 16;
+
+ if (smp_num_siblings == 1) {
+ printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
+ } else if (smp_num_siblings > 1 ) {
+ index_lsb = 0;
+ index_msb = 31;
+
+ if (smp_num_siblings > NR_CPUS) {
+ printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
+ smp_num_siblings = 1;
+ return;
+ }
+ tmp = smp_num_siblings;
+ while ((tmp & 1) == 0) {
+ tmp >>=1 ;
+ index_lsb++;
+ }
+ tmp = smp_num_siblings;
+ while ((tmp & 0x80000000 ) == 0) {
+ tmp <<=1 ;
+ index_msb--;
+ }
+ if (index_lsb != index_msb )
+ index_msb++;
+ phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
+
+ printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
+ phys_proc_id[cpu]);
+ }
+}
+#endif
+
void __init print_cpu_info(struct cpuinfo_x86 *c)
{
char *vendor = NULL;
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
index eb145ed88d6a..b8d847b850dc 100644
--- a/arch/i386/kernel/cpu/intel.c
+++ b/arch/i386/kernel/cpu/intel.c
@@ -139,50 +139,7 @@ static void __init init_intel(struct cpuinfo_x86 *c)
if ( p )
strcpy(c->x86_model_id, p);
-#ifdef CONFIG_X86_HT
- if (cpu_has(c, X86_FEATURE_HT)) {
- extern int phys_proc_id[NR_CPUS];
-
- u32 eax, ebx, ecx, edx;
- int index_lsb, index_msb, tmp;
- int cpu = smp_processor_id();
-
- cpuid(1, &eax, &ebx, &ecx, &edx);
- smp_num_siblings = (ebx & 0xff0000) >> 16;
-
- if (smp_num_siblings == 1) {
- printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
- } else if (smp_num_siblings > 1 ) {
- index_lsb = 0;
- index_msb = 31;
-
- if (smp_num_siblings > NR_CPUS) {
- printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
- smp_num_siblings = 1;
- goto too_many_siblings;
- }
- tmp = smp_num_siblings;
- while ((tmp & 1) == 0) {
- tmp >>=1 ;
- index_lsb++;
- }
- tmp = smp_num_siblings;
- while ((tmp & 0x80000000 ) == 0) {
- tmp <<=1 ;
- index_msb--;
- }
- if (index_lsb != index_msb )
- index_msb++;
- phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
-
- printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
- phys_proc_id[cpu]);
- }
-
- }
-too_many_siblings:
-
-#endif
+ detect_ht(c);
/* Work around errata */
Intel_errata_workarounds(c);
diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c
index 60a04638e397..cf7fd685b345 100644
--- a/arch/i386/kernel/cpu/mtrr/generic.c
+++ b/arch/i386/kernel/cpu/mtrr/generic.c
@@ -258,7 +258,7 @@ static void prepare_set(void)
/* Save value of CR4 and clear Page Global Enable (bit 7) */
if ( cpu_has_pge ) {
cr4 = read_cr4();
- write_cr4(cr4 & (unsigned char) ~(1 << 7));
+ write_cr4(cr4 & ~X86_CR4_PGE);
}
/* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index 4ba834c44ea5..c8d83fdc237a 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -28,7 +28,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
"pni", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL,
- NULL, NULL, NULL, NULL, NULL, "lm", "3dnowext", "3dnow",
+ NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow",
/* Transmeta-defined */
"recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
@@ -45,7 +45,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
/* Intel-defined (#2) */
"pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est",
- "tm2", NULL, "cid", NULL, NULL, NULL, "xtpr", NULL,
+ "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -54,6 +54,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+ /* AMD-defined (#2) */
+ "lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
struct cpuinfo_x86 *c = v;
int i, n = c - cpu_data;
@@ -88,11 +94,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
if (c->x86_cache_size >= 0)
seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
#ifdef CONFIG_X86_HT
- if (smp_num_siblings > 1) {
- extern int phys_proc_id[NR_CPUS];
- seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]);
- seq_printf(m, "siblings\t: %d\n", smp_num_siblings);
- }
+ seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]);
+ seq_printf(m, "siblings\t: %d\n", c->x86_num_cores * smp_num_siblings);
#endif
/* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
index c6a5907c6283..e57bb554c743 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/arch/i386/kernel/dmi_scan.c
@@ -104,6 +104,11 @@ static int __init dmi_iterate(void (*decode)(struct dmi_header *))
u8 buf[15];
char __iomem *p, *q;
+ /*
+ * no iounmap() for that ioremap(); it would be a no-op, but it's
+ * so early in setup that sucker gets confused into doing what
+ * it shouldn't if we actually call it.
+ */
for (p = q = ioremap(0xF0000, 0x10000); q < p + 0x10000; q += 16) {
memcpy_fromio(buf, q, 15);
if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
@@ -125,13 +130,10 @@ static int __init dmi_iterate(void (*decode)(struct dmi_header *))
num, len));
dmi_printk((KERN_INFO "DMI table at 0x%08X.\n",
base));
- if(dmi_table(base,len, num, decode)==0) {
- iounmap(p);
+ if(dmi_table(base,len, num, decode)==0)
return 0;
- }
}
}
- iounmap(p);
return -1;
}
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index b9eb1a95bb53..1879a89d00ac 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -86,15 +86,28 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
* Interrupts are disabled on entry as trap3 is an interrupt gate and they
* remain disabled thorough out this function.
*/
-static inline int kprobe_handler(struct pt_regs *regs)
+static int kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
int ret = 0;
- u8 *addr = (u8 *) (regs->eip - 1);
+ kprobe_opcode_t *addr = NULL;
+ unsigned long *lp;
/* We're in an interrupt, but this is clear and BUG()-safe. */
preempt_disable();
-
+ /* Check if the application is using LDT entry for its code segment and
+ * calculate the address by reading the base address from the LDT entry.
+ */
+ if ((regs->xcs & 4) && (current->mm)) {
+ lp = (unsigned long *) ((unsigned long)((regs->xcs >> 3) * 8)
+ + (char *) current->mm->context.ldt);
+ addr = (kprobe_opcode_t *) ((((*lp) >> 16 & 0x0000ffff)
+ | (*(lp +1) & 0xff000000)
+ | ((*(lp +1) << 16) & 0x00ff0000))
+ + regs->eip - sizeof(kprobe_opcode_t));
+ } else {
+ addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t));
+ }
/* Check we're not actually recursing */
if (kprobe_running()) {
/* We *are* holding lock here, so this is safe.
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index 51c4bfc53c93..f98146004f5e 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -190,6 +190,12 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
goto badframe;
err |= restore_i387(buf);
+ } else {
+ struct task_struct *me = current;
+ if (me->used_math) {
+ clear_fpu(me);
+ me->used_math = 0;
+ }
}
}
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index caa3d1315a74..d1ced13320d0 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -61,6 +61,7 @@ static int __initdata smp_b_stepping;
/* Number of siblings per CPU package */
int smp_num_siblings = 1;
int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
+EXPORT_SYMBOL(phys_proc_id);
/* bitmap of online cpus */
cpumask_t cpu_online_map;
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index 1aa488b7f999..58ff04eeb9db 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/mm/ioremap.c
@@ -157,7 +157,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
/*
* Ok, go for it..
*/
- area = get_vm_area(size, VM_IOREMAP);
+ area = get_vm_area(size, VM_IOREMAP | (flags << 20));
if (!area)
return NULL;
area->phys_addr = phys_addr;
@@ -235,9 +235,9 @@ void iounmap(volatile void __iomem *addr)
if (!p) {
printk("__iounmap: bad address %p\n", addr);
return;
- }
+ }
- if (p->flags && p->phys_addr < virt_to_phys(high_memory) - 1) {
+ if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
change_page_attr(virt_to_page(__va(p->phys_addr)),
p->size >> PAGE_SHIFT,
PAGE_KERNEL);
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
index 7647cde233a7..46c86395fe40 100644
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -120,27 +120,35 @@ __change_page_attr(struct page *page, pgprot_t prot)
kpte_page = virt_to_page(kpte);
if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) {
if ((pte_val(*kpte) & _PAGE_PSE) == 0) {
- pte_t old = *kpte;
- pte_t standard = mk_pte(page, PAGE_KERNEL);
set_pte_atomic(kpte, mk_pte(page, prot));
- if (pte_same(old,standard))
- get_page(kpte_page);
} else {
struct page *split = split_large_page(address, prot);
if (!split)
return -ENOMEM;
- get_page(kpte_page);
set_pmd_pte(kpte,address,mk_pte(split, PAGE_KERNEL));
+ kpte_page = split;
}
+ get_page(kpte_page);
} else if ((pte_val(*kpte) & _PAGE_PSE) == 0) {
set_pte_atomic(kpte, mk_pte(page, PAGE_KERNEL));
__put_page(kpte_page);
- }
+ } else
+ BUG();
- if (cpu_has_pse && (page_count(kpte_page) == 1)) {
- list_add(&kpte_page->lru, &df_list);
- revert_page(kpte_page, address);
- }
+ /*
+ * If the pte was reserved, it means it was created at boot
+ * time (not via split_large_page) and in turn we must not
+ * replace it with a largepage.
+ */
+ if (!PageReserved(kpte_page)) {
+ /* memleak and potential failed 2M page regeneration */
+ BUG_ON(!page_count(kpte_page));
+
+ if (cpu_has_pse && (page_count(kpte_page) == 1)) {
+ list_add(&kpte_page->lru, &df_list);
+ revert_page(kpte_page, address);
+ }
+ }
return 0;
}
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index 27cf192061c2..af18331b3fb2 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -227,10 +227,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_
*/
static void __init pci_fixup_nforce2(struct pci_dev *dev)
{
- u32 val, fixed_val;
- u8 rev;
-
- pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+ u32 val;
/*
* Chip Old value New value
@@ -240,17 +237,14 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev)
* Northbridge chip version may be determined by
* reading the PCI revision ID (0xC1 or greater is C18D).
*/
- fixed_val = rev < 0xC1 ? 0x1F01FF01 : 0x9F01FF01;
-
pci_read_config_dword(dev, 0x6c, &val);
/*
- * Apply fixup only if C1 Halt Disconnect is enabled
- * (bit28) because it is not supported on some boards.
+ * Apply fixup if needed, but don't touch disconnect state
*/
- if ((val & (1 << 28)) && val != fixed_val) {
+ if ((val & 0x00FF0000) != 0x00010000) {
printk(KERN_WARNING "PCI: nForce2 C1 Halt Disconnect fixup\n");
- pci_write_config_dword(dev, 0x6c, fixed_val);
+ pci_write_config_dword(dev, 0x6c, (val & 0xFF00FFFF) | 0x00010000);
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 252f750115fd..9882a43ce4c1 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -737,7 +737,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
if (!pirq_table)
return 0;
- DBG("IRQ for %s:%d", pci_name(dev), pin);
+ DBG("IRQ for %s[%c]", pci_name(dev), 'A' + pin);
info = pirq_get_info(dev);
if (!info) {
DBG(" -> not found in routing table\n");
@@ -894,16 +894,16 @@ static void __init pcibios_fixup_irqs(void)
irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
PCI_SLOT(bridge->devfn), pin);
if (irq >= 0)
- printk(KERN_WARNING "PCI: using PPB(B%d,I%d,P%d) to get irq %d\n",
- bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq);
+ printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
+ pci_name(bridge), 'A' + pin, irq);
}
if (irq >= 0) {
if (use_pci_vector() &&
!platform_legacy_irq(irq))
irq = IO_APIC_VECTOR(irq);
- printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
- dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
+ printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
+ pci_name(dev), 'A' + pin, irq);
dev->irq = irq;
}
}
@@ -1053,8 +1053,8 @@ static int pirq_enable_irq(struct pci_dev *dev)
irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
PCI_SLOT(bridge->devfn), pin);
if (irq >= 0)
- printk(KERN_WARNING "PCI: using PPB(B%d,I%d,P%d) to get irq %d\n",
- bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq);
+ printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
+ pci_name(bridge), 'A' + pin, irq);
dev = bridge;
}
dev = temp_dev;
@@ -1063,8 +1063,8 @@ static int pirq_enable_irq(struct pci_dev *dev)
if (!platform_legacy_irq(irq))
irq = IO_APIC_VECTOR(irq);
#endif
- printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
- dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
+ printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
+ pci_name(dev), 'A' + pin, irq);
dev->irq = irq;
return 0;
} else
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 0b87da9d55b5..bd846b6596d2 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -61,11 +61,12 @@ config IA64_GENERIC
will run on any supported IA-64 system. However, if you configure
a kernel for your specific system, it will be faster and smaller.
- generic For any supported IA-64 system
- DIG-compliant For DIG ("Developer's Interface Guide") compliant systems
- HP-zx1/sx1000 For HP systems
- SGI-SN2 For SGI Altix systems
- Ski-simulator For the HP simulator <http://www.hpl.hp.com/research/linux/ski/>
+ generic For any supported IA-64 system
+ DIG-compliant For DIG ("Developer's Interface Guide") compliant systems
+ HP-zx1/sx1000 For HP systems
+ HP-zx1/sx1000+swiotlb For HP systems with (broken) DMA-constrained devices.
+ SGI-SN2 For SGI Altix systems
+ Ski-simulator For the HP simulator <http://www.hpl.hp.com/research/linux/ski/>
If you don't know what to do, choose "generic".
@@ -78,6 +79,15 @@ config IA64_HP_ZX1
Build a kernel that runs on HP zx1 and sx1000 systems. This adds
support for the HP I/O MMU.
+config IA64_HP_ZX1_SWIOTLB
+ bool "HP-zx1/sx1000 with software I/O TLB"
+ help
+ Build a kernel that runs on HP zx1 and sx1000 systems even when they
+ have broken PCI devices which cannot DMA to full 32 bits. Apart
+ from support for the HP I/O MMU, this includes support for the software
+ I/O TLB, which allows supporting the broken devices at the expense of
+ wasting some kernel memory (about 2MB by default).
+
config IA64_SGI_SN2
bool "SGI-SN2"
help
@@ -188,7 +198,7 @@ config HOLES_IN_ZONE
config DISCONTIGMEM
bool "Discontiguous memory support"
- depends on (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1) && NUMA && VIRTUAL_MEM_MAP
+ depends on (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB) && NUMA && VIRTUAL_MEM_MAP
default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA
help
Say Y to support efficient handling of discontiguous physical memory,
@@ -326,7 +336,7 @@ menu "Power management and ACPI"
config PM
bool "Power Management support"
- depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
+ depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB
default y
help
"Power Management" means that parts of your computer are shut
diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug
index 19edc8b2c61d..de9d507ba0fd 100644
--- a/arch/ia64/Kconfig.debug
+++ b/arch/ia64/Kconfig.debug
@@ -16,7 +16,7 @@ config IA64_GRANULE_16MB
config IA64_GRANULE_64MB
bool "64MB"
- depends on !(IA64_GENERIC || IA64_HP_ZX1 || IA64_SGI_SN2)
+ depends on !(IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_SGI_SN2)
endchoice
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index 2932ac71bd0b..c0b3d95d0f81 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -57,11 +57,13 @@ core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/
core-$(CONFIG_IA64_DIG) += arch/ia64/dig/
core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/
core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/
+core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/
drivers-$(CONFIG_PCI) += arch/ia64/pci/
drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/
drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/
+drivers-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/hp/common/ arch/ia64/hp/zx1/
drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ arch/ia64/sn/
drivers-$(CONFIG_OPROFILE) += arch/ia64/oprofile/
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index d62ec979bdfb..a32758a6a58b 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc1
-# Mon Nov 1 14:35:44 2004
+# Linux kernel version: 2.6.10
+# Mon Jan 10 13:57:35 2005
#
#
@@ -58,6 +58,7 @@ CONFIG_IA64=y
CONFIG_64BIT=y
CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_TIME_INTERPOLATION=y
CONFIG_EFI=y
CONFIG_GENERIC_IOMAP=y
@@ -75,6 +76,7 @@ CONFIG_IA64_PAGE_SIZE_16KB=y
CONFIG_IA64_L1_CACHE_SHIFT=7
CONFIG_NUMA=y
CONFIG_VIRTUAL_MEM_MAP=y
+CONFIG_HOLES_IN_ZONE=y
CONFIG_DISCONTIGMEM=y
# CONFIG_IA64_CYCLONE is not set
CONFIG_IOSAPIC=y
@@ -90,6 +92,7 @@ CONFIG_COMPAT=y
CONFIG_IA64_MCA_RECOVERY=y
CONFIG_PERFMON=y
CONFIG_IA64_PALINFO=y
+CONFIG_ACPI_DEALLOCATE_IRQ=y
#
# Firmware Drivers
@@ -110,6 +113,7 @@ CONFIG_ACPI=y
CONFIG_ACPI_BOOT=y
CONFIG_ACPI_INTERPRETER=y
# CONFIG_ACPI_BUTTON is not set
+CONFIG_ACPI_VIDEO=m
# CONFIG_ACPI_FAN is not set
# CONFIG_ACPI_PROCESSOR is not set
CONFIG_ACPI_NUMA=y
@@ -119,6 +123,7 @@ CONFIG_ACPI_BUS=y
CONFIG_ACPI_POWER=y
CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
+# CONFIG_ACPI_CONTAINER is not set
#
# Bus options (PCI, PCMCIA)
@@ -174,6 +179,7 @@ CONFIG_FW_LOADER=m
#
# Plug and Play support
#
+# CONFIG_PNP is not set
#
# Block devices
@@ -188,6 +194,7 @@ CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
@@ -200,6 +207,7 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
#
# ATA/ATAPI/MFM/RLL support
@@ -287,6 +295,7 @@ CONFIG_SCSI_CONSTANTS=y
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
#
# SCSI low-level drivers
@@ -333,7 +342,6 @@ CONFIG_SCSI_QLA22XX=y
CONFIG_SCSI_QLA2300=y
CONFIG_SCSI_QLA2322=y
# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
@@ -350,6 +358,7 @@ CONFIG_MD_RAID1=y
CONFIG_MD_RAID5=y
# CONFIG_MD_RAID6 is not set
CONFIG_MD_MULTIPATH=y
+# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
@@ -399,6 +408,8 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
CONFIG_IPV6=m
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_INET6_AH is not set
@@ -478,6 +489,7 @@ CONFIG_TIGON3=y
# CONFIG_IXGB is not set
CONFIG_S2IO=m
# CONFIG_S2IO_NAPI is not set
+# CONFIG_2BUFF_MODE is not set
#
# Token Ring devices
@@ -554,6 +566,8 @@ CONFIG_HW_CONSOLE=y
CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_ROCKETPORT is not set
# CONFIG_CYCLADES is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
# CONFIG_SYNCLINK is not set
# CONFIG_SYNCLINKMP is not set
# CONFIG_N_HDLC is not set
@@ -664,6 +678,7 @@ CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_OHCI_HCD=m
CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
#
# USB Device Class drivers
@@ -671,6 +686,10 @@ CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_BLUETOOTH_TTY is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
# CONFIG_USB_STORAGE is not set
#
@@ -700,7 +719,6 @@ CONFIG_USB_HIDINPUT=y
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
#
# USB Multimedia devices
@@ -712,7 +730,7 @@ CONFIG_USB_HIDINPUT=y
#
#
-# USB Network adaptors
+# USB Network Adapters
#
# CONFIG_USB_CATC is not set
# CONFIG_USB_KAWETH is not set
@@ -734,7 +752,6 @@ CONFIG_USB_HIDINPUT=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
@@ -754,6 +771,20 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_MTHCA=m
+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -864,7 +895,7 @@ CONFIG_SMB_FS=m
CONFIG_CIFS=m
# CONFIG_CIFS_STATS is not set
# CONFIG_CIFS_XATTR is not set
-# CONFIG_CIFS_POSIX is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -958,6 +989,7 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
CONFIG_IA64_GRANULE_16MB=y
# CONFIG_IA64_GRANULE_64MB is not set
# CONFIG_IA64_PRINT_HAZARDS is not set
@@ -994,7 +1026,12 @@ CONFIG_CRYPTO_DES=m
# CONFIG_CRYPTO_TEA is not set
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
CONFIG_CRYPTO_DEFLATE=m
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig
index c7fc9df176a7..7539e83bf054 100644
--- a/arch/ia64/defconfig
+++ b/arch/ia64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc1
-# Tue Nov 2 11:47:56 2004
+# Linux kernel version: 2.6.10
+# Thu Jan 6 11:13:13 2005
#
#
@@ -59,6 +59,7 @@ CONFIG_IA64=y
CONFIG_64BIT=y
CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_TIME_INTERPOLATION=y
CONFIG_EFI=y
CONFIG_GENERIC_IOMAP=y
@@ -90,6 +91,7 @@ CONFIG_COMPAT=y
CONFIG_IA64_MCA_RECOVERY=y
CONFIG_PERFMON=y
CONFIG_IA64_PALINFO=y
+CONFIG_ACPI_DEALLOCATE_IRQ=y
#
# Firmware Drivers
@@ -111,8 +113,10 @@ CONFIG_ACPI=y
CONFIG_ACPI_BOOT=y
CONFIG_ACPI_INTERPRETER=y
CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
CONFIG_ACPI_FAN=m
CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_HOTPLUG_CPU=y
CONFIG_ACPI_THERMAL=m
CONFIG_ACPI_NUMA=y
CONFIG_ACPI_BLACKLIST_YEAR=0
@@ -121,6 +125,7 @@ CONFIG_ACPI_BUS=y
CONFIG_ACPI_POWER=y
CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_CONTAINER=m
#
# Bus options (PCI, PCMCIA)
@@ -176,6 +181,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNP is not set
#
# Block devices
@@ -189,8 +195,10 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CDROM_PKTCDVD is not set
@@ -288,6 +296,7 @@ CONFIG_CHR_DEV_SG=m
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
#
# SCSI low-level drivers
@@ -328,7 +337,6 @@ CONFIG_SCSI_QLA22XX=m
CONFIG_SCSI_QLA2300=m
CONFIG_SCSI_QLA2322=m
# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
@@ -345,6 +353,7 @@ CONFIG_MD_RAID1=m
CONFIG_MD_RAID5=m
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
+# CONFIG_MD_FAULTY is not set
CONFIG_BLK_DEV_DM=m
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
@@ -395,6 +404,7 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -573,6 +583,7 @@ CONFIG_SERIO_I8042=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
#
@@ -601,6 +612,7 @@ CONFIG_HW_CONSOLE=y
CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_ROCKETPORT is not set
# CONFIG_CYCLADES is not set
+# CONFIG_MOXA_SMARTIO is not set
# CONFIG_SYNCLINK is not set
# CONFIG_SYNCLINKMP is not set
# CONFIG_N_HDLC is not set
@@ -651,7 +663,7 @@ CONFIG_EFI_RTC=y
CONFIG_AGP=m
CONFIG_AGP_I460=m
CONFIG_AGP_HP_ZX1=m
-CONFIG_DRM=y
+CONFIG_DRM=m
CONFIG_DRM_TDFX=m
CONFIG_DRM_R128=m
CONFIG_DRM_RADEON=m
@@ -810,6 +822,7 @@ CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_OHCI_HCD=m
CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
#
# USB Device Class drivers
@@ -819,6 +832,10 @@ CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_MIDI is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_RW_DETECT is not set
@@ -858,7 +875,6 @@ CONFIG_USB_HIDINPUT=y
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
#
# USB Multimedia devices
@@ -870,7 +886,7 @@ CONFIG_USB_HIDINPUT=y
#
#
-# USB Network adaptors
+# USB Network Adapters
#
# CONFIG_USB_CATC is not set
# CONFIG_USB_KAWETH is not set
@@ -913,6 +929,20 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_MTHCA=m
+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1023,7 +1053,7 @@ CONFIG_SMB_NLS_REMOTE="cp437"
CONFIG_CIFS=m
# CONFIG_CIFS_STATS is not set
# CONFIG_CIFS_XATTR is not set
-# CONFIG_CIFS_POSIX is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -1158,7 +1188,12 @@ CONFIG_CRYPTO_DES=m
# CONFIG_CRYPTO_TEA is not set
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ia64/hp/common/Makefile b/arch/ia64/hp/common/Makefile
index e7c7133c7ca7..f61a60057ff7 100644
--- a/arch/ia64/hp/common/Makefile
+++ b/arch/ia64/hp/common/Makefile
@@ -6,3 +6,5 @@
#
obj-y := sba_iommu.o
+obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += hwsw_iommu.o
+obj-$(CONFIG_IA64_GENERIC) += hwsw_iommu.o
diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
new file mode 100644
index 000000000000..80f8ef013939
--- /dev/null
+++ b/arch/ia64/hp/common/hwsw_iommu.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
+ * Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * This is a pseudo I/O MMU which dispatches to the hardware I/O MMU
+ * whenever possible. We assume that the hardware I/O MMU requires
+ * full 32-bit addressability, as is the case, e.g., for HP zx1-based
+ * systems (there, the I/O MMU window is mapped at 3-4GB). If a
+ * device doesn't provide full 32-bit addressability, we fall back on
+ * the sw I/O TLB. This is good enough to let us support broken
+ * hardware such as soundcards which have a DMA engine that can
+ * address only 28 bits.
+ */
+
+#include <linux/device.h>
+
+#include <asm/machvec.h>
+
+/* swiotlb declarations & definitions: */
+extern void swiotlb_init_with_default_size (size_t size);
+extern ia64_mv_dma_alloc_coherent swiotlb_alloc_coherent;
+extern ia64_mv_dma_free_coherent swiotlb_free_coherent;
+extern ia64_mv_dma_map_single swiotlb_map_single;
+extern ia64_mv_dma_unmap_single swiotlb_unmap_single;
+extern ia64_mv_dma_map_sg swiotlb_map_sg;
+extern ia64_mv_dma_unmap_sg swiotlb_unmap_sg;
+extern ia64_mv_dma_supported swiotlb_dma_supported;
+extern ia64_mv_dma_mapping_error swiotlb_dma_mapping_error;
+
+/* hwiommu declarations & definitions: */
+
+extern ia64_mv_dma_alloc_coherent sba_alloc_coherent;
+extern ia64_mv_dma_free_coherent sba_free_coherent;
+extern ia64_mv_dma_map_single sba_map_single;
+extern ia64_mv_dma_unmap_single sba_unmap_single;
+extern ia64_mv_dma_map_sg sba_map_sg;
+extern ia64_mv_dma_unmap_sg sba_unmap_sg;
+extern ia64_mv_dma_supported sba_dma_supported;
+extern ia64_mv_dma_mapping_error sba_dma_mapping_error;
+
+#define hwiommu_alloc_coherent sba_alloc_coherent
+#define hwiommu_free_coherent sba_free_coherent
+#define hwiommu_map_single sba_map_single
+#define hwiommu_unmap_single sba_unmap_single
+#define hwiommu_map_sg sba_map_sg
+#define hwiommu_unmap_sg sba_unmap_sg
+#define hwiommu_dma_supported sba_dma_supported
+#define hwiommu_dma_mapping_error sba_dma_mapping_error
+#define hwiommu_sync_single_for_cpu machvec_dma_sync_single
+#define hwiommu_sync_sg_for_cpu machvec_dma_sync_sg
+#define hwiommu_sync_single_for_device machvec_dma_sync_single
+#define hwiommu_sync_sg_for_device machvec_dma_sync_sg
+
+
+/*
+ * Note: we need to make the determination of whether or not to use
+ * the sw I/O TLB based purely on the device structure. Anything else
+ * would be unreliable or would be too intrusive.
+ */
+static inline int
+use_swiotlb (struct device *dev)
+{
+ return dev && dev->dma_mask && !hwiommu_dma_supported(dev, *dev->dma_mask);
+}
+
+void
+hwsw_init (void)
+{
+ /* default to a smallish 2MB sw I/O TLB */
+ swiotlb_init_with_default_size (2 * (1<<20));
+}
+
+void *
+hwsw_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flags)
+{
+ if (use_swiotlb(dev))
+ return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
+ else
+ return hwiommu_alloc_coherent(dev, size, dma_handle, flags);
+}
+
+void
+hwsw_free_coherent (struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+ if (use_swiotlb(dev))
+ swiotlb_free_coherent(dev, size, vaddr, dma_handle);
+ else
+ hwiommu_free_coherent(dev, size, vaddr, dma_handle);
+}
+
+dma_addr_t
+hwsw_map_single (struct device *dev, void *addr, size_t size, int dir)
+{
+ if (use_swiotlb(dev))
+ return swiotlb_map_single(dev, addr, size, dir);
+ else
+ return hwiommu_map_single(dev, addr, size, dir);
+}
+
+void
+hwsw_unmap_single (struct device *dev, dma_addr_t iova, size_t size, int dir)
+{
+ if (use_swiotlb(dev))
+ return swiotlb_unmap_single(dev, iova, size, dir);
+ else
+ return hwiommu_unmap_single(dev, iova, size, dir);
+}
+
+
+int
+hwsw_map_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir)
+{
+ if (use_swiotlb(dev))
+ return swiotlb_map_sg(dev, sglist, nents, dir);
+ else
+ return hwiommu_map_sg(dev, sglist, nents, dir);
+}
+
+void
+hwsw_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir)
+{
+ if (use_swiotlb(dev))
+ return swiotlb_unmap_sg(dev, sglist, nents, dir);
+ else
+ return hwiommu_unmap_sg(dev, sglist, nents, dir);
+}
+
+void
+hwsw_sync_single_for_cpu (struct device *dev, dma_addr_t addr, size_t size, int dir)
+{
+ if (use_swiotlb(dev))
+ swiotlb_sync_single_for_cpu(dev, addr, size, dir);
+ else
+ hwiommu_sync_single_for_cpu(dev, addr, size, dir);
+}
+
+void
+hwsw_sync_sg_for_cpu (struct device *dev, struct scatterlist *sg, int nelems, int dir)
+{
+ if (use_swiotlb(dev))
+ swiotlb_sync_sg_for_cpu(dev, sg, nelems, dir);
+ else
+ hwiommu_sync_sg_for_cpu(dev, sg, nelems, dir);
+}
+
+void
+hwsw_sync_single_for_device (struct device *dev, dma_addr_t addr, size_t size, int dir)
+{
+ if (use_swiotlb(dev))
+ swiotlb_sync_single_for_device(dev, addr, size, dir);
+ else
+ hwiommu_sync_single_for_device(dev, addr, size, dir);
+}
+
+void
+hwsw_sync_sg_for_device (struct device *dev, struct scatterlist *sg, int nelems, int dir)
+{
+ if (use_swiotlb(dev))
+ swiotlb_sync_sg_for_device(dev, sg, nelems, dir);
+ else
+ hwiommu_sync_sg_for_device(dev, sg, nelems, dir);
+}
+
+int
+hwsw_dma_supported (struct device *dev, u64 mask)
+{
+ if (hwiommu_dma_supported(dev, mask))
+ return 1;
+ return swiotlb_dma_supported(dev, mask);
+}
+
+int
+hwsw_dma_mapping_error (dma_addr_t dma_addr)
+{
+ return hwiommu_dma_mapping_error (dma_addr) || swiotlb_dma_mapping_error(dma_addr);
+}
+
+EXPORT_SYMBOL(hwsw_dma_mapping_error);
+EXPORT_SYMBOL(hwsw_map_single);
+EXPORT_SYMBOL(hwsw_unmap_single);
+EXPORT_SYMBOL(hwsw_map_sg);
+EXPORT_SYMBOL(hwsw_unmap_sg);
+EXPORT_SYMBOL(hwsw_dma_supported);
+EXPORT_SYMBOL(hwsw_alloc_coherent);
+EXPORT_SYMBOL(hwsw_free_coherent);
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 472d376b4f06..272291d6073c 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1557,7 +1557,7 @@ ioc_iova_init(struct ioc *ioc)
** We program the next pdir index after we stop w/ a key for
** the GART code to handshake on.
*/
- while ((device = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, device)) != NULL)
+ for_each_pci_dev(device)
agp_found |= pci_find_capability(device, PCI_CAP_ID_AGP);
if (agp_found && reserve_sba_gart) {
diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
index 45d69f4d3c72..ae84a1018a89 100644
--- a/arch/ia64/hp/sim/simeth.c
+++ b/arch/ia64/hp/sim/simeth.c
@@ -286,7 +286,7 @@ static __inline__ int dev_is_ethdev(struct net_device *dev)
static int
simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
{
- struct net_device *dev = (struct net_device *)ptr;
+ struct net_device *dev = ptr;
struct simeth_local *local;
struct in_device *in_dev;
struct in_ifaddr **ifap = NULL;
@@ -382,7 +382,7 @@ frame_print(unsigned char *from, unsigned char *frame, int len)
static int
simeth_tx(struct sk_buff *skb, struct net_device *dev)
{
- struct simeth_local *local = (struct simeth_local *)dev->priv;
+ struct simeth_local *local = dev->priv;
#if 0
/* ensure we have at least ETH_ZLEN bytes (min frame size) */
@@ -446,7 +446,7 @@ simeth_rx(struct net_device *dev)
int len;
int rcv_count = SIMETH_RECV_MAX;
- local = (struct simeth_local *)dev->priv;
+ local = dev->priv;
/*
* the loop concept has been borrowed from other drivers
* looks to me like it's a throttling thing to avoid pushing to many
@@ -515,7 +515,7 @@ simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs)
static struct net_device_stats *
simeth_get_stats(struct net_device *dev)
{
- struct simeth_local *local = (struct simeth_local *) dev->priv;
+ struct simeth_local *local = dev->priv;
return &local->stats;
}
diff --git a/arch/ia64/hp/zx1/Makefile b/arch/ia64/hp/zx1/Makefile
index 64e39aa82a3f..61e878729d1e 100644
--- a/arch/ia64/hp/zx1/Makefile
+++ b/arch/ia64/hp/zx1/Makefile
@@ -5,4 +5,4 @@
# Copyright (C) Alex Williamson (alex_williamson@hp.com)
#
-obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o
+obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o hpzx1_swiotlb_machvec.o
diff --git a/arch/ia64/hp/zx1/hpzx1_swiotlb_machvec.c b/arch/ia64/hp/zx1/hpzx1_swiotlb_machvec.c
new file mode 100644
index 000000000000..4392a96b3c58
--- /dev/null
+++ b/arch/ia64/hp/zx1/hpzx1_swiotlb_machvec.c
@@ -0,0 +1,3 @@
+#define MACHVEC_PLATFORM_NAME hpzx1_swiotlb
+#define MACHVEC_PLATFORM_HEADER <asm/machvec_hpzx1_swiotlb.h>
+#include <asm/machvec_init.h>
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 009e40e500ea..f79c0da79bb1 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -1873,6 +1873,10 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
compat_ptr(data));
break;
+ case PTRACE_GETEVENTMSG:
+ ret = put_user(child->ptrace_message, (unsigned int __user *) compat_ptr(data));
+ break;
+
case PTRACE_SYSCALL: /* continue, stop after next syscall */
case PTRACE_CONT: /* restart after signal. */
case PTRACE_KILL:
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 12d8bf976cc2..c1a02bbc252c 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -12,6 +12,7 @@ obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o i
obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o
obj-$(CONFIG_IA64_HP_ZX1) += acpi-ext.o
+obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += acpi-ext.o
obj-$(CONFIG_IA64_PALINFO) += palinfo.o
obj-$(CONFIG_IOSAPIC) += iosapic.o
obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index baa9c1eee662..ca062b9628ab 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -113,6 +113,8 @@ acpi_get_sysname (void)
return "hpsim";
# elif defined (CONFIG_IA64_HP_ZX1)
return "hpzx1";
+# elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB)
+ return "hpzx1_swiotlb";
# elif defined (CONFIG_IA64_SGI_SN2)
return "sn2";
# elif defined (CONFIG_IA64_DIG)
diff --git a/arch/ia64/kernel/domain.c b/arch/ia64/kernel/domain.c
index c655353941bf..db4f28a4fd0a 100644
--- a/arch/ia64/kernel/domain.c
+++ b/arch/ia64/kernel/domain.c
@@ -12,6 +12,7 @@
#include <linux/cpumask.h>
#include <linux/init.h>
#include <linux/topology.h>
+#include <linux/nodemask.h>
#define SD_NODES_PER_DOMAIN 6
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index f2ea1ad67cb7..cac7feb93f41 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -65,10 +65,27 @@ start_ap:
;;
/*
* Initialize kernel region registers:
+ * rr[0]: VHPT enabled, page size = PAGE_SHIFT
+ * rr[1]: VHPT enabled, page size = PAGE_SHIFT
+ * rr[2]: VHPT enabled, page size = PAGE_SHIFT
+ * rr[3]: VHPT enabled, page size = PAGE_SHIFT
+ * rr[4]: VHPT enabled, page size = PAGE_SHIFT
* rr[5]: VHPT enabled, page size = PAGE_SHIFT
* rr[6]: VHPT disabled, page size = IA64_GRANULE_SHIFT
* rr[7]: VHPT disabled, page size = IA64_GRANULE_SHIFT
+ * We initialize all of them to prevent inadvertently assuming
+ * something about the state of address translation early in boot.
*/
+ mov r6=((ia64_rid(IA64_REGION_ID_KERNEL, (0<<61)) << 8) | (PAGE_SHIFT << 2) | 1)
+ movl r7=(0<<61)
+ mov r8=((ia64_rid(IA64_REGION_ID_KERNEL, (1<<61)) << 8) | (PAGE_SHIFT << 2) | 1)
+ movl r9=(1<<61)
+ mov r10=((ia64_rid(IA64_REGION_ID_KERNEL, (2<<61)) << 8) | (PAGE_SHIFT << 2) | 1)
+ movl r11=(2<<61)
+ mov r12=((ia64_rid(IA64_REGION_ID_KERNEL, (3<<61)) << 8) | (PAGE_SHIFT << 2) | 1)
+ movl r13=(3<<61)
+ mov r14=((ia64_rid(IA64_REGION_ID_KERNEL, (4<<61)) << 8) | (PAGE_SHIFT << 2) | 1)
+ movl r15=(4<<61)
mov r16=((ia64_rid(IA64_REGION_ID_KERNEL, (5<<61)) << 8) | (PAGE_SHIFT << 2) | 1)
movl r17=(5<<61)
mov r18=((ia64_rid(IA64_REGION_ID_KERNEL, (6<<61)) << 8) | (IA64_GRANULE_SHIFT << 2))
@@ -76,6 +93,11 @@ start_ap:
mov r20=((ia64_rid(IA64_REGION_ID_KERNEL, (7<<61)) << 8) | (IA64_GRANULE_SHIFT << 2))
movl r21=(7<<61)
;;
+ mov rr[r7]=r6
+ mov rr[r9]=r8
+ mov rr[r11]=r10
+ mov rr[r13]=r12
+ mov rr[r15]=r14
mov rr[r17]=r16
mov rr[r19]=r18
mov rr[r21]=r20
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 662bf21331a8..bf4a4571c279 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -1133,6 +1133,7 @@ ia64_init_handler (struct pt_regs *pt, struct switch_stack *sw)
pal_min_state_area_t *ms;
oops_in_progress = 1; /* avoid deadlock in printk, but it makes recovery dodgy */
+ console_loglevel = 15; /* make sure printks make it to console */
printk(KERN_INFO "Entered OS INIT handler. PSP=%lx\n",
ia64_sal_to_os_handoff_state.proc_state_param);
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 7b2033bf0954..d35bda31d238 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -1,7 +1,7 @@
/*
* Architecture-specific setup.
*
- * Copyright (C) 1998-2001, 2003 Hewlett-Packard Co
+ * Copyright (C) 1998-2001, 2003-2004 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
* Stephane Eranian <eranian@hpl.hp.com>
* Copyright (C) 2000, Rohit Seth <rohit.seth@intel.com>
@@ -312,7 +312,28 @@ setup_arch (char **cmdline_p)
io_port_init();
#ifdef CONFIG_IA64_GENERIC
- machvec_init(acpi_get_sysname());
+ {
+ const char *mvec_name = strstr (*cmdline_p, "machvec=");
+ char str[64];
+
+ if (mvec_name) {
+ const char *end;
+ size_t len;
+
+ mvec_name += 8;
+ end = strchr (mvec_name, ' ');
+ if (end)
+ len = end - mvec_name;
+ else
+ len = strlen (mvec_name);
+ len = min(len, sizeof (str) - 1);
+ strncpy (str, mvec_name, len);
+ str[len] = '\0';
+ mvec_name = str;
+ } else
+ mvec_name = acpi_get_sysname();
+ machvec_init(mvec_name);
+ }
#endif
if (early_console_setup(*cmdline_p) == 0)
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index 76539968ac4f..f1aafd4c05f9 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -18,6 +18,7 @@
#include <linux/node.h>
#include <linux/init.h>
#include <linux/bootmem.h>
+#include <linux/nodemask.h>
#include <asm/mmzone.h>
#include <asm/numa.h>
#include <asm/cpu.h>
diff --git a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c
index e4770828db59..d38b01538184 100644
--- a/arch/ia64/lib/swiotlb.c
+++ b/arch/ia64/lib/swiotlb.c
@@ -61,9 +61,8 @@ static char *io_tlb_start, *io_tlb_end;
/*
* The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and
* io_tlb_end. This is command line adjustable via setup_io_tlb_npages.
- * Default to 64MB.
*/
-static unsigned long io_tlb_nslabs = 32768;
+static unsigned long io_tlb_nslabs;
/*
* When the IOMMU overflows we return a fallback buffer. This sets the size.
@@ -113,10 +112,15 @@ __setup("swiotlb=", setup_io_tlb_npages);
* structures for the software IO TLB used to implement the PCI DMA API.
*/
void
-swiotlb_init(void)
+swiotlb_init_with_default_size (size_t default_size)
{
unsigned long i;
+ if (!io_tlb_nslabs) {
+ io_tlb_nslabs = (default_size >> PAGE_SHIFT);
+ io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
+ }
+
/*
* Get IO TLB memory from the low pages
*/
@@ -145,6 +149,12 @@ swiotlb_init(void)
virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end));
}
+void
+swiotlb_init (void)
+{
+ swiotlb_init_with_default_size(64 * (1<<20)); /* default to 64MB */
+}
+
static inline int
address_needs_mapping(struct device *hwdev, dma_addr_t addr)
{
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 01f8eabf3636..52951437d9d3 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -6,6 +6,7 @@
* Copyright (C) 2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
* Bjorn Helgaas <bjorn_helgaas@hp.com>
+ * Copyright (C) 2004 Silicon Graphics, Inc.
*
* Note: Above list of copyright holders is incomplete...
*/
@@ -131,6 +132,19 @@ struct pci_ops pci_root_ops = {
.write = pci_write,
};
+#ifdef CONFIG_NUMA
+extern acpi_status acpi_map_iosapic(acpi_handle, u32, void *, void **);
+static void acpi_map_iosapics(void)
+{
+ acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL);
+}
+#else
+static void acpi_map_iosapics(void)
+{
+ return;
+}
+#endif /* CONFIG_NUMA */
+
static int __init
pci_acpi_init (void)
{
@@ -138,11 +152,7 @@ pci_acpi_init (void)
printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
-#ifdef CONFIG_NUMA
-extern acpi_status acpi_map_iosapic (acpi_handle, u32, void*, void**);
-
- acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL);
-#endif
+ acpi_map_iosapics();
if (pci_routeirq) {
/*
@@ -154,7 +164,7 @@ extern acpi_status acpi_map_iosapic (acpi_handle, u32, void*, void**);
printk(KERN_INFO "** was specified. If this was required to make a driver work,\n");
printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
printk(KERN_INFO "** so I can fix the driver.\n");
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
+ for_each_pci_dev(dev)
acpi_pci_irq_enable(dev);
} else {
printk(KERN_INFO "** PCI interrupts are no longer routed automatically. If this\n");
@@ -367,6 +377,7 @@ void pcibios_resource_to_bus(struct pci_dev *dev,
region->start = res->start - offset;
region->end = res->end - offset;
}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
void pcibios_bus_to_resource(struct pci_dev *dev,
struct resource *res, struct pci_bus_region *region)
@@ -526,7 +537,7 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
* Leave vm_pgoff as-is, the PCI space address is the physical
* address on this platform.
*/
- vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
+ vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO);
if (write_combine)
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
@@ -541,6 +552,117 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
}
/**
+ * ia64_pci_get_legacy_mem - generic legacy mem routine
+ * @bus: bus to get legacy memory base address for
+ *
+ * Find the base of legacy memory for @bus. This is typically the first
+ * megabyte of bus address space for @bus or is simply 0 on platforms whose
+ * chipsets support legacy I/O and memory routing. Returns the base address
+ * or an error pointer if an error occurred.
+ *
+ * This is the ia64 generic version of this routine. Other platforms
+ * are free to override it with a machine vector.
+ */
+char *ia64_pci_get_legacy_mem(struct pci_bus *bus)
+{
+ return (char *)__IA64_UNCACHED_OFFSET;
+}
+
+/**
+ * pci_mmap_legacy_page_range - map legacy memory space to userland
+ * @bus: bus whose legacy space we're mapping
+ * @vma: vma passed in by mmap
+ *
+ * Map legacy memory space for this device back to userspace using a machine
+ * vector to get the base address.
+ */
+int
+pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma)
+{
+ char *addr;
+
+ addr = pci_get_legacy_mem(bus);
+ if (IS_ERR(addr))
+ return PTR_ERR(addr);
+
+ vma->vm_pgoff += (unsigned long)addr >> PAGE_SHIFT;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO);
+
+ if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
+ return -EAGAIN;
+
+ return 0;
+}
+
+/**
+ * ia64_pci_legacy_read - read from legacy I/O space
+ * @bus: bus to read
+ * @port: legacy port value
+ * @val: caller allocated storage for returned value
+ * @size: number of bytes to read
+ *
+ * Simply reads @size bytes from @port and puts the result in @val.
+ *
+ * Again, this (and the write routine) are generic versions that can be
+ * overridden by the platform. This is necessary on platforms that don't
+ * support legacy I/O routing or that hard fail on legacy I/O timeouts.
+ */
+int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
+{
+ int ret = size;
+
+ switch (size) {
+ case 1:
+ *val = inb(port);
+ break;
+ case 2:
+ *val = inw(port);
+ break;
+ case 4:
+ *val = inl(port);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * ia64_pci_legacy_write - perform a legacy I/O write
+ * @bus: bus pointer
+ * @port: port to write
+ * @val: value to write
+ * @size: number of bytes to write from @val
+ *
+ * Simply writes @size bytes of @val to @port.
+ */
+int ia64_pci_legacy_write(struct pci_dev *bus, u16 port, u32 val, u8 size)
+{
+ int ret = 0;
+
+ switch (size) {
+ case 1:
+ outb(val, port);
+ break;
+ case 2:
+ outw(val, port);
+ break;
+ case 4:
+ outl(val, port);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/**
* pci_cacheline_size - determine cacheline size for PCI devices
* @dev: void
*
diff --git a/arch/ia64/sn/kernel/bte_error.c b/arch/ia64/sn/kernel/bte_error.c
index 3591c2cf1a84..4db0096ef0a1 100644
--- a/arch/ia64/sn/kernel/bte_error.c
+++ b/arch/ia64/sn/kernel/bte_error.c
@@ -47,6 +47,7 @@ void bte_error_handler(unsigned long _nodepda)
ii_icrb0_d_u_t icrbd; /* II CRB Register D */
ii_ibcr_u_t ibcr;
ii_icmr_u_t icmr;
+ ii_ieclr_u_t ieclr;
BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda,
smp_processor_id()));
@@ -131,6 +132,14 @@ void bte_error_handler(unsigned long _nodepda)
imem.ii_imem_fld_s.i_b0_esd = imem.ii_imem_fld_s.i_b1_esd = 1;
REMOTE_HUB_S(nasid, IIO_IMEM, imem.ii_imem_regval);
+ /* Clear BTE0/1 error bits */
+ ieclr.ii_ieclr_regval = 0;
+ if (err_nodepda->bte_if[0].bh_error != BTE_SUCCESS)
+ ieclr.ii_ieclr_fld_s.i_e_bte_0 = 1;
+ if (err_nodepda->bte_if[1].bh_error != BTE_SUCCESS)
+ ieclr.ii_ieclr_fld_s.i_e_bte_1 = 1;
+ REMOTE_HUB_S(nasid, IIO_IECLR, ieclr.ii_ieclr_regval);
+
/* Reinitialize both BTE state machines. */
ibcr.ii_ibcr_regval = REMOTE_HUB_L(nasid, IIO_IBCR);
ibcr.ii_ibcr_fld_s.i_soft_reset = 1;
@@ -152,7 +161,7 @@ void bte_error_handler(unsigned long _nodepda)
err_nodepda->bte_if[i].cleanup_active = 0;
BTE_PRINTK(("eh:%p:%d Unlocked %d\n", err_nodepda,
smp_processor_id(), i));
- spin_unlock(&pda->cpu_bte_if[i]->spinlock);
+ spin_unlock(&err_nodepda->bte_if[i].spinlock);
}
del_timer(recovery_timer);
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 032fc4774c56..001880812b7c 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -7,6 +7,7 @@
*/
#include <linux/bootmem.h>
+#include <linux/nodemask.h>
#include <asm/sn/types.h>
#include <asm/sn/sn_sal.h>
#include <asm/sn/addrs.h>
@@ -201,7 +202,7 @@ static void sn_pci_fixup_slot(struct pci_dev *dev)
struct pci_dev *host_pci_dev;
int status = 0;
- SN_PCIDEV_INFO(dev) = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL);
+ dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL);
if (SN_PCIDEV_INFO(dev) <= 0)
BUG(); /* Cannot afford to run out of memory */
memset(SN_PCIDEV_INFO(dev), 0, sizeof(struct pcidev_info));
@@ -309,8 +310,8 @@ static void sn_pci_controller_fixup(int segment, int busnum)
* after this point.
*/
- PCI_CONTROLLER(bus) = controller;
- SN_PCIBUS_BUSSOFT(bus) = provider_soft;
+ bus->sysdata = controller;
+ PCI_CONTROLLER(bus)->platform_data = provider_soft;
nasid = NASID_GET(SN_PCIBUS_BUSSOFT(bus)->bs_base);
cnode = nasid_to_cnodeid(nasid);
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index b91a5a2d9f4c..aa87b33c9d2e 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -28,6 +28,7 @@
#include <linux/compiler.h>
#include <linux/sched.h>
#include <linux/root_dev.h>
+#include <linux/nodemask.h>
#include <asm/io.h>
#include <asm/sal.h>
@@ -504,15 +505,15 @@ static void __init scan_for_ionodes(void)
/* Setup ionodes with memory */
for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) {
- u64 klgraph_header;
+ char *klgraph_header;
cnodeid_t cnodeid;
if (physical_node_map[nasid] == -1)
continue;
- klgraph_header = cnodeid = -1;
- klgraph_header = ia64_sn_get_klconfig_addr(nasid);
- if (klgraph_header <= 0) {
+ cnodeid = -1;
+ klgraph_header = __va(ia64_sn_get_klconfig_addr(nasid));
+ if (!klgraph_header) {
if (IS_RUNNING_ON_SIMULATOR())
continue;
BUG(); /* All nodes must have klconfig tables! */
diff --git a/arch/ia64/sn/kernel/sn2/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
index 78520eb5f0bf..81c63b2f8ae9 100644
--- a/arch/ia64/sn/kernel/sn2/prominfo_proc.c
+++ b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
+#include <linux/nodemask.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/sn/sn_sal.h>
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index f102dc58131e..bd088baeb210 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -19,6 +19,7 @@
#include <linux/mmzone.h>
#include <linux/module.h>
#include <linux/bitops.h>
+#include <linux/nodemask.h>
#include <asm/processor.h>
#include <asm/irq.h>
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 21c08eaa5e39..1184b23e0361 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -30,6 +30,7 @@
#include <linux/miscdevice.h>
#include <linux/cpumask.h>
#include <linux/smp_lock.h>
+#include <linux/nodemask.h>
#include <asm/processor.h>
#include <asm/topology.h>
#include <asm/smp.h>
@@ -529,8 +530,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
}
error:
- if (p)
- vfree(p);
+ vfree(p);
lock_kernel();
return r;
@@ -641,7 +641,6 @@ int sn_topology_release(struct inode *inode, struct file *file)
{
struct seq_file *seq = file->private_data;
- if (seq->private)
- vfree(seq->private);
+ vfree(seq->private);
return seq_release(inode, file);
}
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index 71f311dc04c3..4187f920d26d 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -475,3 +475,67 @@ EXPORT_SYMBOL(sn_pci_alloc_consistent);
EXPORT_SYMBOL(sn_pci_free_consistent);
EXPORT_SYMBOL(sn_pci_dma_supported);
EXPORT_SYMBOL(sn_dma_mapping_error);
+
+char *sn_pci_get_legacy_mem(struct pci_bus *bus)
+{
+ if (!SN_PCIBUS_BUSSOFT(bus))
+ return ERR_PTR(-ENODEV);
+
+ return (char *)(SN_PCIBUS_BUSSOFT(bus)->bs_legacy_mem | __IA64_UNCACHED_OFFSET);
+}
+
+int sn_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
+{
+ unsigned long addr;
+ int ret;
+
+ if (!SN_PCIBUS_BUSSOFT(bus))
+ return -ENODEV;
+
+ addr = SN_PCIBUS_BUSSOFT(bus)->bs_legacy_io | __IA64_UNCACHED_OFFSET;
+ addr += port;
+
+ ret = ia64_sn_probe_mem(addr, (long)size, (void *)val);
+
+ if (ret == 2)
+ return -EINVAL;
+
+ if (ret == 1)
+ *val = -1;
+
+ return size;
+}
+
+int sn_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
+{
+ int ret = size;
+ unsigned long paddr;
+ unsigned long *addr;
+
+ if (!SN_PCIBUS_BUSSOFT(bus)) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ /* Put the phys addr in uncached space */
+ paddr = SN_PCIBUS_BUSSOFT(bus)->bs_legacy_io | __IA64_UNCACHED_OFFSET;
+ paddr += port;
+ addr = (unsigned long *)paddr;
+
+ switch (size) {
+ case 1:
+ *(volatile u8 *)(addr) = (u8)(val);
+ break;
+ case 2:
+ *(volatile u16 *)(addr) = (u16)(val);
+ break;
+ case 4:
+ *(volatile u32 *)(addr) = (u32)(val);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ out:
+ return ret;
+}
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 3ad33ed06091..0d90ea58a0cb 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -14,7 +14,7 @@ config SBUS
config UID16
bool
- default y
+ default n
config GENERIC_ISA_DMA
bool
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
index 29b0d8d0c68e..e71801637083 100644
--- a/arch/m32r/kernel/entry.S
+++ b/arch/m32r/kernel/entry.S
@@ -725,25 +725,25 @@ ENTRY(sys_call_table)
.long sys_time
.long sys_mknod
.long sys_chmod /* 15 */
- .long sys_lchown
+ .long sys_ni_syscall /* lchown16 syscall holder */
.long sys_ni_syscall /* old break syscall holder */
- .long sys_stat
+ .long sys_ni_syscall /* old stat syscall holder */
.long sys_lseek
.long sys_getpid /* 20 */
.long sys_mount
.long sys_oldumount
- .long sys_setuid
- .long sys_getuid
+ .long sys_ni_syscall /* setuid16 syscall holder */
+ .long sys_ni_syscall /* getuid16 syscall holder */
.long sys_stime /* 25 */
.long sys_ptrace
.long sys_alarm
- .long sys_fstat
+ .long sys_ni_syscall /* old fstat syscall holder */
.long sys_pause
.long sys_utime /* 30 */
- .long sys_cacheflush /* for M32R */ /* old stty syscall holder */
+ .long sys_ni_syscall /* old stty syscall holder */
.long sys_cachectl /* for M32R */ /* old gtty syscall holder */
.long sys_access
- .long sys_nice
+ .long sys_ni_syscall /* nice syscall holder */
.long sys_ni_syscall /* 35 - old ftime syscall holder */
.long sys_sync
.long sys_kill
@@ -755,17 +755,17 @@ ENTRY(sys_call_table)
.long sys_times
.long sys_ni_syscall /* old prof syscall holder */
.long sys_brk /* 45 */
- .long sys_setgid
- .long sys_getgid
- .long sys_signal
- .long sys_geteuid
- .long sys_getegid /* 50 */
+ .long sys_ni_syscall /* setgid16 syscall holder */
+ .long sys_getgid /* will be unused */
+ .long sys_ni_syscall /* signal syscall holder */
+ .long sys_ni_syscall /* geteuid16 syscall holder */
+ .long sys_ni_syscall /* 50 - getegid16 syscall holder */
.long sys_acct
.long sys_umount /* recycled never used phys() */
.long sys_ni_syscall /* old lock syscall holder */
.long sys_ioctl
- .long sys_fcntl /* 55 */
- .long sys_ni_syscall /* old mpx syscall holder */
+ .long sys_fcntl /* 55 - will be unused */
+ .long sys_ni_syscall /* mpx syscall holder */
.long sys_setpgid
.long sys_ni_syscall /* old ulimit syscall holder */
.long sys_ni_syscall /* sys_olduname */
@@ -776,41 +776,41 @@ ENTRY(sys_call_table)
.long sys_getppid
.long sys_getpgrp /* 65 */
.long sys_setsid
- .long sys_sigaction
- .long sys_sgetmask
- .long sys_ssetmask
- .long sys_setreuid /* 70 */
- .long sys_setregid
- .long sys_sigsuspend
- .long sys_sigpending
+ .long sys_ni_syscall /* sigaction syscall holder */
+ .long sys_ni_syscall /* sgetmask syscall holder */
+ .long sys_ni_syscall /* ssetmask syscall holder */
+ .long sys_ni_syscall /* 70 - setreuid16 syscall holder */
+ .long sys_ni_syscall /* setregid16 syscall holder */
+ .long sys_ni_syscall /* sigsuspend syscall holder */
+ .long sys_ni_syscall /* sigpending syscall holder */
.long sys_sethostname
.long sys_setrlimit /* 75 */
- .long sys_getrlimit
+ .long sys_getrlimit/*will be unused*/
.long sys_getrusage
.long sys_gettimeofday
.long sys_settimeofday
- .long sys_getgroups /* 80 */
- .long sys_setgroups
+ .long sys_ni_syscall /* 80 - getgroups16 syscall holder */
+ .long sys_ni_syscall /* setgroups16 syscall holder */
.long sys_ni_syscall /* sys_oldselect */
.long sys_symlink
- .long sys_lstat
+ .long sys_ni_syscall /* old lstat syscall holder */
.long sys_readlink /* 85 */
.long sys_uselib
.long sys_swapon
.long sys_reboot
- .long old_readdir
+ .long sys_ni_syscall /* readdir syscall holder */
.long sys_ni_syscall /* 90 - old_mmap syscall holder */
.long sys_munmap
.long sys_truncate
.long sys_ftruncate
.long sys_fchmod
- .long sys_fchown /* 95 */
+ .long sys_ni_syscall /* 95 - fchwon16 syscall holder */
.long sys_getpriority
.long sys_setpriority
.long sys_ni_syscall /* old profil syscall holder */
.long sys_statfs
.long sys_fstatfs /* 100 */
- .long sys_ni_syscall /* ioperm */
+ .long sys_ni_syscall /* ioperm syscall holder */
.long sys_socketcall
.long sys_syslog
.long sys_setitimer
@@ -818,37 +818,37 @@ ENTRY(sys_call_table)
.long sys_newstat
.long sys_newlstat
.long sys_newfstat
- .long sys_uname
- .long sys_ni_syscall /* 110 - iopl */
+ .long sys_ni_syscall /* old uname syscall holder */
+ .long sys_ni_syscall /* 110 - iopl syscall holder */
.long sys_vhangup
- .long sys_ni_syscall /* for idle */
- .long sys_ni_syscall /* for vm86old */
+ .long sys_ni_syscall /* idle syscall holder */
+ .long sys_ni_syscall /* vm86old syscall holder */
.long sys_wait4
.long sys_swapoff /* 115 */
.long sys_sysinfo
.long sys_ipc
.long sys_fsync
- .long sys_sigreturn
+ .long sys_ni_syscall /* sigreturn syscall holder */
.long sys_clone /* 120 */
.long sys_setdomainname
.long sys_newuname
- .long sys_ni_syscall /* sys_modify_ldt */
+ .long sys_ni_syscall /* modify_ldt syscall holder */
.long sys_adjtimex
.long sys_mprotect /* 125 */
- .long sys_sigprocmask
- .long sys_ni_syscall /* sys_create_module */
+ .long sys_ni_syscall /* sigprocmask syscall holder */
+ .long sys_ni_syscall /* create_module syscall holder */
.long sys_init_module
.long sys_delete_module
- .long sys_ni_syscall /* 130 sys_get_kernel_syms */
+ .long sys_ni_syscall /* 130 - get_kernel_syms */
.long sys_quotactl
.long sys_getpgid
.long sys_fchdir
.long sys_bdflush
.long sys_sysfs /* 135 */
.long sys_personality
- .long sys_ni_syscall /* for afs_syscall */
- .long sys_setfsuid
- .long sys_setfsgid
+ .long sys_ni_syscall /* afs_syscall syscall holder */
+ .long sys_ni_syscall /* setfsuid16 syscall holder */
+ .long sys_ni_syscall /* setfsgid16 syscall holder */
.long sys_llseek /* 140 */
.long sys_getdents
.long sys_select
@@ -873,10 +873,10 @@ ENTRY(sys_call_table)
.long sys_sched_rr_get_interval
.long sys_nanosleep
.long sys_mremap
- .long sys_setresuid
- .long sys_getresuid /* 165 */
- .long sys_tas /* vm86 */
- .long sys_ni_syscall /* sys_query_module */
+ .long sys_ni_syscall /* setresuid16 syscall holder */
+ .long sys_ni_syscall /* 165 - getresuid16 syscall holder */
+ .long sys_tas /* vm86 syscall holder */
+ .long sys_ni_syscall /* query_module syscall holder */
.long sys_poll
.long sys_nfsservctl
.long sys_setresgid /* 170 */
@@ -891,7 +891,7 @@ ENTRY(sys_call_table)
.long sys_rt_sigsuspend
.long sys_pread64 /* 180 */
.long sys_pwrite64
- .long sys_chown
+ .long sys_ni_syscall /* chown16 syscall holder */
.long sys_getcwd
.long sys_capget
.long sys_capset /* 185 */
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index cbfa6748e4ab..d1f782517ad5 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -33,32 +33,6 @@
int do_signal(struct pt_regs *, sigset_t *);
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage int
-sys_sigsuspend(old_sigset_t mask, unsigned long r1,
- unsigned long r2, unsigned long r3, unsigned long r4,
- unsigned long r5, unsigned long r6, struct pt_regs regs)
-{
- sigset_t saveset;
-
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- regs.r0 = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(&regs, &saveset))
- return regs.r0;
- }
-}
-
asmlinkage int
sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
unsigned long r2, unsigned long r3, unsigned long r4,
@@ -90,38 +64,6 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
}
asmlinkage int
-sys_sigaction(int sig, const struct old_sigaction __user *act,
- struct old_sigaction __user *oact)
-{
- struct k_sigaction new_ka, old_ka;
- int ret;
-
- if (act) {
- old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
- return -EFAULT;
- __get_user(new_ka.sa.sa_flags, &act->sa_flags);
- __get_user(mask, &act->sa_mask);
- siginitset(&new_ka.sa.sa_mask, mask);
- }
-
- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
- if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
- return -EFAULT;
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
- }
-
- return ret;
-}
-
-asmlinkage int
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
unsigned long r2, unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, struct pt_regs regs)
@@ -134,26 +76,14 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
* Do a signal return; undo the signal stack.
*/
-struct sigframe
-{
-// char *pretcode;
- int sig;
- struct sigcontext sc;
-// struct _fpstate fpstate;
- unsigned long extramask[_NSIG_WORDS-1];
- char retcode[4];
-};
-
struct rt_sigframe
{
-// char *pretcode;
int sig;
struct siginfo *pinfo;
void *puc;
struct siginfo info;
struct ucontext uc;
// struct _fpstate fpstate;
- char retcode[8];
};
static int
@@ -208,38 +138,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
}
asmlinkage int
-sys_sigreturn(unsigned long r0, unsigned long r1,
- unsigned long r2, unsigned long r3, unsigned long r4,
- unsigned long r5, unsigned long r6, struct pt_regs regs)
-{
- struct sigframe __user *frame = (struct sigframe __user *)regs.spu;
- sigset_t set;
- int result;
-
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
- if (__get_user(set.sig[0], &frame->sc.oldmask)
- || (_NSIG_WORDS > 1
- && __copy_from_user(&set.sig[1], &frame->extramask,
- sizeof(frame->extramask))))
- goto badframe;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- if (restore_sigcontext(&regs, &frame->sc, &result))
- goto badframe;
- return result;
-
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
-
-asmlinkage int
sys_rt_sigreturn(unsigned long r0, unsigned long r1,
unsigned long r2, unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, struct pt_regs regs)
@@ -342,71 +240,6 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
return (void __user *)((sp - frame_size) & -8ul);
}
-static void setup_frame(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs *regs)
-{
- struct sigframe __user *frame;
- int err = 0;
- int signal;
-
- frame = get_sigframe(ka, regs->spu, sizeof(*frame));
-
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
-
- signal = current_thread_info()->exec_domain
- && current_thread_info()->exec_domain->signal_invmap
- && sig < 32
- ? current_thread_info()->exec_domain->signal_invmap[sig]
- : sig;
-
- err |= __put_user(signal, &frame->sig);
- if (err)
- goto give_sigsegv;
-
- err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
- if (err)
- goto give_sigsegv;
-
- if (_NSIG_WORDS > 1) {
- err |= __copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
- if (err)
- goto give_sigsegv;
- }
-
- if (ka->sa.sa_flags & SA_RESTORER)
- regs->lr = (unsigned long)ka->sa.sa_restorer;
- else {
- /* This is : ldi r7, #__NR_sigreturn ; trap #2 */
- unsigned long code = 0x670010f2 | (__NR_sigreturn << 16);
-
- regs->lr = (unsigned long)frame->retcode;
- err |= __put_user(code, (long __user *)(frame->retcode+0));
- if (err)
- goto give_sigsegv;
- flush_cache_sigtramp((unsigned long)frame->retcode);
- }
-
- /* Set up registers for signal handler */
- regs->spu = (unsigned long)frame;
- regs->r0 = signal; /* Arg for signal handler */
- regs->r1 = (unsigned long)&frame->sc;
- regs->bpc = (unsigned long)ka->sa.sa_handler;
-
- set_fs(USER_DS);
-
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): sp=%p pc=%p\n",
- current->comm, current->pid, frame, regs->pc);
-#endif
-
- return;
-
-give_sigsegv:
- force_sigsegv(sig, current);
-}
-
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs)
{
@@ -448,20 +281,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
goto give_sigsegv;
/* Set up to return from userspace. */
- if (ka->sa.sa_flags & SA_RESTORER)
- regs->lr = (unsigned long)ka->sa.sa_restorer;
- else {
- /* This is : ldi r7, #__NR_rt_sigreturn ; trap #2 */
- unsigned long code1 = 0x97f00000 | (__NR_rt_sigreturn);
- unsigned long code2 = 0x10f2f000;
-
- regs->lr = (unsigned long)frame->retcode;
- err |= __put_user(code1, (long __user *)(frame->retcode+0));
- err |= __put_user(code2, (long __user *)(frame->retcode+4));
- if (err)
- goto give_sigsegv;
- flush_cache_sigtramp((unsigned long)frame->retcode);
- }
+ regs->lr = (unsigned long)ka->sa.sa_restorer;
/* Set up registers for signal handler */
regs->spu = (unsigned long)frame;
@@ -519,10 +339,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
}
/* Set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(sig, ka, info, oldset, regs);
- else
- setup_frame(sig, ka, oldset, regs);
+ setup_rt_frame(sig, ka, info, oldset, regs);
if (!(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&current->sighand->siglock);
diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c
index 736c8d86f64b..ec968e453f79 100644
--- a/arch/m32r/mm/init.c
+++ b/arch/m32r/mm/init.c
@@ -9,8 +9,6 @@
* Copyright (C) 1995 Linus Torvalds
*/
-/* $Id$ */
-
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -19,6 +17,7 @@
#include <linux/swap.h>
#include <linux/highmem.h>
#include <linux/bitops.h>
+#include <linux/nodemask.h>
#include <asm/types.h>
#include <asm/processor.h>
#include <asm/page.h>
diff --git a/arch/m68k/apollo/dn_debug.c b/arch/m68k/apollo/dn_debug.c
deleted file mode 100644
index b106969bd8fe..000000000000
--- a/arch/m68k/apollo/dn_debug.c
+++ /dev/null
@@ -1,22 +0,0 @@
-
-#define DN_DEBUG_BUFFER_BASE 0x82800000
-#define DN_DEBUG_BUFFER_SIZE 8*1024*1024
-
-static char *current_dbg_ptr=DN_DEBUG_BUFFER_BASE;
-
-int dn_deb_printf(const char *fmt, ...) {
-
- va_list args;
- int i;
-
- if(current_dbg_ptr<(DN_DEBUG_BUFFER_BASE + DN_DEBUG_BUFFER_SIZE)) {
- va_start(args,fmt);
- i=vsprintf(current_dbg_ptr,fmt,args);
- va_end(args);
- current_dbg_ptr+=i;
-
- return i;
- }
- else
- return 0;
-}
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index 714483fe7182..c1b23336450b 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc3-m68k
-# Sun Dec 5 14:21:25 2004
+# Linux kernel version: 2.6.10-m68k
+# Sun Dec 26 11:22:54 2004
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -731,6 +731,11 @@ CONFIG_DMASOUND=m
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# Character devices
#
CONFIG_AMIGA_BUILTIN_SERIAL=y
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index 15e0b04c8dcc..648361b544c0 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc3-m68k
-# Sun Dec 5 14:21:29 2004
+# Linux kernel version: 2.6.10-m68k
+# Sun Dec 26 11:22:58 2004
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -590,6 +590,11 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# Character devices
#
CONFIG_DN_SERIAL=y
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 85e7e376fdb5..1fb25c0b3e95 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc3-m68k
-# Sun Dec 5 14:21:34 2004
+# Linux kernel version: 2.6.10-m68k
+# Sun Dec 26 11:23:11 2004
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -643,6 +643,11 @@ CONFIG_DMASOUND=m
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# Character devices
#
CONFIG_ATARI_MFPSER=m
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index d6afed384004..f1f2cf027100 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc3-m68k
-# Sun Dec 5 14:21:38 2004
+# Linux kernel version: 2.6.10-m68k
+# Sun Dec 26 11:23:15 2004
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -589,6 +589,11 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# Character devices
#
CONFIG_BVME6000_SCC=y
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index d9a8765e5529..53dde43ddfcb 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc3-m68k
-# Sun Dec 5 14:21:44 2004
+# Linux kernel version: 2.6.10-m68k
+# Sun Dec 26 11:23:40 2004
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -591,6 +591,11 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# Character devices
#
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 6c3cac1404a1..2452dac8db9d 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc3-m68k
-# Sun Dec 5 14:21:47 2004
+# Linux kernel version: 2.6.10-m68k
+# Sun Dec 26 11:23:44 2004
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -652,6 +652,11 @@ CONFIG_LOGO_MAC_CLUT224=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# Character devices
#
CONFIG_MAC_SCC=y
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index c70eabba17c5..ea38e87a6051 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc3-m68k
-# Sun Dec 5 14:21:49 2004
+# Linux kernel version: 2.6.10-m68k
+# Sun Dec 26 11:23:49 2004
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -606,6 +606,11 @@ CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# Character devices
#
CONFIG_MVME147_SCC=y
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index 34d31cc5147b..f931a64939d6 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc3-m68k
-# Sun Dec 5 14:21:52 2004
+# Linux kernel version: 2.6.10-m68k
+# Sun Dec 26 11:23:53 2004
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -605,6 +605,11 @@ CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# Character devices
#
CONFIG_MVME162_SCC=y
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index a83e649fa9ce..713020cd6f2e 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc3-m68k
-# Sun Dec 5 14:21:55 2004
+# Linux kernel version: 2.6.10-m68k
+# Sun Dec 26 11:23:57 2004
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -682,6 +682,11 @@ CONFIG_DMASOUND=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# Character devices
#
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index df64a87a415e..783d00cbb707 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc3-m68k
-# Sun Dec 5 14:21:58 2004
+# Linux kernel version: 2.6.10-m68k
+# Sun Dec 26 11:24:01 2004
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -595,6 +595,11 @@ CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# Character devices
#
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index d21a7ae0bf77..c25f91347893 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc3-m68k
-# Sun Dec 5 14:22:01 2004
+# Linux kernel version: 2.6.10-m68k
+# Sun Dec 26 11:24:05 2004
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -605,6 +605,11 @@ CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# Character devices
#
diff --git a/arch/m68k/defconfig b/arch/m68k/defconfig
index 89628d8d9c93..78f57d398340 100644
--- a/arch/m68k/defconfig
+++ b/arch/m68k/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc3-m68k
-# Sun Dec 5 14:21:41 2004
+# Linux kernel version: 2.6.10-m68k
+# Sun Dec 26 11:23:36 2004
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -462,6 +462,11 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# Character devices
#
CONFIG_AMIGA_BUILTIN_SERIAL=y
diff --git a/arch/m68k/sun3x/sun3x_ksyms.c b/arch/m68k/sun3x/sun3x_ksyms.c
deleted file mode 100644
index 43e5a9af8abd..000000000000
--- a/arch/m68k/sun3x/sun3x_ksyms.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/dvma.h>
-#include <asm/idprom.h>
-
-/*
- * Add things here when you find the need for it.
- */
-EXPORT_SYMBOL(dvma_map_align);
-EXPORT_SYMBOL(dvma_unmap);
-EXPORT_SYMBOL(dvma_malloc_align);
-EXPORT_SYMBOL(dvma_free);
-EXPORT_SYMBOL(idprom);
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index aee1f399e15b..43c254299e4a 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -127,7 +127,9 @@ static void set_brk(unsigned long start, unsigned long end)
end = PAGE_ALIGN(end);
if (end <= start)
return;
+ down_write(&current->mm->mmap_sem);
do_brk(start, end - start);
+ up_write(&current->mm->mmap_sem);
}
@@ -375,7 +377,9 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
/* Map the last of the bss segment */
if (last_bss > len) {
+ down_write(&current->mm->mmap_sem);
do_brk(len, (last_bss - len));
+ up_write(&current->mm->mmap_sem);
}
kfree(elf_phdata);
@@ -562,7 +566,9 @@ void irix_map_prda_page (void)
unsigned long v;
struct prda *pp;
+ down_write(&current->mm->mmap_sem);
v = do_brk (PRDA_ADDRESS, PAGE_SIZE);
+ up_write(&current->mm->mmap_sem);
if (v < 0)
return;
@@ -852,8 +858,11 @@ static int load_irix_library(struct file *file)
len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
- if (bss > len)
+ if (bss > len) {
+ down_write(&current->mm->mmap_sem);
do_brk(len, bss-len);
+ up_write(&current->mm->mmap_sem);
+ }
kfree(elf_phdata);
return 0;
}
diff --git a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c
index 3613999a189a..d14dae150b8a 100644
--- a/arch/mips/vr41xx/common/bcu.c
+++ b/arch/mips/vr41xx/common/bcu.c
@@ -30,6 +30,7 @@
*/
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/types.h>
diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c
index 3e1079dfb6c1..c5f1043de938 100644
--- a/arch/mips/vr41xx/common/pmu.c
+++ b/arch/mips/vr41xx/common/pmu.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/types.h>
diff --git a/arch/parisc/kernel/binfmt_elf32.c b/arch/parisc/kernel/binfmt_elf32.c
index 4486a745b0ef..6fd07e90aad7 100644
--- a/arch/parisc/kernel/binfmt_elf32.c
+++ b/arch/parisc/kernel/binfmt_elf32.c
@@ -92,10 +92,12 @@ struct elf_prpsinfo32
current->thread.map_base = DEFAULT_MAP_BASE32; \
current->thread.task_size = DEFAULT_TASK_SIZE32 \
-#define jiffies_to_timeval jiffies_to_compat_timeval
+#undef cputime_to_timeval
+#define cputime_to_timeval cputime_to_compat_timeval
static __inline__ void
-jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
+cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
{
+ unsigned long jiffies = cputime_to_jiffies(cputime);
value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
value->tv_sec = jiffies / HZ;
}
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index 53547b6de45b..ddad50b01298 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -41,14 +41,17 @@ void default_idle(void)
if (!need_resched()) {
if (powersave != NULL)
powersave();
-#ifdef CONFIG_SMP
else {
+#ifdef CONFIG_SMP
set_thread_flag(TIF_POLLING_NRFLAG);
+ local_irq_enable();
while (!need_resched())
barrier();
clear_thread_flag(TIF_POLLING_NRFLAG);
- }
+#else
+ local_irq_enable();
#endif
+ }
}
if (need_resched())
schedule();
diff --git a/arch/ppc/kernel/perfmon.c b/arch/ppc/kernel/perfmon.c
index 88452272cc93..cbb29e6f4902 100644
--- a/arch/ppc/kernel/perfmon.c
+++ b/arch/ppc/kernel/perfmon.c
@@ -47,7 +47,6 @@ static void dummy_perf(struct pt_regs *regs)
#else
/* Ensure exceptions are disabled */
-#define MMCR0_PMXE (1UL << (31 - 5))
static void dummy_perf(struct pt_regs *regs)
{
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index e69bc4e94297..6e31db0fe4b4 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -31,6 +31,7 @@
#include <linux/bootmem.h>
#include <linux/highmem.h>
#include <linux/initrd.h>
+#include <linux/pagemap.h>
#include <asm/pgalloc.h>
#include <asm/prom.h>
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index 0bc438f7edca..b4dd00342397 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -231,6 +231,17 @@ config PREEMPT
Say Y here if you are building a kernel for a desktop, embedded
or real-time system. Say N if you are unsure.
+config PREEMPT_BKL
+ bool "Preempt The Big Kernel Lock"
+ depends on PREEMPT
+ default y
+ help
+ This option reduces the latency of the kernel by making the
+ big kernel lock preemptible.
+
+ Say Y here if you are building a kernel for a desktop system.
+ Say N if you are unsure.
+
#
# Use the generic interrupt handling code in kernel/irq/:
#
diff --git a/arch/ppc64/kernel/binfmt_elf32.c b/arch/ppc64/kernel/binfmt_elf32.c
index 478e5fce6be1..fadc699a0497 100644
--- a/arch/ppc64/kernel/binfmt_elf32.c
+++ b/arch/ppc64/kernel/binfmt_elf32.c
@@ -60,10 +60,12 @@ struct elf_prpsinfo32
#include <linux/time.h>
-#define jiffies_to_timeval jiffies_to_compat_timeval
+#undef cputime_to_timeval
+#define cputime_to_timeval cputime_to_compat_timeval
static __inline__ void
-jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
+cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
{
+ unsigned long jiffies = cputime_to_jiffies(cputime);
value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
value->tv_sec = jiffies / HZ;
}
diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
index b3b7da3a4c92..5a879757da6f 100644
--- a/arch/ppc64/kernel/entry.S
+++ b/arch/ppc64/kernel/entry.S
@@ -574,25 +574,22 @@ do_work:
crandc eq,cr1*4+eq,eq
bne restore
/* here we are preempting the current task */
-1: lis r0,PREEMPT_ACTIVE@h
- stw r0,TI_PREEMPT(r9)
+1:
#ifdef CONFIG_PPC_ISERIES
li r0,1
stb r0,PACAPROCENABLED(r13)
#endif
ori r10,r10,MSR_EE
mtmsrd r10,1 /* reenable interrupts */
- bl .schedule
+ bl .preempt_schedule
mfmsr r10
clrrdi r9,r1,THREAD_SHIFT
rldicl r10,r10,48,1 /* disable interrupts again */
- li r0,0
rotldi r10,r10,16
mtmsrd r10,1
ld r4,TI_FLAGS(r9)
andi. r0,r4,_TIF_NEED_RESCHED
bne 1b
- stw r0,TI_PREEMPT(r9)
b restore
user_work:
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index f136d3d8a947..677f6272fc29 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -99,6 +99,7 @@ static inline int kprobe_handler(struct pt_regs *regs)
p = get_kprobe(addr);
if (!p) {
unlock_kprobes();
+#if 0
if (*addr != BREAKPOINT_INSTRUCTION) {
/*
* The breakpoint instruction was removed right
@@ -109,6 +110,7 @@ static inline int kprobe_handler(struct pt_regs *regs)
*/
ret = 1;
}
+#endif
/* Not one of ours: let kernel handle it */
goto no_kprobe;
}
diff --git a/arch/ppc64/kernel/maple_pci.c b/arch/ppc64/kernel/maple_pci.c
index f8cd5b495d6b..53993999b265 100644
--- a/arch/ppc64/kernel/maple_pci.c
+++ b/arch/ppc64/kernel/maple_pci.c
@@ -382,9 +382,6 @@ void __init maple_pcibios_fixup(void)
/* Do the mapping of the IO space */
phbs_remap_io();
- /* Fixup the pci_bus sysdata pointers */
- pci_fix_bus_sysdata();
-
DBG(" <- maple_pcibios_fixup\n");
}
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index a795ae320b37..1502b814a558 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -167,27 +167,7 @@ _GLOBAL(call_with_mmu_off)
xori r0,r0,MSR_IR|MSR_DR
mtspr SPRN_SRR1,r0
rfid
-
-/*
- * Flush instruction cache.
- */
-_GLOBAL(flush_instruction_cache)
-/*
- * This is called by kgdb code
- * and should probably go away
- * to be replaced by invalidating
- * the cache lines that are actually
- * modified
- */
- /* use invalidate-all bit in HID0
- * - is this consistent across all 64-bit cpus? -- paulus */
- mfspr r3,HID0
- ori r3,r3,HID0_ICFI
- mtspr HID0,r3
- sync
- isync
- blr
.section ".toc","aw"
PPC64_CACHES:
diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c
index 3d625552739f..08d8262dbca0 100644
--- a/arch/ppc64/kernel/pSeries_iommu.c
+++ b/arch/ppc64/kernel/pSeries_iommu.c
@@ -293,10 +293,6 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb,
struct iommu_table *tbl,
unsigned int *dma_window)
{
- if (!dma_window)
- panic("iommu_table_setparms_lpar: device %s has no"
- " ibm,dma-window property!\n", dn->full_name);
-
tbl->it_busno = dn->bussubno;
/* TODO: Parse field size properties properly. */
@@ -385,7 +381,10 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
break;
}
- WARN_ON(dma_window == NULL);
+ if (dma_window == NULL) {
+ DBG("iommu_bus_setup_pSeriesLP: bus %s seems to have no ibm,dma-window property\n", dn->full_name);
+ return;
+ }
if (!pdn->iommu_table) {
/* Bussubno hasn't been copied yet.
@@ -420,10 +419,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev)
while (dn && dn->iommu_table == NULL)
dn = dn->parent;
- WARN_ON(!dn);
-
- if (dn)
+ if (dn) {
mydn->iommu_table = dn->iommu_table;
+ } else {
+ DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, dev->pretty_name);
+ }
}
static void iommu_bus_setup_null(struct pci_bus *b) { }
diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c
index 2b9a00951f20..8953e94889ba 100644
--- a/arch/ppc64/kernel/pSeries_pci.c
+++ b/arch/ppc64/kernel/pSeries_pci.c
@@ -552,7 +552,6 @@ void __init pSeries_final_fixup(void)
phbs_remap_io();
pSeries_request_regions();
- pci_fix_bus_sysdata();
pci_addr_cache_build();
}
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index d03c47164001..f8f2007b8885 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -19,9 +19,7 @@
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/spinlock.h>
@@ -40,7 +38,6 @@
#include <asm/smp.h>
#include <asm/paca.h>
#include <asm/time.h>
-#include <asm/ppcdebug.h>
#include <asm/machdep.h>
#include <asm/xics.h>
#include <asm/cputable.h>
@@ -87,11 +84,8 @@ static int query_cpu_stopped(unsigned int pcpu)
#ifdef CONFIG_HOTPLUG_CPU
-int __cpu_disable(void)
+int pSeries_cpu_disable(void)
{
- /* FIXME: go put this in a header somewhere */
- extern void xics_migrate_irqs_away(void);
-
systemcfg->processorCount--;
/*fix boot_cpuid here*/
@@ -103,7 +97,7 @@ int __cpu_disable(void)
return 0;
}
-void __cpu_die(unsigned int cpu)
+void pSeries_cpu_die(unsigned int cpu)
{
int tries;
int cpu_status;
@@ -250,8 +244,6 @@ static void smp_xics_message_pass(int target, int msg)
}
}
-extern void xics_request_IPIs(void);
-
static int __init smp_xics_probe(void)
{
xics_request_IPIs();
@@ -263,6 +255,19 @@ static void __devinit smp_xics_setup_cpu(int cpu)
{
if (cpu != boot_cpuid)
xics_setup_cpu();
+
+ if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
+ vpa_init(cpu);
+
+#ifdef CONFIG_IRQ_ALL_CPUS
+ /*
+ * Put the calling processor into the GIQ. This is really only
+ * necessary from a secondary thread as the OF start-cpu interface
+ * performs this function for us on primary threads.
+ */
+ rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+ (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
+#endif
}
static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
@@ -290,26 +295,7 @@ static void __devinit pSeries_take_timebase(void)
spin_unlock(&timebase_lock);
}
-static void __devinit pSeries_late_setup_cpu(int cpu)
-{
- extern unsigned int default_distrib_server;
-
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
- vpa_init(cpu);
- }
-
-#ifdef CONFIG_IRQ_ALL_CPUS
- /* Put the calling processor into the GIQ. This is really only
- * necessary from a secondary thread as the OF start-cpu interface
- * performs this function for us on primary threads.
- */
- /* TODO: 9005 is #defined in rtas-proc.c -- move to a header */
- rtas_set_indicator(9005, default_distrib_server, 1);
-#endif
-}
-
-
-void __devinit smp_pSeries_kick_cpu(int nr)
+static void __devinit smp_pSeries_kick_cpu(int nr)
{
BUG_ON(nr < 0 || nr >= NR_CPUS);
@@ -329,7 +315,6 @@ static struct smp_ops_t pSeries_mpic_smp_ops = {
.probe = smp_mpic_probe,
.kick_cpu = smp_pSeries_kick_cpu,
.setup_cpu = smp_mpic_setup_cpu,
- .late_setup_cpu = pSeries_late_setup_cpu,
};
static struct smp_ops_t pSeries_xics_smp_ops = {
@@ -337,7 +322,6 @@ static struct smp_ops_t pSeries_xics_smp_ops = {
.probe = smp_xics_probe,
.kick_cpu = smp_pSeries_kick_cpu,
.setup_cpu = smp_xics_setup_cpu,
- .late_setup_cpu = pSeries_late_setup_cpu,
};
/* This is called very early */
@@ -352,6 +336,11 @@ void __init smp_init_pSeries(void)
else
smp_ops = &pSeries_xics_smp_ops;
+#ifdef CONFIG_HOTPLUG_CPU
+ smp_ops->cpu_disable = pSeries_cpu_disable;
+ smp_ops->cpu_die = pSeries_cpu_die;
+#endif
+
/* Start secondary threads on SMT systems; primary threads
* are already in the running state.
*/
@@ -367,9 +356,6 @@ void __init smp_init_pSeries(void)
}
}
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
- vpa_init(boot_cpuid);
-
/* Non-lpar has additional take/give timebase */
if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
smp_ops->give_timebase = pSeries_give_timebase;
diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c
index 206c52d8ca66..0b18d17b94d4 100644
--- a/arch/ppc64/kernel/pacaData.c
+++ b/arch/ppc64/kernel/pacaData.c
@@ -78,13 +78,16 @@ struct paca_struct paca[] = {
#else
PACAINITDATA( 0, 1, NULL, STAB0_PHYS_ADDR, STAB0_VIRT_ADDR),
#endif
+#if NR_CPUS > 1
PACAINITDATA( 1, 0, NULL, 0, 0),
PACAINITDATA( 2, 0, NULL, 0, 0),
PACAINITDATA( 3, 0, NULL, 0, 0),
+#if NR_CPUS > 4
PACAINITDATA( 4, 0, NULL, 0, 0),
PACAINITDATA( 5, 0, NULL, 0, 0),
PACAINITDATA( 6, 0, NULL, 0, 0),
PACAINITDATA( 7, 0, NULL, 0, 0),
+#if NR_CPUS > 8
PACAINITDATA( 8, 0, NULL, 0, 0),
PACAINITDATA( 9, 0, NULL, 0, 0),
PACAINITDATA(10, 0, NULL, 0, 0),
@@ -209,4 +212,7 @@ struct paca_struct paca[] = {
PACAINITDATA(127, 0, NULL, 0, 0),
#endif
#endif
+#endif
+#endif
+#endif
};
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index 25822272542e..a7bf62655601 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -91,7 +91,7 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region
struct resource *res)
{
unsigned long offset = 0;
- struct pci_controller *hose = PCI_GET_PHB_PTR(dev);
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
if (!hose)
return;
@@ -127,7 +127,7 @@ void pcibios_align_resource(void *data, struct resource *res,
unsigned long size, unsigned long align)
{
struct pci_dev *dev = data;
- struct pci_controller *hose = PCI_GET_PHB_PTR(dev);
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
unsigned long start = res->start;
unsigned long alignto;
@@ -292,7 +292,7 @@ int pci_domain_nr(struct pci_bus *bus)
#ifdef CONFIG_PPC_ISERIES
return 0;
#else
- struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
+ struct pci_controller *hose = pci_bus_to_host(bus);
return hose->global_number;
#endif
@@ -304,7 +304,7 @@ EXPORT_SYMBOL(pci_domain_nr);
int pci_name_bus(char *name, struct pci_bus *bus)
{
#ifndef CONFIG_PPC_ISERIES
- struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
+ struct pci_controller *hose = pci_bus_to_host(bus);
if (hose->buid)
sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
@@ -336,7 +336,7 @@ static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev,
struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
{
- struct pci_controller *hose = PCI_GET_PHB_PTR(dev);
+ struct pci_controller *hose = pci_bus_to_host(dev->bus);
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long io_offset = 0;
int i, res_bit;
@@ -643,7 +643,7 @@ void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose)
static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys,
unsigned long *start_virt, unsigned long *size)
{
- struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
+ struct pci_controller *hose = pci_bus_to_host(bus);
struct pci_bus_region region;
struct resource *res;
@@ -728,23 +728,6 @@ void phbs_remap_io(void)
remap_bus_range(hose->bus);
}
-
-/*
- * This function finds the PHB that matching device_node in the
- * OpenFirmware by scanning all the pci_controllers.
- */
-struct pci_controller* pci_find_hose_for_OF_device(struct device_node *node)
-{
- while (node) {
- struct pci_controller *hose, *tmp;
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
- if (hose->arch_data == node)
- return hose;
- node=node->parent;
- }
- return NULL;
-}
-
/*
* ppc64 can have multifunction devices that do not respond to function 0.
* In this case we must scan all functions.
@@ -778,7 +761,7 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
struct pci_bus *bus)
{
/* Update device resources. */
- struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
+ struct pci_controller *hose = pci_bus_to_host(bus);
int i;
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
@@ -814,7 +797,7 @@ EXPORT_SYMBOL(pcibios_fixup_device_resources);
void __devinit pcibios_fixup_bus(struct pci_bus *bus)
{
- struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
+ struct pci_controller *hose = pci_bus_to_host(bus);
struct pci_dev *dev = bus->self;
struct resource *res;
int i;
diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
index 2ed6b674bbca..28517c14015b 100644
--- a/arch/ppc64/kernel/pci.h
+++ b/arch/ppc64/kernel/pci.h
@@ -17,7 +17,6 @@ extern unsigned long isa_io_base;
extern void pci_setup_pci_controller(struct pci_controller *hose);
extern void pci_setup_phb_io(struct pci_controller *hose, int primary);
-extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node);
extern void pci_setup_phb_io_dynamic(struct pci_controller *hose);
@@ -36,11 +35,8 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
void pci_devs_phb_init(void);
void pci_devs_phb_init_dynamic(struct pci_controller *phb);
-void pci_fix_bus_sysdata(void);
struct device_node *fetch_dev_dn(struct pci_dev *dev);
-#define PCI_GET_PHB_PTR(dev) (((struct device_node *)(dev)->sysdata)->phb)
-
/* PCI address cache management routines */
void pci_addr_cache_insert_device(struct pci_dev *dev);
void pci_addr_cache_remove_device(struct pci_dev *dev);
diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c
index 962394708ece..280b744fe64e 100644
--- a/arch/ppc64/kernel/pci_dn.c
+++ b/arch/ppc64/kernel/pci_dn.c
@@ -21,19 +21,12 @@
*/
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/delay.h>
#include <linux/string.h>
#include <linux/init.h>
-#include <linux/bootmem.h>
#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
#include <asm/prom.h>
-#include <asm/machdep.h>
#include <asm/pci-bridge.h>
-#include <asm/ppcdebug.h>
-#include <asm/iommu.h>
#include "pci.h"
@@ -178,29 +171,3 @@ void __init pci_devs_phb_init(void)
list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
pci_devs_phb_init_dynamic(phb);
}
-
-
-static void __init pci_fixup_bus_sysdata_list(struct list_head *bus_list)
-{
- struct pci_bus *bus;
-
- list_for_each_entry(bus, bus_list, node) {
- if (bus->self)
- bus->sysdata = bus->self->sysdata;
- pci_fixup_bus_sysdata_list(&bus->children);
- }
-}
-
-/*
- * Fixup the bus->sysdata ptrs to point to the bus' device_node.
- * This is done late in pcibios_init(). We do this mostly for
- * sanity, but pci_dma.c uses these at DMA time so they must be
- * correct.
- * To do this we recurse down the bus hierarchy. Note that PHB's
- * have bus->self == NULL, but fortunately bus->sysdata is already
- * correct in this case.
- */
-void __init pci_fix_bus_sysdata(void)
-{
- pci_fixup_bus_sysdata_list(&pci_root_buses);
-}
diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c
index 32634216ad78..00a831df6d9f 100644
--- a/arch/ppc64/kernel/pmac_pci.c
+++ b/arch/ppc64/kernel/pmac_pci.c
@@ -664,8 +664,6 @@ void __init pmac_pcibios_fixup(void)
for_each_pci_dev(dev)
pci_read_irq_line(dev);
-
- pci_fix_bus_sysdata();
}
static void __init pmac_fixup_phb_resources(void)
diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c
index 7efdaabf5b7b..38c0398d823c 100644
--- a/arch/ppc64/kernel/ppc_ksyms.c
+++ b/arch/ppc64/kernel/ppc_ksyms.c
@@ -114,7 +114,6 @@ EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(flush_instruction_cache);
EXPORT_SYMBOL(giveup_fpu);
#ifdef CONFIG_ALTIVEC
EXPORT_SYMBOL(giveup_altivec);
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
index e647e7bc95c1..d90a50e45669 100644
--- a/arch/ppc64/kernel/process.c
+++ b/arch/ppc64/kernel/process.c
@@ -214,23 +214,57 @@ struct task_struct *__switch_to(struct task_struct *prev,
return last;
}
+static int instructions_to_print = 16;
+
+static void show_instructions(struct pt_regs *regs)
+{
+ int i;
+ unsigned long pc = regs->nip - (instructions_to_print * 3 / 4 *
+ sizeof(int));
+
+ printk("Instruction dump:");
+
+ for (i = 0; i < instructions_to_print; i++) {
+ int instr;
+
+ if (!(i % 8))
+ printk("\n");
+
+ if (((REGION_ID(pc) != KERNEL_REGION_ID) &&
+ (REGION_ID(pc) != VMALLOC_REGION_ID)) ||
+ __get_user(instr, (unsigned int *)pc)) {
+ printk("XXXXXXXX ");
+ } else {
+ if (regs->nip == pc)
+ printk("<%08x> ", instr);
+ else
+ printk("%08x ", instr);
+ }
+
+ pc += sizeof(int);
+ }
+
+ printk("\n");
+}
+
void show_regs(struct pt_regs * regs)
{
int i;
unsigned long trap;
- printk("NIP: %016lX XER: %016lX LR: %016lX\n",
- regs->nip, regs->xer, regs->link);
+ printk("NIP: %016lX XER: %08X LR: %016lX CTR: %016lX\n",
+ regs->nip, (unsigned int)regs->xer, regs->link, regs->ctr);
printk("REGS: %p TRAP: %04lx %s (%s)\n",
regs, regs->trap, print_tainted(), UTS_RELEASE);
- printk("MSR: %016lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ printk("MSR: %016lx EE: %01x PR: %01x FP: %01x ME: %01x "
+ "IR/DR: %01x%01x CR: %08X\n",
regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
regs->msr&MSR_IR ? 1 : 0,
- regs->msr&MSR_DR ? 1 : 0);
+ regs->msr&MSR_DR ? 1 : 0,
+ (unsigned int)regs->ccr);
trap = TRAP(regs);
- if (trap == 0x300 || trap == 0x380 || trap == 0x600)
- printk("DAR: %016lx, DSISR: %016lx\n", regs->dar, regs->dsisr);
+ printk("DAR: %016lx DSISR: %016lx\n", regs->dar, regs->dsisr);
printk("TASK: %p[%d] '%s' THREAD: %p",
current, current->pid, current->comm, current->thread_info);
@@ -257,6 +291,8 @@ void show_regs(struct pt_regs * regs)
printk("LR [%016lx] ", regs->link);
print_symbol("%s\n", regs->link);
show_stack(current, (unsigned long *)regs->gpr[1]);
+ if (!user_mode(regs))
+ show_instructions(regs);
}
void exit_thread(void)
diff --git a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c
index ed07210b9917..28b1f1521f21 100644
--- a/arch/ppc64/kernel/rtas-proc.c
+++ b/arch/ppc64/kernel/rtas-proc.c
@@ -52,7 +52,6 @@
#define IBM_VOLTAGE 0x232a /* 9002 */
#define IBM_DRCONNECTOR 0x232b /* 9003 */
#define IBM_POWERSUPPLY 0x232c /* 9004 */
-#define IBM_INTQUEUE 0x232d /* 9005 */
/* Status return values */
#define SENSOR_CRITICAL_HIGH 13
@@ -107,7 +106,6 @@
#define DR_ACTION 0x2329 /* 9001 */
#define DR_INDICATOR 0x232a /* 9002 */
/* 9003 - 9004: Vendor specific */
-#define GLOBAL_INTERRUPT_QUEUE 0x232d /* 9005 */
/* 9006 - 9999: Vendor specific */
/* other */
@@ -553,7 +551,6 @@ static void ppc_rtas_process_sensor(struct seq_file *m,
"No current flow" };
const char * ibm_drconnector[] = { "Empty", "Present", "Unusable",
"Exchange" };
- const char * ibm_intqueue[] = { "Disabled", "Enabled" };
int have_strings = 0;
int num_states = 0;
@@ -665,15 +662,6 @@ static void ppc_rtas_process_sensor(struct seq_file *m,
case IBM_POWERSUPPLY:
seq_printf(m, "Powersupply:\t");
break;
- case IBM_INTQUEUE:
- seq_printf(m, "Interrupt queue:\t");
- num_states = sizeof(ibm_intqueue) / sizeof(char *);
- if (state < num_states) {
- seq_printf(m, "%s\t",
- ibm_intqueue[state]);
- have_strings = 1;
- }
- break;
default:
seq_printf(m, "Unknown sensor (type %d), ignoring it\n",
s->token);
diff --git a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
index ade32f6a6d30..b5a96ec9f3bc 100644
--- a/arch/ppc64/kernel/rtasd.c
+++ b/arch/ppc64/kernel/rtasd.c
@@ -486,7 +486,7 @@ static int __init rtas_init(void)
/* No RTAS, only warn if we are on a pSeries box */
if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
- if (systemcfg->platform & PLATFORM_PSERIES);
+ if (systemcfg->platform & PLATFORM_PSERIES)
printk(KERN_ERR "rtasd: no event-scan on system\n");
return 1;
}
diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
index db78b2f03884..f5b4a8f29581 100644
--- a/arch/ppc64/kernel/smp.c
+++ b/arch/ppc64/kernel/smp.c
@@ -22,9 +22,7 @@
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/spinlock.h>
@@ -38,12 +36,10 @@
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <asm/io.h>
#include <asm/prom.h>
#include <asm/smp.h>
#include <asm/paca.h>
#include <asm/time.h>
-#include <asm/ppcdebug.h>
#include <asm/machdep.h>
#include <asm/cputable.h>
#include <asm/system.h>
@@ -58,7 +54,6 @@
#endif
int smp_threads_ready;
-unsigned long cache_decay_ticks;
cpumask_t cpu_possible_map = CPU_MASK_NONE;
cpumask_t cpu_online_map = CPU_MASK_NONE;
@@ -77,10 +72,6 @@ void smp_call_function_interrupt(void);
int smt_enabled_at_boot = 1;
-/* Low level assembly function used to backup CPU 0 state */
-extern void __save_cpu_setup(void);
-
-
#ifdef CONFIG_PPC_MULTIPLATFORM
void smp_mpic_message_pass(int target, int msg)
{
@@ -507,9 +498,6 @@ int __devinit start_secondary(void *unused)
if (smp_ops->take_timebase)
smp_ops->take_timebase();
- if (smp_ops->late_setup_cpu)
- smp_ops->late_setup_cpu(cpu);
-
spin_lock(&call_lock);
cpu_set(cpu, cpu_online_map);
spin_unlock(&call_lock);
@@ -551,3 +539,19 @@ void __init smp_cpus_done(unsigned int max_cpus)
*/
cpu_present_map = cpu_possible_map;
}
+
+#ifdef CONFIG_HOTPLUG_CPU
+int __cpu_disable(void)
+{
+ if (smp_ops->cpu_disable)
+ return smp_ops->cpu_disable();
+
+ return -ENOSYS;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+ if (smp_ops->cpu_die)
+ smp_ops->cpu_die(cpu);
+}
+#endif
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
index 1a6493196f2d..01b21095b76c 100644
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -142,16 +142,54 @@ static __inline__ void timer_check_rtc(void)
}
}
+/*
+ * This version of gettimeofday has microsecond resolution.
+ */
+static inline void __do_gettimeofday(struct timeval *tv, unsigned long tb_val)
+{
+ unsigned long sec, usec, tb_ticks;
+ unsigned long xsec, tb_xsec;
+ struct gettimeofday_vars * temp_varp;
+ unsigned long temp_tb_to_xs, temp_stamp_xsec;
+
+ /*
+ * These calculations are faster (gets rid of divides)
+ * if done in units of 1/2^20 rather than microseconds.
+ * The conversion to microseconds at the end is done
+ * without a divide (and in fact, without a multiply)
+ */
+ tb_ticks = tb_val - do_gtod.tb_orig_stamp;
+ temp_varp = do_gtod.varp;
+ temp_tb_to_xs = temp_varp->tb_to_xs;
+ temp_stamp_xsec = temp_varp->stamp_xsec;
+ tb_xsec = mulhdu( tb_ticks, temp_tb_to_xs );
+ xsec = temp_stamp_xsec + tb_xsec;
+ sec = xsec / XSEC_PER_SEC;
+ xsec -= sec * XSEC_PER_SEC;
+ usec = (xsec * USEC_PER_SEC)/XSEC_PER_SEC;
+
+ tv->tv_sec = sec;
+ tv->tv_usec = usec;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+ __do_gettimeofday(tv, get_tb());
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+
/* Synchronize xtime with do_gettimeofday */
-static __inline__ void timer_sync_xtime( unsigned long cur_tb )
+static inline void timer_sync_xtime(unsigned long cur_tb)
{
struct timeval my_tv;
- if ( cur_tb > next_xtime_sync_tb ) {
+ if (cur_tb > next_xtime_sync_tb) {
next_xtime_sync_tb = cur_tb + xtime_sync_interval;
- do_gettimeofday( &my_tv );
- if ( xtime.tv_sec <= my_tv.tv_sec ) {
+ __do_gettimeofday(&my_tv, cur_tb);
+
+ if (xtime.tv_sec <= my_tv.tv_sec) {
xtime.tv_sec = my_tv.tv_sec;
xtime.tv_nsec = my_tv.tv_usec * 1000;
}
@@ -274,7 +312,7 @@ int timer_interrupt(struct pt_regs * regs)
write_seqlock(&xtime_lock);
tb_last_stamp = lpaca->next_jiffy_update_tb;
do_timer(regs);
- timer_sync_xtime( cur_tb );
+ timer_sync_xtime(lpaca->next_jiffy_update_tb);
timer_check_rtc();
write_sequnlock(&xtime_lock);
if ( adjusting_time && (time_adjust == 0) )
@@ -313,36 +351,6 @@ unsigned long long sched_clock(void)
return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift;
}
-/*
- * This version of gettimeofday has microsecond resolution.
- */
-void do_gettimeofday(struct timeval *tv)
-{
- unsigned long sec, usec, tb_ticks;
- unsigned long xsec, tb_xsec;
- struct gettimeofday_vars * temp_varp;
- unsigned long temp_tb_to_xs, temp_stamp_xsec;
-
- /* These calculations are faster (gets rid of divides)
- * if done in units of 1/2^20 rather than microseconds.
- * The conversion to microseconds at the end is done
- * without a divide (and in fact, without a multiply) */
- tb_ticks = get_tb() - do_gtod.tb_orig_stamp;
- temp_varp = do_gtod.varp;
- temp_tb_to_xs = temp_varp->tb_to_xs;
- temp_stamp_xsec = temp_varp->stamp_xsec;
- tb_xsec = mulhdu( tb_ticks, temp_tb_to_xs );
- xsec = temp_stamp_xsec + tb_xsec;
- sec = xsec / XSEC_PER_SEC;
- xsec -= sec * XSEC_PER_SEC;
- usec = (xsec * USEC_PER_SEC)/XSEC_PER_SEC;
-
- tv->tv_sec = sec;
- tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
int do_settimeofday(struct timespec *tv)
{
time_t wtm_sec, new_sec = tv->tv_sec;
diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c
index 44f04fc727fd..418aff49933e 100644
--- a/arch/ppc64/kernel/traps.c
+++ b/arch/ppc64/kernel/traps.c
@@ -127,6 +127,7 @@ int die(const char *str, struct pt_regs *regs, long err)
}
if (nl)
printk("\n");
+ print_modules();
show_regs(regs);
bust_spinlocks(0);
spin_unlock_irq(&die_lock);
@@ -343,7 +344,7 @@ extern struct bug_entry __start___bug_table[], __stop___bug_table[];
#define module_find_bug(x) NULL
#endif
-static struct bug_entry *find_bug(unsigned long bugaddr)
+struct bug_entry *find_bug(unsigned long bugaddr)
{
struct bug_entry *bug;
@@ -353,7 +354,7 @@ static struct bug_entry *find_bug(unsigned long bugaddr)
return module_find_bug(bugaddr);
}
-int
+static int
check_bug_trap(struct pt_regs *regs)
{
struct bug_entry *bug;
diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
index b9fdcc60d6e8..eca025abe098 100644
--- a/arch/ppc64/kernel/xics.c
+++ b/arch/ppc64/kernel/xics.c
@@ -91,6 +91,7 @@ static int xics_irq_8259_cascade_real = 0;
static unsigned int default_server = 0xFF;
/* also referenced in smp.c... */
unsigned int default_distrib_server = 0;
+unsigned int interrupt_server_size = 8;
/*
* XICS only has a single IPI, so encode the messages per CPU
@@ -511,6 +512,10 @@ nextnode:
default_server = ireg[0];
default_distrib_server = ireg[i-1]; /* take last element */
}
+ ireg = (uint *)get_property(np,
+ "ibm,interrupt-server#-size", NULL);
+ if (ireg)
+ interrupt_server_size = *ireg;
break;
}
}
@@ -643,20 +648,16 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
/* Interrupts are disabled. */
void xics_migrate_irqs_away(void)
{
- int set_indicator = rtas_token("set-indicator");
- const unsigned int giqs = 9005UL; /* Global Interrupt Queue Server */
- int status = 0;
+ int status;
unsigned int irq, virq, cpu = smp_processor_id();
- BUG_ON(set_indicator == RTAS_UNKNOWN_SERVICE);
-
/* Reject any interrupt that was queued to us... */
ops->cppr_info(cpu, 0);
iosync();
- /* Refuse any new interrupts... */
- rtas_call(set_indicator, 3, 1, &status, giqs,
- hard_smp_processor_id(), 0);
+ /* remove ourselves from the global interrupt queue */
+ status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+ (1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
WARN_ON(status != 0);
/* Allow IPIs again... */
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
index 056db88671b4..723a3dc77db6 100644
--- a/arch/ppc64/mm/init.c
+++ b/arch/ppc64/mm/init.c
@@ -37,6 +37,7 @@
#include <linux/bootmem.h>
#include <linux/highmem.h>
#include <linux/idr.h>
+#include <linux/nodemask.h>
#include <asm/pgalloc.h>
#include <asm/page.h>
diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
index ad07e3d0d344..83d7ec3b7c10 100644
--- a/arch/ppc64/mm/numa.c
+++ b/arch/ppc64/mm/numa.c
@@ -345,8 +345,6 @@ new_range:
numa_domain = 0;
}
- node_set_online(numa_domain);
-
if (max_domain < numa_domain)
max_domain = numa_domain;
@@ -361,14 +359,19 @@ new_range:
init_node_data[numa_domain].node_start_pfn +
init_node_data[numa_domain].node_spanned_pages;
if (shouldstart != (start / PAGE_SIZE)) {
- printk(KERN_ERR "WARNING: Hole in node, "
- "disabling region start %lx "
- "length %lx\n", start, size);
- continue;
+ /* Revert to non-numa for now */
+ printk(KERN_ERR
+ "WARNING: Unexpected node layout: "
+ "region start %lx length %lx\n",
+ start, size);
+ printk(KERN_ERR "NUMA is disabled\n");
+ goto err;
}
init_node_data[numa_domain].node_spanned_pages +=
size / PAGE_SIZE;
} else {
+ node_set_online(numa_domain);
+
init_node_data[numa_domain].node_start_pfn =
start / PAGE_SIZE;
init_node_data[numa_domain].node_spanned_pages =
@@ -388,6 +391,14 @@ new_range:
node_set_online(i);
return 0;
+err:
+ /* Something has gone wrong; revert any setup we've done */
+ for_each_node(i) {
+ node_set_offline(i);
+ init_node_data[i].node_start_pfn = 0;
+ init_node_data[i].node_spanned_pages = 0;
+ }
+ return -1;
}
static void __init setup_nonnuma(void)
diff --git a/arch/ppc64/oprofile/op_model_power4.c b/arch/ppc64/oprofile/op_model_power4.c
index c0f7a151c764..b1ca798f4c29 100644
--- a/arch/ppc64/oprofile/op_model_power4.c
+++ b/arch/ppc64/oprofile/op_model_power4.c
@@ -97,7 +97,7 @@ static void power4_cpu_setup(void *unused)
mtspr(SPRN_MMCR0, mmcr0);
mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE;
- mmcr0 |= MMCR0_PMC1INTCONTROL|MMCR0_PMCNINTCONTROL;
+ mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE;
mtspr(SPRN_MMCR0, mmcr0);
mtspr(SPRN_MMCR1, mmcr1_val);
diff --git a/arch/ppc64/oprofile/op_model_rs64.c b/arch/ppc64/oprofile/op_model_rs64.c
index b34ea586440a..b3cddb7e03d0 100644
--- a/arch/ppc64/oprofile/op_model_rs64.c
+++ b/arch/ppc64/oprofile/op_model_rs64.c
@@ -119,7 +119,7 @@ static void rs64_cpu_setup(void *unused)
mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE;
/* Only applies to POWER3, but should be safe on RS64 */
- mmcr0 |= MMCR0_PMC1INTCONTROL|MMCR0_PMCNINTCONTROL;
+ mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE;
mtspr(SPRN_MMCR0, mmcr0);
dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(),
diff --git a/arch/ppc64/xmon/setjmp.S b/arch/ppc64/xmon/setjmp.S
new file mode 100644
index 000000000000..30ee643d557c
--- /dev/null
+++ b/arch/ppc64/xmon/setjmp.S
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * 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.
+ *
+ * NOTE: assert(sizeof(buf) > 184)
+ */
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+
+_GLOBAL(xmon_setjmp)
+ mflr r0
+ std r0,0(r3)
+ std r1,8(r3)
+ std r2,16(r3)
+ mfcr r0
+ std r0,24(r3)
+ std r13,32(r3)
+ std r14,40(r3)
+ std r15,48(r3)
+ std r16,56(r3)
+ std r17,64(r3)
+ std r18,72(r3)
+ std r19,80(r3)
+ std r20,88(r3)
+ std r21,96(r3)
+ std r22,104(r3)
+ std r23,112(r3)
+ std r24,120(r3)
+ std r25,128(r3)
+ std r26,136(r3)
+ std r27,144(r3)
+ std r28,152(r3)
+ std r29,160(r3)
+ std r30,168(r3)
+ std r31,176(r3)
+ li r3,0
+ blr
+
+_GLOBAL(xmon_longjmp)
+ cmpdi r4,0
+ bne 1f
+ li r4,1
+1: ld r13,32(r3)
+ ld r14,40(r3)
+ ld r15,48(r3)
+ ld r16,56(r3)
+ ld r17,64(r3)
+ ld r18,72(r3)
+ ld r19,80(r3)
+ ld r20,88(r3)
+ ld r21,96(r3)
+ ld r22,104(r3)
+ ld r23,112(r3)
+ ld r24,120(r3)
+ ld r25,128(r3)
+ ld r26,136(r3)
+ ld r27,144(r3)
+ ld r28,152(r3)
+ ld r29,160(r3)
+ ld r30,168(r3)
+ ld r31,176(r3)
+ ld r0,24(r3)
+ mtcrf 56,r0
+ ld r0,0(r3)
+ ld r1,8(r3)
+ ld r2,16(r3)
+ mtlr r0
+ mr r3,r4
+ blr
diff --git a/arch/ppc64/xmon/setjmp.c b/arch/ppc64/xmon/setjmp.c
deleted file mode 100644
index a3f6135c5669..000000000000
--- a/arch/ppc64/xmon/setjmp.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 1996 Paul Mackerras.
- *
- * 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.
- *
- * NB this file must be compiled with -O2.
- */
-
-int
-xmon_setjmp(long *buf) /* NOTE: assert(sizeof(buf) > 184) */
-{
- /* XXX should save fp regs as well */
- asm volatile (
- "mflr 0; std 0,0(%0)\n\
- std 1,8(%0)\n\
- std 2,16(%0)\n\
- mfcr 0; std 0,24(%0)\n\
- std 13,32(%0)\n\
- std 14,40(%0)\n\
- std 15,48(%0)\n\
- std 16,56(%0)\n\
- std 17,64(%0)\n\
- std 18,72(%0)\n\
- std 19,80(%0)\n\
- std 20,88(%0)\n\
- std 21,96(%0)\n\
- std 22,104(%0)\n\
- std 23,112(%0)\n\
- std 24,120(%0)\n\
- std 25,128(%0)\n\
- std 26,136(%0)\n\
- std 27,144(%0)\n\
- std 28,152(%0)\n\
- std 29,160(%0)\n\
- std 30,168(%0)\n\
- std 31,176(%0)\n\
- " : : "r" (buf));
- return 0;
-}
-
-void
-xmon_longjmp(long *buf, int val)
-{
- if (val == 0)
- val = 1;
- asm volatile (
- "ld 13,32(%0)\n\
- ld 14,40(%0)\n\
- ld 15,48(%0)\n\
- ld 16,56(%0)\n\
- ld 17,64(%0)\n\
- ld 18,72(%0)\n\
- ld 19,80(%0)\n\
- ld 20,88(%0)\n\
- ld 21,96(%0)\n\
- ld 22,104(%0)\n\
- ld 23,112(%0)\n\
- ld 24,120(%0)\n\
- ld 25,128(%0)\n\
- ld 26,136(%0)\n\
- ld 27,144(%0)\n\
- ld 28,152(%0)\n\
- ld 29,160(%0)\n\
- ld 30,168(%0)\n\
- ld 31,176(%0)\n\
- ld 0,24(%0)\n\
- mtcrf 0x38,0\n\
- ld 0,0(%0)\n\
- ld 1,8(%0)\n\
- ld 2,16(%0)\n\
- mtlr 0\n\
- mr 3,%1\n\
- " : : "r" (buf), "r" (val));
-}
diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
index c53046d52e6c..2be270592fb3 100644
--- a/arch/ppc64/xmon/xmon.c
+++ b/arch/ppc64/xmon/xmon.c
@@ -31,6 +31,7 @@
#include <asm/cputable.h>
#include <asm/rtas.h>
#include <asm/sstep.h>
+#include <asm/bug.h>
#include "nonstdio.h"
#include "privinst.h"
@@ -1319,6 +1320,26 @@ static void backtrace(struct pt_regs *excp)
scannl();
}
+static void print_bug_trap(struct pt_regs *regs)
+{
+ struct bug_entry *bug;
+ unsigned long addr;
+
+ if (regs->msr & MSR_PR)
+ return; /* not in kernel */
+ addr = regs->nip; /* address of trap instruction */
+ if (addr < PAGE_OFFSET)
+ return;
+ bug = find_bug(regs->nip);
+ if (bug == NULL)
+ return;
+ if (bug->line & BUG_WARNING_TRAP)
+ return;
+
+ printf("kernel BUG in %s at %s:%d!\n",
+ bug->function, bug->file, (unsigned int)bug->line);
+}
+
void excprint(struct pt_regs *fp)
{
unsigned long trap;
@@ -1350,6 +1371,9 @@ void excprint(struct pt_regs *fp)
printf(" pid = %ld, comm = %s\n",
current->pid, current->comm);
}
+
+ if (trap == 0x700)
+ print_bug_trap(fp);
}
void prregs(struct pt_regs *fp)
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 85ecab32be89..8394c4e51073 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -367,6 +367,13 @@ config VIRT_TIMER
This provides a kernel interface for virtual CPU timers.
Default is disabled.
+config VIRT_CPU_ACCOUNTING
+ bool "Base user process accounting on virtual cpu timer"
+ depends on VIRT_TIMER
+ help
+ Select this option to use CPU timer deltas to do user
+ process accounting.
+
config APPLDATA_BASE
bool "Linux - VM Monitor Stream, base infrastructure"
depends on PROC_FS && VIRT_TIMER=y
diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c
index 1100c409b5bb..03ba5893f17b 100644
--- a/arch/s390/kernel/binfmt_elf32.c
+++ b/arch/s390/kernel/binfmt_elf32.c
@@ -197,12 +197,13 @@ MODULE_AUTHOR("Gerhard Tonn <ton@de.ibm.com>");
#undef MODULE_DESCRIPTION
#undef MODULE_AUTHOR
-#define jiffies_to_timeval jiffies_to_compat_timeval
+#undef cputime_to_timeval
+#define cputime_to_timeval cputime_to_compat_timeval
static __inline__ void
-jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
+cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
{
- value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
- value->tv_sec = jiffies / HZ;
+ value->tv_usec = cputime % 1000000;
+ value->tv_sec = cputime / 1000000;
}
#include "../../../fs/binfmt_elf.c"
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index f72f9ec9be55..c0e09b33febe 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -66,6 +66,27 @@ STACK_SIZE = 1 << STACK_SHIFT
* R15 - kernel stack pointer
*/
+ .macro STORE_TIMER lc_offset
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ stpt \lc_offset
+#endif
+ .endm
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ .macro UPDATE_VTIME lc_from,lc_to,lc_sum
+ lm %r10,%r11,\lc_from
+ sl %r10,\lc_to
+ sl %r11,\lc_to+4
+ bc 3,BASED(0f)
+ sl %r10,BASED(.Lc_1)
+0: al %r10,\lc_sum
+ al %r11,\lc_sum+4
+ bc 12,BASED(1f)
+ al %r10,BASED(.Lc_1)
+1: stm %r10,%r11,\lc_sum
+ .endm
+#endif
+
.macro SAVE_ALL_BASE savearea
stm %r12,%r15,\savearea
l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13
@@ -118,6 +139,7 @@ STACK_SIZE = 1 << STACK_SHIFT
ni __LC_RETURN_PSW+1,0xfd # clear wait state bit
.endif
lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user
+ STORE_TIMER __LC_EXIT_TIMER
lpsw __LC_RETURN_PSW # back to caller
.endm
@@ -159,9 +181,21 @@ __critical_start:
.globl system_call
system_call:
+ STORE_TIMER __LC_SYNC_ENTER_TIMER
+sysc_saveall:
SAVE_ALL_BASE __LC_SAVE_AREA
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
lh %r7,0x8a # get svc number from lowcore
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+sysc_vtime:
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ bz BASED(sysc_do_svc)
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
+sysc_stime:
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+sysc_update:
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+#endif
sysc_do_svc:
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
sla %r7,2 # *4 and test for svc 0
@@ -391,10 +425,19 @@ pgm_check_handler:
* we just ignore the PER event (FIXME: is there anything we have to do
* for LPSW?).
*/
+ STORE_TIMER __LC_SYNC_ENTER_TIMER
SAVE_ALL_BASE __LC_SAVE_AREA
tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
bnz BASED(pgm_per) # got per exception -> special case
SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ bz BASED(pgm_no_vtime)
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+pgm_no_vtime:
+#endif
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
l %r3,__LC_PGM_ILC # load program interruption code
la %r8,0x7f
@@ -425,6 +468,14 @@ pgm_per:
#
pgm_per_std:
SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ bz BASED(pgm_no_vtime2)
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+pgm_no_vtime2:
+#endif
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
l %r1,__TI_task(%r9)
mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
@@ -442,6 +493,14 @@ pgm_per_std:
#
pgm_svcper:
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ bz BASED(pgm_no_vtime3)
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+pgm_no_vtime3:
+#endif
lh %r7,0x8a # get svc number from lowcore
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
l %r1,__TI_task(%r9)
@@ -458,9 +517,18 @@ pgm_svcper:
.globl io_int_handler
io_int_handler:
+ STORE_TIMER __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
SAVE_ALL_BASE __LC_SAVE_AREA+16
SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+16,0
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ bz BASED(io_no_vtime)
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
+io_no_vtime:
+#endif
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ
la %r2,SP_PTREGS(%r15) # address of register-save area
@@ -549,9 +617,18 @@ io_sigpending:
.globl ext_int_handler
ext_int_handler:
+ STORE_TIMER __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
SAVE_ALL_BASE __LC_SAVE_AREA+16
SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16,0
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ bz BASED(ext_no_vtime)
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
+ext_no_vtime:
+#endif
l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
la %r2,SP_PTREGS(%r15) # address of register-save area
lh %r3,__LC_EXT_INT_CODE # get interruption code
@@ -565,8 +642,17 @@ ext_int_handler:
.globl mcck_int_handler
mcck_int_handler:
+ STORE_TIMER __LC_ASYNC_ENTER_TIMER
SAVE_ALL_BASE __LC_SAVE_AREA+32
SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32,0
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ bz BASED(mcck_no_vtime)
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
+mcck_no_vtime:
+#endif
l %r1,BASED(.Ls390_mcck)
basr %r14,%r1 # call machine check handler
mcck_return:
@@ -661,17 +747,47 @@ cleanup_critical:
br %r14
cleanup_system_call:
- mvc __LC_RETURN_PSW(4),0(%r12)
- clc 4(4,%r12),BASED(cleanup_table_system_call)
- bne BASED(0f)
+ mvc __LC_RETURN_PSW(8),0(%r12)
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4)
+ bh BASED(0f)
+ mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER
+0: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+8)
+ bhe BASED(cleanup_vtime)
+#endif
+ clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn)
+ bh BASED(0f)
mvc __LC_SAVE_AREA(16),__LC_SAVE_AREA+16
0: st %r13,__LC_SAVE_AREA+20
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
st %r15,__LC_SAVE_AREA+28
lh %r7,0x8a
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+cleanup_vtime:
+ clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12)
+ bhe BASED(cleanup_stime)
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ bz BASED(cleanup_novtime)
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
+cleanup_stime:
+ clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+16)
+ bh BASED(cleanup_update)
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+cleanup_update:
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+cleanup_novtime:
+#endif
mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_system_call+4)
la %r12,__LC_RETURN_PSW
br %r14
+cleanup_system_call_insn:
+ .long sysc_saveall + 0x80000000
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ .long system_call + 0x80000000
+ .long sysc_vtime + 0x80000000
+ .long sysc_stime + 0x80000000
+ .long sysc_update + 0x80000000
+#endif
cleanup_sysc_return:
mvc __LC_RETURN_PSW(4),0(%r12)
@@ -680,15 +796,23 @@ cleanup_sysc_return:
br %r14
cleanup_sysc_leave:
- clc 4(4,%r12),BASED(cleanup_sysc_leave_lpsw)
+ clc 4(4,%r12),BASED(cleanup_sysc_leave_insn)
+ be BASED(0f)
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+ clc 4(4,%r12),BASED(cleanup_sysc_leave_insn+4)
be BASED(0f)
+#endif
mvc __LC_RETURN_PSW(8),SP_PSW(%r15)
mvc __LC_SAVE_AREA+16(16),SP_R12(%r15)
lm %r0,%r11,SP_R0(%r15)
l %r15,SP_R15(%r15)
0: la %r12,__LC_RETURN_PSW
br %r14
-cleanup_sysc_leave_lpsw:
+cleanup_sysc_leave_insn:
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ .long sysc_leave + 14 + 0x80000000
+#endif
.long sysc_leave + 10 + 0x80000000
/*
@@ -704,6 +828,7 @@ cleanup_sysc_leave_lpsw:
.L0x028: .short 0x028
.L0x030: .short 0x030
.L0x038: .short 0x038
+.Lc_1: .long 1
/*
* Symbol constants
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index adbe2a5f5f72..51527ab8c8f9 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -58,6 +58,21 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
#define BASED(name) name-system_call(%r13)
+ .macro STORE_TIMER lc_offset
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ stpt \lc_offset
+#endif
+ .endm
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ .macro UPDATE_VTIME lc_from,lc_to,lc_sum
+ lg %r10,\lc_from
+ slg %r10,\lc_to
+ alg %r10,\lc_sum
+ stg %r10,\lc_sum
+ .endm
+#endif
+
/*
* Register usage in interrupt handlers:
* R9 - pointer to current task structure
@@ -117,6 +132,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
ni __LC_RETURN_PSW+1,0xfd # clear wait state bit
.endif
lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user
+ STORE_TIMER __LC_EXIT_TIMER
lpswe __LC_RETURN_PSW # back to caller
.endm
@@ -156,9 +172,21 @@ __critical_start:
.globl system_call
system_call:
+ STORE_TIMER __LC_SYNC_ENTER_TIMER
+sysc_saveall:
SAVE_ALL_BASE __LC_SAVE_AREA
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+sysc_vtime:
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ jz sysc_do_svc
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
+sysc_stime:
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+sysc_update:
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+#endif
sysc_do_svc:
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
slag %r7,%r7,2 # *4 and test for svc 0
@@ -441,10 +469,19 @@ pgm_check_handler:
* we just ignore the PER event (FIXME: is there anything we have to do
* for LPSW?).
*/
+ STORE_TIMER __LC_SYNC_ENTER_TIMER
SAVE_ALL_BASE __LC_SAVE_AREA
tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
jnz pgm_per # got per exception -> special case
SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ jz pgm_no_vtime
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+pgm_no_vtime:
+#endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
lgf %r3,__LC_PGM_ILC # load program interruption code
lghi %r8,0x7f
@@ -475,6 +512,14 @@ pgm_per:
#
pgm_per_std:
SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ jz pgm_no_vtime2
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+pgm_no_vtime2:
+#endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
lg %r1,__TI_task(%r9)
mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
@@ -492,6 +537,14 @@ pgm_per_std:
#
pgm_svcper:
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ jz pgm_no_vtime3
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+pgm_no_vtime3:
+#endif
llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
lg %r1,__TI_task(%r9)
@@ -507,9 +560,18 @@ pgm_svcper:
*/
.globl io_int_handler
io_int_handler:
+ STORE_TIMER __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
SAVE_ALL_BASE __LC_SAVE_AREA+32
SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ jz io_no_vtime
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
+io_no_vtime:
+#endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
la %r2,SP_PTREGS(%r15) # address of register-save area
brasl %r14,do_IRQ # call standard irq handler
@@ -595,9 +657,18 @@ io_sigpending:
*/
.globl ext_int_handler
ext_int_handler:
+ STORE_TIMER __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
SAVE_ALL_BASE __LC_SAVE_AREA+32
SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ jz ext_no_vtime
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
+ext_no_vtime:
+#endif
lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
la %r2,SP_PTREGS(%r15) # address of register-save area
llgh %r3,__LC_EXT_INT_CODE # get interruption code
@@ -609,8 +680,17 @@ ext_int_handler:
*/
.globl mcck_int_handler
mcck_int_handler:
+ STORE_TIMER __LC_ASYNC_ENTER_TIMER
SAVE_ALL_BASE __LC_SAVE_AREA+64
SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64,0
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ jz mcck_no_vtime
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
+mcck_no_vtime:
+#endif
brasl %r14,s390_do_machine_check
mcck_return:
RESTORE_ALL 0
@@ -700,17 +780,47 @@ cleanup_critical:
br %r14
cleanup_system_call:
- mvc __LC_RETURN_PSW(8),0(%r12)
- clc 8(8,%r12),BASED(cleanup_table_system_call)
- jne 0f
+ mvc __LC_RETURN_PSW(16),0(%r12)
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8)
+ jh 0f
+ mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER
+0: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16)
+ jhe cleanup_vtime
+#endif
+ clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn)
+ jh 0f
mvc __LC_SAVE_AREA(32),__LC_SAVE_AREA+32
0: stg %r13,__LC_SAVE_AREA+40
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
stg %r15,__LC_SAVE_AREA+56
llgh %r7,__LC_SVC_INT_CODE
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+cleanup_vtime:
+ clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24)
+ jhe cleanup_stime
+ tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ jz cleanup_novtime
+ UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
+cleanup_stime:
+ clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+32)
+ jh cleanup_update
+ UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
+cleanup_update:
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+cleanup_novtime:
+#endif
mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8)
la %r12,__LC_RETURN_PSW
br %r14
+cleanup_system_call_insn:
+ .quad sysc_saveall
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ .quad system_call
+ .quad sysc_vtime
+ .quad sysc_stime
+ .quad sysc_update
+#endif
cleanup_sysc_return:
mvc __LC_RETURN_PSW(8),0(%r12)
@@ -719,15 +829,23 @@ cleanup_sysc_return:
br %r14
cleanup_sysc_leave:
- clc 8(8,%r12),BASED(cleanup_sysc_leave_lpsw)
+ clc 8(8,%r12),BASED(cleanup_sysc_leave_insn)
+ je 0f
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+ clc 8(8,%r12),BASED(cleanup_sysc_leave_insn+8)
je 0f
+#endif
mvc __LC_RETURN_PSW(16),SP_PSW(%r15)
mvc __LC_SAVE_AREA+32(32),SP_R12(%r15)
lmg %r0,%r11,SP_R0(%r15)
lg %r15,SP_R15(%r15)
0: la %r12,__LC_RETURN_PSW
br %r14
-cleanup_sysc_leave_lpsw:
+cleanup_sysc_leave_insn:
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ .quad sysc_leave + 16
+#endif
.quad sysc_leave + 12
/*
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 75275fe905b1..59bfceabaebe 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -71,6 +71,10 @@ asmlinkage void do_softirq(void)
local_irq_save(flags);
+ account_system_vtime(current);
+
+ local_bh_disable();
+
if (local_softirq_pending()) {
/* Get current stack pointer. */
asm volatile("la %0,0(15)" : "=a" (old));
@@ -93,6 +97,10 @@ asmlinkage void do_softirq(void)
__do_softirq();
}
+ account_system_vtime(current);
+
+ __local_bh_enable();
+
local_irq_restore(flags);
}
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 2fea300f4b47..995e2cd38e77 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -150,28 +150,6 @@ int do_settimeofday(struct timespec *tv)
EXPORT_SYMBOL(do_settimeofday);
-#ifndef CONFIG_ARCH_S390X
-
-static inline __u32
-__calculate_ticks(__u64 elapsed)
-{
- register_pair rp;
-
- rp.pair = elapsed >> 1;
- asm ("dr %0,%1" : "+d" (rp) : "d" (CLK_TICKS_PER_JIFFY >> 1));
- return rp.subreg.odd;
-}
-
-#else /* CONFIG_ARCH_S390X */
-
-static inline __u32
-__calculate_ticks(__u64 elapsed)
-{
- return elapsed / CLK_TICKS_PER_JIFFY;
-}
-
-#endif /* CONFIG_ARCH_S390X */
-
#ifdef CONFIG_PROFILING
#define s390_do_profile(regs) profile_tick(CPU_PROFILING, regs)
@@ -187,14 +165,14 @@ __calculate_ticks(__u64 elapsed)
void account_ticks(struct pt_regs *regs)
{
__u64 tmp;
- __u32 ticks;
+ __u32 ticks, xticks;
/* Calculate how many ticks have passed. */
if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer)
return;
tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer;
if (tmp >= 2*CLK_TICKS_PER_JIFFY) { /* more than two ticks ? */
- ticks = __calculate_ticks(tmp) + 1;
+ ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1;
S390_lowcore.jiffy_timer +=
CLK_TICKS_PER_JIFFY * (__u64) ticks;
} else if (tmp >= CLK_TICKS_PER_JIFFY) {
@@ -216,11 +194,9 @@ void account_ticks(struct pt_regs *regs)
*/
write_seqlock(&xtime_lock);
if (S390_lowcore.jiffy_timer > xtime_cc) {
- __u32 xticks;
-
tmp = S390_lowcore.jiffy_timer - xtime_cc;
if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
- xticks = __calculate_ticks(tmp);
+ xticks = __div(tmp, CLK_TICKS_PER_JIFFY);
xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY;
} else {
xticks = 1;
@@ -230,14 +206,18 @@ void account_ticks(struct pt_regs *regs)
do_timer(regs);
}
write_sequnlock(&xtime_lock);
- while (ticks--)
- update_process_times(user_mode(regs));
#else
- while (ticks--) {
+ for (xticks = ticks; xticks > 0; xticks--)
do_timer(regs);
+#endif
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+ account_user_vtime(current);
+#else
+ while (ticks--)
update_process_times(user_mode(regs));
- }
#endif
+
s390_do_profile(regs);
}
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 02d2179e4082..63cdfec3ba99 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -17,6 +17,8 @@
#include <linux/types.h>
#include <linux/timex.h>
#include <linux/notifier.h>
+#include <linux/kernel_stat.h>
+#include <linux/rcupdate.h>
#include <asm/s390_ext.h>
#include <asm/timer.h>
@@ -25,7 +27,95 @@
static ext_int_info_t ext_int_info_timer;
DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
-void start_cpu_timer(void)
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+/*
+ * Update process times based on virtual cpu times stored by entry.S
+ * to the lowcore fields user_timer, system_timer & steal_clock.
+ */
+void account_user_vtime(struct task_struct *tsk)
+{
+ cputime_t cputime;
+ __u64 timer, clock;
+ int rcu_user_flag;
+
+ timer = S390_lowcore.last_update_timer;
+ clock = S390_lowcore.last_update_clock;
+ asm volatile (" STPT %0\n" /* Store current cpu timer value */
+ " STCK %1" /* Store current tod clock value */
+ : "=m" (S390_lowcore.last_update_timer),
+ "=m" (S390_lowcore.last_update_clock) );
+ S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
+ S390_lowcore.steal_clock += S390_lowcore.last_update_clock - clock;
+
+ cputime = S390_lowcore.user_timer >> 12;
+ rcu_user_flag = cputime != 0;
+ S390_lowcore.user_timer -= cputime << 12;
+ S390_lowcore.steal_clock -= cputime << 12;
+ account_user_time(tsk, cputime);
+
+ cputime = S390_lowcore.system_timer >> 12;
+ S390_lowcore.system_timer -= cputime << 12;
+ S390_lowcore.steal_clock -= cputime << 12;
+ account_system_time(tsk, HARDIRQ_OFFSET, cputime);
+
+ cputime = S390_lowcore.steal_clock;
+ if ((__s64) cputime > 0) {
+ cputime >>= 12;
+ S390_lowcore.steal_clock -= cputime << 12;
+ account_steal_time(tsk, cputime);
+ }
+
+ run_local_timers();
+ if (rcu_pending(smp_processor_id()))
+ rcu_check_callbacks(smp_processor_id(), rcu_user_flag);
+ scheduler_tick();
+}
+
+/*
+ * Update process times based on virtual cpu times stored by entry.S
+ * to the lowcore fields user_timer, system_timer & steal_clock.
+ */
+void account_system_vtime(struct task_struct *tsk)
+{
+ cputime_t cputime;
+ __u64 timer;
+
+ timer = S390_lowcore.last_update_timer;
+ asm volatile (" STPT %0" /* Store current cpu timer value */
+ : "=m" (S390_lowcore.last_update_timer) );
+ S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
+
+ cputime = S390_lowcore.system_timer >> 12;
+ S390_lowcore.system_timer -= cputime << 12;
+ S390_lowcore.steal_clock -= cputime << 12;
+ account_system_time(tsk, 0, cputime);
+}
+
+static inline void set_vtimer(__u64 expires)
+{
+ __u64 timer;
+
+ asm volatile (" STPT %0\n" /* Store current cpu timer value */
+ " SPT %1" /* Set new value immediatly afterwards */
+ : "=m" (timer) : "m" (expires) );
+ S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer;
+ S390_lowcore.last_update_timer = expires;
+
+ /* store expire time for this CPU timer */
+ per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires;
+}
+#else
+static inline void set_vtimer(__u64 expires)
+{
+ S390_lowcore.last_update_timer = expires;
+ asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer));
+
+ /* store expire time for this CPU timer */
+ per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires;
+}
+#endif
+
+static void start_cpu_timer(void)
{
struct vtimer_queue *vt_list;
@@ -33,7 +123,7 @@ void start_cpu_timer(void)
set_vtimer(vt_list->idle);
}
-void stop_cpu_timer(void)
+static void stop_cpu_timer(void)
{
__u64 done;
struct vtimer_queue *vt_list;
@@ -71,19 +161,11 @@ void stop_cpu_timer(void)
set_vtimer(VTIMER_MAX_SLICE);
}
-void set_vtimer(__u64 expires)
-{
- asm volatile ("SPT %0" : : "m" (expires));
-
- /* store expire time for this CPU timer */
- per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires;
-}
-
/*
* Sorted add to a list. List is linear searched until first bigger
* element is found.
*/
-void list_add_sorted(struct vtimer_list *timer, struct list_head *head)
+static void list_add_sorted(struct vtimer_list *timer, struct list_head *head)
{
struct vtimer_list *event;
@@ -429,11 +511,12 @@ void init_cpu_vtimer(void)
{
struct vtimer_queue *vt_list;
unsigned long cr0;
- __u64 timer;
/* kick the virtual timer */
- timer = VTIMER_MAX_SLICE;
- asm volatile ("SPT %0" : : "m" (timer));
+ S390_lowcore.exit_timer = VTIMER_MAX_SLICE;
+ S390_lowcore.last_update_timer = VTIMER_MAX_SLICE;
+ asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer));
+ asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock));
__ctl_store(cr0, 0, 0);
cr0 |= 0x400;
__ctl_load(cr0, 0, 0);
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 4d48a00f77dc..3a1ab51d9077 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -92,8 +92,8 @@ config SMP
bool "Symmetric multi-processing support"
---help---
This enables support for systems with more than one CPU. If you have
- a system with only one CPU, like most personal computers, say N. If
- you have a system with more than one CPU, say Y.
+ a system with only one CPU, say N. If you have a system with more than
+ one CPU, say Y.
If you say N here, the kernel will run on single and multiprocessor
machines, but will use only one CPU of a multiprocessor machine. If
@@ -101,17 +101,11 @@ config SMP
singleprocessor machines. On a singleprocessor machine, the kernel
will run faster if you say N here.
- Note that if you say Y here and choose architecture "586" or
- "Pentium" under "Processor family", the kernel will not work on 486
- architectures. Similarly, multiprocessor kernels for the "PPro"
- architecture may not work on all Pentium based boards.
-
People using multiprocessor machines who say Y here should also say
Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
Management" code will be disabled if you say Y here.
See also the <file:Documentation/smp.txt>,
- <file:Documentation/i386/IO-APIC.txt>,
<file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
<http://www.tldp.org/docs.html#howto>.
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index c5f2317481f4..2166fd9cdceb 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.10
-# Mon Dec 27 22:36:56 2004
+# Mon Jan 10 11:24:25 2005
#
CONFIG_64BIT=y
CONFIG_MMU=y
@@ -79,6 +79,7 @@ CONFIG_US3_FREQ=m
CONFIG_US2E_FREQ=m
CONFIG_SPARC64=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HUGETLB_PAGE_SIZE_4MB=y
# CONFIG_HUGETLB_PAGE_SIZE_512K is not set
# CONFIG_HUGETLB_PAGE_SIZE_64K is not set
@@ -336,6 +337,7 @@ CONFIG_SCSI_CONSTANTS=y
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
#
# SCSI low-level drivers
@@ -395,7 +397,6 @@ CONFIG_SCSI_QLA2XXX=y
# CONFIG_SCSI_QLA2300 is not set
# CONFIG_SCSI_QLA2322 is not set
# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
CONFIG_SCSI_DC395x=m
# CONFIG_SCSI_DC390T is not set
CONFIG_SCSI_DEBUG=m
@@ -619,8 +620,6 @@ CONFIG_IP_NF_TARGET_NOTRACK=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-CONFIG_IP_NF_COMPAT_IPFWADM=m
#
# IPv6: Netfilter Configuration
@@ -894,7 +893,6 @@ CONFIG_B44=m
CONFIG_FORCEDETH=m
CONFIG_DGRS=m
CONFIG_EEPRO100=m
-# CONFIG_EEPRO100_PIO is not set
CONFIG_E100=m
CONFIG_E100_NAPI=y
CONFIG_FEALNX=m
@@ -1081,7 +1079,6 @@ CONFIG_UNIX98_PTY_COUNT=256
# XFree86 DRI support
#
CONFIG_DRM=y
-CONFIG_DRM_FFB=m
CONFIG_DRM_TDFX=m
# CONFIG_DRM_R128 is not set
@@ -1112,13 +1109,14 @@ CONFIG_SOUND_GAMEPORT=m
# CONFIG_GAMEPORT_EMU10K1 is not set
# CONFIG_GAMEPORT_VORTEX is not set
# CONFIG_GAMEPORT_FM801 is not set
-# CONFIG_GAMEPORT_CS461x is not set
+CONFIG_GAMEPORT_CS461X=m
CONFIG_SERIO=y
CONFIG_SERIO_I8042=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PARKBD is not set
CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_LIBPS2=y
CONFIG_SERIO_RAW=m
#
@@ -1239,6 +1237,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
CONFIG_JFS_FS=m
CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
CONFIG_FS_POSIX_ACL=y
@@ -1308,7 +1307,6 @@ CONFIG_CRAMFS=m
CONFIG_VXFS_FS=m
CONFIG_HPFS_FS=m
CONFIG_QNX4FS_FS=m
-# CONFIG_QNX4FS_RW is not set
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
CONFIG_UFS_FS_WRITE=y
@@ -1579,6 +1577,8 @@ CONFIG_SND_CS46XX=m
# CONFIG_SND_CS46XX_NEW_DSP is not set
CONFIG_SND_CS4281=m
CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_CA0106=m
CONFIG_SND_KORG1212=m
CONFIG_SND_MIXART=m
CONFIG_SND_NM256=m
@@ -1603,13 +1603,13 @@ CONFIG_SND_INTEL8X0=m
CONFIG_SND_INTEL8X0M=m
CONFIG_SND_SONICVIBES=m
# CONFIG_SND_VIA82XX is not set
+CONFIG_SND_VIA82XX_MODEM=m
CONFIG_SND_VX222=m
#
# USB devices
#
# CONFIG_SND_USB_AUDIO is not set
-CONFIG_SND_USB_USX2Y=m
#
# ALSA Sparc devices
@@ -1691,7 +1691,6 @@ CONFIG_USB_ATI_REMOTE=m
#
CONFIG_USB_MDC800=m
CONFIG_USB_MICROTEK=m
-CONFIG_USB_HPUSBSCSI=m
#
# USB Multimedia devices
@@ -1862,7 +1861,7 @@ CONFIG_SCHEDSTATS=y
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_STACK_USAGE is not set
CONFIG_KPROBES=y
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index 64d547853b48..1afe88f6abc0 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -49,7 +49,9 @@ static void set_brk(unsigned long start, unsigned long end)
end = PAGE_ALIGN(end);
if (end <= start)
return;
+ down_write(&current->mm->mmap_sem);
do_brk(start, end - start);
+ up_write(&current->mm->mmap_sem);
}
/*
@@ -95,7 +97,7 @@ static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file)
set_fs(KERNEL_DS);
has_dumped = 1;
current->flags |= PF_DUMPCORE;
- strncpy(dump.u_comm, current->comm, sizeof(current->comm));
+ strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm));
dump.signal = signr;
dump_thread(regs, &dump);
@@ -246,10 +248,14 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (N_MAGIC(ex) == NMAGIC) {
loff_t pos = fd_offset;
/* Fuck me plenty... */
+ down_write(&current->mm->mmap_sem);
error = do_brk(N_TXTADDR(ex), ex.a_text);
+ up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
ex.a_text, &pos);
+ down_write(&current->mm->mmap_sem);
error = do_brk(N_DATADDR(ex), ex.a_data);
+ up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex),
ex.a_data, &pos);
goto beyond_if;
@@ -257,8 +263,10 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (N_MAGIC(ex) == OMAGIC) {
loff_t pos = fd_offset;
+ down_write(&current->mm->mmap_sem);
do_brk(N_TXTADDR(ex) & PAGE_MASK,
ex.a_text+ex.a_data + PAGE_SIZE - 1);
+ up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
ex.a_text+ex.a_data, &pos);
} else {
@@ -272,7 +280,9 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (!bprm->file->f_op->mmap) {
loff_t pos = fd_offset;
+ down_write(&current->mm->mmap_sem);
do_brk(0, ex.a_text+ex.a_data);
+ up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file,
(char __user *)N_TXTADDR(ex),
ex.a_text+ex.a_data, &pos);
@@ -389,7 +399,9 @@ static int load_aout32_library(struct file *file)
len = PAGE_ALIGN(ex.a_text + ex.a_data);
bss = ex.a_text + ex.a_data + ex.a_bss;
if (bss > len) {
+ down_write(&current->mm->mmap_sem);
error = do_brk(start_addr + len, bss - len);
+ up_write(&current->mm->mmap_sem);
retval = error;
if (error != start_addr + len)
goto out;
diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c
index c13eaf030758..a1a12d2aa353 100644
--- a/arch/sparc64/kernel/binfmt_elf32.c
+++ b/arch/sparc64/kernel/binfmt_elf32.c
@@ -132,10 +132,12 @@ struct elf_prpsinfo32
#include <linux/time.h>
-#define jiffies_to_timeval jiffies_to_compat_timeval
+#undef cputime_to_timeval
+#define cputime_to_timeval cputime_to_compat_timeval
static __inline__ void
-jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
+cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
{
+ unsigned long jiffies = cputime_to_jiffies(cputime);
value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
value->tv_sec = jiffies / HZ;
}
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 2dacbd7808a7..70b2441b6a63 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -453,9 +453,9 @@ static void __psycho_check_one_stc(struct pci_controller_info *p,
tag_base = regbase + PSYCHO_STC_TAG_A;
line_base = regbase + PSYCHO_STC_LINE_A;
} else {
- err_base = regbase + PSYCHO_STC_ERR_A;
- tag_base = regbase + PSYCHO_STC_TAG_A;
- line_base = regbase + PSYCHO_STC_LINE_A;
+ err_base = regbase + PSYCHO_STC_ERR_B;
+ tag_base = regbase + PSYCHO_STC_TAG_B;
+ line_base = regbase + PSYCHO_STC_LINE_B;
}
spin_lock(&stc_buf_lock);
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index f2314232f5f8..fe2510dc57ba 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1598,7 +1598,8 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
put_user(oldlen, (u32 __user *)(unsigned long) tmp.oldlenp))
error = -EFAULT;
}
- copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
+ if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
+ error = -EFAULT;
}
return error;
#endif
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index 1bf38a5eaff7..2571a279326f 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -291,7 +291,8 @@ static int sunos_filldir(void * __buf, const char * name, int namlen,
put_user(ino, &dirent->d_ino);
put_user(namlen, &dirent->d_namlen);
put_user(reclen, &dirent->d_reclen);
- copy_to_user(dirent->d_name, name, namlen);
+ if (copy_to_user(dirent->d_name, name, namlen))
+ return -EFAULT;
put_user(0, dirent->d_name + namlen);
dirent = (void __user *) dirent + reclen;
buf->curr = dirent;
@@ -371,7 +372,8 @@ static int sunos_filldirentry(void * __buf, const char * name, int namlen,
put_user(ino, &dirent->d_ino);
put_user(namlen, &dirent->d_namlen);
put_user(reclen, &dirent->d_reclen);
- copy_to_user(dirent->d_name, name, namlen);
+ if (copy_to_user(dirent->d_name, name, namlen))
+ return -EFAULT;
put_user(0, dirent->d_name + namlen);
dirent = (void __user *) dirent + reclen;
buf->curr = dirent;
diff --git a/arch/sparc64/lib/find_bit.c b/arch/sparc64/lib/find_bit.c
index 27545fbf5da7..6059557067b4 100644
--- a/arch/sparc64/lib/find_bit.c
+++ b/arch/sparc64/lib/find_bit.c
@@ -50,9 +50,10 @@ found_middle:
* on Linus's ALPHA routines, which are pretty portable BTW.
*/
-unsigned long find_next_zero_bit(unsigned long *addr, unsigned long size, unsigned long offset)
+unsigned long find_next_zero_bit(const unsigned long *addr,
+ unsigned long size, unsigned long offset)
{
- unsigned long *p = addr + (offset >> 6);
+ const unsigned long *p = addr + (offset >> 6);
unsigned long result = offset & ~63UL;
unsigned long tmp;
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 06ba2aca73a5..f399b64a137c 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -68,6 +68,8 @@ config MODE_SKAS
to CONFIG_MODE_TT). Otherwise, it is safe to say Y. Disabling this
option will shrink the UML binary slightly.
+source "arch/um/Kconfig_arch"
+
config NET
bool "Networking support"
help
@@ -283,7 +285,10 @@ if BROKEN
endif
config INPUT
- bool
+ bool "Dummy option"
+ depends BROKEN
default n
+ help
+ This is a dummy option to get rid of warnings.
source "arch/um/Kconfig.debug"
diff --git a/arch/um/Kconfig_arch b/arch/um/Kconfig_arch
new file mode 100644
index 000000000000..2f5f053bc461
--- /dev/null
+++ b/arch/um/Kconfig_arch
@@ -0,0 +1,16 @@
+config 64_BIT
+ bool
+ default n
+
+config TOP_ADDR
+ hex
+ default 0xc0000000 if !HOST_2G_2G
+ default 0x80000000 if HOST_2G_2G
+
+config 3_LEVEL_PGTABLES
+ bool "Three-level pagetables"
+ default n
+ help
+ Three-level pagetables will let UML have more than 4G of physical
+ memory. All the memory that can't be mapped directly will be treated
+ as high memory.
diff --git a/arch/um/Kconfig_char b/arch/um/Kconfig_char
index 7a933d1b5d5b..fa34a9698586 100644
--- a/arch/um/Kconfig_char
+++ b/arch/um/Kconfig_char
@@ -23,15 +23,6 @@ config SSL
Unless you have a specific reason for disabling this, say Y.
-config FD_CHAN
- bool "file descriptor channel support"
- help
- This option enables support for attaching UML consoles and serial
- lines to already set up file descriptors. Generally, the main
- console is attached to file descriptors 0 and 1 (stdin and stdout),
- so it would be wise to leave this enabled unless you intend to
- attach it to some other host device.
-
config NULL_CHAN
bool "null channel support"
help
@@ -80,7 +71,7 @@ config XTERM_CHAN
config NOCONFIG_CHAN
bool
- default !(XTERM_CHAN && TTY_CHAN && PTY_CHAN && PORT_CHAN && FD_CHAN && NULL_CHAN)
+ default !(XTERM_CHAN && TTY_CHAN && PTY_CHAN && PORT_CHAN && NULL_CHAN)
config CON_ZERO_CHAN
string "Default main console channel initialization"
diff --git a/arch/um/Kconfig_i386 b/arch/um/Kconfig_i386
new file mode 100644
index 000000000000..e3d956db3daa
--- /dev/null
+++ b/arch/um/Kconfig_i386
@@ -0,0 +1,20 @@
+config 64_BIT
+ bool
+ default n
+
+config TOP_ADDR
+ hex
+ default 0xc0000000 if !HOST_2G_2G
+ default 0x80000000 if HOST_2G_2G
+
+config 3_LEVEL_PGTABLES
+ bool "Three-level pagetables"
+ default n
+ help
+ Three-level pagetables will let UML have more than 4G of physical
+ memory. All the memory that can't be mapped directly will be treated
+ as high memory.
+
+config ARCH_HAS_SC_SIGNALS
+ bool
+ default y
diff --git a/arch/um/Kconfig_x86_64 b/arch/um/Kconfig_x86_64
new file mode 100644
index 000000000000..0d3d05cab5b7
--- /dev/null
+++ b/arch/um/Kconfig_x86_64
@@ -0,0 +1,11 @@
+config 64_BIT
+ bool
+ default y
+
+config 3_LEVEL_PGTABLES
+ bool
+ default y
+
+config ARCH_HAS_SC_SIGNALS
+ bool
+ default n
diff --git a/arch/um/Makefile b/arch/um/Makefile
index b8371a95849a..a21b5d1da07f 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -12,14 +12,17 @@ SHELL := /bin/bash
filechk_gen_header = $<
core-y += $(ARCH_DIR)/kernel/ \
- $(ARCH_DIR)/drivers/ \
- $(ARCH_DIR)/sys-$(SUBARCH)/
+ $(ARCH_DIR)/drivers/
+
+clean-dirs := sys-$(SUBARCH)
# Have to precede the include because the included Makefiles reference them.
SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \
- arch-signal.h module.h
+ arch-signal.h module.h vm-flags.h
SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
+CLEAN_FILES += $(ARCH_SYMLINKS)
+
ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
$(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
@@ -38,6 +41,9 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH)
include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
+core-y += $(SUBARCH_CORE)
+libs-y += $(SUBARCH_LIBS)
+
# -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 CFLAGS. Otherwise, it would cause ld to complain about the two different
@@ -77,6 +83,11 @@ define archhelp
echo ' find in the kernel root.'
endef
+$(shell cd $(ARCH_DIR) && ln -sf Kconfig_$(SUBARCH) Kconfig_arch)
+
+CLEAN_FILES += $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h \
+ $(TOPDIR)/$(ARCH_DIR)/os
+
prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) \
$(ARCH_DIR)/kernel/vmlinux.lds.S
@@ -137,7 +148,8 @@ USER_CFLAGS += -D_GNU_SOURCE
#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 \
- $(GEN_HEADERS) $(ARCH_DIR)/include/skas_ptregs.h
+ $(GEN_HEADERS) $(ARCH_DIR)/include/skas_ptregs.h \
+ $(ARCH_DIR)/util/mk_constants $(ARCH_DIR)/util/mk_task
MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \
$(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index 7c7d008478b6..97b223bfa78e 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -1,8 +1,6 @@
-ifeq ($(CONFIG_HOST_2G_2G), y)
-TOP_ADDR := 0x80000000
-else
-TOP_ADDR := 0xc0000000
-endif
+SUBARCH_CORE := arch/um/sys-i386/
+
+TOP_ADDR := $(CONFIG_TOP_ADDR)
ifeq ($(CONFIG_MODE_SKAS),y)
ifneq ($(CONFIG_MODE_TT),y)
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index 705df73454c8..9638cac93165 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -1 +1,36 @@
+# Copyright 2003 - 2004 Pathscale, Inc
+# Released under the GPL
+
+SUBARCH_LIBS := arch/um/sys-x86_64/
+START := 0x60000000
+
+CFLAGS += -U__$(SUBARCH)__ -fno-builtin
ARCH_USER_CFLAGS := -D__x86_64__
+
+ELF_ARCH := i386:x86-64
+ELF_FORMAT := elf64-x86-64
+
+SYS_UTIL_DIR := $(ARCH_DIR)/sys-x86_64/util
+SYS_DIR := $(ARCH_DIR)/include/sysdep-x86_64
+
+SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
+
+prepare: $(SYS_HEADERS)
+
+$(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
+ $(call filechk,gen_header)
+
+$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
+ $(call filechk,gen_header)
+
+$(SYS_UTIL_DIR)/mk_sc: scripts_basic FORCE
+ $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
+
+$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE
+ $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
+
+CLEAN_FILES += $(SYS_HEADERS)
+
+LIBC_DIR := /usr/lib64
+
+export LIBC_DIR
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 708878e397a9..66f902a9907b 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -17,6 +17,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
#
CONFIG_MODE_TT=y
CONFIG_MODE_SKAS=y
+# CONFIG_3_LEVEL_PGTABLES is not set
CONFIG_NET=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
@@ -91,13 +92,12 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_STDERR_CONSOLE=y
CONFIG_STDIO_CONSOLE=y
CONFIG_SSL=y
-CONFIG_FD_CHAN=y
CONFIG_NULL_CHAN=y
CONFIG_PORT_CHAN=y
CONFIG_PTY_CHAN=y
CONFIG_TTY_CHAN=y
CONFIG_XTERM_CHAN=y
-# CONFIG_NOCONFIG_CHAN is not set
+CONFIG_NOCONFIG_CHAN=y
CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
CONFIG_CON_CHAN="xterm"
CONFIG_SSL_CHAN="pty"
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index 3a3ac38017f4..e94da95ffdcf 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -20,7 +20,7 @@ ubd-objs := ubd_kern.o ubd_user.o
port-objs := port_kern.o port_user.o
harddog-objs := harddog_kern.o harddog_user.o
-obj-y := stdio_console.o $(CHAN_OBJS)
+obj-y := stdio_console.o fd.o $(CHAN_OBJS)
obj-$(CONFIG_SSL) += ssl.o
obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o
@@ -34,7 +34,6 @@ obj-$(CONFIG_MCONSOLE) += mconsole.o
obj-$(CONFIG_MMAPPER) += mmapper_kern.o
obj-$(CONFIG_BLK_DEV_UBD) += ubd.o
obj-$(CONFIG_HOSTAUDIO) += hostaudio.o
-obj-$(CONFIG_FD_CHAN) += fd.o
obj-$(CONFIG_NULL_CHAN) += null.o
obj-$(CONFIG_PORT_CHAN) += port.o
obj-$(CONFIG_PTY_CHAN) += pty.o
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index bf4bb736e6af..f30ae1b0bcc0 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -399,11 +399,7 @@ struct chan_type {
};
struct chan_type chan_table[] = {
-#ifdef CONFIG_FD_CHAN
{ "fd", &fd_ops },
-#else
- { "fd", &not_configged_ops },
-#endif
#ifdef CONFIG_NULL_CHAN
{ "null", &null_ops },
diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h
index 19517312aa86..4fcbe8b1b77e 100644
--- a/arch/um/drivers/cow.h
+++ b/arch/um/drivers/cow.h
@@ -21,11 +21,12 @@ extern int file_reader(__u64 offset, char *buf, int len, void *arg);
extern int read_cow_header(int (*reader)(__u64, char *, int, void *),
void *arg, __u32 *version_out,
char **backing_file_out, time_t *mtime_out,
- __u64 *size_out, int *sectorsize_out,
+ unsigned long long *size_out, int *sectorsize_out,
__u32 *align_out, int *bitmap_offset_out);
extern int write_cow_header(char *cow_file, int fd, char *backing_file,
- int sectorsize, int alignment, long long *size);
+ int sectorsize, int alignment,
+ unsigned long long *size);
extern void cow_sizes(int version, __u64 size, int sectorsize, int align,
int bitmap_offset, unsigned long *bitmap_len_out,
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
index ce251f08305f..c83fc5d68936 100644
--- a/arch/um/drivers/cow_sys.h
+++ b/arch/um/drivers/cow_sys.h
@@ -23,12 +23,12 @@ static inline char *cow_strdup(char *str)
return(uml_strdup(str));
}
-static inline int cow_seek_file(int fd, __u64 offset)
+static inline int cow_seek_file(int fd, unsigned long long offset)
{
return(os_seek_file(fd, offset));
}
-static inline int cow_file_size(char *file, __u64 *size_out)
+static inline int cow_file_size(char *file, unsigned long long *size_out)
{
return(os_file_size(file, size_out));
}
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 122664b6b16a..c43425c1ee1f 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -159,7 +159,7 @@ static int absolutize(char *to, int size, char *from)
}
int write_cow_header(char *cow_file, int fd, char *backing_file,
- int sectorsize, int alignment, long long *size)
+ int sectorsize, int alignment, unsigned long long *size)
{
struct cow_header_v3 *header;
unsigned long modtime;
@@ -236,7 +236,7 @@ int file_reader(__u64 offset, char *buf, int len, void *arg)
int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
__u32 *version_out, char **backing_file_out,
- time_t *mtime_out, __u64 *size_out,
+ time_t *mtime_out, unsigned long long *size_out,
int *sectorsize_out, __u32 *align_out,
int *bitmap_offset_out)
{
@@ -329,7 +329,7 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
int alignment, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out)
{
- __u64 size, offset;
+ unsigned long long size, offset;
char zero = 0;
int err;
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 73d6e3e0af51..baa9f7f46bc3 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -198,6 +198,37 @@ int line_ioctl(struct tty_struct *tty, struct file * file,
ret = 0;
switch(cmd) {
+#ifdef TIOCGETP
+ case TIOCGETP:
+ case TIOCSETP:
+ case TIOCSETN:
+#endif
+#ifdef TIOCGETC
+ case TIOCGETC:
+ case TIOCSETC:
+#endif
+#ifdef TIOCGLTC
+ case TIOCGLTC:
+ case TIOCSLTC:
+#endif
+ case TCGETS:
+ case TCSETSF:
+ case TCSETSW:
+ case TCSETS:
+ case TCGETA:
+ case TCSETAF:
+ case TCSETAW:
+ case TCSETA:
+ case TCXONC:
+ case TCFLSH:
+ case TIOCOUTQ:
+ case TIOCINQ:
+ case TIOCGLCKTRMIOS:
+ case TIOCSLCKTRMIOS:
+ case TIOCPKT:
+ case TIOCGSOFTCAR:
+ case TIOCSSOFTCAR:
+ return -ENOIOCTLCMD;
#if 0
case TCwhatever:
/* do something */
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 0c87589c0781..ecbabd351c6d 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -73,11 +73,12 @@ DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
static irqreturn_t mconsole_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
- int fd;
+ /* long to avoid size mismatch warnings from gcc */
+ long fd;
struct mconsole_entry *new;
struct mc_request req;
- fd = (int) dev_id;
+ fd = (long) dev_id;
while (mconsole_get_request(fd, &req)){
if(req.cmd->context == MCONSOLE_INTR)
(*req.cmd->handler)(&req);
@@ -457,7 +458,9 @@ static char *notify_socket = NULL;
int mconsole_init(void)
{
- int err, sock;
+ /* long to avoid size mismatch warnings from gcc */
+ long sock;
+ int err;
char file[256];
if(umid_file_name("mconsole", file, sizeof(file))) return(-1);
@@ -496,7 +499,7 @@ int mconsole_init(void)
__initcall(mconsole_init);
-static int write_proc_mconsole(struct file *file, const char *buffer,
+static int write_proc_mconsole(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char *buf;
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index 1546b0429ce2..a63231dffe05 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -8,6 +8,8 @@
* Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com
*
*/
+
+#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/time.h>
#include <linux/devfs_fs_kernel.h>
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index f05c2b7514f2..17d85730086b 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -172,7 +172,7 @@ static struct proc_dir_entry *proc_ide = NULL;
static void make_proc_ide(void)
{
- proc_ide_root = proc_mkdir("ide", 0);
+ proc_ide_root = proc_mkdir("ide", NULL);
proc_ide = proc_mkdir("ide0", proc_ide_root);
}
@@ -1087,7 +1087,7 @@ static void do_ubd_request(request_queue_t *q)
static int ubd_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
- struct hd_geometry *loc = (struct hd_geometry *) arg;
+ struct hd_geometry __user *loc = (struct hd_geometry __user *) arg;
struct ubd *dev = inode->i_bdev->bd_disk->private_data;
struct hd_driveid ubd_id = {
.cyls = 0,
@@ -1108,19 +1108,19 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
case HDIO_GET_IDENTITY:
ubd_id.cyls = dev->size / (128 * 32 * 512);
- if(copy_to_user((char *) arg, (char *) &ubd_id,
+ if(copy_to_user((char __user *) arg, (char *) &ubd_id,
sizeof(ubd_id)))
return(-EFAULT);
return(0);
case CDROMVOLREAD:
- if(copy_from_user(&volume, (char *) arg, sizeof(volume)))
+ if(copy_from_user(&volume, (char __user *) arg, sizeof(volume)))
return(-EFAULT);
volume.channel0 = 255;
volume.channel1 = 255;
volume.channel2 = 255;
volume.channel3 = 255;
- if(copy_to_user((char *) arg, &volume, sizeof(volume)))
+ if(copy_to_user((char __user *) arg, &volume, sizeof(volume)))
return(-EFAULT);
return(0);
}
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 882d2f7c1ee7..c6d8ffa5641b 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -107,7 +107,7 @@ int open_ubd_file(char *file, struct openflags *openflags,
int *create_cow_out)
{
time_t mtime;
- __u64 size;
+ unsigned long long size;
__u32 version, align;
char *backing_file;
int fd, err, sectorsize, same, mode = 0644;
diff --git a/arch/um/include/process.h b/arch/um/include/process.h
index 07af218574fd..5af9157ff54f 100644
--- a/arch/um/include/process.h
+++ b/arch/um/include/process.h
@@ -6,7 +6,7 @@
#ifndef __PROCESS_H__
#define __PROCESS_H__
-#include <asm/sigcontext.h>
+#include <signal.h>
extern void sig_handler(int sig, struct sigcontext sc);
extern void alarm_handler(int sig, struct sigcontext sc);
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
new file mode 100644
index 000000000000..87899df0072f
--- /dev/null
+++ b/arch/um/include/registers.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004 PathScale, Inc
+ * Licensed under the GPL
+ */
+
+#ifndef __REGISTERS_H
+#define __REGISTERS_H
+
+#include "sysdep/ptrace.h"
+
+extern void init_thread_registers(union uml_pt_regs *to);
+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);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
index fc8e4f314ca6..dc126e5e25ac 100644
--- a/arch/um/include/sysdep-i386/ptrace.h
+++ b/arch/um/include/sysdep-i386/ptrace.h
@@ -9,11 +9,52 @@
#include "uml-config.h"
#ifdef UML_CONFIG_MODE_TT
-#include "ptrace-tt.h"
+#include "sysdep/sc.h"
#endif
#ifdef UML_CONFIG_MODE_SKAS
-#include "ptrace-skas.h"
+
+/* syscall emulation path in ptrace */
+
+#ifndef PTRACE_SYSEMU
+#define PTRACE_SYSEMU 31
+#endif
+
+void set_using_sysemu(int value);
+int get_using_sysemu(void);
+extern int sysemu_supported;
+
+#include "skas_ptregs.h"
+
+#define HOST_FRAME_SIZE 17
+
+#define REGS_IP(r) ((r)[HOST_IP])
+#define REGS_SP(r) ((r)[HOST_SP])
+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
+#define REGS_EAX(r) ((r)[HOST_EAX])
+#define REGS_EBX(r) ((r)[HOST_EBX])
+#define REGS_ECX(r) ((r)[HOST_ECX])
+#define REGS_EDX(r) ((r)[HOST_EDX])
+#define REGS_ESI(r) ((r)[HOST_ESI])
+#define REGS_EDI(r) ((r)[HOST_EDI])
+#define REGS_EBP(r) ((r)[HOST_EBP])
+#define REGS_CS(r) ((r)[HOST_CS])
+#define REGS_SS(r) ((r)[HOST_SS])
+#define REGS_DS(r) ((r)[HOST_DS])
+#define REGS_ES(r) ((r)[HOST_ES])
+#define REGS_FS(r) ((r)[HOST_FS])
+#define REGS_GS(r) ((r)[HOST_GS])
+
+#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res)
+
+#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
+
+#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type)
+
+#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
+
+#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
+
#endif
#ifndef PTRACE_SYSEMU_SINGLESTEP
#define PTRACE_SYSEMU_SINGLESTEP 32
diff --git a/arch/um/include/sysdep-i386/signal.h b/arch/um/include/sysdep-i386/signal.h
new file mode 100644
index 000000000000..b1e1f7a77499
--- /dev/null
+++ b/arch/um/include/sysdep-i386/signal.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004 PathScale, Inc
+ * Licensed under the GPL
+ */
+
+#ifndef __I386_SIGNAL_H_
+#define __I386_SIGNAL_H_
+
+#include <signal.h>
+
+#define ARCH_GET_SIGCONTEXT(sc, sig) \
+ do sc = (struct sigcontext *) (&sig + 1); while(0)
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
index 47687dcf2b51..36d9beec431b 100644
--- a/arch/um/include/sysdep-i386/syscalls.h
+++ b/arch/um/include/sysdep-i386/syscalls.h
@@ -8,11 +8,70 @@
typedef long syscall_handler_t(struct pt_regs);
+/* Not declared on x86, incompatible declarations on x86_64, so these have
+ * to go here rather than in sys_call_table.c
+ */
+extern syscall_handler_t sys_ptrace;
+extern syscall_handler_t sys_rt_sigaction;
+
+extern syscall_handler_t old_mmap_i386;
+
#define EXECUTE_SYSCALL(syscall, regs) \
((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
+extern long sys_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff);
+
#define ARCH_SYSCALLS \
+ [ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid, \
+ [ __NR_break ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_oldstat ] = (syscall_handler_t *) sys_stat, \
+ [ __NR_umount ] = (syscall_handler_t *) sys_oldumount, \
+ [ __NR_stime ] = um_stime, \
+ [ __NR_oldfstat ] = (syscall_handler_t *) sys_fstat, \
+ [ __NR_stty ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_gtty ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_nice ] = (syscall_handler_t *) sys_nice, \
+ [ __NR_ftime ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_prof ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_signal ] = (syscall_handler_t *) sys_signal, \
+ [ __NR_lock ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_mpx ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_ulimit ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_oldolduname ] = (syscall_handler_t *) sys_olduname, \
+ [ __NR_sigaction ] = (syscall_handler_t *) sys_sigaction, \
+ [ __NR_sgetmask ] = (syscall_handler_t *) sys_sgetmask, \
+ [ __NR_ssetmask ] = (syscall_handler_t *) sys_ssetmask, \
+ [ __NR_sigsuspend ] = (syscall_handler_t *) sys_sigsuspend, \
+ [ __NR_sigpending ] = (syscall_handler_t *) sys_sigpending, \
+ [ __NR_oldlstat ] = (syscall_handler_t *) sys_lstat, \
+ [ __NR_readdir ] = old_readdir, \
+ [ __NR_profil ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_socketcall ] = (syscall_handler_t *) sys_socketcall, \
+ [ __NR_olduname ] = (syscall_handler_t *) sys_uname, \
+ [ __NR_iopl ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_idle ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_ipc ] = (syscall_handler_t *) sys_ipc, \
+ [ __NR_sigreturn ] = (syscall_handler_t *) sys_sigreturn, \
+ [ __NR_sigprocmask ] = (syscall_handler_t *) sys_sigprocmask, \
+ [ __NR_bdflush ] = (syscall_handler_t *) sys_bdflush, \
+ [ __NR__llseek ] = (syscall_handler_t *) sys_llseek, \
+ [ __NR__newselect ] = (syscall_handler_t *) sys_select, \
+ [ __NR_vm86 ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_mmap ] = (syscall_handler_t *) old_mmap_i386, \
+ [ __NR_ugetrlimit ] = (syscall_handler_t *) sys_getrlimit, \
+ [ __NR_mmap2 ] = (syscall_handler_t *) sys_mmap2, \
+ [ __NR_truncate64 ] = (syscall_handler_t *) sys_truncate64, \
+ [ __NR_ftruncate64 ] = (syscall_handler_t *) sys_ftruncate64, \
+ [ __NR_stat64 ] = (syscall_handler_t *) sys_stat64, \
+ [ __NR_lstat64 ] = (syscall_handler_t *) sys_lstat64, \
+ [ __NR_fstat64 ] = (syscall_handler_t *) sys_fstat64, \
+ [ __NR_fcntl64 ] = (syscall_handler_t *) sys_fcntl64, \
+ [ __NR_sendfile64 ] = (syscall_handler_t *) sys_sendfile64, \
+ [ __NR_statfs64 ] = (syscall_handler_t *) sys_statfs64, \
+ [ __NR_fstatfs64 ] = (syscall_handler_t *) sys_fstatfs64, \
+ [ __NR_fadvise64_64 ] = (syscall_handler_t *) sys_fadvise64_64, \
[ __NR_select ] = (syscall_handler_t *) old_select, \
[ __NR_vm86old ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
@@ -38,11 +97,19 @@ typedef long syscall_handler_t(struct pt_regs);
[ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \
[ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \
[ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \
- [ 222 ] = (syscall_handler_t *) sys_ni_syscall,
+ [ 222 ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ 223 ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, \
+ [ 251 ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages, \
+ [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \
+ [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall,
/* 222 doesn't yet have a name in include/asm-i386/unistd.h */
-#define LAST_ARCH_SYSCALL 222
+#define LAST_ARCH_SYSCALL __NR_vserver
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/include/sysdep-ppc/syscalls.h b/arch/um/include/sysdep-ppc/syscalls.h
index d703d0d12c7e..679df351e19b 100644
--- a/arch/um/include/sysdep-ppc/syscalls.h
+++ b/arch/um/include/sysdep-ppc/syscalls.h
@@ -34,9 +34,12 @@ int old_mmap(unsigned long addr, unsigned long len,
[ __NR_multiplexer ] = sys_ni_syscall, \
[ __NR_mmap ] = old_mmap, \
[ __NR_madvise ] = sys_madvise, \
- [ __NR_mincore ] = sys_mincore,
+ [ __NR_mincore ] = sys_mincore, \
+ [ __NR_iopl ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \
+ [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64,
-#define LAST_ARCH_SYSCALL __NR_mincore
+#define LAST_ARCH_SYSCALL __NR_fadvise64
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/include/sysdep-x86_64/checksum.h b/arch/um/include/sysdep-x86_64/checksum.h
new file mode 100644
index 000000000000..d57aa7f3130e
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/checksum.h
@@ -0,0 +1,151 @@
+/*
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_SYSDEP_CHECKSUM_H
+#define __UM_SYSDEP_CHECKSUM_H
+
+#include "linux/string.h"
+#include "linux/in6.h"
+#include "asm/uaccess.h"
+
+extern unsigned int csum_partial_copy_from(const char *src, char *dst, int len,
+ int sum, int *err_ptr);
+extern unsigned csum_partial(const unsigned char *buff, unsigned len,
+ unsigned sum);
+
+/*
+ * Note: when you get a NULL pointer exception here this means someone
+ * passed in an incorrect kernel address to one of these functions.
+ *
+ * If you use these functions directly please don't forget the
+ * verify_area().
+ */
+
+static __inline__
+unsigned int csum_partial_copy_nocheck(const char *src, char *dst,
+ int len, int sum)
+{
+ memcpy(dst, src, len);
+ return(csum_partial(dst, len, sum));
+}
+
+static __inline__
+unsigned int csum_partial_copy_from_user(const char *src, char *dst,
+ int len, int sum, int *err_ptr)
+{
+ return csum_partial_copy_from(src, dst, len, sum, err_ptr);
+}
+
+/**
+ * csum_fold - Fold and invert a 32bit checksum.
+ * sum: 32bit unfolded sum
+ *
+ * Fold a 32bit running checksum to 16bit and invert it. This is usually
+ * the last step before putting a checksum into a packet.
+ * Make sure not to mix with 64bit checksums.
+ */
+static inline unsigned int csum_fold(unsigned int sum)
+{
+ __asm__(
+ " addl %1,%0\n"
+ " adcl $0xffff,%0"
+ : "=r" (sum)
+ : "r" (sum << 16), "0" (sum & 0xffff0000)
+ );
+ return (~sum) >> 16;
+}
+
+/**
+ * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
+ * @saddr: source address
+ * @daddr: destination address
+ * @len: length of packet
+ * @proto: ip protocol of packet
+ * @sum: initial sum to be added in (32bit unfolded)
+ *
+ * Returns the pseudo header checksum the input data. Result is
+ * 32bit unfolded.
+ */
+static inline unsigned long
+csum_tcpudp_nofold(unsigned saddr, unsigned daddr, unsigned short len,
+ unsigned short proto, unsigned int sum)
+{
+ asm(" addl %1, %0\n"
+ " adcl %2, %0\n"
+ " adcl %3, %0\n"
+ " adcl $0, %0\n"
+ : "=r" (sum)
+ : "g" (daddr), "g" (saddr), "g" ((ntohs(len)<<16)+proto*256), "0" (sum));
+ return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/**
+ * ip_fast_csum - Compute the IPv4 header checksum efficiently.
+ * iph: ipv4 header
+ * ihl: length of header / 4
+ */
+static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
+{
+ unsigned int sum;
+
+ asm( " movl (%1), %0\n"
+ " subl $4, %2\n"
+ " jbe 2f\n"
+ " addl 4(%1), %0\n"
+ " adcl 8(%1), %0\n"
+ " adcl 12(%1), %0\n"
+ "1: adcl 16(%1), %0\n"
+ " lea 4(%1), %1\n"
+ " decl %2\n"
+ " jne 1b\n"
+ " adcl $0, %0\n"
+ " movl %0, %2\n"
+ " shrl $16, %0\n"
+ " addw %w2, %w0\n"
+ " adcl $0, %0\n"
+ " notl %0\n"
+ "2:"
+ /* Since the input registers which are loaded with iph and ipl
+ are modified, we must also specify them as outputs, or gcc
+ will assume they contain their original values. */
+ : "=r" (sum), "=r" (iph), "=r" (ihl)
+ : "1" (iph), "2" (ihl)
+ : "memory");
+ return(sum);
+}
+
+static inline unsigned add32_with_carry(unsigned a, unsigned b)
+{
+ asm("addl %2,%0\n\t"
+ "adcl $0,%0"
+ : "=r" (a)
+ : "0" (a), "r" (b));
+ return a;
+}
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
new file mode 100644
index 000000000000..64b1cc16752d
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_64_PTRACE_H
+#define __SYSDEP_X86_64_PTRACE_H
+
+#include "uml-config.h"
+
+#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])
+#define REGS_SP(r) ((r)[HOST_SP])
+
+#define REGS_RBX(r) ((r)[HOST_RBX])
+#define REGS_RCX(r) ((r)[HOST_RCX])
+#define REGS_RDX(r) ((r)[HOST_RDX])
+#define REGS_RSI(r) ((r)[HOST_RSI])
+#define REGS_RDI(r) ((r)[HOST_RDI])
+#define REGS_RBP(r) ((r)[HOST_RBP])
+#define REGS_RAX(r) ((r)[HOST_RAX])
+#define REGS_R8(r) ((r)[HOST_R8])
+#define REGS_R9(r) ((r)[HOST_R9])
+#define REGS_R10(r) ((r)[HOST_R10])
+#define REGS_R11(r) ((r)[HOST_R11])
+#define REGS_R12(r) ((r)[HOST_R12])
+#define REGS_R13(r) ((r)[HOST_R13])
+#define REGS_R14(r) ((r)[HOST_R14])
+#define REGS_R15(r) ((r)[HOST_R15])
+#define REGS_CS(r) ((r)[HOST_CS])
+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
+#define REGS_SS(r) ((r)[HOST_SS])
+
+#define HOST_FS_BASE 21
+#define HOST_GS_BASE 22
+#define HOST_DS 23
+#define HOST_ES 24
+#define HOST_FS 25
+#define HOST_GS 26
+
+#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE])
+#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE])
+#define REGS_DS(r) ((r)[HOST_DS])
+#define REGS_ES(r) ((r)[HOST_ES])
+#define REGS_FS(r) ((r)[HOST_FS])
+#define REGS_GS(r) ((r)[HOST_GS])
+
+#define REGS_ORIG_RAX(r) ((r)[HOST_ORIG_RAX])
+
+#define REGS_SET_SYSCALL_RETURN(r, res) REGS_RAX(r) = (res)
+
+#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
+
+#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type)
+
+#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
+
+#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
+
+#define REGS_TRAP(r) ((r)->trap_type)
+
+#define REGS_ERR(r) ((r)->fault_type)
+
+#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;
+ } tt;
+#endif
+#ifdef UML_CONFIG_MODE_SKAS
+ struct skas_regs {
+ /* XXX */
+ unsigned long regs[27];
+ unsigned long fp[65];
+ unsigned long fault_addr;
+ unsigned long fault_type;
+ unsigned long trap_type;
+ long syscall;
+ int is_user;
+ } skas;
+#endif
+};
+
+#define EMPTY_UML_PT_REGS { }
+
+/* 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(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_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_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)
+
+extern int user_context(unsigned long sp);
+
+#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)
+#define UPT_SYSCALL_ARG3(r) UPT_RDX(r)
+#define UPT_SYSCALL_ARG4(r) UPT_R10(r)
+#define UPT_SYSCALL_ARG5(r) UPT_R8(r)
+#define UPT_SYSCALL_ARG6(r) UPT_R9(r)
+
+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) } } )
+
+#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 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 val; \
+ switch(reg){ \
+ case R8: UPT_R8(regs) = val; break; \
+ case R9: UPT_R9(regs) = val; break; \
+ case R10: UPT_R10(regs) = val; break; \
+ case R11: UPT_R11(regs) = val; break; \
+ case R12: UPT_R12(regs) = val; break; \
+ case R13: UPT_R13(regs) = val; break; \
+ case R14: UPT_R14(regs) = val; break; \
+ case R15: UPT_R15(regs) = val; break; \
+ case RIP: UPT_IP(regs) = val; break; \
+ case RSP: UPT_SP(regs) = val; break; \
+ case RAX: UPT_RAX(regs) = val; break; \
+ case RBX: UPT_RBX(regs) = val; break; \
+ case RCX: UPT_RCX(regs) = val; break; \
+ case RDX: UPT_RDX(regs) = val; break; \
+ case RSI: UPT_RSI(regs) = val; break; \
+ case RDI: UPT_RDI(regs) = val; break; \
+ case RBP: UPT_RBP(regs) = val; break; \
+ case ORIG_RAX: UPT_ORIG_RAX(regs) = val; break; \
+ case CS: UPT_CS(regs) = val; break; \
+ case DS: UPT_DS(regs) = val; break; \
+ case ES: UPT_ES(regs) = val; break; \
+ case FS: UPT_FS(regs) = val; break; \
+ case GS: UPT_GS(regs) = val; break; \
+ case EFLAGS: UPT_EFLAGS(regs) = val; break; \
+ default : \
+ panic("Bad register in UPT_SET : %d\n", reg); \
+ break; \
+ } \
+ val; \
+ })
+
+#define UPT_SET_SYSCALL_RETURN(r, res) \
+ CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \
+ REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res)))
+
+#define UPT_RESTART_SYSCALL(r) \
+ CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \
+ REGS_RESTART_SYSCALL((r)->skas.regs))
+
+#define UPT_SEGV_IS_FIXABLE(r) \
+ CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \
+ REGS_SEGV_IS_FIXABLE(&r->skas))
+
+#define UPT_FAULT_ADDR(r) \
+ CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas))
+
+#define UPT_FAULT_WRITE(r) \
+ CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas))
+
+#define UPT_TRAP(r) CHOOSE_MODE(SC_TRAP_TYPE(UPT_SC(r)), REGS_TRAP(&r->skas))
+#define UPT_ERR(r) CHOOSE_MODE(SC_FAULT_TYPE(UPT_SC(r)), REGS_ERR(&r->skas))
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/include/sysdep-x86_64/ptrace_user.h b/arch/um/include/sysdep-x86_64/ptrace_user.h
new file mode 100644
index 000000000000..a7bb52bbe624
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/ptrace_user.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_64_PTRACE_USER_H__
+#define __SYSDEP_X86_64_PTRACE_USER_H__
+
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
+#undef __FRAME_OFFSETS
+
+#define PT_INDEX(off) ((off) / sizeof(unsigned long))
+
+#define PT_SYSCALL_NR(regs) ((regs)[PT_INDEX(ORIG_RAX)])
+#define PT_SYSCALL_NR_OFFSET (ORIG_RAX)
+
+#define PT_SYSCALL_ARG1(regs) (((unsigned long *) (regs))[PT_INDEX(RDI)])
+#define PT_SYSCALL_ARG1_OFFSET (RDI)
+
+#define PT_SYSCALL_ARG2(regs) (((unsigned long *) (regs))[PT_INDEX(RSI)])
+#define PT_SYSCALL_ARG2_OFFSET (RSI)
+
+#define PT_SYSCALL_ARG3(regs) (((unsigned long *) (regs))[PT_INDEX(RDX)])
+#define PT_SYSCALL_ARG3_OFFSET (RDX)
+
+#define PT_SYSCALL_ARG4(regs) (((unsigned long *) (regs))[PT_INDEX(RCX)])
+#define PT_SYSCALL_ARG4_OFFSET (RCX)
+
+#define PT_SYSCALL_ARG5(regs) (((unsigned long *) (regs))[PT_INDEX(R8)])
+#define PT_SYSCALL_ARG5_OFFSET (R8)
+
+#define PT_SYSCALL_ARG6(regs) (((unsigned long *) (regs))[PT_INDEX(R9)])
+#define PT_SYSCALL_ARG6_OFFSET (R9)
+
+#define PT_SYSCALL_RET_OFFSET (RAX)
+
+#define PT_IP_OFFSET (RIP)
+#define PT_IP(regs) ((regs)[PT_INDEX(RIP)])
+
+#define PT_SP_OFFSET (RSP)
+#define PT_SP(regs) ((regs)[PT_INDEX(RSP)])
+
+#define PT_ORIG_RAX_OFFSET (ORIG_RAX)
+#define PT_ORIG_RAX(regs) ((regs)[PT_INDEX(ORIG_RAX)])
+
+#define MAX_REG_OFFSET (FRAME_SIZE)
+#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
+
+/* x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though
+ * it's defined in the kernel's include/linux/ptrace.h
+ */
+#ifndef PTRACE_SETOPTIONS
+#define PTRACE_SETOPTIONS 0x4200
+#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/arch/um/include/sysdep-x86_64/sigcontext.h b/arch/um/include/sysdep-x86_64/sigcontext.h
new file mode 100644
index 000000000000..6a0c346b6404
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/sigcontext.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_64_SIGCONTEXT_H
+#define __SYSDEP_X86_64_SIGCONTEXT_H
+
+#include "sc.h"
+
+#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_RAX(sc) = (result)
+
+#define SC_FAULT_ADDR(sc) SC_CR2(sc)
+#define SC_FAULT_TYPE(sc) SC_ERR(sc)
+
+#define FAULT_WRITE(err) ((err) & 2)
+
+#define SC_FAULT_WRITE(sc) FAULT_WRITE(SC_FAULT_TYPE(sc))
+
+#define SC_TRAP_TYPE(sc) 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)
+
+#define SEGV_IS_FIXABLE(trap) ((trap) == 14)
+#define SC_SEGV_IS_FIXABLE(sc) SEGV_IS_FIXABLE(SC_TRAP_TYPE(sc))
+
+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/arch/um/include/sysdep-x86_64/signal.h b/arch/um/include/sysdep-x86_64/signal.h
new file mode 100644
index 000000000000..e5e52756fab4
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/signal.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004 PathScale, Inc
+ * Licensed under the GPL
+ */
+
+#ifndef __X86_64_SIGNAL_H_
+#define __X86_64_SIGNAL_H_
+
+#define ARCH_GET_SIGCONTEXT(sc, sig_addr) \
+ do { \
+ struct ucontext *__uc; \
+ asm("movq %%rdx, %0" : "=r" (__uc)); \
+ sc = (struct sigcontext *) &__uc->uc_mcontext; \
+ } while(0)
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h
new file mode 100644
index 000000000000..65fd494420f9
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/syscalls.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_64_SYSCALLS_H__
+#define __SYSDEP_X86_64_SYSCALLS_H__
+
+#include <linux/msg.h>
+#include <linux/shm.h>
+
+typedef long syscall_handler_t(void);
+
+extern syscall_handler_t *ia32_sys_call_table[];
+
+#define EXECUTE_SYSCALL(syscall, regs) \
+ (((long (*)(long, long, long, long, long, long)) \
+ (*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
+ UPT_SYSCALL_ARG2(&regs->regs), \
+ UPT_SYSCALL_ARG3(&regs->regs), \
+ UPT_SYSCALL_ARG4(&regs->regs), \
+ UPT_SYSCALL_ARG5(&regs->regs), \
+ UPT_SYSCALL_ARG6(&regs->regs)))
+
+extern long old_mmap(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff);
+extern syscall_handler_t wrap_sys_shmat;
+extern syscall_handler_t sys_modify_ldt;
+extern syscall_handler_t sys_arch_prctl;
+
+#define ARCH_SYSCALLS \
+ [ __NR_mmap ] = (syscall_handler_t *) old_mmap, \
+ [ __NR_select ] = (syscall_handler_t *) sys_select, \
+ [ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \
+ [ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \
+ [ __NR_shmget ] = (syscall_handler_t *) sys_shmget, \
+ [ __NR_shmat ] = (syscall_handler_t *) wrap_sys_shmat, \
+ [ __NR_shmctl ] = (syscall_handler_t *) sys_shmctl, \
+ [ __NR_semop ] = (syscall_handler_t *) sys_semop, \
+ [ __NR_semget ] = (syscall_handler_t *) sys_semget, \
+ [ __NR_semctl ] = (syscall_handler_t *) sys_semctl, \
+ [ __NR_shmdt ] = (syscall_handler_t *) sys_shmdt, \
+ [ __NR_msgget ] = (syscall_handler_t *) sys_msgget, \
+ [ __NR_msgsnd ] = (syscall_handler_t *) sys_msgsnd, \
+ [ __NR_msgrcv ] = (syscall_handler_t *) sys_msgrcv, \
+ [ __NR_msgctl ] = (syscall_handler_t *) sys_msgctl, \
+ [ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \
+ [ __NR_tuxcall ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_security ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_epoll_ctl_old ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_epoll_wait_old ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
+ [ __NR_arch_prctl ] = (syscall_handler_t *) sys_arch_prctl, \
+ [ __NR_socket ] = (syscall_handler_t *) sys_socket, \
+ [ __NR_connect ] = (syscall_handler_t *) sys_connect, \
+ [ __NR_accept ] = (syscall_handler_t *) sys_accept, \
+ [ __NR_recvfrom ] = (syscall_handler_t *) sys_recvfrom, \
+ [ __NR_recvmsg ] = (syscall_handler_t *) sys_recvmsg, \
+ [ __NR_sendmsg ] = (syscall_handler_t *) sys_sendmsg, \
+ [ __NR_bind ] = (syscall_handler_t *) sys_bind, \
+ [ __NR_listen ] = (syscall_handler_t *) sys_listen, \
+ [ __NR_getsockname ] = (syscall_handler_t *) sys_getsockname, \
+ [ __NR_getpeername ] = (syscall_handler_t *) sys_getpeername, \
+ [ __NR_socketpair ] = (syscall_handler_t *) sys_socketpair, \
+ [ __NR_sendto ] = (syscall_handler_t *) sys_sendto, \
+ [ __NR_shutdown ] = (syscall_handler_t *) sys_shutdown, \
+ [ __NR_setsockopt ] = (syscall_handler_t *) sys_setsockopt, \
+ [ __NR_getsockopt ] = (syscall_handler_t *) sys_getsockopt, \
+ [ __NR_iopl ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages, \
+ [ __NR_semtimedop ] = (syscall_handler_t *) sys_semtimedop, \
+ [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, \
+ [ 223 ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \
+ [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ 251 ] = (syscall_handler_t *) sys_ni_syscall,
+
+#define LAST_ARCH_SYSCALL 251
+#define NR_syscalls 1024
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
index 0924fcc95f1c..4eb302cbf865 100644
--- a/arch/um/include/um_uaccess.h
+++ b/arch/um/include/um_uaccess.h
@@ -20,19 +20,19 @@
#define access_ok(type, addr, size) \
CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size)
-static inline int verify_area(int type, const void * addr, unsigned long size)
+static inline int verify_area(int type, const void __user *addr, unsigned long size)
{
- return(CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr,
+ return (CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr,
size));
}
-static inline int copy_from_user(void *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));
}
-static inline int copy_to_user(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));
@@ -57,7 +57,7 @@ static inline int copy_to_user(void *to, const void *from, int n)
* and returns @count.
*/
-static inline int strncpy_from_user(char *dst, const char *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));
@@ -89,7 +89,7 @@ static inline int __clear_user(void *mem, int len)
* Returns number of bytes that could not be cleared.
* On success, this will be zero.
*/
-static inline int clear_user(void *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));
}
@@ -105,7 +105,7 @@ static inline int clear_user(void *mem, int len)
* On exception, returns 0.
* If the string is too long, returns a value greater than @n.
*/
-static inline int strnlen_user(const void *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));
}
diff --git a/arch/um/include/uml_uaccess.h b/arch/um/include/uml_uaccess.h
index 785ccd51bbf5..f77eb6428453 100644
--- a/arch/um/include/uml_uaccess.h
+++ b/arch/um/include/uml_uaccess.h
@@ -7,7 +7,7 @@
#define __UML_UACCESS_H__
extern int __do_copy_to_user(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher);
+ void **fault_addr, void **fault_catcher);
extern unsigned long __do_user_copy(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher,
void (*op)(void *to, const void *from,
diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c
index fa50a9b81ca2..669783580fe5 100644
--- a/arch/um/kernel/checksum.c
+++ b/arch/um/kernel/checksum.c
@@ -2,16 +2,16 @@
#include "linux/errno.h"
#include "linux/module.h"
-extern unsigned int arch_csum_partial(const char *buff, int len, int sum);
+unsigned int arch_csum_partial(const char *buff, int len, int sum);
-extern unsigned int csum_partial(char *buff, int len, int sum)
+unsigned int csum_partial(char *buff, int len, int sum)
{
- return(arch_csum_partial(buff, len, sum));
+ return arch_csum_partial(buff, len, sum);
}
EXPORT_SYMBOL(csum_partial);
-unsigned int csum_partial_copy_to(const char *src, char *dst, int len,
+unsigned int csum_partial_copy_to(const char *src, char __user *dst, int len,
int sum, int *err_ptr)
{
if(copy_to_user(dst, src, len)){
@@ -22,7 +22,7 @@ unsigned int csum_partial_copy_to(const char *src, char *dst, int len,
return(arch_csum_partial(src, len, sum));
}
-unsigned int csum_partial_copy_from(const char *src, char *dst, int len,
+unsigned int csum_partial_copy_from(const char __user *src, char *dst, int len,
int sum, int *err_ptr)
{
if(copy_from_user(dst, src, len)){
@@ -30,7 +30,7 @@ unsigned int csum_partial_copy_from(const char *src, char *dst, int len,
return(-1);
}
- return(arch_csum_partial(dst, len, sum));
+ return arch_csum_partial(dst, len, sum);
}
/*
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index 4336240c179a..49ddabe69be7 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -34,7 +34,8 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
extern void log_exec(char **argv, void *tty);
-static long execve1(char *file, char **argv, char **env)
+static long execve1(char *file, char __user * __user *argv,
+ char *__user __user *env)
{
long error;
@@ -51,7 +52,7 @@ static long execve1(char *file, char **argv, char **env)
return(error);
}
-long um_execve(char *file, char **argv, char **env)
+long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
{
long err;
@@ -61,13 +62,14 @@ long um_execve(char *file, char **argv, char **env)
return(err);
}
-long sys_execve(char *file, char **argv, char **env)
+long sys_execve(char *file, char __user *__user *argv,
+ char __user *__user *env)
{
long error;
char *filename;
lock_kernel();
- filename = getname((char *) file);
+ filename = getname((char __user *) file);
error = PTR_ERR(filename);
if (IS_ERR(filename)) goto out;
error = execve1(filename, argv, env);
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index 14a748e2e25a..0ea87f24b36f 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -27,7 +27,7 @@ static int read_proc_exitcode(char *page, char **start, off_t off,
return(len);
}
-static int write_proc_exitcode(struct file *file, const char *buffer,
+static int write_proc_exitcode(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char *end, buf[sizeof("nnnnn\0")];
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 9d572b6ffd1d..ab7417b78c87 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -45,9 +45,8 @@ int show_interrupts(struct seq_file *p, void *v)
if (i == 0) {
seq_printf(p, " ");
- for (j=0; j<NR_CPUS; j++)
- if (cpu_online(j))
- seq_printf(p, "CPU%d ",j);
+ for_each_cpu(j)
+ seq_printf(p, "CPU%d ",j);
seq_putc(p, '\n');
}
@@ -60,9 +59,8 @@ int show_interrupts(struct seq_file *p, void *v)
#ifndef CONFIG_SMP
seq_printf(p, "%10u ", kstat_irqs(i));
#else
- for (j = 0; j < NR_CPUS; j++)
- if (cpu_online(j))
- seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+ for_each_cpu(j)
+ seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
#endif
seq_printf(p, " %14s", irq_desc[i].handler->typename);
seq_printf(p, " %s", action->name);
@@ -154,13 +152,13 @@ void __init init_IRQ(void)
int i;
irq_desc[TIMER_IRQ].status = IRQ_DISABLED;
- irq_desc[TIMER_IRQ].action = 0;
+ irq_desc[TIMER_IRQ].action = NULL;
irq_desc[TIMER_IRQ].depth = 1;
irq_desc[TIMER_IRQ].handler = &SIGVTALRM_irq_type;
enable_irq(TIMER_IRQ);
for(i=1;i<NR_IRQS;i++){
irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
+ irq_desc[i].action = NULL;
irq_desc[i].depth = 1;
irq_desc[i].handler = &SIGIO_irq_type;
enable_irq(i);
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 4279161c8849..b138eca53d06 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -25,7 +25,7 @@ extern char __binary_start;
/* Changed during early boot */
unsigned long *empty_zero_page = NULL;
unsigned long *empty_bad_page = NULL;
-pgd_t swapper_pg_dir[1024];
+pgd_t swapper_pg_dir[PTRS_PER_PGD];
unsigned long highmem;
int kmalloc_ok = 0;
@@ -130,12 +130,13 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
}
}
-#if CONFIG_HIGHMEM
+#ifdef CONFIG_HIGHMEM
pte_t *kmap_pte;
pgprot_t kmap_prot;
#define kmap_get_fixmap_pte(vaddr) \
- pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
+ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\
+ (vaddr)), (vaddr))
void __init kmap_init(void)
{
@@ -172,6 +173,7 @@ static void init_highmem(void)
static void __init fixaddr_user_init( void)
{
+#if FIXADDR_USER_START != 0
long size = FIXADDR_USER_END - FIXADDR_USER_START;
pgd_t *pgd;
pmd_t *pmd;
@@ -191,6 +193,7 @@ static void __init fixaddr_user_init( void)
pte = pte_offset_kernel(pmd, vaddr);
pte_set_val( (*pte), paddr, PAGE_READONLY);
}
+#endif
}
void paging_init(void)
@@ -232,7 +235,7 @@ struct page *arch_validate(struct page *page, int mask, int order)
addr = (unsigned long) page_address(page);
for(i = 0; i < (1 << order); i++){
current->thread.fault_addr = (void *) addr;
- if(__do_copy_to_user((void *) addr, &zero,
+ if(__do_copy_to_user((void __user *) addr, &zero,
sizeof(zero),
&current->thread.fault_addr,
&current->thread.fault_catcher)){
@@ -241,6 +244,7 @@ struct page *arch_validate(struct page *page, int mask, int order)
}
addr += PAGE_SIZE;
}
+
if(i == (1 << order)) return(page);
page = alloc_pages(mask, order);
goto again;
@@ -335,7 +339,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
struct page *pte;
- pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+ pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
return pte;
}
diff --git a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c
index 33f71e764951..4a663fd434bb 100644
--- a/arch/um/kernel/mem_user.c
+++ b/arch/um/kernel/mem_user.c
@@ -48,8 +48,6 @@
#include "tempfile.h"
#include "kern_constants.h"
-extern struct mem_region physmem_region;
-
#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
static int create_tmp_file(unsigned long len)
@@ -135,7 +133,7 @@ static int create_anon_file(unsigned long len)
addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if(addr == MAP_FAILED){
- os_print_error((int) addr, "mapping physmem file");
+ perror("mapping physmem file");
exit(1);
}
munmap(addr, len);
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index 3253bc0e3a5c..2853028657b3 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -309,7 +309,7 @@ struct page *__virt_to_page(const unsigned long virt)
return(&mem_map[__pa(virt) >> PAGE_SHIFT]);
}
-unsigned long page_to_phys(struct page *page)
+phys_t page_to_phys(struct page *page)
{
return((page - mem_map) << PAGE_SHIFT);
}
@@ -318,8 +318,9 @@ pte_t mk_pte(struct page *page, pgprot_t pgprot)
{
pte_t pte;
- pte_val(pte) = page_to_phys(page) + pgprot_val(pgprot);
- if(pte_present(pte)) pte_mknewprot(pte_mknewpage(pte));
+ pte_set_val(pte, page_to_phys(page), pgprot);
+ if(pte_present(pte))
+ pte_mknewprot(pte_mknewpage(pte));
return(pte);
}
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 7460bd36e534..1e638b813199 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -13,14 +13,10 @@
#include <setjmp.h>
#include <sys/time.h>
#include <sys/ptrace.h>
-#include <linux/ptrace.h>
#include <sys/wait.h>
#include <sys/mman.h>
-#include <asm/ptrace.h>
-#include <asm/sigcontext.h>
#include <asm/unistd.h>
#include <asm/page.h>
-#include <asm/user.h>
#include "user_util.h"
#include "kern_util.h"
#include "user.h"
@@ -28,6 +24,7 @@
#include "signal_kern.h"
#include "signal_user.h"
#include "sysdep/ptrace.h"
+#include "sysdep/ptrace_user.h"
#include "sysdep/sigcontext.h"
#include "irq_user.h"
#include "ptrace_user.h"
@@ -40,6 +37,7 @@
#ifdef UML_CONFIG_MODE_SKAS
#include "skas.h"
#include "skas_ptrace.h"
+#include "registers.h"
#endif
void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
@@ -330,7 +328,7 @@ void __init check_ptrace(void)
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if(n < 0)
panic("check_ptrace : wait failed, errno = %d", errno);
- if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP + 0x80)))
+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP + 0x80))
panic("check_ptrace : expected SIGTRAP + 0x80, "
"got status = %d", status);
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 2af5a343cf1c..8d003f351eb3 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -235,18 +235,28 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
pte_t *pte_out)
{
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
pte_t *pte;
if(task->mm == NULL)
return(ERR_PTR(-EINVAL));
pgd = pgd_offset(task->mm, addr);
- pmd = pmd_offset(pgd, addr);
+ if(!pgd_present(*pgd))
+ return(ERR_PTR(-EINVAL));
+
+ pud = pud_offset(pgd, addr);
+ if(!pud_present(*pud))
+ return(ERR_PTR(-EINVAL));
+
+ pmd = pmd_offset(pud, addr);
if(!pmd_present(*pmd))
return(ERR_PTR(-EINVAL));
+
pte = pte_offset_kernel(pmd, addr);
if(!pte_present(*pte))
return(ERR_PTR(-EINVAL));
+
if(pte_out != NULL)
*pte_out = *pte;
return((void *) (pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK));
@@ -358,22 +368,22 @@ void *get_init_task(void)
return(&init_thread_union.thread_info.task);
}
-int copy_to_user_proc(void *to, void *from, int size)
+int copy_to_user_proc(void __user *to, void *from, int size)
{
return(copy_to_user(to, from, size));
}
-int copy_from_user_proc(void *to, void *from, int size)
+int copy_from_user_proc(void *to, void __user *from, int size)
{
return(copy_from_user(to, from, size));
}
-int clear_user_proc(void *buf, int size)
+int clear_user_proc(void __user *buf, int size)
{
return(clear_user(buf, size));
}
-int strlen_user_proc(char *str)
+int strlen_user_proc(char __user *str)
{
return(strlen_user(str));
}
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index daf1cb54d023..0d8e76969600 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -16,6 +16,7 @@
#include "asm/uaccess.h"
#include "kern_util.h"
#include "ptrace_user.h"
+#include "skas_ptrace.h"
/*
* Called by kernel/ptrace.c when detaching..
@@ -80,7 +81,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
if (copied != sizeof(tmp))
break;
- ret = put_user(tmp,(unsigned long *) data);
+ ret = put_user(tmp, (unsigned long __user *) data);
break;
}
@@ -102,7 +103,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
addr = addr >> 2;
tmp = child->thread.arch.debugregs[addr];
}
- ret = put_user(tmp, (unsigned long *) data);
+ ret = put_user(tmp, (unsigned long __user *) data);
break;
}
@@ -200,7 +201,8 @@ long sys_ptrace(long request, long pid, long addr, long data)
break;
}
for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) {
- __put_user(getreg(child, i), (unsigned long *) data);
+ __put_user(getreg(child, i),
+ (unsigned long __user *) data);
data += sizeof(long);
}
ret = 0;
@@ -216,7 +218,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
break;
}
for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) {
- __get_user(tmp, (unsigned long *) data);
+ __get_user(tmp, (unsigned long __user *) data);
putreg(child, i, tmp);
data += sizeof(long);
}
@@ -250,14 +252,14 @@ long sys_ptrace(long request, long pid, long addr, long data)
fault = ((struct ptrace_faultinfo)
{ .is_write = child->thread.err,
.addr = child->thread.cr2 });
- ret = copy_to_user((unsigned long *) data, &fault,
+ ret = copy_to_user((unsigned long __user *) data, &fault,
sizeof(fault));
if(ret)
break;
break;
}
case PTRACE_SIGPENDING:
- ret = copy_to_user((unsigned long *) data,
+ ret = copy_to_user((unsigned long __user *) data,
&child->pending.signal,
sizeof(child->pending.signal));
break;
@@ -265,7 +267,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_LDT: {
struct ptrace_ldt ldt;
- if(copy_from_user(&ldt, (unsigned long *) data,
+ if(copy_from_user(&ldt, (unsigned long __user *) data,
sizeof(ldt))){
ret = -EIO;
break;
@@ -306,6 +308,25 @@ long sys_ptrace(long request, long pid, long addr, long data)
return ret;
}
+void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs,
+ int error_code)
+{
+ struct siginfo info;
+
+ memset(&info, 0, sizeof(info));
+ info.si_signo = SIGTRAP;
+ info.si_code = TRAP_BRKPT;
+
+ /* User-mode eip? */
+ info.si_addr = UPT_IS_USER(regs) ? (void __user *) UPT_IP(regs) : NULL;
+
+ /* Send us the fakey SIGTRAP */
+ force_sig_info(SIGTRAP, &info, tsk);
+}
+
+/* XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and
+ * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check
+ */
void syscall_trace(union uml_pt_regs *regs, int entryexit)
{
int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit;
@@ -320,14 +341,19 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
audit_syscall_exit(current, regs->eax);
}
- if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_singlestep)
+ /* Fake a debug trap */
+ if (is_singlestep)
+ send_sigtrap(current, regs, 0);
+
+ if (!test_thread_flag(TIF_SYSCALL_TRACE))
return;
+
if (!(current->ptrace & PT_PTRACED))
return;
/* the 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
- tracesysgood = (current->ptrace & PT_TRACESYSGOOD) && !is_singlestep;
+ tracesysgood = (current->ptrace & PT_TRACESYSGOOD);
ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0));
if (entryexit) /* force do_signal() --> is_syscall() */
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
index 2a5b9b8ef3f8..7807a3e8c426 100644
--- a/arch/um/kernel/signal_kern.c
+++ b/arch/um/kernel/signal_kern.c
@@ -74,10 +74,12 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
sp = current->sas_ss_sp + current->sas_ss_size;
- if(ka->sa.sa_flags & SA_SIGINFO)
- err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);
- else
+#ifdef CONFIG_ARCH_HAS_SC_SIGNALS
+ 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){
spin_lock_irq(&current->sighand->siglock);
@@ -194,38 +196,7 @@ long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
}
}
-int sys_sigaction(int sig, const struct old_sigaction __user *act,
- struct old_sigaction __user *oact)
-{
- struct k_sigaction new_ka, old_ka;
- int ret;
-
- if (act) {
- old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
- return -EFAULT;
- __get_user(new_ka.sa.sa_flags, &act->sa_flags);
- __get_user(mask, &act->sa_mask);
- siginitset(&new_ka.sa.sa_mask, mask);
- }
-
- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
- if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
- return -EFAULT;
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
- }
-
- return ret;
-}
-
-long sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
{
return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
}
diff --git a/arch/um/kernel/signal_user.c b/arch/um/kernel/signal_user.c
index 2468cd6a625d..62f457835fb1 100644
--- a/arch/um/kernel/signal_user.c
+++ b/arch/um/kernel/signal_user.c
@@ -41,6 +41,7 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
while((mask = va_arg(ap, int)) != -1){
sigaddset(&action.sa_mask, mask);
}
+ va_end(ap);
action.sa_flags = flags;
action.sa_restorer = NULL;
if(sigaction(sig, &action, NULL) < 0)
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index d7b61cba9448..c340c9cbf19b 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -6,8 +6,6 @@
obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o \
-subdir-y := util
-
USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
diff --git a/arch/um/kernel/skas/include/ptrace-skas.h b/arch/um/kernel/skas/include/ptrace-skas.h
deleted file mode 100644
index f5c5268cc492..000000000000
--- a/arch/um/kernel/skas/include/ptrace-skas.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __PTRACE_SKAS_H
-#define __PTRACE_SKAS_H
-
-#include "uml-config.h"
-
-#ifdef UML_CONFIG_MODE_SKAS
-
-#include "skas_ptregs.h"
-
-#define HOST_FRAME_SIZE 17
-
-#define REGS_IP(r) ((r)[HOST_IP])
-#define REGS_SP(r) ((r)[HOST_SP])
-#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
-#define REGS_EAX(r) ((r)[HOST_EAX])
-#define REGS_EBX(r) ((r)[HOST_EBX])
-#define REGS_ECX(r) ((r)[HOST_ECX])
-#define REGS_EDX(r) ((r)[HOST_EDX])
-#define REGS_ESI(r) ((r)[HOST_ESI])
-#define REGS_EDI(r) ((r)[HOST_EDI])
-#define REGS_EBP(r) ((r)[HOST_EBP])
-#define REGS_CS(r) ((r)[HOST_CS])
-#define REGS_SS(r) ((r)[HOST_SS])
-#define REGS_DS(r) ((r)[HOST_DS])
-#define REGS_ES(r) ((r)[HOST_ES])
-#define REGS_FS(r) ((r)[HOST_FS])
-#define REGS_GS(r) ((r)[HOST_GS])
-
-#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res)
-
-#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
-
-#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type)
-
-#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
-
-#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
-
-#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/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index 2f6eaa37455d..1c7fcd3effc2 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -29,10 +29,7 @@ extern int protect(int fd, unsigned long addr, unsigned long len,
int r, int w, int x, int must_succeed);
extern void user_signal(int sig, union uml_pt_regs *regs);
extern int new_mm(int from);
-extern void save_registers(union uml_pt_regs *regs);
-extern void restore_registers(union uml_pt_regs *regs);
extern void start_userspace(int cpu);
-extern void init_registers(int pid);
#endif
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
index ec169a86cdbe..438db2f43456 100644
--- a/arch/um/kernel/skas/mem.c
+++ b/arch/um/kernel/skas/mem.c
@@ -13,8 +13,13 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
/* Round up to the nearest 4M */
unsigned long top = ROUND_4M((unsigned long) &arg);
+#ifdef CONFIG_HOST_TASK_SIZE
+ *host_size_out = CONFIG_HOST_TASK_SIZE;
+ *task_size_out = CONFIG_HOST_TASK_SIZE;
+#else
*host_size_out = top;
*task_size_out = top;
+#endif
return(((unsigned long) set_task_sizes_skas) & ~0xffffff);
}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 247b06d09c59..6b1acc66ff94 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -28,6 +28,7 @@
#include "skas_ptrace.h"
#include "chan_user.h"
#include "signal_user.h"
+#include "registers.h"
int is_skas_winch(int pid, int fd, void *data)
{
@@ -38,13 +39,6 @@ int is_skas_winch(int pid, int fd, void *data)
return(1);
}
-/* These are set once at boot time and not changed thereafter */
-
-unsigned long exec_regs[FRAME_SIZE];
-unsigned long exec_fp_regs[HOST_FP_SIZE];
-unsigned long exec_fpx_regs[HOST_XFP_SIZE];
-int have_fpx_regs = 1;
-
static void handle_segv(int pid)
{
struct ptrace_faultinfo fault;
@@ -79,7 +73,8 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu
"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))
panic("handle_trap - failed to wait at end of syscall, "
"errno = %d, status = %d\n", errno, status);
}
@@ -97,6 +92,7 @@ static int userspace_tramp(void *arg)
}
/* Each element set once, and only accessed by a single processor anyway */
+#undef NR_CPUS
#define NR_CPUS 1
int userspace_pid[NR_CPUS];
@@ -143,7 +139,7 @@ void userspace(union uml_pt_regs *regs)
int err, status, op, pid = userspace_pid[0];
int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
- restore_registers(regs);
+ restore_registers(pid, regs);
local_using_sysemu = get_using_sysemu();
@@ -160,7 +156,7 @@ void userspace(union uml_pt_regs *regs)
errno);
regs->skas.is_user = 1;
- save_registers(regs);
+ save_registers(pid, regs);
UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
if(WIFSTOPPED(status)){
@@ -192,7 +188,7 @@ void userspace(union uml_pt_regs *regs)
PT_SYSCALL_NR(regs->skas.regs) = -1;
}
- restore_registers(regs);
+ restore_registers(pid, regs);
/*Now we ended the syscall, so re-read local_using_sysemu.*/
local_using_sysemu = get_using_sysemu();
@@ -243,58 +239,6 @@ void thread_wait(void *sw, void *fb)
siglongjmp(*fork_buf, 1);
}
-static int move_registers(int pid, int int_op, int fp_op,
- union uml_pt_regs *regs, unsigned long *fp_regs)
-{
- if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
- return(-errno);
- if(ptrace(fp_op, pid, 0, fp_regs) < 0)
- return(-errno);
- return(0);
-}
-
-void save_registers(union uml_pt_regs *regs)
-{
- 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(userspace_pid[0], PTRACE_GETREGS, fp_op, regs,
- fp_regs);
- if(err)
- panic("save_registers - saving registers failed, errno = %d\n",
- -err);
-}
-
-void restore_registers(union uml_pt_regs *regs)
-{
- unsigned long *fp_regs;
- int err, fp_op;
-
- 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(userspace_pid[0], PTRACE_SETREGS, fp_op, regs,
- fp_regs);
- if(err)
- panic("restore_registers - saving registers failed, "
- "errno = %d\n", -err);
-}
-
void switch_threads(void *me, void *next)
{
sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
@@ -394,29 +338,6 @@ void kill_off_processes_skas(void)
os_kill_ptraced_process(userspace_pid[0], 1);
}
-void init_registers(int pid)
-{
- int err;
-
- if(ptrace(PTRACE_GETREGS, pid, 0, exec_regs) < 0)
- panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
- errno);
-
- err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs);
- if(!err)
- return;
-
- have_fpx_regs = 0;
- if(errno != EIO)
- panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
- errno);
-
- err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
- if(err)
- panic("check_ptrace : PTRACE_GETFPREGS 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
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 648955b0476f..5d096ea63b97 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -22,6 +22,7 @@
#include "kern.h"
#include "mode.h"
#include "proc_mm.h"
+#include "registers.h"
void *switch_to_skas(void *prev, void *next)
{
@@ -118,12 +119,7 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
handler = fork_handler;
}
else {
- memcpy(p->thread.regs.regs.skas.regs, exec_regs,
- sizeof(p->thread.regs.regs.skas.regs));
- memcpy(p->thread.regs.regs.skas.fp, exec_fp_regs,
- sizeof(p->thread.regs.regs.skas.fp));
- memcpy(p->thread.regs.regs.skas.xfp, exec_fpx_regs,
- sizeof(p->thread.regs.regs.skas.xfp));
+ init_thread_registers(&p->thread.regs.regs);
p->thread.request.u.thread = current->thread.request.u.thread;
handler = new_thread_handler;
}
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
index 02e3e06bb033..956fb0102a1e 100644
--- a/arch/um/kernel/skas/tlb.c
+++ b/arch/um/kernel/skas/tlb.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright 2003 PathScale, Inc.
* Licensed under the GPL
*/
@@ -18,52 +19,86 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
unsigned long end_addr, int force)
{
pgd_t *npgd;
+ pud_t *npud;
pmd_t *npmd;
pte_t *npte;
- unsigned long addr;
+ unsigned long addr, end;
int r, w, x, err, fd;
if(mm == NULL) return;
fd = mm->context.skas.mm_fd;
for(addr = start_addr; addr < end_addr;){
npgd = pgd_offset(mm, addr);
- npmd = pmd_offset(npgd, addr);
- if(pmd_present(*npmd)){
- npte = pte_offset_kernel(npmd, addr);
- r = pte_read(*npte);
- w = pte_write(*npte);
- x = pte_exec(*npte);
- if(!pte_dirty(*npte)) w = 0;
- if(!pte_young(*npte)){
- r = 0;
- w = 0;
- }
- if(force || pte_newpage(*npte)){
- err = unmap(fd, (void *) addr, PAGE_SIZE);
+ if(!pgd_present(*npgd)){
+ if(force || pgd_newpage(*npgd)){
+ end = addr + PGDIR_SIZE;
+ if(end > end_addr)
+ end = end_addr;
+ err = unmap(fd, (void *) addr, end - addr);
if(err < 0)
panic("munmap failed, errno = %d\n",
-err);
- if(pte_present(*npte))
- map(fd, addr,
- pte_val(*npte) & PAGE_MASK,
- PAGE_SIZE, r, w, x);
+ pgd_mkuptodate(*npgd);
}
- else if(pte_newprot(*npte)){
- protect(fd, addr, PAGE_SIZE, r, w, x, 1);
+ addr += PGDIR_SIZE;
+ continue;
+ }
+
+ npud = pud_offset(npgd, addr);
+ if(!pud_present(*npud)){
+ if(force || pud_newpage(*npud)){
+ end = addr + PUD_SIZE;
+ if(end > end_addr)
+ end = end_addr;
+ err = unmap(fd, (void *) addr, end - addr);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ pud_mkuptodate(*npud);
}
- *npte = pte_mkuptodate(*npte);
- addr += PAGE_SIZE;
+ addr += PUD_SIZE;
+ continue;
}
- else {
+
+ npmd = pmd_offset(npud, addr);
+ if(!pmd_present(*npmd)){
if(force || pmd_newpage(*npmd)){
- err = unmap(fd, (void *) addr, PMD_SIZE);
+ end = addr + PMD_SIZE;
+ if(end > end_addr)
+ end = end_addr;
+ err = unmap(fd, (void *) addr, end - addr);
if(err < 0)
panic("munmap failed, errno = %d\n",
-err);
pmd_mkuptodate(*npmd);
}
addr += PMD_SIZE;
+ continue;
+ }
+
+ npte = pte_offset_kernel(npmd, addr);
+ r = pte_read(*npte);
+ w = pte_write(*npte);
+ x = pte_exec(*npte);
+ if(!pte_dirty(*npte))
+ w = 0;
+ if(!pte_young(*npte)){
+ r = 0;
+ w = 0;
+ }
+ if(force || pte_newpage(*npte)){
+ err = unmap(fd, (void *) addr, PAGE_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n", -err);
+ if(pte_present(*npte))
+ map(fd, addr, pte_val(*npte) & PAGE_MASK,
+ PAGE_SIZE, r, w, x);
}
+ else if(pte_newprot(*npte))
+ protect(fd, addr, PAGE_SIZE, r, w, x, 1);
+
+ *npte = pte_mkuptodate(*npte);
+ addr += PAGE_SIZE;
}
}
@@ -71,45 +106,82 @@ void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end)
{
struct mm_struct *mm;
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
pte_t *pte;
- unsigned long addr;
+ unsigned long addr, last;
int updated = 0, err;
mm = &init_mm;
for(addr = start; addr < end;){
pgd = pgd_offset(mm, addr);
- pmd = pmd_offset(pgd, addr);
- if(pmd_present(*pmd)){
- pte = pte_offset_kernel(pmd, addr);
- if(!pte_present(*pte) || pte_newpage(*pte)){
+ pud = pud_offset(pgd, addr);
+ pmd = pmd_offset(pud, addr);
+ if(!pgd_present(*pgd)){
+ if(pgd_newpage(*pgd)){
updated = 1;
+ last = addr + PGDIR_SIZE;
+ if(last > end)
+ last = end;
err = os_unmap_memory((void *) addr,
- PAGE_SIZE);
+ last - addr);
if(err < 0)
panic("munmap failed, errno = %d\n",
-err);
- if(pte_present(*pte))
- map_memory(addr,
- pte_val(*pte) & PAGE_MASK,
- PAGE_SIZE, 1, 1, 1);
}
- else if(pte_newprot(*pte)){
+ addr += PGDIR_SIZE;
+ continue;
+ }
+
+ pud = pud_offset(pgd, addr);
+ if(!pud_present(*pud)){
+ if(pud_newpage(*pud)){
updated = 1;
- protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
+ last = addr + PUD_SIZE;
+ if(last > end)
+ last = end;
+ err = os_unmap_memory((void *) addr,
+ last - addr);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
}
- addr += PAGE_SIZE;
+ addr += PUD_SIZE;
+ continue;
}
- else {
+
+ pmd = pmd_offset(pud, addr);
+ if(!pmd_present(*pmd)){
if(pmd_newpage(*pmd)){
updated = 1;
- err = os_unmap_memory((void *) addr, PMD_SIZE);
+ last = addr + PMD_SIZE;
+ if(last > end)
+ last = end;
+ err = os_unmap_memory((void *) addr,
+ last - addr);
if(err < 0)
panic("munmap failed, errno = %d\n",
-err);
}
addr += PMD_SIZE;
+ continue;
+ }
+
+ pte = pte_offset_kernel(pmd, addr);
+ if(!pte_present(*pte) || pte_newpage(*pte)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr, PAGE_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n", -err);
+ if(pte_present(*pte))
+ map_memory(addr, pte_val(*pte) & PAGE_MASK,
+ PAGE_SIZE, 1, 1, 1);
}
+ else if(pte_newprot(*pte)){
+ updated = 1;
+ protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
+ }
+ addr += PAGE_SIZE;
}
}
diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c
index 96593709a6e1..09248772de60 100644
--- a/arch/um/kernel/skas/trap_user.c
+++ b/arch/um/kernel/skas/trap_user.c
@@ -5,7 +5,6 @@
#include <signal.h>
#include <errno.h>
-#include <asm/sigcontext.h>
#include "sysdep/ptrace.h"
#include "signal_user.h"
#include "user_util.h"
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 77048cd6775c..c8e5fe49583a 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -54,15 +54,23 @@ static int do_op(unsigned long addr, int len, int is_write,
static void do_buffer_op(void *jmpbuf, void *arg_ptr)
{
- va_list args = *((va_list *) arg_ptr);
- unsigned long addr = va_arg(args, unsigned long);
- int len = va_arg(args, int);
- int is_write = va_arg(args, int);
- int (*op)(unsigned long, int, void *) = va_arg(args, void *);
- void *arg = va_arg(args, void *);
- int *res = va_arg(args, int *);
- int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
- int remain = len, n;
+ va_list args;
+ unsigned long addr;
+ int len, is_write, size, remain, n;
+ int (*op)(unsigned long, int, void *);
+ void *arg;
+ int *res;
+
+ va_copy(args, *(va_list *)arg_ptr);
+ addr = va_arg(args, unsigned long);
+ len = va_arg(args, int);
+ is_write = va_arg(args, int);
+ op = va_arg(args, void *);
+ arg = va_arg(args, void *);
+ res = va_arg(args, int *);
+ va_end(args);
+ size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
+ remain = len;
current->thread.fault_catcher = jmpbuf;
n = do_op(addr, size, is_write, op, arg);
@@ -124,10 +132,10 @@ static int copy_chunk_from_user(unsigned long from, int len, void *arg)
return(0);
}
-int copy_from_user_skas(void *to, const void *from, int n)
+int copy_from_user_skas(void *to, const void __user *from, int n)
{
if(segment_eq(get_fs(), KERNEL_DS)){
- memcpy(to, from, n);
+ memcpy(to, (__force void*)from, n);
return(0);
}
@@ -145,10 +153,10 @@ static int copy_chunk_to_user(unsigned long to, int len, void *arg)
return(0);
}
-int copy_to_user_skas(void *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(to, from, n);
+ memcpy((__force void*)to, from, n);
return(0);
}
@@ -171,13 +179,13 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
return(0);
}
-int strncpy_from_user_skas(char *dst, const char *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, src, count);
+ strncpy(dst, (__force void*)src, count);
return(strnlen(dst, count));
}
@@ -197,15 +205,15 @@ static int clear_chunk(unsigned long addr, int len, void *unused)
return(0);
}
-int __clear_user_skas(void *mem, int len)
+int __clear_user_skas(void __user *mem, int len)
{
return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL));
}
-int clear_user_skas(void *mem, int len)
+int clear_user_skas(void __user *mem, int len)
{
if(segment_eq(get_fs(), KERNEL_DS)){
- memset(mem, 0, len);
+ memset((__force void*)mem, 0, len);
return(0);
}
@@ -225,12 +233,12 @@ static int strnlen_chunk(unsigned long str, int len, void *arg)
return(0);
}
-int strnlen_user_skas(const void *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(str, len) + 1);
+ return(strnlen((__force char*)str, len) + 1);
n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count);
if(n == 0)
diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile
index a26e0c34a762..17f5909d60f7 100644
--- a/arch/um/kernel/skas/util/Makefile
+++ b/arch/um/kernel/skas/util/Makefile
@@ -1,2 +1,4 @@
hostprogs-y := mk_ptregs
always := $(hostprogs-y)
+
+mk_ptregs-objs := mk_ptregs-$(SUBARCH).o
diff --git a/arch/um/kernel/skas/util/mk_ptregs.c b/arch/um/kernel/skas/util/mk_ptregs-i386.c
index 116f74d2c334..0788dd05bcac 100644
--- a/arch/um/kernel/skas/util/mk_ptregs.c
+++ b/arch/um/kernel/skas/util/mk_ptregs-i386.c
@@ -13,9 +13,9 @@ int main(int argc, char **argv)
printf("#define __SKAS_PT_REGS_\n");
printf("\n");
printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE);
- printf("#define HOST_FP_SIZE %d\n",
+ printf("#define HOST_FP_SIZE %d\n",
sizeof(struct user_i387_struct) / sizeof(unsigned long));
- printf("#define HOST_XFP_SIZE %d\n",
+ printf("#define HOST_XFP_SIZE %d\n",
sizeof(struct user_fxsr_struct) / sizeof(unsigned long));
PRINT_REG("IP", EIP);
diff --git a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
new file mode 100644
index 000000000000..67aee92a70ef
--- /dev/null
+++ b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include <stdio.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
+
+#define PRINT_REG(name, val) \
+ printf("#define HOST_%s (%d / sizeof(unsigned long))\n", (name), (val))
+
+int main(int argc, char **argv)
+{
+ printf("/* Automatically generated by "
+ "arch/um/kernel/skas/util/mk_ptregs */\n");
+ printf("\n");
+ printf("#ifndef __SKAS_PT_REGS_\n");
+ printf("#define __SKAS_PT_REGS_\n");
+ printf("#define HOST_FRAME_SIZE (%d / sizeof(unsigned long))\n",
+ FRAME_SIZE);
+ PRINT_REG("RBX", RBX);
+ PRINT_REG("RCX", RCX);
+ PRINT_REG("RDI", RDI);
+ PRINT_REG("RSI", RSI);
+ PRINT_REG("RDX", RDX);
+ PRINT_REG("RBP", RBP);
+ PRINT_REG("RAX", RAX);
+ PRINT_REG("R8", R8);
+ PRINT_REG("R9", R9);
+ PRINT_REG("R10", R10);
+ PRINT_REG("R11", R11);
+ PRINT_REG("R12", R12);
+ PRINT_REG("R13", R13);
+ PRINT_REG("R14", R14);
+ PRINT_REG("R15", R15);
+ PRINT_REG("ORIG_RAX", ORIG_RAX);
+ PRINT_REG("CS", CS);
+ PRINT_REG("SS", SS);
+ PRINT_REG("EFLAGS", EFLAGS);
+#if 0
+ PRINT_REG("FS", FS);
+ PRINT_REG("GS", GS);
+ PRINT_REG("DS", DS);
+ PRINT_REG("ES", ES);
+#endif
+
+ PRINT_REG("IP", RIP);
+ PRINT_REG("SP", RSP);
+ printf("#define HOST_FP_SIZE 0\n");
+ printf("#define HOST_XFP_SIZE 0\n");
+ printf("\n");
+ printf("\n");
+ printf("#endif\n");
+ 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/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index b5e66b291cc3..abe892be6cfe 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -247,10 +247,8 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
func = _func;
info = _info;
- for (i=0;i<NR_CPUS;i++)
- if((i != current_thread->cpu) &&
- cpu_isset(i, cpu_online_map))
- os_write_file(cpu_data[i].ipi_pipe[1], "C", 1);
+ for_each_cpu(i)
+ os_write_file(cpu_data[i].ipi_pipe[1], "C", 1);
while (atomic_read(&scf_started) != cpus)
barrier();
diff --git a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c
index 314925365cf5..b09266a012c1 100644
--- a/arch/um/kernel/sys_call_table.c
+++ b/arch/um/kernel/sys_call_table.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright 2003 PathScale, Inc.
* Licensed under the GPL
*/
@@ -19,7 +20,7 @@
#define NFSSERVCTL sys_ni_syscall
#endif
-#define LAST_GENERIC_SYSCALL __NR_vserver
+#define LAST_GENERIC_SYSCALL __NR_vperfctr_read
#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
#define LAST_SYSCALL LAST_GENERIC_SYSCALL
@@ -32,7 +33,6 @@ extern syscall_handler_t sys_execve;
extern syscall_handler_t um_time;
extern syscall_handler_t um_mount;
extern syscall_handler_t um_stime;
-extern syscall_handler_t sys_ptrace;
extern syscall_handler_t sys_pipe;
extern syscall_handler_t sys_olduname;
extern syscall_handler_t sys_sigaction;
@@ -43,269 +43,249 @@ extern syscall_handler_t sys_ipc;
extern syscall_handler_t sys_sigreturn;
extern syscall_handler_t sys_clone;
extern syscall_handler_t sys_rt_sigreturn;
-extern syscall_handler_t sys_rt_sigaction;
extern syscall_handler_t sys_sigaltstack;
extern syscall_handler_t sys_vfork;
-extern syscall_handler_t sys_mmap2;
-extern syscall_handler_t old_mmap_i386;
extern syscall_handler_t old_select;
extern syscall_handler_t sys_modify_ldt;
extern syscall_handler_t sys_rt_sigsuspend;
+extern syscall_handler_t sys_vserver;
+extern syscall_handler_t sys_mbind;
+extern syscall_handler_t sys_get_mempolicy;
+extern syscall_handler_t sys_set_mempolicy;
+extern syscall_handler_t sys_sys_kexec_load;
+extern syscall_handler_t sys_sys_setaltroot;
+extern syscall_handler_t sys_vperfctr_open;
+extern syscall_handler_t sys_vperfctr_control;
+extern syscall_handler_t sys_vperfctr_unlink;
+extern syscall_handler_t sys_vperfctr_iresume;
+extern syscall_handler_t sys_vperfctr_read;
syscall_handler_t *sys_call_table[] = {
[ __NR_restart_syscall ] = (syscall_handler_t *) sys_restart_syscall,
- [ __NR_exit ] (syscall_handler_t *) sys_exit,
- [ __NR_fork ] (syscall_handler_t *) sys_fork,
+ [ __NR_exit ] = (syscall_handler_t *) sys_exit,
+ [ __NR_fork ] = (syscall_handler_t *) sys_fork,
[ __NR_read ] = (syscall_handler_t *) sys_read,
[ __NR_write ] = (syscall_handler_t *) sys_write,
/* These three are declared differently in asm/unistd.h */
[ __NR_open ] = (syscall_handler_t *) sys_open,
[ __NR_close ] = (syscall_handler_t *) sys_close,
- [ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid,
- [ __NR_creat ] (syscall_handler_t *) sys_creat,
- [ __NR_link ] (syscall_handler_t *) sys_link,
- [ __NR_unlink ] (syscall_handler_t *) sys_unlink,
+ [ __NR_creat ] = (syscall_handler_t *) sys_creat,
+ [ __NR_link ] = (syscall_handler_t *) sys_link,
+ [ __NR_unlink ] = (syscall_handler_t *) sys_unlink,
[ __NR_execve ] = (syscall_handler_t *) sys_execve,
/* declared differently in kern_util.h */
- [ __NR_chdir ] (syscall_handler_t *) sys_chdir,
+ [ __NR_chdir ] = (syscall_handler_t *) sys_chdir,
[ __NR_time ] = um_time,
- [ __NR_mknod ] (syscall_handler_t *) sys_mknod,
- [ __NR_chmod ] (syscall_handler_t *) sys_chmod,
- [ __NR_lchown ] (syscall_handler_t *) sys_lchown16,
- [ __NR_break ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_oldstat ] (syscall_handler_t *) sys_stat,
+ [ __NR_mknod ] = (syscall_handler_t *) sys_mknod,
+ [ __NR_chmod ] = (syscall_handler_t *) sys_chmod,
+ [ __NR_lchown ] = (syscall_handler_t *) sys_lchown16,
[ __NR_lseek ] = (syscall_handler_t *) sys_lseek,
- [ __NR_getpid ] (syscall_handler_t *) sys_getpid,
+ [ __NR_getpid ] = (syscall_handler_t *) sys_getpid,
[ __NR_mount ] = um_mount,
- [ __NR_umount ] (syscall_handler_t *) sys_oldumount,
- [ __NR_setuid ] (syscall_handler_t *) sys_setuid16,
- [ __NR_getuid ] (syscall_handler_t *) sys_getuid16,
- [ __NR_stime ] = um_stime,
- [ __NR_ptrace ] (syscall_handler_t *) sys_ptrace,
- [ __NR_alarm ] (syscall_handler_t *) sys_alarm,
- [ __NR_oldfstat ] (syscall_handler_t *) sys_fstat,
- [ __NR_pause ] (syscall_handler_t *) sys_pause,
- [ __NR_utime ] (syscall_handler_t *) sys_utime,
- [ __NR_stty ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_gtty ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_access ] (syscall_handler_t *) sys_access,
- [ __NR_nice ] (syscall_handler_t *) sys_nice,
- [ __NR_ftime ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_sync ] (syscall_handler_t *) sys_sync,
- [ __NR_kill ] (syscall_handler_t *) sys_kill,
- [ __NR_rename ] (syscall_handler_t *) sys_rename,
- [ __NR_mkdir ] (syscall_handler_t *) sys_mkdir,
- [ __NR_rmdir ] (syscall_handler_t *) sys_rmdir,
+ [ __NR_setuid ] = (syscall_handler_t *) sys_setuid16,
+ [ __NR_getuid ] = (syscall_handler_t *) sys_getuid16,
+ [ __NR_ptrace ] = (syscall_handler_t *) sys_ptrace,
+ [ __NR_alarm ] = (syscall_handler_t *) sys_alarm,
+ [ __NR_pause ] = (syscall_handler_t *) sys_pause,
+ [ __NR_utime ] = (syscall_handler_t *) sys_utime,
+ [ __NR_access ] = (syscall_handler_t *) sys_access,
+ [ __NR_sync ] = (syscall_handler_t *) sys_sync,
+ [ __NR_kill ] = (syscall_handler_t *) sys_kill,
+ [ __NR_rename ] = (syscall_handler_t *) sys_rename,
+ [ __NR_mkdir ] = (syscall_handler_t *) sys_mkdir,
+ [ __NR_rmdir ] = (syscall_handler_t *) sys_rmdir,
/* Declared differently in asm/unistd.h */
[ __NR_dup ] = (syscall_handler_t *) sys_dup,
- [ __NR_pipe ] (syscall_handler_t *) sys_pipe,
- [ __NR_times ] (syscall_handler_t *) sys_times,
- [ __NR_prof ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_brk ] (syscall_handler_t *) sys_brk,
- [ __NR_setgid ] (syscall_handler_t *) sys_setgid16,
- [ __NR_getgid ] (syscall_handler_t *) sys_getgid16,
- [ __NR_signal ] (syscall_handler_t *) sys_signal,
- [ __NR_geteuid ] (syscall_handler_t *) sys_geteuid16,
- [ __NR_getegid ] (syscall_handler_t *) sys_getegid16,
- [ __NR_acct ] (syscall_handler_t *) sys_acct,
- [ __NR_umount2 ] (syscall_handler_t *) sys_umount,
- [ __NR_lock ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_ioctl ] (syscall_handler_t *) sys_ioctl,
- [ __NR_fcntl ] (syscall_handler_t *) sys_fcntl,
- [ __NR_mpx ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_setpgid ] (syscall_handler_t *) sys_setpgid,
- [ __NR_ulimit ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_oldolduname ] (syscall_handler_t *) sys_olduname,
- [ __NR_umask ] (syscall_handler_t *) sys_umask,
- [ __NR_chroot ] (syscall_handler_t *) sys_chroot,
- [ __NR_ustat ] (syscall_handler_t *) sys_ustat,
- [ __NR_dup2 ] (syscall_handler_t *) sys_dup2,
- [ __NR_getppid ] (syscall_handler_t *) sys_getppid,
- [ __NR_getpgrp ] (syscall_handler_t *) sys_getpgrp,
+ [ __NR_pipe ] = (syscall_handler_t *) sys_pipe,
+ [ __NR_times ] = (syscall_handler_t *) sys_times,
+ [ __NR_brk ] = (syscall_handler_t *) sys_brk,
+ [ __NR_setgid ] = (syscall_handler_t *) sys_setgid16,
+ [ __NR_getgid ] = (syscall_handler_t *) sys_getgid16,
+ [ __NR_geteuid ] = (syscall_handler_t *) sys_geteuid16,
+ [ __NR_getegid ] = (syscall_handler_t *) sys_getegid16,
+ [ __NR_acct ] = (syscall_handler_t *) sys_acct,
+ [ __NR_umount2 ] = (syscall_handler_t *) sys_umount,
+ [ __NR_ioctl ] = (syscall_handler_t *) sys_ioctl,
+ [ __NR_fcntl ] = (syscall_handler_t *) sys_fcntl,
+ [ __NR_setpgid ] = (syscall_handler_t *) sys_setpgid,
+ [ __NR_umask ] = (syscall_handler_t *) sys_umask,
+ [ __NR_chroot ] = (syscall_handler_t *) sys_chroot,
+ [ __NR_ustat ] = (syscall_handler_t *) sys_ustat,
+ [ __NR_dup2 ] = (syscall_handler_t *) sys_dup2,
+ [ __NR_getppid ] = (syscall_handler_t *) sys_getppid,
+ [ __NR_getpgrp ] = (syscall_handler_t *) sys_getpgrp,
[ __NR_setsid ] = (syscall_handler_t *) sys_setsid,
- [ __NR_sigaction ] (syscall_handler_t *) sys_sigaction,
- [ __NR_sgetmask ] (syscall_handler_t *) sys_sgetmask,
- [ __NR_ssetmask ] (syscall_handler_t *) sys_ssetmask,
- [ __NR_setreuid ] (syscall_handler_t *) sys_setreuid16,
- [ __NR_setregid ] (syscall_handler_t *) sys_setregid16,
- [ __NR_sigsuspend ] (syscall_handler_t *) sys_sigsuspend,
- [ __NR_sigpending ] (syscall_handler_t *) sys_sigpending,
- [ __NR_sethostname ] (syscall_handler_t *) sys_sethostname,
- [ __NR_setrlimit ] (syscall_handler_t *) sys_setrlimit,
- [ __NR_getrlimit ] (syscall_handler_t *) sys_old_getrlimit,
- [ __NR_getrusage ] (syscall_handler_t *) sys_getrusage,
- [ __NR_gettimeofday ] (syscall_handler_t *) sys_gettimeofday,
- [ __NR_settimeofday ] (syscall_handler_t *) sys_settimeofday,
- [ __NR_getgroups ] (syscall_handler_t *) sys_getgroups16,
- [ __NR_setgroups ] (syscall_handler_t *) sys_setgroups16,
- [ __NR_symlink ] (syscall_handler_t *) sys_symlink,
- [ __NR_oldlstat ] (syscall_handler_t *) sys_lstat,
- [ __NR_readlink ] (syscall_handler_t *) sys_readlink,
- [ __NR_uselib ] (syscall_handler_t *) sys_uselib,
+ [ __NR_setreuid ] = (syscall_handler_t *) sys_setreuid16,
+ [ __NR_setregid ] = (syscall_handler_t *) sys_setregid16,
+ [ __NR_sethostname ] = (syscall_handler_t *) sys_sethostname,
+ [ __NR_setrlimit ] = (syscall_handler_t *) sys_setrlimit,
+ [ __NR_getrlimit ] = (syscall_handler_t *) sys_old_getrlimit,
+ [ __NR_getrusage ] = (syscall_handler_t *) sys_getrusage,
+ [ __NR_gettimeofday ] = (syscall_handler_t *) sys_gettimeofday,
+ [ __NR_settimeofday ] = (syscall_handler_t *) sys_settimeofday,
+ [ __NR_getgroups ] = (syscall_handler_t *) sys_getgroups16,
+ [ __NR_setgroups ] = (syscall_handler_t *) sys_setgroups16,
+ [ __NR_symlink ] = (syscall_handler_t *) sys_symlink,
+ [ __NR_readlink ] = (syscall_handler_t *) sys_readlink,
+ [ __NR_uselib ] = (syscall_handler_t *) sys_uselib,
[ __NR_swapon ] = (syscall_handler_t *) sys_swapon,
- [ __NR_reboot ] (syscall_handler_t *) sys_reboot,
- [ __NR_readdir ] = old_readdir,
- [ __NR_munmap ] (syscall_handler_t *) sys_munmap,
- [ __NR_truncate ] (syscall_handler_t *) sys_truncate,
- [ __NR_ftruncate ] (syscall_handler_t *) sys_ftruncate,
- [ __NR_fchmod ] (syscall_handler_t *) sys_fchmod,
- [ __NR_fchown ] (syscall_handler_t *) sys_fchown16,
- [ __NR_getpriority ] (syscall_handler_t *) sys_getpriority,
- [ __NR_setpriority ] (syscall_handler_t *) sys_setpriority,
- [ __NR_profil ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_statfs ] (syscall_handler_t *) sys_statfs,
- [ __NR_fstatfs ] (syscall_handler_t *) sys_fstatfs,
- [ __NR_ioperm ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_socketcall ] (syscall_handler_t *) sys_socketcall,
- [ __NR_syslog ] (syscall_handler_t *) sys_syslog,
- [ __NR_setitimer ] (syscall_handler_t *) sys_setitimer,
- [ __NR_getitimer ] (syscall_handler_t *) sys_getitimer,
- [ __NR_stat ] (syscall_handler_t *) sys_newstat,
- [ __NR_lstat ] (syscall_handler_t *) sys_newlstat,
- [ __NR_fstat ] (syscall_handler_t *) sys_newfstat,
- [ __NR_olduname ] (syscall_handler_t *) sys_uname,
- [ __NR_iopl ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_vhangup ] (syscall_handler_t *) sys_vhangup,
- [ __NR_idle ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_reboot ] = (syscall_handler_t *) sys_reboot,
+ [ __NR_munmap ] = (syscall_handler_t *) sys_munmap,
+ [ __NR_truncate ] = (syscall_handler_t *) sys_truncate,
+ [ __NR_ftruncate ] = (syscall_handler_t *) sys_ftruncate,
+ [ __NR_fchmod ] = (syscall_handler_t *) sys_fchmod,
+ [ __NR_fchown ] = (syscall_handler_t *) sys_fchown16,
+ [ __NR_getpriority ] = (syscall_handler_t *) sys_getpriority,
+ [ __NR_setpriority ] = (syscall_handler_t *) sys_setpriority,
+ [ __NR_statfs ] = (syscall_handler_t *) sys_statfs,
+ [ __NR_fstatfs ] = (syscall_handler_t *) sys_fstatfs,
+ [ __NR_ioperm ] = (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_syslog ] = (syscall_handler_t *) sys_syslog,
+ [ __NR_setitimer ] = (syscall_handler_t *) sys_setitimer,
+ [ __NR_getitimer ] = (syscall_handler_t *) sys_getitimer,
+ [ __NR_stat ] = (syscall_handler_t *) sys_newstat,
+ [ __NR_lstat ] = (syscall_handler_t *) sys_newlstat,
+ [ __NR_fstat ] = (syscall_handler_t *) sys_newfstat,
+ [ __NR_vhangup ] = (syscall_handler_t *) sys_vhangup,
[ __NR_wait4 ] = (syscall_handler_t *) sys_wait4,
[ __NR_swapoff ] = (syscall_handler_t *) sys_swapoff,
- [ __NR_sysinfo ] (syscall_handler_t *) sys_sysinfo,
- [ __NR_ipc ] (syscall_handler_t *) sys_ipc,
- [ __NR_fsync ] (syscall_handler_t *) sys_fsync,
- [ __NR_sigreturn ] (syscall_handler_t *) sys_sigreturn,
- [ __NR_clone ] (syscall_handler_t *) sys_clone,
- [ __NR_setdomainname ] (syscall_handler_t *) sys_setdomainname,
- [ __NR_uname ] (syscall_handler_t *) sys_newuname,
- [ __NR_adjtimex ] (syscall_handler_t *) sys_adjtimex,
- [ __NR_mprotect ] (syscall_handler_t *) sys_mprotect,
- [ __NR_sigprocmask ] (syscall_handler_t *) sys_sigprocmask,
- [ __NR_create_module ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_init_module ] (syscall_handler_t *) sys_init_module,
- [ __NR_delete_module ] (syscall_handler_t *) sys_delete_module,
- [ __NR_get_kernel_syms ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_quotactl ] (syscall_handler_t *) sys_quotactl,
- [ __NR_getpgid ] (syscall_handler_t *) sys_getpgid,
- [ __NR_fchdir ] (syscall_handler_t *) sys_fchdir,
- [ __NR_bdflush ] (syscall_handler_t *) sys_bdflush,
- [ __NR_sysfs ] (syscall_handler_t *) sys_sysfs,
- [ __NR_personality ] (syscall_handler_t *) sys_personality,
- [ __NR_afs_syscall ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_setfsuid ] (syscall_handler_t *) sys_setfsuid16,
- [ __NR_setfsgid ] (syscall_handler_t *) sys_setfsgid16,
- [ __NR__llseek ] (syscall_handler_t *) sys_llseek,
- [ __NR_getdents ] (syscall_handler_t *) sys_getdents,
- [ __NR__newselect ] = (syscall_handler_t *) sys_select,
- [ __NR_flock ] (syscall_handler_t *) sys_flock,
- [ __NR_msync ] (syscall_handler_t *) sys_msync,
- [ __NR_readv ] (syscall_handler_t *) sys_readv,
- [ __NR_writev ] (syscall_handler_t *) sys_writev,
- [ __NR_getsid ] (syscall_handler_t *) sys_getsid,
- [ __NR_fdatasync ] (syscall_handler_t *) sys_fdatasync,
+ [ __NR_sysinfo ] = (syscall_handler_t *) sys_sysinfo,
+ [ __NR_fsync ] = (syscall_handler_t *) sys_fsync,
+ [ __NR_clone ] = (syscall_handler_t *) sys_clone,
+ [ __NR_setdomainname ] = (syscall_handler_t *) sys_setdomainname,
+ [ __NR_uname ] = (syscall_handler_t *) sys_newuname,
+ [ __NR_adjtimex ] = (syscall_handler_t *) sys_adjtimex,
+ [ __NR_mprotect ] = (syscall_handler_t *) sys_mprotect,
+ [ __NR_create_module ] = (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_init_module ] = (syscall_handler_t *) sys_init_module,
+ [ __NR_delete_module ] = (syscall_handler_t *) sys_delete_module,
+ [ __NR_get_kernel_syms ] = (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_quotactl ] = (syscall_handler_t *) sys_quotactl,
+ [ __NR_getpgid ] = (syscall_handler_t *) sys_getpgid,
+ [ __NR_fchdir ] = (syscall_handler_t *) sys_fchdir,
+ [ __NR_sysfs ] = (syscall_handler_t *) sys_sysfs,
+ [ __NR_personality ] = (syscall_handler_t *) sys_personality,
+ [ __NR_afs_syscall ] = (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_setfsuid ] = (syscall_handler_t *) sys_setfsuid16,
+ [ __NR_setfsgid ] = (syscall_handler_t *) sys_setfsgid16,
+ [ __NR_getdents ] = (syscall_handler_t *) sys_getdents,
+ [ __NR_flock ] = (syscall_handler_t *) sys_flock,
+ [ __NR_msync ] = (syscall_handler_t *) sys_msync,
+ [ __NR_readv ] = (syscall_handler_t *) sys_readv,
+ [ __NR_writev ] = (syscall_handler_t *) sys_writev,
+ [ __NR_getsid ] = (syscall_handler_t *) sys_getsid,
+ [ __NR_fdatasync ] = (syscall_handler_t *) sys_fdatasync,
[ __NR__sysctl ] = (syscall_handler_t *) sys_sysctl,
- [ __NR_mlock ] (syscall_handler_t *) sys_mlock,
- [ __NR_munlock ] (syscall_handler_t *) sys_munlock,
- [ __NR_mlockall ] (syscall_handler_t *) sys_mlockall,
- [ __NR_munlockall ] (syscall_handler_t *) sys_munlockall,
- [ __NR_sched_setparam ] (syscall_handler_t *) sys_sched_setparam,
- [ __NR_sched_getparam ] (syscall_handler_t *) sys_sched_getparam,
- [ __NR_sched_setscheduler ] (syscall_handler_t *) sys_sched_setscheduler,
- [ __NR_sched_getscheduler ] (syscall_handler_t *) sys_sched_getscheduler,
+ [ __NR_mlock ] = (syscall_handler_t *) sys_mlock,
+ [ __NR_munlock ] = (syscall_handler_t *) sys_munlock,
+ [ __NR_mlockall ] = (syscall_handler_t *) sys_mlockall,
+ [ __NR_munlockall ] = (syscall_handler_t *) sys_munlockall,
+ [ __NR_sched_setparam ] = (syscall_handler_t *) sys_sched_setparam,
+ [ __NR_sched_getparam ] = (syscall_handler_t *) sys_sched_getparam,
+ [ __NR_sched_setscheduler ] = (syscall_handler_t *) sys_sched_setscheduler,
+ [ __NR_sched_getscheduler ] = (syscall_handler_t *) sys_sched_getscheduler,
[ __NR_sched_yield ] = (syscall_handler_t *) yield,
- [ __NR_sched_get_priority_max ] (syscall_handler_t *) sys_sched_get_priority_max,
- [ __NR_sched_get_priority_min ] (syscall_handler_t *) sys_sched_get_priority_min,
- [ __NR_sched_rr_get_interval ] (syscall_handler_t *) sys_sched_rr_get_interval,
- [ __NR_nanosleep ] (syscall_handler_t *) sys_nanosleep,
- [ __NR_mremap ] (syscall_handler_t *) sys_mremap,
- [ __NR_setresuid ] (syscall_handler_t *) sys_setresuid16,
- [ __NR_getresuid ] (syscall_handler_t *) sys_getresuid16,
- [ __NR_vm86 ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_query_module ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_poll ] (syscall_handler_t *) sys_poll,
+ [ __NR_sched_get_priority_max ] = (syscall_handler_t *) sys_sched_get_priority_max,
+ [ __NR_sched_get_priority_min ] = (syscall_handler_t *) sys_sched_get_priority_min,
+ [ __NR_sched_rr_get_interval ] = (syscall_handler_t *) sys_sched_rr_get_interval,
+ [ __NR_nanosleep ] = (syscall_handler_t *) sys_nanosleep,
+ [ __NR_mremap ] = (syscall_handler_t *) sys_mremap,
+ [ __NR_setresuid ] = (syscall_handler_t *) sys_setresuid16,
+ [ __NR_getresuid ] = (syscall_handler_t *) sys_getresuid16,
+ [ __NR_query_module ] = (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_poll ] = (syscall_handler_t *) sys_poll,
[ __NR_nfsservctl ] = (syscall_handler_t *) NFSSERVCTL,
- [ __NR_setresgid ] (syscall_handler_t *) sys_setresgid16,
- [ __NR_getresgid ] (syscall_handler_t *) sys_getresgid16,
- [ __NR_prctl ] (syscall_handler_t *) sys_prctl,
- [ __NR_rt_sigreturn ] (syscall_handler_t *) sys_rt_sigreturn,
- [ __NR_rt_sigaction ] (syscall_handler_t *) sys_rt_sigaction,
- [ __NR_rt_sigprocmask ] (syscall_handler_t *) sys_rt_sigprocmask,
- [ __NR_rt_sigpending ] (syscall_handler_t *) sys_rt_sigpending,
- [ __NR_rt_sigtimedwait ] (syscall_handler_t *) sys_rt_sigtimedwait,
- [ __NR_rt_sigqueueinfo ] (syscall_handler_t *) sys_rt_sigqueueinfo,
- [ __NR_rt_sigsuspend ] (syscall_handler_t *) sys_rt_sigsuspend,
- [ __NR_pread64 ] (syscall_handler_t *) sys_pread64,
- [ __NR_pwrite64 ] (syscall_handler_t *) sys_pwrite64,
- [ __NR_chown ] (syscall_handler_t *) sys_chown16,
- [ __NR_getcwd ] (syscall_handler_t *) sys_getcwd,
- [ __NR_capget ] (syscall_handler_t *) sys_capget,
- [ __NR_capset ] (syscall_handler_t *) sys_capset,
- [ __NR_sigaltstack ] (syscall_handler_t *) sys_sigaltstack,
- [ __NR_sendfile ] (syscall_handler_t *) sys_sendfile,
- [ __NR_getpmsg ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_putpmsg ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_vfork ] (syscall_handler_t *) sys_vfork,
- [ __NR_ugetrlimit ] (syscall_handler_t *) sys_getrlimit,
- [ __NR_mmap2 ] (syscall_handler_t *) sys_mmap2,
- [ __NR_truncate64 ] (syscall_handler_t *) sys_truncate64,
- [ __NR_ftruncate64 ] (syscall_handler_t *) sys_ftruncate64,
- [ __NR_stat64 ] (syscall_handler_t *) sys_stat64,
- [ __NR_lstat64 ] (syscall_handler_t *) sys_lstat64,
- [ __NR_fstat64 ] (syscall_handler_t *) sys_fstat64,
- [ __NR_getdents64 ] (syscall_handler_t *) sys_getdents64,
- [ __NR_fcntl64 ] (syscall_handler_t *) sys_fcntl64,
- [ 223 ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_gettid ] (syscall_handler_t *) sys_gettid,
- [ __NR_readahead ] (syscall_handler_t *) sys_readahead,
- [ __NR_setxattr ] (syscall_handler_t *) sys_setxattr,
- [ __NR_lsetxattr ] (syscall_handler_t *) sys_lsetxattr,
- [ __NR_fsetxattr ] (syscall_handler_t *) sys_fsetxattr,
- [ __NR_getxattr ] (syscall_handler_t *) sys_getxattr,
- [ __NR_lgetxattr ] (syscall_handler_t *) sys_lgetxattr,
- [ __NR_fgetxattr ] (syscall_handler_t *) sys_fgetxattr,
- [ __NR_listxattr ] (syscall_handler_t *) sys_listxattr,
- [ __NR_llistxattr ] (syscall_handler_t *) sys_llistxattr,
- [ __NR_flistxattr ] (syscall_handler_t *) sys_flistxattr,
- [ __NR_removexattr ] (syscall_handler_t *) sys_removexattr,
- [ __NR_lremovexattr ] (syscall_handler_t *) sys_lremovexattr,
- [ __NR_fremovexattr ] (syscall_handler_t *) sys_fremovexattr,
- [ __NR_tkill ] (syscall_handler_t *) sys_tkill,
- [ __NR_sendfile64 ] (syscall_handler_t *) sys_sendfile64,
- [ __NR_futex ] (syscall_handler_t *) sys_futex,
- [ __NR_sched_setaffinity ] (syscall_handler_t *) sys_sched_setaffinity,
- [ __NR_sched_getaffinity ] (syscall_handler_t *) sys_sched_getaffinity,
- [ __NR_set_thread_area ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_get_thread_area ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_io_setup ] (syscall_handler_t *) sys_io_setup,
- [ __NR_io_destroy ] (syscall_handler_t *) sys_io_destroy,
- [ __NR_io_getevents ] (syscall_handler_t *) sys_io_getevents,
- [ __NR_io_submit ] (syscall_handler_t *) sys_io_submit,
- [ __NR_io_cancel ] (syscall_handler_t *) sys_io_cancel,
- [ __NR_fadvise64 ] (syscall_handler_t *) sys_fadvise64,
- [ 251 ] (syscall_handler_t *) sys_ni_syscall,
- [ __NR_exit_group ] (syscall_handler_t *) sys_exit_group,
- [ __NR_lookup_dcookie ] (syscall_handler_t *) sys_lookup_dcookie,
- [ __NR_epoll_create ] (syscall_handler_t *) sys_epoll_create,
- [ __NR_epoll_ctl ] (syscall_handler_t *) sys_epoll_ctl,
- [ __NR_epoll_wait ] (syscall_handler_t *) sys_epoll_wait,
- [ __NR_remap_file_pages ] (syscall_handler_t *) sys_remap_file_pages,
- [ __NR_set_tid_address ] (syscall_handler_t *) sys_set_tid_address,
- [ __NR_timer_create ] (syscall_handler_t *) sys_timer_create,
- [ __NR_timer_settime ] (syscall_handler_t *) sys_timer_settime,
- [ __NR_timer_gettime ] (syscall_handler_t *) sys_timer_gettime,
- [ __NR_timer_getoverrun ] (syscall_handler_t *) sys_timer_getoverrun,
- [ __NR_timer_delete ] (syscall_handler_t *) sys_timer_delete,
- [ __NR_clock_settime ] (syscall_handler_t *) sys_clock_settime,
- [ __NR_clock_gettime ] (syscall_handler_t *) sys_clock_gettime,
- [ __NR_clock_getres ] (syscall_handler_t *) sys_clock_getres,
- [ __NR_clock_nanosleep ] (syscall_handler_t *) sys_clock_nanosleep,
- [ __NR_statfs64 ] (syscall_handler_t *) sys_statfs64,
- [ __NR_fstatfs64 ] (syscall_handler_t *) sys_fstatfs64,
- [ __NR_tgkill ] (syscall_handler_t *) sys_tgkill,
- [ __NR_utimes ] (syscall_handler_t *) sys_utimes,
- [ __NR_fadvise64_64 ] (syscall_handler_t *) sys_fadvise64_64,
- [ __NR_vserver ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_setresgid ] = (syscall_handler_t *) sys_setresgid16,
+ [ __NR_getresgid ] = (syscall_handler_t *) sys_getresgid16,
+ [ __NR_prctl ] = (syscall_handler_t *) sys_prctl,
+ [ __NR_rt_sigreturn ] = (syscall_handler_t *) sys_rt_sigreturn,
+ [ __NR_rt_sigaction ] = (syscall_handler_t *) sys_rt_sigaction,
+ [ __NR_rt_sigprocmask ] = (syscall_handler_t *) sys_rt_sigprocmask,
+ [ __NR_rt_sigpending ] = (syscall_handler_t *) sys_rt_sigpending,
+ [ __NR_rt_sigtimedwait ] = (syscall_handler_t *) sys_rt_sigtimedwait,
+ [ __NR_rt_sigqueueinfo ] = (syscall_handler_t *) sys_rt_sigqueueinfo,
+ [ __NR_rt_sigsuspend ] = (syscall_handler_t *) sys_rt_sigsuspend,
+ [ __NR_pread64 ] = (syscall_handler_t *) sys_pread64,
+ [ __NR_pwrite64 ] = (syscall_handler_t *) sys_pwrite64,
+ [ __NR_chown ] = (syscall_handler_t *) sys_chown16,
+ [ __NR_getcwd ] = (syscall_handler_t *) sys_getcwd,
+ [ __NR_capget ] = (syscall_handler_t *) sys_capget,
+ [ __NR_capset ] = (syscall_handler_t *) sys_capset,
+ [ __NR_sigaltstack ] = (syscall_handler_t *) sys_sigaltstack,
+ [ __NR_sendfile ] = (syscall_handler_t *) sys_sendfile,
+ [ __NR_getpmsg ] = (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_putpmsg ] = (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_vfork ] = (syscall_handler_t *) sys_vfork,
+ [ __NR_getdents64 ] = (syscall_handler_t *) sys_getdents64,
+ [ __NR_gettid ] = (syscall_handler_t *) sys_gettid,
+ [ __NR_readahead ] = (syscall_handler_t *) sys_readahead,
+ [ __NR_setxattr ] = (syscall_handler_t *) sys_setxattr,
+ [ __NR_lsetxattr ] = (syscall_handler_t *) sys_lsetxattr,
+ [ __NR_fsetxattr ] = (syscall_handler_t *) sys_fsetxattr,
+ [ __NR_getxattr ] = (syscall_handler_t *) sys_getxattr,
+ [ __NR_lgetxattr ] = (syscall_handler_t *) sys_lgetxattr,
+ [ __NR_fgetxattr ] = (syscall_handler_t *) sys_fgetxattr,
+ [ __NR_listxattr ] = (syscall_handler_t *) sys_listxattr,
+ [ __NR_llistxattr ] = (syscall_handler_t *) sys_llistxattr,
+ [ __NR_flistxattr ] = (syscall_handler_t *) sys_flistxattr,
+ [ __NR_removexattr ] = (syscall_handler_t *) sys_removexattr,
+ [ __NR_lremovexattr ] = (syscall_handler_t *) sys_lremovexattr,
+ [ __NR_fremovexattr ] = (syscall_handler_t *) sys_fremovexattr,
+ [ __NR_tkill ] = (syscall_handler_t *) sys_tkill,
+ [ __NR_futex ] = (syscall_handler_t *) sys_futex,
+ [ __NR_sched_setaffinity ] = (syscall_handler_t *) sys_sched_setaffinity,
+ [ __NR_sched_getaffinity ] = (syscall_handler_t *) sys_sched_getaffinity,
+ [ __NR_io_setup ] = (syscall_handler_t *) sys_io_setup,
+ [ __NR_io_destroy ] = (syscall_handler_t *) sys_io_destroy,
+ [ __NR_io_getevents ] = (syscall_handler_t *) sys_io_getevents,
+ [ __NR_io_submit ] = (syscall_handler_t *) sys_io_submit,
+ [ __NR_io_cancel ] = (syscall_handler_t *) sys_io_cancel,
+ [ __NR_exit_group ] = (syscall_handler_t *) sys_exit_group,
+ [ __NR_lookup_dcookie ] = (syscall_handler_t *) sys_lookup_dcookie,
+ [ __NR_epoll_create ] = (syscall_handler_t *) sys_epoll_create,
+ [ __NR_epoll_ctl ] = (syscall_handler_t *) sys_epoll_ctl,
+ [ __NR_epoll_wait ] = (syscall_handler_t *) sys_epoll_wait,
+ [ __NR_set_tid_address ] = (syscall_handler_t *) sys_set_tid_address,
+ [ __NR_timer_create ] = (syscall_handler_t *) sys_timer_create,
+ [ __NR_timer_settime ] = (syscall_handler_t *) sys_timer_settime,
+ [ __NR_timer_gettime ] = (syscall_handler_t *) sys_timer_gettime,
+ [ __NR_timer_getoverrun ] = (syscall_handler_t *) sys_timer_getoverrun,
+ [ __NR_timer_delete ] = (syscall_handler_t *) sys_timer_delete,
+ [ __NR_clock_settime ] = (syscall_handler_t *) sys_clock_settime,
+ [ __NR_clock_gettime ] = (syscall_handler_t *) sys_clock_gettime,
+ [ __NR_clock_getres ] = (syscall_handler_t *) sys_clock_getres,
+ [ __NR_clock_nanosleep ] = (syscall_handler_t *) sys_clock_nanosleep,
+ [ __NR_statfs64 ] = (syscall_handler_t *) sys_statfs64,
+ [ __NR_fstatfs64 ] = (syscall_handler_t *) sys_fstatfs64,
+ [ __NR_tgkill ] = (syscall_handler_t *) sys_tgkill,
+ [ __NR_utimes ] = (syscall_handler_t *) sys_utimes,
+ [ __NR_fadvise64_64 ] = (syscall_handler_t *) sys_fadvise64_64,
+ [ __NR_vserver ] = (syscall_handler_t *) sys_vserver,
+ [ __NR_mbind ] = (syscall_handler_t *) sys_mbind,
+ [ __NR_get_mempolicy ] = (syscall_handler_t *) sys_get_mempolicy,
+ [ __NR_set_mempolicy ] = (syscall_handler_t *) sys_set_mempolicy,
+ [ __NR_mq_open ] = (syscall_handler_t *) sys_mq_open,
+ [ __NR_mq_unlink ] = (syscall_handler_t *) sys_mq_unlink,
+ [ __NR_mq_timedsend ] = (syscall_handler_t *) sys_mq_timedsend,
+ [ __NR_mq_timedreceive ] = (syscall_handler_t *) sys_mq_timedreceive,
+ [ __NR_mq_notify ] = (syscall_handler_t *) sys_mq_notify,
+ [ __NR_mq_getsetattr ] = (syscall_handler_t *) sys_mq_getsetattr,
+ [ __NR_sys_kexec_load ] = (syscall_handler_t *) sys_kexec_load,
+ [ __NR_waitid ] = (syscall_handler_t *) sys_waitid,
+#if 0
+ [ __NR_sys_setaltroot ] = (syscall_handler_t *) sys_sys_setaltroot,
+#endif
+ [ __NR_add_key ] = (syscall_handler_t *) sys_add_key,
+ [ __NR_request_key ] = (syscall_handler_t *) sys_request_key,
+ [ __NR_keyctl ] = (syscall_handler_t *) sys_keyctl,
+ [ __NR_vperfctr_open ] = (syscall_handler_t *) sys_vperfctr_open,
+ [ __NR_vperfctr_control ] = (syscall_handler_t *) sys_vperfctr_control,
+ [ __NR_vperfctr_unlink ] = (syscall_handler_t *) sys_vperfctr_unlink,
+ [ __NR_vperfctr_iresume ] = (syscall_handler_t *) sys_vperfctr_iresume,
+ [ __NR_vperfctr_read ] = (syscall_handler_t *) sys_vperfctr_read,
ARCH_SYSCALLS
[ LAST_SYSCALL + 1 ... NR_syscalls ] =
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
index a549b3b1410f..a294e5071fe8 100644
--- a/arch/um/kernel/syscall_kern.c
+++ b/arch/um/kernel/syscall_kern.c
@@ -27,10 +27,9 @@
/* Unlocked, I don't care if this is a bit off */
int nsyscalls = 0;
-long um_mount(char * dev_name, char * dir_name, char * type,
- unsigned long new_flags, void * data)
+long um_mount(char __user * dev_name, char __user * dir_name,
+ char __user * type, unsigned long new_flags, void __user * data)
{
- if(type == NULL) type = "";
return(sys_mount(dev_name, dir_name, type, new_flags, data));
}
@@ -56,12 +55,11 @@ long sys_vfork(void)
}
/* common code for old and new mmaps */
-static inline long do_mmap2(
- unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff)
+long sys_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
{
- int error = -EBADF;
+ long error = -EBADF;
struct file * file = NULL;
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
@@ -81,38 +79,15 @@ static inline long do_mmap2(
return error;
}
-long sys_mmap2(unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff)
-{
- return do_mmap2(addr, len, prot, flags, fd, pgoff);
-}
-
-/*
- * Perform the select(nd, in, out, ex, tv) and mmap() system
- * calls. Linux/i386 didn't use to be able to handle more than
- * 4 system call parameters, so these system calls used a memory
- * block for parameter passing..
- */
-
-struct mmap_arg_struct {
- unsigned long addr;
- unsigned long len;
- unsigned long prot;
- unsigned long flags;
- unsigned long fd;
- unsigned long offset;
-};
-
long old_mmap(unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long offset)
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long offset)
{
long err = -EINVAL;
if (offset & ~PAGE_MASK)
goto out;
- err = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+ err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
out:
return err;
}
@@ -120,7 +95,7 @@ long old_mmap(unsigned long addr, unsigned long len,
* sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way unix traditionally does this, though.
*/
-long sys_pipe(unsigned long * fildes)
+long sys_pipe(unsigned long __user * fildes)
{
int fd[2];
long error;
@@ -133,90 +108,6 @@ long sys_pipe(unsigned long * fildes)
return error;
}
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-int sys_ipc (uint call, int first, int second,
- int third, void *ptr, long fifth)
-{
- int version, ret;
-
- version = call >> 16; /* hack for backward compatibility */
- call &= 0xffff;
-
- switch (call) {
- case SEMOP:
- return sys_semtimedop(first, (struct sembuf *) ptr, second,
- NULL);
- case SEMTIMEDOP:
- return sys_semtimedop(first, (struct sembuf *) ptr, second,
- (const struct timespec *) fifth);
- case SEMGET:
- return sys_semget (first, second, third);
- case SEMCTL: {
- union semun fourth;
- if (!ptr)
- return -EINVAL;
- if (get_user(fourth.__pad, (void **) ptr))
- return -EFAULT;
- return sys_semctl (first, second, third, fourth);
- }
-
- case MSGSND:
- return sys_msgsnd (first, (struct msgbuf *) ptr,
- second, third);
- case MSGRCV:
- switch (version) {
- case 0: {
- struct ipc_kludge tmp;
- if (!ptr)
- return -EINVAL;
-
- if (copy_from_user(&tmp,
- (struct ipc_kludge *) ptr,
- sizeof (tmp)))
- return -EFAULT;
- return sys_msgrcv (first, tmp.msgp, second,
- tmp.msgtyp, third);
- }
- default:
- panic("msgrcv with version != 0");
- return sys_msgrcv (first,
- (struct msgbuf *) ptr,
- second, fifth, third);
- }
- case MSGGET:
- return sys_msgget ((key_t) first, second);
- case MSGCTL:
- return sys_msgctl (first, second, (struct msqid_ds *) ptr);
-
- case SHMAT:
- switch (version) {
- default: {
- ulong raddr;
- ret = do_shmat (first, (char *) ptr, second, &raddr);
- if (ret)
- return ret;
- return put_user (raddr, (ulong *) third);
- }
- case 1: /* iBCS2 emulator entry point */
- if (!segment_eq(get_fs(), get_ds()))
- return -EINVAL;
- return do_shmat (first, (char *) ptr, second, (ulong *) third);
- }
- case SHMDT:
- return sys_shmdt ((char *)ptr);
- case SHMGET:
- return sys_shmget (first, second, third);
- case SHMCTL:
- return sys_shmctl (first, second,
- (struct shmid_ds *) ptr);
- default:
- return -ENOSYS;
- }
-}
long sys_uname(struct old_utsname * name)
{
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 498344110eee..df21b0529ae6 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -111,19 +111,19 @@ irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
return(IRQ_HANDLED);
}
-long um_time(int * tloc)
+long um_time(int __user *tloc)
{
struct timeval now;
do_gettimeofday(&now);
if (tloc) {
- if (put_user(now.tv_sec,tloc))
+ if (put_user(now.tv_sec, tloc))
now.tv_sec = -EFAULT;
}
return now.tv_sec;
}
-long um_stime(int * tptr)
+long um_stime(int __user *tptr)
{
int value;
struct timespec new;
@@ -136,22 +136,7 @@ long um_stime(int * tptr)
return 0;
}
-/* XXX Needs to be moved under sys-i386 */
-void __delay(um_udelay_t time)
-{
- /* Stolen from the i386 __loop_delay */
- int d0;
- __asm__ __volatile__(
- "\tjmp 1f\n"
- ".align 16\n"
- "1:\tjmp 2f\n"
- ".align 16\n"
- "2:\tdecl %0\n\tjns 2b"
- :"=&a" (d0)
- :"0" (time));
-}
-
-void __udelay(um_udelay_t usecs)
+void __udelay(unsigned long usecs)
{
int i, n;
@@ -159,7 +144,7 @@ void __udelay(um_udelay_t usecs)
for(i=0;i<n;i++) ;
}
-void __const_udelay(um_udelay_t usecs)
+void __const_udelay(unsigned long usecs)
{
int i, n;
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index c42053140e2b..26f5d12d81f3 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -59,9 +59,14 @@ pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
return(pgd_offset(mm, address));
}
-pmd_t *pmd_offset_proc(pgd_t *pgd, unsigned long address)
+pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address)
{
- return(pmd_offset(pgd, address));
+ return(pud_offset(pgd, address));
+}
+
+pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address)
+{
+ return(pmd_offset(pud, address));
}
pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
@@ -71,8 +76,11 @@ pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
pte_t *addr_pte(struct task_struct *task, unsigned long addr)
{
- return(pte_offset_kernel(pmd_offset(pgd_offset(task->mm, addr), addr),
- addr));
+ pgd_t *pgd = pgd_offset(task->mm, addr);
+ pud_t *pud = pud_offset(pgd, addr);
+ pmd_t *pmd = pmd_offset(pud, addr);
+
+ return(pte_offset_map(pmd, addr));
}
/*
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index cba33ef6da5d..80d07fe6b979 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -13,6 +13,7 @@
#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"
@@ -32,6 +33,7 @@ int handle_page_fault(unsigned long address, unsigned long ip,
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
pte_t *pte;
unsigned long page;
@@ -55,7 +57,8 @@ int handle_page_fault(unsigned long address, unsigned long ip,
goto out;
page = address & PAGE_MASK;
pgd = pgd_offset(mm, page);
- pmd = pmd_offset(pgd, page);
+ pud = pud_offset(pgd, page);
+ pmd = pmd_offset(pud, page);
do {
survive:
switch (handle_mm_fault(mm, vma, address, is_write)){
@@ -74,6 +77,9 @@ int handle_page_fault(unsigned long address, unsigned long ip,
default:
BUG();
}
+ pgd = pgd_offset(mm, page);
+ pud = pud_offset(pgd, page);
+ pmd = pmd_offset(pud, page);
pte = pte_offset_kernel(pmd, page);
} while(!pte_present(*pte));
err = 0;
diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
index 73103c29aff7..0a3d279ce64f 100644
--- a/arch/um/kernel/trap_user.c
+++ b/arch/um/kernel/trap_user.c
@@ -102,28 +102,6 @@ struct signal_info sig_info[] = {
.is_irq = 0 },
};
-void sig_handler(int sig, struct sigcontext sc)
-{
- CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
- sig, &sc);
-}
-
-extern int timer_irq_inited;
-
-void alarm_handler(int sig, struct sigcontext sc)
-{
- if(!timer_irq_inited) return;
-
- if(sig == SIGALRM)
- switch_timers(0);
-
- CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
- sig, &sc);
-
- if(sig == SIGALRM)
- switch_timers(1);
-}
-
void do_longjmp(void *b, int val)
{
sigjmp_buf *buf = b;
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
index 17f4594dc231..7c9eec5fded5 100644
--- a/arch/um/kernel/tt/Makefile
+++ b/arch/um/kernel/tt/Makefile
@@ -24,6 +24,9 @@ $(USER_OBJS) : %.o: %.c
$(obj)/unmap.o: $(src)/unmap.c
$(CC) $(UNMAP_CFLAGS) -c -o $@ $<
+LIBC_DIR ?= /usr/lib
+
$(obj)/unmap_fin.o : $(obj)/unmap.o
- ld -r -o $(obj)/unmap_tmp.o $< -lc -L/usr/lib
+ ld -r -o $(obj)/unmap_tmp.o $< -lc -L$(LIBC_DIR)
objcopy $(obj)/unmap_tmp.o $@ -G switcheroo
+
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 10db6d6ab7ea..22cbdbffbe3e 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -162,7 +162,7 @@ int gdb_remove(char *unused)
void signal_usr1(int sig)
{
if(debugger_pid != -1){
- printk(UM_KERN_ERR "The debugger is already running\n");
+ printf("The debugger is already running\n");
return;
}
debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
@@ -228,19 +228,19 @@ 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)
{
- printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n");
+ printf("debug requested when CONFIG_PT_PROXY is off\n");
kill_child_dead(idle_pid);
exit(1);
}
void signal_usr1(int sig)
{
- printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n");
+ printf("debug requested when CONFIG_PT_PROXY is off\n");
}
int attach_debugger(int idle_pid, int pid, int stop)
{
- printk(UM_KERN_ERR "attach_debugger called when CONFIG_PT_PROXY "
+ printf("attach_debugger called when CONFIG_PT_PROXY "
"is off\n");
return(-1);
}
diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c
index 458ecf9a45f1..f41832c79f36 100644
--- a/arch/um/kernel/tt/ptproxy/proxy.c
+++ b/arch/um/kernel/tt/ptproxy/proxy.c
@@ -94,7 +94,9 @@ int debugger_syscall(debugger_state *debugger, pid_t child)
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,
@@ -153,7 +155,11 @@ static int parent_syscall(debugger_state *debugger, int pid)
syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5);
- if((syscall == __NR_waitpid) || (syscall == __NR_wait4)){
+ 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);
}
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
index c42855aeda60..4545ea4f27e1 100644
--- a/arch/um/kernel/tt/ptproxy/sysdep.c
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c
@@ -12,7 +12,6 @@ terms and conditions.
#include <errno.h>
#include <sys/types.h>
#include <sys/ptrace.h>
-#include <asm/ptrace.h>
#include <linux/unistd.h>
#include "ptrace_user.h"
#include "user_util.h"
diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c
index 86ef67653e72..fcb7ea50fc7e 100644
--- a/arch/um/kernel/tt/ptproxy/wait.c
+++ b/arch/um/kernel/tt/ptproxy/wait.c
@@ -10,7 +10,6 @@ terms and conditions.
#include <signal.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
-#include <asm/ptrace.h>
#include "ptproxy.h"
#include "sysdep.h"
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c
index 891045bb966a..c02e504e54c1 100644
--- a/arch/um/kernel/tt/syscall_kern.c
+++ b/arch/um/kernel/tt/syscall_kern.c
@@ -14,95 +14,6 @@
#include "sysdep/syscalls.h"
#include "kern_util.h"
-static inline int check_area(void *ptr, int size)
-{
- return(verify_area(VERIFY_WRITE, ptr, size));
-}
-
-static int check_readlink(struct pt_regs *regs)
-{
- return(check_area((void *) UPT_SYSCALL_ARG1(&regs->regs),
- UPT_SYSCALL_ARG2(&regs->regs)));
-}
-
-static int check_utime(struct pt_regs *regs)
-{
- return(check_area((void *) UPT_SYSCALL_ARG1(&regs->regs),
- sizeof(struct utimbuf)));
-}
-
-static int check_oldstat(struct pt_regs *regs)
-{
- return(check_area((void *) UPT_SYSCALL_ARG1(&regs->regs),
- sizeof(struct __old_kernel_stat)));
-}
-
-static int check_stat(struct pt_regs *regs)
-{
- return(check_area((void *) UPT_SYSCALL_ARG1(&regs->regs),
- sizeof(struct stat)));
-}
-
-static int check_stat64(struct pt_regs *regs)
-{
- return(check_area((void *) UPT_SYSCALL_ARG1(&regs->regs),
- sizeof(struct stat64)));
-}
-
-struct bogus {
- int kernel_ds;
- int (*check_params)(struct pt_regs *);
-};
-
-struct bogus this_is_bogus[256] = {
- [ __NR_mknod ] = { 1, NULL },
- [ __NR_mkdir ] = { 1, NULL },
- [ __NR_rmdir ] = { 1, NULL },
- [ __NR_unlink ] = { 1, NULL },
- [ __NR_symlink ] = { 1, NULL },
- [ __NR_link ] = { 1, NULL },
- [ __NR_rename ] = { 1, NULL },
- [ __NR_umount ] = { 1, NULL },
- [ __NR_mount ] = { 1, NULL },
- [ __NR_pivot_root ] = { 1, NULL },
- [ __NR_chdir ] = { 1, NULL },
- [ __NR_chroot ] = { 1, NULL },
- [ __NR_open ] = { 1, NULL },
- [ __NR_quotactl ] = { 1, NULL },
- [ __NR_sysfs ] = { 1, NULL },
- [ __NR_readlink ] = { 1, check_readlink },
- [ __NR_acct ] = { 1, NULL },
- [ __NR_execve ] = { 1, NULL },
- [ __NR_uselib ] = { 1, NULL },
- [ __NR_statfs ] = { 1, NULL },
- [ __NR_truncate ] = { 1, NULL },
- [ __NR_access ] = { 1, NULL },
- [ __NR_chmod ] = { 1, NULL },
- [ __NR_chown ] = { 1, NULL },
- [ __NR_lchown ] = { 1, NULL },
- [ __NR_utime ] = { 1, check_utime },
- [ __NR_oldlstat ] = { 1, check_oldstat },
- [ __NR_oldstat ] = { 1, check_oldstat },
- [ __NR_stat ] = { 1, check_stat },
- [ __NR_lstat ] = { 1, check_stat },
- [ __NR_stat64 ] = { 1, check_stat64 },
- [ __NR_lstat64 ] = { 1, check_stat64 },
- [ __NR_chown32 ] = { 1, NULL },
-};
-
-/* sys_utimes */
-
-static int check_bogosity(struct pt_regs *regs)
-{
- struct bogus *bogon = &this_is_bogus[UPT_SYSCALL_NR(&regs->regs)];
-
- if(!bogon->kernel_ds) return(0);
- if(bogon->check_params && (*bogon->check_params)(regs))
- return(-EFAULT);
- set_fs(KERNEL_DS);
- return(0);
-}
-
extern syscall_handler_t *sys_call_table[];
long execute_syscall_tt(void *r)
@@ -117,12 +28,8 @@ long execute_syscall_tt(void *r)
if((syscall >= NR_syscalls) || (syscall < 0))
res = -ENOSYS;
- else if(honeypot && check_bogosity(regs))
- res = -EFAULT;
else res = EXECUTE_SYSCALL(syscall, regs);
- set_fs(USER_DS);
-
return(res);
}
diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c
index d8ad334cfac9..3bc35eea1da4 100644
--- a/arch/um/kernel/tt/tlb.c
+++ b/arch/um/kernel/tt/tlb.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright 2003 PathScale, Inc.
* Licensed under the GPL
*/
@@ -19,9 +20,10 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
unsigned long end_addr, int force)
{
pgd_t *npgd;
+ pud_t *npud;
pmd_t *npmd;
pte_t *npte;
- unsigned long addr;
+ unsigned long addr, end;
int r, w, x, err;
if((current->thread.mode.tt.extern_pid != -1) &&
@@ -41,45 +43,81 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
addr = STACK_TOP - ABOVE_KMEM;
continue;
}
+
npgd = pgd_offset(mm, addr);
- npmd = pmd_offset(npgd, addr);
- if(pmd_present(*npmd)){
- npte = pte_offset_kernel(npmd, addr);
- r = pte_read(*npte);
- w = pte_write(*npte);
- x = pte_exec(*npte);
- if(!pte_dirty(*npte)) w = 0;
- if(!pte_young(*npte)){
- r = 0;
- w = 0;
- }
- if(force || pte_newpage(*npte)){
+ if(!pgd_present(*npgd)){
+ if(force || pgd_newpage(*npgd)){
+ end = addr + PGDIR_SIZE;
+ if(end > end_addr)
+ end = end_addr;
+ err = os_unmap_memory((void *) addr,
+ end - addr);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ pgd_mkuptodate(*npgd);
+ }
+ addr += PGDIR_SIZE;
+ continue;
+ }
+
+ npud = pud_offset(npgd, addr);
+ if(!pud_present(*npud)){
+ if(force || pud_newpage(*npud)){
+ end = addr + PUD_SIZE;
+ if(end > end_addr)
+ end = end_addr;
err = os_unmap_memory((void *) addr,
- PAGE_SIZE);
+ end - addr);
if(err < 0)
panic("munmap failed, errno = %d\n",
-err);
- if(pte_present(*npte))
- map_memory(addr,
- pte_val(*npte) & PAGE_MASK,
- PAGE_SIZE, r, w, x);
- }
- else if(pte_newprot(*npte)){
- protect_memory(addr, PAGE_SIZE, r, w, x, 1);
+ pud_mkuptodate(*npud);
}
- *npte = pte_mkuptodate(*npte);
- addr += PAGE_SIZE;
+ addr += PUD_SIZE;
+ continue;
}
- else {
+
+ npmd = pmd_offset(npud, addr);
+ if(!pmd_present(*npmd)){
if(force || pmd_newpage(*npmd)){
- err = os_unmap_memory((void *) addr, PMD_SIZE);
+ end = addr + PMD_SIZE;
+ if(end > end_addr)
+ end = end_addr;
+ err = os_unmap_memory((void *) addr,
+ end - addr);
if(err < 0)
panic("munmap failed, errno = %d\n",
-err);
pmd_mkuptodate(*npmd);
}
addr += PMD_SIZE;
+ continue;
}
+
+ npte = pte_offset_kernel(npmd, addr);
+ r = pte_read(*npte);
+ w = pte_write(*npte);
+ x = pte_exec(*npte);
+ if(!pte_dirty(*npte))
+ w = 0;
+ if(!pte_young(*npte)){
+ r = 0;
+ w = 0;
+ }
+ if(force || pte_newpage(*npte)){
+ err = os_unmap_memory((void *) addr, PAGE_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n", -err);
+ if(pte_present(*npte))
+ map_memory(addr, pte_val(*npte) & PAGE_MASK,
+ PAGE_SIZE, r, w, x);
+ }
+ else if(pte_newprot(*npte))
+ protect_memory(addr, PAGE_SIZE, r, w, x, 1);
+
+ *npte = pte_mkuptodate(*npte);
+ addr += PAGE_SIZE;
}
}
@@ -90,45 +128,83 @@ static void flush_kernel_vm_range(unsigned long start, unsigned long end,
{
struct mm_struct *mm;
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
pte_t *pte;
- unsigned long addr;
+ unsigned long addr, last;
int updated = 0, err;
mm = &init_mm;
for(addr = start; addr < end;){
pgd = pgd_offset(mm, addr);
- pmd = pmd_offset(pgd, addr);
- if(pmd_present(*pmd)){
- pte = pte_offset_kernel(pmd, addr);
- if(!pte_present(*pte) || pte_newpage(*pte)){
+ if(!pgd_present(*pgd)){
+ if(pgd_newpage(*pgd)){
updated = 1;
+ last = addr + PGDIR_SIZE;
+ if(last > end)
+ last = end;
err = os_unmap_memory((void *) addr,
- PAGE_SIZE);
+ last - addr);
if(err < 0)
panic("munmap failed, errno = %d\n",
-err);
- if(pte_present(*pte))
- map_memory(addr,
- pte_val(*pte) & PAGE_MASK,
- PAGE_SIZE, 1, 1, 1);
}
- else if(pte_newprot(*pte)){
+ addr += PGDIR_SIZE;
+ continue;
+ }
+
+ pud = pud_offset(pgd, addr);
+ if(!pud_present(*pud)){
+ if(pud_newpage(*pud)){
updated = 1;
- protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
+ last = addr + PUD_SIZE;
+ if(last > end)
+ last = end;
+ err = os_unmap_memory((void *) addr,
+ last - addr);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
}
- addr += PAGE_SIZE;
+ addr += PUD_SIZE;
+ continue;
}
- else {
+
+ pmd = pmd_offset(pud, addr);
+ if(!pmd_present(*pmd)){
if(pmd_newpage(*pmd)){
updated = 1;
- err = os_unmap_memory((void *) addr, PMD_SIZE);
+ last = addr + PMD_SIZE;
+ if(last > end)
+ last = end;
+ err = os_unmap_memory((void *) addr,
+ last - addr);
if(err < 0)
panic("munmap failed, errno = %d\n",
-err);
}
addr += PMD_SIZE;
+ continue;
+ }
+
+ pte = pte_offset_kernel(pmd, addr);
+ if(!pte_present(*pte) || pte_newpage(*pte)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ PAGE_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ if(pte_present(*pte))
+ map_memory(addr,
+ pte_val(*pte) & PAGE_MASK,
+ PAGE_SIZE, 1, 1, 1);
+ }
+ else if(pte_newprot(*pte)){
+ updated = 1;
+ protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
}
+ addr += PAGE_SIZE;
}
if(updated && update_seq) atomic_inc(&vmchange_seq);
}
@@ -155,6 +231,7 @@ void mprotect_kernel_vm(int w)
{
struct mm_struct *mm;
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
pte_t *pte;
unsigned long addr;
@@ -162,7 +239,8 @@ void mprotect_kernel_vm(int w)
mm = &init_mm;
for(addr = start_vm; addr < end_vm;){
pgd = pgd_offset(mm, addr);
- pmd = pmd_offset(pgd, addr);
+ pud = pud_offset(pgd, addr);
+ pmd = pmd_offset(pud, addr);
if(pmd_present(*pmd)){
pte = pte_offset_kernel(pmd, addr);
if(pte_present(*pte)) protect_vm_page(addr, w, 0);
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
index e1f3506e9d1d..de5dcd250425 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -84,6 +84,7 @@ void tracer_panic(char *format, ...)
va_start(ap, format);
vprintf(format, ap);
+ va_end(ap);
printf("\n");
while(1) pause();
}
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index 00bacacfcc35..67fdef69d54e 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_user.c
@@ -6,7 +6,6 @@
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
-#include <asm/sigcontext.h>
#include "sysdep/ptrace.h"
#include "signal_user.h"
#include "user_util.h"
diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c
index 0409718935f7..a72aa632972f 100644
--- a/arch/um/kernel/tt/uaccess.c
+++ b/arch/um/kernel/tt/uaccess.c
@@ -6,7 +6,7 @@
#include "linux/sched.h"
#include "asm/uaccess.h"
-int copy_from_user_tt(void *to, const void *from, int n)
+int copy_from_user_tt(void *to, const void __user *from, int n)
{
if(!access_ok_tt(VERIFY_READ, from, n))
return(n);
@@ -15,7 +15,7 @@ int copy_from_user_tt(void *to, const void *from, int n)
&current->thread.fault_catcher));
}
-int copy_to_user_tt(void *to, const void *from, int n)
+int copy_to_user_tt(void __user *to, const void *from, int n)
{
if(!access_ok_tt(VERIFY_WRITE, to, n))
return(n);
@@ -24,7 +24,7 @@ int copy_to_user_tt(void *to, const void *from, int n)
&current->thread.fault_catcher));
}
-int strncpy_from_user_tt(char *dst, const char *src, int count)
+int strncpy_from_user_tt(char *dst, const char __user *src, int count)
{
int n;
@@ -38,14 +38,14 @@ int strncpy_from_user_tt(char *dst, const char *src, int count)
return(n);
}
-int __clear_user_tt(void *mem, int len)
+int __clear_user_tt(void __user *mem, int len)
{
return(__do_clear_user(mem, len,
&current->thread.fault_addr,
&current->thread.fault_catcher));
}
-int clear_user_tt(void *mem, int len)
+int clear_user_tt(void __user *mem, int len)
{
if(!access_ok_tt(VERIFY_WRITE, mem, len))
return(len);
@@ -54,7 +54,7 @@ int clear_user_tt(void *mem, int len)
&current->thread.fault_catcher));
}
-int strnlen_user_tt(const void *str, int len)
+int strnlen_user_tt(const void __user *str, int len)
{
return(__do_strnlen_user(str, len,
&current->thread.fault_addr,
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 1ce25f89f8ac..8096843e4d4c 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -17,6 +17,7 @@
#include "linux/sysrq.h"
#include "linux/seq_file.h"
#include "linux/delay.h"
+#include "linux/module.h"
#include "asm/page.h"
#include "asm/pgtable.h"
#include "asm/ptrace.h"
@@ -156,6 +157,8 @@ static int __init uml_version_setup(char *line, int *add)
{
printf("%s\n", system_utsname.release);
exit(0);
+
+ return 0;
}
__uml_setup("--version", uml_version_setup,
@@ -256,6 +259,8 @@ static int __init Usage(char *line, int *add)
p++;
}
exit(0);
+
+ return 0;
}
__uml_setup("--help", Usage,
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 3521466db282..f8378124be13 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,10 +3,13 @@
# Licensed under the GPL
#
-obj-y = elf_aux.o file.o process.o time.o tty.o user_syms.o drivers/
+obj-y = elf_aux.o file.o process.o signal.o time.o tty.o user_syms.o drivers/ \
+ sys-$(SUBARCH)/
-USER_OBJS := elf_aux.o file.o process.o time.o tty.o
+USER_OBJS := elf_aux.o file.o process.o signal.o time.o tty.o
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+
+CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index 36575ff8bfac..9aee0b62ebca 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -26,7 +26,6 @@ unsigned long vsyscall_end;
unsigned long __kernel_vsyscall;
-
__init void scan_elf_aux( char **envp)
{
long page_size = 0;
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
new file mode 100644
index 000000000000..7eac1baf5975
--- /dev/null
+++ b/arch/um/os-Linux/signal.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2004 PathScale, Inc
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+#include "time_user.h"
+#include "mode.h"
+#include "sysdep/signal.h"
+
+void sig_handler(int sig)
+{
+ struct sigcontext *sc;
+
+ ARCH_GET_SIGCONTEXT(sc, sig);
+ CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
+ sig, sc);
+}
+
+extern int timer_irq_inited;
+
+void alarm_handler(int sig)
+{
+ struct sigcontext *sc;
+
+ ARCH_GET_SIGCONTEXT(sc, sig);
+ if(!timer_irq_inited) return;
+
+ if(sig == SIGALRM)
+ switch_timers(0);
+
+ CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
+ sig, sc);
+
+ if(sig == SIGALRM)
+ switch_timers(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/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile
new file mode 100644
index 000000000000..bdfa841fca16
--- /dev/null
+++ b/arch/um/os-Linux/sys-i386/Makefile
@@ -0,0 +1,11 @@
+#
+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+obj-$(CONFIG_MODE_SKAS) = registers.o
+
+USER_OBJS := $(foreach file,$(obj-y),$(obj)/$(file))
+
+$(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
new file mode 100644
index 000000000000..cbfbaf2ab78d
--- /dev/null
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2004 PathScale, Inc
+ * Licensed under the GPL
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <sys/ptrace.h>
+#include "sysdep/ptrace.h"
+#include "uml-config.h"
+#include "skas_ptregs.h"
+#include "registers.h"
+#include "user.h"
+
+/* These are set once at boot time and not changed thereafter */
+
+static unsigned long exec_regs[HOST_FRAME_SIZE];
+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));
+}
+
+static int move_registers(int pid, int int_op, union uml_pt_regs *regs,
+ int fp_op, unsigned long *fp_regs)
+{
+ if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
+ return(-errno);
+
+ if(ptrace(fp_op, pid, 0, fp_regs) < 0)
+ return(-errno);
+
+ return(0);
+}
+
+void save_registers(int pid, union uml_pt_regs *regs)
+{
+ 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);
+}
+
+void restore_registers(int pid, union uml_pt_regs *regs)
+{
+ unsigned long *fp_regs;
+ int err, fp_op;
+
+ 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)
+{
+ int err;
+
+ err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
+ if(err)
+ panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
+ err);
+
+ err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs);
+ if(!err)
+ return;
+
+ have_fpx_regs = 0;
+ if(err != EIO)
+ panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
+ err);
+
+ err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
+ if(err)
+ panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
+ err);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
new file mode 100644
index 000000000000..bdfa841fca16
--- /dev/null
+++ b/arch/um/os-Linux/sys-x86_64/Makefile
@@ -0,0 +1,11 @@
+#
+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+obj-$(CONFIG_MODE_SKAS) = registers.o
+
+USER_OBJS := $(foreach file,$(obj-y),$(obj)/$(file))
+
+$(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
new file mode 100644
index 000000000000..31b1f4fa67e0
--- /dev/null
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2004 PathScale, Inc
+ * Licensed under the GPL
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <sys/ptrace.h>
+#include "sysdep/ptrace.h"
+#include "uml-config.h"
+#include "skas_ptregs.h"
+#include "registers.h"
+#include "user.h"
+
+/* These are set once at boot time and not changed thereafter */
+
+static unsigned long exec_regs[HOST_FRAME_SIZE];
+static unsigned long exec_fp_regs[HOST_FP_SIZE];
+
+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",
+ err);
+
+ err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
+ if(err)
+ panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
+ err);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 383ac7b52beb..75d7af9ae1d2 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -26,9 +26,6 @@ EXPORT_SYMBOL(printf);
EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(vsyscall_ehdr);
-EXPORT_SYMBOL(vsyscall_end);
-
/* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
* However, the modules will use the CRC defined *here*, no matter if it is
* good; so the versions of these symbols will always match
@@ -37,6 +34,11 @@ EXPORT_SYMBOL(vsyscall_end);
int sym(void); \
EXPORT_SYMBOL(sym);
+#ifdef SUBARCH_i386
+EXPORT_SYMBOL(vsyscall_ehdr);
+EXPORT_SYMBOL(vsyscall_end);
+#endif
+
EXPORT_SYMBOL_PROTO(__errno_location);
EXPORT_SYMBOL_PROTO(access);
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 45cc75f63a75..8a0994b696b0 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -1,4 +1,4 @@
-obj-y = bitops.o bugs.o checksum.o fault.o ksyms.o ldt.o ptrace.o \
+obj-y = bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o
obj-$(CONFIG_HIGHMEM) += highmem.o
diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c
new file mode 100644
index 000000000000..20d37dbbaf08
--- /dev/null
+++ b/arch/um/sys-i386/delay.c
@@ -0,0 +1,14 @@
+void __delay(unsigned long time)
+{
+ /* Stolen from the i386 __loop_delay */
+ int d0;
+ __asm__ __volatile__(
+ "\tjmp 1f\n"
+ ".align 16\n"
+ "1:\tjmp 2f\n"
+ ".align 16\n"
+ "2:\tdecl %0\n\tjns 2b"
+ :"=&a" (d0)
+ :"0" (time));
+}
+
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index ba77ccaa8361..e97b98806af7 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -15,17 +15,21 @@ extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
/* XXX this needs copy_to_user and copy_from_user */
-int sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount)
+int sys_modify_ldt_tt(int func, void __user *ptr, unsigned long bytecount)
{
- if(verify_area(VERIFY_READ, ptr, bytecount)) return(-EFAULT);
- return(modify_ldt(func, ptr, bytecount));
+ if (verify_area(VERIFY_READ, ptr, bytecount))
+ return -EFAULT;
+
+ return modify_ldt(func, ptr, bytecount);
}
#endif
#ifdef CONFIG_MODE_SKAS
extern int userspace_pid;
-int sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
+#include "skas_ptrace.h"
+
+int sys_modify_ldt_skas(int func, void __user *ptr, unsigned long bytecount)
{
struct ptrace_ldt ldt;
void *buf;
@@ -74,7 +78,7 @@ int sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
}
#endif
-int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
+int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
{
return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func,
ptr, bytecount));
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index 42322d888503..c6a1bba337ea 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -3,6 +3,8 @@
* Licensed under the GPL
*/
+#include <linux/config.h>
+#include <linux/compiler.h>
#include "linux/sched.h"
#include "asm/elf.h"
#include "asm/ptrace.h"
@@ -22,7 +24,7 @@ int is_syscall(unsigned long addr)
unsigned short instr;
int n;
- n = copy_from_user(&instr, (void *) addr, sizeof(instr));
+ n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
if(n){
printk("is_syscall : failed to read instruction from 0x%lx\n",
addr);
@@ -175,12 +177,12 @@ static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave
*/
#ifdef CONFIG_MODE_TT
-static inline int convert_fxsr_to_user_tt(struct _fpstate *buf,
+static inline int convert_fxsr_to_user_tt(struct _fpstate __user *buf,
struct pt_regs *regs)
{
struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
unsigned long env[7];
- struct _fpreg *to;
+ struct _fpreg __user *to;
struct _fpxreg *from;
int i;
@@ -205,7 +207,7 @@ static inline int convert_fxsr_to_user_tt(struct _fpstate *buf,
}
#endif
-static inline int convert_fxsr_to_user(struct _fpstate *buf,
+static inline int convert_fxsr_to_user(struct _fpstate __user *buf,
struct pt_regs *regs)
{
return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0));
@@ -213,12 +215,12 @@ static inline int convert_fxsr_to_user(struct _fpstate *buf,
#ifdef CONFIG_MODE_TT
static inline int convert_fxsr_from_user_tt(struct pt_regs *regs,
- struct _fpstate *buf)
+ 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 *from;
+ struct _fpreg __user *from;
int i;
if ( __copy_from_user( env, buf, 7 * sizeof(long) ) )
@@ -244,7 +246,7 @@ static inline int convert_fxsr_from_user_tt(struct pt_regs *regs,
#endif
static inline int convert_fxsr_from_user(struct pt_regs *regs,
- struct _fpstate *buf)
+ struct _fpstate __user *buf)
{
return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs, buf), 0));
}
@@ -253,7 +255,7 @@ int get_fpregs(unsigned long buf, struct task_struct *child)
{
int err;
- err = convert_fxsr_to_user((struct _fpstate *) buf,
+ err = convert_fxsr_to_user((struct _fpstate __user *) buf,
&child->thread.regs);
if(err) return(-EFAULT);
else return(0);
@@ -264,7 +266,7 @@ int set_fpregs(unsigned long buf, struct task_struct *child)
int err;
err = convert_fxsr_from_user(&child->thread.regs,
- (struct _fpstate *) buf);
+ (struct _fpstate __user *) buf);
if(err) return(-EFAULT);
else return(0);
}
@@ -276,7 +278,7 @@ int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk)
struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
int err;
- err = __copy_to_user((void *) buf, fxsave,
+ err = __copy_to_user((void __user *) buf, fxsave,
sizeof(struct user_fxsr_struct));
if(err) return -EFAULT;
else return 0;
@@ -295,7 +297,7 @@ int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk)
struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
int err;
- err = __copy_from_user(fxsave, (void *) buf,
+ err = __copy_from_user(fxsave, (void __user *) buf,
sizeof(struct user_fxsr_struct) );
if(err) return -EFAULT;
else return 0;
diff --git a/arch/um/sys-i386/sigcontext.c b/arch/um/sys-i386/sigcontext.c
index a30140331cf7..467d489c31cd 100644
--- a/arch/um/sys-i386/sigcontext.c
+++ b/arch/um/sys-i386/sigcontext.c
@@ -22,8 +22,7 @@ void sc_to_sc(void *to_ptr, void *from_ptr)
unsigned long *sc_sigmask(void *sc_ptr)
{
struct sigcontext *sc = sc_ptr;
-
- return(&sc->oldmask);
+ return &sc->oldmask;
}
int sc_get_fpregs(unsigned long buf, void *sc_ptr)
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 6794671be7a3..0cb4c86b5c2b 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -146,7 +146,7 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
}
#endif
-static int copy_sc_from_user(struct pt_regs *to, void *from)
+static int copy_sc_from_user(struct pt_regs *to, void __user *from)
{
int ret;
diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c
index 6ad31749bfe7..dd58b5511e9b 100644
--- a/arch/um/sys-i386/syscalls.c
+++ b/arch/um/sys-i386/syscalls.c
@@ -1,9 +1,11 @@
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
#include "linux/sched.h"
+#include "linux/shm.h"
+#include "asm/ipc.h"
#include "asm/mman.h"
#include "asm/uaccess.h"
#include "asm/unistd.h"
@@ -28,7 +30,7 @@ extern int old_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long offset);
-int old_mmap_i386(struct mmap_arg_struct *arg)
+long old_mmap_i386(struct mmap_arg_struct __user *arg)
{
struct mmap_arg_struct a;
int err = -EFAULT;
@@ -43,11 +45,13 @@ int old_mmap_i386(struct mmap_arg_struct *arg)
struct sel_arg_struct {
unsigned long n;
- fd_set *inp, *outp, *exp;
- struct timeval *tvp;
+ fd_set __user *inp;
+ fd_set __user *outp;
+ fd_set __user *exp;
+ struct timeval __user *tvp;
};
-int old_select(struct sel_arg_struct *arg)
+long old_select(struct sel_arg_struct __user *arg)
{
struct sel_arg_struct a;
@@ -60,8 +64,8 @@ int old_select(struct sel_arg_struct *arg)
/* The i386 version skips reading from %esi, the fourth argument. So we must do
* this, too.
*/
-int sys_clone(unsigned long clone_flags, unsigned long newsp, int *parent_tid,
- int unused, int *child_tid)
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+ int __user *parent_tid, int unused, int __user *child_tid)
{
long ret;
@@ -79,6 +83,122 @@ int sys_clone(unsigned long clone_flags, unsigned long newsp, int *parent_tid,
}
/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+long sys_ipc (uint call, int first, int second,
+ int third, void *__user ptr, long fifth)
+{
+ int version, ret;
+
+ version = call >> 16; /* hack for backward compatibility */
+ call &= 0xffff;
+
+ switch (call) {
+ case SEMOP:
+ return sys_semtimedop(first, (struct sembuf *) ptr, second,
+ NULL);
+ case SEMTIMEDOP:
+ return sys_semtimedop(first, (struct sembuf *) ptr, second,
+ (const struct timespec *) fifth);
+ case SEMGET:
+ return sys_semget (first, second, third);
+ case SEMCTL: {
+ union semun fourth;
+ if (!ptr)
+ return -EINVAL;
+ if (get_user(fourth.__pad, (void **) ptr))
+ return -EFAULT;
+ return sys_semctl (first, second, third, fourth);
+ }
+
+ case MSGSND:
+ return sys_msgsnd (first, (struct msgbuf *) ptr,
+ second, third);
+ case MSGRCV:
+ switch (version) {
+ case 0: {
+ struct ipc_kludge tmp;
+ if (!ptr)
+ return -EINVAL;
+
+ if (copy_from_user(&tmp,
+ (struct ipc_kludge *) ptr,
+ sizeof (tmp)))
+ return -EFAULT;
+ return sys_msgrcv (first, tmp.msgp, second,
+ tmp.msgtyp, third);
+ }
+ default:
+ panic("msgrcv with version != 0");
+ return sys_msgrcv (first,
+ (struct msgbuf *) ptr,
+ second, fifth, third);
+ }
+ case MSGGET:
+ return sys_msgget ((key_t) first, second);
+ case MSGCTL:
+ return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+
+ case SHMAT:
+ switch (version) {
+ default: {
+ ulong raddr;
+ ret = do_shmat (first, (char *) ptr, second, &raddr);
+ if (ret)
+ return ret;
+ return put_user (raddr, (ulong *) third);
+ }
+ case 1: /* iBCS2 emulator entry point */
+ if (!segment_eq(get_fs(), get_ds()))
+ return -EINVAL;
+ return do_shmat (first, (char *) ptr, second, (ulong *) third);
+ }
+ case SHMDT:
+ return sys_shmdt ((char *)ptr);
+ case SHMGET:
+ return sys_shmget (first, second, third);
+ case SHMCTL:
+ return sys_shmctl (first, second,
+ (struct shmid_ds *) ptr);
+ default:
+ return -ENOSYS;
+ }
+}
+
+long sys_sigaction(int sig, const struct old_sigaction __user *act,
+ struct old_sigaction __user *oact)
+{
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+
+ if (act) {
+ old_sigset_t mask;
+ if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+ return -EFAULT;
+ __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ __get_user(mask, &act->sa_mask);
+ siginitset(&new_ka.sa.sa_mask, mask);
+ }
+
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+ if (!ret && oact) {
+ if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+ return -EFAULT;
+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+ }
+
+ 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
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
new file mode 100644
index 000000000000..1ec504b76810
--- /dev/null
+++ b/arch/um/sys-x86_64/Makefile
@@ -0,0 +1,39 @@
+#
+# Copyright 2003 PathScale, Inc.
+#
+# Licensed under the GPL
+#
+
+lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \
+ ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o \
+ syscalls.o sysrq.o thunk.o
+
+USER_OBJS := ptrace_user.o sigcontext.o
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+
+SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \
+ semaphore.c thunk.S
+SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f)
+
+clean-files := $(SYMLINKS)
+
+bitops.c-dir = lib
+csum-copy.S-dir = lib
+csum-partial.c-dir = lib
+csum-wrappers.c-dir = lib
+memcpy.S-dir = lib
+semaphore.c-dir = kernel
+thunk.S-dir = lib
+
+define make_link
+ -rm -f $1
+ ln -sf $(TOPDIR)/arch/x86_64/$($(notdir $1)-dir)/$(notdir $1) $1
+endef
+
+$(SYMLINKS):
+ $(call make_link,$@)
+
+$(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+
+CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial
diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c
new file mode 100644
index 000000000000..fdce7ea98ca7
--- /dev/null
+++ b/arch/um/sys-x86_64/bugs.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include "linux/sched.h"
+#include "linux/errno.h"
+#include "asm/system.h"
+#include "asm/pda.h"
+#include "sysdep/ptrace.h"
+#include "os.h"
+
+void arch_init_thread(void)
+{
+}
+
+void arch_check_bugs(void)
+{
+}
+
+int arch_handle_signal(int sig, union uml_pt_regs *regs)
+{
+ return(0);
+}
+
+#define MAXTOKEN 64
+
+/* Set during early boot */
+int host_has_cmov = 1;
+int host_has_xmm = 0;
+
+static char token(int fd, char *buf, int len, char stop)
+{
+ int n;
+ char *ptr, *end, c;
+
+ ptr = buf;
+ end = &buf[len];
+ do {
+ n = os_read_file(fd, ptr, sizeof(*ptr));
+ c = *ptr++;
+ if(n != sizeof(*ptr)){
+ if(n == 0) return(0);
+ printk("Reading /proc/cpuinfo failed, err = %d\n", -n);
+ if(n < 0)
+ return(n);
+ else
+ return(-EIO);
+ }
+ } while((c != '\n') && (c != stop) && (ptr < end));
+
+ if(ptr == end){
+ printk("Failed to find '%c' in /proc/cpuinfo\n", stop);
+ return(-1);
+ }
+ *(ptr - 1) = '\0';
+ return(c);
+}
+
+static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
+{
+ int n;
+ char c;
+
+ scratch[len - 1] = '\0';
+ while(1){
+ c = token(fd, scratch, len - 1, ':');
+ if(c <= 0)
+ return(0);
+ else if(c != ':'){
+ printk("Failed to find ':' in /proc/cpuinfo\n");
+ return(0);
+ }
+
+ if(!strncmp(scratch, key, strlen(key)))
+ return(1);
+
+ do {
+ n = os_read_file(fd, &c, sizeof(c));
+ if(n != sizeof(c)){
+ printk("Failed to find newline in "
+ "/proc/cpuinfo, err = %d\n", -n);
+ return(0);
+ }
+ } while(c != '\n');
+ }
+ return(0);
+}
+
+int cpu_feature(char *what, char *buf, int len)
+{
+ int fd, ret = 0;
+
+ fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
+ if(fd < 0){
+ printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
+ return(0);
+ }
+
+ if(!find_cpuinfo_line(fd, what, buf, len)){
+ printk("Couldn't find '%s' line in /proc/cpuinfo\n", what);
+ goto out_close;
+ }
+
+ token(fd, buf, len, '\n');
+ ret = 1;
+
+ out_close:
+ os_close_file(fd);
+ 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/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c
new file mode 100644
index 000000000000..f3b5187942b4
--- /dev/null
+++ b/arch/um/sys-x86_64/delay.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ * Copied from arch/x86_64
+ *
+ * Licensed under the GPL
+ */
+
+#include "asm/processor.h"
+
+void __delay(unsigned long loops)
+{
+ unsigned long i;
+
+ for(i = 0; i < loops; i++) ;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/sys-x86_64/fault.c b/arch/um/sys-x86_64/fault.c
new file mode 100644
index 000000000000..cee1513c5c31
--- /dev/null
+++ b/arch/um/sys-x86_64/fault.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include "user.h"
+
+int arch_fixup(unsigned long address, void *sc_ptr)
+{
+ /* XXX search_exception_tables() */
+ 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/arch/um/sys-x86_64/mem.c b/arch/um/sys-x86_64/mem.c
new file mode 100644
index 000000000000..3f59a0a4f156
--- /dev/null
+++ b/arch/um/sys-x86_64/mem.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include "linux/mm.h"
+#include "asm/page.h"
+#include "asm/mman.h"
+
+unsigned long vm_stack_flags = __VM_STACK_FLAGS;
+unsigned long vm_stack_flags32 = __VM_STACK_FLAGS;
+unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS;
+unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS;
+unsigned long vm_force_exec32 = PROT_EXEC;
+
+/* Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
new file mode 100644
index 000000000000..8c146b2a1e00
--- /dev/null
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#define __FRAME_OFFSETS
+#include "asm/ptrace.h"
+#include "linux/sched.h"
+#include "linux/errno.h"
+#include "asm/elf.h"
+
+/* 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)
+{
+ unsigned long tmp;
+
+#ifdef TIF_IA32
+ /* Some code in the 64bit emulation may not be 64bit clean.
+ Don't take any chances. */
+ if (test_tsk_thread_flag(child, TIF_IA32))
+ value &= 0xffffffff;
+#endif
+ switch (regno){
+ case FS:
+ case GS:
+ case DS:
+ case ES:
+ case SS:
+ case CS:
+ if (value && (value & 3) != 3)
+ return -EIO;
+ value &= 0xffff;
+ break;
+
+ case FS_BASE:
+ case GS_BASE:
+ if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
+ return -EIO;
+ break;
+
+ case EFLAGS:
+ value &= FLAG_MASK;
+ tmp = PT_REGS_EFLAGS(&child->thread.regs) & ~FLAG_MASK;
+ value |= tmp;
+ break;
+ }
+
+ PT_REGS_SET(&child->thread.regs, regno, value);
+ return 0;
+}
+
+unsigned long getreg(struct task_struct *child, int regno)
+{
+ unsigned long retval = ~0UL;
+ switch (regno) {
+ case FS:
+ case GS:
+ case DS:
+ case ES:
+ case SS:
+ case CS:
+ retval = 0xffff;
+ /* fall through */
+ default:
+ retval &= PT_REG(&child->thread.regs, regno);
+#ifdef TIF_IA32
+ if (test_tsk_thread_flag(child, TIF_IA32))
+ retval &= 0xffffffff;
+#endif
+ }
+ return retval;
+}
+
+void arch_switch(void)
+{
+/* XXX
+ printk("arch_switch\n");
+*/
+}
+
+int is_syscall(unsigned long addr)
+{
+ panic("is_syscall");
+}
+
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu )
+{
+ panic("dump_fpu");
+ return(1);
+}
+
+int get_fpregs(unsigned long buf, struct task_struct *child)
+{
+ panic("get_fpregs");
+ return(0);
+}
+
+int set_fpregs(unsigned long buf, struct task_struct *child)
+{
+ panic("set_fpregs");
+ return(0);
+}
+
+int get_fpxregs(unsigned long buf, struct task_struct *tsk)
+{
+ panic("get_fpxregs");
+ return(0);
+}
+
+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/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c
new file mode 100644
index 000000000000..e1f8bacc5f1a
--- /dev/null
+++ b/arch/um/sys-x86_64/ptrace_user.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include <stddef.h>
+#include <errno.h>
+#define __FRAME_OFFSETS
+#include <sys/ptrace.h>
+#include <asm/ptrace.h>
+#include "user.h"
+#include "kern_constants.h"
+
+int ptrace_getregs(long pid, unsigned long *regs_out)
+{
+ if(ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
+ return(-errno);
+ return(0);
+}
+
+int ptrace_setregs(long pid, unsigned long *regs)
+{
+ if(ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
+ return(-errno);
+ return(0);
+}
+
+void ptrace_pokeuser(unsigned long addr, unsigned long data)
+{
+ panic("ptrace_pokeuser");
+}
+
+#define DS 184
+#define ES 192
+#define __USER_DS 0x2b
+
+void arch_enter_kernel(void *task, int pid)
+{
+}
+
+void arch_leave_kernel(void *task, int pid)
+{
+#ifdef UM_USER_CS
+ if(ptrace(PTRACE_POKEUSER, pid, CS, UM_USER_CS) < 0)
+ tracer_panic("POKEUSER CS failed");
+#endif
+
+ if(ptrace(PTRACE_POKEUSER, pid, DS, __USER_DS) < 0)
+ tracer_panic("POKEUSER DS failed");
+ if(ptrace(PTRACE_POKEUSER, pid, ES, __USER_DS) < 0)
+ tracer_panic("POKEUSER ES failed");
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/sys-x86_64/sigcontext.c b/arch/um/sys-x86_64/sigcontext.c
new file mode 100644
index 000000000000..c88e64def6f2
--- /dev/null
+++ b/arch/um/sys-x86_64/sigcontext.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#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/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
new file mode 100644
index 000000000000..a5682f1d020d
--- /dev/null
+++ b/arch/um/sys-x86_64/signal.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2003 PathScale, Inc.
+ * Licensed under the GPL
+ */
+
+#include "linux/stddef.h"
+#include "linux/errno.h"
+#include "linux/personality.h"
+#include "linux/ptrace.h"
+#include "asm/current.h"
+#include "asm/uaccess.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"
+
+static int copy_sc_from_user_skas(struct pt_regs *regs,
+ struct sigcontext *from)
+{
+ 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
+
+ return(err);
+}
+
+int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
+ struct pt_regs *regs, unsigned long mask)
+{
+ unsigned long eflags;
+ 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.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);
+ err |= PUTREG(regs, RSP, to, rsp);
+ err |= PUTREG(regs, RBX, to, rbx);
+ err |= PUTREG(regs, RDX, to, rdx);
+ err |= PUTREG(regs, RCX, to, rcx);
+ err |= PUTREG(regs, RAX, to, rax);
+ err |= PUTREG(regs, R8, to, r8);
+ err |= PUTREG(regs, R9, to, r9);
+ err |= PUTREG(regs, R10, to, r10);
+ err |= PUTREG(regs, R11, to, r11);
+ err |= PUTREG(regs, R12, to, r12);
+ err |= PUTREG(regs, R13, to, r13);
+ err |= PUTREG(regs, R14, to, r14);
+ err |= PUTREG(regs, R15, to, r15);
+ err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */
+ err |= __put_user(current->thread.err, &to->err);
+ err |= __put_user(current->thread.trap_no, &to->trapno);
+ err |= PUTREG(regs, RIP, to, rip);
+ err |= PUTREG(regs, EFLAGS, to, eflags);
+#undef PUTREG
+
+ err |= __put_user(mask, &to->oldmask);
+ err |= __put_user(current->thread.cr2, &to->cr2);
+
+ return(err);
+}
+
+#endif
+
+#ifdef CONFIG_MODE_TT
+int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
+ int fpsize)
+{
+ struct _fpstate *to_fp, *from_fp;
+ unsigned long sigs;
+ int err;
+
+ to_fp = to->fpstate;
+ from_fp = from->fpstate;
+ sigs = to->oldmask;
+ err = copy_from_user(to, from, sizeof(*to));
+ to->oldmask = sigs;
+ return(err);
+}
+
+int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
+ struct sigcontext *from, int fpsize)
+{
+ struct _fpstate *to_fp, *from_fp;
+ int err;
+
+ to_fp = (fp ? fp : (struct _fpstate *) (to + 1));
+ from_fp = from->fpstate;
+ err = copy_to_user(to, from, sizeof(*to));
+ 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 *to, struct _fpstate *fp,
+ struct pt_regs *from, unsigned long mask)
+{
+ return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
+ sizeof(*fp)),
+ copy_sc_to_user_skas(to, fp, from, mask)));
+}
+
+struct rt_sigframe
+{
+ char *pretcode;
+ struct ucontext uc;
+ struct siginfo info;
+};
+
+#define round_down(m, n) (((m) / (n)) * (n))
+
+int setup_signal_stack_si(unsigned long stack_top, int sig,
+ struct k_sigaction *ka, struct pt_regs * regs,
+ siginfo_t *info, sigset_t *set)
+{
+ struct rt_sigframe __user *frame;
+ struct _fpstate __user *fp = NULL;
+ int err = 0;
+ struct task_struct *me = current;
+
+ frame = (struct rt_sigframe __user *)
+ round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8;
+ frame -= 128;
+
+ 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;
+
+ if (ka->sa.sa_flags & SA_SIGINFO) {
+ err |= copy_siginfo_to_user(&frame->info, info);
+ if (err)
+ goto out;
+ }
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)),
+ &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, fp, regs, set->sig[0]);
+ 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]);
+ }
+ else
+ 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. */
+ /* x86-64 should always use SA_RESTORER. */
+ if (ka->sa.sa_flags & SA_RESTORER)
+ err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
+ else
+ /* could use a vstub here */
+ goto out;
+
+ if (err)
+ goto out;
+
+ /* Set up registers for signal handler */
+ {
+ struct exec_domain *ed = current_thread_info()->exec_domain;
+ if (unlikely(ed && ed->signal_invmap && sig < 32))
+ sig = ed->signal_invmap[sig];
+ }
+
+ PT_REGS_RDI(regs) = 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. */
+ 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;
+
+ PT_REGS_RSP(regs) = (unsigned long) frame;
+ out:
+ return(err);
+}
+
+long sys_rt_sigreturn(struct pt_regs *regs)
+{
+ unsigned long __user sp = PT_REGS_SP(&current->thread.regs);
+ struct rt_sigframe __user *frame =
+ (struct rt_sigframe __user *)(sp - 8);
+ struct ucontext __user *uc = &frame->uc;
+ sigset_t set;
+
+ if(copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
+ goto segfault;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+
+ spin_lock_irq(&current->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ if(copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
+ goto segfault;
+
+ /* Avoid ERESTART handling */
+ PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
+ return(PT_REGS_SYSCALL_RET(&current->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/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
new file mode 100644
index 000000000000..4c61dcc0901f
--- /dev/null
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include "linux/linkage.h"
+#include "linux/slab.h"
+#include "linux/shm.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"
+
+asmlinkage long wrap_sys_shmat(int shmid, char __user *shmaddr, int shmflg)
+{
+ unsigned long raddr;
+
+ return do_shmat(shmid, shmaddr, shmflg, &raddr) ?: (long) raddr;
+}
+
+#ifdef CONFIG_MODE_TT
+extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
+
+long sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount)
+{
+ /* XXX This should check VERIFY_WRITE depending on func, check this
+ * in i386 as well.
+ */
+ if(verify_area(VERIFY_READ, ptr, bytecount))
+ return(-EFAULT);
+ return(modify_ldt(func, ptr, bytecount));
+}
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+extern int userspace_pid;
+
+#ifndef __NR_mm_indirect
+#define __NR_mm_indirect 241
+#endif
+
+long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
+{
+ unsigned long args[6];
+ void *buf;
+ int res, n;
+
+ buf = kmalloc(bytecount, GFP_KERNEL);
+ if(buf == NULL)
+ return(-ENOMEM);
+
+ res = 0;
+
+ switch(func){
+ case 1:
+ case 0x11:
+ res = copy_from_user(buf, ptr, bytecount);
+ break;
+ }
+
+ if(res != 0){
+ res = -EFAULT;
+ goto out;
+ }
+
+ args[0] = func;
+ args[1] = (unsigned long) buf;
+ args[2] = bytecount;
+ res = syscall(__NR_mm_indirect, &current->mm->context.u,
+ __NR_modify_ldt, args);
+
+ if(res < 0)
+ goto out;
+
+ switch(func){
+ case 0:
+ case 2:
+ n = res;
+ res = copy_to_user(ptr, buf, n);
+ if(res != 0)
+ res = -EFAULT;
+ else
+ res = n;
+ break;
+ }
+
+ out:
+ kfree(buf);
+ return(res);
+}
+#endif
+
+long sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
+{
+ return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func,
+ ptr, bytecount));
+}
+
+#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, &addr);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return(ret);
+}
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+
+static long arch_prctl_skas(int code, unsigned long addr)
+{
+ long ret = 0;
+
+ switch(code){
+ case ARCH_SET_GS:
+ current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr;
+ break;
+ case ARCH_SET_FS:
+ current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr;
+ break;
+ case ARCH_GET_FS:
+ ret = put_user(current->thread.regs.regs.skas.regs[GS / sizeof(unsigned long)], &addr);
+ break;
+ case ARCH_GET_GS:
+ ret = put_user(current->thread.regs.regs.skas.regs[FS / sizeof(unsigned \
+long)], &addr);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return(ret);
+}
+#endif
+
+long sys_arch_prctl(int code, unsigned long addr)
+{
+ return(CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code, addr));
+}
+
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+ void __user *parent_tid, void __user *child_tid)
+{
+ long ret;
+
+ /* XXX: normal arch do here this pass, and also pass the regs to
+ * do_fork, instead of NULL. Currently the arch-independent code
+ * ignores these values, while the UML code (actually it's
+ * copy_thread) does the right thing. But this should change,
+ probably. */
+ /*if (!newsp)
+ newsp = UPT_SP(current->thread.regs);*/
+ current->thread.forking = 1;
+ ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid);
+ current->thread.forking = 0;
+ 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/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c
new file mode 100644
index 000000000000..c33f85f9e8bb
--- /dev/null
+++ b/arch/um/sys-x86_64/sysrq.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include "linux/kernel.h"
+#include "linux/version.h"
+#include "linux/module.h"
+#include "asm/current.h"
+#include "asm/ptrace.h"
+#include "sysrq.h"
+
+void __show_regs(struct pt_regs * regs)
+{
+ printk("\n");
+ print_modules();
+ printk("Pid: %d, comm: %.20s %s %s\n",
+ current->pid, current->comm, print_tainted(), UTS_RELEASE);
+ printk("RIP: %04lx:[<%016lx>] ", PT_REGS_CS(regs) & 0xffff,
+ PT_REGS_RIP(regs));
+ printk("\nRSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs),
+ PT_REGS_EFLAGS(regs));
+ printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
+ PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
+ printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
+ PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs));
+ printk("RBP: %016lx R08: %016lx R09: %016lx\n",
+ PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
+ printk("R10: %016lx R11: %016lx R12: %016lx\n",
+ PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
+ printk("R13: %016lx R14: %016lx R15: %016lx\n",
+ PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs));
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ __show_regs(regs);
+ show_trace((unsigned long *) &regs);
+}
+
+/* Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/sys-x86_64/util/Makefile b/arch/um/sys-x86_64/util/Makefile
new file mode 100644
index 000000000000..002607980864
--- /dev/null
+++ b/arch/um/sys-x86_64/util/Makefile
@@ -0,0 +1,10 @@
+# Copyright 2003 - 2004 Pathscale, Inc
+# Released under the GPL
+
+hostprogs-y := mk_sc mk_thread
+always := $(hostprogs-y)
+
+mk_thread-objs := mk_thread_kern.o mk_thread_user.o
+
+HOSTCFLAGS_mk_thread_kern.o := $(CFLAGS) $(CPPFLAGS)
+HOSTCFLAGS_mk_thread_user.o := $(USER_CFLAGS)
diff --git a/arch/um/sys-x86_64/util/mk_sc.c b/arch/um/sys-x86_64/util/mk_sc.c
new file mode 100644
index 000000000000..c236e213918d
--- /dev/null
+++ b/arch/um/sys-x86_64/util/mk_sc.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 2003 - 2004 PathScale, Inc
+ * Released under the GPL
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <linux/stddef.h>
+
+#define SC_OFFSET(name, field) \
+ printf("#define " name \
+ "(sc) *((unsigned long *) &(((char *) (sc))[%ld]))\n",\
+ offsetof(struct sigcontext, field))
+
+#define SC_FP_OFFSET(name, field) \
+ printf("#define " name \
+ "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%ld]))\n",\
+ offsetof(struct _fpstate, field))
+
+#define SC_FP_OFFSET_PTR(name, field, type) \
+ printf("#define " name \
+ "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\
+ offsetof(struct _fpstate, field))
+
+int main(int argc, char **argv)
+{
+ SC_OFFSET("SC_RBX", rbx);
+ SC_OFFSET("SC_RCX", rcx);
+ SC_OFFSET("SC_RDX", rdx);
+ SC_OFFSET("SC_RSI", rsi);
+ SC_OFFSET("SC_RDI", rdi);
+ SC_OFFSET("SC_RBP", rbp);
+ SC_OFFSET("SC_RAX", rax);
+ SC_OFFSET("SC_R8", r8);
+ SC_OFFSET("SC_R9", r9);
+ SC_OFFSET("SC_R10", r10);
+ SC_OFFSET("SC_R11", r11);
+ SC_OFFSET("SC_R12", r12);
+ SC_OFFSET("SC_R13", r13);
+ SC_OFFSET("SC_R14", r14);
+ SC_OFFSET("SC_R15", r15);
+ SC_OFFSET("SC_IP", rip);
+ SC_OFFSET("SC_SP", rsp);
+ SC_OFFSET("SC_CR2", cr2);
+ SC_OFFSET("SC_ERR", err);
+ SC_OFFSET("SC_TRAPNO", trapno);
+ SC_OFFSET("SC_CS", cs);
+ SC_OFFSET("SC_FS", fs);
+ SC_OFFSET("SC_GS", gs);
+ SC_OFFSET("SC_EFLAGS", eflags);
+ SC_OFFSET("SC_SIGMASK", oldmask);
+#if 0
+ SC_OFFSET("SC_ORIG_RAX", orig_rax);
+ SC_OFFSET("SC_DS", ds);
+ SC_OFFSET("SC_ES", es);
+ SC_OFFSET("SC_SS", ss);
+#endif
+ return(0);
+}
diff --git a/arch/um/sys-x86_64/util/mk_thread_kern.c b/arch/um/sys-x86_64/util/mk_thread_kern.c
new file mode 100644
index 000000000000..a281673f02b2
--- /dev/null
+++ b/arch/um/sys-x86_64/util/mk_thread_kern.c
@@ -0,0 +1,21 @@
+#include "linux/config.h"
+#include "linux/stddef.h"
+#include "linux/sched.h"
+
+extern void print_head(void);
+extern void print_constant_ptr(char *name, int value);
+extern void print_constant(char *name, char *type, int value);
+extern void print_tail(void);
+
+#define THREAD_OFFSET(field) offsetof(struct task_struct, thread.field)
+
+int main(int argc, char **argv)
+{
+ print_head();
+#ifdef CONFIG_MODE_TT
+ print_constant("TASK_EXTERN_PID", "int", THREAD_OFFSET(mode.tt.extern_pid));
+#endif
+ print_tail();
+ return(0);
+}
+
diff --git a/arch/um/sys-x86_64/util/mk_thread_user.c b/arch/um/sys-x86_64/util/mk_thread_user.c
new file mode 100644
index 000000000000..7989725568b8
--- /dev/null
+++ b/arch/um/sys-x86_64/util/mk_thread_user.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+
+void print_head(void)
+{
+ printf("/*\n");
+ printf(" * Generated by mk_thread\n");
+ printf(" */\n");
+ printf("\n");
+ printf("#ifndef __UM_THREAD_H\n");
+ printf("#define __UM_THREAD_H\n");
+ printf("\n");
+}
+
+void print_constant_ptr(char *name, int value)
+{
+ printf("#define %s(task) ((unsigned long *) "
+ "&(((char *) (task))[%d]))\n", name, value);
+}
+
+void print_constant(char *name, char *type, int value)
+{
+ printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type,
+ value);
+}
+
+void print_tail(void)
+{
+ printf("\n");
+ printf("#endif\n");
+}
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 47339a83c995..5186d2a4c4e9 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -251,7 +251,7 @@ config PREEMPT
config PREEMPT_BKL
bool "Preempt The Big Kernel Lock"
- depends on PREEMPT || SMP
+ depends on PREEMPT
default y
help
This option reduces the latency of the kernel by making the
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index a69f7bcdfc2c..6f90c246c418 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -59,6 +59,8 @@ endif
# -funit-at-a-time shrinks the kernel .text considerably
# unfortunately it makes reading oopses harder.
CFLAGS += $(call cc-option,-funit-at-a-time)
+# prevent gcc from generating any FP code by mistake
+CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 06d778083fee..941e9b930081 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc1-bk6
-# Thu Oct 28 00:07:32 2004
+# Linux kernel version: 2.6.10-bk7
+# Fri Jan 7 06:27:52 2005
#
CONFIG_X86_64=y
CONFIG_64BIT=y
@@ -45,6 +45,10 @@ CONFIG_FUTEX=y
CONFIG_EPOLL=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
#
@@ -88,6 +92,7 @@ CONFIG_NR_CPUS=8
CONFIG_GART_IOMMU=y
CONFIG_SWIOTLB=y
CONFIG_X86_MCE=y
+CONFIG_X86_MCE_INTEL=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -110,10 +115,13 @@ CONFIG_ACPI_SLEEP_PROC_FS=y
CONFIG_ACPI_AC=y
CONFIG_ACPI_BATTERY=y
CONFIG_ACPI_BUTTON=y
+# CONFIG_ACPI_VIDEO is not set
CONFIG_ACPI_FAN=y
CONFIG_ACPI_PROCESSOR=y
CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_NUMA=y
# CONFIG_ACPI_ASUS is not set
+# CONFIG_ACPI_IBM is not set
CONFIG_ACPI_TOSHIBA=y
CONFIG_ACPI_BLACKLIST_YEAR=2001
CONFIG_ACPI_DEBUG=y
@@ -122,11 +130,35 @@ CONFIG_ACPI_EC=y
CONFIG_ACPI_POWER=y
CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
+# CONFIG_ACPI_CONTAINER is not set
#
# CPU Frequency scaling
#
-# CONFIG_CPU_FREQ is not set
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_PROC_INTF=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_24_API=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_TABLE=y
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_X86_POWERNOW_K8_ACPI=y
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+CONFIG_X86_ACPI_CPUFREQ=y
+
+#
+# shared options
+#
+CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y
#
# Bus options (PCI etc.)
@@ -174,6 +206,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNP is not set
#
# Block devices
@@ -189,6 +222,7 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
@@ -292,6 +326,7 @@ CONFIG_BLK_DEV_SD=y
#
# CONFIG_SCSI_SPI_ATTRS is not set
# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
#
# SCSI low-level drivers
@@ -337,14 +372,12 @@ CONFIG_SCSI_SATA_VIA=y
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLOGIC_1280_1040 is not set
CONFIG_SCSI_QLA2XXX=y
# CONFIG_SCSI_QLA21XX is not set
# CONFIG_SCSI_QLA22XX is not set
# CONFIG_SCSI_QLA2300 is not set
# CONFIG_SCSI_QLA2322 is not set
# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
@@ -397,6 +430,8 @@ CONFIG_IP_MULTICAST=y
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+CONFIG_IP_TCPDIAG_IPV6=y
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_INET6_AH is not set
@@ -508,7 +543,9 @@ CONFIG_TIGON3=y
# Ethernet (10000 Mbit)
#
# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
+CONFIG_S2IO=m
+# CONFIG_S2IO_NAPI is not set
+# CONFIG_2BUFF_MODE is not set
#
# Token Ring devices
@@ -743,6 +780,7 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
#
# USB Device Class drivers
@@ -752,6 +790,10 @@ CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_MIDI is not set
# CONFIG_USB_ACM is not set
CONFIG_USB_PRINTER=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_RW_DETECT is not set
@@ -797,7 +839,7 @@ CONFIG_USB_HIDINPUT=y
#
#
-# USB Network adaptors
+# USB Network Adapters
#
# CONFIG_USB_CATC is not set
# CONFIG_USB_KAWETH is not set
@@ -840,6 +882,16 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
# Firmware Drivers
#
# CONFIG_EDD is not set
@@ -870,6 +922,7 @@ CONFIG_FS_POSIX_ACL=y
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
@@ -884,8 +937,11 @@ CONFIG_ISO9660_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
@@ -951,7 +1007,46 @@ CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=y
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
#
# Profiling support
@@ -972,6 +1067,7 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_INFO is not set
CONFIG_INIT_DEBUG=y
# CONFIG_IOMMU_DEBUG is not set
+CONFIG_KPROBES=y
#
# Security options
@@ -985,6 +1081,10 @@ CONFIG_INIT_DEBUG=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c
index 6ac57fcf1340..2014f2113cd8 100644
--- a/arch/x86_64/ia32/ia32_aout.c
+++ b/arch/x86_64/ia32/ia32_aout.c
@@ -115,7 +115,9 @@ static void set_brk(unsigned long start, unsigned long end)
end = PAGE_ALIGN(end);
if (end <= start)
return;
+ down_write(&current->mm->mmap_sem);
do_brk(start, end - start);
+ up_write(&current->mm->mmap_sem);
}
#if CORE_DUMP
@@ -325,7 +327,10 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
pos = 32;
map_size = ex.a_text+ex.a_data;
+ down_write(&current->mm->mmap_sem);
error = do_brk(text_addr & PAGE_MASK, map_size);
+ up_write(&current->mm->mmap_sem);
+
if (error != (text_addr & PAGE_MASK)) {
send_sig(SIGKILL, current, 0);
return error;
@@ -361,7 +366,9 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
loff_t pos = fd_offset;
+ down_write(&current->mm->mmap_sem);
do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
+ up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex),
ex.a_text+ex.a_data, &pos);
flush_icache_range((unsigned long) N_TXTADDR(ex),
@@ -469,8 +476,9 @@ static int load_aout_library(struct file *file)
error_time = jiffies;
}
#endif
-
+ down_write(&current->mm->mmap_sem);
do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+ up_write(&current->mm->mmap_sem);
file->f_op->read(file, (char *)start_addr,
ex.a_text + ex.a_data, &pos);
@@ -494,7 +502,9 @@ static int load_aout_library(struct file *file)
len = PAGE_ALIGN(ex.a_text + ex.a_data);
bss = ex.a_text + ex.a_data + ex.a_bss;
if (bss > len) {
+ down_write(&current->mm->mmap_sem);
error = do_brk(start_addr + len, bss - len);
+ up_write(&current->mm->mmap_sem);
retval = error;
if (error != start_addr + len)
goto out;
diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
index 16854c4faa64..7b78206dd90b 100644
--- a/arch/x86_64/ia32/ia32_signal.c
+++ b/arch/x86_64/ia32/ia32_signal.c
@@ -261,6 +261,12 @@ ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 __user *sc,
if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
goto badframe;
err |= restore_i387_ia32(current, buf, 0);
+ } else {
+ struct task_struct *me = current;
+ if (me->used_math) {
+ clear_fpu(me);
+ me->used_math = 0;
+ }
}
}
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 4210fa0e6918..270f8ca873ae 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -587,6 +587,10 @@ ia32_sys_call_table:
.quad compat_sys_mq_getsetattr
.quad quiet_ni_syscall /* reserved for kexec */
.quad sys32_waitid
+ .quad quiet_ni_syscall /* sys_altroot */
+ .quad sys_add_key
+ .quad sys_request_key
+ .quad sys_keyctl
/* don't forget to change IA32_NR_syscalls */
ia32_syscall_end:
.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index 1d8b3912c1d9..4baa99fe1e5c 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -200,8 +200,8 @@ static __u32 __init search_agp_bridge(u32 *order, int *valid_agp)
void __init iommu_hole_init(void)
{
int fix, num;
- u32 aper_size, aper_alloc = 0, aper_order;
- u64 aper_base;
+ u32 aper_size, aper_alloc = 0, aper_order, last_aper_order = 0;
+ u64 aper_base, last_aper_base = 0;
int valid_agp = 0;
if (iommu_aperture_disabled || !fix_aperture)
@@ -230,7 +230,15 @@ void __init iommu_hole_init(void)
if (!aperture_valid(name, aper_base, aper_size)) {
fix = 1;
break;
- }
+ }
+
+ if ((last_aper_order && aper_order != last_aper_order) ||
+ (last_aper_base && aper_base != last_aper_base)) {
+ fix = 1;
+ break;
+ }
+ last_aper_order = aper_order;
+ last_aper_base = aper_base;
}
if (!fix && !fallback_aper_force)
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index cd37a0aa66f3..dbccec4894c0 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -225,6 +225,11 @@ int __init verify_local_APIC(void)
void __init sync_Arb_IDs(void)
{
+ /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */
+ unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
+ if (ver >= 0x14) /* P4 or higher */
+ return;
+
/*
* Wait for idle.
*/
diff --git a/arch/x86_64/kernel/genapic.c b/arch/x86_64/kernel/genapic.c
index 9aa5cb6af660..d2c42fb99cb3 100644
--- a/arch/x86_64/kernel/genapic.c
+++ b/arch/x86_64/kernel/genapic.c
@@ -41,6 +41,12 @@ void __init clustered_apic_check(void)
u8 id;
u8 cluster_cnt[NUM_APIC_CLUSTERS];
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
+ /* AMD always uses flat mode right now */
+ genapic = &apic_flat;
+ goto print;
+ }
+
memset(cluster_cnt, 0, sizeof(cluster_cnt));
for (i = 0; i < NR_CPUS; i++) {
@@ -71,6 +77,7 @@ void __init clustered_apic_check(void)
else
genapic = &apic_cluster;
+print:
printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
}
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 766a7d6ef9b0..30e92ff8b3c0 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -355,7 +355,7 @@ ENTRY(cpu_gdt_table)
.quad 0x008f9a000000ffff /* __KERNEL_COMPAT32_CS */
.quad 0x00af9a000000ffff /* __KERNEL_CS */
.quad 0x00cf92000000ffff /* __KERNEL_DS */
- .quad 0x00cffe000000ffff /* __USER32_CS */
+ .quad 0x00cffa000000ffff /* __USER32_CS */
.quad 0x00cff2000000ffff /* __USER_DS, __USER32_DS */
.quad 0x00affa000000ffff /* __USER_CS */
.quad 0x00cf9a000000ffff /* __KERNEL32_CS */
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
index 5254e90a8113..6cad46c98a23 100644
--- a/arch/x86_64/kernel/head64.c
+++ b/arch/x86_64/kernel/head64.c
@@ -61,16 +61,17 @@ static void __init copy_bootdata(char *real_mode_data)
static void __init setup_boot_cpu_data(void)
{
- int dummy, eax;
+ unsigned int dummy, eax;
/* get vendor info */
- cpuid(0, &boot_cpu_data.cpuid_level,
- (int *)&boot_cpu_data.x86_vendor_id[0],
- (int *)&boot_cpu_data.x86_vendor_id[8],
- (int *)&boot_cpu_data.x86_vendor_id[4]);
+ cpuid(0, (unsigned int *)&boot_cpu_data.cpuid_level,
+ (unsigned int *)&boot_cpu_data.x86_vendor_id[0],
+ (unsigned int *)&boot_cpu_data.x86_vendor_id[8],
+ (unsigned int *)&boot_cpu_data.x86_vendor_id[4]);
/* get cpu type */
- cpuid(1, &eax, &dummy, &dummy, (int *) &boot_cpu_data.x86_capability);
+ cpuid(1, &eax, &dummy, &dummy,
+ (unsigned int *) &boot_cpu_data.x86_capability);
boot_cpu_data.x86 = (eax >> 8) & 0xf;
boot_cpu_data.x86_model = (eax >> 4) & 0xf;
boot_cpu_data.x86_mask = eax & 0xf;
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index c22a8f045ecf..7b568f14b5ec 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -1160,13 +1160,6 @@ static void __init setup_ioapic_ids_from_mpc (void)
old_id = mp_ioapics[apic].mpc_apicid;
- if (mp_ioapics[apic].mpc_apicid >= 0xf) {
- apic_printk(APIC_QUIET,KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
- apic, mp_ioapics[apic].mpc_apicid);
- apic_printk(APIC_QUIET,KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
- reg_00.bits.ID);
- mp_ioapics[apic].mpc_apicid = reg_00.bits.ID;
- }
printk(KERN_INFO "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid);
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 6e717e470460..b05d3b19278d 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -31,6 +31,8 @@ static int mce_dont_init;
static int tolerant = 1;
static int banks;
static unsigned long bank[NR_BANKS] = { [0 ... NR_BANKS-1] = ~0UL };
+static unsigned long console_logged;
+static int notify_user;
/*
* Lockless MCE logging infrastructure.
@@ -68,6 +70,9 @@ void mce_log(struct mce *mce)
smp_wmb();
mcelog.entry[entry].finished = 1;
smp_wmb();
+
+ if (!test_and_set_bit(0, &console_logged))
+ notify_user = 1;
}
static void print_mce(struct mce *m)
@@ -252,6 +257,19 @@ static void mcheck_timer(void *data)
{
on_each_cpu(mcheck_check_cpu, NULL, 1, 1);
schedule_delayed_work(&mcheck_work, check_interval * HZ);
+
+ /*
+ * It's ok to read stale data here for notify_user and
+ * console_logged as we'll simply get the updated versions
+ * on the next mcheck_timer execution and atomic operations
+ * on console_logged act as synchronization for notify_user
+ * writes.
+ */
+ if (notify_user && console_logged) {
+ notify_user = 0;
+ clear_bit(0, &console_logged);
+ printk(KERN_INFO "Machine check events logged\n");
+ }
}
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index 1f415db882d1..7f5f57e54740 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -576,7 +576,6 @@ static int __init smp_scan_config (unsigned long base, unsigned long length)
extern void __bad_mpf_size(void);
unsigned int *bp = phys_to_virt(base);
struct intel_mp_floating *mpf;
- static int printed __initdata;
Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
if (sizeof(*mpf) != 16)
@@ -600,10 +599,6 @@ static int __init smp_scan_config (unsigned long base, unsigned long length)
bp += 4;
length -= 16;
}
- if (!printed) {
- printk(KERN_INFO "No mptable found.\n");
- printed = 1;
- }
return 0;
}
@@ -640,7 +635,11 @@ void __init find_intel_smp (void)
address = *(unsigned short *)phys_to_virt(0x40E);
address <<= 4;
- smp_scan_config(address, 0x1000);
+ if (smp_scan_config(address, 0x1000))
+ return;
+
+ /* If we have come this far, we did not find an MP table */
+ printk(KERN_INFO "No mptable found.\n");
}
/*
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 1bf8d4e95e92..407d42b2dc55 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -493,7 +493,7 @@ void __init setup_arch(char **cmdline_p)
check_efer();
- init_memory_mapping();
+ init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
#ifdef CONFIG_ACPI_BOOT
/*
@@ -657,18 +657,18 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
- c->x86_cache_size=(ecx>>24)+(edx>>24);
- /* DTLB and ITLB together, but only 4K */
- c->x86_tlbsize = ((ebx>>16)&0xff) + (ebx&0xff);
+ c->x86_cache_size=(ecx>>24)+(edx>>24);
+ /* On K8 L1 TLB is inclusive, so don't count it */
+ c->x86_tlbsize = 0;
}
if (n >= 0x80000006) {
cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);
- ecx = cpuid_ecx(0x80000006);
- c->x86_cache_size = ecx >> 16;
+ ecx = cpuid_ecx(0x80000006);
+ c->x86_cache_size = ecx >> 16;
c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);
- printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
+ printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
c->x86_cache_size, ecx & 0xFF);
}
@@ -849,10 +849,10 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
memset(&c->x86_capability, 0, sizeof c->x86_capability);
/* Get vendor name */
- cpuid(0x00000000, &c->cpuid_level,
- (int *)&c->x86_vendor_id[0],
- (int *)&c->x86_vendor_id[8],
- (int *)&c->x86_vendor_id[4]);
+ cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
+ (unsigned int *)&c->x86_vendor_id[0],
+ (unsigned int *)&c->x86_vendor_id[8],
+ (unsigned int *)&c->x86_vendor_id[4]);
get_cpu_vendor(c);
@@ -892,19 +892,19 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
/* AMD-defined flags: level 0x80000001 */
xlvl = cpuid_eax(0x80000000);
- if ( (xlvl & 0xffff0000) == 0x80000000 ) {
- if ( xlvl >= 0x80000001 ) {
+ if ((xlvl & 0xffff0000) == 0x80000000) {
+ if (xlvl >= 0x80000001) {
c->x86_capability[1] = cpuid_edx(0x80000001);
c->x86_capability[5] = cpuid_ecx(0x80000001);
}
- if ( xlvl >= 0x80000004 )
+ if (xlvl >= 0x80000004)
get_model_name(c); /* Default name */
}
/* Transmeta-defined flags: level 0x80860001 */
xlvl = cpuid_eax(0x80860000);
- if ( (xlvl & 0xffff0000) == 0x80860000 ) {
- if ( xlvl >= 0x80860001 )
+ if ((xlvl & 0xffff0000) == 0x80860000) {
+ if (xlvl >= 0x80860001)
c->x86_capability[2] = cpuid_edx(0x80860001);
}
@@ -918,20 +918,19 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
* At the end of this section, c->x86_capability better
* indicate the features this CPU genuinely supports!
*/
- switch ( c->x86_vendor ) {
-
- case X86_VENDOR_AMD:
- init_amd(c);
- break;
+ switch (c->x86_vendor) {
+ case X86_VENDOR_AMD:
+ init_amd(c);
+ break;
- case X86_VENDOR_INTEL:
- init_intel(c);
- break;
+ case X86_VENDOR_INTEL:
+ init_intel(c);
+ break;
- case X86_VENDOR_UNKNOWN:
- default:
- display_cacheinfo(c);
- break;
+ case X86_VENDOR_UNKNOWN:
+ default:
+ display_cacheinfo(c);
+ break;
}
select_idle_routine(c);
@@ -944,9 +943,9 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
* common between the CPUs. The first time this routine gets
* executed, c == &boot_cpu_data.
*/
- if ( c != &boot_cpu_data ) {
+ if (c != &boot_cpu_data) {
/* AND the already accumulated flags with these */
- for ( i = 0 ; i < NCAPINTS ; i++ )
+ for (i = 0 ; i < NCAPINTS ; i++)
boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
}
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
index e9aa2ca0b55d..ad3b240cdd9c 100644
--- a/arch/x86_64/kernel/signal.c
+++ b/arch/x86_64/kernel/signal.c
@@ -125,6 +125,12 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned
if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
goto badframe;
err |= restore_i387(buf);
+ } else {
+ struct task_struct *me = current;
+ if (me->used_math) {
+ clear_fpu(me);
+ me->used_math = 0;
+ }
}
}
@@ -139,7 +145,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
sigset_t set;
- long eax;
+ unsigned long eax;
frame = (struct rt_sigframe __user *)(regs->rsp - 8);
if (verify_area(VERIFY_READ, frame, sizeof(*frame))) {
diff --git a/arch/x86_64/lib/io.c b/arch/x86_64/lib/io.c
index df68a2623736..87b4a4e18039 100644
--- a/arch/x86_64/lib/io.c
+++ b/arch/x86_64/lib/io.c
@@ -13,3 +13,11 @@ void __memcpy_fromio(void *dst,unsigned long src,unsigned len)
__inline_memcpy(dst,(const void *) src,len);
}
EXPORT_SYMBOL(__memcpy_fromio);
+
+void memset_io(volatile void __iomem *a, int b, size_t c)
+{
+ /* XXX: memset can mangle the IO patterns quite a bit.
+ perhaps it would be better to use a dumb one */
+ memset((void *)a,b,c);
+}
+EXPORT_SYMBOL(memset_io);
diff --git a/arch/x86_64/lib/old-checksum.c b/arch/x86_64/lib/old-checksum.c
deleted file mode 100644
index 20d5b8f633d3..000000000000
--- a/arch/x86_64/lib/old-checksum.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Temporal C versions of the checksum functions until optimized assembler versions
- * can go in.
- */
-
-#include <net/checksum.h>
-
-/*
- * Copy from userspace and compute checksum. If we catch an exception
- * then zero the rest of the buffer.
- */
-unsigned int csum_partial_copy_from_user (const char *src, char *dst,
- int len, unsigned int sum,
- int *err_ptr)
-{
- int missing;
-
- missing = copy_from_user(dst, src, len);
- if (missing) {
- memset(dst + len - missing, 0, missing);
- *err_ptr = -EFAULT;
- }
-
- return csum_partial(dst, len, sum);
-}
-
-unsigned int csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum)
-{
- memcpy(dst,src,len);
- return csum_partial(dst,len,sum);
-}
-
-/* Fallback for csum_and_copy_to_user is currently in include/net/checksum.h */
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index f47f0715e37f..e4c8d2dc190c 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -68,8 +68,8 @@ void show_mem(void)
for_each_pgdat(pgdat) {
for (i = 0; i < pgdat->node_spanned_pages; ++i) {
- page = pgdat->node_mem_map + i;
- total++;
+ page = pfn_to_page(pgdat->node_start_pfn + i);
+ total++;
if (PageReserved(page))
reserved++;
else if (PageSwapCache(page))
@@ -252,51 +252,55 @@ static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned lon
__flush_tlb();
}
+static void __init find_early_table_space(unsigned long end)
+{
+ unsigned long puds, pmds, tables;
+
+ puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
+ pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
+ tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) +
+ round_up(pmds * sizeof(pmd_t), PAGE_SIZE);
+
+ table_start = find_e820_area(0x8000, __pa_symbol(&_text), tables);
+ if (table_start == -1UL)
+ panic("Cannot find space for the kernel page tables");
+
+ table_start >>= PAGE_SHIFT;
+ table_end = table_start;
+}
+
/* Setup the direct mapping of the physical memory at PAGE_OFFSET.
This runs before bootmem is initialized and gets pages directly from the
physical memory. To access them they are temporarily mapped. */
-void __init init_memory_mapping(void)
+void __init init_memory_mapping(unsigned long start, unsigned long end)
{
- unsigned long adr;
- unsigned long end;
unsigned long next;
- unsigned long puds, pmds, tables;
Dprintk("init_memory_mapping\n");
- end = end_pfn_map << PAGE_SHIFT;
-
/*
* Find space for the kernel direct mapping tables.
* Later we should allocate these tables in the local node of the memory
* mapped. Unfortunately this is done currently before the nodes are
* discovered.
*/
+ find_early_table_space(end);
- puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
- pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
- tables = round_up(puds*8, PAGE_SIZE) + round_up(pmds * 8, PAGE_SIZE);
-
- table_start = find_e820_area(0x8000, __pa_symbol(&_text), tables);
- if (table_start == -1UL)
- panic("Cannot find space for the kernel page tables");
+ start = (unsigned long)__va(start);
+ end = (unsigned long)__va(end);
- table_start >>= PAGE_SHIFT;
- table_end = table_start;
-
- end += __PAGE_OFFSET; /* turn virtual */
-
- for (adr = PAGE_OFFSET; adr < end; adr = next) {
+ for (; start < end; start = next) {
int map;
unsigned long pud_phys;
pud_t *pud = alloc_low_page(&map, &pud_phys);
- next = adr + PGDIR_SIZE;
+ next = start + PGDIR_SIZE;
if (next > end)
next = end;
- phys_pud_init(pud, adr-PAGE_OFFSET, next-PAGE_OFFSET);
- set_pgd(init_level4_pgt + pgd_index(adr), mk_kernel_pgd(pud_phys));
+ phys_pud_init(pud, __pa(start), __pa(next));
+ set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
unmap_low_page(map);
}
+
asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features));
__flush_tlb_all();
early_printk("kernel direct mapping tables upto %lx @ %lx-%lx\n", end,
@@ -437,7 +441,7 @@ void __init mem_init(void)
/*
* Only count reserved RAM pages
*/
- if (page_is_ram(tmp) && PageReserved(mem_map+tmp))
+ if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))
reservedpages++;
#endif
diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
index 1a166779eeba..12363e69b0c3 100644
--- a/arch/x86_64/mm/ioremap.c
+++ b/arch/x86_64/mm/ioremap.c
@@ -175,11 +175,11 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
if (phys_addr >= 0xA0000 && last_addr < 0x100000)
return (__force void __iomem *)phys_to_virt(phys_addr);
+#ifndef CONFIG_DISCONTIGMEM
/*
* Don't allow anybody to remap normal RAM that we're using..
*/
- if (phys_addr < virt_to_phys(high_memory)) {
-#ifndef CONFIG_DISCONTIGMEM
+ if (last_addr < virt_to_phys(high_memory)) {
char *t_addr, *t_end;
struct page *page;
@@ -189,8 +189,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
if(!PageReserved(page))
return NULL;
-#endif
}
+#endif
/*
* Mappings have to be page-aligned
@@ -202,7 +202,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
/*
* Ok, go for it..
*/
- area = get_vm_area(size, VM_IOREMAP | (flags << 24));
+ area = get_vm_area(size, VM_IOREMAP | (flags << 20));
if (!area)
return NULL;
area->phys_addr = phys_addr;
@@ -263,7 +263,7 @@ void iounmap(volatile void __iomem *addr)
}
*pprev = p->next;
unmap_vm_area(p);
- if ((p->flags >> 24) &&
+ if ((p->flags >> 20) &&
p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) {
change_page_attr(virt_to_page(__va(p->phys_addr)),
p->size >> PAGE_SHIFT,
diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c
index b3acd04b3b30..55a2e67e32a6 100644
--- a/arch/x86_64/mm/k8topology.c
+++ b/arch/x86_64/mm/k8topology.c
@@ -47,6 +47,10 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
int nodeid, i, nb;
int found = 0;
u32 reg;
+ unsigned numnodes;
+ nodemask_t nodes_parsed;
+
+ nodes_clear(nodes_parsed);
nb = find_northbridge();
if (nb < 0)
@@ -55,10 +59,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
printk(KERN_INFO "Scanning NUMA topology in Northbridge %d\n", nb);
reg = read_pci_config(0, nb, 0, 0x60);
- for (i = 0; i <= ((reg >> 4) & 7); i++)
- node_set_online(i);
+ numnodes = ((reg >> 4) & 7) + 1;
- printk(KERN_INFO "Number of nodes %d (%x)\n", num_online_nodes(), reg);
+ printk(KERN_INFO "Number of nodes %d\n", numnodes);
memset(&nodes,0,sizeof(nodes));
prevbase = 0;
@@ -70,11 +73,11 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
nodeid = limit & 7;
if ((base & 3) == 0) {
- if (i < num_online_nodes())
+ if (i < numnodes)
printk("Skipping disabled node %d\n", i);
continue;
}
- if (nodeid >= num_online_nodes()) {
+ if (nodeid >= numnodes) {
printk("Ignoring excess node %d (%lx:%lx)\n", nodeid,
base, limit);
continue;
@@ -90,7 +93,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
nodeid, (base>>8)&3, (limit>>8) & 3);
return -1;
}
- if (node_online(nodeid)) {
+ if (node_isset(nodeid, nodes_parsed)) {
printk(KERN_INFO "Node %d already present. Skipping\n",
nodeid);
continue;
@@ -138,12 +141,14 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
nodes[nodeid].end = limit;
prevbase = base;
+
+ node_set(nodeid, nodes_parsed);
}
if (!found)
return -1;
- memnode_shift = compute_hash_shift(nodes);
+ memnode_shift = compute_hash_shift(nodes, numnodes);
if (memnode_shift < 0) {
printk(KERN_ERR "No NUMA node hash function found. Contact maintainer\n");
return -1;
@@ -154,8 +159,8 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
if (nodes[i].start != nodes[i].end) {
/* assume 1:1 NODE:CPU */
cpu_to_node[i] = i;
- setup_node_bootmem(i, nodes[i].start, nodes[i].end);
- }
+ setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+ }
}
numa_init_array();
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index b1a7db4f4d6d..ecc0c60989c0 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -34,9 +34,7 @@ cpumask_t node_to_cpumask[MAX_NUMNODES];
int numa_off __initdata;
-unsigned long nodes_present;
-
-int __init compute_hash_shift(struct node *nodes)
+int __init compute_hash_shift(struct node *nodes, int numnodes)
{
int i;
int shift = 24;
@@ -45,7 +43,7 @@ int __init compute_hash_shift(struct node *nodes)
/* When in doubt use brute force. */
while (shift < 48) {
memset(memnodemap,0xff,sizeof(*memnodemap) * NODEMAPSIZE);
- for_each_online_node(i) {
+ for (i = 0; i < numnodes; i++) {
if (nodes[i].start == nodes[i].end)
continue;
for (addr = nodes[i].start;
@@ -197,7 +195,7 @@ static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
(nodes[i].end - nodes[i].start) >> 20);
node_set_online(i);
}
- memnode_shift = compute_hash_shift(nodes);
+ memnode_shift = compute_hash_shift(nodes, numa_fake);
if (memnode_shift < 0) {
memnode_shift = 0;
printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n");
@@ -274,7 +272,7 @@ void __init paging_init(void)
/* [numa=off] */
__init int numa_setup(char *opt)
{
- if (!strcmp(opt,"off"))
+ if (!strncmp(opt,"off",3))
numa_off = 1;
#ifdef CONFIG_NUMA_EMU
if(!strncmp(opt, "fake=", 5)) {
diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c
index 05074f177730..5b3cd2000a54 100644
--- a/arch/x86_64/mm/pageattr.c
+++ b/arch/x86_64/mm/pageattr.c
@@ -131,28 +131,36 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
kpte_flags = pte_val(*kpte);
if (pgprot_val(prot) != pgprot_val(ref_prot)) {
if ((kpte_flags & _PAGE_PSE) == 0) {
- pte_t old = *kpte;
- pte_t standard = pfn_pte(pfn, ref_prot);
-
set_pte(kpte, pfn_pte(pfn, prot));
- if (pte_same(old,standard))
- get_page(kpte_page);
} else {
+ /*
+ * split_large_page will take the reference for this change_page_attr
+ * on the split page.
+ */
struct page *split = split_large_page(address, prot, ref_prot);
if (!split)
return -ENOMEM;
- get_page(split);
set_pte(kpte,mk_pte(split, ref_prot));
+ kpte_page = split;
}
+ get_page(kpte_page);
} else if ((kpte_flags & _PAGE_PSE) == 0) {
set_pte(kpte, pfn_pte(pfn, ref_prot));
__put_page(kpte_page);
- }
+ } else
+ BUG();
- if (page_count(kpte_page) == 1) {
+ /* on x86-64 the direct mapping set at boot is not using 4k pages */
+ BUG_ON(PageReserved(kpte_page));
+
+ switch (page_count(kpte_page)) {
+ case 1:
save_page(address, kpte_page);
revert_page(address, ref_prot);
- }
+ break;
+ case 0:
+ BUG(); /* memleak and failed 2M page regeneration */
+ }
return 0;
}
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 1db7483a0564..3bd04832f041 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -20,17 +20,20 @@
static struct acpi_table_slit *acpi_slit;
-static DECLARE_BITMAP(nodes_parsed, MAX_NUMNODES) __initdata;
+static nodemask_t nodes_parsed __initdata;
+static nodemask_t nodes_found __initdata;
static struct node nodes[MAX_NUMNODES] __initdata;
static __u8 pxm2node[256] __initdata = { [0 ... 255] = 0xff };
static __init int setup_node(int pxm)
{
- if (pxm2node[pxm] == 0xff) {
- if (num_online_nodes() >= MAX_NUMNODES)
+ unsigned node = pxm2node[pxm];
+ if (node == 0xff) {
+ if (nodes_weight(nodes_found) >= MAX_NUMNODES)
return -1;
- pxm2node[pxm] = num_online_nodes();
- node_set_online(num_online_nodes());
+ node = first_unset_node(nodes_found);
+ node_set(node, nodes_found);
+ pxm2node[pxm] = node;
}
return pxm2node[pxm];
}
@@ -140,7 +143,7 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
return;
}
nd = &nodes[node];
- if (!test_and_set_bit(node, &nodes_parsed)) {
+ if (!node_test_and_set(node, nodes_parsed)) {
nd->start = start;
nd->end = end;
} else {
@@ -163,7 +166,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
int i;
if (acpi_numa <= 0)
return -1;
- memnode_shift = compute_hash_shift(nodes);
+ memnode_shift = compute_hash_shift(nodes, nodes_weight(nodes_parsed));
if (memnode_shift < 0) {
printk(KERN_ERR
"SRAT: No NUMA node hash function found. Contact maintainer\n");
@@ -171,7 +174,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
return -1;
}
for (i = 0; i < MAX_NUMNODES; i++) {
- if (!test_bit(i, &nodes_parsed))
+ if (!node_isset(i, nodes_parsed))
continue;
cutoff_node(i, start, end);
if (nodes[i].start == nodes[i].end)
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 47eb7463c009..797be2e919a0 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -162,7 +162,7 @@ static void acpi_processor_idle (void)
int sleep_ticks = 0;
u32 t1, t2 = 0;
- pr = processors[smp_processor_id()];
+ pr = processors[_smp_processor_id()];
if (!pr)
return;
@@ -838,12 +838,12 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
if (!pr)
goto end;
- seq_printf(seq, "active state: C%d\n"
+ seq_printf(seq, "active state: C%zd\n"
"max_cstate: C%d\n"
"bus master activity: %08x\n",
pr->power.state ? pr->power.state - pr->power.states : 0,
max_cstate,
- pr->power.bm_activity);
+ (unsigned)pr->power.bm_activity);
seq_puts(seq, "states:\n");
@@ -872,14 +872,14 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
}
if (pr->power.states[i].promotion.state)
- seq_printf(seq, "promotion[C%d] ",
+ seq_printf(seq, "promotion[C%zd] ",
(pr->power.states[i].promotion.state -
pr->power.states));
else
seq_puts(seq, "promotion[--] ");
if (pr->power.states[i].demotion.state)
- seq_printf(seq, "demotion[C%d] ",
+ seq_printf(seq, "demotion[C%zd] ",
(pr->power.states[i].demotion.state -
pr->power.states));
else
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 81251fde2516..c8c87cebcbc1 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -276,7 +276,7 @@ static int platform_match(struct device * dev, struct device_driver * drv)
return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
}
-static int platform_suspend(struct device * dev, u32 state)
+static int platform_suspend(struct device * dev, pm_message_t state)
{
int ret = 0;
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 66cb431b1433..e5eda746f2a6 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -71,14 +71,14 @@ extern int resume_device(struct device *);
/*
* suspend.c
*/
-extern int suspend_device(struct device *, u32);
+extern int suspend_device(struct device *, pm_message_t);
/*
* runtime.c
*/
-extern int dpm_runtime_suspend(struct device *, u32);
+extern int dpm_runtime_suspend(struct device *, pm_message_t);
extern void dpm_runtime_resume(struct device *);
#else /* CONFIG_PM */
@@ -93,7 +93,7 @@ static inline void device_pm_remove(struct device * dev)
}
-static inline int dpm_runtime_suspend(struct device * dev, u32 state)
+static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state)
{
return 0;
}
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 5e58f68363af..325962d80191 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -44,7 +44,7 @@ void dpm_runtime_resume(struct device * dev)
* @state: State to enter.
*/
-int dpm_runtime_suspend(struct device * dev, u32 state)
+int dpm_runtime_suspend(struct device * dev, pm_message_t state)
{
int error = 0;
@@ -73,7 +73,7 @@ int dpm_runtime_suspend(struct device * dev, u32 state)
* always be able to tell, but we need accurate information to
* work reliably.
*/
-void dpm_set_power_state(struct device * dev, u32 state)
+void dpm_set_power_state(struct device * dev, pm_message_t state)
{
down(&dpm_sem);
dev->power.power_state = state;
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 94c1311ee26b..8e1ace2d817e 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -11,7 +11,7 @@
#include <linux/device.h>
#include "power.h"
-extern int sysdev_suspend(u32 state);
+extern int sysdev_suspend(pm_message_t state);
/*
* The entries in the dpm_active list are in a depth first order, simply
@@ -35,7 +35,7 @@ extern int sysdev_suspend(u32 state);
* @state: Power state device is entering.
*/
-int suspend_device(struct device * dev, u32 state)
+int suspend_device(struct device * dev, pm_message_t state)
{
int error = 0;
@@ -65,7 +65,7 @@ int suspend_device(struct device * dev, u32 state)
*
*/
-int device_suspend(u32 state)
+int device_suspend(pm_message_t state)
{
int error = 0;
@@ -118,7 +118,7 @@ EXPORT_SYMBOL_GPL(device_suspend);
* done, power down system devices.
*/
-int device_power_down(u32 state)
+int device_power_down(pm_message_t state)
{
int error = 0;
struct device * dev;
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index ce71d5dec3db..c77f49e174c1 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -449,7 +449,6 @@ source "drivers/block/Kconfig.iosched"
config ATA_OVER_ETH
tristate "ATA over Ethernet support"
depends on NET
- default m
help
This driver provides Support for ATA over Ethernet block
devices like the Coraid EtherDrive (R) Storage Blade.
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index f747fb3d13db..2f30018d3387 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -46,14 +46,14 @@
#include <linux/completion.h>
#define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "HP CISS Driver (v 2.6.2)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,2)
+#define DRIVER_NAME "HP CISS Driver (v 2.6.4)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,4)
/* Embedded module documentation macros - see modules.h */
MODULE_AUTHOR("Hewlett-Packard Company");
-MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.2");
+MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.4");
MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
- " SA6i V100");
+ " SA6i P600");
MODULE_LICENSE("GPL");
#include "cciss_cmd.h"
@@ -80,10 +80,8 @@ const struct pci_device_id cciss_pci_device_id[] = {
0x0E11, 0x409D, 0, 0, 0},
{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
0x0E11, 0x4091, 0, 0, 0},
- { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
- 0x0E11, 0x409E, 0, 0, 0},
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISS,
- 0x103C, 0x3211, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA,
+ 0x103C, 0x3225, 0, 0, 0},
{0,}
};
MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
@@ -104,8 +102,7 @@ static struct board_type products[] = {
{ 0x409C0E11, "Smart Array 6400", &SA5_access},
{ 0x409D0E11, "Smart Array 6400 EM", &SA5_access},
{ 0x40910E11, "Smart Array 6i", &SA5_access},
- { 0x409E0E11, "Smart Array 6422", &SA5_access},
- { 0x3211103C, "Smart Array V100", &SA5_access},
+ { 0x3225103C, "Smart Array P600", &SA5_access},
};
/* How long to wait (in millesconds) for board to go into simple mode */
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c
index 6c24f236f7f6..635d93fae58f 100644
--- a/drivers/block/cfq-iosched.c
+++ b/drivers/block/cfq-iosched.c
@@ -622,8 +622,10 @@ static void cfq_requeue_request(request_queue_t *q, struct request *rq)
cfq_sort_rr_list(cfqq, 0);
}
- crq->accounted = 0;
- cfqq->cfqd->rq_in_driver--;
+ if (crq->accounted) {
+ crq->accounted = 0;
+ cfqq->cfqd->rq_in_driver--;
+ }
}
list_add(&rq->queuelist, &q->queue_head);
}
diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c
index 2d6fbd4fce65..820baa66291b 100644
--- a/drivers/block/deadline-iosched.c
+++ b/drivers/block/deadline-iosched.c
@@ -791,24 +791,24 @@ struct deadline_fs_entry {
};
static ssize_t
-deadline_var_show(unsigned int var, char *page)
+deadline_var_show(int var, char *page)
{
return sprintf(page, "%d\n", var);
}
static ssize_t
-deadline_var_store(unsigned int *var, const char *page, size_t count)
+deadline_var_store(int *var, const char *page, size_t count)
{
char *p = (char *) page;
- *var = simple_strtoul(p, &p, 10);
+ *var = simple_strtol(p, &p, 10);
return count;
}
#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \
static ssize_t __FUNC(struct deadline_data *dd, char *page) \
{ \
- unsigned int __data = __VAR; \
+ int __data = __VAR; \
if (__CONV) \
__data = jiffies_to_msecs(__data); \
return deadline_var_show(__data, (page)); \
@@ -823,7 +823,7 @@ SHOW_FUNCTION(deadline_fifobatch_show, dd->fifo_batch, 0);
#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
static ssize_t __FUNC(struct deadline_data *dd, const char *page, size_t count) \
{ \
- unsigned int __data; \
+ int __data; \
int ret = deadline_var_store(&__data, (page), count); \
if (__data < (MIN)) \
__data = (MIN); \
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 52e29886f8cf..0bf9458f911d 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -170,8 +170,6 @@ static void elevator_setup_default(void)
#else
#error "You must build at least 1 IO scheduler into the kernel"
#endif
- printk(KERN_INFO "elevator: using %s as default io scheduler\n",
- chosen_elevator);
}
static int __init elevator_setup(char *str)
@@ -515,7 +513,10 @@ int elv_register(struct elevator_type *e)
list_add_tail(&e->list, &elv_list);
spin_unlock_irq(&elv_list_lock);
- printk(KERN_INFO "io scheduler %s registered\n", e->elevator_name);
+ printk(KERN_INFO "io scheduler %s registered", e->elevator_name);
+ if (!strcmp(e->elevator_name, chosen_elevator))
+ printk(" (default)");
+ printk("\n");
return 0;
}
EXPORT_SYMBOL_GPL(elv_register);
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 98db1776ba31..3994af7e555b 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -1438,6 +1438,7 @@ static int blk_init_free_list(request_queue_t *q)
struct request_list *rl = &q->rq;
rl->count[READ] = rl->count[WRITE] = 0;
+ rl->starved[READ] = rl->starved[WRITE] = 0;
init_waitqueue_head(&rl->wait[READ]);
init_waitqueue_head(&rl->wait[WRITE]);
init_waitqueue_head(&rl->drain);
@@ -1618,6 +1619,22 @@ void ioc_set_batching(request_queue_t *q, struct io_context *ioc)
ioc->last_waited = jiffies;
}
+static void __freed_request(request_queue_t *q, int rw)
+{
+ struct request_list *rl = &q->rq;
+
+ if (rl->count[rw] < queue_congestion_off_threshold(q))
+ clear_queue_congested(q, rw);
+
+ if (rl->count[rw] + 1 <= q->nr_requests) {
+ smp_mb();
+ if (waitqueue_active(&rl->wait[rw]))
+ wake_up(&rl->wait[rw]);
+
+ blk_clear_queue_full(q, rw);
+ }
+}
+
/*
* A request has just been released. Account for it, update the full and
* congestion status, wake up any waiters. Called under q->queue_lock.
@@ -1627,17 +1644,17 @@ static void freed_request(request_queue_t *q, int rw)
struct request_list *rl = &q->rq;
rl->count[rw]--;
- if (rl->count[rw] < queue_congestion_off_threshold(q))
- clear_queue_congested(q, rw);
- if (rl->count[rw]+1 <= q->nr_requests) {
+
+ __freed_request(q, rw);
+
+ if (unlikely(rl->starved[rw ^ 1]))
+ __freed_request(q, rw ^ 1);
+
+ if (!rl->count[READ] && !rl->count[WRITE]) {
smp_mb();
- if (waitqueue_active(&rl->wait[rw]))
- wake_up(&rl->wait[rw]);
- blk_clear_queue_full(q, rw);
+ if (unlikely(waitqueue_active(&rl->drain)))
+ wake_up(&rl->drain);
}
- if (unlikely(waitqueue_active(&rl->drain)) &&
- !rl->count[READ] && !rl->count[WRITE])
- wake_up(&rl->drain);
}
#define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist)
@@ -1669,8 +1686,7 @@ static struct request *get_request(request_queue_t *q, int rw, int gfp_mask)
switch (elv_may_queue(q, rw)) {
case ELV_MQUEUE_NO:
- spin_unlock_irq(q->queue_lock);
- goto out;
+ goto rq_starved;
case ELV_MQUEUE_MAY:
break;
case ELV_MQUEUE_MUST:
@@ -1688,6 +1704,7 @@ static struct request *get_request(request_queue_t *q, int rw, int gfp_mask)
get_rq:
rl->count[rw]++;
+ rl->starved[rw] = 0;
if (rl->count[rw] >= queue_congestion_on_threshold(q))
set_queue_congested(q, rw);
spin_unlock_irq(q->queue_lock);
@@ -1703,6 +1720,18 @@ get_rq:
*/
spin_lock_irq(q->queue_lock);
freed_request(q, rw);
+
+ /*
+ * in the very unlikely event that allocation failed and no
+ * requests for this direction was pending, mark us starved
+ * so that freeing of a request in the other direction will
+ * notice us. another possible fix would be to split the
+ * rq mempool into READ and WRITE
+ */
+rq_starved:
+ if (unlikely(rl->count[rw] == 0))
+ rl->starved[rw] = 1;
+
spin_unlock_irq(q->queue_lock);
goto out;
}
diff --git a/drivers/block/noop-iosched.c b/drivers/block/noop-iosched.c
index 43f857842d87..888c477e02b3 100644
--- a/drivers/block/noop-iosched.c
+++ b/drivers/block/noop-iosched.c
@@ -52,12 +52,10 @@ static void elevator_noop_merge_requests(request_queue_t *q, struct request *req
static void elevator_noop_add_request(request_queue_t *q, struct request *rq,
int where)
{
- struct list_head *insert = q->queue_head.prev;
-
if (where == ELEVATOR_INSERT_FRONT)
- insert = &q->queue_head;
-
- list_add_tail(&rq->queuelist, &q->queue_head);
+ list_add(&rq->queuelist, &q->queue_head);
+ else
+ list_add_tail(&rq->queuelist, &q->queue_head);
/*
* new merges must not precede this barrier
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 4487cfc24037..7590000b9457 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -605,8 +605,7 @@ static int pkt_set_segment_merging(struct pktcdvd_device *pd, request_queue_t *q
/*
* Copy CD_FRAMESIZE bytes from src_bio into a destination page
*/
-static void pkt_copy_bio_data(struct bio *src_bio, int seg, int offs,
- struct page *dst_page, int dst_offs)
+static void pkt_copy_bio_data(struct bio *src_bio, int seg, int offs, struct page *dst_page, int dst_offs)
{
unsigned int copy_size = CD_FRAMESIZE;
@@ -1299,8 +1298,7 @@ static void pkt_print_settings(struct pktcdvd_device *pd)
printk("Mode-%c disc\n", pd->settings.block_mode == 8 ? '1' : '2');
}
-static int pkt_mode_sense(struct pktcdvd_device *pd, struct packet_command *cgc,
- int page_code, int page_control)
+static int pkt_mode_sense(struct pktcdvd_device *pd, struct packet_command *cgc, int page_code, int page_control)
{
memset(cgc->cmd, 0, sizeof(cgc->cmd));
@@ -2625,7 +2623,7 @@ static struct miscdevice pkt_misc = {
.fops = &pkt_ctl_fops
};
-int pkt_init(void)
+static int pkt_init(void)
{
int ret;
@@ -2661,7 +2659,7 @@ out2:
return ret;
}
-void pkt_exit(void)
+static void pkt_exit(void)
{
remove_proc_entry("pktcdvd", proc_root_driver);
misc_deregister(&pkt_misc);
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
index 1fe57c940d2e..cdb11fc7ad25 100644
--- a/drivers/block/scsi_ioctl.c
+++ b/drivers/block/scsi_ioctl.c
@@ -339,7 +339,8 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic)
{
struct request *rq;
- int err, in_len, out_len, bytes, opcode, cmdlen;
+ int err;
+ unsigned int in_len, out_len, bytes, opcode, cmdlen;
char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
/*
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
index 924bf39a4d06..5fd3e4cb7525 100644
--- a/drivers/bluetooth/bcm203x.c
+++ b/drivers/bluetooth/bcm203x.c
@@ -46,6 +46,8 @@
#define VERSION "1.0"
+static int ignore = 0;
+
static struct usb_device_id bcm203x_table[] = {
/* Broadcom Blutonium (BCM2033) */
{ USB_DEVICE(0x0a5c, 0x2033) },
@@ -55,7 +57,6 @@ static struct usb_device_id bcm203x_table[] = {
MODULE_DEVICE_TABLE(usb, bcm203x_table);
-
#define BCM203X_ERROR 0
#define BCM203X_RESET 1
#define BCM203X_LOAD_MINIDRV 2
@@ -175,7 +176,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
BT_DBG("intf %p id %p", intf, id);
- if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+ if (ignore || (intf->cur_altsetting->desc.bInterfaceNumber != 0))
return -ENODEV;
data = kmalloc(sizeof(*data), GFP_KERNEL);
@@ -304,6 +305,9 @@ static void __exit bcm203x_exit(void)
module_init(bcm203x_init);
module_exit(bcm203x_exit);
+module_param(ignore, bool, 0644);
+MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
+
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION);
MODULE_VERSION(VERSION);
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index 70afb90dc14a..913f49e56a93 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -47,6 +47,8 @@
#define VERSION "1.1"
+static int ignore = 0;
+
static struct usb_driver bfusb_driver;
static struct usb_device_id bfusb_table[] = {
@@ -655,6 +657,9 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
BT_DBG("intf %p id %p", intf, id);
+ if (ignore)
+ return -ENODEV;
+
/* Check number of endpoints */
if (intf->cur_altsetting->desc.bNumEndpoints < 2)
return -EIO;
@@ -792,6 +797,9 @@ static void __exit bfusb_exit(void)
module_init(bfusb_init);
module_exit(bfusb_exit);
+module_param(ignore, bool, 0644);
+MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
+
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION);
MODULE_VERSION(VERSION);
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 4db1feeefc0b..325ab5d76786 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -904,7 +904,6 @@ static dev_link_t *bluecard_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -1117,10 +1116,7 @@ static int __init init_bluecard_cs(void)
static void __exit exit_bluecard_cs(void)
{
pcmcia_unregister_driver(&bluecard_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- bluecard_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_bluecard_cs);
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index a50adb67bd5a..84977a0605e5 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -709,7 +709,6 @@ static dev_link_t *bt3c_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -967,10 +966,7 @@ static int __init init_bt3c_cs(void)
static void __exit exit_bt3c_cs(void)
{
pcmcia_unregister_driver(&bt3c_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- bt3c_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_bt3c_cs);
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 74644df24477..38dbac8db507 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -628,7 +628,6 @@ static dev_link_t *btuart_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -887,10 +886,7 @@ static int __init init_btuart_cs(void)
static void __exit exit_btuart_cs(void)
{
pcmcia_unregister_driver(&btuart_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- btuart_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_btuart_cs);
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 87ff7966ffba..9fcc8e4d2159 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -607,7 +607,6 @@ static dev_link_t *dtl1_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -839,10 +838,7 @@ static int __init init_dtl1_cs(void)
static void __exit exit_dtl1_cs(void)
{
pcmcia_unregister_driver(&dtl1_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- dtl1_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_dtl1_cs);
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 4d1f7ea9c63e..846cdffc4964 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -265,7 +265,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
/* This is a rewrite of pkt_avail in ABCSP */
static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
{
- struct bcsp_struct *bcsp = (struct bcsp_struct *) hu->priv;
+ struct bcsp_struct *bcsp = hu->priv;
unsigned long flags;
struct sk_buff *skb;
@@ -629,7 +629,7 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count)
static void bcsp_timed_event(unsigned long arg)
{
struct hci_uart *hu = (struct hci_uart *) arg;
- struct bcsp_struct *bcsp = (struct bcsp_struct *) hu->priv;
+ struct bcsp_struct *bcsp = hu->priv;
struct sk_buff *skb;
unsigned long flags;
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index dfb4142a551a..9075bbb56ad4 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -51,6 +51,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
+
#include "hci_uart.h"
#ifndef CONFIG_BT_HCIUART_DEBUG
@@ -60,6 +61,8 @@
#define BT_DMP( A... )
#endif
+static int reset = 0;
+
static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
int hci_uart_register_proto(struct hci_uart_proto *p)
@@ -412,7 +415,10 @@ static int hci_uart_register_dev(struct hci_uart *hu)
hdev->destruct = hci_uart_destruct;
hdev->owner = THIS_MODULE;
-
+
+ if (reset)
+ set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
+
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
@@ -577,7 +583,10 @@ static void __exit hci_uart_exit(void)
module_init(hci_uart_init);
module_exit(hci_uart_exit);
-MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
+module_param(reset, bool, 0644);
+MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
+
+MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth HCI UART driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index a5df8b573cfa..673fcce8e2c8 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -66,6 +66,9 @@
#define URB_ZERO_PACKET 0
#endif
+static int ignore = 0;
+static int reset = 0;
+
#ifdef CONFIG_BT_HCIUSB_SCO
static int isoc = 2;
#endif
@@ -827,7 +830,7 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
id = match;
}
- if (id->driver_info & HCI_IGNORE)
+ if (ignore || id->driver_info & HCI_IGNORE)
return -ENODEV;
if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
@@ -963,7 +966,7 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
hdev->owner = THIS_MODULE;
- if (id->driver_info & HCI_RESET)
+ if (reset || id->driver_info & HCI_RESET)
set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
if (hci_register_dev(hdev) < 0) {
@@ -1036,6 +1039,12 @@ static void __exit hci_usb_exit(void)
module_init(hci_usb_init);
module_exit(hci_usb_exit);
+module_param(ignore, bool, 0644);
+MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
+
+module_param(reset, bool, 0644);
+MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
+
#ifdef CONFIG_BT_HCIUSB_SCO
module_param(isoc, int, 0644);
MODULE_PARM_DESC(isoc, "Set isochronous transfers for SCO over HCI support");
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index d9b4a6e7fb94..fe0cb7bf529e 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -144,7 +144,7 @@ config AGP_I460
config AGP_HP_ZX1
tristate "HP ZX1 chipset AGP support"
- depends on AGP && (IA64_HP_ZX1 || IA64_GENERIC)
+ depends on AGP && (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC)
help
This option gives you AGP GART support for the HP ZX1 chipset
for IA64 processors.
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 62f8e3087fe6..fb681990a84d 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -2401,7 +2401,7 @@ static struct tty_operations esp_ops = {
/*
* The serial driver boot-time initialization code!
*/
-int __init espserial_init(void)
+static int __init espserial_init(void)
{
int i, offset;
struct esp_struct * info;
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index fc02f72f013b..d3a2bc36129b 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -83,7 +83,7 @@ static unsigned char days_in_mo[] =
static int irq_active;
#ifdef CONFIG_GEN_RTC_X
-struct work_struct genrtc_task;
+static struct work_struct genrtc_task;
static struct timer_list timer_task;
static unsigned int oldsecs;
diff --git a/drivers/char/ip2/fip_firm.h b/drivers/char/ip2/fip_firm.h
index f118123ea912..4c525fa4929f 100644
--- a/drivers/char/ip2/fip_firm.h
+++ b/drivers/char/ip2/fip_firm.h
@@ -1,7 +1,7 @@
/* fip_firm.h - Intelliport II loadware */
/* -31232 bytes read from ff.lod */
-unsigned char fip_firm[] __initdata = {
+static unsigned char fip_firm[] __initdata = {
0x3C,0x42,0x37,0x18,0x02,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x57,0x65,0x64,0x20,0x44,0x65,0x63,0x20,0x30,0x31,0x20,0x31,0x32,0x3A,0x32,0x34,
0x3A,0x33,0x30,0x20,0x31,0x39,0x39,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c
index 77fd8543efc3..fd299d6c42ac 100644
--- a/drivers/char/ip2/i2cmd.c
+++ b/drivers/char/ip2/i2cmd.c
@@ -88,7 +88,7 @@ static UCHAR ct36[] = { 2, BTH, 0x24,0 }; // SETERRMODE
//static UCHAR ct37[]={ 5, BYP|VIP, 0x25,0,0,0,0 }; // FLOW PACKET
// Back to normal
-static UCHAR ct38[] = {11, BTH|VAR, 0x26,0,0,0,0,0,0,0,0,0,0 }; // DEF KEY SEQ
+//static UCHAR ct38[] = {11, BTH|VAR, 0x26,0,0,0,0,0,0,0,0,0,0 }; // DEF KEY SEQ
//static UCHAR ct39[]={ 3, BTH|END, 0x27,0,0 }; // OPOSTON
//static UCHAR ct40[]={ 1, BTH|END, 0x28 }; // OPOSTOFF
static UCHAR ct41[] = { 1, BYP, 0x29 }; // RESUME
@@ -103,7 +103,7 @@ static UCHAR ct47[] = { 7, BTH, 0x2F,0,0,0,0,0,0 }; // UNIX FLAGS
//static UCHAR ct50[]={ 1, BTH, 0x32 }; // DTRFLOWENAB
//static UCHAR ct51[]={ 1, BTH, 0x33 }; // DTRFLOWDSAB
//static UCHAR ct52[]={ 1, BTH, 0x34 }; // BAUDTABRESET
-static UCHAR ct53[] = { 3, BTH, 0x35,0,0 }; // BAUDREMAP
+//static UCHAR ct53[] = { 3, BTH, 0x35,0,0 }; // BAUDREMAP
static UCHAR ct54[] = { 3, BTH, 0x36,0,0 }; // CUSTOMBAUD1
static UCHAR ct55[] = { 3, BTH, 0x37,0,0 }; // CUSTOMBAUD2
static UCHAR ct56[] = { 2, BTH|END, 0x38,0 }; // PAUSE
@@ -152,40 +152,6 @@ static UCHAR ct89[]={ 1, BYP, 0x59 }; // DSS_NOW
//********
//******************************************************************************
-// Function: i2cmdSetSeq(type, size, string)
-// Parameters: type - sequence number
-// size - length of sequence
-// string - substitution string
-//
-// Returns: Pointer to command structure
-//
-// Description:
-//
-// This routine sets the parameters of command 38 Define Hot Key sequence (alias
-// "special receive sequence"). Returns a pointer to the structure. Endeavours
-// to be bullet-proof in that the sequence number is forced in range, and any
-// out-of-range sizes are forced to zero.
-//******************************************************************************
-cmdSyntaxPtr
-i2cmdSetSeq(unsigned char type, unsigned char size, unsigned char *string)
-{
- cmdSyntaxPtr pCM = (cmdSyntaxPtr) ct38;
- unsigned char *pc;
-
- pCM->cmd[1] = ((type > 0xf) ? 0xf : type); // Sequence number
- size = ((size > 0x8) ? 0 : size); // size
- pCM->cmd[2] = size;
- pCM->length = 3 + size; // UPDATES THE LENGTH!
-
- pc = &(pCM->cmd[3]);
-
- while(size--) {
- *pc++ = *string++;
- }
- return pCM;
-}
-
-//******************************************************************************
// Function: i2cmdUnixFlags(iflag, cflag, lflag)
// Parameters: Unix tty flags
//
@@ -211,27 +177,6 @@ i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
}
//******************************************************************************
-// Function: i2cmdBaudRemap(dest,src)
-// Parameters: ?
-//
-// Returns: Pointer to command structure
-//
-// Description:
-//
-// This routine sets the parameters of command 53 and returns a pointer to the
-// appropriate structure.
-//******************************************************************************
-cmdSyntaxPtr
-i2cmdBaudRemap(unsigned char dest, unsigned char src)
-{
- cmdSyntaxPtr pCM = (cmdSyntaxPtr) ct53;
-
- pCM->cmd[1] = dest;
- pCM->cmd[2] = src;
- return pCM;
-}
-
-//******************************************************************************
// Function: i2cmdBaudDef(which, rate)
// Parameters: ?
//
diff --git a/drivers/char/ip2/i2cmd.h b/drivers/char/ip2/i2cmd.h
index 83475167f491..c41728a85710 100644
--- a/drivers/char/ip2/i2cmd.h
+++ b/drivers/char/ip2/i2cmd.h
@@ -71,9 +71,7 @@ typedef struct _cmdSyntax
// there is more than one parameter to assign, we must use a function rather
// than a macro (used usually).
//
-extern cmdSyntaxPtr i2cmdSetSeq(UCHAR seqno, UCHAR size, UCHAR *string);
extern cmdSyntaxPtr i2cmdUnixFlags(USHORT iflag,USHORT cflag,USHORT lflag);
-extern cmdSyntaxPtr i2cmdBaudRemap(UCHAR dest, UCHAR src);
extern cmdSyntaxPtr i2cmdBaudDef(int which, USHORT rate);
// Declarations for the global arrays used to bear the commands and their
@@ -397,14 +395,6 @@ static UCHAR cc02[];
// library code in response to data movement and shouldn't ever be sent by the
// user code. See i2pack.h and the body of i2lib.c for details.
-// COMMAND 38: Define the hot-key sequence
-// seqno: sequence number 0-15
-// size: number of characters in sequence (1-8)
-// string: pointer to the characters
-// (if size == 0, "undefines" this sequence
-//
-#define CMD_SET_SEQ(seqno,size,string) i2cmdSetSeq(seqno,size,string)
-
// Enable on-board post-processing, using options given in oflag argument.
// Formerly, this command was automatically preceded by a CMD_OPOST_OFF command
// because the loadware does not permit sending back-to-back CMD_OPOST_ON
@@ -458,13 +448,6 @@ static UCHAR cc02[];
#define CMD_DTRFL_DSAB (cmdSyntaxPtr)(ct51) // Disable DTR flow control
#define CMD_BAUD_RESET (cmdSyntaxPtr)(ct52) // Reset baudrate table
-// COMMAND 53: Remap baud rate table
-// dest = index of table entry to be changed
-// src = index value to substitute.
-// at default mapping table is f(x) = x
-//
-#define CMD_BAUD_REMAP(dest,src) i2cmdBaudRemap(dest,src)
-
// COMMAND 54: Define custom rate #1
// rate = (short) 1/10 of the desired baud rate
//
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
index a886e954cae9..82c5f30375ac 100644
--- a/drivers/char/ip2/i2lib.c
+++ b/drivers/char/ip2/i2lib.c
@@ -141,7 +141,7 @@ fatality(i2eBordStrPtr pB )
//* Code *
//********
-inline int
+static inline int
i2Validate ( i2ChanStrPtr pCh )
{
//ip2trace(pCh->port_index, ITRC_VERIFY,ITRC_ENTER,2,pCh->validity,
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index 3d3ae6856bbd..fca9a978fb73 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -138,7 +138,7 @@
#include <linux/proc_fs.h>
static int ip2_read_procmem(char *, char **, off_t, int);
-int ip2_read_proc(char *, char **, off_t, int, int *, void * );
+static int ip2_read_proc(char *, char **, off_t, int, int *, void * );
/********************/
/* Type Definitions */
@@ -202,7 +202,6 @@ static void do_status(void *p);
static void ip2_wait_until_sent(PTTY,int);
static void set_params (i2ChanStrPtr, struct termios *);
-static int set_modem_info(i2ChanStrPtr, unsigned int, unsigned int *);
static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *);
static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *);
@@ -3097,7 +3096,7 @@ ip2_read_procmem(char *buf, char **start, off_t offset, int len)
* different sources including ip2mkdev.c and a couple of other drivers.
* The bugs are all mine. :-) =mhw=
*/
-int ip2_read_proc(char *page, char **start, off_t off,
+static int ip2_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int i, j, box;
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 7c943edc7dcc..fae2ab6d9dc3 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -330,7 +330,7 @@ static void applkey(struct vc_data *vc, int key, char mode)
* in utf-8 already. UTF-8 is defined for words of up to 31 bits,
* but we need only 16 bits here
*/
-void to_utf8(struct vc_data *vc, ushort c)
+static void to_utf8(struct vc_data *vc, ushort c)
{
if (c < 0x80)
/* 0******* */
@@ -392,7 +392,7 @@ void compute_shiftstate(void)
* Otherwise, conclude that DIACR was not combining after all,
* queue it and return CH.
*/
-unsigned char handle_diacr(struct vc_data *vc, unsigned char ch)
+static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch)
{
int d = diacr;
int i;
@@ -853,18 +853,6 @@ void setledstate(struct kbd_struct *kbd, unsigned int led)
set_leds();
}
-void register_leds(struct kbd_struct *kbd, unsigned int led,
- unsigned int *addr, unsigned int mask)
-{
- if (led < 3) {
- ledptrs[led].addr = addr;
- ledptrs[led].mask = mask;
- ledptrs[led].valid = 1;
- kbd->ledmode = LED_SHOW_MEM;
- } else
- kbd->ledmode = LED_SHOW_FLAGS;
-}
-
static inline unsigned char getleds(void)
{
struct kbd_struct *kbd = kbd_table + fg_console;
@@ -925,7 +913,7 @@ DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
/*
* This allows a newly plugged keyboard to pick the LED state.
*/
-void kbd_refresh_leds(struct input_handle *handle)
+static void kbd_refresh_leds(struct input_handle *handle)
{
unsigned char leds = ledstate;
@@ -1027,7 +1015,7 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char u
}
#endif
-void kbd_rawcode(unsigned char data)
+static void kbd_rawcode(unsigned char data)
{
struct vc_data *vc = vc_cons[fg_console].d;
kbd = kbd_table + fg_console;
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 093f79828fca..92a54cb659d6 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -142,7 +142,7 @@
/* ROUND_UP macro from fs/select.c */
#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
-struct lp_struct lp_table[LP_NO];
+static struct lp_struct lp_table[LP_NO];
static unsigned int lp_count = 0;
static struct class_simple *lp_class;
@@ -867,7 +867,7 @@ static struct parport_driver lp_driver = {
.detach = lp_detach,
};
-int __init lp_init (void)
+static int __init lp_init (void)
{
int i, err = 0;
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index 0256d5823504..24ccc233b213 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -177,7 +177,7 @@ static struct n_hdlc *n_hdlc_alloc (void);
static int debuglevel;
/* max frame size for memory allocations */
-static ssize_t maxframe = 4096;
+static int maxframe = 4096;
/* TTY callbacks */
@@ -672,7 +672,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
if (debuglevel & DEBUG_LEVEL_INFO)
printk (KERN_WARNING
"n_hdlc_tty_write: truncating user packet "
- "from %lu to %Zd\n", (unsigned long) count,
+ "from %lu to %d\n", (unsigned long) count,
maxframe );
count = maxframe;
}
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index a29dffd9408e..4280394442f7 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -152,7 +152,7 @@ static void reset_buffer_flags(struct tty_struct *tty)
* lock_kernel() still.
*/
-void n_tty_flush_buffer(struct tty_struct * tty)
+static void n_tty_flush_buffer(struct tty_struct * tty)
{
/* clear everything and unthrottle the driver */
reset_buffer_flags(tty);
@@ -174,7 +174,7 @@ void n_tty_flush_buffer(struct tty_struct * tty)
* at this instant in time.
*/
-ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
+static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
{
unsigned long flags;
ssize_t n = 0;
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index e331fc0ce3c5..c6accb1ab6ac 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -608,7 +608,6 @@ static dev_link_t *mgslpc_attach(void)
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -923,7 +922,7 @@ static void tx_release(struct tty_struct *tty)
/* Return next bottom half action to perform.
* or 0 if nothing to do.
*/
-int bh_action(MGSLPC_INFO *info)
+static int bh_action(MGSLPC_INFO *info)
{
unsigned long flags;
int rc = 0;
@@ -1017,7 +1016,7 @@ void bh_status(MGSLPC_INFO *info)
}
/* eom: non-zero = end of frame */
-void rx_ready_hdlc(MGSLPC_INFO *info, int eom)
+static void rx_ready_hdlc(MGSLPC_INFO *info, int eom)
{
unsigned char data[2];
unsigned char fifo_count, read_count, i;
@@ -1079,7 +1078,7 @@ void rx_ready_hdlc(MGSLPC_INFO *info, int eom)
issue_command(info, CHA, CMD_RXFIFO);
}
-void rx_ready_async(MGSLPC_INFO *info, int tcd)
+static void rx_ready_async(MGSLPC_INFO *info, int tcd)
{
unsigned char data, status;
int fifo_count;
@@ -1153,7 +1152,7 @@ void rx_ready_async(MGSLPC_INFO *info, int tcd)
}
-void tx_done(MGSLPC_INFO *info)
+static void tx_done(MGSLPC_INFO *info)
{
if (!info->tx_active)
return;
@@ -1190,7 +1189,7 @@ void tx_done(MGSLPC_INFO *info)
}
}
-void tx_ready(MGSLPC_INFO *info)
+static void tx_ready(MGSLPC_INFO *info)
{
unsigned char fifo_count = 32;
int c;
@@ -1239,7 +1238,7 @@ void tx_ready(MGSLPC_INFO *info)
}
}
-void cts_change(MGSLPC_INFO *info)
+static void cts_change(MGSLPC_INFO *info)
{
get_signals(info);
if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
@@ -1276,7 +1275,7 @@ void cts_change(MGSLPC_INFO *info)
info->pending_bh |= BH_STATUS;
}
-void dcd_change(MGSLPC_INFO *info)
+static void dcd_change(MGSLPC_INFO *info)
{
get_signals(info);
if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
@@ -1310,7 +1309,7 @@ void dcd_change(MGSLPC_INFO *info)
info->pending_bh |= BH_STATUS;
}
-void dsr_change(MGSLPC_INFO *info)
+static void dsr_change(MGSLPC_INFO *info)
{
get_signals(info);
if ((info->dsr_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
@@ -1325,7 +1324,7 @@ void dsr_change(MGSLPC_INFO *info)
info->pending_bh |= BH_STATUS;
}
-void ri_change(MGSLPC_INFO *info)
+static void ri_change(MGSLPC_INFO *info)
{
get_signals(info);
if ((info->ri_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
@@ -2955,7 +2954,7 @@ static inline int line_info(char *buf, MGSLPC_INFO *info)
/* Called to print information about devices
*/
-int mgslpc_read_proc(char *page, char **start, off_t off, int count,
+static int mgslpc_read_proc(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
int len = 0, l;
@@ -3147,13 +3146,7 @@ static void synclink_cs_cleanup(void)
}
pcmcia_unregister_driver(&mgslpc_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- mgslpc_release((u_long)dev_list);
- mgslpc_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
static int __init synclink_cs_init(void)
@@ -3218,7 +3211,7 @@ static void __exit synclink_cs_exit(void)
module_init(synclink_cs_init);
module_exit(synclink_cs_exit);
-void mgslpc_set_rate(MGSLPC_INFO *info, unsigned char channel, unsigned int rate)
+static void mgslpc_set_rate(MGSLPC_INFO *info, unsigned char channel, unsigned int rate)
{
unsigned int M, N;
unsigned char val;
@@ -3254,7 +3247,7 @@ void mgslpc_set_rate(MGSLPC_INFO *info, unsigned char channel, unsigned int rate
/* Enabled the AUX clock output at the specified frequency.
*/
-void enable_auxclk(MGSLPC_INFO *info)
+static void enable_auxclk(MGSLPC_INFO *info)
{
unsigned char val;
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index a47386427eb2..22e6caadcddf 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -35,7 +35,7 @@
/* These are global because they are accessed in tty_io.c */
#ifdef CONFIG_UNIX98_PTYS
struct tty_driver *ptm_driver;
-struct tty_driver *pts_driver;
+static struct tty_driver *pts_driver;
#endif
static void pty_close(struct tty_struct * tty, struct file * filp)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 69784eb102a1..8bd3b600f34f 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -2,7 +2,7 @@
* random.c -- A strong random number generator
*
* Version 1.89, last modified 19-Sep-99
- *
+ *
* Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. All
* rights reserved.
*
@@ -18,13 +18,13 @@
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
- *
+ *
* ALTERNATIVELY, this product may be distributed under the terms of
* the GNU General Public License, in which case the provisions of the GPL are
* required INSTEAD OF the above restrictions. (This clause is
* necessary due to a potential bad interaction between the GPL and
* the restrictions contained in a BSD-style copyright.)
- *
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
@@ -40,8 +40,8 @@
*/
/*
- * (now, with legal B.S. out of the way.....)
- *
+ * (now, with legal B.S. out of the way.....)
+ *
* This routine gathers environmental noise from device drivers, etc.,
* and returns good random numbers, suitable for cryptographic use.
* Besides the obvious cryptographic uses, these numbers are also good
@@ -51,7 +51,7 @@
*
* Theory of operation
* ===================
- *
+ *
* Computers are very predictable devices. Hence it is extremely hard
* to produce truly random numbers on a computer --- as opposed to
* pseudo-random numbers, which can easily generated by using a
@@ -62,7 +62,7 @@
* must be hard for outside attackers to observe, and use that to
* generate random numbers. In a Unix environment, this is best done
* from inside the kernel.
- *
+ *
* Sources of randomness from the environment include inter-keyboard
* timings, inter-interrupt timings from some interrupts, and other
* events which are both (a) non-deterministic and (b) hard for an
@@ -74,7 +74,7 @@
* As random bytes are mixed into the entropy pool, the routines keep
* an *estimate* of how many bits of randomness have been stored into
* the random number generator's internal state.
- *
+ *
* When random bytes are desired, they are obtained by taking the SHA
* hash of the contents of the "entropy pool". The SHA hash avoids
* exposing the internal state of the entropy pool. It is believed to
@@ -86,7 +86,7 @@
* reason, the routine decreases its internal estimate of how many
* bits of "true randomness" are contained in the entropy pool as it
* outputs random numbers.
- *
+ *
* If this estimate goes to zero, the routine can still generate
* random numbers; however, an attacker may (at least in theory) be
* able to infer the future output of the generator from prior
@@ -94,10 +94,10 @@
* not believed to be feasible, but there is a remote possibility.
* Nonetheless, these numbers should be useful for the vast majority
* of purposes.
- *
+ *
* Exported interfaces ---- output
* ===============================
- *
+ *
* There are three exported interfaces; the first is one designed to
* be used from within the kernel:
*
@@ -105,14 +105,14 @@
*
* This interface will return the requested number of random bytes,
* and place it in the requested buffer.
- *
+ *
* The two other interfaces are two character devices /dev/random and
* /dev/urandom. /dev/random is suitable for use when very high
* quality randomness is desired (for example, for key generation or
* one-time pads), as it will only return a maximum of the number of
* bits of randomness (as estimated by the random number generator)
* contained in the entropy pool.
- *
+ *
* The /dev/urandom device does not have this limit, and will return
* as many bytes as are requested. As more and more random bytes are
* requested without giving time for the entropy pool to recharge,
@@ -121,17 +121,17 @@
*
* Exported interfaces ---- input
* ==============================
- *
+ *
* The current exported interfaces for gathering environmental noise
* from the devices are:
- *
+ *
* void add_keyboard_randomness(unsigned char scancode);
* void add_mouse_randomness(__u32 mouse_data);
* void add_interrupt_randomness(int irq);
- *
+ *
* add_keyboard_randomness() uses the inter-keypress timing, as well as the
* scancode as random inputs into the "entropy pool".
- *
+ *
* add_mouse_randomness() uses the mouse interrupt timing, as well as
* the reported position of the mouse from the hardware.
*
@@ -142,14 +142,14 @@
* regular, and hence predictable to an attacker. Disk interrupts are
* a better measure, since the timing of the disk interrupts are more
* unpredictable.
- *
+ *
* All of these routines try to estimate how many bits of randomness a
* particular randomness source. They do this by keeping track of the
* first and second order deltas of the event timings.
*
* Ensuring unpredictability at system startup
* ============================================
- *
+ *
* When any operating system starts up, it will go through a sequence
* of actions that are fairly predictable by an adversary, especially
* if the start-up does not involve interaction with a human operator.
@@ -158,7 +158,7 @@
* counteract this effect, it helps to carry information in the
* entropy pool across shut-downs and start-ups. To do this, put the
* following lines an appropriate script which is run during the boot
- * sequence:
+ * sequence:
*
* echo "Initializing random number generator..."
* random_seed=/var/run/random-seed
@@ -170,9 +170,7 @@
* touch $random_seed
* fi
* chmod 600 $random_seed
- * poolfile=/proc/sys/kernel/random/poolsize
- * [ -r $poolfile ] && bytes=`cat $poolfile` || bytes=512
- * dd if=/dev/urandom of=$random_seed count=1 bs=$bytes
+ * dd if=/dev/urandom of=$random_seed count=1 bs=512
*
* and the following lines in an appropriate script which is run as
* the system is shutdown:
@@ -183,15 +181,13 @@
* random_seed=/var/run/random-seed
* touch $random_seed
* chmod 600 $random_seed
- * poolfile=/proc/sys/kernel/random/poolsize
- * [ -r $poolfile ] && bytes=`cat $poolfile` || bytes=512
- * dd if=/dev/urandom of=$random_seed count=1 bs=$bytes
+ * dd if=/dev/urandom of=$random_seed count=1 bs=512
*
* For example, on most modern systems using the System V init
* scripts, such code fragments would be found in
* /etc/rc.d/init.d/random. On older Linux systems, the correct script
* location might be in /etc/rcb.d/rc.local or /etc/rc.d/rc.0.
- *
+ *
* Effectively, these commands cause the contents of the entropy pool
* to be saved at shut-down time and reloaded into the entropy pool at
* start-up. (The 'dd' in the addition to the bootup script is to
@@ -211,7 +207,7 @@
*
* mknod /dev/random c 1 8
* mknod /dev/urandom c 1 9
- *
+ *
* Acknowledgements:
* =================
*
@@ -221,17 +217,17 @@
* number generator, which speed up the mixing function of the entropy
* pool, taken from PGPfone. Dale Worley has also contributed many
* useful ideas and suggestions to improve this driver.
- *
+ *
* Any flaws in the design are solely my responsibility, and should
* not be attributed to the Phil, Colin, or any of authors of PGP.
- *
+ *
* The code for SHA transform was taken from Peter Gutmann's
* implementation, which has been placed in the public domain.
* The code for MD5 transform was taken from Colin Plumb's
* implementation, which has been placed in the public domain.
* The MD5 cryptographic checksum was devised by Ronald Rivest, and is
* documented in RFC 1321, "The MD5 Message Digest Algorithm".
- *
+ *
* Further background information on this topic may be obtained from
* RFC 1750, "Randomness Recommendations for Security", by Donald
* Eastlake, Steve Crocker, and Jeff Schiller.
@@ -299,8 +295,8 @@ static DEFINE_PER_CPU(int, trickle_count) = 0;
* get the twisting happening as fast as possible.
*/
static struct poolinfo {
- int poolwords;
- int tap1, tap2, tap3, tap4, tap5;
+ int poolwords;
+ int tap1, tap2, tap3, tap4, tap5;
} poolinfo_table[] = {
/* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */
{ 2048, 1638, 1231, 819, 411, 1 },
@@ -353,12 +349,12 @@ static struct poolinfo {
* II. ACM Transactions on Mdeling and Computer Simulation 4:254-266)
*
* Thanks to Colin Plumb for suggesting this.
- *
+ *
* We have not analyzed the resultant polynomial to prove it primitive;
* in fact it almost certainly isn't. Nonetheless, the irreducible factors
* of a random large-degree polynomial over GF(2) are more than large enough
* that periodicity is not a concern.
- *
+ *
* The input hash is much less sensitive than the output hash. All
* that we want of it is that it be a good non-cryptographic hash;
* i.e. it not produce collisions when fed "random" data of the sort
@@ -390,7 +386,7 @@ static struct poolinfo {
* Linux 2.2 compatibility
*/
#ifndef DECLARE_WAITQUEUE
-#define DECLARE_WAITQUEUE(WAIT, PTR) struct wait_queue WAIT = { PTR, NULL }
+#define DECLARE_WAITQUEUE(WAIT, PTR) struct wait_queue WAIT = { PTR, NULL }
#endif
#ifndef DECLARE_WAIT_QUEUE_HEAD
#define DECLARE_WAIT_QUEUE_HEAD(WAIT) struct wait_queue *WAIT
@@ -416,7 +412,7 @@ static void sysctl_init_random(struct entropy_store *random_state);
*
* Utility functions, with some ASM defined functions for speed
* purposes
- *
+ *
*****************************************************************/
/*
@@ -428,7 +424,6 @@ static void sysctl_init_random(struct entropy_store *random_state);
static inline __u32 rotate_left(int i, __u32 word)
{
return (word << i) | (word >> (32 - i));
-
}
#else
static inline __u32 rotate_left(int i, __u32 word)
@@ -442,9 +437,9 @@ static inline __u32 rotate_left(int i, __u32 word)
/*
* More asm magic....
- *
+ *
* For entropy estimation, we need to do an integral base 2
- * logarithm.
+ * logarithm.
*
* Note the "12bits" suffix - this is used for numbers between
* 0 and 4095 only. This allows a few shortcuts.
@@ -453,7 +448,7 @@ static inline __u32 rotate_left(int i, __u32 word)
static inline __u32 int_ln_12bits(__u32 word)
{
__u32 nbits = 0;
-
+
while (word >>= 1)
nbits++;
return nbits;
@@ -487,20 +482,20 @@ static inline __u32 int_ln_12bits(__u32 word)
*
* OS independent entropy store. Here are the functions which handle
* storing entropy in an entropy pool.
- *
+ *
**********************************************************************/
struct entropy_store {
/* mostly-read data: */
struct poolinfo poolinfo;
- __u32 *pool;
- const char *name;
+ __u32 *pool;
+ const char *name;
/* read-write data: */
spinlock_t lock ____cacheline_aligned_in_smp;
- unsigned add_ptr;
- int entropy_count;
- int input_rotate;
+ unsigned add_ptr;
+ int entropy_count;
+ int input_rotate;
};
/*
@@ -512,9 +507,9 @@ struct entropy_store {
static int create_entropy_store(int size, const char *name,
struct entropy_store **ret_bucket)
{
- struct entropy_store *r;
- struct poolinfo *p;
- int poolwords;
+ struct entropy_store *r;
+ struct poolinfo *p;
+ int poolwords;
poolwords = (size + 3) / 4; /* Convert bytes->words */
/* The pool size must be a multiple of 16 32-bit words */
@@ -554,19 +549,12 @@ static void clear_entropy_store(struct entropy_store *r)
r->input_rotate = 0;
memset(r->pool, 0, r->poolinfo.POOLBYTES);
}
-#ifdef CONFIG_SYSCTL
-static void free_entropy_store(struct entropy_store *r)
-{
- if (r->pool)
- kfree(r->pool);
- kfree(r);
-}
-#endif
+
/*
* This function adds a byte into the entropy "pool". It does not
* update the entropy estimate. The caller should call
* credit_entropy_store if this is appropriate.
- *
+ *
* The pool is stirred with a primitive polynomial of the appropriate
* degree, and then twisted. We twist by three bits at a time because
* it's cheap to do so and helps slightly in the expected case where
@@ -576,7 +564,7 @@ static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
int nwords, __u32 out[16])
{
static __u32 const twist_table[8] = {
- 0, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+ 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
unsigned long i, add_ptr, tap1, tap2, tap3, tap4, tap5;
int new_rotate, input_rotate;
@@ -642,7 +630,6 @@ static inline void add_entropy_words(struct entropy_store *r, const __u32 *in,
__add_entropy_words(r, in, nwords, NULL);
}
-
/*
* Credit (or debit) the entropy store with n bits of entropy
*/
@@ -682,10 +669,10 @@ struct sample {
};
static struct sample *batch_entropy_pool, *batch_entropy_copy;
-static int batch_head, batch_tail;
+static int batch_head, batch_tail;
static DEFINE_SPINLOCK(batch_lock);
-static int batch_max;
+static int batch_max;
static void batch_entropy_process(void *private_);
static DECLARE_WORK(batch_work, batch_entropy_process, NULL);
@@ -726,19 +713,14 @@ static void batch_entropy_store(u32 a, u32 b, int num)
batch_entropy_pool[batch_head].data[1] = b;
batch_entropy_pool[batch_head].credit = num;
- if (((batch_head - batch_tail) & (batch_max-1)) >= (batch_max / 2)) {
- /*
- * Schedule it for the next timer tick:
- */
+ if (((batch_head - batch_tail) & (batch_max - 1)) >= (batch_max / 2))
schedule_delayed_work(&batch_work, 1);
- }
- new = (batch_head+1) & (batch_max-1);
- if (new == batch_tail) {
+ new = (batch_head + 1) & (batch_max - 1);
+ if (new == batch_tail)
DEBUG_ENT("batch entropy buffer full\n");
- } else {
+ else
batch_head = new;
- }
spin_unlock_irqrestore(&batch_lock, flags);
}
@@ -762,7 +744,7 @@ static void batch_entropy_process(void *private_)
spin_lock_irq(&batch_lock);
memcpy(batch_entropy_copy, batch_entropy_pool,
- batch_max*sizeof(struct sample));
+ batch_max * sizeof(struct sample));
head = batch_head;
tail = batch_tail;
@@ -773,13 +755,13 @@ static void batch_entropy_process(void *private_)
p = r;
while (head != tail) {
if (r->entropy_count >= max_entropy) {
- r = (r == sec_random_state) ? random_state :
- sec_random_state;
+ r = (r == sec_random_state) ? random_state :
+ sec_random_state;
max_entropy = r->poolinfo.POOLBITS;
}
add_entropy_words(r, batch_entropy_copy[tail].data, 2);
credit_entropy_store(r, batch_entropy_copy[tail].credit);
- tail = (tail+1) & (batch_max-1);
+ tail = (tail + 1) & (batch_max - 1);
}
if (p->entropy_count >= random_read_wakeup_thresh)
wake_up_interruptible(&random_read_wait);
@@ -793,9 +775,9 @@ static void batch_entropy_process(void *private_)
/* There is one of these per entropy source */
struct timer_rand_state {
- cycles_t last_time;
- long last_delta,last_delta2;
- unsigned dont_count_entropy:1;
+ cycles_t last_time;
+ long last_delta,last_delta2;
+ unsigned dont_count_entropy:1;
};
static struct timer_rand_state keyboard_timer_state;
@@ -815,14 +797,14 @@ static struct timer_rand_state *irq_timer_state[NR_IRQS];
*/
static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
{
- cycles_t time;
- long delta, delta2, delta3;
- int entropy = 0;
+ cycles_t time;
+ long delta, delta2, delta3;
+ int entropy = 0;
preempt_disable();
/* if over the trickle threshold, use only 1 in 4096 samples */
- if ( random_state->entropy_count > trickle_thresh &&
- (__get_cpu_var(trickle_count)++ & 0xfff))
+ if (random_state->entropy_count > trickle_thresh &&
+ (__get_cpu_var(trickle_count)++ & 0xfff))
goto out;
/*
@@ -898,7 +880,7 @@ void add_interrupt_randomness(int irq)
if (irq >= NR_IRQS || irq_timer_state[irq] == 0)
return;
- add_timer_randomness(irq_timer_state[irq], 0x100+irq);
+ add_timer_randomness(irq_timer_state[irq], 0x100 + irq);
}
void add_disk_randomness(struct gendisk *disk)
@@ -906,7 +888,8 @@ void add_disk_randomness(struct gendisk *disk)
if (!disk || !disk->random)
return;
/* first major is 1, so we get >= 0x200 here */
- add_timer_randomness(disk->random, 0x100+MKDEV(disk->major, disk->first_minor));
+ add_timer_randomness(disk->random,
+ 0x100 + MKDEV(disk->major, disk->first_minor));
}
EXPORT_SYMBOL(add_disk_randomness);
@@ -921,7 +904,7 @@ EXPORT_SYMBOL(add_disk_randomness);
* This chunk of code defines a function
* void HASH_TRANSFORM(__u32 digest[HASH_BUFFER_SIZE + HASH_EXTRA_SIZE],
* __u32 const data[16])
- *
+ *
* The function hashes the input data to produce a digest in the first
* HASH_BUFFER_SIZE words of the digest[] array, and uses HASH_EXTRA_SIZE
* more words for internal purposes. (This buffer is exported so the
@@ -936,7 +919,7 @@ EXPORT_SYMBOL(add_disk_randomness);
* 3) 0x98badcfe
* 4) 0x10325476
* 5) 0xc3d2e1f0 (SHA only)
- *
+ *
* For /dev/random purposes, the length of the data being hashed is
* fixed in length, so appending a bit count in the usual way is not
* cryptographically necessary.
@@ -958,9 +941,9 @@ EXPORT_SYMBOL(add_disk_randomness);
/* The SHA f()-functions. */
-#define f1(x,y,z) ( z ^ (x & (y^z)) ) /* Rounds 0-19: x ? y : z */
+#define f1(x,y,z) (z ^ (x & (y ^ z))) /* Rounds 0-19: x ? y : z */
#define f2(x,y,z) (x ^ y ^ z) /* Rounds 20-39: XOR */
-#define f3(x,y,z) ( (x & y) + (z & (x ^ y)) ) /* Rounds 40-59: majority */
+#define f3(x,y,z) ((x & y) + (z & (x ^ y))) /* Rounds 40-59: majority */
#define f4(x,y,z) (x ^ y ^ z) /* Rounds 60-79: XOR */
/* The SHA Mysterious Constants */
@@ -970,199 +953,198 @@ EXPORT_SYMBOL(add_disk_randomness);
#define K3 0x8F1BBCDCL /* Rounds 40-59: sqrt(5) * 2^30 */
#define K4 0xCA62C1D6L /* Rounds 60-79: sqrt(10) * 2^30 */
-#define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )
+#define ROTL(n,X) (((X) << n ) | ((X) >> (32 - n)))
#define subRound(a, b, c, d, e, f, k, data) \
- ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) )
-
+ (e += ROTL(5, a) + f(b, c, d) + k + data, b = ROTL(30, b))
static void SHATransform(__u32 digest[85], __u32 const data[16])
{
- __u32 A, B, C, D, E; /* Local vars */
- __u32 TEMP;
- int i;
+ __u32 A, B, C, D, E; /* Local vars */
+ __u32 TEMP;
+ int i;
#define W (digest + HASH_BUFFER_SIZE) /* Expanded data array */
- /*
- * Do the preliminary expansion of 16 to 80 words. Doing it
- * out-of-line line this is faster than doing it in-line on
- * register-starved machines like the x86, and not really any
- * slower on real processors.
- */
- memcpy(W, data, 16*sizeof(__u32));
- for (i = 0; i < 64; i++) {
- TEMP = W[i] ^ W[i+2] ^ W[i+8] ^ W[i+13];
- W[i+16] = ROTL(1, TEMP);
- }
-
- /* Set up first buffer and local data buffer */
- A = digest[ 0 ];
- B = digest[ 1 ];
- C = digest[ 2 ];
- D = digest[ 3 ];
- E = digest[ 4 ];
-
- /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */
+ /*
+ * Do the preliminary expansion of 16 to 80 words. Doing it
+ * out-of-line line this is faster than doing it in-line on
+ * register-starved machines like the x86, and not really any
+ * slower on real processors.
+ */
+ memcpy(W, data, 16*sizeof(__u32));
+ for (i = 0; i < 64; i++) {
+ TEMP = W[i] ^ W[i+2] ^ W[i+8] ^ W[i+13];
+ W[i+16] = ROTL(1, TEMP);
+ }
+
+ /* Set up first buffer and local data buffer */
+ A = digest[ 0 ];
+ B = digest[ 1 ];
+ C = digest[ 2 ];
+ D = digest[ 3 ];
+ E = digest[ 4 ];
+
+ /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */
#if SHA_CODE_SIZE == 0
- /*
- * Approximately 50% of the speed of the largest version, but
- * takes up 1/16 the space. Saves about 6k on an i386 kernel.
- */
- for (i = 0; i < 80; i++) {
- if (i < 40) {
- if (i < 20)
- TEMP = f1(B, C, D) + K1;
- else
- TEMP = f2(B, C, D) + K2;
- } else {
- if (i < 60)
- TEMP = f3(B, C, D) + K3;
- else
- TEMP = f4(B, C, D) + K4;
+ /*
+ * Approximately 50% of the speed of the largest version, but
+ * takes up 1/16 the space. Saves about 6k on an i386 kernel.
+ */
+ for (i = 0; i < 80; i++) {
+ if (i < 40) {
+ if (i < 20)
+ TEMP = f1(B, C, D) + K1;
+ else
+ TEMP = f2(B, C, D) + K2;
+ } else {
+ if (i < 60)
+ TEMP = f3(B, C, D) + K3;
+ else
+ TEMP = f4(B, C, D) + K4;
+ }
+ TEMP += ROTL(5, A) + E + W[i];
+ E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
}
- TEMP += ROTL(5, A) + E + W[i];
- E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
- }
#elif SHA_CODE_SIZE == 1
- for (i = 0; i < 20; i++) {
- TEMP = f1(B, C, D) + K1 + ROTL(5, A) + E + W[i];
- E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
- }
- for (; i < 40; i++) {
- TEMP = f2(B, C, D) + K2 + ROTL(5, A) + E + W[i];
- E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
- }
- for (; i < 60; i++) {
- TEMP = f3(B, C, D) + K3 + ROTL(5, A) + E + W[i];
- E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
- }
- for (; i < 80; i++) {
- TEMP = f4(B, C, D) + K4 + ROTL(5, A) + E + W[i];
- E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
- }
+ for (i = 0; i < 20; i++) {
+ TEMP = f1(B, C, D) + K1 + ROTL(5, A) + E + W[i];
+ E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
+ }
+ for (; i < 40; i++) {
+ TEMP = f2(B, C, D) + K2 + ROTL(5, A) + E + W[i];
+ E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
+ }
+ for (; i < 60; i++) {
+ TEMP = f3(B, C, D) + K3 + ROTL(5, A) + E + W[i];
+ E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
+ }
+ for (; i < 80; i++) {
+ TEMP = f4(B, C, D) + K4 + ROTL(5, A) + E + W[i];
+ E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
+ }
#elif SHA_CODE_SIZE == 2
- for (i = 0; i < 20; i += 5) {
- subRound( A, B, C, D, E, f1, K1, W[ i ] );
- subRound( E, A, B, C, D, f1, K1, W[ i+1 ] );
- subRound( D, E, A, B, C, f1, K1, W[ i+2 ] );
- subRound( C, D, E, A, B, f1, K1, W[ i+3 ] );
- subRound( B, C, D, E, A, f1, K1, W[ i+4 ] );
- }
- for (; i < 40; i += 5) {
- subRound( A, B, C, D, E, f2, K2, W[ i ] );
- subRound( E, A, B, C, D, f2, K2, W[ i+1 ] );
- subRound( D, E, A, B, C, f2, K2, W[ i+2 ] );
- subRound( C, D, E, A, B, f2, K2, W[ i+3 ] );
- subRound( B, C, D, E, A, f2, K2, W[ i+4 ] );
- }
- for (; i < 60; i += 5) {
- subRound( A, B, C, D, E, f3, K3, W[ i ] );
- subRound( E, A, B, C, D, f3, K3, W[ i+1 ] );
- subRound( D, E, A, B, C, f3, K3, W[ i+2 ] );
- subRound( C, D, E, A, B, f3, K3, W[ i+3 ] );
- subRound( B, C, D, E, A, f3, K3, W[ i+4 ] );
- }
- for (; i < 80; i += 5) {
- subRound( A, B, C, D, E, f4, K4, W[ i ] );
- subRound( E, A, B, C, D, f4, K4, W[ i+1 ] );
- subRound( D, E, A, B, C, f4, K4, W[ i+2 ] );
- subRound( C, D, E, A, B, f4, K4, W[ i+3 ] );
- subRound( B, C, D, E, A, f4, K4, W[ i+4 ] );
- }
+ for (i = 0; i < 20; i += 5) {
+ subRound(A, B, C, D, E, f1, K1, W[i ]);
+ subRound(E, A, B, C, D, f1, K1, W[i+1]);
+ subRound(D, E, A, B, C, f1, K1, W[i+2]);
+ subRound(C, D, E, A, B, f1, K1, W[i+3]);
+ subRound(B, C, D, E, A, f1, K1, W[i+4]);
+ }
+ for (; i < 40; i += 5) {
+ subRound(A, B, C, D, E, f2, K2, W[i ]);
+ subRound(E, A, B, C, D, f2, K2, W[i+1]);
+ subRound(D, E, A, B, C, f2, K2, W[i+2]);
+ subRound(C, D, E, A, B, f2, K2, W[i+3]);
+ subRound(B, C, D, E, A, f2, K2, W[i+4]);
+ }
+ for (; i < 60; i += 5) {
+ subRound(A, B, C, D, E, f3, K3, W[i ]);
+ subRound(E, A, B, C, D, f3, K3, W[i+1]);
+ subRound(D, E, A, B, C, f3, K3, W[i+2]);
+ subRound(C, D, E, A, B, f3, K3, W[i+3]);
+ subRound(B, C, D, E, A, f3, K3, W[i+4]);
+ }
+ for (; i < 80; i += 5) {
+ subRound(A, B, C, D, E, f4, K4, W[i ]);
+ subRound(E, A, B, C, D, f4, K4, W[i+1]);
+ subRound(D, E, A, B, C, f4, K4, W[i+2]);
+ subRound(C, D, E, A, B, f4, K4, W[i+3]);
+ subRound(B, C, D, E, A, f4, K4, W[i+4]);
+ }
#elif SHA_CODE_SIZE == 3 /* Really large version */
- subRound( A, B, C, D, E, f1, K1, W[ 0 ] );
- subRound( E, A, B, C, D, f1, K1, W[ 1 ] );
- subRound( D, E, A, B, C, f1, K1, W[ 2 ] );
- subRound( C, D, E, A, B, f1, K1, W[ 3 ] );
- subRound( B, C, D, E, A, f1, K1, W[ 4 ] );
- subRound( A, B, C, D, E, f1, K1, W[ 5 ] );
- subRound( E, A, B, C, D, f1, K1, W[ 6 ] );
- subRound( D, E, A, B, C, f1, K1, W[ 7 ] );
- subRound( C, D, E, A, B, f1, K1, W[ 8 ] );
- subRound( B, C, D, E, A, f1, K1, W[ 9 ] );
- subRound( A, B, C, D, E, f1, K1, W[ 10 ] );
- subRound( E, A, B, C, D, f1, K1, W[ 11 ] );
- subRound( D, E, A, B, C, f1, K1, W[ 12 ] );
- subRound( C, D, E, A, B, f1, K1, W[ 13 ] );
- subRound( B, C, D, E, A, f1, K1, W[ 14 ] );
- subRound( A, B, C, D, E, f1, K1, W[ 15 ] );
- subRound( E, A, B, C, D, f1, K1, W[ 16 ] );
- subRound( D, E, A, B, C, f1, K1, W[ 17 ] );
- subRound( C, D, E, A, B, f1, K1, W[ 18 ] );
- subRound( B, C, D, E, A, f1, K1, W[ 19 ] );
-
- subRound( A, B, C, D, E, f2, K2, W[ 20 ] );
- subRound( E, A, B, C, D, f2, K2, W[ 21 ] );
- subRound( D, E, A, B, C, f2, K2, W[ 22 ] );
- subRound( C, D, E, A, B, f2, K2, W[ 23 ] );
- subRound( B, C, D, E, A, f2, K2, W[ 24 ] );
- subRound( A, B, C, D, E, f2, K2, W[ 25 ] );
- subRound( E, A, B, C, D, f2, K2, W[ 26 ] );
- subRound( D, E, A, B, C, f2, K2, W[ 27 ] );
- subRound( C, D, E, A, B, f2, K2, W[ 28 ] );
- subRound( B, C, D, E, A, f2, K2, W[ 29 ] );
- subRound( A, B, C, D, E, f2, K2, W[ 30 ] );
- subRound( E, A, B, C, D, f2, K2, W[ 31 ] );
- subRound( D, E, A, B, C, f2, K2, W[ 32 ] );
- subRound( C, D, E, A, B, f2, K2, W[ 33 ] );
- subRound( B, C, D, E, A, f2, K2, W[ 34 ] );
- subRound( A, B, C, D, E, f2, K2, W[ 35 ] );
- subRound( E, A, B, C, D, f2, K2, W[ 36 ] );
- subRound( D, E, A, B, C, f2, K2, W[ 37 ] );
- subRound( C, D, E, A, B, f2, K2, W[ 38 ] );
- subRound( B, C, D, E, A, f2, K2, W[ 39 ] );
-
- subRound( A, B, C, D, E, f3, K3, W[ 40 ] );
- subRound( E, A, B, C, D, f3, K3, W[ 41 ] );
- subRound( D, E, A, B, C, f3, K3, W[ 42 ] );
- subRound( C, D, E, A, B, f3, K3, W[ 43 ] );
- subRound( B, C, D, E, A, f3, K3, W[ 44 ] );
- subRound( A, B, C, D, E, f3, K3, W[ 45 ] );
- subRound( E, A, B, C, D, f3, K3, W[ 46 ] );
- subRound( D, E, A, B, C, f3, K3, W[ 47 ] );
- subRound( C, D, E, A, B, f3, K3, W[ 48 ] );
- subRound( B, C, D, E, A, f3, K3, W[ 49 ] );
- subRound( A, B, C, D, E, f3, K3, W[ 50 ] );
- subRound( E, A, B, C, D, f3, K3, W[ 51 ] );
- subRound( D, E, A, B, C, f3, K3, W[ 52 ] );
- subRound( C, D, E, A, B, f3, K3, W[ 53 ] );
- subRound( B, C, D, E, A, f3, K3, W[ 54 ] );
- subRound( A, B, C, D, E, f3, K3, W[ 55 ] );
- subRound( E, A, B, C, D, f3, K3, W[ 56 ] );
- subRound( D, E, A, B, C, f3, K3, W[ 57 ] );
- subRound( C, D, E, A, B, f3, K3, W[ 58 ] );
- subRound( B, C, D, E, A, f3, K3, W[ 59 ] );
-
- subRound( A, B, C, D, E, f4, K4, W[ 60 ] );
- subRound( E, A, B, C, D, f4, K4, W[ 61 ] );
- subRound( D, E, A, B, C, f4, K4, W[ 62 ] );
- subRound( C, D, E, A, B, f4, K4, W[ 63 ] );
- subRound( B, C, D, E, A, f4, K4, W[ 64 ] );
- subRound( A, B, C, D, E, f4, K4, W[ 65 ] );
- subRound( E, A, B, C, D, f4, K4, W[ 66 ] );
- subRound( D, E, A, B, C, f4, K4, W[ 67 ] );
- subRound( C, D, E, A, B, f4, K4, W[ 68 ] );
- subRound( B, C, D, E, A, f4, K4, W[ 69 ] );
- subRound( A, B, C, D, E, f4, K4, W[ 70 ] );
- subRound( E, A, B, C, D, f4, K4, W[ 71 ] );
- subRound( D, E, A, B, C, f4, K4, W[ 72 ] );
- subRound( C, D, E, A, B, f4, K4, W[ 73 ] );
- subRound( B, C, D, E, A, f4, K4, W[ 74 ] );
- subRound( A, B, C, D, E, f4, K4, W[ 75 ] );
- subRound( E, A, B, C, D, f4, K4, W[ 76 ] );
- subRound( D, E, A, B, C, f4, K4, W[ 77 ] );
- subRound( C, D, E, A, B, f4, K4, W[ 78 ] );
- subRound( B, C, D, E, A, f4, K4, W[ 79 ] );
+ subRound(A, B, C, D, E, f1, K1, W[ 0]);
+ subRound(E, A, B, C, D, f1, K1, W[ 1]);
+ subRound(D, E, A, B, C, f1, K1, W[ 2]);
+ subRound(C, D, E, A, B, f1, K1, W[ 3]);
+ subRound(B, C, D, E, A, f1, K1, W[ 4]);
+ subRound(A, B, C, D, E, f1, K1, W[ 5]);
+ subRound(E, A, B, C, D, f1, K1, W[ 6]);
+ subRound(D, E, A, B, C, f1, K1, W[ 7]);
+ subRound(C, D, E, A, B, f1, K1, W[ 8]);
+ subRound(B, C, D, E, A, f1, K1, W[ 9]);
+ subRound(A, B, C, D, E, f1, K1, W[10]);
+ subRound(E, A, B, C, D, f1, K1, W[11]);
+ subRound(D, E, A, B, C, f1, K1, W[12]);
+ subRound(C, D, E, A, B, f1, K1, W[13]);
+ subRound(B, C, D, E, A, f1, K1, W[14]);
+ subRound(A, B, C, D, E, f1, K1, W[15]);
+ subRound(E, A, B, C, D, f1, K1, W[16]);
+ subRound(D, E, A, B, C, f1, K1, W[17]);
+ subRound(C, D, E, A, B, f1, K1, W[18]);
+ subRound(B, C, D, E, A, f1, K1, W[19]);
+
+ subRound(A, B, C, D, E, f2, K2, W[20]);
+ subRound(E, A, B, C, D, f2, K2, W[21]);
+ subRound(D, E, A, B, C, f2, K2, W[22]);
+ subRound(C, D, E, A, B, f2, K2, W[23]);
+ subRound(B, C, D, E, A, f2, K2, W[24]);
+ subRound(A, B, C, D, E, f2, K2, W[25]);
+ subRound(E, A, B, C, D, f2, K2, W[26]);
+ subRound(D, E, A, B, C, f2, K2, W[27]);
+ subRound(C, D, E, A, B, f2, K2, W[28]);
+ subRound(B, C, D, E, A, f2, K2, W[29]);
+ subRound(A, B, C, D, E, f2, K2, W[30]);
+ subRound(E, A, B, C, D, f2, K2, W[31]);
+ subRound(D, E, A, B, C, f2, K2, W[32]);
+ subRound(C, D, E, A, B, f2, K2, W[33]);
+ subRound(B, C, D, E, A, f2, K2, W[34]);
+ subRound(A, B, C, D, E, f2, K2, W[35]);
+ subRound(E, A, B, C, D, f2, K2, W[36]);
+ subRound(D, E, A, B, C, f2, K2, W[37]);
+ subRound(C, D, E, A, B, f2, K2, W[38]);
+ subRound(B, C, D, E, A, f2, K2, W[39]);
+
+ subRound(A, B, C, D, E, f3, K3, W[40]);
+ subRound(E, A, B, C, D, f3, K3, W[41]);
+ subRound(D, E, A, B, C, f3, K3, W[42]);
+ subRound(C, D, E, A, B, f3, K3, W[43]);
+ subRound(B, C, D, E, A, f3, K3, W[44]);
+ subRound(A, B, C, D, E, f3, K3, W[45]);
+ subRound(E, A, B, C, D, f3, K3, W[46]);
+ subRound(D, E, A, B, C, f3, K3, W[47]);
+ subRound(C, D, E, A, B, f3, K3, W[48]);
+ subRound(B, C, D, E, A, f3, K3, W[49]);
+ subRound(A, B, C, D, E, f3, K3, W[50]);
+ subRound(E, A, B, C, D, f3, K3, W[51]);
+ subRound(D, E, A, B, C, f3, K3, W[52]);
+ subRound(C, D, E, A, B, f3, K3, W[53]);
+ subRound(B, C, D, E, A, f3, K3, W[54]);
+ subRound(A, B, C, D, E, f3, K3, W[55]);
+ subRound(E, A, B, C, D, f3, K3, W[56]);
+ subRound(D, E, A, B, C, f3, K3, W[57]);
+ subRound(C, D, E, A, B, f3, K3, W[58]);
+ subRound(B, C, D, E, A, f3, K3, W[59]);
+
+ subRound(A, B, C, D, E, f4, K4, W[60]);
+ subRound(E, A, B, C, D, f4, K4, W[61]);
+ subRound(D, E, A, B, C, f4, K4, W[62]);
+ subRound(C, D, E, A, B, f4, K4, W[63]);
+ subRound(B, C, D, E, A, f4, K4, W[64]);
+ subRound(A, B, C, D, E, f4, K4, W[65]);
+ subRound(E, A, B, C, D, f4, K4, W[66]);
+ subRound(D, E, A, B, C, f4, K4, W[67]);
+ subRound(C, D, E, A, B, f4, K4, W[68]);
+ subRound(B, C, D, E, A, f4, K4, W[69]);
+ subRound(A, B, C, D, E, f4, K4, W[70]);
+ subRound(E, A, B, C, D, f4, K4, W[71]);
+ subRound(D, E, A, B, C, f4, K4, W[72]);
+ subRound(C, D, E, A, B, f4, K4, W[73]);
+ subRound(B, C, D, E, A, f4, K4, W[74]);
+ subRound(A, B, C, D, E, f4, K4, W[75]);
+ subRound(E, A, B, C, D, f4, K4, W[76]);
+ subRound(D, E, A, B, C, f4, K4, W[77]);
+ subRound(C, D, E, A, B, f4, K4, W[78]);
+ subRound(B, C, D, E, A, f4, K4, W[79]);
#else
#error Illegal SHA_CODE_SIZE
#endif
- /* Build message digest */
- digest[ 0 ] += A;
- digest[ 1 ] += B;
- digest[ 2 ] += C;
- digest[ 3 ] += D;
- digest[ 4 ] += E;
+ /* Build message digest */
+ digest[0] += A;
+ digest[1] += B;
+ digest[2] += C;
+ digest[3] += D;
+ digest[4] += E;
/* W is wiped by the caller */
#undef W
@@ -1173,18 +1155,18 @@ static void SHATransform(__u32 digest[85], __u32 const data[16])
#undef f2
#undef f3
#undef f4
-#undef K1
+#undef K1
#undef K2
-#undef K3
-#undef K4
+#undef K3
+#undef K4
#undef subRound
-
+
#else /* !USE_SHA - Use MD5 */
#define HASH_BUFFER_SIZE 4
#define HASH_EXTRA_SIZE 0
#define HASH_TRANSFORM MD5Transform
-
+
/*
* MD5 transform algorithm, taken from code written by Colin Plumb,
* and put into the public domain
@@ -1200,7 +1182,7 @@ static void SHATransform(__u32 digest[85], __u32 const data[16])
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
- ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+ (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
@@ -1360,7 +1342,6 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf,
__u32 x;
unsigned long cpuflags;
-
/* Redundant, but just in case... */
if (r->entropy_count > r->poolinfo.POOLBITS)
r->entropy_count = r->poolinfo.POOLBITS;
@@ -1456,7 +1437,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf,
x ^= (x >> 16); /* Fold it in half */
((__u16 *)tmp)[HASH_BUFFER_SIZE-1] = (__u16)x;
#endif
-
+
/* Copy data to destination buffer */
i = min(nbytes, HASH_BUFFER_SIZE*sizeof(__u32)/2);
if (flags & EXTRACT_ENTROPY_USER) {
@@ -1467,6 +1448,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf,
}
} else
memcpy(buf, (__u8 const *)tmp, i);
+
nbytes -= i;
buf += i;
ret += i;
@@ -1474,7 +1456,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf,
/* Wipe data just returned from memory */
memset(tmp, 0, sizeof(tmp));
-
+
return ret;
}
@@ -1517,10 +1499,10 @@ EXPORT_SYMBOL(get_random_bytes);
*/
static void init_std_data(struct entropy_store *r)
{
- struct timeval tv;
- __u32 words[2];
- char *p;
- int i;
+ struct timeval tv;
+ __u32 words[2];
+ char *p;
+ int i;
do_gettimeofday(&tv);
words[0] = tv.tv_sec;
@@ -1577,7 +1559,7 @@ module_init(rand_initialize);
void rand_initialize_irq(int irq)
{
struct timer_rand_state *state;
-
+
if (irq >= NR_IRQS || irq_timer_state[irq])
return;
@@ -1591,11 +1573,11 @@ void rand_initialize_irq(int irq)
irq_timer_state[irq] = state;
}
}
-
+
void rand_initialize_disk(struct gendisk *disk)
{
struct timer_rand_state *state;
-
+
/*
* If kmalloc returns null, we just won't use that entropy
* source.
@@ -1611,8 +1593,8 @@ static ssize_t
random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
{
DECLARE_WAITQUEUE(wait, current);
- ssize_t n, retval = 0, count = 0;
-
+ ssize_t n, retval = 0, count = 0;
+
if (nbytes == 0)
return 0;
@@ -1683,7 +1665,7 @@ random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
*/
if (count)
file_accessed(file);
-
+
return (count ? count : retval);
}
@@ -1721,11 +1703,11 @@ static ssize_t
random_write(struct file * file, const char __user * buffer,
size_t count, loff_t *ppos)
{
- int ret = 0;
- size_t bytes;
- __u32 buf[16];
- const char __user *p = buffer;
- size_t c = count;
+ int ret = 0;
+ size_t bytes;
+ __u32 buf[16];
+ const char __user *p = buffer;
+ size_t c = count;
while (c > 0) {
bytes = min(c, sizeof(buf));
@@ -1757,7 +1739,7 @@ random_ioctl(struct inode * inode, struct file * file,
int size, ent_count;
int __user *p = (int __user *)arg;
int retval;
-
+
switch (cmd) {
case RNDGETENTCNT:
ent_count = random_state->entropy_count;
@@ -1816,22 +1798,22 @@ random_ioctl(struct inode * inode, struct file * file,
}
struct file_operations random_fops = {
- .read = random_read,
- .write = random_write,
- .poll = random_poll,
- .ioctl = random_ioctl,
+ .read = random_read,
+ .write = random_write,
+ .poll = random_poll,
+ .ioctl = random_ioctl,
};
struct file_operations urandom_fops = {
- .read = urandom_read,
- .write = random_write,
- .ioctl = random_ioctl,
+ .read = urandom_read,
+ .write = random_write,
+ .ioctl = random_ioctl,
};
/***************************************************************
* Random UUID interface
- *
- * Used here for a Boot ID, but can be useful for other kernel
+ *
+ * Used here for a Boot ID, but can be useful for other kernel
* drivers.
***************************************************************/
@@ -1859,91 +1841,24 @@ EXPORT_SYMBOL(generate_random_uuid);
#include <linux/sysctl.h>
-static int sysctl_poolsize;
static int min_read_thresh, max_read_thresh;
static int min_write_thresh, max_write_thresh;
static char sysctl_bootid[16];
/*
- * This function handles a request from the user to change the pool size
- * of the primary entropy store.
- */
-static int change_poolsize(int poolsize)
-{
- struct entropy_store *new_store, *old_store;
- int ret;
-
- if ((ret = create_entropy_store(poolsize, random_state->name,
- &new_store)))
- return ret;
-
- add_entropy_words(new_store, random_state->pool,
- random_state->poolinfo.poolwords);
- credit_entropy_store(new_store, random_state->entropy_count);
-
- sysctl_init_random(new_store);
- old_store = random_state;
- random_state = batch_work.data = new_store;
- free_entropy_store(old_store);
- return 0;
-}
-
-static int proc_do_poolsize(ctl_table *table, int write, struct file *filp,
- void __user *buffer, size_t *lenp, loff_t *ppos)
-{
- int ret;
-
- sysctl_poolsize = random_state->poolinfo.POOLBYTES;
-
- ret = proc_dointvec(table, write, filp, buffer, lenp, ppos);
- if (ret || !write ||
- (sysctl_poolsize == random_state->poolinfo.POOLBYTES))
- return ret;
-
- return change_poolsize(sysctl_poolsize);
-}
-
-static int poolsize_strategy(ctl_table *table, int __user *name, int nlen,
- void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen, void **context)
-{
- int len;
-
- sysctl_poolsize = random_state->poolinfo.POOLBYTES;
-
- /*
- * We only handle the write case, since the read case gets
- * handled by the default handler (and we don't care if the
- * write case happens twice; it's harmless).
- */
- if (newval && newlen) {
- len = newlen;
- if (len > table->maxlen)
- len = table->maxlen;
- if (copy_from_user(table->data, newval, len))
- return -EFAULT;
- }
-
- if (sysctl_poolsize != random_state->poolinfo.POOLBYTES)
- return change_poolsize(sysctl_poolsize);
-
- return 0;
-}
-
-/*
* These functions is used to return both the bootid UUID, and random
* UUID. The difference is in whether table->data is NULL; if it is,
* then a new UUID is generated and returned to the user.
- *
+ *
* If the user accesses this via the proc interface, it will be returned
- * as an ASCII string in the standard UUID format. If accesses via the
+ * as an ASCII string in the standard UUID format. If accesses via the
* sysctl system call, it is returned as 16 bytes of binary data.
*/
static int proc_do_uuid(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
- ctl_table fake_table;
- unsigned char buf[64], tmp_uuid[16], *uuid;
+ ctl_table fake_table;
+ unsigned char buf[64], tmp_uuid[16], *uuid;
uuid = table->data;
if (!uuid) {
@@ -1969,8 +1884,8 @@ static int uuid_strategy(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen, void **context)
{
- unsigned char tmp_uuid[16], *uuid;
- unsigned int len;
+ unsigned char tmp_uuid[16], *uuid;
+ unsigned int len;
if (!oldval || !oldlenp)
return 1;
@@ -1995,15 +1910,15 @@ static int uuid_strategy(ctl_table *table, int __user *name, int nlen,
return 1;
}
+static int sysctl_poolsize = DEFAULT_POOL_SIZE;
ctl_table random_table[] = {
{
- .ctl_name = RANDOM_POOLSIZE,
+ .ctl_name = RANDOM_POOLSIZE,
.procname = "poolsize",
.data = &sysctl_poolsize,
.maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_do_poolsize,
- .strategy = &poolsize_strategy,
+ .mode = 0444,
+ .proc_handler = &proc_dointvec,
},
{
.ctl_name = RANDOM_ENTROPY_COUNT,
@@ -2095,7 +2010,7 @@ static void sysctl_init_random(struct entropy_store *random_state)
* Rotation is separate from addition to prevent recomputation
*/
#define ROUND(f, a, b, c, d, x, s) \
- (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
+ (a += f(b, c, d) + x, a = (a << s) | (a >> (32 - s)))
#define K1 0
#define K2 013240474631UL
#define K3 015666365641UL
@@ -2105,7 +2020,7 @@ static void sysctl_init_random(struct entropy_store *random_state)
*/
static __u32 halfMD4Transform (__u32 const buf[4], __u32 const in[8])
{
- __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+ __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
/* Round 1 */
ROUND(F, a, b, c, d, in[0] + K1, 3);
@@ -2145,7 +2060,7 @@ static __u32 halfMD4Transform (__u32 const buf[4], __u32 const in[8])
static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
{
- __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+ __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
/* Round 1 */
ROUND(F, a, b, c, d, in[ 0] + K1, 3);
@@ -2189,7 +2104,7 @@ static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
ROUND(H, c, d, a, b, in[ 4] + K3, 11);
ROUND(H, b, c, d, a, in[ 8] + K3, 15);
- return buf[1] + b; /* "most hashed" word */
+ return buf[1] + b; /* "most hashed" word */
/* Alternative: return sum of all words? */
}
#endif
@@ -2203,7 +2118,7 @@ static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
#undef K3
/* This should not be decreased so low that ISNs wrap too fast. */
-#define REKEY_INTERVAL (300*HZ)
+#define REKEY_INTERVAL (300 * HZ)
/*
* Bit layout of the tcp sequence numbers (before adding current time):
* bit 24-31: increased after every key exchange
@@ -2221,16 +2136,16 @@ static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
*
* SMP cleanup and lock avoidance with poor man's RCU.
* Manfred Spraul <manfred@colorfullife.com>
- *
+ *
*/
-#define COUNT_BITS 8
-#define COUNT_MASK ( (1<<COUNT_BITS)-1)
-#define HASH_BITS 24
-#define HASH_MASK ( (1<<HASH_BITS)-1 )
+#define COUNT_BITS 8
+#define COUNT_MASK ((1 << COUNT_BITS) - 1)
+#define HASH_BITS 24
+#define HASH_MASK ((1 << HASH_BITS) - 1)
static struct keydata {
- __u32 count; // already shifted to the final position
- __u32 secret[12];
+ __u32 count; /* already shifted to the final position */
+ __u32 secret[12];
} ____cacheline_aligned ip_keydata[2];
static unsigned int ip_cnt;
@@ -2253,10 +2168,10 @@ static DECLARE_WORK(rekey_work, rekey_seq_generator, NULL);
*/
static void rekey_seq_generator(void *private_)
{
- struct keydata *keyptr = &ip_keydata[1^(ip_cnt&1)];
+ struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)];
get_random_bytes(keyptr->secret, sizeof(keyptr->secret));
- keyptr->count = (ip_cnt&COUNT_MASK)<<HASH_BITS;
+ keyptr->count = (ip_cnt & COUNT_MASK) << HASH_BITS;
smp_wmb();
ip_cnt++;
schedule_delayed_work(&rekey_work, REKEY_INTERVAL);
@@ -2264,7 +2179,7 @@ static void rekey_seq_generator(void *private_)
static inline struct keydata *get_keyptr(void)
{
- struct keydata *keyptr = &ip_keydata[ip_cnt&1];
+ struct keydata *keyptr = &ip_keydata[ip_cnt & 1];
smp_rmb();
@@ -2282,25 +2197,24 @@ late_initcall(seqgen_init);
__u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
__u16 sport, __u16 dport)
{
- struct timeval tv;
- __u32 seq;
- __u32 hash[12];
+ struct timeval tv;
+ __u32 seq;
+ __u32 hash[12];
struct keydata *keyptr = get_keyptr();
/* The procedure is the same as for IPv4, but addresses are longer.
* Thus we must use twothirdsMD4Transform.
*/
-
memcpy(hash, saddr, 16);
hash[4]=(sport << 16) + dport;
- memcpy(&hash[5],keyptr->secret,sizeof(__u32)*7);
+ memcpy(&hash[5],keyptr->secret,sizeof(__u32) * 7);
seq = twothirdsMD4Transform(daddr, hash) & HASH_MASK;
seq += keyptr->count;
do_gettimeofday(&tv);
- seq += tv.tv_usec + tv.tv_sec*1000000;
+ seq += tv.tv_usec + tv.tv_sec * 1000000;
return seq;
}
@@ -2310,15 +2224,15 @@ EXPORT_SYMBOL(secure_tcpv6_sequence_number);
__u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
__u16 sport, __u16 dport)
{
- struct timeval tv;
- __u32 seq;
- __u32 hash[4];
+ struct timeval tv;
+ __u32 seq;
+ __u32 hash[4];
struct keydata *keyptr = get_keyptr();
/*
* Pick a unique starting offset for each TCP connection endpoints
* (saddr, daddr, sport, dport).
- * Note that the words are placed into the starting vector, which is
+ * Note that the words are placed into the starting vector, which is
* then mixed with a partial MD4 over random data.
*/
hash[0]=saddr;
@@ -2337,7 +2251,7 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
* (Networks are faster now - should this be increased?)
*/
do_gettimeofday(&tv);
- seq += tv.tv_usec + tv.tv_sec*1000000;
+ seq += tv.tv_usec + tv.tv_sec * 1000000;
#if 0
printk("init_seq(%lx, %lx, %d, %d) = %d\n",
saddr, daddr, sport, dport, seq);
@@ -2400,14 +2314,14 @@ u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport)
#define COOKIEBITS 24 /* Upper bits store count */
#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
-static int syncookie_init;
-static __u32 syncookie_secret[2][16-3+HASH_BUFFER_SIZE];
+static int syncookie_init;
+static __u32 syncookie_secret[2][16-3+HASH_BUFFER_SIZE];
__u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
__u16 dport, __u32 sseq, __u32 count, __u32 data)
{
- __u32 tmp[16 + HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];
- __u32 seq;
+ __u32 tmp[16 + HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];
+ __u32 seq;
/*
* Pick two random secrets the first time we need a cookie.
@@ -2428,19 +2342,19 @@ __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
* MSS into the second hash value.
*/
- memcpy(tmp+3, syncookie_secret[0], sizeof(syncookie_secret[0]));
+ memcpy(tmp + 3, syncookie_secret[0], sizeof(syncookie_secret[0]));
tmp[0]=saddr;
tmp[1]=daddr;
tmp[2]=(sport << 16) + dport;
HASH_TRANSFORM(tmp+16, tmp);
seq = tmp[17] + sseq + (count << COOKIEBITS);
- memcpy(tmp+3, syncookie_secret[1], sizeof(syncookie_secret[1]));
+ memcpy(tmp + 3, syncookie_secret[1], sizeof(syncookie_secret[1]));
tmp[0]=saddr;
tmp[1]=daddr;
tmp[2]=(sport << 16) + dport;
tmp[3] = count; /* minute counter */
- HASH_TRANSFORM(tmp+16, tmp);
+ HASH_TRANSFORM(tmp + 16, tmp);
/* Add in the second hash and the data */
return seq + ((tmp[17] + data) & COOKIEMASK);
@@ -2458,22 +2372,22 @@ __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
__u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, __u16 sport,
__u16 dport, __u32 sseq, __u32 count, __u32 maxdiff)
{
- __u32 tmp[16 + HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];
- __u32 diff;
+ __u32 tmp[16 + HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];
+ __u32 diff;
if (syncookie_init == 0)
- return (__u32)-1; /* Well, duh! */
+ return (__u32)-1; /* Well, duh! */
/* Strip away the layers from the cookie */
- memcpy(tmp+3, syncookie_secret[0], sizeof(syncookie_secret[0]));
+ memcpy(tmp + 3, syncookie_secret[0], sizeof(syncookie_secret[0]));
tmp[0]=saddr;
tmp[1]=daddr;
tmp[2]=(sport << 16) + dport;
- HASH_TRANSFORM(tmp+16, tmp);
+ HASH_TRANSFORM(tmp + 16, tmp);
cookie -= tmp[17] + sseq;
/* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
- diff = (count - (cookie >> COOKIEBITS)) & ((__u32)-1 >> COOKIEBITS);
+ diff = (count - (cookie >> COOKIEBITS)) & ((__u32) - 1 >> COOKIEBITS);
if (diff >= maxdiff)
return (__u32)-1;
@@ -2482,7 +2396,7 @@ __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, __u16 sport,
tmp[1] = daddr;
tmp[2] = (sport << 16) + dport;
tmp[3] = count - diff; /* minute counter */
- HASH_TRANSFORM(tmp+16, tmp);
+ HASH_TRANSFORM(tmp + 16, tmp);
return (cookie - tmp[17]) & COOKIEMASK; /* Leaving the data behind */
}
diff --git a/drivers/char/rio/cdproto.h b/drivers/char/rio/cdproto.h
deleted file mode 100644
index d53a03c73f2c..000000000000
--- a/drivers/char/rio/cdproto.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-#ifndef _cirrusprots_h
-#define _cirrusprots_h
-
-#ifdef RTA
-extern void cd1400_reset ( int uart) ;
-extern void cd1400_init ( int uart ) ;
-extern void ccr_wait ( int priority, int port) ;
-extern void cd1400_txstart( int port) ;
-extern void cd1400_rxstart ( int port) ;
-extern void command_acknowledge ( PHB *port_header ) ;
-extern int close_port ( ushort port, PHB *port_header, ushort preemptive, int pseudo) ;
-extern void command_preemptive ( PKT *packet) ;
-extern void rup_service ( void ) ;
-extern ushort GetModemLines(struct PHB *, register short *);
-extern void cd1400_intr (Process *cirrus_p, ushort *RtaType) ;
-extern void cd1400_mdint ( short port) ;
-extern void cd1400_rxint ( short port) ;
-extern void cd1400_rxexcept ( short port) ;
-extern void cd1400_txdata ( short port, PHB *port_header, PKT *packet) ;
-extern void cd1400_fast_clock(void);
-extern void cd1400_map_baud ( ushort host_rate, ushort *prescaler, ushort *divisor) ;
-extern void cd1400_modem ( ushort port, ushort way) ;
-extern void cd1400_txcommand ( short port, PHB *port_header, PKT *packet) ;
-extern void cd1400_txint ( int port) ;
-void Rprintf( char *RIOPrBuf, char *Str, ... );
-#if defined(DCIRRUS)
-void debug_packet(PKT *pkt, int option, char *string, int channel);
-#endif /* defined(DCIRRUS) */
-#endif
-
-#ifdef HOST
-extern void wflush (PHB *);
-extern void command_preemptive (PKT *);
-#endif
-
-#endif /* _cirrusprots_h */
diff --git a/drivers/char/rsf16fmi.h b/drivers/char/rsf16fmi.h
deleted file mode 100644
index b71e35bdd73d..000000000000
--- a/drivers/char/rsf16fmi.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SF16FMI FMRadio include file.
- * (c) 1998 Petr Vandrovec
- *
- * Not in include/linux/ because there's no need for anyone
- * to know about these details, I reckon.
- */
-
-#ifndef __RSF16FMI_H
-#define __RSF16FMI_H
-
-int radiosf16fmi_init(void);
-
-#endif /* __RSF16FMI_H */
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index 0c265fe6713a..791b1fc1f4a0 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -33,7 +33,7 @@ extern void poke_blanked_console(void);
/* Variables for selection control. */
/* Use a dynamic buffer, instead of static (Dec 1994) */
- int sel_cons; /* must not be disallocated */
+struct vc_data *sel_cons; /* must not be disallocated */
static volatile int sel_start = -1; /* cleared by clear_selection */
static int sel_end;
static int sel_buffer_lth;
@@ -44,20 +44,22 @@ static char *sel_buffer;
/* set reverse video on characters s-e of console with selection. */
inline static void
-highlight(const int s, const int e) {
+highlight(const int s, const int e)
+{
invert_screen(sel_cons, s, e-s+2, 1);
}
/* use complementary color to show the pointer */
inline static void
-highlight_pointer(const int where) {
+highlight_pointer(const int where)
+{
complement_pos(sel_cons, where);
}
static unsigned char
sel_pos(int n)
{
- return inverse_translate(vc_cons[sel_cons].d, screen_glyph(sel_cons, n));
+ return inverse_translate(sel_cons, screen_glyph(sel_cons, n));
}
/* remove the current selection highlight, if any,
@@ -111,10 +113,10 @@ static inline unsigned short limit(const unsigned short v, const unsigned short
/* set the current selection. Invoked by ioctl() or by kernel code. */
int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
{
+ struct vc_data *vc = vc_cons[fg_console].d;
int sel_mode, new_sel_start, new_sel_end, spc;
char *bp, *obp;
int i, ps, pe;
- unsigned int currcons = fg_console;
poke_blanked_console();
@@ -128,12 +130,12 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
__get_user(ye, &sel->ye);
__get_user(sel_mode, &sel->sel_mode);
xs--; ys--; xe--; ye--;
- xs = limit(xs, video_num_columns - 1);
- ys = limit(ys, video_num_lines - 1);
- xe = limit(xe, video_num_columns - 1);
- ye = limit(ye, video_num_lines - 1);
- ps = ys * video_size_row + (xs << 1);
- pe = ye * video_size_row + (xe << 1);
+ xs = limit(xs, vc->vc_cols - 1);
+ ys = limit(ys, vc->vc_rows - 1);
+ xe = limit(xe, vc->vc_cols - 1);
+ ye = limit(ye, vc->vc_rows - 1);
+ ps = ys * vc->vc_size_row + (xs << 1);
+ pe = ye * vc->vc_size_row + (xe << 1);
if (sel_mode == TIOCL_SELCLEAR) {
/* useful for screendump without selection highlights */
@@ -154,9 +156,9 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
pe = tmp;
}
- if (sel_cons != fg_console) {
+ if (sel_cons != vc_cons[fg_console].d) {
clear_selection();
- sel_cons = fg_console;
+ sel_cons = vc_cons[fg_console].d;
}
switch (sel_mode)
@@ -173,7 +175,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
(!spc && !inword(sel_pos(ps))))
break;
new_sel_start = ps;
- if (!(ps % video_size_row))
+ if (!(ps % vc->vc_size_row))
break;
}
spc = isspace(sel_pos(pe));
@@ -183,14 +185,14 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
(!spc && !inword(sel_pos(pe))))
break;
new_sel_end = pe;
- if (!((pe + 2) % video_size_row))
+ if (!((pe + 2) % vc->vc_size_row))
break;
}
break;
case TIOCL_SELLINE: /* line-by-line selection */
- new_sel_start = ps - ps % video_size_row;
- new_sel_end = pe + video_size_row
- - pe % video_size_row - 2;
+ new_sel_start = ps - ps % vc->vc_size_row;
+ new_sel_end = pe + vc->vc_size_row
+ - pe % vc->vc_size_row - 2;
break;
case TIOCL_SELPOINTER:
highlight_pointer(pe);
@@ -204,11 +206,11 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
/* select to end of line if on trailing space */
if (new_sel_end > new_sel_start &&
- !atedge(new_sel_end, video_size_row) &&
+ !atedge(new_sel_end, vc->vc_size_row) &&
isspace(sel_pos(new_sel_end))) {
for (pe = new_sel_end + 2; ; pe += 2)
if (!isspace(sel_pos(pe)) ||
- atedge(pe, video_size_row))
+ atedge(pe, vc->vc_size_row))
break;
if (isspace(sel_pos(pe)))
new_sel_end = pe;
@@ -255,7 +257,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
*bp = sel_pos(i);
if (!isspace(*bp++))
obp = bp;
- if (! ((i + 2) % video_size_row)) {
+ if (! ((i + 2) % vc->vc_size_row)) {
/* strip trailing blanks from line and add newline,
unless non-space at end of line. */
if (obp != bp) {
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index a23342724582..37c8bea8e2b0 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -53,7 +53,6 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
#if defined(__i386__)
# define BREAKPOINT() asm(" int $3");
#else
@@ -118,7 +117,7 @@
#define RCLRVALUE 0xffff
-MGSL_PARAMS default_params = {
+static MGSL_PARAMS default_params = {
MGSL_MODE_HDLC, /* unsigned long mode */
0, /* unsigned char loopback; */
HDLC_FLAG_UNDERRUN_ABORT15, /* unsigned short flags; */
@@ -679,13 +678,13 @@ void usc_ClearIrqPendingBits( struct mgsl_struct *info, u16 IrqMask );
#define usc_EnableReceiver(a,b) \
usc_OutReg( (a), RMR, (u16)((usc_InReg((a),RMR) & 0xfffc) | (b)) )
-u16 usc_InDmaReg( struct mgsl_struct *info, u16 Port );
-void usc_OutDmaReg( struct mgsl_struct *info, u16 Port, u16 Value );
-void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd );
+static u16 usc_InDmaReg( struct mgsl_struct *info, u16 Port );
+static void usc_OutDmaReg( struct mgsl_struct *info, u16 Port, u16 Value );
+static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd );
-u16 usc_InReg( struct mgsl_struct *info, u16 Port );
-void usc_OutReg( struct mgsl_struct *info, u16 Port, u16 Value );
-void usc_RTCmd( struct mgsl_struct *info, u16 Cmd );
+static u16 usc_InReg( struct mgsl_struct *info, u16 Port );
+static void usc_OutReg( struct mgsl_struct *info, u16 Port, u16 Value );
+static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd );
void usc_RCmd( struct mgsl_struct *info, u16 Cmd );
void usc_TCmd( struct mgsl_struct *info, u16 Cmd );
@@ -694,40 +693,39 @@ void usc_TCmd( struct mgsl_struct *info, u16 Cmd );
#define usc_SetTransmitSyncChars(a,s0,s1) usc_OutReg((a), TSR, (u16)(((u16)s0<<8)|(u16)s1))
-void usc_process_rxoverrun_sync( struct mgsl_struct *info );
-void usc_start_receiver( struct mgsl_struct *info );
-void usc_stop_receiver( struct mgsl_struct *info );
+static void usc_process_rxoverrun_sync( struct mgsl_struct *info );
+static void usc_start_receiver( struct mgsl_struct *info );
+static void usc_stop_receiver( struct mgsl_struct *info );
-void usc_start_transmitter( struct mgsl_struct *info );
-void usc_stop_transmitter( struct mgsl_struct *info );
-void usc_set_txidle( struct mgsl_struct *info );
-void usc_load_txfifo( struct mgsl_struct *info );
+static void usc_start_transmitter( struct mgsl_struct *info );
+static void usc_stop_transmitter( struct mgsl_struct *info );
+static void usc_set_txidle( struct mgsl_struct *info );
+static void usc_load_txfifo( struct mgsl_struct *info );
-void usc_enable_aux_clock( struct mgsl_struct *info, u32 DataRate );
-void usc_enable_loopback( struct mgsl_struct *info, int enable );
+static void usc_enable_aux_clock( struct mgsl_struct *info, u32 DataRate );
+static void usc_enable_loopback( struct mgsl_struct *info, int enable );
-void usc_get_serial_signals( struct mgsl_struct *info );
-void usc_set_serial_signals( struct mgsl_struct *info );
+static void usc_get_serial_signals( struct mgsl_struct *info );
+static void usc_set_serial_signals( struct mgsl_struct *info );
-void usc_reset( struct mgsl_struct *info );
+static void usc_reset( struct mgsl_struct *info );
-void usc_set_sync_mode( struct mgsl_struct *info );
-void usc_set_sdlc_mode( struct mgsl_struct *info );
-void usc_set_async_mode( struct mgsl_struct *info );
-void usc_enable_async_clock( struct mgsl_struct *info, u32 DataRate );
+static void usc_set_sync_mode( struct mgsl_struct *info );
+static void usc_set_sdlc_mode( struct mgsl_struct *info );
+static void usc_set_async_mode( struct mgsl_struct *info );
+static void usc_enable_async_clock( struct mgsl_struct *info, u32 DataRate );
-void usc_loopback_frame( struct mgsl_struct *info );
+static void usc_loopback_frame( struct mgsl_struct *info );
-void mgsl_tx_timeout(unsigned long context);
+static void mgsl_tx_timeout(unsigned long context);
-void usc_loopmode_cancel_transmit( struct mgsl_struct * info );
-void usc_loopmode_insert_request( struct mgsl_struct * info );
-int usc_loopmode_active( struct mgsl_struct * info);
-void usc_loopmode_send_done( struct mgsl_struct * info );
-int usc_loopmode_send_active( struct mgsl_struct * info );
+static void usc_loopmode_cancel_transmit( struct mgsl_struct * info );
+static void usc_loopmode_insert_request( struct mgsl_struct * info );
+static int usc_loopmode_active( struct mgsl_struct * info);
+static void usc_loopmode_send_done( struct mgsl_struct * info );
-int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg);
+static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg);
#ifdef CONFIG_HDLC
#define dev_to_port(D) (dev_to_hdlc(D)->priv)
@@ -753,77 +751,77 @@ static void hdlcdev_exit(struct mgsl_struct *info);
((Nrdd) << 11) + \
((Nrad) << 6) )
-void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit);
+static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit);
/*
* Adapter diagnostic routines
*/
-BOOLEAN mgsl_register_test( struct mgsl_struct *info );
-BOOLEAN mgsl_irq_test( struct mgsl_struct *info );
-BOOLEAN mgsl_dma_test( struct mgsl_struct *info );
-BOOLEAN mgsl_memory_test( struct mgsl_struct *info );
-int mgsl_adapter_test( struct mgsl_struct *info );
+static BOOLEAN mgsl_register_test( struct mgsl_struct *info );
+static BOOLEAN mgsl_irq_test( struct mgsl_struct *info );
+static BOOLEAN mgsl_dma_test( struct mgsl_struct *info );
+static BOOLEAN mgsl_memory_test( struct mgsl_struct *info );
+static int mgsl_adapter_test( struct mgsl_struct *info );
/*
* device and resource management routines
*/
-int mgsl_claim_resources(struct mgsl_struct *info);
-void mgsl_release_resources(struct mgsl_struct *info);
-void mgsl_add_device(struct mgsl_struct *info);
-struct mgsl_struct* mgsl_allocate_device(void);
+static int mgsl_claim_resources(struct mgsl_struct *info);
+static void mgsl_release_resources(struct mgsl_struct *info);
+static void mgsl_add_device(struct mgsl_struct *info);
+static struct mgsl_struct* mgsl_allocate_device(void);
/*
* DMA buffer manupulation functions.
*/
-void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex );
-int mgsl_get_rx_frame( struct mgsl_struct *info );
-int mgsl_get_raw_rx_frame( struct mgsl_struct *info );
-void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info );
-void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info );
-int num_free_tx_dma_buffers(struct mgsl_struct *info);
-void mgsl_load_tx_dma_buffer( struct mgsl_struct *info, const char *Buffer, unsigned int BufferSize);
-void mgsl_load_pci_memory(char* TargetPtr, const char* SourcePtr, unsigned short count);
+static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex );
+static int mgsl_get_rx_frame( struct mgsl_struct *info );
+static int mgsl_get_raw_rx_frame( struct mgsl_struct *info );
+static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info );
+static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info );
+static int num_free_tx_dma_buffers(struct mgsl_struct *info);
+static void mgsl_load_tx_dma_buffer( struct mgsl_struct *info, const char *Buffer, unsigned int BufferSize);
+static void mgsl_load_pci_memory(char* TargetPtr, const char* SourcePtr, unsigned short count);
/*
* DMA and Shared Memory buffer allocation and formatting
*/
-int mgsl_allocate_dma_buffers(struct mgsl_struct *info);
-void mgsl_free_dma_buffers(struct mgsl_struct *info);
-int mgsl_alloc_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
-void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
-int mgsl_alloc_buffer_list_memory(struct mgsl_struct *info);
-void mgsl_free_buffer_list_memory(struct mgsl_struct *info);
-int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info);
-void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info);
-int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info);
-void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info);
-int load_next_tx_holding_buffer(struct mgsl_struct *info);
-int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize);
+static int mgsl_allocate_dma_buffers(struct mgsl_struct *info);
+static void mgsl_free_dma_buffers(struct mgsl_struct *info);
+static int mgsl_alloc_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
+static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
+static int mgsl_alloc_buffer_list_memory(struct mgsl_struct *info);
+static void mgsl_free_buffer_list_memory(struct mgsl_struct *info);
+static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info);
+static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info);
+static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info);
+static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info);
+static int load_next_tx_holding_buffer(struct mgsl_struct *info);
+static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize);
/*
* Bottom half interrupt handlers
*/
-void mgsl_bh_handler(void* Context);
-void mgsl_bh_receive(struct mgsl_struct *info);
-void mgsl_bh_transmit(struct mgsl_struct *info);
-void mgsl_bh_status(struct mgsl_struct *info);
+static void mgsl_bh_handler(void* Context);
+static void mgsl_bh_receive(struct mgsl_struct *info);
+static void mgsl_bh_transmit(struct mgsl_struct *info);
+static void mgsl_bh_status(struct mgsl_struct *info);
/*
* Interrupt handler routines and dispatch table.
*/
-void mgsl_isr_null( struct mgsl_struct *info );
-void mgsl_isr_transmit_data( struct mgsl_struct *info );
-void mgsl_isr_receive_data( struct mgsl_struct *info );
-void mgsl_isr_receive_status( struct mgsl_struct *info );
-void mgsl_isr_transmit_status( struct mgsl_struct *info );
-void mgsl_isr_io_pin( struct mgsl_struct *info );
-void mgsl_isr_misc( struct mgsl_struct *info );
-void mgsl_isr_receive_dma( struct mgsl_struct *info );
-void mgsl_isr_transmit_dma( struct mgsl_struct *info );
+static void mgsl_isr_null( struct mgsl_struct *info );
+static void mgsl_isr_transmit_data( struct mgsl_struct *info );
+static void mgsl_isr_receive_data( struct mgsl_struct *info );
+static void mgsl_isr_receive_status( struct mgsl_struct *info );
+static void mgsl_isr_transmit_status( struct mgsl_struct *info );
+static void mgsl_isr_io_pin( struct mgsl_struct *info );
+static void mgsl_isr_misc( struct mgsl_struct *info );
+static void mgsl_isr_receive_dma( struct mgsl_struct *info );
+static void mgsl_isr_transmit_dma( struct mgsl_struct *info );
typedef void (*isr_dispatch_func)(struct mgsl_struct *);
-isr_dispatch_func UscIsrTable[7] =
+static isr_dispatch_func UscIsrTable[7] =
{
mgsl_isr_null,
mgsl_isr_misc,
@@ -858,7 +856,7 @@ static int pci_registered;
/*
* Global linked list of SyncLink devices
*/
-struct mgsl_struct *mgsl_device_list;
+static struct mgsl_struct *mgsl_device_list;
static int mgsl_device_count;
/*
@@ -935,7 +933,7 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout);
* (gdb) to get the .text address for the add-symbol-file command.
* This allows remote debugging of dynamically loadable modules.
*/
-void* mgsl_get_text_ptr(void)
+static void* mgsl_get_text_ptr(void)
{
return mgsl_get_text_ptr;
}
@@ -1052,7 +1050,7 @@ static void mgsl_start(struct tty_struct *tty)
/* mgsl_bh_action() Return next bottom half action to perform.
* Return Value: BH action code or 0 if nothing to do.
*/
-int mgsl_bh_action(struct mgsl_struct *info)
+static int mgsl_bh_action(struct mgsl_struct *info)
{
unsigned long flags;
int rc = 0;
@@ -1084,7 +1082,7 @@ int mgsl_bh_action(struct mgsl_struct *info)
/*
* Perform bottom half processing of work items queued by ISR.
*/
-void mgsl_bh_handler(void* Context)
+static void mgsl_bh_handler(void* Context)
{
struct mgsl_struct *info = (struct mgsl_struct*)Context;
int action;
@@ -1128,7 +1126,7 @@ void mgsl_bh_handler(void* Context)
__FILE__,__LINE__,info->device_name);
}
-void mgsl_bh_receive(struct mgsl_struct *info)
+static void mgsl_bh_receive(struct mgsl_struct *info)
{
int (*get_rx_frame)(struct mgsl_struct *info) =
(info->params.mode == MGSL_MODE_HDLC ? mgsl_get_rx_frame : mgsl_get_raw_rx_frame);
@@ -1149,7 +1147,7 @@ void mgsl_bh_receive(struct mgsl_struct *info)
} while(get_rx_frame(info));
}
-void mgsl_bh_transmit(struct mgsl_struct *info)
+static void mgsl_bh_transmit(struct mgsl_struct *info)
{
struct tty_struct *tty = info->tty;
unsigned long flags;
@@ -1172,7 +1170,7 @@ void mgsl_bh_transmit(struct mgsl_struct *info)
spin_unlock_irqrestore(&info->irq_spinlock,flags);
}
-void mgsl_bh_status(struct mgsl_struct *info)
+static void mgsl_bh_status(struct mgsl_struct *info)
{
if ( debug_level >= DEBUG_LEVEL_BH )
printk( "%s(%d):mgsl_bh_status() entry on %s\n",
@@ -1193,7 +1191,7 @@ void mgsl_bh_status(struct mgsl_struct *info)
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_receive_status( struct mgsl_struct *info )
+static void mgsl_isr_receive_status( struct mgsl_struct *info )
{
u16 status = usc_InReg( info, RCSR );
@@ -1245,7 +1243,7 @@ void mgsl_isr_receive_status( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_transmit_status( struct mgsl_struct *info )
+static void mgsl_isr_transmit_status( struct mgsl_struct *info )
{
u16 status = usc_InReg( info, TCSR );
@@ -1312,7 +1310,7 @@ void mgsl_isr_transmit_status( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_io_pin( struct mgsl_struct *info )
+static void mgsl_isr_io_pin( struct mgsl_struct *info )
{
struct mgsl_icount *icount;
u16 status = usc_InReg( info, MISR );
@@ -1430,7 +1428,7 @@ void mgsl_isr_io_pin( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_transmit_data( struct mgsl_struct *info )
+static void mgsl_isr_transmit_data( struct mgsl_struct *info )
{
if ( debug_level >= DEBUG_LEVEL_ISR )
printk("%s(%d):mgsl_isr_transmit_data xmit_cnt=%d\n",
@@ -1462,7 +1460,7 @@ void mgsl_isr_transmit_data( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_receive_data( struct mgsl_struct *info )
+static void mgsl_isr_receive_data( struct mgsl_struct *info )
{
int Fifocount;
u16 status;
@@ -1574,7 +1572,7 @@ void mgsl_isr_receive_data( struct mgsl_struct *info )
* Arguments: info pointer to device extension (instance data)
* Return Value: None
*/
-void mgsl_isr_misc( struct mgsl_struct *info )
+static void mgsl_isr_misc( struct mgsl_struct *info )
{
u16 status = usc_InReg( info, MISR );
@@ -1610,7 +1608,7 @@ void mgsl_isr_misc( struct mgsl_struct *info )
* Arguments: info pointer to device extension (instance data)
* Return Value: None
*/
-void mgsl_isr_null( struct mgsl_struct *info )
+static void mgsl_isr_null( struct mgsl_struct *info )
{
} /* end of mgsl_isr_null() */
@@ -1634,7 +1632,7 @@ void mgsl_isr_null( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_receive_dma( struct mgsl_struct *info )
+static void mgsl_isr_receive_dma( struct mgsl_struct *info )
{
u16 status;
@@ -1678,7 +1676,7 @@ void mgsl_isr_receive_dma( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_transmit_dma( struct mgsl_struct *info )
+static void mgsl_isr_transmit_dma( struct mgsl_struct *info )
{
u16 status;
@@ -2990,7 +2988,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
return mgsl_ioctl_common(info, cmd, arg);
}
-int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
+static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
{
int error;
struct mgsl_icount cnow; /* kernel counter temps */
@@ -3649,7 +3647,7 @@ static inline int line_info(char *buf, struct mgsl_struct *info)
*
* Return Value:
*/
-int mgsl_read_proc(char *page, char **start, off_t off, int count,
+static int mgsl_read_proc(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
int len = 0, l;
@@ -3688,7 +3686,7 @@ done:
* Arguments: info pointer to device instance data
* Return Value: 0 if success, otherwise error
*/
-int mgsl_allocate_dma_buffers(struct mgsl_struct *info)
+static int mgsl_allocate_dma_buffers(struct mgsl_struct *info)
{
unsigned short BuffersPerFrame;
@@ -3795,7 +3793,7 @@ int mgsl_allocate_dma_buffers(struct mgsl_struct *info)
* Arguments: info pointer to device instance data
* Return Value: 0 if success, otherwise error
*/
-int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info )
+static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info )
{
unsigned int i;
@@ -3880,7 +3878,7 @@ int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info )
* the buffer list contains the information necessary to free
* the individual buffers!
*/
-void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
+static void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
{
if ( info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI )
kfree(info->buffer_list);
@@ -3907,7 +3905,7 @@ void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
*
* Return Value: 0 if success, otherwise -ENOMEM
*/
-int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount)
+static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount)
{
int i;
unsigned long phys_addr;
@@ -3949,7 +3947,7 @@ int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,
*
* Return Value: None
*/
-void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList, int Buffercount)
+static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList, int Buffercount)
{
int i;
@@ -3972,7 +3970,7 @@ void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_free_dma_buffers( struct mgsl_struct *info )
+static void mgsl_free_dma_buffers( struct mgsl_struct *info )
{
mgsl_free_frame_memory( info, info->rx_buffer_list, info->rx_buffer_count );
mgsl_free_frame_memory( info, info->tx_buffer_list, info->tx_buffer_count );
@@ -3993,7 +3991,7 @@ void mgsl_free_dma_buffers( struct mgsl_struct *info )
*
* Return Value: 0 if success, otherwise -ENOMEM
*/
-int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info)
+static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info)
{
info->intermediate_rxbuffer = kmalloc(info->max_frame_size, GFP_KERNEL | GFP_DMA);
if ( info->intermediate_rxbuffer == NULL )
@@ -4013,7 +4011,7 @@ int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info)
*
* Return Value: None
*/
-void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info)
+static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info)
{
if ( info->intermediate_rxbuffer )
kfree(info->intermediate_rxbuffer);
@@ -4035,7 +4033,7 @@ void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info)
*
* Return Value: 0 if success, otherwise -ENOMEM
*/
-int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info)
+static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info)
{
int i;
@@ -4066,7 +4064,7 @@ int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info)
*
* Return Value: None
*/
-void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info)
+static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info)
{
int i;
@@ -4098,7 +4096,7 @@ void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info)
* into adapter's tx dma buffer,
* 0 otherwise
*/
-int load_next_tx_holding_buffer(struct mgsl_struct *info)
+static int load_next_tx_holding_buffer(struct mgsl_struct *info)
{
int ret = 0;
@@ -4144,7 +4142,7 @@ int load_next_tx_holding_buffer(struct mgsl_struct *info)
*
* Return Value: 1 if able to store, 0 otherwise
*/
-int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize)
+static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize)
{
struct tx_holding_buffer *ptx;
@@ -4163,7 +4161,7 @@ int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned
return 1;
}
-int mgsl_claim_resources(struct mgsl_struct *info)
+static int mgsl_claim_resources(struct mgsl_struct *info)
{
if (request_region(info->io_base,info->io_addr_size,"synclink") == NULL) {
printk( "%s(%d):I/O address conflict on device %s Addr=%08X\n",
@@ -4243,7 +4241,7 @@ errout:
} /* end of mgsl_claim_resources() */
-void mgsl_release_resources(struct mgsl_struct *info)
+static void mgsl_release_resources(struct mgsl_struct *info)
{
if ( debug_level >= DEBUG_LEVEL_INFO )
printk( "%s(%d):mgsl_release_resources(%s) entry\n",
@@ -4297,7 +4295,7 @@ void mgsl_release_resources(struct mgsl_struct *info)
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_add_device( struct mgsl_struct *info )
+static void mgsl_add_device( struct mgsl_struct *info )
{
info->next_device = NULL;
info->line = mgsl_device_count;
@@ -4363,7 +4361,7 @@ void mgsl_add_device( struct mgsl_struct *info )
* Arguments: none
* Return Value: pointer to mgsl_struct if success, otherwise NULL
*/
-struct mgsl_struct* mgsl_allocate_device(void)
+static struct mgsl_struct* mgsl_allocate_device(void)
{
struct mgsl_struct *info;
@@ -4582,7 +4580,7 @@ module_exit(synclink_exit);
*
* None
*/
-void usc_RTCmd( struct mgsl_struct *info, u16 Cmd )
+static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd )
{
/* output command to CCAR in bits <15..11> */
/* preserve bits <10..7>, bits <6..0> must be zero */
@@ -4609,7 +4607,7 @@ void usc_RTCmd( struct mgsl_struct *info, u16 Cmd )
*
* None
*/
-void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd )
+static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd )
{
/* write command mask to DCAR */
outw( Cmd + info->mbre_bit, info->io_base );
@@ -4636,7 +4634,7 @@ void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd )
* None
*
*/
-void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
+static void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
{
/* Note: The DCAR is located at the adapter base address */
/* Note: must preserve state of BIT8 in DCAR */
@@ -4665,7 +4663,7 @@ void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
* The 16-bit value read from register
*
*/
-u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr )
+static u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr )
{
/* Note: The DCAR is located at the adapter base address */
/* Note: must preserve state of BIT8 in DCAR */
@@ -4692,7 +4690,7 @@ u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr )
* None
*
*/
-void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
+static void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
{
outw( RegAddr + info->loopback_bits, info->io_base + CCAR );
outw( RegValue, info->io_base + CCAR );
@@ -4717,7 +4715,7 @@ void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
*
* 16-bit value read from register
*/
-u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr )
+static u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr )
{
outw( RegAddr + info->loopback_bits, info->io_base + CCAR );
return inw( info->io_base + CCAR );
@@ -4731,7 +4729,7 @@ u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr )
* Arguments: info pointer to device instance data
* Return Value: NONE
*/
-void usc_set_sdlc_mode( struct mgsl_struct *info )
+static void usc_set_sdlc_mode( struct mgsl_struct *info )
{
u16 RegValue;
int PreSL1660;
@@ -5311,7 +5309,7 @@ void usc_set_sdlc_mode( struct mgsl_struct *info )
* enable 1 = enable loopback, 0 = disable
* Return Value: None
*/
-void usc_enable_loopback(struct mgsl_struct *info, int enable)
+static void usc_enable_loopback(struct mgsl_struct *info, int enable)
{
if (enable) {
/* blank external TXD output */
@@ -5375,7 +5373,7 @@ void usc_enable_loopback(struct mgsl_struct *info, int enable)
*
* Return Value: None
*/
-void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate )
+static void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate )
{
u32 XtalSpeed;
u16 Tc;
@@ -5432,7 +5430,7 @@ void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate )
*
* Return Value: None
*/
-void usc_process_rxoverrun_sync( struct mgsl_struct *info )
+static void usc_process_rxoverrun_sync( struct mgsl_struct *info )
{
int start_index;
int end_index;
@@ -5571,7 +5569,7 @@ void usc_process_rxoverrun_sync( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_stop_receiver( struct mgsl_struct *info )
+static void usc_stop_receiver( struct mgsl_struct *info )
{
if (debug_level >= DEBUG_LEVEL_ISR)
printk("%s(%d):usc_stop_receiver(%s)\n",
@@ -5604,7 +5602,7 @@ void usc_stop_receiver( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_start_receiver( struct mgsl_struct *info )
+static void usc_start_receiver( struct mgsl_struct *info )
{
u32 phys_addr;
@@ -5668,7 +5666,7 @@ void usc_start_receiver( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_start_transmitter( struct mgsl_struct *info )
+static void usc_start_transmitter( struct mgsl_struct *info )
{
u32 phys_addr;
unsigned int FrameSize;
@@ -5774,7 +5772,7 @@ void usc_start_transmitter( struct mgsl_struct *info )
* Arguments: info pointer to device isntance data
* Return Value: None
*/
-void usc_stop_transmitter( struct mgsl_struct *info )
+static void usc_stop_transmitter( struct mgsl_struct *info )
{
if (debug_level >= DEBUG_LEVEL_ISR)
printk("%s(%d):usc_stop_transmitter(%s)\n",
@@ -5803,7 +5801,7 @@ void usc_stop_transmitter( struct mgsl_struct *info )
* Arguments: info pointer to device extension (instance data)
* Return Value: None
*/
-void usc_load_txfifo( struct mgsl_struct *info )
+static void usc_load_txfifo( struct mgsl_struct *info )
{
int Fifocount;
u8 TwoBytes[2];
@@ -5860,7 +5858,7 @@ void usc_load_txfifo( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_reset( struct mgsl_struct *info )
+static void usc_reset( struct mgsl_struct *info )
{
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
int i;
@@ -5974,7 +5972,7 @@ void usc_reset( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_set_async_mode( struct mgsl_struct *info )
+static void usc_set_async_mode( struct mgsl_struct *info )
{
u16 RegValue;
@@ -6167,7 +6165,7 @@ void usc_set_async_mode( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_loopback_frame( struct mgsl_struct *info )
+static void usc_loopback_frame( struct mgsl_struct *info )
{
int i;
unsigned long oldmode = info->params.mode;
@@ -6235,7 +6233,7 @@ void usc_loopback_frame( struct mgsl_struct *info )
* Arguments: info pointer to adapter info structure
* Return Value: None
*/
-void usc_set_sync_mode( struct mgsl_struct *info )
+static void usc_set_sync_mode( struct mgsl_struct *info )
{
usc_loopback_frame( info );
usc_set_sdlc_mode( info );
@@ -6258,7 +6256,7 @@ void usc_set_sync_mode( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_set_txidle( struct mgsl_struct *info )
+static void usc_set_txidle( struct mgsl_struct *info )
{
u16 usc_idle_mode = IDLEMODE_FLAGS;
@@ -6321,7 +6319,7 @@ void usc_set_txidle( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_get_serial_signals( struct mgsl_struct *info )
+static void usc_get_serial_signals( struct mgsl_struct *info )
{
u16 status;
@@ -6357,7 +6355,7 @@ void usc_get_serial_signals( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_set_serial_signals( struct mgsl_struct *info )
+static void usc_set_serial_signals( struct mgsl_struct *info )
{
u16 Control;
unsigned char V24Out = info->serial_signals;
@@ -6389,7 +6387,7 @@ void usc_set_serial_signals( struct mgsl_struct *info )
* 0 disables the AUX clock.
* Return Value: None
*/
-void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate )
+static void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate )
{
if ( data_rate ) {
/*
@@ -6499,7 +6497,7 @@ void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info )
+static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info )
{
unsigned int i;
@@ -6525,7 +6523,7 @@ void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: number of free tx dma buffers
*/
-int num_free_tx_dma_buffers(struct mgsl_struct *info)
+static int num_free_tx_dma_buffers(struct mgsl_struct *info)
{
return info->tx_buffer_count - info->tx_dma_buffers_used;
}
@@ -6540,7 +6538,7 @@ int num_free_tx_dma_buffers(struct mgsl_struct *info)
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info )
+static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info )
{
unsigned int i;
@@ -6568,7 +6566,7 @@ void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info )
*
* Return Value: None
*/
-void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex )
+static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex )
{
int Done = 0;
DMABUFFERENTRY *pBufEntry;
@@ -6611,7 +6609,7 @@ void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartInd
* Arguments: info pointer to device extension
* Return Value: 1 if frame returned, otherwise 0
*/
-int mgsl_get_rx_frame(struct mgsl_struct *info)
+static int mgsl_get_rx_frame(struct mgsl_struct *info)
{
unsigned int StartIndex, EndIndex; /* index of 1st and last buffers of Rx frame */
unsigned short status;
@@ -6810,7 +6808,7 @@ Cleanup:
* Arguments: info pointer to device extension
* Return Value: 1 if frame returned, otherwise 0
*/
-int mgsl_get_raw_rx_frame(struct mgsl_struct *info)
+static int mgsl_get_raw_rx_frame(struct mgsl_struct *info)
{
unsigned int CurrentIndex, NextIndex;
unsigned short status;
@@ -6975,8 +6973,8 @@ int mgsl_get_raw_rx_frame(struct mgsl_struct *info)
*
* Return Value: None
*/
-void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, const char *Buffer,
- unsigned int BufferSize)
+static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info,
+ const char *Buffer, unsigned int BufferSize)
{
unsigned short Copycount;
unsigned int i = 0;
@@ -7052,7 +7050,7 @@ void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, const char *Buffer,
* Arguments: info pointer to device instance data
* Return Value: TRUE if test passed, otherwise FALSE
*/
-BOOLEAN mgsl_register_test( struct mgsl_struct *info )
+static BOOLEAN mgsl_register_test( struct mgsl_struct *info )
{
static unsigned short BitPatterns[] =
{ 0x0000, 0xffff, 0xaaaa, 0x5555, 0x1234, 0x6969, 0x9696, 0x0f0f };
@@ -7108,7 +7106,7 @@ BOOLEAN mgsl_register_test( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: TRUE if test passed, otherwise FALSE
*/
-BOOLEAN mgsl_irq_test( struct mgsl_struct *info )
+static BOOLEAN mgsl_irq_test( struct mgsl_struct *info )
{
unsigned long EndTime;
unsigned long flags;
@@ -7163,7 +7161,7 @@ BOOLEAN mgsl_irq_test( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: TRUE if test passed, otherwise FALSE
*/
-BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
+static BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
{
unsigned short FifoLevel;
unsigned long phys_addr;
@@ -7455,7 +7453,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: 0 if success, otherwise -ENODEV
*/
-int mgsl_adapter_test( struct mgsl_struct *info )
+static int mgsl_adapter_test( struct mgsl_struct *info )
{
if ( debug_level >= DEBUG_LEVEL_INFO )
printk( "%s(%d):Testing device %s\n",
@@ -7497,7 +7495,7 @@ int mgsl_adapter_test( struct mgsl_struct *info )
* Arguments: info pointer to device instance data
* Return Value: TRUE if test passed, otherwise FALSE
*/
-BOOLEAN mgsl_memory_test( struct mgsl_struct *info )
+static BOOLEAN mgsl_memory_test( struct mgsl_struct *info )
{
static unsigned long BitPatterns[] = { 0x0, 0x55555555, 0xaaaaaaaa,
0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
@@ -7578,7 +7576,7 @@ BOOLEAN mgsl_memory_test( struct mgsl_struct *info )
*
* Return Value: None
*/
-void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr,
+static void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr,
unsigned short count )
{
/* 16 32-bit writes @ 60ns each = 960ns max latency on local bus */
@@ -7600,7 +7598,7 @@ void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr,
} /* End Of mgsl_load_pci_memory() */
-void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit)
+static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit)
{
int i;
int linecount;
@@ -7640,7 +7638,7 @@ void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int
* Arguments: context pointer to device instance data
* Return Value: None
*/
-void mgsl_tx_timeout(unsigned long context)
+static void mgsl_tx_timeout(unsigned long context)
{
struct mgsl_struct *info = (struct mgsl_struct*)context;
unsigned long flags;
@@ -7694,7 +7692,7 @@ static int mgsl_loopmode_send_done( struct mgsl_struct * info )
/* release the line by echoing RxD to TxD
* upon completion of a transmit frame
*/
-void usc_loopmode_send_done( struct mgsl_struct * info )
+static void usc_loopmode_send_done( struct mgsl_struct * info )
{
info->loopmode_send_done_requested = FALSE;
/* clear CMR:13 to 0 to start echoing RxData to TxData */
@@ -7704,7 +7702,7 @@ void usc_loopmode_send_done( struct mgsl_struct * info )
/* abort a transmit in progress while in HDLC LoopMode
*/
-void usc_loopmode_cancel_transmit( struct mgsl_struct * info )
+static void usc_loopmode_cancel_transmit( struct mgsl_struct * info )
{
/* reset tx dma channel and purge TxFifo */
usc_RTCmd( info, RTCmd_PurgeTxFifo );
@@ -7716,7 +7714,7 @@ void usc_loopmode_cancel_transmit( struct mgsl_struct * info )
* is an Insert Into Loop action. Upon receipt of a GoAhead sequence (RxAbort)
* we must clear CMR:13 to begin repeating TxData to RxData
*/
-void usc_loopmode_insert_request( struct mgsl_struct * info )
+static void usc_loopmode_insert_request( struct mgsl_struct * info )
{
info->loopmode_insert_requested = TRUE;
@@ -7733,18 +7731,11 @@ void usc_loopmode_insert_request( struct mgsl_struct * info )
/* return 1 if station is inserted into the loop, otherwise 0
*/
-int usc_loopmode_active( struct mgsl_struct * info)
+static int usc_loopmode_active( struct mgsl_struct * info)
{
return usc_InReg( info, CCSR ) & BIT7 ? 1 : 0 ;
}
-/* return 1 if USC is in loop send mode, otherwise 0
- */
-int usc_loopmode_send_active( struct mgsl_struct * info )
-{
- return usc_InReg( info, CCSR ) & BIT6 ? 1 : 0 ;
-}
-
#ifdef CONFIG_HDLC
/**
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index 7696ead16862..0c5ba9dc9063 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -488,7 +488,7 @@ static struct parport_driver tipar_driver = {
.detach = tipar_detach,
};
-int __init
+static int __init
tipar_init_module(void)
{
int err = 0;
@@ -525,7 +525,7 @@ out:
return err;
}
-void __exit
+static void __exit
tipar_cleanup_module(void)
{
unsigned int i;
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index baf65901ab41..58e21fe44262 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -407,7 +407,7 @@ static int tosh_get_machine_id(void)
* laptop, otherwise zero and determines the Machine ID, BIOS version and
* date, and SCI version.
*/
-int tosh_probe(void)
+static int tosh_probe(void)
{
int i,major,minor,day,year,month,flag;
unsigned char signature[7] = { 0x54,0x4f,0x53,0x48,0x49,0x42,0x41 };
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index ffc82ee87b37..0edec4f95c30 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -327,7 +327,7 @@ void tty_ldisc_put(int disc)
EXPORT_SYMBOL_GPL(tty_ldisc_put);
-void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
+static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
{
tty->ldisc = *ld;
tty->ldisc.refcount = 0;
@@ -583,7 +583,7 @@ restart:
/*
* This routine returns a tty driver structure, given a device number
*/
-struct tty_driver *get_tty_driver(dev_t device, int *index)
+static struct tty_driver *get_tty_driver(dev_t device, int *index)
{
struct tty_driver *p;
@@ -744,7 +744,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
* but doesn't hold any locks, so we need to make sure we have the appropriate
* locks for what we're doing..
*/
-void do_tty_hangup(void *data)
+static void do_tty_hangup(void *data)
{
struct tty_struct *tty = (struct tty_struct *) data;
struct file * cons_filp = NULL;
@@ -2524,28 +2524,6 @@ out:
}
/*
- * Call the ldisc flush directly from a driver. This function may
- * return an error and need retrying by the user.
- */
-
-int tty_push_data(struct tty_struct *tty, unsigned char *cp, unsigned char *fp, int count)
-{
- int ret = 0;
- struct tty_ldisc *disc;
-
- disc = tty_ldisc_ref(tty);
- if(test_bit(TTY_DONT_FLIP, &tty->flags))
- ret = -EAGAIN;
- else if(disc == NULL)
- ret = -EIO;
- else
- disc->receive_buf(tty, cp, fp, count);
- tty_ldisc_deref(disc);
- return ret;
-
-}
-
-/*
* Routine which returns the baud rate of the tty
*
* Note that the baud_table needs to be kept in sync with the
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 7145057e0a48..58597993954f 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -372,7 +372,7 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
/*
* Send a high priority character to the tty.
*/
-void send_prio_char(struct tty_struct *tty, char ch)
+static void send_prio_char(struct tty_struct *tty, char ch)
{
int was_stopped = tty->stopped;
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index c5c6b5e26850..55971a272ead 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -59,7 +59,7 @@ vcs_size(struct inode *inode)
if (!vc_cons_allocated(currcons))
return -ENXIO;
- size = video_num_lines * video_num_columns;
+ size = vc_cons[currcons].d->vc_rows * vc_cons[currcons].d->vc_cols;
if (minor & 128)
size = 2*size + HEADER_SIZE;
@@ -99,6 +99,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
unsigned int currcons = iminor(inode);
+ struct vc_data *vc;
long pos;
long viewed, attr, read;
int col, maxcol;
@@ -126,6 +127,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
ret = -ENXIO;
if (!vc_cons_allocated(currcons))
goto unlock_out;
+ vc = vc_cons[currcons].d;
ret = -EINVAL;
if (pos < 0)
@@ -159,15 +161,15 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
con_buf_start = con_buf0 = con_buf;
orig_count = this_round;
- maxcol = video_num_columns;
+ maxcol = vc->vc_cols;
if (!attr) {
- org = screen_pos(currcons, p, viewed);
+ org = screen_pos(vc, p, viewed);
col = p % maxcol;
p += maxcol - col;
while (this_round-- > 0) {
- *con_buf0++ = (vcs_scr_readw(currcons, org++) & 0xff);
+ *con_buf0++ = (vcs_scr_readw(vc, org++) & 0xff);
if (++col == maxcol) {
- org = screen_pos(currcons, p, viewed);
+ org = screen_pos(vc, p, viewed);
col = 0;
p += maxcol;
}
@@ -176,9 +178,9 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
if (p < HEADER_SIZE) {
size_t tmp_count;
- con_buf0[0] = (char) video_num_lines;
- con_buf0[1] = (char) video_num_columns;
- getconsxy(currcons, con_buf0 + 2);
+ con_buf0[0] = (char)vc->vc_rows;
+ con_buf0[1] = (char)vc->vc_cols;
+ getconsxy(vc, con_buf0 + 2);
con_buf_start += p;
this_round += p;
@@ -214,7 +216,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
p /= 2;
col = p % maxcol;
- org = screen_pos(currcons, p, viewed);
+ org = screen_pos(vc, p, viewed);
p += maxcol - col;
/* Buffer has even length, so we can always copy
@@ -224,10 +226,10 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
this_round = (this_round + 1) >> 1;
while (this_round) {
- *tmp_buf++ = vcs_scr_readw(currcons, org++);
+ *tmp_buf++ = vcs_scr_readw(vc, org++);
this_round --;
if (++col == maxcol) {
- org = screen_pos(currcons, p, viewed);
+ org = screen_pos(vc, p, viewed);
col = 0;
p += maxcol;
}
@@ -270,6 +272,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
unsigned int currcons = iminor(inode);
+ struct vc_data *vc;
long pos;
long viewed, attr, size, written;
char *con_buf0;
@@ -299,6 +302,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
ret = -ENXIO;
if (!vc_cons_allocated(currcons))
goto unlock_out;
+ vc = vc_cons[currcons].d;
size = vcs_size(inode);
ret = -EINVAL;
@@ -351,10 +355,10 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
con_buf0 = con_buf;
orig_count = this_round;
- maxcol = video_num_columns;
+ maxcol = vc->vc_cols;
p = pos;
if (!attr) {
- org0 = org = screen_pos(currcons, p, viewed);
+ org0 = org = screen_pos(vc, p, viewed);
col = p % maxcol;
p += maxcol - col;
@@ -362,11 +366,11 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
unsigned char c = *con_buf0++;
this_round--;
- vcs_scr_writew(currcons,
- (vcs_scr_readw(currcons, org) & 0xff00) | c, org);
+ vcs_scr_writew(vc,
+ (vcs_scr_readw(vc, org) & 0xff00) | c, org);
org++;
if (++col == maxcol) {
- org = screen_pos(currcons, p, viewed);
+ org = screen_pos(vc, p, viewed);
col = 0;
p += maxcol;
}
@@ -375,34 +379,34 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
if (p < HEADER_SIZE) {
char header[HEADER_SIZE];
- getconsxy(currcons, header + 2);
+ getconsxy(vc, header + 2);
while (p < HEADER_SIZE && this_round > 0) {
this_round--;
header[p++] = *con_buf0++;
}
if (!viewed)
- putconsxy(currcons, header + 2);
+ putconsxy(vc, header + 2);
}
p -= HEADER_SIZE;
col = (p/2) % maxcol;
if (this_round > 0) {
- org0 = org = screen_pos(currcons, p/2, viewed);
+ org0 = org = screen_pos(vc, p/2, viewed);
if ((p & 1) && this_round > 0) {
char c;
this_round--;
c = *con_buf0++;
#ifdef __BIG_ENDIAN
- vcs_scr_writew(currcons, c |
- (vcs_scr_readw(currcons, org) & 0xff00), org);
+ vcs_scr_writew(vc, c |
+ (vcs_scr_readw(vc, org) & 0xff00), org);
#else
- vcs_scr_writew(currcons, (c << 8) |
- (vcs_scr_readw(currcons, org) & 0xff), org);
+ vcs_scr_writew(vc, (c << 8) |
+ (vcs_scr_readw(vc, org) & 0xff), org);
#endif
org++;
p++;
if (++col == maxcol) {
- org = screen_pos(currcons, p/2, viewed);
+ org = screen_pos(vc, p/2, viewed);
col = 0;
}
}
@@ -413,11 +417,11 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
unsigned short w;
w = get_unaligned(((const unsigned short *)con_buf0));
- vcs_scr_writew(currcons, w, org++);
+ vcs_scr_writew(vc, w, org++);
con_buf0 += 2;
this_round -= 2;
if (++col == maxcol) {
- org = screen_pos(currcons, p, viewed);
+ org = screen_pos(vc, p, viewed);
col = 0;
p += maxcol;
}
@@ -427,9 +431,9 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
c = *con_buf0++;
#ifdef __BIG_ENDIAN
- vcs_scr_writew(currcons, (vcs_scr_readw(currcons, org) & 0xff) | (c << 8), org);
+ vcs_scr_writew(vc, (vcs_scr_readw(vc, org) & 0xff) | (c << 8), org);
#else
- vcs_scr_writew(currcons, (vcs_scr_readw(currcons, org) & 0xff00) | c, org);
+ vcs_scr_writew(vc, (vcs_scr_readw(vc, org) & 0xff00) | c, org);
#endif
}
}
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 7ef949fbceb5..261599fd095a 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -40,15 +40,6 @@
* - Arno Griffioen <arno@usn.nl>
* - David Carter <carter@cs.bris.ac.uk>
*
- * Note that the abstract console driver allows all consoles to be of
- * potentially different sizes, so the following variables depend on the
- * current console (currcons):
- *
- * - video_num_columns
- * - video_num_lines
- * - video_size_row
- * - can_do_color
- *
* The abstract console driver provides a generic interface for a text
* console. It supports VGA text mode, frame buffer based graphical consoles
* and special graphics processors that are only accessible through some
@@ -146,13 +137,13 @@ static const struct consw *con_driver_map[MAX_NR_CONSOLES];
static int con_open(struct tty_struct *, struct file *);
static void vc_init(unsigned int console, unsigned int rows,
unsigned int cols, int do_clear);
-static void gotoxy(int currcons, int new_x, int new_y);
+static void gotoxy(struct vc_data *vc, int new_x, int new_y);
static void save_cur(int currcons);
static void reset_terminal(int currcons, int do_clear);
static void con_flush_chars(struct tty_struct *tty);
static void set_vesa_blanking(char __user *p);
-static void set_cursor(int currcons);
-static void hide_cursor(int currcons);
+static void set_cursor(struct vc_data *vc);
+static void hide_cursor(struct vc_data *vc);
static void console_callback(void *ignored);
static void blank_screen_t(unsigned long dummy);
@@ -223,28 +214,32 @@ enum {
* Low-Level Functions
*/
-#define IS_FG (currcons == fg_console)
+#define IS_FG (currcons == fg_console)
+#define IS_FG_VC(vc) (vc == vc_cons[fg_console].d)
+
#define IS_VISIBLE CON_IS_VISIBLE(vc_cons[currcons].d)
#ifdef VT_BUF_VRAM_ONLY
-#define DO_UPDATE 0
+#define DO_UPDATE 0
+#define DO_UPDATE_VC(vc) 0
#else
-#define DO_UPDATE IS_VISIBLE
+#define DO_UPDATE IS_VISIBLE
+#define DO_UPDATE_VC(vc) CON_IS_VISIBLE(vc)
#endif
static int pm_con_request(struct pm_dev *dev, pm_request_t rqst, void *data);
static struct pm_dev *pm_con;
-static inline unsigned short *screenpos(int currcons, int offset, int viewed)
+static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed)
{
unsigned short *p;
if (!viewed)
- p = (unsigned short *)(origin + offset);
- else if (!sw->con_screen_pos)
- p = (unsigned short *)(visible_origin + offset);
+ p = (unsigned short *)(vc->vc_origin + offset);
+ else if (!vc->vc_sw->con_screen_pos)
+ p = (unsigned short *)(vc->vc_visible_origin + offset);
else
- p = sw->con_screen_pos(vc_cons[currcons].d, offset);
+ p = vc->vc_sw->con_screen_pos(vc, offset);
return p;
}
@@ -265,14 +260,15 @@ static void scrup(int currcons, unsigned int t, unsigned int b, int nr)
if (t+nr >= b)
nr = b - t - 1;
- if (b > video_num_lines || t >= b || nr < 1)
+ if (b > vc_cons[currcons].d->vc_rows || t >= b || nr < 1)
return;
if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr))
return;
- d = (unsigned short *) (origin+video_size_row*t);
- s = (unsigned short *) (origin+video_size_row*(t+nr));
- scr_memmovew(d, s, (b-t-nr) * video_size_row);
- scr_memsetw(d + (b-t-nr) * video_num_columns, video_erase_char, video_size_row*nr);
+ d = (unsigned short *) (origin+vc_cons[currcons].d->vc_size_row*t);
+ s = (unsigned short *) (origin+vc_cons[currcons].d->vc_size_row*(t+nr));
+ scr_memmovew(d, s, (b-t-nr) * vc_cons[currcons].d->vc_size_row);
+ scr_memsetw(d + (b-t-nr) * vc_cons[currcons].d->vc_cols, video_erase_char,
+ vc_cons[currcons].d->vc_size_row * nr);
}
static void
@@ -283,40 +279,40 @@ scrdown(int currcons, unsigned int t, unsigned int b, int nr)
if (t+nr >= b)
nr = b - t - 1;
- if (b > video_num_lines || t >= b || nr < 1)
+ if (b > vc_cons[currcons].d->vc_rows || t >= b || nr < 1)
return;
if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr))
return;
- s = (unsigned short *) (origin+video_size_row*t);
- step = video_num_columns * nr;
- scr_memmovew(s + step, s, (b-t-nr)*video_size_row);
+ s = (unsigned short *) (origin+vc_cons[currcons].d->vc_size_row*t);
+ step = vc_cons[currcons].d->vc_cols * nr;
+ scr_memmovew(s + step, s, (b-t-nr)*vc_cons[currcons].d->vc_size_row);
scr_memsetw(s, video_erase_char, 2*step);
}
-static void do_update_region(int currcons, unsigned long start, int count)
+static void do_update_region(struct vc_data *vc, unsigned long start, int count)
{
#ifndef VT_BUF_VRAM_ONLY
unsigned int xx, yy, offset;
u16 *p;
p = (u16 *) start;
- if (!sw->con_getxy) {
- offset = (start - origin) / 2;
- xx = offset % video_num_columns;
- yy = offset / video_num_columns;
+ if (!vc->vc_sw->con_getxy) {
+ offset = (start - vc->vc_origin) / 2;
+ xx = offset % vc->vc_cols;
+ yy = offset / vc->vc_cols;
} else {
int nxx, nyy;
- start = sw->con_getxy(vc_cons[currcons].d, start, &nxx, &nyy);
+ start = vc->vc_sw->con_getxy(vc, start, &nxx, &nyy);
xx = nxx; yy = nyy;
}
for(;;) {
u16 attrib = scr_readw(p) & 0xff00;
int startx = xx;
u16 *q = p;
- while (xx < video_num_columns && count) {
+ while (xx < vc->vc_cols && count) {
if (attrib != (scr_readw(p) & 0xff00)) {
if (p > q)
- sw->con_putcs(vc_cons[currcons].d, q, p-q, yy, startx);
+ vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
startx = xx;
q = p;
attrib = scr_readw(p) & 0xff00;
@@ -326,14 +322,14 @@ static void do_update_region(int currcons, unsigned long start, int count)
count--;
}
if (p > q)
- sw->con_putcs(vc_cons[currcons].d, q, p-q, yy, startx);
+ vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
if (!count)
break;
xx = 0;
yy++;
- if (sw->con_getxy) {
+ if (vc->vc_sw->con_getxy) {
p = (u16 *)start;
- start = sw->con_getxy(vc_cons[currcons].d, start, NULL, NULL);
+ start = vc->vc_sw->con_getxy(vc, start, NULL, NULL);
}
}
#endif
@@ -344,9 +340,9 @@ void update_region(int currcons, unsigned long start, int count)
WARN_CONSOLE_UNLOCKED();
if (DO_UPDATE) {
- hide_cursor(currcons);
- do_update_region(currcons, start, count);
- set_cursor(currcons);
+ hide_cursor(vc_cons[currcons].d);
+ do_update_region(vc_cons[currcons].d, start, count);
+ set_cursor(vc_cons[currcons].d);
}
}
@@ -370,7 +366,7 @@ static u8 build_attr(int currcons, u8 _color, u8 _intensity, u8 _blink, u8 _unde
*/
{
u8 a = color;
- if (!can_do_color)
+ if (!vc_cons[currcons].d->vc_can_do_color)
return _intensity |
(_underline ? 4 : 0) |
(_reverse ? 8 : 0) |
@@ -401,31 +397,30 @@ static void update_attr(int currcons)
}
/* Note: inverting the screen twice should revert to the original state */
-
-void invert_screen(int currcons, int offset, int count, int viewed)
+void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
{
unsigned short *p;
WARN_CONSOLE_UNLOCKED();
count /= 2;
- p = screenpos(currcons, offset, viewed);
- if (sw->con_invert_region)
- sw->con_invert_region(vc_cons[currcons].d, p, count);
+ p = screenpos(vc, offset, viewed);
+ if (vc->vc_sw->con_invert_region)
+ vc->vc_sw->con_invert_region(vc, p, count);
#ifndef VT_BUF_VRAM_ONLY
else {
u16 *q = p;
int cnt = count;
u16 a;
- if (!can_do_color) {
+ if (!vc->vc_can_do_color) {
while (cnt--) {
a = scr_readw(q);
a ^= 0x0800;
scr_writew(a, q);
q++;
}
- } else if (hi_font_mask == 0x100) {
+ } else if (vc->vc_hi_font_mask == 0x100) {
while (cnt--) {
a = scr_readw(q);
a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4);
@@ -442,12 +437,12 @@ void invert_screen(int currcons, int offset, int count, int viewed)
}
}
#endif
- if (DO_UPDATE)
- do_update_region(currcons, (unsigned long) p, count);
+ if (DO_UPDATE_VC(vc))
+ do_update_region(vc, (unsigned long) p, count);
}
/* used by selection: complement pointer position */
-void complement_pos(int currcons, int offset)
+void complement_pos(struct vc_data *vc, int offset)
{
static unsigned short *p;
static unsigned short old;
@@ -457,21 +452,21 @@ void complement_pos(int currcons, int offset)
if (p) {
scr_writew(old, p);
- if (DO_UPDATE)
- sw->con_putc(vc_cons[currcons].d, old, oldy, oldx);
+ if (DO_UPDATE_VC(vc))
+ vc->vc_sw->con_putc(vc, old, oldy, oldx);
}
if (offset == -1)
p = NULL;
else {
unsigned short new;
- p = screenpos(currcons, offset, 1);
+ p = screenpos(vc, offset, 1);
old = scr_readw(p);
- new = old ^ complement_mask;
+ new = old ^ vc->vc_complement_mask;
scr_writew(new, p);
- if (DO_UPDATE) {
- oldx = (offset >> 1) % video_num_columns;
- oldy = (offset >> 1) / video_num_columns;
- sw->con_putc(vc_cons[currcons].d, new, oldy, oldx);
+ if (DO_UPDATE_VC(vc)) {
+ oldx = (offset >> 1) % vc->vc_cols;
+ oldy = (offset >> 1) / vc->vc_cols;
+ vc->vc_sw->con_putc(vc, new, oldy, oldx);
}
}
}
@@ -480,7 +475,7 @@ static void insert_char(int currcons, unsigned int nr)
{
unsigned short *p, *q = (unsigned short *) pos;
- p = q + video_num_columns - nr - x;
+ p = q + vc_cons[currcons].d->vc_cols - nr - x;
while (--p >= q)
scr_writew(scr_readw(p), p + nr);
scr_memsetw(q, video_erase_char, nr*2);
@@ -488,7 +483,7 @@ static void insert_char(int currcons, unsigned int nr)
if (DO_UPDATE) {
unsigned short oldattr = attr;
sw->con_bmove(vc_cons[currcons].d,y,x,y,x+nr,1,
- video_num_columns-x-nr);
+ vc_cons[currcons].d->vc_cols-x-nr);
attr = video_erase_char >> 8;
while (nr--)
sw->con_putc(vc_cons[currcons].d,
@@ -502,7 +497,7 @@ static void delete_char(int currcons, unsigned int nr)
unsigned int i = x;
unsigned short *p = (unsigned short *) pos;
- while (++i <= video_num_columns - nr) {
+ while (++i <= vc_cons[currcons].d->vc_cols - nr) {
scr_writew(scr_readw(p+nr), p);
p++;
}
@@ -511,22 +506,22 @@ static void delete_char(int currcons, unsigned int nr)
if (DO_UPDATE) {
unsigned short oldattr = attr;
sw->con_bmove(vc_cons[currcons].d, y, x+nr, y, x, 1,
- video_num_columns-x-nr);
+ vc_cons[currcons].d->vc_cols-x-nr);
attr = video_erase_char >> 8;
while (nr--)
sw->con_putc(vc_cons[currcons].d,
video_erase_char, y,
- video_num_columns-1-nr);
+ vc_cons[currcons].d->vc_cols-1-nr);
attr = oldattr;
}
}
static int softcursor_original;
-static void add_softcursor(int currcons)
+static void add_softcursor(struct vc_data *vc)
{
- int i = scr_readw((u16 *) pos);
- u32 type = cursor_type;
+ int i = scr_readw((u16 *) vc->vc_pos);
+ u32 type = vc->vc_cursor_type;
if (! (type & 0x10)) return;
if (softcursor_original != -1) return;
@@ -535,41 +530,43 @@ static void add_softcursor(int currcons)
i ^= ((type) & 0xff00 );
if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;
if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;
- scr_writew(i, (u16 *) pos);
- if (DO_UPDATE)
- sw->con_putc(vc_cons[currcons].d, i, y, x);
+ scr_writew(i, (u16 *) vc->vc_pos);
+ if (DO_UPDATE_VC(vc))
+ vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x);
}
-static void hide_softcursor(int currcons)
+static void hide_softcursor(struct vc_data *vc)
{
if (softcursor_original != -1) {
- scr_writew(softcursor_original,(u16 *) pos);
- if (DO_UPDATE)
- sw->con_putc(vc_cons[currcons].d, softcursor_original, y, x);
+ scr_writew(softcursor_original, (u16 *)vc->vc_pos);
+ if (DO_UPDATE_VC(vc))
+ vc->vc_sw->con_putc(vc, softcursor_original,
+ vc->vc_y, vc->vc_x);
softcursor_original = -1;
}
}
-static void hide_cursor(int currcons)
+static void hide_cursor(struct vc_data *vc)
{
- if (currcons == sel_cons)
+ if (vc == sel_cons)
clear_selection();
- sw->con_cursor(vc_cons[currcons].d,CM_ERASE);
- hide_softcursor(currcons);
+ vc->vc_sw->con_cursor(vc, CM_ERASE);
+ hide_softcursor(vc);
}
-static void set_cursor(int currcons)
+static void set_cursor(struct vc_data *vc)
{
- if (!IS_FG || console_blanked || vcmode == KD_GRAPHICS)
- return;
- if (deccm) {
- if (currcons == sel_cons)
- clear_selection();
- add_softcursor(currcons);
- if ((cursor_type & 0x0f) != 1)
- sw->con_cursor(vc_cons[currcons].d,CM_DRAW);
- } else
- hide_cursor(currcons);
+ if (!IS_FG_VC(vc) || console_blanked ||
+ vc->vc_vt->vc_mode == KD_GRAPHICS)
+ return;
+ if (vc->vc_deccm) {
+ if (vc == sel_cons)
+ clear_selection();
+ add_softcursor(vc);
+ if ((vc->vc_cursor_type & 0x0f) != 1)
+ vc->vc_sw->con_cursor(vc, CM_DRAW);
+ } else
+ hide_cursor(vc);
}
static void set_origin(int currcons)
@@ -582,7 +579,7 @@ static void set_origin(int currcons)
origin = (unsigned long) screenbuf;
visible_origin = origin;
scr_end = origin + screenbuf_size;
- pos = origin + video_size_row*y + 2*x;
+ pos = origin + vc_cons[currcons].d->vc_size_row*y + 2*x;
}
static inline void save_screen(int currcons)
@@ -623,7 +620,7 @@ void redraw_screen(int new_console, int is_switch)
if (is_switch) {
currcons = fg_console;
- hide_cursor(currcons);
+ hide_cursor(vc_cons[currcons].d);
if (fg_console != new_console) {
struct vc_data **display = vc_cons[new_console].d->vc_display_fg;
old_console = (*display) ? (*display)->vc_num : fg_console;
@@ -640,7 +637,7 @@ void redraw_screen(int new_console, int is_switch)
}
} else {
currcons = new_console;
- hide_cursor(currcons);
+ hide_cursor(vc_cons[currcons].d);
}
if (redraw) {
@@ -661,9 +658,9 @@ void redraw_screen(int new_console, int is_switch)
clear_buffer_attributes(currcons);
}
if (update && vcmode != KD_GRAPHICS)
- do_update_region(currcons, origin, screenbuf_size/2);
+ do_update_region(vc_cons[currcons].d, origin, screenbuf_size/2);
}
- set_cursor(currcons);
+ set_cursor(vc_cons[currcons].d);
if (is_switch) {
set_leds();
compute_shiftstate();
@@ -696,13 +693,14 @@ static void visual_init(int currcons, int init)
vc_cons[currcons].d->vc_uni_pagedir = 0;
hi_font_mask = 0;
complement_mask = 0;
- can_do_color = 0;
+ vc_cons[currcons].d->vc_can_do_color = 0;
sw->con_init(vc_cons[currcons].d, init);
if (!complement_mask)
- complement_mask = can_do_color ? 0x7700 : 0x0800;
+ complement_mask =
+ vc_cons[currcons].d->vc_can_do_color ? 0x7700 : 0x0800;
s_complement_mask = complement_mask;
- video_size_row = video_num_columns<<1;
- screenbuf_size = video_num_lines*video_size_row;
+ vc_cons[currcons].d->vc_size_row = vc_cons[currcons].d->vc_cols<<1;
+ screenbuf_size = vc_cons[currcons].d->vc_rows * vc_cons[currcons].d->vc_size_row;
}
int vc_allocate(unsigned int currcons) /* return 0 on success */
@@ -730,6 +728,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
memset((void *)p, 0, structsize);
vc_cons[currcons].d = (struct vc_data *)p;
vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data));
+ vc_cons[currcons].d->vc_vt = vt_cons[currcons];
visual_init(currcons, 1);
if (!*vc_cons[currcons].d->vc_uni_pagedir_loc)
con_set_default_unimap(currcons);
@@ -742,7 +741,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
}
screenbuf = (unsigned short *) q;
kmalloced = 1;
- vc_init(currcons, video_num_lines, video_num_columns, 1);
+ vc_init(currcons, vc_cons[currcons].d->vc_rows, vc_cons[currcons].d->vc_cols, 1);
if (!pm_con) {
pm_con = pm_register(PM_SYS_DEV,
@@ -785,21 +784,21 @@ int vc_resize(int currcons, unsigned int cols, unsigned int lines)
if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW)
return -EINVAL;
- new_cols = (cols ? cols : video_num_columns);
- new_rows = (lines ? lines : video_num_lines);
+ new_cols = (cols ? cols : vc_cons[currcons].d->vc_cols);
+ new_rows = (lines ? lines : vc_cons[currcons].d->vc_rows);
new_row_size = new_cols << 1;
new_screen_size = new_row_size * new_rows;
- if (new_cols == video_num_columns && new_rows == video_num_lines)
+ if (new_cols == vc_cons[currcons].d->vc_cols && new_rows == vc_cons[currcons].d->vc_rows)
return 0;
newscreen = (unsigned short *) kmalloc(new_screen_size, GFP_USER);
if (!newscreen)
return -ENOMEM;
- old_rows = video_num_lines;
- old_cols = video_num_columns;
- old_row_size = video_size_row;
+ old_rows = vc_cons[currcons].d->vc_rows;
+ old_cols = vc_cons[currcons].d->vc_cols;
+ old_row_size = vc_cons[currcons].d->vc_size_row;
old_screen_size = screenbuf_size;
err = resize_screen(currcons, new_cols, new_rows);
@@ -808,9 +807,9 @@ int vc_resize(int currcons, unsigned int cols, unsigned int lines)
return err;
}
- video_num_lines = new_rows;
- video_num_columns = new_cols;
- video_size_row = new_row_size;
+ vc_cons[currcons].d->vc_rows = new_rows;
+ vc_cons[currcons].d->vc_cols = new_cols;
+ vc_cons[currcons].d->vc_size_row = new_row_size;
screenbuf_size = new_screen_size;
rlth = min(old_row_size, new_row_size);
@@ -841,16 +840,16 @@ int vc_resize(int currcons, unsigned int cols, unsigned int lines)
/* do part of a reset_terminal() */
top = 0;
- bottom = video_num_lines;
- gotoxy(currcons, x, y);
+ bottom = vc_cons[currcons].d->vc_rows;
+ gotoxy(vc_cons[currcons].d, x, y);
save_cur(currcons);
if (vc_cons[currcons].d->vc_tty) {
struct winsize ws, *cws = &vc_cons[currcons].d->vc_tty->winsize;
memset(&ws, 0, sizeof(ws));
- ws.ws_row = video_num_lines;
- ws.ws_col = video_num_columns;
+ ws.ws_row = vc_cons[currcons].d->vc_rows;
+ ws.ws_col = vc_cons[currcons].d->vc_cols;
ws.ws_ypixel = video_scan_lines;
if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
vc_cons[currcons].d->vc_tty->pgrp > 0)
@@ -913,38 +912,40 @@ int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
* might also be negative. If the given position is out of
* bounds, the cursor is placed at the nearest margin.
*/
-static void gotoxy(int currcons, int new_x, int new_y)
+static void gotoxy(struct vc_data *vc, int new_x, int new_y)
{
int min_y, max_y;
if (new_x < 0)
- x = 0;
- else
- if (new_x >= video_num_columns)
- x = video_num_columns - 1;
+ vc->vc_x = 0;
+ else {
+ if (new_x >= vc->vc_cols)
+ vc->vc_x = vc->vc_cols - 1;
else
- x = new_x;
- if (decom) {
- min_y = top;
- max_y = bottom;
+ vc->vc_x = new_x;
+ }
+
+ if (vc->vc_decom) {
+ min_y = vc->vc_top;
+ max_y = vc->vc_bottom;
} else {
min_y = 0;
- max_y = video_num_lines;
+ max_y = vc->vc_rows;
}
if (new_y < min_y)
- y = min_y;
+ vc->vc_y = min_y;
else if (new_y >= max_y)
- y = max_y - 1;
+ vc->vc_y = max_y - 1;
else
- y = new_y;
- pos = origin + y*video_size_row + (x<<1);
- need_wrap = 0;
+ vc->vc_y = new_y;
+ vc->vc_pos = vc->vc_origin + vc->vc_y * vc->vc_size_row + (vc->vc_x<<1);
+ vc->vc_need_wrap = 0;
}
/* for absolute user moves, when decom is set */
static void gotoxay(int currcons, int new_x, int new_y)
{
- gotoxy(currcons, new_x, decom ? (top+new_y) : new_y);
+ gotoxy(vc_cons[currcons].d, new_x, decom ? (top+new_y) : new_y);
}
void scrollback(int lines)
@@ -952,7 +953,7 @@ void scrollback(int lines)
int currcons = fg_console;
if (!lines)
- lines = video_num_lines/2;
+ lines = vc_cons[currcons].d->vc_rows/2;
scrolldelta(-lines);
}
@@ -961,7 +962,7 @@ void scrollfront(int lines)
int currcons = fg_console;
if (!lines)
- lines = video_num_lines/2;
+ lines = vc_cons[currcons].d->vc_rows/2;
scrolldelta(lines);
}
@@ -972,9 +973,9 @@ static void lf(int currcons)
*/
if (y+1 == bottom)
scrup(currcons,top,bottom,1);
- else if (y < video_num_lines-1) {
+ else if (y < vc_cons[currcons].d->vc_rows-1) {
y++;
- pos += video_size_row;
+ pos += vc_cons[currcons].d->vc_size_row;
}
need_wrap = 0;
}
@@ -988,7 +989,7 @@ static void ri(int currcons)
scrdown(currcons,top,bottom,1);
else if (y > 0) {
y--;
- pos -= video_size_row;
+ pos -= vc_cons[currcons].d->vc_size_row;
}
need_wrap = 0;
}
@@ -1025,10 +1026,10 @@ static void csi_J(int currcons, int vpar)
if (DO_UPDATE) {
/* do in two stages */
sw->con_clear(vc_cons[currcons].d, y, x, 1,
- video_num_columns-x);
+ vc_cons[currcons].d->vc_cols-x);
sw->con_clear(vc_cons[currcons].d, y+1, 0,
- video_num_lines-y-1,
- video_num_columns);
+ vc_cons[currcons].d->vc_rows-y-1,
+ vc_cons[currcons].d->vc_cols);
}
break;
case 1: /* erase from start to cursor */
@@ -1037,18 +1038,18 @@ static void csi_J(int currcons, int vpar)
if (DO_UPDATE) {
/* do in two stages */
sw->con_clear(vc_cons[currcons].d, 0, 0, y,
- video_num_columns);
+ vc_cons[currcons].d->vc_cols);
sw->con_clear(vc_cons[currcons].d, y, 0, 1,
x + 1);
}
break;
case 2: /* erase whole display */
- count = video_num_columns * video_num_lines;
+ count = vc_cons[currcons].d->vc_cols * vc_cons[currcons].d->vc_rows;
start = (unsigned short *) origin;
if (DO_UPDATE)
sw->con_clear(vc_cons[currcons].d, 0, 0,
- video_num_lines,
- video_num_columns);
+ vc_cons[currcons].d->vc_rows,
+ vc_cons[currcons].d->vc_cols);
break;
default:
return;
@@ -1064,11 +1065,11 @@ static void csi_K(int currcons, int vpar)
switch (vpar) {
case 0: /* erase from cursor to end of line */
- count = video_num_columns-x;
+ count = vc_cons[currcons].d->vc_cols-x;
start = (unsigned short *) pos;
if (DO_UPDATE)
sw->con_clear(vc_cons[currcons].d, y, x, 1,
- video_num_columns-x);
+ vc_cons[currcons].d->vc_cols-x);
break;
case 1: /* erase from start of line to cursor */
start = (unsigned short *) (pos - (x<<1));
@@ -1079,10 +1080,10 @@ static void csi_K(int currcons, int vpar)
break;
case 2: /* erase whole line */
start = (unsigned short *) (pos - (x<<1));
- count = video_num_columns;
+ count = vc_cons[currcons].d->vc_cols;
if (DO_UPDATE)
sw->con_clear(vc_cons[currcons].d, y, 0, 1,
- video_num_columns);
+ vc_cons[currcons].d->vc_cols);
break;
default:
return;
@@ -1097,7 +1098,7 @@ static void csi_X(int currcons, int vpar) /* erase the following vpar positions
if (!vpar)
vpar++;
- count = (vpar > video_num_columns-x) ? (video_num_columns-x) : vpar;
+ count = (vpar > vc_cons[currcons].d->vc_cols-x) ? (vc_cons[currcons].d->vc_cols-x) : vpar;
scr_memsetw((unsigned short *) pos, video_erase_char, 2 * count);
if (DO_UPDATE)
@@ -1270,7 +1271,7 @@ static void set_mode(int currcons, int on_off)
case 3: /* 80/132 mode switch unimplemented */
deccolm = on_off;
#if 0
- (void) vc_resize(deccolm ? 132 : 80, video_num_lines);
+ (void) vc_resize(deccolm ? 132 : 80, vc_cons[currcons].d->vc_rows);
/* this alone does not suffice; some user mode
utility has to change the hardware regs */
#endif
@@ -1278,7 +1279,7 @@ static void set_mode(int currcons, int on_off)
case 5: /* Inverted screen on/off */
if (decscnm != on_off) {
decscnm = on_off;
- invert_screen(currcons, 0, screenbuf_size, 0);
+ invert_screen(vc_cons[currcons].d, 0, screenbuf_size, 0);
update_attr(currcons);
}
break;
@@ -1325,14 +1326,16 @@ static void setterm_command(int currcons)
{
switch(par[0]) {
case 1: /* set color for underline mode */
- if (can_do_color && par[1] < 16) {
+ if (vc_cons[currcons].d->vc_can_do_color &&
+ par[1] < 16) {
ulcolor = color_table[par[1]];
if (underline)
update_attr(currcons);
}
break;
case 2: /* set color for half intensity mode */
- if (can_do_color && par[1] < 16) {
+ if (vc_cons[currcons].d->vc_can_do_color &&
+ par[1] < 16) {
halfcolor = color_table[par[1]];
if (intensity == 0)
update_attr(currcons);
@@ -1381,8 +1384,8 @@ static void setterm_command(int currcons)
/* console_sem is held */
static void csi_at(int currcons, unsigned int nr)
{
- if (nr > video_num_columns - x)
- nr = video_num_columns - x;
+ if (nr > vc_cons[currcons].d->vc_cols - x)
+ nr = vc_cons[currcons].d->vc_cols - x;
else if (!nr)
nr = 1;
insert_char(currcons, nr);
@@ -1391,8 +1394,8 @@ static void csi_at(int currcons, unsigned int nr)
/* console_sem is held */
static void csi_L(int currcons, unsigned int nr)
{
- if (nr > video_num_lines - y)
- nr = video_num_lines - y;
+ if (nr > vc_cons[currcons].d->vc_rows - y)
+ nr = vc_cons[currcons].d->vc_rows - y;
else if (!nr)
nr = 1;
scrdown(currcons,y,bottom,nr);
@@ -1402,8 +1405,8 @@ static void csi_L(int currcons, unsigned int nr)
/* console_sem is held */
static void csi_P(int currcons, unsigned int nr)
{
- if (nr > video_num_columns - x)
- nr = video_num_columns - x;
+ if (nr > vc_cons[currcons].d->vc_cols - x)
+ nr = vc_cons[currcons].d->vc_cols - x;
else if (!nr)
nr = 1;
delete_char(currcons, nr);
@@ -1412,8 +1415,8 @@ static void csi_P(int currcons, unsigned int nr)
/* console_sem is held */
static void csi_M(int currcons, unsigned int nr)
{
- if (nr > video_num_lines - y)
- nr = video_num_lines - y;
+ if (nr > vc_cons[currcons].d->vc_rows - y)
+ nr = vc_cons[currcons].d->vc_rows - y;
else if (!nr)
nr=1;
scrup(currcons,y,bottom,nr);
@@ -1438,7 +1441,7 @@ static void save_cur(int currcons)
/* console_sem is held */
static void restore_cur(int currcons)
{
- gotoxy(currcons,saved_x,saved_y);
+ gotoxy(vc_cons[currcons].d,saved_x,saved_y);
intensity = s_intensity;
underline = s_underline;
blink = s_blink;
@@ -1460,7 +1463,7 @@ enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
static void reset_terminal(int currcons, int do_clear)
{
top = 0;
- bottom = video_num_lines;
+ bottom = vc_cons[currcons].d->vc_rows;
vc_state = ESnormal;
ques = 0;
translate = set_translate(LAT1_MAP,currcons);
@@ -1507,7 +1510,7 @@ static void reset_terminal(int currcons, int do_clear)
bell_pitch = DEFAULT_BELL_PITCH;
bell_duration = DEFAULT_BELL_DURATION;
- gotoxy(currcons,0,0);
+ gotoxy(vc_cons[currcons].d, 0, 0);
save_cur(currcons);
if (do_clear)
csi_J(currcons,2);
@@ -1532,7 +1535,7 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
return;
case 9:
pos -= (x << 1);
- while (x < video_num_columns - 1) {
+ while (x < vc_cons[currcons].d->vc_cols - 1) {
x++;
if (tab_stop[x >> 5] & (1 << (x & 31)))
break;
@@ -1719,31 +1722,31 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
switch(c) {
case 'G': case '`':
if (par[0]) par[0]--;
- gotoxy(currcons,par[0],y);
+ gotoxy(vc_cons[currcons].d, par[0], y);
return;
case 'A':
if (!par[0]) par[0]++;
- gotoxy(currcons,x,y-par[0]);
+ gotoxy(vc_cons[currcons].d, x, y-par[0]);
return;
case 'B': case 'e':
if (!par[0]) par[0]++;
- gotoxy(currcons,x,y+par[0]);
+ gotoxy(vc_cons[currcons].d, x, y+par[0]);
return;
case 'C': case 'a':
if (!par[0]) par[0]++;
- gotoxy(currcons,x+par[0],y);
+ gotoxy(vc_cons[currcons].d, x+par[0], y);
return;
case 'D':
if (!par[0]) par[0]++;
- gotoxy(currcons,x-par[0],y);
+ gotoxy(vc_cons[currcons].d, x-par[0], y);
return;
case 'E':
if (!par[0]) par[0]++;
- gotoxy(currcons,0,y+par[0]);
+ gotoxy(vc_cons[currcons].d, 0, y+par[0]);
return;
case 'F':
if (!par[0]) par[0]++;
- gotoxy(currcons,0,y-par[0]);
+ gotoxy(vc_cons[currcons].d, 0, y-par[0]);
return;
case 'd':
if (par[0]) par[0]--;
@@ -1797,10 +1800,10 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
if (!par[0])
par[0]++;
if (!par[1])
- par[1] = video_num_lines;
+ par[1] = vc_cons[currcons].d->vc_rows;
/* Minimum allowed region is 2 lines */
if (par[0] < par[1] &&
- par[1] <= video_num_lines) {
+ par[1] <= vc_cons[currcons].d->vc_rows) {
top=par[0]-1;
bottom=par[1];
gotoxay(currcons,0,0);
@@ -1847,7 +1850,7 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
csi_J(currcons, 2);
video_erase_char =
(video_erase_char & 0xff00) | ' ';
- do_update_region(currcons, origin, screenbuf_size/2);
+ do_update_region(vc_cons[currcons].d, origin, screenbuf_size/2);
}
return;
case ESsetG0:
@@ -1963,7 +1966,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
/* undraw cursor first */
if (IS_FG)
- hide_cursor(currcons);
+ hide_cursor(vc_cons[currcons].d);
while (!tty->stopped && count) {
int orig = *buf;
@@ -2065,7 +2068,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
draw_x = x;
draw_from = pos;
}
- if (x == video_num_columns - 1) {
+ if (x == vc_cons[currcons].d->vc_cols - 1) {
need_wrap = decawm;
draw_to = pos+2;
} else {
@@ -2102,7 +2105,7 @@ static void console_callback(void *ignored)
if (want_console >= 0) {
if (want_console != fg_console &&
vc_cons_allocated(want_console)) {
- hide_cursor(fg_console);
+ hide_cursor(vc_cons[fg_console].d);
change_console(want_console);
/* we only changed when the console had already
been allocated - a new console is not created
@@ -2176,7 +2179,7 @@ void vt_console_print(struct console *co, const char *b, unsigned count)
/* undraw cursor first */
if (IS_FG)
- hide_cursor(currcons);
+ hide_cursor(vc_cons[currcons].d);
start = (ushort *)pos;
@@ -2209,7 +2212,7 @@ void vt_console_print(struct console *co, const char *b, unsigned count)
}
scr_writew((attr << 8) + c, (unsigned short *) pos);
cnt++;
- if (myx == video_num_columns - 1) {
+ if (myx == vc_cons[currcons].d->vc_cols - 1) {
need_wrap = 1;
continue;
}
@@ -2220,12 +2223,12 @@ void vt_console_print(struct console *co, const char *b, unsigned count)
if (IS_VISIBLE)
sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
x += cnt;
- if (x == video_num_columns) {
+ if (x == vc_cons[currcons].d->vc_cols) {
x--;
need_wrap = 1;
}
}
- set_cursor(currcons);
+ set_cursor(vc_cons[currcons].d);
if (!oops_in_progress)
poke_blanked_console();
@@ -2438,7 +2441,7 @@ static void con_flush_chars(struct tty_struct *tty)
acquire_console_sem();
vt = tty->driver_data;
if (vt)
- set_cursor(vt->vc_num);
+ set_cursor(vc_cons[vt->vc_num].d);
release_console_sem();
}
@@ -2459,8 +2462,8 @@ static int con_open(struct tty_struct *tty, struct file *filp)
vc_cons[currcons].d->vc_tty = tty;
if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
- tty->winsize.ws_row = video_num_lines;
- tty->winsize.ws_col = video_num_columns;
+ tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
+ tty->winsize.ws_col = vc_cons[currcons].d->vc_cols;
}
release_console_sem();
vcs_make_devfs(tty);
@@ -2507,10 +2510,10 @@ static void vc_init(unsigned int currcons, unsigned int rows,
{
int j, k ;
- video_num_columns = cols;
- video_num_lines = rows;
- video_size_row = cols<<1;
- screenbuf_size = video_num_lines * video_size_row;
+ vc_cons[currcons].d->vc_cols = cols;
+ vc_cons[currcons].d->vc_rows = rows;
+ vc_cons[currcons].d->vc_size_row = cols<<1;
+ screenbuf_size = vc_cons[currcons].d->vc_rows * vc_cons[currcons].d->vc_size_row;
set_origin(currcons);
pos = origin;
@@ -2563,22 +2566,23 @@ static int __init con_init(void)
alloc_bootmem(sizeof(struct vc_data));
vt_cons[currcons] = (struct vt_struct *)
alloc_bootmem(sizeof(struct vt_struct));
+ vc_cons[currcons].d->vc_vt = vt_cons[currcons];
visual_init(currcons, 1);
screenbuf = (unsigned short *) alloc_bootmem(screenbuf_size);
kmalloced = 0;
- vc_init(currcons, video_num_lines, video_num_columns,
+ vc_init(currcons, vc_cons[currcons].d->vc_rows, vc_cons[currcons].d->vc_cols,
currcons || !sw->con_save_screen);
}
currcons = fg_console = 0;
master_display_fg = vc_cons[currcons].d;
set_origin(currcons);
save_screen(currcons);
- gotoxy(currcons,x,y);
+ gotoxy(vc_cons[currcons].d, x, y);
csi_J(currcons, 0);
update_screen(fg_console);
printk("Console: %s %s %dx%d",
- can_do_color ? "colour" : "mono",
- display_desc, video_num_columns, video_num_lines);
+ vc_cons[currcons].d->vc_can_do_color ? "colour" : "mono",
+ display_desc, vc_cons[currcons].d->vc_cols, vc_cons[currcons].d->vc_rows);
printable = 1;
printk("\n");
@@ -2690,7 +2694,7 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt)
origin = (unsigned long) screenbuf;
visible_origin = origin;
scr_end = origin + screenbuf_size;
- pos = origin + video_size_row*y + 2*x;
+ pos = origin + vc_cons[currcons].d->vc_size_row*y + 2*x;
visual_init(i, 0);
update_attr(i);
@@ -2788,7 +2792,7 @@ void do_blank_screen(int entering_gfx)
/* entering graphics mode? */
if (entering_gfx) {
- hide_cursor(currcons);
+ hide_cursor(vc_cons[currcons].d);
save_screen(currcons);
sw->con_blank(vc_cons[currcons].d, -1, 1);
console_blanked = fg_console + 1;
@@ -2802,7 +2806,7 @@ void do_blank_screen(int entering_gfx)
return;
}
- hide_cursor(currcons);
+ hide_cursor(vc_cons[currcons].d);
del_timer_sync(&console_timer);
blank_timer_expired = 0;
@@ -2859,7 +2863,7 @@ void do_unblank_screen(int leaving_gfx)
if (console_blank_hook)
console_blank_hook(0);
set_palette(currcons);
- set_cursor(fg_console);
+ set_cursor(vc_cons[fg_console].d);
}
EXPORT_SYMBOL(do_unblank_screen);
@@ -3185,47 +3189,47 @@ int con_font_op(int currcons, struct console_font_op *op)
*/
/* used by selection */
-u16 screen_glyph(int currcons, int offset)
+u16 screen_glyph(struct vc_data *vc, int offset)
{
- u16 w = scr_readw(screenpos(currcons, offset, 1));
+ u16 w = scr_readw(screenpos(vc, offset, 1));
u16 c = w & 0xff;
- if (w & hi_font_mask)
+ if (w & vc->vc_hi_font_mask)
c |= 0x100;
return c;
}
/* used by vcs - note the word offset */
-unsigned short *screen_pos(int currcons, int w_offset, int viewed)
+unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed)
{
- return screenpos(currcons, 2 * w_offset, viewed);
+ return screenpos(vc, 2 * w_offset, viewed);
}
-void getconsxy(int currcons, unsigned char *p)
+void getconsxy(struct vc_data *vc, unsigned char *p)
{
- p[0] = x;
- p[1] = y;
+ p[0] = vc->vc_x;
+ p[1] = vc->vc_y;
}
-void putconsxy(int currcons, unsigned char *p)
+void putconsxy(struct vc_data *vc, unsigned char *p)
{
- gotoxy(currcons, p[0], p[1]);
- set_cursor(currcons);
+ gotoxy(vc, p[0], p[1]);
+ set_cursor(vc);
}
-u16 vcs_scr_readw(int currcons, const u16 *org)
+u16 vcs_scr_readw(struct vc_data *vc, const u16 *org)
{
- if ((unsigned long)org == pos && softcursor_original != -1)
+ if ((unsigned long)org == vc->vc_pos && softcursor_original != -1)
return softcursor_original;
return scr_readw(org);
}
-void vcs_scr_writew(int currcons, u16 val, u16 *org)
+void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org)
{
scr_writew(val, org);
- if ((unsigned long)org == pos) {
+ if ((unsigned long)org == vc->vc_pos) {
softcursor_original = -1;
- add_softcursor(currcons);
+ add_softcursor(vc);
}
}
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index dd8e2f7817f5..ad3a5d3d394c 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -37,7 +37,7 @@ char vt_dont_switch;
extern struct tty_driver *console_driver;
#define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count)
-#define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
+#define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons)
/*
* Console (vt and kd) routines, as defined by USL SVR4 manual, and by
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 912dfca74e15..8778702739cd 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -456,7 +456,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
s = "(reserved error code)";
}
- printk(" %s -- (asc=0x%02x, ascq=0x%02x)\n",
+ printk(KERN_ERR " %s -- (asc=0x%02x, ascq=0x%02x)\n",
s, sense->asc, sense->ascq);
if (failed_command != NULL) {
@@ -478,7 +478,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
lo = mid+1;
}
- printk (" The failed \"%s\" packet command was: \n \"", s);
+ printk (KERN_ERR " The failed \"%s\" packet command was: \n \"", s);
for (i=0; i<sizeof (failed_command->cmd); i++)
printk ("%02x ", failed_command->cmd[i]);
printk ("\"\n");
@@ -491,13 +491,13 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
*/
if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
- printk(" Command is %02d%% complete\n", progress / 0xffff);
+ printk(KERN_ERR " Command is %02d%% complete\n", progress / 0xffff);
}
if (sense->sense_key == ILLEGAL_REQUEST &&
(sense->sks[0] & 0x80) != 0) {
- printk(" Error in %s byte %d",
+ printk(KERN_ERR " Error in %s byte %d",
(sense->sks[0] & 0x40) != 0 ?
"command packet" : "command data",
(sense->sks[1] << 8) + sense->sks[2]);
@@ -519,7 +519,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
sense->asc == 0x3a)))
return;
- printk("%s: error code: 0x%02x sense_key: 0x%02x asc: 0x%02x ascq: 0x%02x\n",
+ printk(KERN_ERR "%s: error code: 0x%02x sense_key: 0x%02x asc: 0x%02x ascq: 0x%02x\n",
drive->name,
sense->error_code, sense->sense_key,
sense->asc, sense->ascq);
@@ -958,7 +958,7 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
return 0;
else if (ireason == 0) {
/* Whoops... The drive is expecting to receive data from us! */
- printk("%s: read_intr: Drive wants to transfer data the "
+ printk(KERN_ERR "%s: read_intr: Drive wants to transfer data the "
"wrong way!\n", drive->name);
/* Throw some data at the drive so it doesn't hang
@@ -976,7 +976,7 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
return 0;
} else {
/* Drive wants a command packet, or invalid ireason... */
- printk("%s: read_intr: bad interrupt reason %x\n", drive->name,
+ printk(KERN_ERR "%s: read_intr: bad interrupt reason %x\n", drive->name,
ireason);
}
@@ -1029,7 +1029,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
/* If we're not done filling the current buffer, complain.
Otherwise, complete the command normally. */
if (rq->current_nr_sectors > 0) {
- printk ("%s: cdrom_read_intr: data underrun (%d blocks)\n",
+ printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n",
drive->name, rq->current_nr_sectors);
rq->flags |= REQ_FAILED;
cdrom_end_request(drive, 0);
@@ -1046,12 +1046,12 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
of at least SECTOR_SIZE, as it gets hairy to keep track
of the transfers otherwise. */
if ((len % SECTOR_SIZE) != 0) {
- printk ("%s: cdrom_read_intr: Bad transfer size %d\n",
+ printk (KERN_ERR "%s: cdrom_read_intr: Bad transfer size %d\n",
drive->name, len);
if (CDROM_CONFIG_FLAGS(drive)->limit_nframes)
- printk (" This drive is not supported by this version of the driver\n");
+ printk (KERN_ERR " This drive is not supported by this version of the driver\n");
else {
- printk (" Trying to limit transfer sizes\n");
+ printk (KERN_ERR " Trying to limit transfer sizes\n");
CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
}
cdrom_end_request(drive, 0);
@@ -1165,7 +1165,7 @@ static int cdrom_read_from_buffer (ide_drive_t *drive)
paranoid and check. */
if (rq->current_nr_sectors < bio_cur_sectors(rq->bio) &&
(rq->sector & (sectors_per_frame - 1))) {
- printk("%s: cdrom_read_from_buffer: buffer botch (%ld)\n",
+ printk(KERN_ERR "%s: cdrom_read_from_buffer: buffer botch (%ld)\n",
drive->name, (long)rq->sector);
cdrom_end_request(drive, 0);
return -1;
@@ -1200,7 +1200,7 @@ static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
/* Sanity check... */
if (rq->current_nr_sectors != bio_cur_sectors(rq->bio) &&
(rq->sector & (sectors_per_frame - 1))) {
- printk ("%s: cdrom_start_read_continuation: buffer botch (%u)\n",
+ printk(KERN_ERR "%s: cdrom_start_read_continuation: buffer botch (%u)\n",
drive->name, rq->current_nr_sectors);
cdrom_end_request(drive, 0);
return ide_stopped;
@@ -1425,7 +1425,7 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
rq->sense_len += thislen;
} else {
confused:
- printk ("%s: cdrom_pc_intr: The drive "
+ printk (KERN_ERR "%s: cdrom_pc_intr: The drive "
"appears confused (ireason = 0x%02x)\n",
drive->name, ireason);
rq->flags |= REQ_FAILED;
@@ -1539,7 +1539,7 @@ static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ire
return 0;
else if (ireason == 2) {
/* Whoops... The drive wants to send data. */
- printk("%s: write_intr: wrong transfer direction!\n",
+ printk(KERN_ERR "%s: write_intr: wrong transfer direction!\n",
drive->name);
while (len > 0) {
@@ -1549,7 +1549,7 @@ static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ire
}
} else {
/* Drive wants a command packet, or invalid ireason... */
- printk("%s: write_intr: bad interrupt reason %x\n",
+ printk(KERN_ERR "%s: write_intr: bad interrupt reason %x\n",
drive->name, ireason);
}
@@ -1615,7 +1615,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
*/
if (dma) {
if (dma_error) {
- printk("ide-cd: dma error\n");
+ printk(KERN_ERR "ide-cd: dma error\n");
__ide_dma_off(drive);
return ide_error(drive, "dma error", stat);
}
@@ -1680,7 +1680,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
}
if (!ptr) {
- printk("%s: confused, missing data\n", drive->name);
+ printk(KERN_ERR "%s: confused, missing data\n", drive->name);
break;
}
@@ -1742,7 +1742,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
if (dma) {
info->dma = 0;
if ((dma_error = HWIF(drive)->ide_dma_end(drive))) {
- printk("ide-cd: write dma error\n");
+ printk(KERN_ERR "ide-cd: write dma error\n");
__ide_dma_off(drive);
}
}
@@ -1775,7 +1775,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
*/
uptodate = 1;
if (rq->current_nr_sectors > 0) {
- printk("%s: write_intr: data underrun (%d blocks)\n",
+ printk(KERN_ERR "%s: write_intr: data underrun (%d blocks)\n",
drive->name, rq->current_nr_sectors);
uptodate = 0;
}
@@ -1796,7 +1796,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
int this_transfer;
if (!rq->current_nr_sectors) {
- printk("ide-cd: write_intr: oops\n");
+ printk(KERN_ERR "ide-cd: write_intr: oops\n");
break;
}
@@ -1942,7 +1942,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
ide_stall_queue(drive, IDECD_SEEK_TIMER);
return ide_stopped;
}
- printk ("%s: DSC timeout\n", drive->name);
+ printk (KERN_ERR "%s: DSC timeout\n", drive->name);
}
CDROM_CONFIG_FLAGS(drive)->seeking = 0;
}
@@ -2078,7 +2078,7 @@ cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
if (stat != 0 &&
sense->sense_key == ILLEGAL_REQUEST &&
(sense->asc == 0x24 || sense->asc == 0x20)) {
- printk ("%s: door locking not supported\n",
+ printk (KERN_ERR "%s: door locking not supported\n",
drive->name);
CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
stat = 0;
@@ -2196,7 +2196,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
GFP_KERNEL);
info->toc = toc;
if (toc == NULL) {
- printk ("%s: No cdrom TOC buffer!\n", drive->name);
+ printk (KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name);
return -ENOMEM;
}
}
@@ -2883,7 +2883,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
if (drive->media == ide_optical) {
CDROM_CONFIG_FLAGS(drive)->mo_drive = 1;
CDROM_CONFIG_FLAGS(drive)->ram = 1;
- printk("%s: ATAPI magneto-optical drive\n", drive->name);
+ printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", drive->name);
return nslots;
}
@@ -2973,7 +2973,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
/* don't print speed if the drive reported 0.
*/
- printk("%s: ATAPI", drive->name);
+ printk(KERN_INFO "%s: ATAPI", drive->name);
if (CDROM_CONFIG_FLAGS(drive)->max_speed)
printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed);
printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM");
@@ -3216,7 +3216,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
#endif
if (ide_cdrom_register(drive, nslots)) {
- printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
+ printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
info->devinfo.handle = NULL;
return 1;
}
@@ -3243,7 +3243,7 @@ int ide_cdrom_cleanup(ide_drive_t *drive)
struct gendisk *g = drive->disk;
if (ide_unregister_subdriver(drive)) {
- printk("%s: %s: failed to ide_unregister_subdriver\n",
+ printk(KERN_ERR "%s: %s: failed to ide_unregister_subdriver\n",
__FUNCTION__, drive->name);
return 1;
}
@@ -3254,7 +3254,7 @@ int ide_cdrom_cleanup(ide_drive_t *drive)
if (info->changer_info != NULL)
kfree(info->changer_info);
if (devinfo->handle == drive && unregister_cdrom(devinfo))
- printk("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
+ printk(KERN_ERR "%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
kfree(info);
drive->driver_data = NULL;
blk_queue_prep_rq(drive->queue, NULL);
@@ -3403,21 +3403,21 @@ static int ide_cdrom_attach (ide_drive_t *drive)
/* skip drives that we were told to ignore */
if (ignore != NULL) {
if (strstr(ignore, drive->name)) {
- printk("ide-cd: ignoring drive %s\n", drive->name);
+ printk(KERN_INFO "ide-cd: ignoring drive %s\n", drive->name);
goto failed;
}
}
if (drive->scsi) {
- printk("ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name);
+ printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name);
goto failed;
}
info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL);
if (info == NULL) {
- printk("%s: Can't allocate a cdrom structure\n", drive->name);
+ printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name);
goto failed;
}
if (ide_register_subdriver(drive, &ide_cdrom_driver)) {
- printk("%s: Failed to register the driver with ide.c\n",
+ printk(KERN_ERR "%s: Failed to register the driver with ide.c\n",
drive->name);
kfree(info);
goto failed;
@@ -3441,7 +3441,7 @@ static int ide_cdrom_attach (ide_drive_t *drive)
if (info->changer_info != NULL)
kfree(info->changer_info);
if (devinfo->handle == drive && unregister_cdrom(devinfo))
- printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
+ printk (KERN_ERR "%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
kfree(info);
drive->driver_data = NULL;
goto failed;
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 2e50f8597b83..7f867df01a56 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1380,7 +1380,7 @@ int ata_attach(ide_drive_t *drive)
return 1;
}
-static int generic_ide_suspend(struct device *dev, u32 state)
+static int generic_ide_suspend(struct device *dev, pm_message_t state)
{
ide_drive_t *drive = dev->driver_data;
struct request rq;
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index abab060fd230..b114113b0acb 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -144,7 +144,6 @@ static dev_link_t *ide_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -485,8 +484,7 @@ static int __init init_ide_cs(void)
static void __exit exit_ide_cs(void)
{
pcmcia_unregister_driver(&ide_cs_driver);
- while (dev_list != NULL)
- ide_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_ide_cs);
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 1e7f9922d18d..3df65bbcf259 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -101,8 +101,6 @@ struct synaptics_data {
unsigned long int ext_cap; /* Extended Capabilities */
unsigned long int identity; /* Identification */
- /* Data for normal processing */
- int old_w; /* Previous w value */
unsigned char pkt_type; /* packet type - old, new, etc */
unsigned char mode; /* current mode byte */
};
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 9661806d0239..fbbfb9cfbc4e 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -178,7 +178,6 @@ static dev_link_t *avmcs_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -521,13 +520,7 @@ static int __init avmcs_init(void)
static void __exit avmcs_exit(void)
{
pcmcia_unregister_driver(&avmcs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- avmcs_release(dev_list);
- avmcs_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
module_init(avmcs_init);
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 06ce6605517b..784df60d1a1f 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -193,7 +193,6 @@ static dev_link_t *avma1cs_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -531,13 +530,7 @@ static int __init init_avma1_cs(void)
static void __exit exit_avma1_cs(void)
{
pcmcia_unregister_driver(&avma1cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- avma1cs_release(dev_list);
- avma1cs_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
module_init(init_avma1_cs);
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 5087eefd1e3d..92349814990f 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -227,7 +227,6 @@ static dev_link_t *elsa_cs_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -541,10 +540,7 @@ static int __init init_elsa_cs(void)
static void __exit exit_elsa_cs(void)
{
pcmcia_unregister_driver(&elsa_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- elsa_cs_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_elsa_cs);
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 44545eaf8333..ab4f78a33def 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -240,7 +240,6 @@ static dev_link_t *sedlbauer_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -648,13 +647,7 @@ static int __init init_sedlbauer_cs(void)
static void __exit exit_sedlbauer_cs(void)
{
pcmcia_unregister_driver(&sedlbauer_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- sedlbauer_release(dev_list);
- sedlbauer_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
module_init(init_sedlbauer_cs);
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index b84b3a21553c..c17c25fd4713 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -208,7 +208,6 @@ static dev_link_t *teles_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -522,10 +521,7 @@ static int __init init_teles_cs(void)
static void __exit exit_teles_cs(void)
{
pcmcia_unregister_driver(&teles_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- teles_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_teles_cs);
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index f98849abbe2a..6107058460b6 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -83,7 +83,7 @@ int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len,
* Remove all allocated DMA memory and unmap memory IO regions. If MTRR
* is enabled, also remove it again.
*/
-static void __devexit i2o_pci_free(struct i2o_controller *c)
+static void i2o_pci_free(struct i2o_controller *c)
{
struct device *dev;
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 21becb1e55c1..72f2b466b816 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -51,7 +51,7 @@ config MMC_PXA
config MMC_WBSD
tristate "Winbond W83L51xD SD/MMC Card Interface support"
- depends on MMC
+ depends on MMC && ISA
help
This selects the Winbond(R) W83L51xD Secure digital and
Multimedia card Interface.
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index 7df2e2185fe3..074ad87d7fbc 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -32,6 +32,7 @@
#define MANUFACTURER_HYUNDAI 0x00AD
#define MANUFACTURER_INTEL 0x0089
#define MANUFACTURER_MACRONIX 0x00C2
+#define MANUFACTURER_NEC 0x0010
#define MANUFACTURER_PMC 0x009D
#define MANUFACTURER_SST 0x00BF
#define MANUFACTURER_ST 0x0020
@@ -115,6 +116,9 @@
#define MX29F004T 0x0045
#define MX29F004B 0x0046
+/* NEC */
+#define UPD29F064115 0x221C
+
/* PMC */
#define PM49FL002 0x006D
#define PM49FL004 0x006E
@@ -1130,6 +1134,22 @@ static const struct amd_flash_info jedec_table[] = {
ERASEINFO(0x04000,1)
}
}, {
+ .mfr_id = MANUFACTURER_NEC,
+ .dev_id = UPD29F064115,
+ .name = "NEC uPD29F064115",
+ .uaddr = {
+ [0] = MTD_UADDR_0x0555_0x02AA, /* x8 */
+ [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
+ },
+ .DevSize = SIZE_8MiB,
+ .CmdSet = P_ID_AMD_STD,
+ .NumEraseRegions= 3,
+ .regions = {
+ ERASEINFO(0x2000,8),
+ ERASEINFO(0x10000,126),
+ ERASEINFO(0x2000,8),
+ }
+ }, {
.mfr_id = MANUFACTURER_MACRONIX,
.dev_id = MX29LV160B,
.name = "MXIC MX29LV160B",
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index ec63e3b6fa68..e37b4c1976e5 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -800,7 +800,6 @@ static dev_link_t *pcmciamtd_attach(void)
/* Register with Card Services */
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
@@ -854,35 +853,7 @@ static void __exit exit_pcmciamtd(void)
{
DEBUG(1, DRIVER_DESC " unloading");
pcmcia_unregister_driver(&pcmciamtd_driver);
-
- while(dev_list) {
- dev_link_t *link = dev_list;
-
- dev_list = link->next;
- if (link) {
- struct pcmciamtd_dev *dev = link->priv;
-
- if(dev) {
- if(link->state & DEV_PRESENT) {
- if (!(link->state & DEV_STALE_LINK)) {
- pcmciamtd_detach(link);
- }
- link->state &= ~DEV_PRESENT;
- if(dev->mtd_info) {
- del_mtd_device(dev->mtd_info);
- info("mtd%d: Removed",
- dev->mtd_info->index);
- }
- }
- if(dev->mtd_info) {
- DEBUG(2, "Destroying map for mtd%d",
- dev->mtd_info->index);
- map_destroy(dev->mtd_info);
- }
- kfree(dev);
- }
- }
- }
+ BUG_ON(dev_list != NULL);
}
module_init(init_pcmciamtd);
diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c
index 23eb4567cf98..62df7e6f00e1 100644
--- a/drivers/mtd/maps/scx200_docflash.c
+++ b/drivers/mtd/maps/scx200_docflash.c
@@ -26,9 +26,6 @@ MODULE_AUTHOR("Christer Weinigel <wingel@hack.org>");
MODULE_DESCRIPTION("NatSemi SCx200 DOCCS Flash Driver");
MODULE_LICENSE("GPL");
-/* Set this to one if you want to partition the flash */
-#define PARTITION 1
-
static int probe = 0; /* Don't autoprobe */
static unsigned size = 0x1000000; /* 16 MiB the whole ISA address space */
static unsigned width = 8; /* Default to 8 bits wide */
@@ -50,7 +47,7 @@ static struct resource docmem = {
static struct mtd_info *mymtd;
-#if PARTITION
+#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition partition_info[] = {
{
.name = "DOCCS Boot kernel",
@@ -200,7 +197,7 @@ static int __init init_scx200_docflash(void)
mymtd->owner = THIS_MODULE;
-#if PARTITION
+#ifdef CONFIG_MTD_PARTITIONS
partition_info[3].offset = mymtd->size-partition_info[3].size;
partition_info[2].size = partition_info[3].offset-partition_info[2].offset;
add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS);
@@ -213,7 +210,7 @@ static int __init init_scx200_docflash(void)
static void __exit cleanup_scx200_docflash(void)
{
if (mymtd) {
-#if PARTITION
+#ifdef CONFIG_MTD_PARTITIONS
del_mtd_partitions(mymtd);
#else
del_mtd_device(mymtd);
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index f1a08b5631b0..ad46ab8c31ce 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -34,7 +34,7 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " becker@scyld.com and others\n";
/* "Knobs" that adjust features and parameters. */
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
Setting to > 1512 effectively disables this feature. */
-static const int rx_copybreak = 200;
+static int rx_copybreak = 200;
/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
static const int mtu = 1500;
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index a32429f02ae4..6e37cafc2520 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -387,7 +387,7 @@ enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, IS_TORNADO=8,
HAS_PWR_CTRL=0x20, HAS_MII=0x40, HAS_NWAY=0x80, HAS_CB_FNS=0x100,
INVERT_MII_PWR=0x200, INVERT_LED_PWR=0x400, MAX_COLLISION_RESET=0x800,
EEPROM_OFFSET=0x1000, HAS_HWCKSM=0x2000, WNO_XCVR_PWR=0x4000,
- EXTRA_PREAMBLE=0x8000, };
+ EXTRA_PREAMBLE=0x8000, EEPROM_RESET=0x10000, };
enum vortex_chips {
CH_3C590 = 0,
@@ -462,9 +462,9 @@ static struct vortex_chip_info {
{"3c595 Vortex 100base-MII",
PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
{"3c900 Boomerang 10baseT",
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, },
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|EEPROM_RESET, 64, },
{"3c900 Boomerang 10Mbps Combo",
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, },
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|EEPROM_RESET, 64, },
{"3c900 Cyclone 10Mbps TPO", /* AKPM: from Don's 0.99M */
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
{"3c900 Cyclone 10Mbps Combo",
@@ -475,9 +475,9 @@ static struct vortex_chip_info {
{"3c900B-FL Cyclone 10base-FL",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
{"3c905 Boomerang 100baseTx",
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, },
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
{"3c905 Boomerang 100baseT4",
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, },
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
{"3c905B Cyclone 100baseTx",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
@@ -804,7 +804,7 @@ struct vortex_private {
* bale from the ISR */
u16 io_size; /* Size of PCI region (for release_region) */
spinlock_t lock; /* Serialise access to device & its vortex_private */
- spinlock_t mdio_lock; /* Serialise access to mdio hardware */
+ struct mii_if_info mii; /* MII lib hooks/info */
};
#ifdef CONFIG_PCI
@@ -851,6 +851,22 @@ static struct media_table {
{ "Default", 0, 0xFF, XCVR_10baseT, 10000},
};
+static struct {
+ const char str[ETH_GSTRING_LEN];
+} ethtool_stats_keys[] = {
+ { "rx_packets" },
+ { "tx_packets" },
+ { "rx_bytes" },
+ { "tx_bytes" },
+ { "collisions" },
+ { "tx_carrier_errors" },
+ { "tx_heartbeat_errors" },
+ { "tx_window_errors" },
+};
+
+/* number of ETHTOOL_GSTATS u64's */
+#define VORTEX_NUM_STATS 8
+
static int vortex_probe1(struct device *gendev, long ioaddr, int irq,
int chip_idx, int card_idx);
static void vortex_up(struct net_device *dev);
@@ -935,7 +951,7 @@ MODULE_PARM_DESC(watchdog, "3c59x transmit timeout in milliseconds");
#ifdef CONFIG_NET_POLL_CONTROLLER
static void poll_vortex(struct net_device *dev)
{
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
+ struct vortex_private *vp = netdev_priv(dev);
unsigned long flags;
local_save_flags(flags);
local_irq_disable();
@@ -1076,14 +1092,20 @@ static int __devinit vortex_init_one (struct pci_dev *pdev,
int rc;
/* wake up and enable device */
- if (pci_enable_device (pdev)) {
- rc = -EIO;
- } else {
- rc = vortex_probe1 (&pdev->dev, pci_resource_start (pdev, 0),
- pdev->irq, ent->driver_data, vortex_cards_found);
- if (rc == 0)
- vortex_cards_found++;
+ rc = pci_enable_device (pdev);
+ if (rc < 0)
+ goto out;
+
+ rc = vortex_probe1 (&pdev->dev, pci_resource_start (pdev, 0),
+ pdev->irq, ent->driver_data, vortex_cards_found);
+ if (rc < 0) {
+ pci_disable_device (pdev);
+ goto out;
}
+
+ vortex_cards_found++;
+
+out:
return rc;
}
@@ -1212,8 +1234,12 @@ static int __devinit vortex_probe1(struct device *gendev,
}
spin_lock_init(&vp->lock);
- spin_lock_init(&vp->mdio_lock);
vp->gendev = gendev;
+ vp->mii.dev = dev;
+ vp->mii.mdio_read = mdio_read;
+ vp->mii.mdio_write = mdio_write;
+ vp->mii.phy_id_mask = 0x1f;
+ vp->mii.reg_num_mask = 0x1f;
/* Makes sure rings are at least 16 byte aligned. */
vp->rx_ring = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
@@ -1448,6 +1474,7 @@ static int __devinit vortex_probe1(struct device *gendev,
mdio_write(dev, vp->phys[0], 4, vp->advertising);
}
}
+ vp->mii.phy_id = vp->phys[0];
}
if (vp->capabilities & CapBusMaster) {
@@ -1493,7 +1520,7 @@ static int __devinit vortex_probe1(struct device *gendev,
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = poll_vortex;
#endif
- if (pdev && vp->enable_wol) {
+ if (pdev) {
vp->pm_state_valid = 1;
pci_save_state(VORTEX_PCI(vp));
acpi_set_WOL(dev);
@@ -1550,9 +1577,10 @@ vortex_up(struct net_device *dev)
unsigned int config;
int i;
- if (VORTEX_PCI(vp) && vp->enable_wol) {
+ if (VORTEX_PCI(vp)) {
pci_set_power_state(VORTEX_PCI(vp), PCI_D0); /* Go active */
pci_restore_state(VORTEX_PCI(vp));
+ pci_enable_device(VORTEX_PCI(vp));
}
/* Before initializing select the active media port. */
@@ -1840,6 +1868,7 @@ vortex_timer(unsigned long data)
break;
case XCVR_MII: case XCVR_NWAY:
{
+ spin_lock_bh(&vp->lock);
mii_status = mdio_read(dev, vp->phys[0], 1);
ok = 1;
if (vortex_debug > 2)
@@ -1873,6 +1902,7 @@ vortex_timer(unsigned long data)
} else {
netif_carrier_off(dev);
}
+ spin_unlock_bh(&vp->lock);
}
break;
default: /* Other media types handled by Tx timeouts. */
@@ -2708,7 +2738,7 @@ vortex_down(struct net_device *dev, int final_down)
if (vp->full_bus_master_tx)
outl(0, ioaddr + DownListPtr);
- if (final_down && VORTEX_PCI(vp) && vp->enable_wol) {
+ if (final_down && VORTEX_PCI(vp)) {
pci_save_state(VORTEX_PCI(vp));
acpi_set_WOL(dev);
}
@@ -2869,6 +2899,109 @@ static void update_stats(long ioaddr, struct net_device *dev)
return;
}
+static int vortex_nway_reset(struct net_device *dev)
+{
+ struct vortex_private *vp = netdev_priv(dev);
+ long ioaddr = dev->base_addr;
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&vp->lock, flags);
+ EL3WINDOW(4);
+ rc = mii_nway_restart(&vp->mii);
+ spin_unlock_irqrestore(&vp->lock, flags);
+ return rc;
+}
+
+static u32 vortex_get_link(struct net_device *dev)
+{
+ struct vortex_private *vp = netdev_priv(dev);
+ long ioaddr = dev->base_addr;
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&vp->lock, flags);
+ EL3WINDOW(4);
+ rc = mii_link_ok(&vp->mii);
+ spin_unlock_irqrestore(&vp->lock, flags);
+ return rc;
+}
+
+static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct vortex_private *vp = netdev_priv(dev);
+ long ioaddr = dev->base_addr;
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&vp->lock, flags);
+ EL3WINDOW(4);
+ rc = mii_ethtool_gset(&vp->mii, cmd);
+ spin_unlock_irqrestore(&vp->lock, flags);
+ return rc;
+}
+
+static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct vortex_private *vp = netdev_priv(dev);
+ long ioaddr = dev->base_addr;
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&vp->lock, flags);
+ EL3WINDOW(4);
+ rc = mii_ethtool_sset(&vp->mii, cmd);
+ spin_unlock_irqrestore(&vp->lock, flags);
+ return rc;
+}
+
+static u32 vortex_get_msglevel(struct net_device *dev)
+{
+ return vortex_debug;
+}
+
+static void vortex_set_msglevel(struct net_device *dev, u32 dbg)
+{
+ vortex_debug = dbg;
+}
+
+static int vortex_get_stats_count(struct net_device *dev)
+{
+ return VORTEX_NUM_STATS;
+}
+
+static void vortex_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct vortex_private *vp = netdev_priv(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&vp->lock, flags);
+ update_stats(dev->base_addr, dev);
+ spin_unlock_irqrestore(&vp->lock, flags);
+
+ data[0] = vp->stats.rx_packets;
+ data[1] = vp->stats.tx_packets;
+ data[2] = vp->stats.rx_bytes;
+ data[3] = vp->stats.tx_bytes;
+ data[4] = vp->stats.collisions;
+ data[5] = vp->stats.tx_carrier_errors;
+ data[6] = vp->stats.tx_heartbeat_errors;
+ data[7] = vp->stats.tx_window_errors;
+}
+
+
+static void vortex_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+ switch (stringset) {
+ case ETH_SS_STATS:
+ memcpy(data, &ethtool_stats_keys, sizeof(ethtool_stats_keys));
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }
+}
static void vortex_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
@@ -2890,44 +3023,18 @@ static void vortex_get_drvinfo(struct net_device *dev,
static struct ethtool_ops vortex_ethtool_ops = {
.get_drvinfo = vortex_get_drvinfo,
+ .get_strings = vortex_get_strings,
+ .get_msglevel = vortex_get_msglevel,
+ .set_msglevel = vortex_set_msglevel,
+ .get_ethtool_stats = vortex_get_ethtool_stats,
+ .get_stats_count = vortex_get_stats_count,
+ .get_settings = vortex_get_settings,
+ .set_settings = vortex_set_settings,
+ .get_link = vortex_get_link,
+ .nway_reset = vortex_nway_reset,
};
#ifdef CONFIG_PCI
-static int vortex_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
- struct mii_ioctl_data *data = if_mii(rq);
- int phy = vp->phys[0] & 0x1f;
- int retval;
-
- switch(cmd) {
- case SIOCGMIIPHY: /* Get address of MII PHY in use. */
- data->phy_id = phy;
-
- case SIOCGMIIREG: /* Read MII PHY register. */
- EL3WINDOW(4);
- data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
- retval = 0;
- break;
-
- case SIOCSMIIREG: /* Write MII PHY register. */
- if (!capable(CAP_NET_ADMIN)) {
- retval = -EPERM;
- } else {
- EL3WINDOW(4);
- mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
- retval = 0;
- }
- break;
- default:
- retval = -EOPNOTSUPP;
- break;
- }
-
- return retval;
-}
-
/*
* Must power the device up to do MDIO operations
*/
@@ -2935,6 +3042,8 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
int err;
struct vortex_private *vp = netdev_priv(dev);
+ long ioaddr = dev->base_addr;
+ unsigned long flags;
int state = 0;
if(VORTEX_PCI(vp))
@@ -2944,7 +3053,10 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if(state != 0)
pci_set_power_state(VORTEX_PCI(vp), PCI_D0);
- err = vortex_do_ioctl(dev, rq, cmd);
+ spin_lock_irqsave(&vp->lock, flags);
+ EL3WINDOW(4);
+ err = generic_mii_ioctl(&vp->mii, if_mii(rq), cmd, NULL);
+ spin_unlock_irqrestore(&vp->lock, flags);
if(state != 0)
pci_set_power_state(VORTEX_PCI(vp), state);
@@ -2983,7 +3095,7 @@ static void set_rx_mode(struct net_device *dev)
static void set_8021q_mode(struct net_device *dev, int enable)
{
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
+ struct vortex_private *vp = netdev_priv(dev);
long ioaddr = dev->base_addr;
int old_window = inw(ioaddr + EL3_CMD);
int mac_ctrl;
@@ -3062,15 +3174,12 @@ static void mdio_sync(long ioaddr, int bits)
static int mdio_read(struct net_device *dev, int phy_id, int location)
{
- struct vortex_private *vp = netdev_priv(dev);
int i;
long ioaddr = dev->base_addr;
int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
unsigned int retval = 0;
long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
- spin_lock_bh(&vp->mdio_lock);
-
if (mii_preamble_required)
mdio_sync(ioaddr, 32);
@@ -3090,20 +3199,16 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)
outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
- spin_unlock_bh(&vp->mdio_lock);
return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff;
}
static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
{
- struct vortex_private *vp = netdev_priv(dev);
long ioaddr = dev->base_addr;
int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
int i;
- spin_lock_bh(&vp->mdio_lock);
-
if (mii_preamble_required)
mdio_sync(ioaddr, 32);
@@ -3122,7 +3227,6 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
- spin_unlock_bh(&vp->mdio_lock);
return;
}
@@ -3133,15 +3237,17 @@ static void acpi_set_WOL(struct net_device *dev)
struct vortex_private *vp = netdev_priv(dev);
long ioaddr = dev->base_addr;
- /* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */
- EL3WINDOW(7);
- outw(2, ioaddr + 0x0c);
- /* The RxFilter must accept the WOL frames. */
- outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
- outw(RxEnable, ioaddr + EL3_CMD);
+ if (vp->enable_wol) {
+ /* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */
+ EL3WINDOW(7);
+ outw(2, ioaddr + 0x0c);
+ /* The RxFilter must accept the WOL frames. */
+ outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
+ outw(RxEnable, ioaddr + EL3_CMD);
+ pci_enable_wake(VORTEX_PCI(vp), 0, 1);
+ }
/* Change the power state to D3; RxEnable doesn't take effect. */
- pci_enable_wake(VORTEX_PCI(vp), 0, 1);
pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot);
}
@@ -3164,13 +3270,15 @@ static void __devexit vortex_remove_one (struct pci_dev *pdev)
*/
unregister_netdev(dev);
- if (VORTEX_PCI(vp) && vp->enable_wol) {
+ if (VORTEX_PCI(vp)) {
pci_set_power_state(VORTEX_PCI(vp), PCI_D0); /* Go active */
if (vp->pm_state_valid)
pci_restore_state(VORTEX_PCI(vp));
+ pci_disable_device(VORTEX_PCI(vp));
}
/* Should really use issue_and_wait() here */
- outw(TotalReset|0x14, dev->base_addr + EL3_CMD);
+ outw(TotalReset | ((vp->drv_flags & EEPROM_RESET) ? 0x04 : 0x14),
+ dev->base_addr + EL3_CMD);
pci_free_consistent(pdev,
sizeof(struct boom_rx_desc) * RX_RING_SIZE
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index bed9c03dd0d1..6fa1bd83f305 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -1636,7 +1636,8 @@ static int rtl8139_thread (void *data)
if (tp->time_to_die)
break;
- rtnl_lock ();
+ if (rtnl_lock_interruptible ())
+ break;
rtl8139_thread_iter (dev, tp, tp->mmio_addr);
rtnl_unlock ();
}
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 4ff0f47d5332..cbdb8cd3d22f 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -691,6 +691,7 @@ config ELMC_II
config VORTEX
tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support"
depends on NET_VENDOR_3COM && (PCI || EISA)
+ select MII
---help---
This option enables driver support for a large number of 10mbps and
10/100mbps EISA, PCI and PCMCIA 3Com network cards:
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 282a678007b3..9fd21724f61f 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -93,7 +93,6 @@ EXPORT_SYMBOL(arc_raw_proto);
EXPORT_SYMBOL(arc_proto_null);
EXPORT_SYMBOL(arcnet_unregister_proto);
EXPORT_SYMBOL(arcnet_debug);
-EXPORT_SYMBOL(arcdev_setup);
EXPORT_SYMBOL(alloc_arcdev);
EXPORT_SYMBOL(arcnet_interrupt);
@@ -317,7 +316,7 @@ static int choose_mtu(void)
/* Setup a struct device for ARCnet. */
-void arcdev_setup(struct net_device *dev)
+static void arcdev_setup(struct net_device *dev)
{
dev->type = ARPHRD_ARCNET;
dev->hard_header_len = sizeof(struct archdr);
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 9b40cf1c2c9c..e4061ffc48aa 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -1666,7 +1666,7 @@ struct ethtool_ops e1000_ethtool_ops = {
.get_ethtool_stats = e1000_get_ethtool_stats,
};
-void set_ethtool_ops(struct net_device *netdev)
+void e1000_set_ethtool_ops(struct net_device *netdev)
{
SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);
}
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 216a5b6eb76a..aa5ad41acf24 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -151,7 +151,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
int cmd);
-void set_ethtool_ops(struct net_device *netdev);
+void e1000_set_ethtool_ops(struct net_device *netdev);
static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
static void e1000_tx_timeout(struct net_device *dev);
@@ -475,7 +475,7 @@ e1000_probe(struct pci_dev *pdev,
netdev->set_mac_address = &e1000_set_mac;
netdev->change_mtu = &e1000_change_mtu;
netdev->do_ioctl = &e1000_ioctl;
- set_ethtool_ops(netdev);
+ e1000_set_ethtool_ops(netdev);
netdev->tx_timeout = &e1000_tx_timeout;
netdev->watchdog_timeo = 5 * HZ;
#ifdef CONFIG_E1000_NAPI
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index 3f05a33e7c69..cd2475683027 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -23,6 +23,7 @@
This is a compatibility hardware problem.
Versions:
+ 0.13b basic ethtool support (aris, 09/13/2004)
0.13a in memory shortage, drop packets also in board
(Michael Westermann <mw@microdata-pos.de>, 07/30/2002)
0.13 irq sharing, rewrote probe function, fixed a nasty bug in
@@ -104,7 +105,7 @@
*/
static const char version[] =
- "eepro.c: v0.13 11/08/2001 aris@cathedrallabs.org\n";
+ "eepro.c: v0.13b 09/13/2004 aris@cathedrallabs.org\n";
#include <linux/module.h>
@@ -146,19 +147,21 @@ static const char version[] =
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/bitops.h>
+#include <linux/ethtool.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/dma.h>
#define DRV_NAME "eepro"
+#define DRV_VERSION "0.13b"
#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) )
/* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */
#define SLOW_DOWN inb(0x80)
/* udelay(2) */
#define compat_init_data __initdata
-
+enum iftype { AUI=0, BNC=1, TPE=2 };
/* First, a few definitions that the brave might change. */
/* A zero-terminated list of I/O addresses to be probed. */
@@ -214,6 +217,7 @@ struct eepro_local {
short rcv_lower_limit;
short rcv_upper_limit;
unsigned char eeprom_reg;
+ unsigned short word[8];
};
/* The station (ethernet) address prefix, used for IDing the board. */
@@ -608,16 +612,22 @@ out:
}
#endif
-static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
+static void __init printEEPROMInfo(struct net_device *dev)
{
+ struct eepro_local *lp = (struct eepro_local *)dev->priv;
+ int ioaddr = dev->base_addr;
unsigned short Word;
int i,j;
- for (i=0, j=ee_Checksum; i<ee_SIZE; i++)
- j+=read_eeprom(ioaddr,i,dev);
+ j = ee_Checksum;
+ for (i = 0; i < 8; i++)
+ j += lp->word[i];
+ for ( ; i < ee_SIZE; i++)
+ j += read_eeprom(ioaddr, i, dev);
+
printk(KERN_DEBUG "Checksum: %#x\n",j&0xffff);
- Word=read_eeprom(ioaddr, 0, dev);
+ Word = lp->word[0];
printk(KERN_DEBUG "Word0:\n");
printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP));
printk(KERN_DEBUG " Buswidth: %d\n",(GetBit(Word,ee_BusWidth)+1)*8 );
@@ -625,7 +635,7 @@ static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
printk(KERN_DEBUG " IO Address: %#x\n", (Word>>ee_IO0)<<4);
if (net_debug>4) {
- Word=read_eeprom(ioaddr, 1, dev);
+ Word = lp->word[1];
printk(KERN_DEBUG "Word1:\n");
printk(KERN_DEBUG " INT: %d\n", Word & ee_IntMask);
printk(KERN_DEBUG " LI: %d\n", GetBit(Word,ee_LI));
@@ -636,7 +646,7 @@ static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));
}
- Word=read_eeprom(ioaddr, 5, dev);
+ Word = lp->word[5];
printk(KERN_DEBUG "Word5:\n");
printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));
printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));
@@ -646,12 +656,12 @@ static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
if (GetBit(Word,ee_PortAUI)) printk(KERN_DEBUG "AUI ");
printk(KERN_DEBUG "port(s) \n");
- Word=read_eeprom(ioaddr, 6, dev);
+ Word = lp->word[6];
printk(KERN_DEBUG "Word6:\n");
printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask);
printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID);
- Word=read_eeprom(ioaddr, 7, dev);
+ Word = lp->word[7];
printk(KERN_DEBUG "Word7:\n");
printk(KERN_DEBUG " INT to IRQ:\n");
@@ -725,7 +735,7 @@ static void __init eepro_print_info (struct net_device *dev)
printk(", %s.\n", ifmap[dev->if_port]);
if (net_debug > 3) {
- i = read_eeprom(dev->base_addr, 5, dev);
+ i = lp->word[5];
if (i & 0x2000) /* bit 13 of EEPROM word 5 */
printk(KERN_DEBUG "%s: Concurrent Processing is "
"enabled but not used!\n", dev->name);
@@ -733,19 +743,20 @@ static void __init eepro_print_info (struct net_device *dev)
/* Check the station address for the manufacturer's code */
if (net_debug>3)
- printEEPROMInfo(dev->base_addr, dev);
+ printEEPROMInfo(dev);
}
+static struct ethtool_ops eepro_ethtool_ops;
+
/* This is the real probe routine. Linux has a history of friendly device
probes on the ISA bus. A good device probe avoids doing writes, and
verifies that the correct device exists and functions. */
static int __init eepro_probe1(struct net_device *dev, int autoprobe)
{
- unsigned short station_addr[6], id, counter;
+ unsigned short station_addr[3], id, counter;
int i;
struct eepro_local *lp;
- enum iftype { AUI=0, BNC=1, TPE=2 };
int ioaddr = dev->base_addr;
/* Grab the region so we can find another board if autoIRQ fails. */
@@ -796,11 +807,16 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
lp->xmt_bar = XMT_BAR_10;
station_addr[0] = read_eeprom(ioaddr, 2, dev);
}
- station_addr[1] = read_eeprom(ioaddr, 3, dev);
- station_addr[2] = read_eeprom(ioaddr, 4, dev);
+
+ /* get all words at once. will be used here and for ethtool */
+ for (i = 0; i < 8; i++) {
+ lp->word[i] = read_eeprom(ioaddr, i, dev);
+ }
+ station_addr[1] = lp->word[3];
+ station_addr[2] = lp->word[4];
if (!lp->eepro) {
- if (read_eeprom(ioaddr,7,dev)== ee_FX_INT2IRQ)
+ if (lp->word[7] == ee_FX_INT2IRQ)
lp->eepro = 2;
else if (station_addr[2] == SA_ADDR1)
lp->eepro = 1;
@@ -817,15 +833,15 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
/* calculate {xmt,rcv}_{lower,upper}_limit */
eepro_recalc(dev);
- if (GetBit( read_eeprom(ioaddr, 5, dev),ee_BNC_TPE))
+ if (GetBit(lp->word[5], ee_BNC_TPE))
dev->if_port = BNC;
else
dev->if_port = TPE;
if (dev->irq < 2 && lp->eepro != 0) {
/* Mask off INT number */
- int count = read_eeprom(ioaddr, 1, dev) & 7;
- unsigned irqMask = read_eeprom(ioaddr, 7, dev);
+ int count = lp->word[1] & 7;
+ unsigned irqMask = lp->word[7];
while (count--)
irqMask &= irqMask - 1;
@@ -850,6 +866,7 @@ static int __init eepro_probe1(struct net_device *dev, int autoprobe)
dev->set_multicast_list = &set_multicast_list;
dev->tx_timeout = eepro_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
+ dev->ethtool_ops = &eepro_ethtool_ops;
/* print boot time info */
eepro_print_info(dev);
@@ -941,7 +958,7 @@ static int eepro_open(struct net_device *dev)
if (net_debug > 3)
printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name);
- irqMask = read_eeprom(ioaddr,7,dev);
+ irqMask = lp->word[7];
if (lp->eepro == LAN595FX_10ISA) {
if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 3;\n");
@@ -1070,8 +1087,6 @@ static int eepro_open(struct net_device *dev)
old9 = inb(ioaddr + 9);
if (irqMask==ee_FX_INT2IRQ) {
- enum iftype { AUI=0, BNC=1, TPE=2 };
-
if (net_debug > 3) {
printk(KERN_DEBUG "IrqMask: %#x\n",irqMask);
printk(KERN_DEBUG "i82595FX detected!\n");
@@ -1701,12 +1716,72 @@ eepro_transmit_interrupt(struct net_device *dev)
}
}
+static int eepro_ethtool_get_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ struct eepro_local *lp = (struct eepro_local *)dev->priv;
+
+ cmd->supported = SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_Autoneg;
+ cmd->advertising = ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_Autoneg;
+
+ if (GetBit(lp->word[5], ee_PortTPE)) {
+ cmd->supported |= SUPPORTED_TP;
+ cmd->advertising |= ADVERTISED_TP;
+ }
+ if (GetBit(lp->word[5], ee_PortBNC)) {
+ cmd->supported |= SUPPORTED_BNC;
+ cmd->advertising |= ADVERTISED_BNC;
+ }
+ if (GetBit(lp->word[5], ee_PortAUI)) {
+ cmd->supported |= SUPPORTED_AUI;
+ cmd->advertising |= ADVERTISED_AUI;
+ }
+
+ cmd->speed = SPEED_10;
+
+ if (dev->if_port == TPE && lp->word[1] & ee_Duplex) {
+ cmd->duplex = DUPLEX_FULL;
+ }
+ else {
+ cmd->duplex = DUPLEX_HALF;
+ }
+
+ cmd->port = dev->if_port;
+ cmd->phy_address = dev->base_addr;
+ cmd->transceiver = XCVR_INTERNAL;
+
+ if (lp->word[0] & ee_AutoNeg) {
+ cmd->autoneg = 1;
+ }
+
+ return 0;
+}
+
+static void eepro_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ strcpy(drvinfo->driver, DRV_NAME);
+ strcpy(drvinfo->version, DRV_VERSION);
+ sprintf(drvinfo->bus_info, "ISA 0x%lx", dev->base_addr);
+}
+
+static struct ethtool_ops eepro_ethtool_ops = {
+ .get_settings = eepro_ethtool_get_settings,
+ .get_drvinfo = eepro_ethtool_get_drvinfo,
+};
+
#ifdef MODULE
#define MAX_EEPRO 8
static struct net_device *dev_eepro[MAX_EEPRO];
-static int io[MAX_EEPRO];
+static int io[MAX_EEPRO] = {
+ [0 ... MAX_EEPRO-1] = -1
+};
static int irq[MAX_EEPRO];
static int mem[MAX_EEPRO] = { /* Size of the rx buffer in KB */
[0 ... MAX_EEPRO-1] = RCV_DEFAULT_RAM/1024
@@ -1716,14 +1791,15 @@ static int autodetect;
static int n_eepro;
/* For linux 2.1.xx */
-MODULE_AUTHOR("Pascal Dupuis, and aris@cathedrallabs.org");
+MODULE_AUTHOR("Pascal Dupuis and others");
MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver");
MODULE_LICENSE("GPL");
-MODULE_PARM(io, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-MODULE_PARM(autodetect, "1-" __MODULE_STRING(1) "i");
+static int num_params;
+module_param_array(io, int, &num_params, 0);
+module_param_array(irq, int, &num_params, 0);
+module_param_array(mem, int, &num_params, 0);
+module_param(autodetect, int, 0);
MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base addres(es)");
MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)");
MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)");
@@ -1734,19 +1810,21 @@ init_module(void)
{
struct net_device *dev;
int i;
- if (io[0] == 0 && autodetect == 0) {
+ if (io[0] == -1 && autodetect == 0) {
printk(KERN_WARNING "eepro_init_module: Probe is very dangerous in ISA boards!\n");
printk(KERN_WARNING "eepro_init_module: Please add \"autodetect=1\" to force probe\n");
- return 1;
+ return -ENODEV;
}
else if (autodetect) {
/* if autodetect is set then we must force detection */
- io[0] = 0;
+ for (i = 0; i < MAX_EEPRO; i++) {
+ io[i] = 0;
+ }
printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n");
}
- for (i = 0; i < MAX_EEPRO; i++) {
+ for (i = 0; io[i] != -1 && i < MAX_EEPRO; i++) {
dev = alloc_etherdev(sizeof(struct eepro_local));
if (!dev)
break;
diff --git a/drivers/net/ibm_emac/ibm_emac.h b/drivers/net/ibm_emac/ibm_emac.h
index 7436af6055ac..9d9b59e61351 100644
--- a/drivers/net/ibm_emac/ibm_emac.h
+++ b/drivers/net/ibm_emac/ibm_emac.h
@@ -98,7 +98,7 @@ typedef struct emac_regs {
#endif /* CONFIG_IBM_EMAC4 */
#define EMAC_M1_BASE (EMAC_M1_TX_FIFO_2K | \
EMAC_M1_APP | \
- EMAC_M1_TR)
+ EMAC_M1_TR | EMAC_M1_VLE)
/* Transmit Mode Register 0 */
#define EMAC_TMR0_GNP0 0x80000000
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index 39c65064c046..7346ab066dbc 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -1363,6 +1363,9 @@ static void emac_reset_configure(struct ocp_enet_private *fep)
/* set frame gap */
out_be32(&emacp->em0ipgvr, CONFIG_IBM_EMAC_FGAP);
+
+ /* set VLAN Tag Protocol Identifier */
+ out_be32(&emacp->em0vtpid, 0x8100);
/* Init ring buffers */
emac_init_rings(fep->ndev);
@@ -1700,6 +1703,15 @@ struct mal_commac_ops emac_commac_ops = {
.rxde = &emac_rxde_dev,
};
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static int emac_netpoll(struct net_device *ndev)
+{
+ emac_rxeob_dev((void *)ndev, 0);
+ emac_txeob_dev((void *)ndev, 0);
+ return 0;
+}
+#endif
+
static int emac_init_device(struct ocp_device *ocpdev, struct ibm_ocp_mal *mal)
{
int deferred_init = 0;
@@ -1882,6 +1894,9 @@ static int emac_init_device(struct ocp_device *ocpdev, struct ibm_ocp_mal *mal)
SET_ETHTOOL_OPS(ndev, &emac_ethtool_ops);
if (emacdata->tah_idx >= 0)
ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ ndev->poll_controller = emac_netpoll;
+#endif
SET_MODULE_OWNER(ndev);
diff --git a/drivers/net/ibm_emac/ibm_emac_phy.c b/drivers/net/ibm_emac/ibm_emac_phy.c
index b439087df8ec..14213f090e91 100644
--- a/drivers/net/ibm_emac/ibm_emac_phy.c
+++ b/drivers/net/ibm_emac/ibm_emac_phy.c
@@ -191,17 +191,18 @@ static int genmii_read_link(struct mii_phy *phy)
u16 lpa;
if (phy->autoneg) {
- lpa = phy_read(phy, MII_LPA);
+ lpa = phy_read(phy, MII_LPA) & phy_read(phy, MII_ADVERTISE);
- if (lpa & (LPA_10FULL | LPA_100FULL))
- phy->duplex = DUPLEX_FULL;
- else
- phy->duplex = DUPLEX_HALF;
- if (lpa & (LPA_100FULL | LPA_100HALF))
- phy->speed = SPEED_100;
- else
- phy->speed = SPEED_10;
+ phy->speed = SPEED_10;
+ phy->duplex = DUPLEX_HALF;
phy->pause = 0;
+
+ if (lpa & (LPA_100FULL | LPA_100HALF)) {
+ phy->speed = SPEED_100;
+ if (lpa & LPA_100FULL)
+ phy->duplex = DUPLEX_FULL;
+ } else if (lpa & LPA_10FULL)
+ phy->duplex = DUPLEX_FULL;
}
/* On non-aneg, we assume what we put in BMCR is the speed,
* though magic-aneg shouldn't prevent this case from occurring
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index d5c6f477f916..3426020a915b 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -46,6 +46,7 @@
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/slab.h>
+#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/string.h>
#include <linux/pagemap.h>
@@ -85,6 +86,20 @@ struct ixgb_adapter;
#define IXGB_ERR(args...) printk(KERN_ERR "ixgb: " args)
+/* TX/RX descriptor defines */
+#define DEFAULT_TXD 256
+#define MAX_TXD 4096
+#define MIN_TXD 64
+
+/* hardware cannot reliably support more than 512 descriptors owned by
+ * hardware descrioptor cache otherwise an unreliable ring under heavy
+ * recieve load may result */
+/* #define DEFAULT_RXD 1024 */
+/* #define MAX_RXD 4096 */
+#define DEFAULT_RXD 512
+#define MAX_RXD 512
+#define MIN_RXD 64
+
/* Supported Rx Buffer Sizes */
#define IXGB_RXBUFFER_2048 2048
#define IXGB_RXBUFFER_4096 4096
@@ -105,9 +120,9 @@ struct ixgb_adapter;
struct ixgb_buffer {
struct sk_buff *skb;
uint64_t dma;
- unsigned long length;
unsigned long time_stamp;
- unsigned int next_to_watch;
+ uint16_t length;
+ uint16_t next_to_watch;
};
struct ixgb_desc_ring {
@@ -167,7 +182,6 @@ struct ixgb_adapter {
uint64_t hw_csum_rx_error;
uint64_t hw_csum_rx_good;
uint32_t rx_int_delay;
- boolean_t raidc;
boolean_t rx_csum;
/* OS defined structs */
@@ -178,5 +192,8 @@ struct ixgb_adapter {
/* structs defined in ixgb_hw.h */
struct ixgb_hw hw;
struct ixgb_hw_stats stats;
+#ifdef CONFIG_PCI_MSI
+ boolean_t have_msi;
+#endif
};
-#endif /* _IXGB_H_ */
+#endif /* _IXGB_H_ */
diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
index c8adde5c9b30..97b5b1665ed6 100644
--- a/drivers/net/ixgb/ixgb_ee.c
+++ b/drivers/net/ixgb/ixgb_ee.c
@@ -32,7 +32,8 @@
static uint16_t ixgb_shift_in_bits(struct ixgb_hw *hw);
static void ixgb_shift_out_bits(struct ixgb_hw *hw,
- uint16_t data, uint16_t count);
+ uint16_t data,
+ uint16_t count);
static void ixgb_standby_eeprom(struct ixgb_hw *hw);
static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw);
@@ -45,7 +46,9 @@ static void ixgb_cleanup_eeprom(struct ixgb_hw *hw);
* hw - Struct containing variables accessed by shared code
* eecd_reg - EECD's current value
*****************************************************************************/
-static void ixgb_raise_clock(struct ixgb_hw *hw, uint32_t * eecd_reg)
+static void
+ixgb_raise_clock(struct ixgb_hw *hw,
+ uint32_t *eecd_reg)
{
/* Raise the clock input to the EEPROM (by setting the SK bit), and then
* wait 50 microseconds.
@@ -62,7 +65,9 @@ static void ixgb_raise_clock(struct ixgb_hw *hw, uint32_t * eecd_reg)
* hw - Struct containing variables accessed by shared code
* eecd_reg - EECD's current value
*****************************************************************************/
-static void ixgb_lower_clock(struct ixgb_hw *hw, uint32_t * eecd_reg)
+static void
+ixgb_lower_clock(struct ixgb_hw *hw,
+ uint32_t *eecd_reg)
{
/* Lower the clock input to the EEPROM (by clearing the SK bit), and then
* wait 50 microseconds.
@@ -81,7 +86,9 @@ static void ixgb_lower_clock(struct ixgb_hw *hw, uint32_t * eecd_reg)
* count - number of bits to shift out
*****************************************************************************/
static void
-ixgb_shift_out_bits(struct ixgb_hw *hw, uint16_t data, uint16_t count)
+ixgb_shift_out_bits(struct ixgb_hw *hw,
+ uint16_t data,
+ uint16_t count)
{
uint32_t eecd_reg;
uint32_t mask;
@@ -101,7 +108,7 @@ ixgb_shift_out_bits(struct ixgb_hw *hw, uint16_t data, uint16_t count)
*/
eecd_reg &= ~IXGB_EECD_DI;
- if (data & mask)
+ if(data & mask)
eecd_reg |= IXGB_EECD_DI;
IXGB_WRITE_REG(hw, EECD, eecd_reg);
@@ -113,7 +120,7 @@ ixgb_shift_out_bits(struct ixgb_hw *hw, uint16_t data, uint16_t count)
mask = mask >> 1;
- } while (mask);
+ } while(mask);
/* We leave the "DI" bit set to "0" when we leave this routine. */
eecd_reg &= ~IXGB_EECD_DI;
@@ -126,7 +133,8 @@ ixgb_shift_out_bits(struct ixgb_hw *hw, uint16_t data, uint16_t count)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static uint16_t ixgb_shift_in_bits(struct ixgb_hw *hw)
+static uint16_t
+ixgb_shift_in_bits(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
uint32_t i;
@@ -144,14 +152,14 @@ static uint16_t ixgb_shift_in_bits(struct ixgb_hw *hw)
eecd_reg &= ~(IXGB_EECD_DO | IXGB_EECD_DI);
data = 0;
- for (i = 0; i < 16; i++) {
+ for(i = 0; i < 16; i++) {
data = data << 1;
ixgb_raise_clock(hw, &eecd_reg);
eecd_reg = IXGB_READ_REG(hw, EECD);
eecd_reg &= ~(IXGB_EECD_DI);
- if (eecd_reg & IXGB_EECD_DO)
+ if(eecd_reg & IXGB_EECD_DO)
data |= 1;
ixgb_lower_clock(hw, &eecd_reg);
@@ -168,7 +176,8 @@ static uint16_t ixgb_shift_in_bits(struct ixgb_hw *hw)
* Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
* function should be called before issuing a command to the EEPROM.
*****************************************************************************/
-static void ixgb_setup_eeprom(struct ixgb_hw *hw)
+static void
+ixgb_setup_eeprom(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
@@ -189,7 +198,8 @@ static void ixgb_setup_eeprom(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void ixgb_standby_eeprom(struct ixgb_hw *hw)
+static void
+ixgb_standby_eeprom(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
@@ -222,7 +232,8 @@ static void ixgb_standby_eeprom(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void ixgb_clock_eeprom(struct ixgb_hw *hw)
+static void
+ixgb_clock_eeprom(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
@@ -245,7 +256,8 @@ static void ixgb_clock_eeprom(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void ixgb_cleanup_eeprom(struct ixgb_hw *hw)
+static void
+ixgb_cleanup_eeprom(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
@@ -270,7 +282,8 @@ static void ixgb_cleanup_eeprom(struct ixgb_hw *hw)
* TRUE: EEPROM data pin is high before timeout.
* FALSE: Time expired.
*****************************************************************************/
-static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw)
+static boolean_t
+ixgb_wait_eeprom_command(struct ixgb_hw *hw)
{
uint32_t eecd_reg;
uint32_t i;
@@ -284,10 +297,10 @@ static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw)
* signal that the command has been completed by raising the DO signal.
* If DO does not go high in 10 milliseconds, then error out.
*/
- for (i = 0; i < 200; i++) {
+ for(i = 0; i < 200; i++) {
eecd_reg = IXGB_READ_REG(hw, EECD);
- if (eecd_reg & IXGB_EECD_DO)
+ if(eecd_reg & IXGB_EECD_DO)
return (TRUE);
udelay(50);
@@ -309,15 +322,16 @@ static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw)
* TRUE: Checksum is valid
* FALSE: Checksum is not valid.
*****************************************************************************/
-boolean_t ixgb_validate_eeprom_checksum(struct ixgb_hw * hw)
+boolean_t
+ixgb_validate_eeprom_checksum(struct ixgb_hw *hw)
{
uint16_t checksum = 0;
uint16_t i;
- for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++)
+ for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++)
checksum += ixgb_read_eeprom(hw, i);
- if (checksum == (uint16_t) EEPROM_SUM)
+ if(checksum == (uint16_t) EEPROM_SUM)
return (TRUE);
else
return (FALSE);
@@ -331,12 +345,13 @@ boolean_t ixgb_validate_eeprom_checksum(struct ixgb_hw * hw)
* Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
* Writes the difference to word offset 63 of the EEPROM.
*****************************************************************************/
-void ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
+void
+ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
{
uint16_t checksum = 0;
uint16_t i;
- for (i = 0; i < EEPROM_CHECKSUM_REG; i++)
+ for(i = 0; i < EEPROM_CHECKSUM_REG; i++)
checksum += ixgb_read_eeprom(hw, i);
checksum = (uint16_t) EEPROM_SUM - checksum;
@@ -356,7 +371,10 @@ void ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
* EEPROM will most likely contain an invalid checksum.
*
*****************************************************************************/
-void ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t offset, uint16_t data)
+void
+ixgb_write_eeprom(struct ixgb_hw *hw,
+ uint16_t offset,
+ uint16_t data)
{
/* Prepare the EEPROM for writing */
ixgb_setup_eeprom(hw);
@@ -404,7 +422,9 @@ void ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t offset, uint16_t data)
* Returns:
* The 16-bit value read from the eeprom
*****************************************************************************/
-uint16_t ixgb_read_eeprom(struct ixgb_hw * hw, uint16_t offset)
+uint16_t
+ixgb_read_eeprom(struct ixgb_hw *hw,
+ uint16_t offset)
{
uint16_t data;
@@ -437,7 +457,8 @@ uint16_t ixgb_read_eeprom(struct ixgb_hw * hw, uint16_t offset)
* TRUE: if eeprom read is successful
* FALSE: otherwise.
*****************************************************************************/
-boolean_t ixgb_get_eeprom_data(struct ixgb_hw * hw)
+boolean_t
+ixgb_get_eeprom_data(struct ixgb_hw *hw)
{
uint16_t i;
uint16_t checksum = 0;
@@ -448,7 +469,7 @@ boolean_t ixgb_get_eeprom_data(struct ixgb_hw * hw)
ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
DEBUGOUT("ixgb_ee: Reading eeprom data\n");
- for (i = 0; i < IXGB_EEPROM_SIZE; i++) {
+ for(i = 0; i < IXGB_EEPROM_SIZE ; i++) {
uint16_t ee_data;
ee_data = ixgb_read_eeprom(hw, i);
checksum += ee_data;
@@ -461,12 +482,12 @@ boolean_t ixgb_get_eeprom_data(struct ixgb_hw * hw)
}
if ((ee_map->init_ctrl_reg_1 & le16_to_cpu(EEPROM_ICW1_SIGNATURE_MASK))
- != le16_to_cpu(EEPROM_ICW1_SIGNATURE_VALID)) {
+ != le16_to_cpu(EEPROM_ICW1_SIGNATURE_VALID)) {
DEBUGOUT("ixgb_ee: Signature invalid.\n");
- return (FALSE);
+ return(FALSE);
}
- return (TRUE);
+ return(TRUE);
}
/******************************************************************************
@@ -479,7 +500,8 @@ boolean_t ixgb_get_eeprom_data(struct ixgb_hw * hw)
* TRUE: eeprom signature was good and the eeprom read was successful
* FALSE: otherwise.
******************************************************************************/
-static boolean_t ixgb_check_and_get_eeprom_data(struct ixgb_hw *hw)
+static boolean_t
+ixgb_check_and_get_eeprom_data (struct ixgb_hw* hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
@@ -500,15 +522,16 @@ static boolean_t ixgb_check_and_get_eeprom_data(struct ixgb_hw *hw)
* Returns:
* Word at indexed offset in eeprom, if valid, 0 otherwise.
******************************************************************************/
-uint16_t ixgb_get_eeprom_word(struct ixgb_hw * hw, uint16_t index)
+uint16_t
+ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index)
{
if ((index < IXGB_EEPROM_SIZE) &&
- (ixgb_check_and_get_eeprom_data(hw) == TRUE)) {
- return (hw->eeprom[index]);
+ (ixgb_check_and_get_eeprom_data(hw) == TRUE)) {
+ return(hw->eeprom[index]);
}
- return (0);
+ return(0);
}
/******************************************************************************
@@ -519,7 +542,9 @@ uint16_t ixgb_get_eeprom_word(struct ixgb_hw * hw, uint16_t index)
*
* Returns: None.
******************************************************************************/
-void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t * mac_addr)
+void
+ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
+ uint8_t *mac_addr)
{
int i;
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
@@ -542,14 +567,15 @@ void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t * mac_addr)
* Returns:
* compatibility flags if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_compatibility(struct ixgb_hw *hw)
+uint16_t
+ixgb_get_ee_compatibility(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->compatibility);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->compatibility);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -560,13 +586,14 @@ uint16_t ixgb_get_ee_compatibility(struct ixgb_hw *hw)
* Returns:
* PBA number if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint32_t ixgb_get_ee_pba_number(struct ixgb_hw * hw)
+uint32_t
+ixgb_get_ee_pba_number(struct ixgb_hw *hw)
{
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(hw->eeprom[EEPROM_PBA_1_2_REG])
- | (le16_to_cpu(hw->eeprom[EEPROM_PBA_3_4_REG]) << 16));
+ | (le16_to_cpu(hw->eeprom[EEPROM_PBA_3_4_REG])<<16));
- return (0);
+ return(0);
}
/******************************************************************************
@@ -577,14 +604,15 @@ uint32_t ixgb_get_ee_pba_number(struct ixgb_hw * hw)
* Returns:
* Initialization Control Word 1 if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->init_ctrl_reg_1);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->init_ctrl_reg_1);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -595,14 +623,15 @@ uint16_t ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw * hw)
* Returns:
* Initialization Control Word 2 if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->init_ctrl_reg_2);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->init_ctrl_reg_2);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -613,14 +642,15 @@ uint16_t ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw * hw)
* Returns:
* Subsystem Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_subsystem_id(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_subsystem_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->subsystem_id);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->subsystem_id);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -631,14 +661,15 @@ uint16_t ixgb_get_ee_subsystem_id(struct ixgb_hw * hw)
* Returns:
* Sub Vendor Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_subvendor_id(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_subvendor_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->subvendor_id);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->subvendor_id);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -649,14 +680,15 @@ uint16_t ixgb_get_ee_subvendor_id(struct ixgb_hw * hw)
* Returns:
* Device Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_device_id(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_device_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->device_id);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->device_id);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -667,14 +699,15 @@ uint16_t ixgb_get_ee_device_id(struct ixgb_hw * hw)
* Returns:
* Device Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_vendor_id(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_vendor_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->vendor_id);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->vendor_id);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -685,14 +718,15 @@ uint16_t ixgb_get_ee_vendor_id(struct ixgb_hw * hw)
* Returns:
* SDP Register if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint16_t ixgb_get_ee_swdpins_reg(struct ixgb_hw * hw)
+uint16_t
+ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->swdpins_reg);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->swdpins_reg);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -703,14 +737,15 @@ uint16_t ixgb_get_ee_swdpins_reg(struct ixgb_hw * hw)
* Returns:
* D3 Power Management Bits if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint8_t ixgb_get_ee_d3_power(struct ixgb_hw * hw)
+uint8_t
+ixgb_get_ee_d3_power(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->d3_power);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->d3_power);
- return (0);
+ return(0);
}
/******************************************************************************
@@ -721,12 +756,13 @@ uint8_t ixgb_get_ee_d3_power(struct ixgb_hw * hw)
* Returns:
* D0 Power Management Bits if EEPROM contents are valid, 0 otherwise
******************************************************************************/
-uint8_t ixgb_get_ee_d0_power(struct ixgb_hw * hw)
+uint8_t
+ixgb_get_ee_d0_power(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return (ee_map->d0_power);
+ if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
+ return(ee_map->d0_power);
- return (0);
+ return(0);
}
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index e455a5f32164..e3ba1410af48 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -37,6 +37,12 @@ extern char ixgb_driver_version[];
extern int ixgb_up(struct ixgb_adapter *adapter);
extern void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
+extern void ixgb_reset(struct ixgb_adapter *adapter);
+extern int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
+extern int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
+extern void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
+extern void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
+extern void ixgb_update_stats(struct ixgb_adapter *adapter);
struct ixgb_stats {
char stat_string[ETH_GSTRING_LEN];
@@ -89,7 +95,7 @@ static struct ixgb_stats ixgb_gstrings_stats[] = {
sizeof(ixgb_gstrings_stats) / sizeof(struct ixgb_stats)
static int
-ixgb_ethtool_gset(struct net_device *netdev, struct ethtool_cmd *ecmd)
+ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
struct ixgb_adapter *adapter = netdev->priv;
ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
@@ -97,7 +103,7 @@ ixgb_ethtool_gset(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_FIBRE;
ecmd->transceiver = XCVR_EXTERNAL;
- if (netif_carrier_ok(adapter->netdev)) {
+ if(netif_carrier_ok(adapter->netdev)) {
ecmd->speed = SPEED_10000;
ecmd->duplex = DUPLEX_FULL;
} else {
@@ -110,86 +116,140 @@ ixgb_ethtool_gset(struct net_device *netdev, struct ethtool_cmd *ecmd)
}
static int
-ixgb_ethtool_sset(struct net_device *netdev, struct ethtool_cmd *ecmd)
+ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
struct ixgb_adapter *adapter = netdev->priv;
- if (ecmd->autoneg == AUTONEG_ENABLE ||
- ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
+ if(ecmd->autoneg == AUTONEG_ENABLE ||
+ ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
return -EINVAL;
- else {
+
+ if(netif_running(adapter->netdev)) {
ixgb_down(adapter, TRUE);
+ ixgb_reset(adapter);
ixgb_up(adapter);
- }
+ } else
+ ixgb_reset(adapter);
+
return 0;
}
static void
-ixgb_ethtool_gpause(struct net_device *dev,
- struct ethtool_pauseparam *epause)
+ixgb_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
{
- struct ixgb_adapter *adapter = dev->priv;
+ struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
-
- epause->autoneg = AUTONEG_DISABLE;
-
- if (hw->fc.type == ixgb_fc_rx_pause)
- epause->rx_pause = 1;
- else if (hw->fc.type == ixgb_fc_tx_pause)
- epause->tx_pause = 1;
- else if (hw->fc.type == ixgb_fc_full) {
- epause->rx_pause = 1;
- epause->tx_pause = 1;
+
+ pause->autoneg = AUTONEG_DISABLE;
+
+ if(hw->fc.type == ixgb_fc_rx_pause)
+ pause->rx_pause = 1;
+ else if(hw->fc.type == ixgb_fc_tx_pause)
+ pause->tx_pause = 1;
+ else if(hw->fc.type == ixgb_fc_full) {
+ pause->rx_pause = 1;
+ pause->tx_pause = 1;
}
}
static int
-ixgb_ethtool_spause(struct net_device *dev,
- struct ethtool_pauseparam *epause)
+ixgb_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
{
- struct ixgb_adapter *adapter = dev->priv;
+ struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
-
- if (epause->autoneg == AUTONEG_ENABLE)
+
+ if(pause->autoneg == AUTONEG_ENABLE)
return -EINVAL;
- if (epause->rx_pause && epause->tx_pause)
+ if(pause->rx_pause && pause->tx_pause)
hw->fc.type = ixgb_fc_full;
- else if (epause->rx_pause && !epause->tx_pause)
+ else if(pause->rx_pause && !pause->tx_pause)
hw->fc.type = ixgb_fc_rx_pause;
- else if (!epause->rx_pause && epause->tx_pause)
+ else if(!pause->rx_pause && pause->tx_pause)
hw->fc.type = ixgb_fc_tx_pause;
- else if (!epause->rx_pause && !epause->tx_pause)
+ else if(!pause->rx_pause && !pause->tx_pause)
hw->fc.type = ixgb_fc_none;
- ixgb_down(adapter, TRUE);
- ixgb_up(adapter);
-
+ if(netif_running(adapter->netdev)) {
+ ixgb_down(adapter, TRUE);
+ ixgb_up(adapter);
+ } else
+ ixgb_reset(adapter);
+
return 0;
}
-static void
-ixgb_ethtool_gdrvinfo(struct net_device *netdev,
- struct ethtool_drvinfo *drvinfo)
+static uint32_t
+ixgb_get_rx_csum(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
- strncpy(drvinfo->driver, ixgb_driver_name, 32);
- strncpy(drvinfo->version, ixgb_driver_version, 32);
- strncpy(drvinfo->fw_version, "N/A", 32);
- strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+ return adapter->rx_csum;
+}
+
+static int
+ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
+{
+ struct ixgb_adapter *adapter = netdev->priv;
+ adapter->rx_csum = data;
+
+ if(netif_running(netdev)) {
+ ixgb_down(adapter,TRUE);
+ ixgb_up(adapter);
+ } else
+ ixgb_reset(adapter);
+ return 0;
+}
+
+static uint32_t
+ixgb_get_tx_csum(struct net_device *netdev)
+{
+ return (netdev->features & NETIF_F_HW_CSUM) != 0;
}
+static int
+ixgb_set_tx_csum(struct net_device *netdev, uint32_t data)
+{
+ if (data)
+ netdev->features |= NETIF_F_HW_CSUM;
+ else
+ netdev->features &= ~NETIF_F_HW_CSUM;
+
+ return 0;
+}
+
+#ifdef NETIF_F_TSO
+static int
+ixgb_set_tso(struct net_device *netdev, uint32_t data)
+{
+ if(data)
+ netdev->features |= NETIF_F_TSO;
+ else
+ netdev->features &= ~NETIF_F_TSO;
+ return 0;
+}
+#endif /* NETIF_F_TSO */
+
#define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_
+
+static int
+ixgb_get_regs_len(struct net_device *netdev)
+{
+#define IXGB_REG_DUMP_LEN 136*sizeof(uint32_t)
+ return IXGB_REG_DUMP_LEN;
+}
+
static void
-ixgb_ethtool_gregs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
+ixgb_get_regs(struct net_device *netdev,
+ struct ethtool_regs *regs, void *p)
{
- struct ixgb_adapter *adapter = dev->priv;
+ struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
- uint32_t *reg = buf;
+ uint32_t *reg = p;
uint32_t *reg_start = reg;
uint8_t i;
- regs->version =
- (adapter->hw.device_id << 16) | adapter->hw.subsystem_id;
+ regs->version = (adapter->hw.device_id << 16) | adapter->hw.subsystem_id;
/* General Registers */
*reg++ = IXGB_READ_REG(hw, CTRL0); /* 0 */
@@ -219,8 +279,8 @@ ixgb_ethtool_gregs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
*reg++ = IXGB_READ_REG(hw, RXCSUM); /* 20 */
for (i = 0; i < IXGB_RAR_ENTRIES; i++) {
- *reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
- *reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
+ *reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
+ *reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
}
/* Transmit */
@@ -316,73 +376,222 @@ ixgb_ethtool_gregs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
}
static int
-ixgb_ethtool_geeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 *data)
+ixgb_get_eeprom_len(struct net_device *netdev)
{
- struct ixgb_adapter *adapter = dev->priv;
+ /* return size in bytes */
+ return (IXGB_EEPROM_SIZE << 1);
+}
+
+static int
+ixgb_get_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, uint8_t *bytes)
+{
+ struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
+ uint16_t *eeprom_buff;
+ int i, max_len, first_word, last_word;
+ int ret_val = 0;
+
+ if(eeprom->len == 0) {
+ ret_val = -EINVAL;
+ goto geeprom_error;
+ }
eeprom->magic = hw->vendor_id | (hw->device_id << 16);
- /* use our function to read the eeprom and update our cache */
- ixgb_get_eeprom_data(hw);
- memcpy(data, (char *)hw->eeprom + eeprom->offset, eeprom->len);
- return 0;
+ max_len = ixgb_get_eeprom_len(netdev);
+
+ if(eeprom->offset > eeprom->offset + eeprom->len) {
+ ret_val = -EINVAL;
+ goto geeprom_error;
+ }
+
+ if((eeprom->offset + eeprom->len) > max_len)
+ eeprom->len = (max_len - eeprom->offset);
+
+ first_word = eeprom->offset >> 1;
+ last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+
+ eeprom_buff = kmalloc(sizeof(uint16_t) *
+ (last_word - first_word + 1), GFP_KERNEL);
+ if(!eeprom_buff)
+ return -ENOMEM;
+
+ /* note the eeprom was good because the driver loaded */
+ for(i = 0; i <= (last_word - first_word); i++) {
+ eeprom_buff[i] = ixgb_get_eeprom_word(hw, (first_word + i));
+ }
+
+ memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
+ eeprom->len);
+ kfree(eeprom_buff);
+
+geeprom_error:
+ return ret_val;
}
static int
-ixgb_ethtool_seeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 *data)
+ixgb_set_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, uint8_t *bytes)
{
- struct ixgb_adapter *adapter = dev->priv;
+ struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
- /* We are under rtnl, so static is OK */
- static uint16_t eeprom_buff[IXGB_EEPROM_SIZE];
- int i, first_word, last_word;
- char *ptr;
+ uint16_t *eeprom_buff;
+ void *ptr;
+ int max_len, first_word, last_word;
+ uint16_t i;
+
+ if(eeprom->len == 0)
+ return -EINVAL;
- if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+ if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
return -EFAULT;
+ max_len = ixgb_get_eeprom_len(netdev);
+
+ if(eeprom->offset > eeprom->offset + eeprom->len)
+ return -EINVAL;
+
+ if((eeprom->offset + eeprom->len) > max_len)
+ eeprom->len = (max_len - eeprom->offset);
+
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
- ptr = (char *)eeprom_buff;
+ eeprom_buff = kmalloc(max_len, GFP_KERNEL);
+ if(!eeprom_buff)
+ return -ENOMEM;
- if (eeprom->offset & 1) {
+ ptr = (void *)eeprom_buff;
+
+ if(eeprom->offset & 1) {
/* need read/modify/write of first changed EEPROM word */
/* only the second byte of the word is being modified */
eeprom_buff[0] = ixgb_read_eeprom(hw, first_word);
ptr++;
}
- if ((eeprom->offset + eeprom->len) & 1) {
+ if((eeprom->offset + eeprom->len) & 1) {
/* need read/modify/write of last changed EEPROM word */
/* only the first byte of the word is being modified */
- eeprom_buff[last_word - first_word]
- = ixgb_read_eeprom(hw, last_word);
+ eeprom_buff[last_word - first_word]
+ = ixgb_read_eeprom(hw, last_word);
}
- memcpy(ptr, data, eeprom->len);
- for (i = 0; i <= (last_word - first_word); i++)
+ memcpy(ptr, bytes, eeprom->len);
+ for(i = 0; i <= (last_word - first_word); i++)
ixgb_write_eeprom(hw, first_word + i, eeprom_buff[i]);
/* Update the checksum over the first part of the EEPROM if needed */
- if (first_word <= EEPROM_CHECKSUM_REG)
+ if(first_word <= EEPROM_CHECKSUM_REG)
ixgb_update_eeprom_checksum(hw);
+ kfree(eeprom_buff);
return 0;
}
+static void
+ixgb_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct ixgb_adapter *adapter = netdev->priv;
+
+ strncpy(drvinfo->driver, ixgb_driver_name, 32);
+ strncpy(drvinfo->version, ixgb_driver_version, 32);
+ strncpy(drvinfo->fw_version, "N/A", 32);
+ strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+ drvinfo->n_stats = IXGB_STATS_LEN;
+ drvinfo->regdump_len = ixgb_get_regs_len(netdev);
+ drvinfo->eedump_len = ixgb_get_eeprom_len(netdev);
+}
+
+static void
+ixgb_get_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_desc_ring *txdr = &adapter->tx_ring;
+ struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
+
+ ring->rx_max_pending = MAX_RXD;
+ ring->tx_max_pending = MAX_TXD;
+ ring->rx_mini_max_pending = 0;
+ ring->rx_jumbo_max_pending = 0;
+ ring->rx_pending = rxdr->count;
+ ring->tx_pending = txdr->count;
+ ring->rx_mini_pending = 0;
+ ring->rx_jumbo_pending = 0;
+}
+
+static int
+ixgb_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct ixgb_adapter *adapter = netdev->priv;
+ struct ixgb_desc_ring *txdr = &adapter->tx_ring;
+ struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
+ struct ixgb_desc_ring tx_old, tx_new, rx_old, rx_new;
+ int err;
+
+ tx_old = adapter->tx_ring;
+ rx_old = adapter->rx_ring;
+
+ if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+ return -EINVAL;
+
+ if(netif_running(adapter->netdev))
+ ixgb_down(adapter,TRUE);
+
+ rxdr->count = max(ring->rx_pending,(uint32_t)MIN_RXD);
+ rxdr->count = min(rxdr->count,(uint32_t)MAX_RXD);
+ IXGB_ROUNDUP(rxdr->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
+
+ txdr->count = max(ring->tx_pending,(uint32_t)MIN_TXD);
+ txdr->count = min(txdr->count,(uint32_t)MAX_TXD);
+ IXGB_ROUNDUP(txdr->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
+
+ if(netif_running(adapter->netdev)) {
+ /* Try to get new resources before deleting old */
+ if((err = ixgb_setup_rx_resources(adapter)))
+ goto err_setup_rx;
+ if((err = ixgb_setup_tx_resources(adapter)))
+ goto err_setup_tx;
+
+ /* save the new, restore the old in order to free it,
+ * then restore the new back again */
+
+ rx_new = adapter->rx_ring;
+ tx_new = adapter->tx_ring;
+ adapter->rx_ring = rx_old;
+ adapter->tx_ring = tx_old;
+ ixgb_free_rx_resources(adapter);
+ ixgb_free_tx_resources(adapter);
+ adapter->rx_ring = rx_new;
+ adapter->tx_ring = tx_new;
+ if((err = ixgb_up(adapter)))
+ return err;
+ }
+
+ return 0;
+err_setup_tx:
+ ixgb_free_rx_resources(adapter);
+err_setup_rx:
+ adapter->rx_ring = rx_old;
+ adapter->tx_ring = tx_old;
+ ixgb_up(adapter);
+ return err;
+}
+
/* toggle LED 4 times per second = 2 "blinks" per second */
#define IXGB_ID_INTERVAL (HZ/4)
/* bit defines for adapter->led_status */
#define IXGB_LED_ON 0
-static void ixgb_led_blink_callback(unsigned long data)
+static void
+ixgb_led_blink_callback(unsigned long data)
{
struct ixgb_adapter *adapter = (struct ixgb_adapter *)data;
- if (test_and_change_bit(IXGB_LED_ON, &adapter->led_status))
+ if(test_and_change_bit(IXGB_LED_ON, &adapter->led_status))
ixgb_led_off(&adapter->hw);
else
ixgb_led_on(&adapter->hw);
@@ -391,10 +600,14 @@ static void ixgb_led_blink_callback(unsigned long data)
}
static int
-ixgb_ethtool_led_blink(struct net_device *netdev, u32 data)
+ixgb_phys_id(struct net_device *netdev, uint32_t data)
{
struct ixgb_adapter *adapter = netdev->priv;
- if (!adapter->blink_timer.function) {
+
+ if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
+ data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
+
+ if(!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
adapter->blink_timer.function = ixgb_led_blink_callback;
adapter->blink_timer.data = (unsigned long)adapter;
@@ -403,7 +616,7 @@ ixgb_ethtool_led_blink(struct net_device *netdev, u32 data)
mod_timer(&adapter->blink_timer, jiffies);
set_current_state(TASK_INTERRUPTIBLE);
- if (data)
+ if(data)
schedule_timeout(data * HZ);
else
schedule_timeout(MAX_SCHEDULE_TIMEOUT);
@@ -415,141 +628,74 @@ ixgb_ethtool_led_blink(struct net_device *netdev, u32 data)
return 0;
}
-static int ixgb_nway_reset(struct net_device *netdev)
-{
- if (netif_running(netdev)) {
- struct ixgb_adapter *adapter = netdev->priv;
- ixgb_down(adapter, TRUE);
- ixgb_up(adapter);
- }
- return 0;
-}
-
-static int ixgb_get_stats_count(struct net_device *dev)
+static int
+ixgb_get_stats_count(struct net_device *netdev)
{
return IXGB_STATS_LEN;
}
-static void ixgb_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+static void
+ixgb_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats, uint64_t *data)
{
+ struct ixgb_adapter *adapter = netdev->priv;
int i;
- for (i = 0; i < IXGB_STATS_LEN; i++) {
- memcpy(data + i * ETH_GSTRING_LEN,
- ixgb_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
- }
-}
-static int ixgb_get_regs_len(struct net_device *dev)
-{
- return 136*sizeof(uint32_t);
-}
-
-static int ixgb_get_eeprom_len(struct net_device *dev)
-{
- /* return size in bytes */
- return (IXGB_EEPROM_SIZE << 1);
+ ixgb_update_stats(adapter);
+ for(i = 0; i < IXGB_STATS_LEN; i++) {
+ char *p = (char *)adapter+ixgb_gstrings_stats[i].stat_offset;
+ data[i] = (ixgb_gstrings_stats[i].sizeof_stat ==
+ sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
+ }
}
-static void get_ethtool_stats(struct net_device *dev,
- struct ethtool_stats *stats, u64 *data)
+static void
+ixgb_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
{
- struct ixgb_adapter *adapter = dev->priv;
int i;
- for (i = 0; i < IXGB_STATS_LEN; i++) {
- void *p = (char *)adapter + ixgb_gstrings_stats[i].stat_offset;
- stats->data[i] =
- (ixgb_gstrings_stats[i].sizeof_stat == sizeof(uint64_t))
- ? *(uint64_t *) p
- : *(uint32_t *) p;
+ switch(stringset) {
+ case ETH_SS_STATS:
+ for(i=0; i < IXGB_STATS_LEN; i++) {
+ memcpy(data + i * ETH_GSTRING_LEN,
+ ixgb_gstrings_stats[i].stat_string,
+ ETH_GSTRING_LEN);
+ }
+ break;
}
}
-static u32 ixgb_get_rx_csum(struct net_device *dev)
-{
- struct ixgb_adapter *adapter = dev->priv;
- return adapter->rx_csum;
-}
-
-static int ixgb_set_rx_csum(struct net_device *dev, u32 sum)
-{
- struct ixgb_adapter *adapter = dev->priv;
- adapter->rx_csum = sum;
- ixgb_down(adapter, TRUE);
- ixgb_up(adapter);
- return 0;
-}
-
-static u32 ixgb_get_tx_csum(struct net_device *dev)
-{
- return (dev->features & NETIF_F_HW_CSUM) != 0;
-}
-
-static int ixgb_set_tx_csum(struct net_device *dev, u32 sum)
-{
- if (sum)
- dev->features |= NETIF_F_HW_CSUM;
- else
- dev->features &= ~NETIF_F_HW_CSUM;
- return 0;
-}
-
-static u32 ixgb_get_sg(struct net_device *dev)
-{
- return (dev->features & NETIF_F_SG) != 0;
-}
-
-static int ixgb_set_sg(struct net_device *dev, u32 sum)
-{
- if (sum)
- dev->features |= NETIF_F_SG;
- else
- dev->features &= ~NETIF_F_SG;
- return 0;
-}
-
-#ifdef NETIF_F_TSO
-static u32 ixgb_get_tso(struct net_device *dev)
-{
- return (dev->features & NETIF_F_TSO) != 0;
-}
-
-static int ixgb_set_tso(struct net_device *dev, u32 sum)
-{
- if (sum)
- dev->features |= NETIF_F_TSO;
- else
- dev->features &= ~NETIF_F_TSO;
- return 0;
-}
-#endif
-
struct ethtool_ops ixgb_ethtool_ops = {
- .get_settings = ixgb_ethtool_gset,
- .set_settings = ixgb_ethtool_sset,
- .get_drvinfo = ixgb_ethtool_gdrvinfo,
- .nway_reset = ixgb_nway_reset,
- .get_link = ethtool_op_get_link,
- .phys_id = ixgb_ethtool_led_blink,
- .get_strings = ixgb_get_strings,
- .get_stats_count = ixgb_get_stats_count,
- .get_regs = ixgb_ethtool_gregs,
+ .get_settings = ixgb_get_settings,
+ .set_settings = ixgb_set_settings,
+ .get_drvinfo = ixgb_get_drvinfo,
.get_regs_len = ixgb_get_regs_len,
+ .get_regs = ixgb_get_regs,
+ .get_link = ethtool_op_get_link,
.get_eeprom_len = ixgb_get_eeprom_len,
- .get_eeprom = ixgb_ethtool_geeprom,
- .set_eeprom = ixgb_ethtool_seeprom,
- .get_pauseparam = ixgb_ethtool_gpause,
- .set_pauseparam = ixgb_ethtool_spause,
- .get_ethtool_stats = get_ethtool_stats,
+ .get_eeprom = ixgb_get_eeprom,
+ .set_eeprom = ixgb_set_eeprom,
+ .get_ringparam = ixgb_get_ringparam,
+ .set_ringparam = ixgb_set_ringparam,
+ .get_pauseparam = ixgb_get_pauseparam,
+ .set_pauseparam = ixgb_set_pauseparam,
.get_rx_csum = ixgb_get_rx_csum,
.set_rx_csum = ixgb_set_rx_csum,
.get_tx_csum = ixgb_get_tx_csum,
.set_tx_csum = ixgb_set_tx_csum,
- .get_sg = ixgb_get_sg,
- .set_sg = ixgb_set_sg,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
#ifdef NETIF_F_TSO
- .get_tso = ixgb_get_tso,
+ .get_tso = ethtool_op_get_tso,
.set_tso = ixgb_set_tso,
#endif
+ .get_strings = ixgb_get_strings,
+ .phys_id = ixgb_phys_id,
+ .get_stats_count = ixgb_get_stats_count,
+ .get_ethtool_stats = ixgb_get_ethtool_stats,
};
+
+void ixgb_set_ethtool_ops(struct net_device *netdev)
+{
+ SET_ETHTOOL_OPS(netdev, &ixgb_ethtool_ops);
+}
diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
index b9998af78ddd..230f0d80d2f2 100644
--- a/drivers/net/ixgb/ixgb_hw.c
+++ b/drivers/net/ixgb/ixgb_hw.c
@@ -53,9 +53,14 @@ uint32_t ixgb_mac_reset(struct ixgb_hw *hw)
{
uint32_t ctrl_reg;
- ctrl_reg = IXGB_CTRL0_RST | IXGB_CTRL0_SDP3_DIR | /* All pins are Output=1 */
- IXGB_CTRL0_SDP2_DIR | IXGB_CTRL0_SDP1_DIR | IXGB_CTRL0_SDP0_DIR | IXGB_CTRL0_SDP3 | /* Initial value 1101 */
- IXGB_CTRL0_SDP2 | IXGB_CTRL0_SDP0;
+ ctrl_reg = IXGB_CTRL0_RST |
+ IXGB_CTRL0_SDP3_DIR | /* All pins are Output=1 */
+ IXGB_CTRL0_SDP2_DIR |
+ IXGB_CTRL0_SDP1_DIR |
+ IXGB_CTRL0_SDP0_DIR |
+ IXGB_CTRL0_SDP3 | /* Initial value 1101 */
+ IXGB_CTRL0_SDP2 |
+ IXGB_CTRL0_SDP0;
#ifdef HP_ZX1
/* Workaround for 82597EX reset errata */
@@ -84,7 +89,8 @@ uint32_t ixgb_mac_reset(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-boolean_t ixgb_adapter_stop(struct ixgb_hw * hw)
+boolean_t
+ixgb_adapter_stop(struct ixgb_hw *hw)
{
uint32_t ctrl_reg;
uint32_t icr_reg;
@@ -94,7 +100,7 @@ boolean_t ixgb_adapter_stop(struct ixgb_hw * hw)
/* If we are stopped or resetting exit gracefully and wait to be
* started again before accessing the hardware.
*/
- if (hw->adapter_stopped) {
+ if(hw->adapter_stopped) {
DEBUGOUT("Exiting because the adapter is already stopped!!!\n");
return FALSE;
}
@@ -135,6 +141,7 @@ boolean_t ixgb_adapter_stop(struct ixgb_hw * hw)
return (ctrl_reg & IXGB_CTRL0_RST);
}
+
/******************************************************************************
* Identifies the vendor of the optics module on the adapter. The SR adapters
* support two different types of XPAK optics, so it is necessary to determine
@@ -144,7 +151,8 @@ boolean_t ixgb_adapter_stop(struct ixgb_hw * hw)
*
* Returns: the vendor of the XPAK optics module.
*****************************************************************************/
-static ixgb_xpak_vendor ixgb_identify_xpak_vendor(struct ixgb_hw *hw)
+static ixgb_xpak_vendor
+ixgb_identify_xpak_vendor(struct ixgb_hw *hw)
{
uint32_t i;
uint16_t vendor_name[5];
@@ -183,7 +191,8 @@ static ixgb_xpak_vendor ixgb_identify_xpak_vendor(struct ixgb_hw *hw)
*
* Returns: the phy type of the adapter.
*****************************************************************************/
-static ixgb_phy_type ixgb_identify_phy(struct ixgb_hw *hw)
+static ixgb_phy_type
+ixgb_identify_phy(struct ixgb_hw *hw)
{
ixgb_phy_type phy_type;
ixgb_xpak_vendor xpak_vendor;
@@ -210,7 +219,10 @@ static ixgb_phy_type ixgb_identify_phy(struct ixgb_hw *hw)
phy_type = ixgb_phy_type_g6005;
}
break;
-
+ case IXGB_DEVICE_ID_82597EX_LR:
+ DEBUGOUT("Identified G6104 optics\n");
+ phy_type = ixgb_phy_type_g6104;
+ break;
default:
DEBUGOUT("Unknown physical layer module\n");
phy_type = ixgb_phy_type_unknown;
@@ -237,7 +249,8 @@ static ixgb_phy_type ixgb_identify_phy(struct ixgb_hw *hw)
* TRUE if successful,
* FALSE if unrecoverable problems were encountered.
*****************************************************************************/
-boolean_t ixgb_init_hw(struct ixgb_hw * hw)
+boolean_t
+ixgb_init_hw(struct ixgb_hw *hw)
{
uint32_t i;
uint32_t ctrl_reg;
@@ -266,7 +279,7 @@ boolean_t ixgb_init_hw(struct ixgb_hw * hw)
msec_delay(IXGB_DELAY_AFTER_EE_RESET);
if (ixgb_get_eeprom_data(hw) == FALSE) {
- return (FALSE);
+ return(FALSE);
}
/* Use the device id to determine the type of phy/transceiver. */
@@ -284,7 +297,7 @@ boolean_t ixgb_init_hw(struct ixgb_hw * hw)
*/
if (!mac_addr_valid(hw->curr_mac_addr)) {
DEBUGOUT("MAC address invalid after ixgb_init_rx_addrs\n");
- return (FALSE);
+ return(FALSE);
}
/* tell the routines in this file they can access hardware again */
@@ -295,7 +308,7 @@ boolean_t ixgb_init_hw(struct ixgb_hw * hw)
/* Zero out the Multicast HASH table */
DEBUGOUT("Zeroing the MTA\n");
- for (i = 0; i < IXGB_MC_TBL_SIZE; i++)
+ for(i = 0; i < IXGB_MC_TBL_SIZE; i++)
IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0);
/* Zero out the VLAN Filter Table Array */
@@ -322,7 +335,8 @@ boolean_t ixgb_init_hw(struct ixgb_hw * hw)
* of the receive addresss registers. Clears the multicast table. Assumes
* the receiver is in reset when the routine is called.
*****************************************************************************/
-void ixgb_init_rx_addrs(struct ixgb_hw *hw)
+void
+ixgb_init_rx_addrs(struct ixgb_hw *hw)
{
uint32_t i;
@@ -360,7 +374,7 @@ void ixgb_init_rx_addrs(struct ixgb_hw *hw)
/* Zero out the other 15 receive addresses. */
DEBUGOUT("Clearing RAR[1-15]\n");
- for (i = 1; i < IXGB_RAR_ENTRIES; i++) {
+ for(i = 1; i < IXGB_RAR_ENTRIES; i++) {
IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
}
@@ -383,12 +397,13 @@ void ixgb_init_rx_addrs(struct ixgb_hw *hw)
*****************************************************************************/
void
ixgb_mc_addr_list_update(struct ixgb_hw *hw,
- uint8_t * mc_addr_list,
- uint32_t mc_addr_count, uint32_t pad)
+ uint8_t *mc_addr_list,
+ uint32_t mc_addr_count,
+ uint32_t pad)
{
uint32_t hash_value;
uint32_t i;
- uint32_t rar_used_count = 1; /* RAR[0] is used for our MAC address */
+ uint32_t rar_used_count = 1; /* RAR[0] is used for our MAC address */
DEBUGFUNC("ixgb_mc_addr_list_update");
@@ -397,19 +412,19 @@ ixgb_mc_addr_list_update(struct ixgb_hw *hw,
/* Clear RAR[1-15] */
DEBUGOUT(" Clearing RAR[1-15]\n");
- for (i = rar_used_count; i < IXGB_RAR_ENTRIES; i++) {
+ for(i = rar_used_count; i < IXGB_RAR_ENTRIES; i++) {
IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
}
/* Clear the MTA */
DEBUGOUT(" Clearing MTA\n");
- for (i = 0; i < IXGB_MC_TBL_SIZE; i++) {
+ for(i = 0; i < IXGB_MC_TBL_SIZE; i++) {
IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0);
}
/* Add the new addresses */
- for (i = 0; i < mc_addr_count; i++) {
+ for(i = 0; i < mc_addr_count; i++) {
DEBUGOUT(" Adding the multicast addresses:\n");
DEBUGOUT7(" MC Addr #%d =%.2X %.2X %.2X %.2X %.2X %.2X\n", i,
mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)],
@@ -427,7 +442,7 @@ ixgb_mc_addr_list_update(struct ixgb_hw *hw,
/* Place this multicast address in the RAR if there is room, *
* else put it in the MTA
*/
- if (rar_used_count < IXGB_RAR_ENTRIES) {
+ if(rar_used_count < IXGB_RAR_ENTRIES) {
ixgb_rar_set(hw,
mc_addr_list +
(i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)),
@@ -460,7 +475,9 @@ ixgb_mc_addr_list_update(struct ixgb_hw *hw,
* Returns:
* The hash value
*****************************************************************************/
-static uint32_t ixgb_hash_mc_addr(struct ixgb_hw *hw, uint8_t * mc_addr)
+static uint32_t
+ixgb_hash_mc_addr(struct ixgb_hw *hw,
+ uint8_t *mc_addr)
{
uint32_t hash_value = 0;
@@ -506,7 +523,9 @@ static uint32_t ixgb_hash_mc_addr(struct ixgb_hw *hw, uint8_t * mc_addr)
* hw - Struct containing variables accessed by shared code
* hash_value - Multicast address hash value
*****************************************************************************/
-static void ixgb_mta_set(struct ixgb_hw *hw, uint32_t hash_value)
+static void
+ixgb_mta_set(struct ixgb_hw *hw,
+ uint32_t hash_value)
{
uint32_t hash_bit, hash_reg;
uint32_t mta_reg;
@@ -538,7 +557,10 @@ static void ixgb_mta_set(struct ixgb_hw *hw, uint32_t hash_value)
* addr - Address to put into receive address register
* index - Receive address register to write
*****************************************************************************/
-void ixgb_rar_set(struct ixgb_hw *hw, uint8_t * addr, uint32_t index)
+void
+ixgb_rar_set(struct ixgb_hw *hw,
+ uint8_t *addr,
+ uint32_t index)
{
uint32_t rar_low, rar_high;
@@ -548,11 +570,13 @@ void ixgb_rar_set(struct ixgb_hw *hw, uint8_t * addr, uint32_t index)
* from network order (big endian) to little endian
*/
rar_low = ((uint32_t) addr[0] |
- ((uint32_t) addr[1] << 8) |
- ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24));
+ ((uint32_t)addr[1] << 8) |
+ ((uint32_t)addr[2] << 16) |
+ ((uint32_t)addr[3] << 24));
rar_high = ((uint32_t) addr[4] |
- ((uint32_t) addr[5] << 8) | IXGB_RAH_AV);
+ ((uint32_t)addr[5] << 8) |
+ IXGB_RAH_AV);
IXGB_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
IXGB_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
@@ -566,7 +590,10 @@ void ixgb_rar_set(struct ixgb_hw *hw, uint8_t * addr, uint32_t index)
* offset - Offset in VLAN filer table to write
* value - Value to write into VLAN filter table
*****************************************************************************/
-void ixgb_write_vfta(struct ixgb_hw *hw, uint32_t offset, uint32_t value)
+void
+ixgb_write_vfta(struct ixgb_hw *hw,
+ uint32_t offset,
+ uint32_t value)
{
IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, value);
return;
@@ -577,11 +604,12 @@ void ixgb_write_vfta(struct ixgb_hw *hw, uint32_t offset, uint32_t value)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void ixgb_clear_vfta(struct ixgb_hw *hw)
+void
+ixgb_clear_vfta(struct ixgb_hw *hw)
{
uint32_t offset;
- for (offset = 0; offset < IXGB_VLAN_FILTER_TBL_SIZE; offset++)
+ for(offset = 0; offset < IXGB_VLAN_FILTER_TBL_SIZE; offset++)
IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
return;
}
@@ -592,10 +620,11 @@ void ixgb_clear_vfta(struct ixgb_hw *hw)
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-boolean_t ixgb_setup_fc(struct ixgb_hw * hw)
+boolean_t
+ixgb_setup_fc(struct ixgb_hw *hw)
{
uint32_t ctrl_reg;
- uint32_t pap_reg = 0; /* by default, assume no pause time */
+ uint32_t pap_reg = 0; /* by default, assume no pause time */
boolean_t status = TRUE;
DEBUGFUNC("ixgb_setup_fc");
@@ -660,16 +689,16 @@ boolean_t ixgb_setup_fc(struct ixgb_hw * hw)
* ability to transmit pause frames in not enabled, then these
* registers will be set to 0.
*/
- if (!(hw->fc.type & ixgb_fc_tx_pause)) {
+ if(!(hw->fc.type & ixgb_fc_tx_pause)) {
IXGB_WRITE_REG(hw, FCRTL, 0);
IXGB_WRITE_REG(hw, FCRTH, 0);
} else {
- /* We need to set up the Receive Threshold high and low water
- * marks as well as (optionally) enabling the transmission of XON frames.
- */
- if (hw->fc.send_xon) {
+ /* We need to set up the Receive Threshold high and low water
+ * marks as well as (optionally) enabling the transmission of XON
+ * frames. */
+ if(hw->fc.send_xon) {
IXGB_WRITE_REG(hw, FCRTL,
- (hw->fc.low_water | IXGB_FCRTL_XONE));
+ (hw->fc.low_water | IXGB_FCRTL_XONE));
} else {
IXGB_WRITE_REG(hw, FCRTL, hw->fc.low_water);
}
@@ -694,9 +723,10 @@ boolean_t ixgb_setup_fc(struct ixgb_hw * hw)
* read command.
*****************************************************************************/
uint16_t
-ixgb_read_phy_reg(struct ixgb_hw * hw,
- uint32_t reg_address,
- uint32_t phy_address, uint32_t device_type)
+ixgb_read_phy_reg(struct ixgb_hw *hw,
+ uint32_t reg_address,
+ uint32_t phy_address,
+ uint32_t device_type)
{
uint32_t i;
uint32_t data;
@@ -721,7 +751,8 @@ ixgb_read_phy_reg(struct ixgb_hw * hw,
** from the CPU Write to the Ready bit assertion.
**************************************************************/
- for (i = 0; i < 10; i++) {
+ for(i = 0; i < 10; i++)
+ {
udelay(10);
command = IXGB_READ_REG(hw, MSCA);
@@ -747,7 +778,8 @@ ixgb_read_phy_reg(struct ixgb_hw * hw,
** from the CPU Write to the Ready bit assertion.
**************************************************************/
- for (i = 0; i < 10; i++) {
+ for(i = 0; i < 10; i++)
+ {
udelay(10);
command = IXGB_READ_REG(hw, MSCA);
@@ -763,7 +795,7 @@ ixgb_read_phy_reg(struct ixgb_hw * hw,
*/
data = IXGB_READ_REG(hw, MSRWD);
data >>= IXGB_MSRWD_READ_DATA_SHIFT;
- return ((uint16_t) data);
+ return((uint16_t) data);
}
/******************************************************************************
@@ -785,8 +817,10 @@ ixgb_read_phy_reg(struct ixgb_hw * hw,
*****************************************************************************/
void
ixgb_write_phy_reg(struct ixgb_hw *hw,
- uint32_t reg_address,
- uint32_t phy_address, uint32_t device_type, uint16_t data)
+ uint32_t reg_address,
+ uint32_t phy_address,
+ uint32_t device_type,
+ uint16_t data)
{
uint32_t i;
uint32_t command = 0;
@@ -796,24 +830,25 @@ ixgb_write_phy_reg(struct ixgb_hw *hw,
ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE);
/* Put the data in the MDIO Read/Write Data register */
- IXGB_WRITE_REG(hw, MSRWD, (uint32_t) data);
+ IXGB_WRITE_REG(hw, MSRWD, (uint32_t)data);
/* Setup and write the address cycle command */
- command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
- (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
- (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
- (IXGB_MSCA_ADDR_CYCLE | IXGB_MSCA_MDI_COMMAND));
+ command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
+ (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
+ (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
+ (IXGB_MSCA_ADDR_CYCLE | IXGB_MSCA_MDI_COMMAND));
IXGB_WRITE_REG(hw, MSCA, command);
- /**************************************************************
- ** Check every 10 usec to see if the address cycle completed
- ** The COMMAND bit will clear when the operation is complete.
- ** This may take as long as 64 usecs (we'll wait 100 usecs max)
- ** from the CPU Write to the Ready bit assertion.
- **************************************************************/
+ /**************************************************************
+ ** Check every 10 usec to see if the address cycle completed
+ ** The COMMAND bit will clear when the operation is complete.
+ ** This may take as long as 64 usecs (we'll wait 100 usecs max)
+ ** from the CPU Write to the Ready bit assertion.
+ **************************************************************/
- for (i = 0; i < 10; i++) {
+ for(i = 0; i < 10; i++)
+ {
udelay(10);
command = IXGB_READ_REG(hw, MSCA);
@@ -825,21 +860,22 @@ ixgb_write_phy_reg(struct ixgb_hw *hw,
ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0);
/* Address cycle complete, setup and write the write command */
- command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
- (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
- (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
- (IXGB_MSCA_WRITE | IXGB_MSCA_MDI_COMMAND));
+ command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
+ (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) |
+ (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) |
+ (IXGB_MSCA_WRITE | IXGB_MSCA_MDI_COMMAND));
IXGB_WRITE_REG(hw, MSCA, command);
- /**************************************************************
- ** Check every 10 usec to see if the read command completed
- ** The COMMAND bit will clear when the operation is complete.
- ** The write may take as long as 64 usecs (we'll wait 100 usecs max)
- ** from the CPU Write to the Ready bit assertion.
- **************************************************************/
+ /**************************************************************
+ ** Check every 10 usec to see if the read command completed
+ ** The COMMAND bit will clear when the operation is complete.
+ ** The write may take as long as 64 usecs (we'll wait 100 usecs max)
+ ** from the CPU Write to the Ready bit assertion.
+ **************************************************************/
- for (i = 0; i < 10; i++) {
+ for(i = 0; i < 10; i++)
+ {
udelay(10);
command = IXGB_READ_REG(hw, MSCA);
@@ -860,7 +896,8 @@ ixgb_write_phy_reg(struct ixgb_hw *hw,
*
* Called by any function that needs to check the link status of the adapter.
*****************************************************************************/
-void ixgb_check_for_link(struct ixgb_hw *hw)
+void
+ixgb_check_for_link(struct ixgb_hw *hw)
{
uint32_t status_reg;
uint32_t xpcss_reg;
@@ -922,14 +959,15 @@ boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
+void
+ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
{
volatile uint32_t temp_reg;
DEBUGFUNC("ixgb_clear_hw_cntrs");
/* if we are stopped or resetting exit gracefully */
- if (hw->adapter_stopped) {
+ if(hw->adapter_stopped) {
DEBUGOUT("Exiting because the adapter is stopped!!!\n");
return;
}
@@ -1002,7 +1040,8 @@ void ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void ixgb_led_on(struct ixgb_hw *hw)
+void
+ixgb_led_on(struct ixgb_hw *hw)
{
uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
@@ -1017,7 +1056,8 @@ void ixgb_led_on(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void ixgb_led_off(struct ixgb_hw *hw)
+void
+ixgb_led_off(struct ixgb_hw *hw)
{
uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
@@ -1032,18 +1072,19 @@ void ixgb_led_off(struct ixgb_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void ixgb_get_bus_info(struct ixgb_hw *hw)
+static void
+ixgb_get_bus_info(struct ixgb_hw *hw)
{
uint32_t status_reg;
status_reg = IXGB_READ_REG(hw, STATUS);
hw->bus.type = (status_reg & IXGB_STATUS_PCIX_MODE) ?
- ixgb_bus_type_pcix : ixgb_bus_type_pci;
+ ixgb_bus_type_pcix : ixgb_bus_type_pci;
if (hw->bus.type == ixgb_bus_type_pci) {
hw->bus.speed = (status_reg & IXGB_STATUS_PCI_SPD) ?
- ixgb_bus_speed_66 : ixgb_bus_speed_33;
+ ixgb_bus_speed_66 : ixgb_bus_speed_33;
} else {
switch (status_reg & IXGB_STATUS_PCIX_SPD_MASK) {
case IXGB_STATUS_PCIX_SPD_66:
@@ -1062,7 +1103,7 @@ static void ixgb_get_bus_info(struct ixgb_hw *hw)
}
hw->bus.width = (status_reg & IXGB_STATUS_BUS64) ?
- ixgb_bus_width_64 : ixgb_bus_width_32;
+ ixgb_bus_width_64 : ixgb_bus_width_32;
return;
}
@@ -1073,7 +1114,8 @@ static void ixgb_get_bus_info(struct ixgb_hw *hw)
* mac_addr - pointer to MAC address.
*
*****************************************************************************/
-boolean_t mac_addr_valid(uint8_t * mac_addr)
+boolean_t
+mac_addr_valid(uint8_t *mac_addr)
{
boolean_t is_valid = TRUE;
DEBUGFUNC("mac_addr_valid");
@@ -1090,9 +1132,11 @@ boolean_t mac_addr_valid(uint8_t * mac_addr)
}
/* Reject the zero address */
else if (mac_addr[0] == 0 &&
- mac_addr[1] == 0 &&
- mac_addr[2] == 0 &&
- mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) {
+ mac_addr[1] == 0 &&
+ mac_addr[2] == 0 &&
+ mac_addr[3] == 0 &&
+ mac_addr[4] == 0 &&
+ mac_addr[5] == 0) {
DEBUGOUT("MAC address is all zeros\n");
is_valid = FALSE;
}
@@ -1105,7 +1149,8 @@ boolean_t mac_addr_valid(uint8_t * mac_addr)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-boolean_t ixgb_link_reset(struct ixgb_hw * hw)
+boolean_t
+ixgb_link_reset(struct ixgb_hw *hw)
{
boolean_t link_status = FALSE;
uint8_t wait_retries = MAX_RESET_ITERATIONS;
@@ -1135,20 +1180,22 @@ boolean_t ixgb_link_reset(struct ixgb_hw * hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void ixgb_optics_reset(struct ixgb_hw *hw)
+void
+ixgb_optics_reset(struct ixgb_hw *hw)
{
if (hw->phy_type == ixgb_phy_type_txn17401) {
uint16_t mdio_reg;
ixgb_write_phy_reg(hw,
- MDIO_PMA_PMD_CR1,
- IXGB_PHY_ADDRESS,
- MDIO_PMA_PMD_DID, MDIO_PMA_PMD_CR1_RESET);
-
- mdio_reg = ixgb_read_phy_reg(hw,
- MDIO_PMA_PMD_CR1,
- IXGB_PHY_ADDRESS,
- MDIO_PMA_PMD_DID);
+ MDIO_PMA_PMD_CR1,
+ IXGB_PHY_ADDRESS,
+ MDIO_PMA_PMD_DID,
+ MDIO_PMA_PMD_CR1_RESET);
+
+ mdio_reg = ixgb_read_phy_reg( hw,
+ MDIO_PMA_PMD_CR1,
+ IXGB_PHY_ADDRESS,
+ MDIO_PMA_PMD_DID);
}
return;
diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h
index fad5032d239b..28489285e2ce 100644
--- a/drivers/net/ixgb/ixgb_hw.h
+++ b/drivers/net/ixgb/ixgb_hw.h
@@ -616,17 +616,17 @@ struct ixgb_context_desc {
#define IXGB_CONTEXT_DESC_STATUS_DD 0x01
/* Filters */
-#define IXGB_RAR_ENTRIES 16 /* Number of entries in Rx Address array */
#define IXGB_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */
#define IXGB_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
+#define IXGB_RAR_ENTRIES 3 /* Number of entries in Rx Address array */
#define IXGB_MEMORY_REGISTER_BASE_ADDRESS 0
-#define ENET_HEADER_SIZE 14
-#define ENET_FCS_LENGTH 4
-#define IXGB_MAX_NUM_MULTICAST_ADDRESSES 128
-#define IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS 60
-#define IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS 1514
-#define IXGB_MAX_JUMBO_FRAME_SIZE 0x3F00
+#define ENET_HEADER_SIZE 14
+#define ENET_FCS_LENGTH 4
+#define IXGB_MAX_NUM_MULTICAST_ADDRESSES 128
+#define IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS 60
+#define IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS 1514
+#define IXGB_MAX_JUMBO_FRAME_SIZE 0x3F00
/* Phy Addresses */
#define IXGB_OPTICAL_PHY_ADDR 0x0 /* Optical Module phy address */
@@ -789,32 +789,39 @@ extern void ixgb_check_for_link(struct ixgb_hw *hw);
extern boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw);
extern boolean_t ixgb_setup_fc(struct ixgb_hw *hw);
extern void ixgb_clear_hw_cntrs(struct ixgb_hw *hw);
-extern boolean_t mac_addr_valid(uint8_t * mac_addr);
+extern boolean_t mac_addr_valid(uint8_t *mac_addr);
extern uint16_t ixgb_read_phy_reg(struct ixgb_hw *hw,
- uint32_t reg_addr,
- uint32_t phy_addr, uint32_t device_type);
+ uint32_t reg_addr,
+ uint32_t phy_addr,
+ uint32_t device_type);
extern void ixgb_write_phy_reg(struct ixgb_hw *hw,
- uint32_t reg_addr,
- uint32_t phy_addr,
- uint32_t device_type, uint16_t data);
+ uint32_t reg_addr,
+ uint32_t phy_addr,
+ uint32_t device_type,
+ uint16_t data);
+
+extern void ixgb_rar_set(struct ixgb_hw *hw,
+ uint8_t *addr,
+ uint32_t index);
-extern void ixgb_rar_set(struct ixgb_hw *hw, uint8_t * addr, uint32_t index);
/* Filters (multicast, vlan, receive) */
extern void ixgb_mc_addr_list_update(struct ixgb_hw *hw,
- uint8_t * mc_addr_list,
- uint32_t mc_addr_count, uint32_t pad);
+ uint8_t *mc_addr_list,
+ uint32_t mc_addr_count,
+ uint32_t pad);
/* Vfta functions */
extern void ixgb_write_vfta(struct ixgb_hw *hw,
- uint32_t offset, uint32_t value);
+ uint32_t offset,
+ uint32_t value);
extern void ixgb_clear_vfta(struct ixgb_hw *hw);
/* Access functions to eeprom data */
-void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t * mac_addr);
+void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t *mac_addr);
uint16_t ixgb_get_ee_compatibility(struct ixgb_hw *hw);
uint32_t ixgb_get_ee_pba_number(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw);
@@ -832,6 +839,9 @@ uint16_t ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index);
/* Everything else */
void ixgb_led_on(struct ixgb_hw *hw);
void ixgb_led_off(struct ixgb_hw *hw);
-void ixgb_write_pci_cfg(struct ixgb_hw *hw, uint32_t reg, uint16_t * value);
+void ixgb_write_pci_cfg(struct ixgb_hw *hw,
+ uint32_t reg,
+ uint16_t * value);
+
-#endif /* _IXGB_HW_H_ */
+#endif /* _IXGB_HW_H_ */
diff --git a/drivers/net/ixgb/ixgb_ids.h b/drivers/net/ixgb/ixgb_ids.h
index ea04cee1259d..6384643e2413 100644
--- a/drivers/net/ixgb/ixgb_ids.h
+++ b/drivers/net/ixgb/ixgb_ids.h
@@ -33,21 +33,16 @@
** The Device and Vendor IDs for 10 Gigabit MACs
**********************************************************************/
-#define INTEL_VENDOR_ID 0x8086
-#define INTEL_SUBVENDOR_ID 0x8086
+#define INTEL_VENDOR_ID 0x8086
+#define INTEL_SUBVENDOR_ID 0x8086
-#define IXGB_DEVICE_ID_82597EX 0x1048
-#define IXGB_DEVICE_ID_82597EX_SR 0x1A48
-#define IXGB_SUBDEVICE_ID_A11F 0xA11F
-#define IXGB_SUBDEVICE_ID_A01F 0xA01F
+#define IXGB_DEVICE_ID_82597EX 0x1048
+#define IXGB_DEVICE_ID_82597EX_SR 0x1A48
+#define IXGB_DEVICE_ID_82597EX_LR 0x1B48
+#define IXGB_SUBDEVICE_ID_A11F 0xA11F
+#define IXGB_SUBDEVICE_ID_A01F 0xA01F
-#define IXGB_SUBDEVICE_ID_A15F 0xA15F
-#define IXGB_SUBDEVICE_ID_A05F 0xA05F
-
-#define IXGB_SUBDEVICE_ID_A12F 0xA12F
-#define IXGB_SUBDEVICE_ID_A02F 0xA02F
-
-#endif /* #ifndef _IXGB_IDS_H_ */
+#endif /* #ifndef _IXGB_IDS_H_ */
/* End of File */
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index bcc10686806c..435cfa165a55 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -28,10 +28,23 @@
#include "ixgb.h"
+/* Change Log
+ * 1.0.84 10/26/04
+ * - reset buffer_info->dma in Tx resource cleanup logic
+ * 1.0.83 10/12/04
+ * - sparse cleanup - shemminger@osdl.org
+ * - fix tx resource cleanup logic
+ */
+
char ixgb_driver_name[] = "ixgb";
char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
-char ixgb_driver_version[] = "1.0.66-k2";
-char ixgb_copyright[] = "Copyright (c) 2001-2004 Intel Corporation.";
+#ifndef CONFIG_IXGB_NAPI
+#define DRIVERNAPI
+#else
+#define DRIVERNAPI "-NAPI"
+#endif
+char ixgb_driver_version[] = "1.0.87-k2"DRIVERNAPI;
+char ixgb_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
/* ixgb_pci_tbl - PCI Device ID Table
*
@@ -46,6 +59,8 @@ static struct pci_device_id ixgb_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_SR,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_LR,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
/* required last entry */
{0,}
@@ -55,11 +70,14 @@ MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);
/* Local Function Prototypes */
-static inline void ixgb_irq_disable(struct ixgb_adapter *adapter);
-static inline void ixgb_irq_enable(struct ixgb_adapter *adapter);
int ixgb_up(struct ixgb_adapter *adapter);
void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
void ixgb_reset(struct ixgb_adapter *adapter);
+int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
+int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
+void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
+void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
+void ixgb_update_stats(struct ixgb_adapter *adapter);
static int ixgb_init_module(void);
static void ixgb_exit_module(void);
@@ -68,27 +86,19 @@ static void __devexit ixgb_remove(struct pci_dev *pdev);
static int ixgb_sw_init(struct ixgb_adapter *adapter);
static int ixgb_open(struct net_device *netdev);
static int ixgb_close(struct net_device *netdev);
-static int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
-static int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
static void ixgb_configure_tx(struct ixgb_adapter *adapter);
static void ixgb_configure_rx(struct ixgb_adapter *adapter);
static void ixgb_setup_rctl(struct ixgb_adapter *adapter);
static void ixgb_clean_tx_ring(struct ixgb_adapter *adapter);
static void ixgb_clean_rx_ring(struct ixgb_adapter *adapter);
-static void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
-static void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
static void ixgb_set_multi(struct net_device *netdev);
static void ixgb_watchdog(unsigned long data);
static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
static struct net_device_stats *ixgb_get_stats(struct net_device *netdev);
static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);
static int ixgb_set_mac(struct net_device *netdev, void *p);
-static void ixgb_update_stats(struct ixgb_adapter *adapter);
static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs);
static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
-static inline void ixgb_rx_checksum(struct ixgb_adapter *adapter,
- struct ixgb_rx_desc *rx_desc,
- struct sk_buff *skb);
#ifdef CONFIG_IXGB_NAPI
static int ixgb_clean(struct net_device *netdev, int *budget);
static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
@@ -97,6 +107,7 @@ static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
#endif
static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
+void ixgb_set_ethtool_ops(struct net_device *netdev);
static void ixgb_tx_timeout(struct net_device *dev);
static void ixgb_tx_timeout_task(struct net_device *dev);
static void ixgb_vlan_rx_register(struct net_device *netdev,
@@ -123,7 +134,6 @@ struct notifier_block ixgb_notifier_reboot = {
/* Exported from other modules */
extern void ixgb_check_options(struct ixgb_adapter *adapter);
-extern struct ethtool_ops ixgb_ethtool_ops;
static struct pci_driver ixgb_driver = {
.name = ixgb_driver_name,
@@ -152,7 +162,8 @@ MODULE_LICENSE("GPL");
* loaded. All it does is register with the PCI subsystem.
**/
-static int __init ixgb_init_module(void)
+static int __init
+ixgb_init_module(void)
{
int ret;
printk(KERN_INFO "%s - version %s\n",
@@ -161,7 +172,7 @@ static int __init ixgb_init_module(void)
printk(KERN_INFO "%s\n", ixgb_copyright);
ret = pci_module_init(&ixgb_driver);
- if (ret >= 0) {
+ if(ret >= 0) {
register_reboot_notifier(&ixgb_notifier_reboot);
}
return ret;
@@ -176,7 +187,8 @@ module_init(ixgb_init_module);
* from memory.
**/
-static void __exit ixgb_exit_module(void)
+static void __exit
+ixgb_exit_module(void)
{
unregister_reboot_notifier(&ixgb_notifier_reboot);
pci_unregister_driver(&ixgb_driver);
@@ -189,7 +201,8 @@ module_exit(ixgb_exit_module);
* @adapter: board private structure
**/
-static inline void ixgb_irq_disable(struct ixgb_adapter *adapter)
+static inline void
+ixgb_irq_disable(struct ixgb_adapter *adapter)
{
atomic_inc(&adapter->irq_sem);
IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
@@ -202,17 +215,19 @@ static inline void ixgb_irq_disable(struct ixgb_adapter *adapter)
* @adapter: board private structure
**/
-static inline void ixgb_irq_enable(struct ixgb_adapter *adapter)
+static inline void
+ixgb_irq_enable(struct ixgb_adapter *adapter)
{
- if (atomic_dec_and_test(&adapter->irq_sem)) {
+ if(atomic_dec_and_test(&adapter->irq_sem)) {
IXGB_WRITE_REG(&adapter->hw, IMS,
- IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
- IXGB_INT_RXO | IXGB_INT_LSC);
+ IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
+ IXGB_INT_RXO | IXGB_INT_LSC);
IXGB_WRITE_FLUSH(&adapter->hw);
}
}
-int ixgb_up(struct ixgb_adapter *adapter)
+int
+ixgb_up(struct ixgb_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
int err;
@@ -230,27 +245,44 @@ int ixgb_up(struct ixgb_adapter *adapter)
ixgb_configure_rx(adapter);
ixgb_alloc_rx_buffers(adapter);
- if ((err = request_irq(adapter->pdev->irq, &ixgb_intr,
- SA_SHIRQ | SA_SAMPLE_RANDOM,
- netdev->name, netdev)))
+#ifdef CONFIG_PCI_MSI
+ {
+ boolean_t pcix = (IXGB_READ_REG(&adapter->hw, STATUS) &
+ IXGB_STATUS_PCIX_MODE) ? TRUE : FALSE;
+ adapter->have_msi = TRUE;
+
+ if (!pcix)
+ adapter->have_msi = FALSE;
+ else if((err = pci_enable_msi(adapter->pdev))) {
+ printk (KERN_ERR
+ "Unable to allocate MSI interrupt Error: %d\n", err);
+ adapter->have_msi = FALSE;
+ /* proceed to try to request regular interrupt */
+ }
+ }
+
+#endif
+ if((err = request_irq(adapter->pdev->irq, &ixgb_intr,
+ SA_SHIRQ | SA_SAMPLE_RANDOM,
+ netdev->name, netdev)))
return err;
/* disable interrupts and get the hardware into a known state */
IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
- if ((hw->max_frame_size != max_frame) ||
- (hw->max_frame_size !=
- (IXGB_READ_REG(hw, MFS) >> IXGB_MFS_SHIFT))) {
+ if((hw->max_frame_size != max_frame) ||
+ (hw->max_frame_size !=
+ (IXGB_READ_REG(hw, MFS) >> IXGB_MFS_SHIFT))) {
hw->max_frame_size = max_frame;
IXGB_WRITE_REG(hw, MFS, hw->max_frame_size << IXGB_MFS_SHIFT);
- if (hw->max_frame_size >
- IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) {
+ if(hw->max_frame_size >
+ IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) {
uint32_t ctrl0 = IXGB_READ_REG(hw, CTRL0);
- if (!(ctrl0 & IXGB_CTRL0_JFE)) {
+ if(!(ctrl0 & IXGB_CTRL0_JFE)) {
ctrl0 |= IXGB_CTRL0_JFE;
IXGB_WRITE_REG(hw, CTRL0, ctrl0);
}
@@ -263,13 +295,19 @@ int ixgb_up(struct ixgb_adapter *adapter)
return 0;
}
-void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
+void
+ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
{
struct net_device *netdev = adapter->netdev;
ixgb_irq_disable(adapter);
free_irq(adapter->pdev->irq, netdev);
- if (kill_watchdog)
+#ifdef CONFIG_PCI_MSI
+ if(adapter->have_msi == TRUE)
+ pci_disable_msi(adapter->pdev);
+
+#endif
+ if(kill_watchdog)
del_timer_sync(&adapter->watchdog_timer);
adapter->link_speed = 0;
adapter->link_duplex = 0;
@@ -281,11 +319,12 @@ void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
ixgb_clean_rx_ring(adapter);
}
-void ixgb_reset(struct ixgb_adapter *adapter)
+void
+ixgb_reset(struct ixgb_adapter *adapter)
{
ixgb_adapter_stop(&adapter->hw);
- if (!ixgb_init_hw(&adapter->hw))
+ if(!ixgb_init_hw(&adapter->hw))
IXGB_DBG("ixgb_init_hw failed.\n");
}
@@ -302,7 +341,8 @@ void ixgb_reset(struct ixgb_adapter *adapter)
**/
static int __devinit
-ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ixgb_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct net_device *netdev = NULL;
struct ixgb_adapter *adapter;
@@ -313,26 +353,26 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int i;
int err;
- if ((err = pci_enable_device(pdev)))
+ if((err = pci_enable_device(pdev)))
return err;
- if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+ if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
pci_using_dac = 1;
} else {
- if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+ if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
IXGB_ERR("No usable DMA configuration, aborting\n");
return err;
}
pci_using_dac = 0;
}
- if ((err = pci_request_regions(pdev, ixgb_driver_name)))
+ if((err = pci_request_regions(pdev, ixgb_driver_name)))
return err;
pci_set_master(pdev);
netdev = alloc_etherdev(sizeof(struct ixgb_adapter));
- if (!netdev) {
+ if(!netdev) {
err = -ENOMEM;
goto err_alloc_etherdev;
}
@@ -350,15 +390,15 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
mmio_len = pci_resource_len(pdev, BAR_0);
adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
- if (!adapter->hw.hw_addr) {
+ if(!adapter->hw.hw_addr) {
err = -EIO;
goto err_ioremap;
}
- for (i = BAR_1; i <= BAR_5; i++) {
- if (pci_resource_len(pdev, i) == 0)
+ for(i = BAR_1; i <= BAR_5; i++) {
+ if(pci_resource_len(pdev, i) == 0)
continue;
- if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+ if(pci_resource_flags(pdev, i) & IORESOURCE_IO) {
adapter->hw.io_base = pci_resource_start(pdev, i);
break;
}
@@ -371,9 +411,9 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->set_multicast_list = &ixgb_set_multi;
netdev->set_mac_address = &ixgb_set_mac;
netdev->change_mtu = &ixgb_change_mtu;
+ ixgb_set_ethtool_ops(netdev);
netdev->tx_timeout = &ixgb_tx_timeout;
netdev->watchdog_timeo = HZ;
- SET_ETHTOOL_OPS(netdev, &ixgb_ethtool_ops);
#ifdef CONFIG_IXGB_NAPI
netdev->poll = &ixgb_clean;
netdev->weight = 64;
@@ -395,22 +435,24 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* setup the private structure */
- if ((err = ixgb_sw_init(adapter)))
+ if((err = ixgb_sw_init(adapter)))
goto err_sw_init;
netdev->features = NETIF_F_SG |
- NETIF_F_HW_CSUM |
- NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
+ NETIF_F_HW_CSUM |
+ NETIF_F_HW_VLAN_TX |
+ NETIF_F_HW_VLAN_RX |
+ NETIF_F_HW_VLAN_FILTER;
#ifdef NETIF_F_TSO
netdev->features |= NETIF_F_TSO;
#endif
- if (pci_using_dac)
+ if(pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
/* make sure the EEPROM is good */
- if (!ixgb_validate_eeprom_checksum(&adapter->hw)) {
+ if(!ixgb_validate_eeprom_checksum(&adapter->hw)) {
printk(KERN_ERR "The EEPROM Checksum Is Not Valid\n");
err = -EIO;
goto err_eeprom;
@@ -418,7 +460,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
- if (!is_valid_ether_addr(netdev->dev_addr)) {
+ if(!is_valid_ether_addr(netdev->dev_addr)) {
err = -EIO;
goto err_eeprom;
}
@@ -432,7 +474,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&adapter->tx_timeout_task,
(void (*)(void *))ixgb_tx_timeout_task, netdev);
- if ((err = register_netdev(netdev)))
+ if((err = register_netdev(netdev)))
goto err_register;
/* we're going to reset, so assume we have no link for now */
@@ -441,7 +483,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netif_stop_queue(netdev);
printk(KERN_INFO "%s: Intel(R) PRO/10GbE Network Connection\n",
- netdev->name);
+ netdev->name);
ixgb_check_options(adapter);
/* reset the hardware with the new settings */
@@ -450,13 +492,13 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
cards_found++;
return 0;
- err_register:
- err_sw_init:
- err_eeprom:
+err_register:
+err_sw_init:
+err_eeprom:
iounmap(adapter->hw.hw_addr);
- err_ioremap:
+err_ioremap:
free_netdev(netdev);
- err_alloc_etherdev:
+err_alloc_etherdev:
pci_release_regions(pdev);
return err;
}
@@ -471,7 +513,8 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
* memory.
**/
-static void __devexit ixgb_remove(struct pci_dev *pdev)
+static void __devexit
+ixgb_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgb_adapter *adapter = netdev->priv;
@@ -493,7 +536,8 @@ static void __devexit ixgb_remove(struct pci_dev *pdev)
* OS network device settings (MTU size).
**/
-static int __devinit ixgb_sw_init(struct ixgb_adapter *adapter)
+static int __devinit
+ixgb_sw_init(struct ixgb_adapter *adapter)
{
struct ixgb_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
@@ -510,9 +554,10 @@ static int __devinit ixgb_sw_init(struct ixgb_adapter *adapter)
hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
- if ((hw->device_id == IXGB_DEVICE_ID_82597EX)
- || (hw->device_id == IXGB_DEVICE_ID_82597EX_SR))
- hw->mac_type = ixgb_82597;
+ if((hw->device_id == IXGB_DEVICE_ID_82597EX)
+ ||(hw->device_id == IXGB_DEVICE_ID_82597EX_LR)
+ ||(hw->device_id == IXGB_DEVICE_ID_82597EX_SR))
+ hw->mac_type = ixgb_82597;
else {
/* should never have loaded on this device */
printk(KERN_ERR "ixgb: unsupported device id\n");
@@ -540,31 +585,32 @@ static int __devinit ixgb_sw_init(struct ixgb_adapter *adapter)
* and the stack is notified that the interface is ready.
**/
-static int ixgb_open(struct net_device *netdev)
+static int
+ixgb_open(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
int err;
/* allocate transmit descriptors */
- if ((err = ixgb_setup_tx_resources(adapter)))
+ if((err = ixgb_setup_tx_resources(adapter)))
goto err_setup_tx;
/* allocate receive descriptors */
- if ((err = ixgb_setup_rx_resources(adapter)))
+ if((err = ixgb_setup_rx_resources(adapter)))
goto err_setup_rx;
- if ((err = ixgb_up(adapter)))
+ if((err = ixgb_up(adapter)))
goto err_up;
return 0;
- err_up:
+err_up:
ixgb_free_rx_resources(adapter);
- err_setup_rx:
+err_setup_rx:
ixgb_free_tx_resources(adapter);
- err_setup_tx:
+err_setup_tx:
ixgb_reset(adapter);
return err;
@@ -582,7 +628,8 @@ static int ixgb_open(struct net_device *netdev)
* hardware, and all transmit and receive resources are freed.
**/
-static int ixgb_close(struct net_device *netdev)
+static int
+ixgb_close(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
@@ -601,15 +648,16 @@ static int ixgb_close(struct net_device *netdev)
* Return 0 on success, negative on failure
**/
-static int ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
+int
+ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *txdr = &adapter->tx_ring;
struct pci_dev *pdev = adapter->pdev;
int size;
size = sizeof(struct ixgb_buffer) * txdr->count;
- txdr->buffer_info = kmalloc(size, GFP_KERNEL);
- if (!txdr->buffer_info) {
+ txdr->buffer_info = vmalloc(size);
+ if(!txdr->buffer_info) {
return -ENOMEM;
}
memset(txdr->buffer_info, 0, size);
@@ -620,8 +668,8 @@ static int ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
IXGB_ROUNDUP(txdr->size, 4096);
txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
- if (!txdr->desc) {
- kfree(txdr->buffer_info);
+ if(!txdr->desc) {
+ vfree(txdr->buffer_info);
return -ENOMEM;
}
memset(txdr->desc, 0, txdr->size);
@@ -639,7 +687,8 @@ static int ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
* Configure the Tx unit of the MAC after a reset.
**/
-static void ixgb_configure_tx(struct ixgb_adapter *adapter)
+static void
+ixgb_configure_tx(struct ixgb_adapter *adapter)
{
uint64_t tdba = adapter->tx_ring.dma;
uint32_t tdlen = adapter->tx_ring.count * sizeof(struct ixgb_tx_desc);
@@ -679,8 +728,8 @@ static void ixgb_configure_tx(struct ixgb_adapter *adapter)
/* Setup Transmit Descriptor Settings for this adapter */
adapter->tx_cmd_type =
- IXGB_TX_DESC_TYPE
- | (adapter->tx_int_delay_enable ? IXGB_TX_DESC_CMD_IDE : 0);
+ IXGB_TX_DESC_TYPE
+ | (adapter->tx_int_delay_enable ? IXGB_TX_DESC_CMD_IDE : 0);
}
/**
@@ -690,15 +739,16 @@ static void ixgb_configure_tx(struct ixgb_adapter *adapter)
* Returns 0 on success, negative on failure
**/
-static int ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
+int
+ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
int size;
size = sizeof(struct ixgb_buffer) * rxdr->count;
- rxdr->buffer_info = kmalloc(size, GFP_KERNEL);
- if (!rxdr->buffer_info) {
+ rxdr->buffer_info = vmalloc(size);
+ if(!rxdr->buffer_info) {
return -ENOMEM;
}
memset(rxdr->buffer_info, 0, size);
@@ -710,8 +760,8 @@ static int ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
- if (!rxdr->desc) {
- kfree(rxdr->buffer_info);
+ if(!rxdr->desc) {
+ vfree(rxdr->buffer_info);
return -ENOMEM;
}
memset(rxdr->desc, 0, rxdr->size);
@@ -727,7 +777,8 @@ static int ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
* @adapter: Board private structure
**/
-static void ixgb_setup_rctl(struct ixgb_adapter *adapter)
+static void
+ixgb_setup_rctl(struct ixgb_adapter *adapter)
{
uint32_t rctl;
@@ -736,9 +787,9 @@ static void ixgb_setup_rctl(struct ixgb_adapter *adapter)
rctl &= ~(3 << IXGB_RCTL_MO_SHIFT);
rctl |=
- IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 |
- IXGB_RCTL_RXEN | IXGB_RCTL_CFF |
- (adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT);
+ IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 |
+ IXGB_RCTL_RXEN | IXGB_RCTL_CFF |
+ (adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT);
rctl |= IXGB_RCTL_SECRC;
@@ -768,7 +819,8 @@ static void ixgb_setup_rctl(struct ixgb_adapter *adapter)
* Configure the Rx unit of the MAC after a reset.
**/
-static void ixgb_configure_rx(struct ixgb_adapter *adapter)
+static void
+ixgb_configure_rx(struct ixgb_adapter *adapter)
{
uint64_t rdba = adapter->rx_ring.dma;
uint32_t rdlen = adapter->rx_ring.count * sizeof(struct ixgb_rx_desc);
@@ -797,51 +849,14 @@ static void ixgb_configure_rx(struct ixgb_adapter *adapter)
IXGB_WRITE_REG(hw, RDH, 0);
IXGB_WRITE_REG(hw, RDT, 0);
- /* burst 16 or burst when RXT0 */
- rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT
- | RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT
- | RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
+ /* burst 16 or burst when RXT0*/
+ rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT
+ | RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT
+ | RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
IXGB_WRITE_REG(hw, RXDCTL, rxdctl);
- if (adapter->raidc) {
- uint32_t raidc;
- uint8_t poll_threshold;
-
- /* Poll every rx_int_delay period, if RBD exists
- * Receive Backlog Detection is set to <threshold>
- * Rx Descriptors
- * max is 0x3F == set to poll when 504 RxDesc left
- * min is 0 */
-
- /* polling times are 1 == 0.8192us
- 2 == 1.6384us
- 3 == 3.2768us etc
- ...
- 511 == 418 us
- */
-#define IXGB_RAIDC_POLL_DEFAULT 122 /* set to poll every ~100 us under load
- also known as 10000 interrupts / sec */
-
- /* divide this by 2^3 (8) to get a register size count */
- poll_threshold = ((adapter->rx_ring.count - 1) >> 3);
- /* poll at half of that size */
- poll_threshold >>= 1;
- /* make sure its not bigger than our max */
- poll_threshold &= 0x3F;
-
- raidc = IXGB_RAIDC_EN | /* turn on raidc style moderation */
- IXGB_RAIDC_RXT_GATE | /* don't interrupt with rxt0 while
- in RBD mode (polling) */
- (IXGB_RAIDC_POLL_DEFAULT << IXGB_RAIDC_POLL_SHIFT) |
- /* this sets the regular "min interrupt delay" */
- (adapter->rx_int_delay << IXGB_RAIDC_DELAY_SHIFT) |
- poll_threshold;
-
- IXGB_WRITE_REG(hw, RAIDC, raidc);
- }
-
/* Enable Receive Checksum Offload for TCP and UDP */
- if (adapter->rx_csum == TRUE) {
+ if(adapter->rx_csum == TRUE) {
rxcsum = IXGB_READ_REG(hw, RXCSUM);
rxcsum |= IXGB_RXCSUM_TUOFL;
IXGB_WRITE_REG(hw, RXCSUM, rxcsum);
@@ -859,13 +874,14 @@ static void ixgb_configure_rx(struct ixgb_adapter *adapter)
* Free all transmit software resources
**/
-static void ixgb_free_tx_resources(struct ixgb_adapter *adapter)
+void
+ixgb_free_tx_resources(struct ixgb_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
ixgb_clean_tx_ring(adapter);
- kfree(adapter->tx_ring.buffer_info);
+ vfree(adapter->tx_ring.buffer_info);
adapter->tx_ring.buffer_info = NULL;
pci_free_consistent(pdev, adapter->tx_ring.size,
@@ -874,33 +890,42 @@ static void ixgb_free_tx_resources(struct ixgb_adapter *adapter)
adapter->tx_ring.desc = NULL;
}
+static inline void
+ixgb_unmap_and_free_tx_resource(struct ixgb_adapter *adapter,
+ struct ixgb_buffer *buffer_info)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ if(buffer_info->dma) {
+ pci_unmap_page(pdev,
+ buffer_info->dma,
+ buffer_info->length,
+ PCI_DMA_TODEVICE);
+ buffer_info->dma = 0;
+ }
+ if(buffer_info->skb) {
+ dev_kfree_skb_any(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+}
+
/**
* ixgb_clean_tx_ring - Free Tx Buffers
* @adapter: board private structure
**/
-static void ixgb_clean_tx_ring(struct ixgb_adapter *adapter)
+static void
+ixgb_clean_tx_ring(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
struct ixgb_buffer *buffer_info;
- struct pci_dev *pdev = adapter->pdev;
unsigned long size;
unsigned int i;
/* Free all the Tx ring sk_buffs */
- for (i = 0; i < tx_ring->count; i++) {
+ for(i = 0; i < tx_ring->count; i++) {
buffer_info = &tx_ring->buffer_info[i];
- if (buffer_info->skb) {
-
- pci_unmap_page(pdev,
- buffer_info->dma,
- buffer_info->length, PCI_DMA_TODEVICE);
-
- dev_kfree_skb(buffer_info->skb);
-
- buffer_info->skb = NULL;
- }
+ ixgb_unmap_and_free_tx_resource(adapter, buffer_info);
}
size = sizeof(struct ixgb_buffer) * tx_ring->count;
@@ -924,14 +949,15 @@ static void ixgb_clean_tx_ring(struct ixgb_adapter *adapter)
* Free all receive software resources
**/
-static void ixgb_free_rx_resources(struct ixgb_adapter *adapter)
+void
+ixgb_free_rx_resources(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
ixgb_clean_rx_ring(adapter);
- kfree(rx_ring->buffer_info);
+ vfree(rx_ring->buffer_info);
rx_ring->buffer_info = NULL;
pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
@@ -944,7 +970,8 @@ static void ixgb_free_rx_resources(struct ixgb_adapter *adapter)
* @adapter: board private structure
**/
-static void ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
+static void
+ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
struct ixgb_buffer *buffer_info;
@@ -954,9 +981,9 @@ static void ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
/* Free all the Rx ring sk_buffs */
- for (i = 0; i < rx_ring->count; i++) {
+ for(i = 0; i < rx_ring->count; i++) {
buffer_info = &rx_ring->buffer_info[i];
- if (buffer_info->skb) {
+ if(buffer_info->skb) {
pci_unmap_single(pdev,
buffer_info->dma,
@@ -991,12 +1018,13 @@ static void ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
* Returns 0 on success, negative on failure
**/
-static int ixgb_set_mac(struct net_device *netdev, void *p)
+static int
+ixgb_set_mac(struct net_device *netdev, void *p)
{
struct ixgb_adapter *adapter = netdev->priv;
struct sockaddr *addr = p;
- if (!is_valid_ether_addr(addr->sa_data))
+ if(!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
@@ -1016,7 +1044,8 @@ static int ixgb_set_mac(struct net_device *netdev, void *p)
* promiscuous mode, and all-multi behavior.
**/
-static void ixgb_set_multi(struct net_device *netdev)
+static void
+ixgb_set_multi(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
@@ -1028,16 +1057,16 @@ static void ixgb_set_multi(struct net_device *netdev)
rctl = IXGB_READ_REG(hw, RCTL);
- if (netdev->flags & IFF_PROMISC) {
+ if(netdev->flags & IFF_PROMISC) {
rctl |= (IXGB_RCTL_UPE | IXGB_RCTL_MPE);
- } else if (netdev->flags & IFF_ALLMULTI) {
+ } else if(netdev->flags & IFF_ALLMULTI) {
rctl |= IXGB_RCTL_MPE;
rctl &= ~IXGB_RCTL_UPE;
} else {
rctl &= ~(IXGB_RCTL_UPE | IXGB_RCTL_MPE);
}
- if (netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES) {
+ if(netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES) {
rctl |= IXGB_RCTL_MPE;
IXGB_WRITE_REG(hw, RCTL, rctl);
} else {
@@ -1045,10 +1074,10 @@ static void ixgb_set_multi(struct net_device *netdev)
IXGB_WRITE_REG(hw, RCTL, rctl);
- for (i = 0, mc_ptr = netdev->mc_list; mc_ptr;
- i++, mc_ptr = mc_ptr->next)
+ for(i = 0, mc_ptr = netdev->mc_list; mc_ptr;
+ i++, mc_ptr = mc_ptr->next)
memcpy(&mta[i * IXGB_ETH_LENGTH_OF_ADDRESS],
- mc_ptr->dmi_addr, IXGB_ETH_LENGTH_OF_ADDRESS);
+ mc_ptr->dmi_addr, IXGB_ETH_LENGTH_OF_ADDRESS);
ixgb_mc_addr_list_update(hw, mta, netdev->mc_count, 0);
}
@@ -1059,7 +1088,8 @@ static void ixgb_set_multi(struct net_device *netdev)
* @data: pointer to netdev cast into an unsigned long
**/
-static void ixgb_watchdog(unsigned long data)
+static void
+ixgb_watchdog(unsigned long data)
{
struct ixgb_adapter *adapter = (struct ixgb_adapter *)data;
struct net_device *netdev = adapter->netdev;
@@ -1073,21 +1103,22 @@ static void ixgb_watchdog(unsigned long data)
netif_stop_queue(netdev);
}
- if (adapter->hw.link_up) {
- if (!netif_carrier_ok(netdev)) {
+ if(adapter->hw.link_up) {
+ if(!netif_carrier_ok(netdev)) {
printk(KERN_INFO "ixgb: %s NIC Link is Up %d Mbps %s\n",
- netdev->name, 10000, "Full Duplex");
+ netdev->name, 10000, "Full Duplex");
adapter->link_speed = 10000;
adapter->link_duplex = FULL_DUPLEX;
netif_carrier_on(netdev);
netif_wake_queue(netdev);
}
} else {
- if (netif_carrier_ok(netdev)) {
+ if(netif_carrier_ok(netdev)) {
adapter->link_speed = 0;
adapter->link_duplex = 0;
printk(KERN_INFO
- "ixgb: %s NIC Link is Down\n", netdev->name);
+ "ixgb: %s NIC Link is Down\n",
+ netdev->name);
netif_carrier_off(netdev);
netif_stop_queue(netdev);
@@ -1096,8 +1127,8 @@ static void ixgb_watchdog(unsigned long data)
ixgb_update_stats(adapter);
- if (!netif_carrier_ok(netdev)) {
- if (IXGB_DESC_UNUSED(txdr) + 1 < txdr->count) {
+ if(!netif_carrier_ok(netdev)) {
+ if(IXGB_DESC_UNUSED(txdr) + 1 < txdr->count) {
/* We've lost link, so the controller stops DMA,
* but we've got queued Tx work that's never going
* to get done, so reset controller to flush Tx.
@@ -1108,9 +1139,9 @@ static void ixgb_watchdog(unsigned long data)
/* Early detection of hung controller */
i = txdr->next_to_clean;
- if (txdr->buffer_info[i].dma &&
- time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) &&
- !(IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF))
+ if(txdr->buffer_info[i].dma &&
+ time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) &&
+ !(IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF))
netif_stop_queue(netdev);
/* generate an interrupt to force clean up of any stragglers */
@@ -1133,7 +1164,7 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
uint16_t ipcse, tucse, mss;
- if (likely(skb_shinfo(skb)->tso_size)) {
+ if(likely(skb_shinfo(skb)->tso_size)) {
hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
mss = skb_shinfo(skb)->tso_size;
skb->nh.iph->tot_len = 0;
@@ -1160,22 +1191,16 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
context_desc->mss = cpu_to_le16(mss);
context_desc->hdr_len = hdr_len;
context_desc->status = 0;
- context_desc->cmd_type_len = cpu_to_le32(IXGB_CONTEXT_DESC_TYPE
- |
- IXGB_CONTEXT_DESC_CMD_TSE
- |
- IXGB_CONTEXT_DESC_CMD_IP
- |
- IXGB_CONTEXT_DESC_CMD_TCP
- |
- IXGB_CONTEXT_DESC_CMD_RS
- |
- IXGB_CONTEXT_DESC_CMD_IDE
- | (skb->len -
- (hdr_len)));
-
- if (++i == adapter->tx_ring.count)
- i = 0;
+ context_desc->cmd_type_len = cpu_to_le32(
+ IXGB_CONTEXT_DESC_TYPE
+ | IXGB_CONTEXT_DESC_CMD_TSE
+ | IXGB_CONTEXT_DESC_CMD_IP
+ | IXGB_CONTEXT_DESC_CMD_TCP
+ | IXGB_CONTEXT_DESC_CMD_RS
+ | IXGB_CONTEXT_DESC_CMD_IDE
+ | (skb->len - (hdr_len)));
+
+ if(++i == adapter->tx_ring.count) i = 0;
adapter->tx_ring.next_to_use = i;
return TRUE;
@@ -1192,7 +1217,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
unsigned int i;
uint8_t css, cso;
- if (likely(skb->ip_summed == CHECKSUM_HW)) {
+ if(likely(skb->ip_summed == CHECKSUM_HW)) {
css = skb->h.raw - skb->data;
cso = (skb->h.raw + skb->csum) - skb->data;
@@ -1203,16 +1228,16 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
context_desc->tucso = cso;
context_desc->tucse = 0;
/* zero out any previously existing data in one instruction */
- *(uint32_t *) & (context_desc->ipcss) = 0;
+ *(uint32_t *)&(context_desc->ipcss) = 0;
context_desc->status = 0;
context_desc->hdr_len = 0;
context_desc->mss = 0;
context_desc->cmd_type_len =
- cpu_to_le32(IXGB_CONTEXT_DESC_TYPE
- | IXGB_TX_DESC_CMD_RS | IXGB_TX_DESC_CMD_IDE);
+ cpu_to_le32(IXGB_CONTEXT_DESC_TYPE
+ | IXGB_TX_DESC_CMD_RS
+ | IXGB_TX_DESC_CMD_IDE);
- if (++i == adapter->tx_ring.count)
- i = 0;
+ if(++i == adapter->tx_ring.count) i = 0;
adapter->tx_ring.next_to_use = i;
return TRUE;
@@ -1239,45 +1264,46 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
i = tx_ring->next_to_use;
- while (len) {
+ while(len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, IXGB_MAX_JUMBO_FRAME_SIZE);
buffer_info->length = size;
buffer_info->dma =
- pci_map_single(adapter->pdev,
- skb->data + offset, size, PCI_DMA_TODEVICE);
+ pci_map_single(adapter->pdev,
+ skb->data + offset,
+ size,
+ PCI_DMA_TODEVICE);
buffer_info->time_stamp = jiffies;
len -= size;
offset += size;
count++;
- if (++i == tx_ring->count)
- i = 0;
+ if(++i == tx_ring->count) i = 0;
}
- for (f = 0; f < nr_frags; f++) {
+ for(f = 0; f < nr_frags; f++) {
struct skb_frag_struct *frag;
frag = &skb_shinfo(skb)->frags[f];
len = frag->size;
offset = 0;
- while (len) {
+ while(len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, IXGB_MAX_JUMBO_FRAME_SIZE);
buffer_info->length = size;
buffer_info->dma =
- pci_map_page(adapter->pdev,
- frag->page,
- frag->page_offset + offset,
- size, PCI_DMA_TODEVICE);
+ pci_map_page(adapter->pdev,
+ frag->page,
+ frag->page_offset + offset,
+ size,
+ PCI_DMA_TODEVICE);
buffer_info->time_stamp = jiffies;
len -= size;
offset += size;
count++;
- if (++i == tx_ring->count)
- i = 0;
+ if(++i == tx_ring->count) i = 0;
}
}
i = (i == 0) ? tx_ring->count - 1 : i - 1;
@@ -1288,8 +1314,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
}
static inline void
-ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,
- int tx_flags)
+ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
{
struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
struct ixgb_tx_desc *tx_desc = NULL;
@@ -1299,36 +1324,35 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,
uint8_t popts = 0;
unsigned int i;
- if (tx_flags & IXGB_TX_FLAGS_TSO) {
+ if(tx_flags & IXGB_TX_FLAGS_TSO) {
cmd_type_len |= IXGB_TX_DESC_CMD_TSE;
popts |= (IXGB_TX_DESC_POPTS_IXSM | IXGB_TX_DESC_POPTS_TXSM);
}
- if (tx_flags & IXGB_TX_FLAGS_CSUM)
+ if(tx_flags & IXGB_TX_FLAGS_CSUM)
popts |= IXGB_TX_DESC_POPTS_TXSM;
- if (tx_flags & IXGB_TX_FLAGS_VLAN) {
+ if(tx_flags & IXGB_TX_FLAGS_VLAN) {
cmd_type_len |= IXGB_TX_DESC_CMD_VLE;
}
i = tx_ring->next_to_use;
- while (count--) {
+ while(count--) {
buffer_info = &tx_ring->buffer_info[i];
tx_desc = IXGB_TX_DESC(*tx_ring, i);
tx_desc->buff_addr = cpu_to_le64(buffer_info->dma);
tx_desc->cmd_type_len =
- cpu_to_le32(cmd_type_len | buffer_info->length);
+ cpu_to_le32(cmd_type_len | buffer_info->length);
tx_desc->status = status;
tx_desc->popts = popts;
tx_desc->vlan = cpu_to_le16(vlan_id);
- if (++i == tx_ring->count)
- i = 0;
+ if(++i == tx_ring->count) i = 0;
}
- tx_desc->cmd_type_len |= cpu_to_le32(IXGB_TX_DESC_CMD_EOP
- | IXGB_TX_DESC_CMD_RS);
+ tx_desc->cmd_type_len |= cpu_to_le32(IXGB_TX_DESC_CMD_EOP
+ | IXGB_TX_DESC_CMD_RS );
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
@@ -1346,7 +1370,8 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,
#define DESC_NEEDED TXD_USE_COUNT(IXGB_MAX_DATA_PER_TXD) + \
MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1
-static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+static int
+ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
unsigned int first;
@@ -1354,33 +1379,33 @@ static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
unsigned long flags;
int vlan_id = 0;
- if (skb->len <= 0) {
+ if(skb->len <= 0) {
dev_kfree_skb_any(skb);
return 0;
}
spin_lock_irqsave(&adapter->tx_lock, flags);
- if (unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) {
+ if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) {
netif_stop_queue(netdev);
spin_unlock_irqrestore(&adapter->tx_lock, flags);
return 1;
}
spin_unlock_irqrestore(&adapter->tx_lock, flags);
- if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+ if(adapter->vlgrp && vlan_tx_tag_present(skb)) {
tx_flags |= IXGB_TX_FLAGS_VLAN;
vlan_id = vlan_tx_tag_get(skb);
}
first = adapter->tx_ring.next_to_use;
-
- if (ixgb_tso(adapter, skb))
+
+ if(ixgb_tso(adapter, skb))
tx_flags |= IXGB_TX_FLAGS_TSO;
- else if (ixgb_tx_csum(adapter, skb))
+ else if(ixgb_tx_csum(adapter, skb))
tx_flags |= IXGB_TX_FLAGS_CSUM;
ixgb_tx_queue(adapter, ixgb_tx_map(adapter, skb, first), vlan_id,
- tx_flags);
+ tx_flags);
netdev->trans_start = jiffies;
@@ -1392,7 +1417,8 @@ static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
* @netdev: network interface device structure
**/
-static void ixgb_tx_timeout(struct net_device *netdev)
+static void
+ixgb_tx_timeout(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
@@ -1400,14 +1426,13 @@ static void ixgb_tx_timeout(struct net_device *netdev)
schedule_work(&adapter->tx_timeout_task);
}
-static void ixgb_tx_timeout_task(struct net_device *netdev)
+static void
+ixgb_tx_timeout_task(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
- netif_device_detach(netdev);
ixgb_down(adapter, TRUE);
ixgb_up(adapter);
- netif_device_attach(netdev);
}
/**
@@ -1418,7 +1443,8 @@ static void ixgb_tx_timeout_task(struct net_device *netdev)
* The statistics are actually updated from the timer callback.
**/
-static struct net_device_stats *ixgb_get_stats(struct net_device *netdev)
+static struct net_device_stats *
+ixgb_get_stats(struct net_device *netdev)
{
struct ixgb_adapter *adapter = netdev->priv;
@@ -1433,27 +1459,28 @@ static struct net_device_stats *ixgb_get_stats(struct net_device *netdev)
* Returns 0 on success, negative on failure
**/
-static int ixgb_change_mtu(struct net_device *netdev, int new_mtu)
+static int
+ixgb_change_mtu(struct net_device *netdev, int new_mtu)
{
struct ixgb_adapter *adapter = netdev->priv;
- uint32_t old_mtu = adapter->rx_buffer_len;
int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+ int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+
- if ((max_frame < IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
- || (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {
+ if((max_frame < IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
+ || (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {
IXGB_ERR("Invalid MTU setting\n");
return -EINVAL;
}
- if ((max_frame <=
- IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
- || (max_frame <= IXGB_RXBUFFER_2048)) {
+ if((max_frame <= IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
+ || (max_frame <= IXGB_RXBUFFER_2048)) {
adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
- } else if (max_frame <= IXGB_RXBUFFER_4096) {
+ } else if(max_frame <= IXGB_RXBUFFER_4096) {
adapter->rx_buffer_len = IXGB_RXBUFFER_4096;
- } else if (max_frame <= IXGB_RXBUFFER_8192) {
+ } else if(max_frame <= IXGB_RXBUFFER_8192) {
adapter->rx_buffer_len = IXGB_RXBUFFER_8192;
} else {
@@ -1462,7 +1489,7 @@ static int ixgb_change_mtu(struct net_device *netdev, int new_mtu)
netdev->mtu = new_mtu;
- if (old_mtu != adapter->rx_buffer_len && netif_running(netdev)) {
+ if(old_max_frame != max_frame && netif_running(netdev)) {
ixgb_down(adapter, TRUE);
ixgb_up(adapter);
@@ -1476,7 +1503,8 @@ static int ixgb_change_mtu(struct net_device *netdev, int new_mtu)
* @adapter: board private structure
**/
-static void ixgb_update_stats(struct ixgb_adapter *adapter)
+void
+ixgb_update_stats(struct ixgb_adapter *adapter)
{
adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL);
adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH);
@@ -1585,31 +1613,33 @@ static void ixgb_update_stats(struct ixgb_adapter *adapter)
* @pt_regs: CPU registers structure
**/
-static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t
+ixgb_intr(int irq, void *data, struct pt_regs *regs)
{
struct net_device *netdev = data;
struct ixgb_adapter *adapter = netdev->priv;
struct ixgb_hw *hw = &adapter->hw;
- uint32_t icr = IXGB_READ_REG(&adapter->hw, ICR);
+ uint32_t icr = IXGB_READ_REG(hw, ICR);
#ifndef CONFIG_IXGB_NAPI
unsigned int i;
#endif
- if (unlikely(!icr))
- return IRQ_NONE; /* Not our interrupt */
+ if(unlikely(!icr))
+ return IRQ_NONE; /* Not our interrupt */
- if (unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) {
+ if(unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) {
mod_timer(&adapter->watchdog_timer, jiffies);
}
+
#ifdef CONFIG_IXGB_NAPI
- if (netif_rx_schedule_prep(netdev)) {
+ if(netif_rx_schedule_prep(netdev)) {
/* Disable interrupts and register for poll. The flush
- of the posted write is intentionally left out.
- */
+ of the posted write is intentionally left out.
+ */
atomic_inc(&adapter->irq_sem);
- IXGB_WRITE_REG(hw, IMC, ~0);
+ IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
__netif_rx_schedule(netdev);
}
#else
@@ -1621,16 +1651,7 @@ static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs)
if(!ixgb_clean_rx_irq(adapter) &
!ixgb_clean_tx_irq(adapter))
break;
- /* if RAIDC:EN == 1 and ICR:RXDMT0 == 1, we need to
- * set IMS:RXDMT0 to 1 to restart the RBD timer (POLL)
- */
- if ((icr & IXGB_INT_RXDMT0) && adapter->raidc) {
- /* ready the timer by writing the clear reg */
- IXGB_WRITE_REG(hw, IMC, IXGB_INT_RXDMT0);
- /* now restart it, h/w will decide if its necessary */
- IXGB_WRITE_REG(hw, IMS, IXGB_INT_RXDMT0);
- }
-#endif
+#endif
return IRQ_HANDLED;
}
@@ -1640,25 +1661,32 @@ static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs)
* @adapter: board private structure
**/
-static int ixgb_clean(struct net_device *netdev, int *budget)
+static int
+ixgb_clean(struct net_device *netdev, int *budget)
{
struct ixgb_adapter *adapter = netdev->priv;
int work_to_do = min(*budget, netdev->quota);
+ int tx_cleaned;
int work_done = 0;
+
+ if (!netif_carrier_ok(netdev))
+ goto quit_polling;
- ixgb_clean_tx_irq(adapter);
+ tx_cleaned = ixgb_clean_tx_irq(adapter);
ixgb_clean_rx_irq(adapter, &work_done, work_to_do);
*budget -= work_done;
netdev->quota -= work_done;
-
- if (work_done < work_to_do || !netif_running(netdev)) {
- netif_rx_complete(netdev);
- /* RAIDC will be automatically restarted by irq_enable */
+
+ /* if no Tx cleanup and not enough Rx work done, exit the polling mode */
+ if((!tx_cleaned && (work_done < work_to_do)) ||
+ !netif_running(netdev)) {
+quit_polling: netif_rx_complete(netdev);
ixgb_irq_enable(adapter);
+ return 0;
}
- return (work_done >= work_to_do);
+ return 1;
}
#endif
@@ -1667,11 +1695,11 @@ static int ixgb_clean(struct net_device *netdev, int *budget)
* @adapter: board private structure
**/
-static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+static boolean_t
+ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
struct net_device *netdev = adapter->netdev;
- struct pci_dev *pdev = adapter->pdev;
struct ixgb_tx_desc *tx_desc, *eop_desc;
struct ixgb_buffer *buffer_info;
unsigned int i, eop;
@@ -1681,9 +1709,9 @@ static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = IXGB_TX_DESC(*tx_ring, eop);
- while (eop_desc->status & IXGB_TX_DESC_STATUS_DD) {
+ while(eop_desc->status & IXGB_TX_DESC_STATUS_DD) {
- for (cleaned = FALSE; !cleaned;) {
+ for(cleaned = FALSE; !cleaned; ) {
tx_desc = IXGB_TX_DESC(*tx_ring, i);
buffer_info = &tx_ring->buffer_info[i];
@@ -1692,28 +1720,12 @@ static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
IXGB_TX_DESC_POPTS_IXSM))
adapter->hw_csum_tx_good++;
- if (buffer_info->dma) {
-
- pci_unmap_page(pdev,
- buffer_info->dma,
- buffer_info->length,
- PCI_DMA_TODEVICE);
-
- buffer_info->dma = 0;
- }
+ ixgb_unmap_and_free_tx_resource(adapter, buffer_info);
- if (buffer_info->skb) {
-
- dev_kfree_skb_any(buffer_info->skb);
-
- buffer_info->skb = NULL;
- }
-
- *(uint32_t *) & (tx_desc->status) = 0;
+ *(uint32_t *)&(tx_desc->status) = 0;
cleaned = (i == eop);
- if (++i == tx_ring->count)
- i = 0;
+ if(++i == tx_ring->count) i = 0;
}
eop = tx_ring->buffer_info[i].next_to_watch;
@@ -1723,8 +1735,8 @@ static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
tx_ring->next_to_clean = i;
spin_lock(&adapter->tx_lock);
- if (cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev)
- && (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE)) {
+ if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
+ (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE)) {
netif_wake_queue(netdev);
}
@@ -1742,20 +1754,21 @@ static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
static inline void
ixgb_rx_checksum(struct ixgb_adapter *adapter,
- struct ixgb_rx_desc *rx_desc, struct sk_buff *skb)
+ struct ixgb_rx_desc *rx_desc,
+ struct sk_buff *skb)
{
/* Ignore Checksum bit is set OR
* TCP Checksum has not been calculated
*/
- if ((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) ||
- (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) {
+ if((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) ||
+ (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) {
skb->ip_summed = CHECKSUM_NONE;
return;
}
/* At this point we know the hardware did the TCP checksum */
/* now look at the TCP checksum error bit */
- if (rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) {
+ if(rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) {
/* let the stack verify checksum errors */
skb->ip_summed = CHECKSUM_NONE;
adapter->hw_csum_rx_error++;
@@ -1792,18 +1805,22 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
rx_desc = IXGB_RX_DESC(*rx_ring, i);
buffer_info = &rx_ring->buffer_info[i];
- while (rx_desc->status & IXGB_RX_DESC_STATUS_DD) {
+ while(rx_desc->status & IXGB_RX_DESC_STATUS_DD) {
+
+#ifdef CONFIG_IXGB_NAPI
+ if(*work_done >= work_to_do)
+ break;
+ (*work_done)++;
+#endif
skb = buffer_info->skb;
prefetch(skb->data);
- if (++i == rx_ring->count)
- i = 0;
+ if(++i == rx_ring->count) i = 0;
next_rxd = IXGB_RX_DESC(*rx_ring, i);
prefetch(next_rxd);
- if ((j = i + 1) == rx_ring->count)
- j = 0;
+ if((j = i + 1) == rx_ring->count) j = 0;
next2_buffer = &rx_ring->buffer_info[j];
prefetch(next2_buffer);
@@ -1811,27 +1828,22 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
next_skb = next_buffer->skb;
prefetch(next_skb);
-#ifdef CONFIG_IXGB_NAPI
- if (*work_done >= work_to_do)
- break;
-
- (*work_done)++;
-#endif
cleaned = TRUE;
pci_unmap_single(pdev,
buffer_info->dma,
- buffer_info->length, PCI_DMA_FROMDEVICE);
+ buffer_info->length,
+ PCI_DMA_FROMDEVICE);
length = le16_to_cpu(rx_desc->length);
- if (unlikely(!(rx_desc->status & IXGB_RX_DESC_STATUS_EOP))) {
+ if(unlikely(!(rx_desc->status & IXGB_RX_DESC_STATUS_EOP))) {
/* All receives must fit into a single buffer */
IXGB_DBG("Receive packet consumed multiple buffers "
- "length<%x>\n", length);
+ "length<%x>\n", length);
dev_kfree_skb_irq(skb);
rx_desc->status = 0;
@@ -1864,26 +1876,22 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
skb->protocol = eth_type_trans(skb, netdev);
#ifdef CONFIG_IXGB_NAPI
- if (adapter->vlgrp
- && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
+ if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->
- special &
- IXGB_RX_DESC_SPECIAL_VLAN_MASK));
+ le16_to_cpu(rx_desc->special) &
+ IXGB_RX_DESC_SPECIAL_VLAN_MASK);
} else {
netif_receive_skb(skb);
}
-#else /* CONFIG_IXGB_NAPI */
- if (adapter->vlgrp
- && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
+#else /* CONFIG_IXGB_NAPI */
+ if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->
- special &
- IXGB_RX_DESC_SPECIAL_VLAN_MASK));
+ le16_to_cpu(rx_desc->special) &
+ IXGB_RX_DESC_SPECIAL_VLAN_MASK);
} else {
netif_rx(skb);
}
-#endif /* CONFIG_IXGB_NAPI */
+#endif /* CONFIG_IXGB_NAPI */
netdev->last_rx = jiffies;
rx_desc->status = 0;
@@ -1905,7 +1913,8 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
* @adapter: address of board private structure
**/
-static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
+static void
+ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
{
struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
@@ -1921,19 +1930,15 @@ static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
buffer_info = &rx_ring->buffer_info[i];
cleancount = IXGB_DESC_UNUSED(rx_ring);
- /* lessen this to 4 if we're
- * in the midst of raidc and rbd is occuring
- * because we don't want to delay returning buffers when low
- */
- num_group_tail_writes = adapter->raidc ? 4 : IXGB_RX_BUFFER_WRITE;
+ num_group_tail_writes = IXGB_RX_BUFFER_WRITE;
/* leave one descriptor unused */
- while (--cleancount > 0) {
+ while(--cleancount > 0) {
rx_desc = IXGB_RX_DESC(*rx_ring, i);
skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
- if (unlikely(!skb)) {
+ if(unlikely(!skb)) {
/* Better luck next round */
break;
}
@@ -1949,13 +1954,14 @@ static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
buffer_info->skb = skb;
buffer_info->length = adapter->rx_buffer_len;
buffer_info->dma =
- pci_map_single(pdev,
+ pci_map_single(pdev,
skb->data,
- adapter->rx_buffer_len, PCI_DMA_FROMDEVICE);
+ adapter->rx_buffer_len,
+ PCI_DMA_FROMDEVICE);
rx_desc->buff_addr = cpu_to_le64(buffer_info->dma);
- if ((i & ~(num_group_tail_writes - 1)) == i) {
+ if((i & ~(num_group_tail_writes- 1)) == i) {
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs,
@@ -1965,8 +1971,7 @@ static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
IXGB_WRITE_REG(&adapter->hw, RDT, i);
}
- if (++i == rx_ring->count)
- i = 0;
+ if(++i == rx_ring->count) i = 0;
buffer_info = &rx_ring->buffer_info[i];
}
@@ -1988,7 +1993,7 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
ixgb_irq_disable(adapter);
adapter->vlgrp = grp;
- if (grp) {
+ if(grp) {
/* enable VLAN tag insert/strip */
ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
ctrl |= IXGB_CTRL0_VME;
@@ -2017,7 +2022,8 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
ixgb_irq_enable(adapter);
}
-static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
+static void
+ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
{
struct ixgb_adapter *adapter = netdev->priv;
uint32_t vfta, index;
@@ -2030,19 +2036,20 @@ static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
ixgb_write_vfta(&adapter->hw, index, vfta);
}
-static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
+static void
+ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
{
struct ixgb_adapter *adapter = netdev->priv;
uint32_t vfta, index;
ixgb_irq_disable(adapter);
- if (adapter->vlgrp)
+ if(adapter->vlgrp)
adapter->vlgrp->vlan_devices[vid] = NULL;
ixgb_irq_enable(adapter);
- /* remove VID from filter table */
+ /* remove VID from filter table*/
index = (vid >> 5) & 0x7F;
vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
@@ -2050,14 +2057,15 @@ static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
ixgb_write_vfta(&adapter->hw, index, vfta);
}
-static void ixgb_restore_vlan(struct ixgb_adapter *adapter)
+static void
+ixgb_restore_vlan(struct ixgb_adapter *adapter)
{
ixgb_vlan_rx_register(adapter->netdev, adapter->vlgrp);
- if (adapter->vlgrp) {
+ if(adapter->vlgrp) {
uint16_t vid;
- for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
- if (!adapter->vlgrp->vlan_devices[vid])
+ for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ if(!adapter->vlgrp->vlan_devices[vid])
continue;
ixgb_vlan_rx_add_vid(adapter->netdev, vid);
}
@@ -2075,7 +2083,7 @@ ixgb_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
{
struct pci_dev *pdev = NULL;
- switch (event) {
+ switch(event) {
case SYS_DOWN:
case SYS_HALT:
case SYS_POWER_OFF:
@@ -2092,14 +2100,15 @@ ixgb_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
* @param pdev pci driver structure used for passing to
* @param state power state to enter
**/
-static int ixgb_suspend(struct pci_dev *pdev, uint32_t state)
+static int
+ixgb_suspend(struct pci_dev *pdev, uint32_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgb_adapter *adapter = netdev->priv;
netif_device_detach(netdev);
- if (netif_running(netdev))
+ if(netif_running(netdev))
ixgb_down(adapter, TRUE);
pci_save_state(pdev);
diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h
index 892f86caeaba..5d254b30b93a 100644
--- a/drivers/net/ixgb/ixgb_osdep.h
+++ b/drivers/net/ixgb/ixgb_osdep.h
@@ -78,19 +78,19 @@ typedef enum {
#define DEBUGOUT7 DEBUGOUT3
#define IXGB_WRITE_REG(a, reg, value) ( \
- writel((value), ((a)->hw_addr + IXGB_##reg)))
+ writel((value), ((a)->hw_addr + IXGB_##reg)))
#define IXGB_READ_REG(a, reg) ( \
- readl((a)->hw_addr + IXGB_##reg))
+ readl((a)->hw_addr + IXGB_##reg))
#define IXGB_WRITE_REG_ARRAY(a, reg, offset, value) ( \
- writel((value), ((a)->hw_addr + IXGB_##reg + ((offset) << 2))))
+ writel((value), ((a)->hw_addr + IXGB_##reg + ((offset) << 2))))
#define IXGB_READ_REG_ARRAY(a, reg, offset) ( \
- readl((a)->hw_addr + IXGB_##reg + ((offset) << 2)))
+ readl((a)->hw_addr + IXGB_##reg + ((offset) << 2)))
#define IXGB_WRITE_FLUSH(a) IXGB_READ_REG(a, STATUS)
#define IXGB_MEMCPY memcpy
-#endif /* _IXGB_OSDEP_H_ */
+#endif /* _IXGB_OSDEP_H_ */
diff --git a/drivers/net/ixgb/ixgb_param.c b/drivers/net/ixgb/ixgb_param.c
index 0cb1027fc295..23379279ea1a 100644
--- a/drivers/net/ixgb/ixgb_param.c
+++ b/drivers/net/ixgb/ixgb_param.c
@@ -34,31 +34,21 @@
#define IXGB_MAX_NIC 8
-#define OPTION_UNSET -1
+#define OPTION_UNSET -1
#define OPTION_DISABLED 0
#define OPTION_ENABLED 1
-/* Module Parameters are always initialized to -1, so that the driver
- * can tell the difference between no user specified value or the
- * user asking for the default value.
- * The true default values are loaded in when ixgb_check_options is called.
- *
- * This is a GCC extension to ANSI C.
- * See the item "Labeled Elements in Initializers" in the section
- * "Extensions to the C Language Family" of the GCC documentation.
- */
-
-#define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET }
-
/* All parameters are treated the same, as an integer array of values.
* This macro just reduces the need to repeat the same declaration code
* over and over (plus this helps to avoid typo bugs).
*/
-#define IXGB_PARAM(X, S) \
-static int __devinitdata X[IXGB_MAX_NIC + 1] = IXGB_PARAM_INIT; \
-module_param_array(X, int, NULL, 0); \
-MODULE_PARM_DESC(X, S);
+#define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET }
+#define IXGB_PARAM(X, desc) \
+ static int __devinitdata X[IXGB_MAX_NIC+1] = IXGB_PARAM_INIT; \
+ static int num_##X = 0; \
+ module_param_array_named(X, X, int, &num_##X, 0); \
+ MODULE_PARM_DESC(X, desc);
/* Transmit Descriptor Count
*
@@ -121,15 +111,6 @@ IXGB_PARAM(TxIntDelay, "Transmit Interrupt Delay");
IXGB_PARAM(RxIntDelay, "Receive Interrupt Delay");
-/* Receive Interrupt Moderation enable (uses RxIntDelay too)
- *
- * Valid Range: 0,1
- *
- * Default Value: 1
- */
-
-IXGB_PARAM(RAIDC, "Disable or enable Receive Interrupt Moderation");
-
/* Receive Flow control high threshold (when we send a pause frame)
* (FCRTH)
*
@@ -173,13 +154,6 @@ IXGB_PARAM(FCReqTimeout, "Flow Control Request Timeout");
IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable");
-#define DEFAULT_TXD 256
-#define MAX_TXD 4096
-#define MIN_TXD 64
-
-#define DEFAULT_RXD 1024
-#define MAX_RXD 4096
-#define MIN_RXD 64
#define DEFAULT_TIDV 32
#define MAX_TIDV 0xFFFF
@@ -224,9 +198,10 @@ struct ixgb_option {
} arg;
};
-static int __devinit ixgb_validate_option(int *value, struct ixgb_option *opt)
+static int __devinit
+ixgb_validate_option(int *value, struct ixgb_option *opt)
{
- if (*value == OPTION_UNSET) {
+ if(*value == OPTION_UNSET) {
*value = opt->def;
return 0;
}
@@ -243,32 +218,31 @@ static int __devinit ixgb_validate_option(int *value, struct ixgb_option *opt)
}
break;
case range_option:
- if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+ if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
printk(KERN_INFO "%s set to %i\n", opt->name, *value);
return 0;
}
break;
- case list_option:{
- int i;
- struct ixgb_opt_list *ent;
-
- for (i = 0; i < opt->arg.l.nr; i++) {
- ent = &opt->arg.l.p[i];
- if (*value == ent->i) {
- if (ent->str[0] != '\0')
- printk(KERN_INFO "%s\n",
- ent->str);
- return 0;
- }
+ case list_option: {
+ int i;
+ struct ixgb_opt_list *ent;
+
+ for(i = 0; i < opt->arg.l.nr; i++) {
+ ent = &opt->arg.l.p[i];
+ if(*value == ent->i) {
+ if(ent->str[0] != '\0')
+ printk(KERN_INFO "%s\n", ent->str);
+ return 0;
}
}
+ }
break;
default:
BUG();
}
printk(KERN_INFO "Invalid %s specified (%i) %s\n",
- opt->name, *value, opt->err);
+ opt->name, *value, opt->err);
*value = opt->def;
return -1;
}
@@ -285,198 +259,218 @@ static int __devinit ixgb_validate_option(int *value, struct ixgb_option *opt)
* in a variable in the adapter structure.
**/
-void __devinit ixgb_check_options(struct ixgb_adapter *adapter)
+void __devinit
+ixgb_check_options(struct ixgb_adapter *adapter)
{
int bd = adapter->bd_number;
- if (bd >= IXGB_MAX_NIC) {
+ if(bd >= IXGB_MAX_NIC) {
printk(KERN_NOTICE
- "Warning: no configuration for board #%i\n", bd);
+ "Warning: no configuration for board #%i\n", bd);
printk(KERN_NOTICE "Using defaults for all values\n");
- bd = IXGB_MAX_NIC;
}
- { /* Transmit Descriptor Count */
+ { /* Transmit Descriptor Count */
struct ixgb_option opt = {
.type = range_option,
.name = "Transmit Descriptors",
- .err = "using default of " __MODULE_STRING(DEFAULT_TXD),
- .def = DEFAULT_TXD,
- .arg = {.r = {.min = MIN_TXD,
- .max = MAX_TXD}}
+ .err = "using default of " __MODULE_STRING(DEFAULT_TXD),
+ .def = DEFAULT_TXD,
+ .arg = { .r = { .min = MIN_TXD,
+ .max = MAX_TXD}}
};
struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
- tx_ring->count = TxDescriptors[bd];
- ixgb_validate_option(&tx_ring->count, &opt);
+ if(num_TxDescriptors > bd) {
+ tx_ring->count = TxDescriptors[bd];
+ ixgb_validate_option(&tx_ring->count, &opt);
+ } else {
+ tx_ring->count = opt.def;
+ }
IXGB_ROUNDUP(tx_ring->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
}
- { /* Receive Descriptor Count */
+ { /* Receive Descriptor Count */
struct ixgb_option opt = {
.type = range_option,
.name = "Receive Descriptors",
- .err = "using default of " __MODULE_STRING(DEFAULT_RXD),
- .def = DEFAULT_RXD,
- .arg = {.r = {.min = MIN_RXD,
- .max = MAX_RXD}}
+ .err = "using default of " __MODULE_STRING(DEFAULT_RXD),
+ .def = DEFAULT_RXD,
+ .arg = { .r = { .min = MIN_RXD,
+ .max = MAX_RXD}}
};
struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
- rx_ring->count = RxDescriptors[bd];
- ixgb_validate_option(&rx_ring->count, &opt);
+ if(num_RxDescriptors > bd) {
+ rx_ring->count = RxDescriptors[bd];
+ ixgb_validate_option(&rx_ring->count, &opt);
+ } else {
+ rx_ring->count = opt.def;
+ }
IXGB_ROUNDUP(rx_ring->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
}
- { /* Receive Checksum Offload Enable */
+ { /* Receive Checksum Offload Enable */
struct ixgb_option opt = {
.type = enable_option,
.name = "Receive Checksum Offload",
- .err = "defaulting to Enabled",
- .def = OPTION_ENABLED
+ .err = "defaulting to Enabled",
+ .def = OPTION_ENABLED
};
- int rx_csum = XsumRX[bd];
- ixgb_validate_option(&rx_csum, &opt);
- adapter->rx_csum = rx_csum;
+ if(num_XsumRX > bd) {
+ int rx_csum = XsumRX[bd];
+ ixgb_validate_option(&rx_csum, &opt);
+ adapter->rx_csum = rx_csum;
+ } else {
+ adapter->rx_csum = opt.def;
+ }
}
- { /* Flow Control */
+ { /* Flow Control */
struct ixgb_opt_list fc_list[] =
- { {ixgb_fc_none, "Flow Control Disabled"},
- {ixgb_fc_rx_pause, "Flow Control Receive Only"},
- {ixgb_fc_tx_pause, "Flow Control Transmit Only"},
- {ixgb_fc_full, "Flow Control Enabled"},
- {ixgb_fc_default, "Flow Control Hardware Default"}
- };
+ {{ ixgb_fc_none, "Flow Control Disabled" },
+ { ixgb_fc_rx_pause,"Flow Control Receive Only" },
+ { ixgb_fc_tx_pause,"Flow Control Transmit Only" },
+ { ixgb_fc_full, "Flow Control Enabled" },
+ { ixgb_fc_default, "Flow Control Hardware Default" }};
struct ixgb_option opt = {
.type = list_option,
.name = "Flow Control",
- .err = "reading default settings from EEPROM",
- .def = ixgb_fc_full,
- .arg = {.l = {.nr = LIST_LEN(fc_list),
- .p = fc_list}}
+ .err = "reading default settings from EEPROM",
+ .def = ixgb_fc_full,
+ .arg = { .l = { .nr = LIST_LEN(fc_list),
+ .p = fc_list }}
};
- int fc = FlowControl[bd];
- ixgb_validate_option(&fc, &opt);
- adapter->hw.fc.type = fc;
+ if(num_FlowControl > bd) {
+ int fc = FlowControl[bd];
+ ixgb_validate_option(&fc, &opt);
+ adapter->hw.fc.type = fc;
+ } else {
+ adapter->hw.fc.type = opt.def;
+ }
}
- { /* Receive Flow Control High Threshold */
+ { /* Receive Flow Control High Threshold */
struct ixgb_option opt = {
.type = range_option,
.name = "Rx Flow Control High Threshold",
- .err =
- "using default of " __MODULE_STRING(DEFAULT_FCRTH),
- .def = DEFAULT_FCRTH,
- .arg = {.r = {.min = MIN_FCRTH,
- .max = MAX_FCRTH}}
+ .err = "using default of " __MODULE_STRING(DEFAULT_FCRTH),
+ .def = DEFAULT_FCRTH,
+ .arg = { .r = { .min = MIN_FCRTH,
+ .max = MAX_FCRTH}}
};
- adapter->hw.fc.high_water = RxFCHighThresh[bd];
- ixgb_validate_option(&adapter->hw.fc.high_water, &opt);
- if (!(adapter->hw.fc.type & ixgb_fc_rx_pause))
- printk(KERN_INFO
- "Ignoring RxFCHighThresh when no RxFC\n");
+ if(num_RxFCHighThresh > bd) {
+ adapter->hw.fc.high_water = RxFCHighThresh[bd];
+ ixgb_validate_option(&adapter->hw.fc.high_water, &opt);
+ } else {
+ adapter->hw.fc.high_water = opt.def;
+ }
+ if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
+ printk (KERN_INFO
+ "Ignoring RxFCHighThresh when no RxFC\n");
}
- { /* Receive Flow Control Low Threshold */
+ { /* Receive Flow Control Low Threshold */
struct ixgb_option opt = {
.type = range_option,
.name = "Rx Flow Control Low Threshold",
- .err =
- "using default of " __MODULE_STRING(DEFAULT_FCRTL),
- .def = DEFAULT_FCRTL,
- .arg = {.r = {.min = MIN_FCRTL,
- .max = MAX_FCRTL}}
+ .err = "using default of " __MODULE_STRING(DEFAULT_FCRTL),
+ .def = DEFAULT_FCRTL,
+ .arg = { .r = { .min = MIN_FCRTL,
+ .max = MAX_FCRTL}}
};
- adapter->hw.fc.low_water = RxFCLowThresh[bd];
- ixgb_validate_option(&adapter->hw.fc.low_water, &opt);
- if (!(adapter->hw.fc.type & ixgb_fc_rx_pause))
- printk(KERN_INFO
- "Ignoring RxFCLowThresh when no RxFC\n");
+ if(num_RxFCLowThresh > bd) {
+ adapter->hw.fc.low_water = RxFCLowThresh[bd];
+ ixgb_validate_option(&adapter->hw.fc.low_water, &opt);
+ } else {
+ adapter->hw.fc.low_water = opt.def;
+ }
+ if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
+ printk (KERN_INFO
+ "Ignoring RxFCLowThresh when no RxFC\n");
}
- { /* Flow Control Pause Time Request */
+ { /* Flow Control Pause Time Request*/
struct ixgb_option opt = {
.type = range_option,
.name = "Flow Control Pause Time Request",
- .err =
- "using default of "
- __MODULE_STRING(DEFAULT_FCPAUSE),
- .def = DEFAULT_FCPAUSE,
- .arg = {.r = {.min = MIN_FCPAUSE,
- .max = MAX_FCPAUSE}}
+ .err = "using default of "__MODULE_STRING(DEFAULT_FCPAUSE),
+ .def = DEFAULT_FCPAUSE,
+ .arg = { .r = { .min = MIN_FCPAUSE,
+ .max = MAX_FCPAUSE}}
};
- int pause_time = FCReqTimeout[bd];
-
- ixgb_validate_option(&pause_time, &opt);
- if (!(adapter->hw.fc.type & ixgb_fc_rx_pause))
- printk(KERN_INFO
- "Ignoring FCReqTimeout when no RxFC\n");
- adapter->hw.fc.pause_time = pause_time;
+ if(num_FCReqTimeout > bd) {
+ int pause_time = FCReqTimeout[bd];
+ ixgb_validate_option(&pause_time, &opt);
+ adapter->hw.fc.pause_time = pause_time;
+ } else {
+ adapter->hw.fc.pause_time = opt.def;
+ }
+ if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
+ printk (KERN_INFO
+ "Ignoring FCReqTimeout when no RxFC\n");
}
/* high low and spacing check for rx flow control thresholds */
if (adapter->hw.fc.type & ixgb_fc_rx_pause) {
/* high must be greater than low */
if (adapter->hw.fc.high_water < (adapter->hw.fc.low_water + 8)) {
/* set defaults */
- printk(KERN_INFO
- "RxFCHighThresh must be >= (RxFCLowThresh + 8), "
- "Using Defaults\n");
+ printk (KERN_INFO
+ "RxFCHighThresh must be >= (RxFCLowThresh + 8), "
+ "Using Defaults\n");
adapter->hw.fc.high_water = DEFAULT_FCRTH;
- adapter->hw.fc.low_water = DEFAULT_FCRTL;
+ adapter->hw.fc.low_water = DEFAULT_FCRTL;
}
}
- { /* Receive Interrupt Delay */
+ { /* Receive Interrupt Delay */
struct ixgb_option opt = {
.type = range_option,
.name = "Receive Interrupt Delay",
- .err =
- "using default of " __MODULE_STRING(DEFAULT_RDTR),
- .def = DEFAULT_RDTR,
- .arg = {.r = {.min = MIN_RDTR,
- .max = MAX_RDTR}}
+ .err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
+ .def = DEFAULT_RDTR,
+ .arg = { .r = { .min = MIN_RDTR,
+ .max = MAX_RDTR}}
};
- adapter->rx_int_delay = RxIntDelay[bd];
- ixgb_validate_option(&adapter->rx_int_delay, &opt);
- }
- { /* Receive Interrupt Moderation */
- struct ixgb_option opt = {
- .type = enable_option,
- .name = "Advanced Receive Interrupt Moderation",
- .err = "defaulting to Enabled",
- .def = OPTION_ENABLED
- };
- int raidc = RAIDC[bd];
-
- ixgb_validate_option(&raidc, &opt);
- adapter->raidc = raidc;
+ if(num_RxIntDelay > bd) {
+ adapter->rx_int_delay = RxIntDelay[bd];
+ ixgb_validate_option(&adapter->rx_int_delay, &opt);
+ } else {
+ adapter->rx_int_delay = opt.def;
+ }
}
- { /* Transmit Interrupt Delay */
+ { /* Transmit Interrupt Delay */
struct ixgb_option opt = {
.type = range_option,
.name = "Transmit Interrupt Delay",
- .err =
- "using default of " __MODULE_STRING(DEFAULT_TIDV),
- .def = DEFAULT_TIDV,
- .arg = {.r = {.min = MIN_TIDV,
- .max = MAX_TIDV}}
+ .err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
+ .def = DEFAULT_TIDV,
+ .arg = { .r = { .min = MIN_TIDV,
+ .max = MAX_TIDV}}
};
- adapter->tx_int_delay = TxIntDelay[bd];
- ixgb_validate_option(&adapter->tx_int_delay, &opt);
+ if(num_TxIntDelay > bd) {
+ adapter->tx_int_delay = TxIntDelay[bd];
+ ixgb_validate_option(&adapter->tx_int_delay, &opt);
+ } else {
+ adapter->tx_int_delay = opt.def;
+ }
}
- { /* Transmit Interrupt Delay Enable */
+ { /* Transmit Interrupt Delay Enable */
struct ixgb_option opt = {
.type = enable_option,
.name = "Tx Interrupt Delay Enable",
- .err = "defaulting to Enabled",
- .def = OPTION_ENABLED
+ .err = "defaulting to Enabled",
+ .def = OPTION_ENABLED
};
- int ide = IntDelayEnable[bd];
- ixgb_validate_option(&ide, &opt);
- adapter->tx_int_delay_enable = ide;
+ if(num_IntDelayEnable > bd) {
+ int ide = IntDelayEnable[bd];
+ ixgb_validate_option(&ide, &opt);
+ adapter->tx_int_delay_enable = ide;
+ } else {
+ adapter->tx_int_delay_enable = opt.def;
+ }
}
}
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 08ffa1bcb68c..3e05fd774128 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -322,7 +322,6 @@ static dev_link_t *tc574_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -519,6 +518,7 @@ static void tc574_config(dev_link_t *link)
link->state &= ~DEV_CONFIG_PENDING;
link->dev = &lp->node;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
@@ -1308,8 +1308,7 @@ static int __init init_tc574(void)
static void __exit exit_tc574(void)
{
pcmcia_unregister_driver(&tc574_driver);
- while (dev_list != NULL)
- tc574_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_tc574);
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 06ace14a6ba2..00c82eafb21b 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -236,7 +236,6 @@ static dev_link_t *tc589_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -391,6 +390,7 @@ static void tc589_config(dev_link_t *link)
link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if (register_netdev(dev) != 0) {
printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
@@ -1083,8 +1083,7 @@ static int __init init_tc589(void)
static void __exit exit_tc589(void)
{
pcmcia_unregister_driver(&tc589_driver);
- while (dev_list != NULL)
- tc589_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_tc589);
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 957bd2e8ab89..c61fba0ea898 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -191,7 +191,6 @@ static dev_link_t *axnet_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -458,6 +457,7 @@ static void axnet_config(dev_link_t *link)
info->phy_id = (i < 32) ? i : -1;
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n");
@@ -877,8 +877,7 @@ static int __init init_axnet_cs(void)
static void __exit exit_axnet_cs(void)
{
pcmcia_unregister_driver(&axnet_cs_driver);
- while (dev_list != NULL)
- axnet_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_axnet_cs);
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index fbdc0b7a53d7..211fdac0a6eb 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -211,7 +211,6 @@ static dev_link_t *com20020_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -394,6 +393,7 @@ static void com20020_config(dev_link_t *link)
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
i = com20020_found(dev, 0); /* calls register_netdev */
@@ -513,8 +513,7 @@ static int __init init_com20020_cs(void)
static void __exit exit_com20020_cs(void)
{
pcmcia_unregister_driver(&com20020_cs_driver);
- while (dev_list != NULL)
- com20020_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_com20020_cs);
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index d676aba69dc1..850f1d94c5d6 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -299,7 +299,6 @@ static dev_link_t *fmvj18x_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -591,6 +590,7 @@ static void fmvj18x_config(dev_link_t *link)
lp->cardtype = cardtype;
link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
@@ -792,8 +792,7 @@ static int __init init_fmvj18x_cs(void)
static void __exit exit_fmvj18x_cs(void)
{
pcmcia_unregister_driver(&fmvj18x_cs_driver);
- while (dev_list != NULL)
- fmvj18x_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_fmvj18x_cs);
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index dbdcbc6cec05..c3ca9fb65912 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -204,7 +204,6 @@ static dev_link_t *ibmtr_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -366,6 +365,7 @@ static void ibmtr_config(dev_link_t *link)
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
i = ibmtr_probe_card(dev);
if (i != 0) {
@@ -538,8 +538,7 @@ static int __init init_ibmtr_cs(void)
static void __exit exit_ibmtr_cs(void)
{
pcmcia_unregister_driver(&ibmtr_cs_driver);
- while (dev_list != NULL)
- ibmtr_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_ibmtr_cs);
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index f97ce65d76b0..35e66f0f9e42 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -512,7 +512,6 @@ static dev_link_t *nmclan_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -775,6 +774,7 @@ static void nmclan_config(dev_link_t *link)
link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
i = register_netdev(dev);
if (i != 0) {
@@ -1702,8 +1702,7 @@ static int __init init_nmclan_cs(void)
static void __exit exit_nmclan_cs(void)
{
pcmcia_unregister_driver(&nmclan_cs_driver);
- while (dev_list != NULL)
- nmclan_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_nmclan_cs);
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index b17b3fb86296..ddaf72136c2d 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -286,7 +286,6 @@ static dev_link_t *pcnet_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -722,6 +721,7 @@ static void pcnet_config(dev_link_t *link)
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = ei_poll;
@@ -1662,8 +1662,7 @@ static void __exit exit_pcnet_cs(void)
{
DEBUG(0, "pcnet_cs: unloading\n");
pcmcia_unregister_driver(&pcnet_driver);
- while (dev_list != NULL)
- pcnet_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_pcnet_cs);
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 284375f2026c..78f84e1f9fc8 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -374,7 +374,6 @@ static dev_link_t *smc91c92_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
@@ -1024,6 +1023,7 @@ static void smc91c92_config(dev_link_t *link)
link->dev = &smc->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if (register_netdev(dev) != 0) {
printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
@@ -2263,8 +2263,7 @@ static int __init init_smc91c92_cs(void)
static void __exit exit_smc91c92_cs(void)
{
pcmcia_unregister_driver(&smc91c92_cs_driver);
- while (dev_list != NULL)
- smc91c92_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_smc91c92_cs);
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 6f4eeaf7f5de..aadbb787982c 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -627,7 +627,6 @@ xirc2ps_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -1121,6 +1120,7 @@ xirc2ps_config(dev_link_t * link)
link->dev = &local->node;
link->state &= ~DEV_CONFIG_PENDING;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if ((err=register_netdev(dev))) {
printk(KNOT_XIRC "register_netdev() failed\n");
@@ -2016,9 +2016,7 @@ static void __exit
exit_xirc2ps_cs(void)
{
pcmcia_unregister_driver(&xirc2ps_cs_driver);
-
- while (dev_list)
- xirc2ps_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_xirc2ps_cs);
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index eca5b66cdb4f..0393ee5ecd85 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -560,21 +560,35 @@ static void free_shared_mem(struct s2io_nic *nic)
for (i = 0; i < config->rx_ring_num; i++) {
blk_cnt =
config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
+ if (!nic->ba[i])
+ goto end_free;
for (j = 0; j < blk_cnt; j++) {
int k = 0;
- if (!nic->ba[i][j])
- continue;
+ if (!nic->ba[i][j]) {
+ kfree(nic->ba[i]);
+ goto end_free;
+ }
while (k != MAX_RXDS_PER_BLOCK) {
buffAdd_t *ba = &nic->ba[i][j][k];
+ if (!ba || !ba->ba_0_org || !ba->ba_1_org)
+ {
+ kfree(nic->ba[i]);
+ kfree(nic->ba[i][j]);
+ if(ba->ba_0_org)
+ kfree(ba->ba_0_org);
+ if(ba->ba_1_org)
+ kfree(ba->ba_1_org);
+ goto end_free;
+ }
kfree(ba->ba_0_org);
kfree(ba->ba_1_org);
k++;
}
kfree(nic->ba[i][j]);
}
- if (nic->ba[i])
- kfree(nic->ba[i]);
+ kfree(nic->ba[i]);
}
+end_free:
#endif
if (mac_control->stats_mem) {
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index d2deaaf5d98b..b4cc65dbf2a7 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -740,8 +740,8 @@ static inline u64 readq(void *addr)
{
u64 ret = 0;
ret = readl(addr + 4);
- (u64) ret <<= 32;
- (u64) ret |= readl(addr);
+ ret <<= 32;
+ ret |= readl(addr);
return ret;
}
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 695278c97afe..a29ac2096923 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -156,8 +156,6 @@ static int __init do_ultra_probe(struct net_device *dev)
/* Look for any installed ISAPnP cards */
if (isapnp_present() && (ultra_probe_isapnp(dev) == 0))
return 0;
-
- printk(KERN_NOTICE "smc-ultra.c: No ISAPnP cards found, trying standard ones...\n");
#endif
for (i = 0; ultra_portlist[i]; i++) {
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 9b75be8b971e..fb9935b670ac 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -1333,6 +1333,19 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void smc_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ smc_interrupt(dev->irq, dev, NULL);
+ enable_irq(dev->irq);
+}
+#endif
+
/* Our watchdog timed out. Called by the networking layer */
static void smc_timeout(struct net_device *dev)
{
@@ -1912,6 +1925,9 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
dev->get_stats = smc_query_statistics;
dev->set_multicast_list = smc_set_multicast_list;
dev->ethtool_ops = &smc_ethtool_ops;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = smc_poll_controller;
+#endif
tasklet_init(&lp->tx_task, smc_hardware_send_pkt, (unsigned long)dev);
INIT_WORK(&lp->phy_configure, smc_phy_configure, dev);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 87a4e0008d42..492354bc4c92 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -365,7 +365,8 @@ static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
* - we are multicast promiscous.
* - we belong to the multicast group.
*/
- memcpy(addr, skb->data, min(sizeof addr, skb->len));
+ memcpy(addr, skb->data,
+ min_t(size_t, sizeof addr, skb->len));
bit_nr = ether_crc(sizeof addr, addr) >> 26;
if ((tun->if_flags & IFF_PROMISC) ||
memcmp(addr, tun->dev_addr, sizeof addr) == 0 ||
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index aee87bb34384..2152403888fc 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -2697,7 +2697,8 @@ int reset_card( struct net_device *dev , int lock) {
}
struct net_device *_init_airo_card( unsigned short irq, int port,
- int is_pcmcia, struct pci_dev *pci )
+ int is_pcmcia, struct pci_dev *pci,
+ struct device *dmdev )
{
struct net_device *dev;
struct airo_info *ai;
@@ -2759,10 +2760,8 @@ struct net_device *_init_airo_card( unsigned short irq, int port,
dev->irq = irq;
dev->base_addr = port;
- /* what is with PCMCIA ??? */
- if (pci) {
- SET_NETDEV_DEV(dev, &pci->dev);
- }
+ SET_NETDEV_DEV(dev, dmdev);
+
if (test_bit(FLAG_MPI,&ai->flags))
reset_card (dev, 1);
@@ -2844,9 +2843,10 @@ err_out_free:
return NULL;
}
-struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia )
+struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia,
+ struct device *dmdev)
{
- return _init_airo_card ( irq, port, is_pcmcia, NULL);
+ return _init_airo_card ( irq, port, is_pcmcia, NULL, dmdev);
}
EXPORT_SYMBOL(init_airo_card);
@@ -5455,9 +5455,9 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev,
pci_set_master(pdev);
if (pdev->device == 0x5000 || pdev->device == 0xa504)
- dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev);
+ dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev, &pdev->dev);
else
- dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev);
+ dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev, &pdev->dev);
if (!dev)
return -ENODEV;
@@ -5559,7 +5559,7 @@ static int __init airo_init_module( void )
printk( KERN_INFO
"airo: Trying to configure ISA adapter at irq=%d io=0x%x\n",
irq[i], io[i] );
- if (init_airo_card( irq[i], io[i], 0 ))
+ if (init_airo_card( irq[i], io[i], 0, NULL ))
have_isa_dev = 1;
}
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index 939783ff1120..16a973141091 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -89,7 +89,7 @@ module_param_array(irq_list, int, NULL, 0);
event handler.
*/
-struct net_device *init_airo_card( int, int, int );
+struct net_device *init_airo_card( int, int, int, struct device * );
void stop_airo_card( struct net_device *, int );
int reset_airo_card( struct net_device * );
@@ -225,7 +225,6 @@ static dev_link_t *airo_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -450,7 +449,7 @@ static void airo_config(dev_link_t *link)
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
((local_info_t*)link->priv)->eth_dev =
init_airo_card( link->irq.AssignedIRQ,
- link->io.BasePort1, 1 );
+ link->io.BasePort1, 1, &handle_to_dev(handle) );
if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed;
/*
@@ -592,13 +591,7 @@ static int airo_cs_init(void)
static void airo_cs_cleanup(void)
{
pcmcia_unregister_driver(&airo_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- airo_release(dev_list);
- airo_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
/*
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 8337121c9ed9..3fe780d128d9 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -237,7 +237,6 @@ static dev_link_t *atmel_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -347,18 +346,6 @@ static struct {
{ 0, 0, "11WAVE/11WP611AL-E", "atmel_at76c502e%s.bin", "11WAVE WaveBuddy" }
};
-/* This is strictly temporary, until PCMCIA devices get integrated into the device model. */
-static struct device *atmel_device(void)
-{
- static struct device dev = {
- .bus_id = "pcmcia",
- };
- kobject_set_name(&dev.kobj, "atmel_cs");
- kobject_init(&dev.kobj);
-
- return &dev;
-}
-
static void atmel_config(dev_link_t *link)
{
client_handle_t handle;
@@ -549,7 +536,7 @@ static void atmel_config(dev_link_t *link)
init_atmel_card(link->irq.AssignedIRQ,
link->io.BasePort1,
card_index == -1 ? NULL : card_table[card_index].firmware,
- atmel_device(),
+ &handle_to_dev(handle),
card_present,
link);
if (!((local_info_t*)link->priv)->eth_dev)
@@ -693,13 +680,7 @@ static int atmel_cs_init(void)
static void atmel_cs_cleanup(void)
{
pcmcia_unregister_driver(&atmel_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- atmel_release(dev_list);
- atmel_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
/*
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 4936d7e3469d..e2685634c2d5 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -503,7 +503,6 @@ static dev_link_t *netwave_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -1073,6 +1072,8 @@ static void netwave_pcmcia_config(dev_link_t *link) {
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+
if (register_netdev(dev) != 0) {
printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n");
goto failed;
@@ -1696,9 +1697,7 @@ static int __init init_netwave_cs(void)
static void __exit exit_netwave_cs(void)
{
pcmcia_unregister_driver(&netwave_driver);
-
- if (dev_list != NULL) /* Critical situation */
- printk("netwave_cs: devices remaining when removing module\n");
+ BUG_ON(dev_list != NULL);
}
module_init(init_netwave_cs);
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 823fa82e6b9a..8f746051af82 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -617,9 +617,8 @@ static int orinoco_open(struct net_device *dev)
unsigned long flags;
int err;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = __orinoco_up(dev);
@@ -671,10 +670,9 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
return NULL; /* FIXME: Can we do better than this? */
}
- err = orinoco_lock(priv, &flags);
- if (err)
- return NULL; /* FIXME: Erg, we've been signalled, how
- * do we propagate this back up? */
+ if (orinoco_lock(priv, &flags) != 0)
+ return NULL; /* FIXME: Erg, we've been signalled, how
+ * do we propagate this back up? */
if (priv->iw_mode == IW_MODE_ADHOC) {
memset(&wstats->qual, 0, sizeof(wstats->qual));
@@ -1819,10 +1817,8 @@ static int orinoco_reconfigure(struct net_device *dev)
return 0;
}
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
-
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_disable_port(hw, 0);
if (err) {
@@ -1864,11 +1860,10 @@ static void orinoco_reset(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
struct hermes *hw = &priv->hw;
- int err;
+ int err = 0;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
+ if (orinoco_lock(priv, &flags) != 0)
/* When the hardware becomes available again, whatever
* detects that is responsible for re-initializing
* it. So no need for anything further */
@@ -2411,9 +2406,8 @@ static int orinoco_hw_get_bssid(struct orinoco_private *priv,
int err = 0;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
ETH_ALEN, NULL, buf);
@@ -2433,9 +2427,8 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
int len;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (strlen(priv->desired_essid) > 0) {
/* We read the desired SSID from the hardware rather
@@ -2486,9 +2479,8 @@ static long orinoco_hw_get_freq(struct orinoco_private *priv)
long freq = 0;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel);
if (err)
@@ -2528,9 +2520,8 @@ static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
int i;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
sizeof(list), NULL, &list);
@@ -2568,9 +2559,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
rrq->length = sizeof(range);
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
mode = priv->iw_mode;
orinoco_unlock(priv, &flags);
@@ -2639,9 +2629,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
range.min_frag = 256;
range.max_frag = 2346;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (priv->has_wep) {
range.max_encoding_tokens = ORINOCO_MAX_KEYS;
@@ -2706,10 +2695,9 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
if (copy_from_user(keybuf, erq->pointer, erq->length))
return -EFAULT;
}
-
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (erq->pointer) {
if (erq->length > ORINOCO_MAX_KEY_SIZE) {
@@ -2788,12 +2776,10 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er
int index = (erq->flags & IW_ENCODE_INDEX) - 1;
u16 xlen = 0;
char keybuf[ORINOCO_MAX_KEY_SIZE];
- int err;
unsigned long flags;
-
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
index = priv->tx_key;
@@ -2833,7 +2819,6 @@ static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
{
struct orinoco_private *priv = netdev_priv(dev);
char essidbuf[IW_ESSID_MAX_SIZE+1];
- int err;
unsigned long flags;
/* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
@@ -2851,9 +2836,8 @@ static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
essidbuf[erq->length] = '\0';
}
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
memcpy(priv->desired_essid, essidbuf, sizeof(priv->desired_essid));
@@ -2877,9 +2861,8 @@ static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
if (err)
return err;
} else {
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
memcpy(essidbuf, priv->desired_essid, sizeof(essidbuf));
orinoco_unlock(priv, &flags);
}
@@ -2899,7 +2882,6 @@ static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq)
{
struct orinoco_private *priv = netdev_priv(dev);
char nickbuf[IW_ESSID_MAX_SIZE+1];
- int err;
unsigned long flags;
if (nrq->length > IW_ESSID_MAX_SIZE)
@@ -2912,9 +2894,8 @@ static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq)
nickbuf[nrq->length] = '\0';
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
memcpy(priv->nick, nickbuf, sizeof(priv->nick));
@@ -2927,12 +2908,10 @@ static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq)
{
struct orinoco_private *priv = netdev_priv(dev);
char nickbuf[IW_ESSID_MAX_SIZE+1];
- int err;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE+1);
orinoco_unlock(priv, &flags);
@@ -2949,7 +2928,6 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
{
struct orinoco_private *priv = netdev_priv(dev);
int chan = -1;
- int err;
unsigned long flags;
/* We can only use this in Ad-Hoc demo mode to set the operating
@@ -2978,9 +2956,8 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
! (priv->channel_mask & (1 << (chan-1)) ) )
return -EINVAL;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
priv->channel = chan;
orinoco_unlock(priv, &flags);
@@ -2998,9 +2975,8 @@ static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq)
if (!priv->has_sensitivity)
return -EOPNOTSUPP;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_read_wordrec(hw, USER_BAP,
HERMES_RID_CNFSYSTEMSCALE, &val);
orinoco_unlock(priv, &flags);
@@ -3018,7 +2994,6 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
{
struct orinoco_private *priv = netdev_priv(dev);
int val = srq->value;
- int err;
unsigned long flags;
if (!priv->has_sensitivity)
@@ -3027,9 +3002,8 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
if ((val < 1) || (val > 3))
return -EINVAL;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
priv->ap_density = val;
orinoco_unlock(priv, &flags);
@@ -3040,7 +3014,6 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
{
struct orinoco_private *priv = netdev_priv(dev);
int val = rrq->value;
- int err;
unsigned long flags;
if (rrq->disabled)
@@ -3049,9 +3022,8 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
if ( (val < 0) || (val > 2347) )
return -EINVAL;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
priv->rts_thresh = val;
orinoco_unlock(priv, &flags);
@@ -3065,9 +3037,8 @@ static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq)
int err = 0;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (priv->has_mwo) {
if (frq->disabled)
@@ -3102,9 +3073,8 @@ static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq)
u16 val;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (priv->has_mwo) {
err = hermes_read_wordrec(hw, USER_BAP,
@@ -3166,9 +3136,8 @@ static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq)
if (ratemode == -1)
return -EINVAL;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
priv->bitratemode = ratemode;
orinoco_unlock(priv, &flags);
@@ -3185,9 +3154,8 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
u16 val;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
ratemode = priv->bitratemode;
@@ -3247,9 +3215,8 @@ static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq)
int err = 0;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (prq->disabled) {
priv->pm_on = 0;
@@ -3302,9 +3269,8 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
u16 enable, period, timeout, mcast;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPMENABLED, &enable);
if (err)
@@ -3351,9 +3317,8 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
u16 short_limit, long_limit, lifetime;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
&short_limit);
@@ -3399,12 +3364,10 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq)
{
struct orinoco_private *priv = netdev_priv(dev);
int val = *( (int *) wrq->u.name );
- int err;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
priv->ibss_port = val ;
@@ -3419,12 +3382,10 @@ static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq)
{
struct orinoco_private *priv = netdev_priv(dev);
int *val = (int *)wrq->u.name;
- int err;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
*val = priv->ibss_port;
orinoco_unlock(priv, &flags);
@@ -3439,9 +3400,8 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
int err = 0;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
switch (val) {
case 0: /* Try to do IEEE ad-hoc mode */
@@ -3478,12 +3438,10 @@ static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq)
{
struct orinoco_private *priv = netdev_priv(dev);
int *val = (int *)wrq->u.name;
- int err;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
*val = priv->prefer_port3;
orinoco_unlock(priv, &flags);
@@ -3513,9 +3471,8 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
}
/* Make sure nobody mess with the structure while we do */
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
/* orinoco_lock() doesn't disable interrupts, so make sure the
* interrupt rx path don't get confused while we copy */
@@ -3546,12 +3503,10 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
struct iw_quality spy_stat[IW_MAX_SPY];
int number;
int i;
- int err;
unsigned long flags;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
number = priv->spy_number;
if ((number > 0) && (srq->pointer)) {
@@ -3621,9 +3576,8 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break;
case SIOCSIWMODE:
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
switch (wrq->u.mode) {
case IW_MODE_ADHOC:
if (! (priv->has_ibss || priv->has_port3) )
@@ -3648,9 +3602,8 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break;
case SIOCGIWMODE:
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
wrq->u.mode = priv->iw_mode;
orinoco_unlock(priv, &flags);
break;
@@ -3865,9 +3818,8 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if(priv->has_preamble) {
int val = *( (int *) wrq->u.name );
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
if (val)
priv->preamble = 1;
else
@@ -3882,9 +3834,8 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if(priv->has_preamble) {
int *val = (int *)wrq->u.name;
- err = orinoco_lock(priv, &flags);
- if (err)
- return err;
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
*val = priv->preamble;
orinoco_unlock(priv, &flags);
} else
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index d7085037eb9b..2c8618098602 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -197,7 +197,6 @@ orinoco_cs_attach(void)
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -454,6 +453,7 @@ orinoco_cs_config(dev_link_t *link)
/* register_netdev will give us an ethX name */
dev->name[0] = '\0';
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
/* Tell the stack we exist */
if (register_netdev(dev) != 0) {
printk(KERN_ERR PFX "register_netdev() failed\n");
@@ -653,14 +653,7 @@ static void __exit
exit_orinoco_cs(void)
{
pcmcia_unregister_driver(&orinoco_driver);
-
- if (dev_list)
- DEBUG(0, PFX "Removing leftover devices.\n");
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG)
- orinoco_cs_release(dev_list);
- orinoco_cs_detach(dev_list);
- }
+ BUG_ON(dev_list != NULL);
}
module_init(init_orinoco_cs);
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 7ba64e3c8757..e220781b03ae 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -398,7 +398,6 @@ static dev_link_t *ray_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -564,6 +563,7 @@ static void ray_config(dev_link_t *link)
return;
}
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
i = register_netdev(dev);
if (i != 0) {
printk("ray_config register_netdev() failed\n");
@@ -2952,8 +2952,7 @@ static void __exit exit_ray_cs(void)
#endif
pcmcia_unregister_driver(&ray_driver);
- while (dev_list != NULL)
- ray_detach(dev_list);
+ BUG_ON(dev_list != NULL);
} /* exit_ray_cs */
module_init(init_ray_cs);
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 17fcd84c1a14..a2b95854f4fc 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -4068,6 +4068,7 @@ wv_pcmcia_config(dev_link_t * link)
lp->mem, dev->irq, (u_int) dev->base_addr);
#endif
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
i = register_netdev(dev);
if(i != 0)
{
@@ -4688,7 +4689,6 @@ wavelan_attach(void)
/* Register with Card Services */
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_REGISTRATION_COMPLETE |
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 58b101389ffa..ba05d01de58a 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -100,7 +100,7 @@ module_param(pc_debug, int, 0);
/* Parameters that can be set with 'insmod' */
/* Bit map of interrupts to choose from */
/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
-static unsigned long wl3501_irq_mask = 0xdeb8;
+static unsigned int wl3501_irq_mask = 0xdeb8;
static int wl3501_irq_list[4] = { -1 };
/*
@@ -2015,7 +2015,6 @@ static dev_link_t *wl3501_attach(void)
link->next = wl3501_dev_list;
wl3501_dev_list = link;
client_reg.dev_info = &wl3501_dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask = CS_EVENT_CARD_INSERTION |
CS_EVENT_RESET_PHYSICAL |
CS_EVENT_CARD_RESET |
@@ -2105,6 +2104,7 @@ static void wl3501_config(dev_link_t *link)
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
+ SET_NETDEV_DEV(dev, &handle_to_dev(handle));
if (register_netdev(dev)) {
printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n");
goto failed;
@@ -2267,19 +2267,13 @@ static void __exit wl3501_exit_module(void)
{
dprintk(0, ": unloading");
pcmcia_unregister_driver(&wl3501_driver);
- while (wl3501_dev_list) {
- /* Mark the device as non-existing to minimize calls to card */
- wl3501_dev_list->state &= ~DEV_PRESENT;
- if (wl3501_dev_list->state & DEV_CONFIG)
- wl3501_release(wl3501_dev_list);
- wl3501_detach(wl3501_dev_list);
- }
+ BUG_ON(wl3501_dev_list != NULL);
}
module_init(wl3501_init_module);
module_exit(wl3501_exit_module);
-module_param(wl3501_irq_mask, int, 0);
+module_param(wl3501_irq_mask, uint, 0);
module_param_array(wl3501_irq_list, int, NULL, 0);
MODULE_AUTHOR("Fox Chen <mhchen@golf.ccl.itri.org.tw>, "
"Arnaldo Carvalho de Melo <acme@conectiva.com.br>,"
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 58706683b886..d497877ef11c 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -143,7 +143,6 @@ static dev_link_t *parport_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -401,10 +400,7 @@ static int __init init_parport_cs(void)
static void __exit exit_parport_cs(void)
{
pcmcia_unregister_driver(&parport_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- parport_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_parport_cs);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 7ce952cd99f6..7371987cf183 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -284,7 +284,7 @@ static int pci_device_remove(struct device * dev)
return 0;
}
-static int pci_device_suspend(struct device * dev, u32 state)
+static int pci_device_suspend(struct device * dev, pm_message_t state)
{
struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver;
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 37b643d24825..ca14e721502d 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -39,18 +39,6 @@ config PCMCIA_DEBUG
In all the above examples, N is the debugging verbosity
level.
-config PCMCIA_OBSOLETE
- bool "Enable obsolete PCCARD code"
- depends on PCCARD != n
- help
- Say Y here to enable some code found in the PCCARD subsystem
- which has no in-kernel usage, but might be needed for certain
- external PCMCIA drivers. If you do need to say Y here so that
- one such driver compiles and/or works correctly, please report
- this to linux-pcmcia <at> lists.infradead.org
-
- If unsure, say N
-
config PCMCIA
tristate "16-bit PCMCIA support"
depends on PCCARD
@@ -92,6 +80,7 @@ config YENTA
depends on PCCARD && PCI
#fixme: remove dependendcy on CARDBUS
depends on CARDBUS
+ select PCCARD_NONSTATIC
---help---
This option enables support for CardBus host bridges. Virtually
all modern PCMCIA bridges are CardBus compatible. A "bridge" is
@@ -106,6 +95,7 @@ config YENTA
config PD6729
tristate "Cirrus PD6729 compatible bridge support"
depends on PCMCIA && PCI
+ select PCCARD_NONSTATIC
help
This provides support for the Cirrus PD6729 PCI-to-PCMCIA bridge
device, found in some older laptops and PCMCIA card readers.
@@ -113,6 +103,7 @@ config PD6729
config I82092
tristate "i82092 compatible bridge support"
depends on PCMCIA && PCI
+ select PCCARD_NONSTATIC
help
This provides support for the Intel I82092AA PCI-to-PCMCIA bridge device,
found in some older laptops and more commonly in evaluation boards for the
@@ -121,6 +112,7 @@ config I82092
config I82365
tristate "i82365 compatible bridge support"
depends on PCMCIA && ISA
+ select PCCARD_NONSTATIC
help
Say Y here to include support for ISA-bus PCMCIA host bridges that
are register compatible with the Intel i82365. These are found on
@@ -131,6 +123,7 @@ config I82365
config TCIC
tristate "Databook TCIC host bridge support"
depends on PCMCIA
+ select PCCARD_NONSTATIC
help
Say Y here to include support for the Databook TCIC family of PCMCIA
host bridges. These are only found on a handful of old systems.
@@ -190,4 +183,8 @@ config M32R_CFC_NUM
help
Set the number of M32R CF slots.
+config PCCARD_NONSTATIC
+ tristate
+ depends on PCCARD
+
endmenu
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index dff3caa0dc39..3d5eb4984a7f 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -10,9 +10,11 @@ pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o
pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
obj-$(CONFIG_PCCARD) += pcmcia_core.o
-pcmcia-y += ds.o bulkmem.o pcmcia_compat.o
+pcmcia-y += ds.o pcmcia_compat.o
obj-$(CONFIG_PCMCIA) += pcmcia.o
+obj-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o
+
# socket drivers
diff --git a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c
deleted file mode 100644
index 855c1f76c5dd..000000000000
--- a/drivers/pcmcia/bulkmem.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/*======================================================================
-
- PCMCIA Bulk Memory Services
-
- bulkmem.c 1.38 2000/09/25 19:29:51
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- 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 <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-
-#define IN_CARD_SERVICES
-#include <pcmcia/cs_types.h>
-#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
-#include <pcmcia/cistpl.h>
-#include "cs_internal.h"
-
-#ifdef DEBUG
-extern int ds_pc_debug;
-#define cs_socket_name(skt) ((skt)->dev.class_id)
-
-#define ds_dbg(skt, lvl, fmt, arg...) do { \
- if (ds_pc_debug >= lvl) \
- printk(KERN_DEBUG "ds: %s: " fmt, \
- cs_socket_name(skt) , ## arg); \
-} while (0)
-#else
-#define ds_dbg(lvl, fmt, arg...) do { } while (0)
-#endif
-
-/*======================================================================
-
- This stuff is used by Card Services to initialize the table of
- region info used for subsequent calls to GetFirstRegion and
- GetNextRegion.
-
-======================================================================*/
-
-static void setup_regions(struct pcmcia_socket *s, unsigned int function,
- int attr, memory_handle_t *list)
-{
- int i, code, has_jedec, has_geo;
- u_int offset;
- cistpl_device_t device;
- cistpl_jedec_t jedec;
- cistpl_device_geo_t geo;
- memory_handle_t r;
-
- ds_dbg(s, 1, "setup_regions(0x%d, %d, 0x%p)\n",
- function, attr, list);
-
- code = (attr) ? CISTPL_DEVICE_A : CISTPL_DEVICE;
- if (pccard_read_tuple(s, function, code, &device) != CS_SUCCESS)
- return;
- code = (attr) ? CISTPL_JEDEC_A : CISTPL_JEDEC_C;
- has_jedec = (pccard_read_tuple(s, function, code, &jedec) == CS_SUCCESS);
- if (has_jedec && (device.ndev != jedec.nid)) {
- ds_dbg(s, 0, "Device info does not match JEDEC info.\n");
- has_jedec = 0;
- }
- code = (attr) ? CISTPL_DEVICE_GEO_A : CISTPL_DEVICE_GEO;
- has_geo = (pccard_read_tuple(s, function, code, &geo) == CS_SUCCESS);
- if (has_geo && (device.ndev != geo.ngeo)) {
- ds_dbg(s, 0, "Device info does not match geometry tuple.\n");
- has_geo = 0;
- }
-
- offset = 0;
- for (i = 0; i < device.ndev; i++) {
- if ((device.dev[i].type != CISTPL_DTYPE_NULL) &&
- (device.dev[i].size != 0)) {
- r = kmalloc(sizeof(*r), GFP_KERNEL);
- if (!r) {
- printk(KERN_NOTICE "cs: setup_regions: kmalloc failed!\n");
- return;
- }
- r->region_magic = REGION_MAGIC;
- r->state = 0;
- r->dev_info[0] = '\0';
- r->mtd = NULL;
- r->info.Attributes = (attr) ? REGION_TYPE_AM : 0;
- r->info.CardOffset = offset;
- r->info.RegionSize = device.dev[i].size;
- r->info.AccessSpeed = device.dev[i].speed;
- if (has_jedec) {
- r->info.JedecMfr = jedec.id[i].mfr;
- r->info.JedecInfo = jedec.id[i].info;
- } else
- r->info.JedecMfr = r->info.JedecInfo = 0;
- if (has_geo) {
- r->info.BlockSize = geo.geo[i].buswidth *
- geo.geo[i].erase_block * geo.geo[i].interleave;
- r->info.PartMultiple =
- r->info.BlockSize * geo.geo[i].partition;
- } else
- r->info.BlockSize = r->info.PartMultiple = 1;
- r->info.next = *list; *list = r;
- }
- offset += device.dev[i].size;
- }
-} /* setup_regions */
-
-/*======================================================================
-
- This is tricky. When get_first_region() is called by Driver
- Services, we initialize the region info table in the socket
- structure. When it is called by an MTD, we can just scan the
- table for matching entries.
-
-======================================================================*/
-
-static int pccard_match_region(memory_handle_t list, region_info_t *match)
-{
- if (list) {
- *match = list->info;
- return CS_SUCCESS;
- }
- return CS_NO_MORE_ITEMS;
-} /* match_region */
-
-int pccard_get_first_region(struct pcmcia_socket *s, region_info_t *rgn)
-{
- if (!(s->state & SOCKET_REGION_INFO)) {
- setup_regions(s, BIND_FN_ALL, 0, &s->c_region);
- setup_regions(s, BIND_FN_ALL, 1, &s->a_region);
- s->state |= SOCKET_REGION_INFO;
- }
-
- if (rgn->Attributes & REGION_TYPE_AM)
- return pccard_match_region(s->a_region, rgn);
- else
- return pccard_match_region(s->c_region, rgn);
-} /* get_first_region */
-
-int pccard_get_next_region(struct pcmcia_socket *s, region_info_t *rgn)
-{
- return pccard_match_region(rgn->next, rgn);
-} /* get_next_region */
-
-
-#ifdef CONFIG_PCMCIA_OBSOLETE
-
-static int match_region(client_handle_t handle, memory_handle_t list,
- region_info_t *match)
-{
- while (list != NULL) {
- if (!(handle->Attributes & INFO_MTD_CLIENT) ||
- (strcmp(handle->dev_info, list->dev_info) == 0)) {
- *match = list->info;
- return CS_SUCCESS;
- }
- list = list->info.next;
- }
- return CS_NO_MORE_ITEMS;
-} /* match_region */
-
-int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn)
-{
- struct pcmcia_socket *s = SOCKET(handle);
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
-
- if ((handle->Attributes & INFO_MASTER_CLIENT) &&
- (!(s->state & SOCKET_REGION_INFO))) {
- setup_regions(s, handle->Function, 0, &s->c_region);
- setup_regions(s, handle->Function, 1, &s->a_region);
- s->state |= SOCKET_REGION_INFO;
- }
-
- if (rgn->Attributes & REGION_TYPE_AM)
- return match_region(handle, s->a_region, rgn);
- else
- return match_region(handle, s->c_region, rgn);
-} /* get_first_region */
-EXPORT_SYMBOL(pcmcia_get_first_region);
-
-int pcmcia_get_next_region(client_handle_t handle, region_info_t *rgn)
-{
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- return match_region(handle, rgn->next, rgn);
-} /* get_next_region */
-EXPORT_SYMBOL(pcmcia_get_next_region);
-
-#endif
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index 1b86c6d3a572..3ccb5247ec50 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -1,35 +1,16 @@
-/*======================================================================
-
- Cardbus device configuration
-
- cardbus.c 1.87 2002/10/24 06:11:41
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- 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.
-
-======================================================================*/
+/*
+ * cardbus.c -- 16-bit PCMCIA core support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ */
/*
* Cardbus handling has been re-written to be more of a PCI bridge thing,
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 8cf0623397f7..e29a6ddf2fd7 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -1,35 +1,16 @@
-/*======================================================================
-
- PCMCIA Card Information Structure parser
-
- cistpl.c 1.99 2002/10/24 06:11:48
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in
- which case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- 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.
-
-======================================================================*/
+/*
+ * cistpl.c -- 16-bit PCMCIA Card Information Structure parser
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ */
#include <linux/config.h>
#include <linux/module.h>
@@ -97,6 +78,7 @@ void release_cis_mem(struct pcmcia_socket *s)
s->cis_virt = NULL;
}
}
+EXPORT_SYMBOL(release_cis_mem);
/*
* Map the card memory at "card_offset" into virtual space.
@@ -108,8 +90,7 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
{
pccard_mem_map *mem = &s->cis_mem;
if (!(s->features & SS_CAP_STATIC_MAP) && mem->res == NULL) {
- mem->res = find_mem_region(0, s->map_size, s->map_size, 0,
- "card services", s);
+ mem->res = find_mem_region(0, s->map_size, s->map_size, 0, s);
if (mem->res == NULL) {
printk(KERN_NOTICE "cs: unable to map card memory!\n");
return NULL;
@@ -340,6 +321,7 @@ void destroy_cis_cache(struct pcmcia_socket *s)
s->fake_cis = NULL;
}
}
+EXPORT_SYMBOL(destroy_cis_cache);
/*======================================================================
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 4e4c964f7e01..edfc17a30687 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -1,35 +1,16 @@
-/*======================================================================
-
- Kernel Card Services -- core services
-
- cs.c 1.271 2000/10/02 20:27:49
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- 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.
-
-======================================================================*/
+/*
+ * cs.c -- Kernel Card Services - core services
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ */
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -60,6 +41,7 @@
#include <pcmcia/bulkmem.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
#include "cs_internal.h"
#ifdef CONFIG_PCI
@@ -92,7 +74,7 @@ static const char *options = "options: " OPTIONS;
MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("Linux Kernel Card Services\noptions:" OPTIONS);
-MODULE_LICENSE("Dual MPL/GPL");
+MODULE_LICENSE("GPL");
#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
@@ -132,6 +114,8 @@ socket_state_t dead_socket = {
/* List of all sockets, protected by a rwsem */
LIST_HEAD(pcmcia_socket_list);
DECLARE_RWSEM(pcmcia_socket_list_rwsem);
+EXPORT_SYMBOL(pcmcia_socket_list);
+EXPORT_SYMBOL(pcmcia_socket_list_rwsem);
/*====================================================================
@@ -189,16 +173,32 @@ int pcmcia_socket_dev_resume(struct device *dev)
EXPORT_SYMBOL(pcmcia_socket_dev_resume);
+struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt)
+{
+ struct class_device *cl_dev = class_device_get(&skt->dev);
+ if (!cl_dev)
+ return NULL;
+ skt = class_get_devdata(cl_dev);
+ if (!try_module_get(skt->owner)) {
+ class_device_put(&skt->dev);
+ return NULL;
+ }
+ return (skt);
+}
+EXPORT_SYMBOL(pcmcia_get_socket);
+
+
+void pcmcia_put_socket(struct pcmcia_socket *skt)
+{
+ module_put(skt->owner);
+ class_device_put(&skt->dev);
+}
+EXPORT_SYMBOL(pcmcia_put_socket);
+
+
static void pcmcia_release_socket(struct class_device *class_dev)
{
struct pcmcia_socket *socket = class_get_devdata(class_dev);
- client_t *client;
-
- while (socket->clients) {
- client = socket->clients;
- socket->clients = socket->clients->next;
- kfree(client);
- }
complete(&socket->socket_released);
}
@@ -212,11 +212,17 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
{
int ret;
- if (!socket || !socket->ops || !socket->dev.dev)
+ if (!socket || !socket->ops || !socket->dev.dev || !socket->resource_ops)
return -EINVAL;
cs_dbg(socket, 0, "pcmcia_register_socket(0x%p)\n", socket->ops);
+ if (socket->resource_ops->init) {
+ ret = socket->resource_ops->init(socket);
+ if (ret)
+ return (ret);
+ }
+
/* try to obtain a socket number [yes, it gets ugly if we
* register more than 2^sizeof(unsigned int) pcmcia
* sockets... but the socket number is deprecated
@@ -305,6 +311,7 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)
up_write(&pcmcia_socket_list_rwsem);
/* wait for sysfs to drop all references */
+ release_resource_db(socket);
wait_for_completion(&socket->socket_released);
} /* pcmcia_unregister_socket */
EXPORT_SYMBOL(pcmcia_unregister_socket);
@@ -349,12 +356,8 @@ static void free_regions(memory_handle_t *list)
}
}
-static int send_event(struct pcmcia_socket *s, event_t event, int priority);
-
static void shutdown_socket(struct pcmcia_socket *s)
{
- client_t **c;
-
cs_dbg(s, 1, "shutdown_socket\n");
/* Blank out the socket state */
@@ -372,15 +375,6 @@ static void shutdown_socket(struct pcmcia_socket *s)
kfree(s->config);
s->config = NULL;
}
- for (c = &s->clients; *c; ) {
- if ((*c)->state & CLIENT_UNBOUND) {
- client_t *d = *c;
- *c = (*c)->next;
- kfree(d);
- } else {
- c = &((*c)->next);
- }
- }
free_regions(&s->a_region);
free_regions(&s->c_region);
@@ -395,45 +389,44 @@ static void shutdown_socket(struct pcmcia_socket *s)
/*======================================================================
- The central event handler. Send_event() sends an event to all
- valid clients. Parse_events() interprets the event bits from
+ The central event handler. Send_event() sends an event to the
+ 16-bit subsystem, which then calls the relevant device drivers.
+ Parse_events() interprets the event bits from
a card status change report. Do_shutdown() handles the high
priority stuff associated with a card removal.
======================================================================*/
+
+/* NOTE: send_event needs to be called with skt->sem held. */
+
static int send_event(struct pcmcia_socket *s, event_t event, int priority)
{
- client_t *client = s->clients;
- int ret;
- cs_dbg(s, 1, "send_event(event %d, pri %d)\n",
- event, priority);
- ret = 0;
- if (s->state & SOCKET_CARDBUS)
- return 0;
- for (; client; client = client->next) {
- if (client->state & (CLIENT_UNBOUND|CLIENT_STALE))
- continue;
- if (client->EventMask & event) {
- ret = EVENT(client, event, priority);
- if (ret != 0)
- return ret;
- }
- }
- return ret;
-} /* send_event */
+ int ret;
+
+ if (s->state & SOCKET_CARDBUS)
+ return 0;
+
+ cs_dbg(s, 1, "send_event(event %d, pri %d, callback 0x%p)\n",
+ event, priority, s->callback);
+
+ if (!s->callback)
+ return 0;
+ if (!try_module_get(s->callback->owner))
+ return 0;
+
+ ret = s->callback->event(s, event, priority);
+
+ module_put(s->callback->owner);
+
+ return ret;
+}
static void socket_remove_drivers(struct pcmcia_socket *skt)
{
- client_t *client;
-
cs_dbg(skt, 4, "remove_drivers\n");
send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
-
- for (client = skt->clients; client; client = client->next)
- if (!(client->Attributes & INFO_MASTER_CLIENT))
- client->state |= CLIENT_STALE;
}
static void socket_shutdown(struct pcmcia_socket *skt)
@@ -756,7 +749,7 @@ void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)
======================================================================*/
static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
- ioaddr_t num, u_int lines, char *name)
+ ioaddr_t num, u_int lines)
{
int i;
ioaddr_t try, align;
@@ -788,7 +781,7 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
return 1;
for (i = 0; i < MAX_IO_WIN; i++) {
if (s->io[i].NumPorts == 0) {
- s->io[i].res = find_io_region(*base, num, align, name, s);
+ s->io[i].res = find_io_region(*base, num, align, s);
if (s->io[i].res) {
s->io[i].Attributes = attr;
s->io[i].BasePort = *base = s->io[i].res->start;
@@ -888,49 +881,6 @@ int pccard_access_configuration_register(struct pcmcia_socket *s,
} /* access_configuration_register */
EXPORT_SYMBOL(pccard_access_configuration_register);
-/*====================================================================*/
-
-int pcmcia_deregister_client(client_handle_t handle)
-{
- client_t **client;
- struct pcmcia_socket *s;
- u_long flags;
- int i;
-
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
-
- s = SOCKET(handle);
- cs_dbg(s, 1, "deregister_client(%p)\n", handle);
-
- if (handle->state &
- (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
- return CS_IN_USE;
- for (i = 0; i < MAX_WIN; i++)
- if (handle->state & CLIENT_WIN_REQ(i))
- return CS_IN_USE;
-
- if ((handle->state & CLIENT_STALE) ||
- (handle->Attributes & INFO_MASTER_CLIENT)) {
- spin_lock_irqsave(&s->lock, flags);
- client = &s->clients;
- while ((*client) && ((*client) != handle))
- client = &(*client)->next;
- if (*client == NULL) {
- spin_unlock_irqrestore(&s->lock, flags);
- return CS_BAD_HANDLE;
- }
- *client = handle->next;
- handle->client_magic = 0;
- kfree(handle);
- spin_unlock_irqrestore(&s->lock, flags);
- } else {
- handle->state = CLIENT_UNBOUND;
- handle->event_handler = NULL;
- }
-
- return CS_SUCCESS;
-} /* deregister_client */
/*====================================================================*/
@@ -1014,53 +964,6 @@ int pcmcia_get_card_services_info(servinfo_t *info)
return CS_SUCCESS;
} /* get_card_services_info */
-#ifdef CONFIG_PCMCIA_OBSOLETE
-
-/*======================================================================
-
- Note that get_first_client() *does* recognize the Socket field
- in the request structure.
-
-======================================================================*/
-
-int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req)
-{
- socket_t s;
- struct pcmcia_socket *socket;
- if (req->Attributes & CLIENT_THIS_SOCKET)
- s = req->Socket;
- else
- s = 0;
- socket = pcmcia_get_socket_by_nr(s);
- if (!socket)
- return CS_BAD_SOCKET;
- if (socket->clients == NULL)
- return CS_NO_MORE_ITEMS;
- *handle = socket->clients;
- return CS_SUCCESS;
-} /* get_first_client */
-EXPORT_SYMBOL(pcmcia_get_first_client);
-
-/*====================================================================*/
-
-int pcmcia_get_next_client(client_handle_t *handle, client_req_t *req)
-{
- struct pcmcia_socket *s;
- if ((handle == NULL) || CHECK_HANDLE(*handle))
- return CS_BAD_HANDLE;
- if ((*handle)->next == NULL) {
- if (req->Attributes & CLIENT_THIS_SOCKET)
- return CS_NO_MORE_ITEMS;
- s = (*handle)->Socket;
- if (s->clients == NULL)
- return CS_NO_MORE_ITEMS;
- *handle = s->clients;
- } else
- *handle = (*handle)->next;
- return CS_SUCCESS;
-} /* get_next_client */
-EXPORT_SYMBOL(pcmcia_get_next_client);
-#endif /* CONFIG_PCMCIA_OBSOLETE */
/*====================================================================*/
@@ -1251,117 +1154,33 @@ int pcmcia_modify_configuration(client_handle_t handle,
return CS_SUCCESS;
} /* modify_configuration */
-#ifdef CONFIG_PCMCIA_OBSOLETE
-
-/*======================================================================
-
- Modify the attributes of a window returned by RequestWindow.
-
-======================================================================*/
-
-int pcmcia_modify_window(window_handle_t win, modwin_t *req)
+/* register pcmcia_callback */
+int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
{
- if ((win == NULL) || (win->magic != WINDOW_MAGIC))
- return CS_BAD_HANDLE;
-
- win->ctl.flags &= ~(MAP_ATTRIB|MAP_ACTIVE);
- if (req->Attributes & WIN_MEMORY_TYPE)
- win->ctl.flags |= MAP_ATTRIB;
- if (req->Attributes & WIN_ENABLE)
- win->ctl.flags |= MAP_ACTIVE;
- if (req->Attributes & WIN_DATA_WIDTH_16)
- win->ctl.flags |= MAP_16BIT;
- if (req->Attributes & WIN_USE_WAIT)
- win->ctl.flags |= MAP_USE_WAIT;
- win->ctl.speed = req->AccessSpeed;
- win->sock->ops->set_mem_map(win->sock, &win->ctl);
-
- return CS_SUCCESS;
-} /* modify_window */
-EXPORT_SYMBOL(pcmcia_modify_window);
-
-#endif /* CONFIG_PCMCIA_OBSOLETE */
-
+ int ret = 0;
-/*======================================================================
+ /* s->skt_sem also protects s->callback */
+ down(&s->skt_sem);
- Register_client() uses the dev_info_t handle to match the
- caller with a socket. The driver must have already been bound
- to a socket with bind_device() -- in fact, bind_device()
- allocates the client structure that will be used.
-
-======================================================================*/
-
-int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
-{
- client_t *client = NULL;
- struct pcmcia_socket *s;
-
- /* Look for unbound client with matching dev_info */
- down_read(&pcmcia_socket_list_rwsem);
- list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
- client = s->clients;
- while (client != NULL) {
- if ((strcmp(client->dev_info, (char *)req->dev_info) == 0)
- && (client->state & CLIENT_UNBOUND)) break;
- client = client->next;
- }
- if (client != NULL) break;
- }
- up_read(&pcmcia_socket_list_rwsem);
- if (client == NULL)
- return CS_OUT_OF_RESOURCE;
+ if (c) {
+ /* registration */
+ if (s->callback) {
+ ret = -EBUSY;
+ goto err;
+ }
- /*
- * Prevent this racing with a card insertion.
- */
- down(&s->skt_sem);
- *handle = client;
- client->state &= ~CLIENT_UNBOUND;
- client->Socket = s;
- client->Attributes = req->Attributes;
- client->EventMask = req->EventMask;
- client->event_handler = req->event_handler;
- client->event_callback_args = req->event_callback_args;
- client->event_callback_args.client_handle = client;
-
- if (s->state & SOCKET_CARDBUS)
- client->state |= CLIENT_CARDBUS;
-
- if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) &&
- (client->Function != BIND_FN_ALL)) {
- cistpl_longlink_mfc_t mfc;
- if (pccard_read_tuple(s, client->Function, CISTPL_LONGLINK_MFC, &mfc)
- == CS_SUCCESS)
- s->functions = mfc.nfn;
- else
- s->functions = 1;
- s->config = kmalloc(sizeof(config_t) * s->functions,
- GFP_KERNEL);
- if (!s->config)
- goto out_no_resource;
- memset(s->config, 0, sizeof(config_t) * s->functions);
- }
-
- cs_dbg(s, 1, "register_client(): client 0x%p, dev %s\n",
- client, client->dev_info);
- if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
- EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW);
-
- if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) {
- if (client->EventMask & CS_EVENT_CARD_INSERTION)
- EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
- else
- client->PendingEvents |= CS_EVENT_CARD_INSERTION;
- }
+ s->callback = c;
- up(&s->skt_sem);
- return CS_SUCCESS;
+ if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT)
+ send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
+ } else
+ s->callback = NULL;
+ err:
+ up(&s->skt_sem);
- out_no_resource:
- up(&s->skt_sem);
- return CS_OUT_OF_RESOURCE;
-} /* register_client */
+ return ret;
+}
+EXPORT_SYMBOL(pccard_register_pcmcia);
/*====================================================================*/
@@ -1685,14 +1504,12 @@ int pcmcia_request_io(client_handle_t handle, io_req_t *req)
return CS_BAD_ATTRIBUTE;
if (alloc_io_space(s, req->Attributes1, &req->BasePort1,
- req->NumPorts1, req->IOAddrLines,
- handle->dev_info))
+ req->NumPorts1, req->IOAddrLines))
return CS_IN_USE;
if (req->NumPorts2) {
if (alloc_io_space(s, req->Attributes2, &req->BasePort2,
- req->NumPorts2, req->IOAddrLines,
- handle->dev_info)) {
+ req->NumPorts2, req->IOAddrLines)) {
release_io_space(s, req->BasePort1, req->NumPorts1);
return CS_IN_USE;
}
@@ -1720,6 +1537,7 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
struct pcmcia_socket *s;
config_t *c;
int ret = CS_IN_USE, irq = 0;
+ struct pcmcia_device *p_dev = handle_to_pdev(handle);
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
@@ -1769,7 +1587,7 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
(s->functions > 1) ||
(irq == s->pci_irq)) ? SA_SHIRQ : 0,
- handle->dev_info, req->Instance))
+ p_dev->dev.bus_id, req->Instance))
return CS_IN_USE;
}
@@ -1832,8 +1650,7 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
if (!(s->features & SS_CAP_STATIC_MAP)) {
win->ctl.res = find_mem_region(req->Base, req->Size, align,
- (req->Attributes & WIN_MAP_BELOW_1MB),
- (*handle)->dev_info, s);
+ (req->Attributes & WIN_MAP_BELOW_1MB), s);
if (!win->ctl.res)
return CS_IN_USE;
}
@@ -2022,47 +1839,16 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
/*======================================================================
- Maybe this should send a CS_EVENT_CARD_INSERTION event if we
- haven't sent one to this client yet?
-
-======================================================================*/
-
-#ifdef CONFIG_PCMCIA_OBSOLETE
-int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask)
-{
- u_int events, bit;
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- if (handle->Attributes & CONF_EVENT_MASK_VALID)
- return CS_BAD_SOCKET;
- handle->EventMask = mask->EventMask;
- events = handle->PendingEvents & handle->EventMask;
- handle->PendingEvents -= events;
- while (events != 0) {
- bit = ((events ^ (events-1)) + 1) >> 1;
- EVENT(handle, bit, CS_EVENT_PRI_LOW);
- events -= bit;
- }
- return CS_SUCCESS;
-} /* set_event_mask */
-EXPORT_SYMBOL(pcmcia_set_event_mask);
-
-#endif /* CONFIG_PCMCIA_OBSOLETE */
-
-/*======================================================================
-
OS-specific module glue goes here
======================================================================*/
/* in alpha order */
-EXPORT_SYMBOL(pcmcia_deregister_client);
EXPORT_SYMBOL(pcmcia_eject_card);
EXPORT_SYMBOL(pcmcia_get_card_services_info);
EXPORT_SYMBOL(pcmcia_get_mem_page);
EXPORT_SYMBOL(pcmcia_insert_card);
EXPORT_SYMBOL(pcmcia_map_mem_page);
EXPORT_SYMBOL(pcmcia_modify_configuration);
-EXPORT_SYMBOL(pcmcia_register_client);
EXPORT_SYMBOL(pcmcia_release_configuration);
EXPORT_SYMBOL(pcmcia_release_io);
EXPORT_SYMBOL(pcmcia_release_irq);
@@ -2100,7 +1886,6 @@ static int __init init_pcmcia_cs(void)
static void __exit exit_pcmcia_cs(void)
{
printk(KERN_INFO "unloading Kernel Card Services\n");
- release_resource_db();
class_interface_unregister(&pccard_sysfs_interface);
class_unregister(&pcmcia_socket_class);
}
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index fbce6b67988b..f64ca5663f3c 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -1,19 +1,15 @@
/*
- * cs_internal.h 1.57 2002/10/24 06:11:43
+ * cs_internal.h
*
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
*/
#ifndef _LINUX_CS_INTERNAL_H
@@ -22,19 +18,7 @@
#include <linux/config.h>
#define CLIENT_MAGIC 0x51E6
-typedef struct client_t {
- u_short client_magic;
- struct pcmcia_socket *Socket;
- u_char Function;
- dev_info_t dev_info;
- u_int Attributes;
- u_int state;
- event_t EventMask, PendingEvents;
- int (*event_handler)(event_t event, int priority,
- event_callback_args_t *);
- event_callback_args_t event_callback_args;
- struct client_t *next;
-} client_t;
+typedef struct client_t client_t;
/* Flags in client state */
#define CLIENT_CONFIG_LOCKED 0x0001
@@ -151,15 +135,15 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t
/* In rsrc_mgr */
void pcmcia_validate_mem(struct pcmcia_socket *s);
struct resource *find_io_region(unsigned long base, int num, unsigned long align,
- char *name, struct pcmcia_socket *s);
+ struct pcmcia_socket *s);
int adjust_io_region(struct resource *res, unsigned long r_start,
unsigned long r_end, struct pcmcia_socket *s);
struct resource *find_mem_region(u_long base, u_long num, u_long align,
- int low, char *name, struct pcmcia_socket *s);
+ int low, struct pcmcia_socket *s);
int try_irq(u_int Attributes, int irq, int specific);
void undo_irq(u_int Attributes, int irq);
int adjust_resource_info(client_handle_t handle, adjust_t *adj);
-void release_resource_db(void);
+void release_resource_db(struct pcmcia_socket *s);
/* In socket_sysfs.c */
extern struct class_interface pccard_sysfs_interface;
@@ -173,6 +157,14 @@ int pccard_reset_card(struct pcmcia_socket *skt);
int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status);
int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int function, conf_reg_t *reg);
+
+struct pcmcia_callback{
+ struct module *owner;
+ int (*event) (struct pcmcia_socket *s, event_t event, int priority);
+};
+
+int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);
+
#define cs_socket_name(skt) ((skt)->dev.class_id)
#ifdef DEBUG
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 639c5acf22f1..6d40401abe93 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1,35 +1,17 @@
-/*======================================================================
-
- PC Card Driver Services
-
- ds.c 1.112 2001/10/13 00:08:28
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in
- which case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- 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.
-
-======================================================================*/
+/*
+ * ds.c -- 16-bit PCMCIA core support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ * (C) 2003 - 2004 Dominik Brodowski
+ */
#include <linux/config.h>
#include <linux/module.h>
@@ -51,6 +33,7 @@
#include <linux/pci.h>
#include <linux/list.h>
#include <linux/delay.h>
+#include <linux/kref.h>
#include <linux/workqueue.h>
#include <asm/atomic.h>
@@ -72,7 +55,7 @@
MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("PCMCIA Driver Services");
-MODULE_LICENSE("Dual MPL/GPL");
+MODULE_LICENSE("GPL");
#ifdef DEBUG
int ds_pc_debug;
@@ -89,13 +72,6 @@ module_param_named(pc_debug, ds_pc_debug, int, 0644);
/*====================================================================*/
-typedef struct socket_bind_t {
- struct pcmcia_driver *driver;
- u_char function;
- dev_link_t *instance;
- struct socket_bind_t *next;
-} socket_bind_t;
-
/* Device user information */
#define MAX_EVENTS 32
#define USER_MAGIC 0x7ea4
@@ -111,16 +87,22 @@ typedef struct user_info_t {
/* Socket state information */
struct pcmcia_bus_socket {
- atomic_t refcount;
- client_handle_t handle;
+ struct kref refcount;
+ struct pcmcia_callback callback;
int state;
user_info_t *user;
int req_pending, req_result;
wait_queue_head_t queue, request;
- struct work_struct removal;
- socket_bind_t *bind;
struct pcmcia_socket *parent;
+
+ /* the PCMCIA devices connected to this socket (normally one, more
+ * for multifunction devices: */
+ struct list_head devices_list;
+ u8 device_count; /* the number of devices, used
+ * only internally and subject
+ * to incorrectness and change */
};
+static spinlock_t pcmcia_dev_list_lock;
#define DS_SOCKET_PRESENT 0x01
#define DS_SOCKET_BUSY 0x02
@@ -129,89 +111,14 @@ struct pcmcia_bus_socket {
/*====================================================================*/
-/* Device driver ID passed to Card Services */
-static dev_info_t dev_info = "Driver Services";
-
static int major_dev = -1;
+static int unbind_request(struct pcmcia_bus_socket *s);
+
/*====================================================================*/
/* code which was in cs.c before */
-/*======================================================================
-
- Bind_device() associates a device driver with a particular socket.
- It is normally called by Driver Services after it has identified
- a newly inserted card. An instance of that driver will then be
- eligible to register as a client of this socket.
-
-======================================================================*/
-
-static int pcmcia_bind_device(bind_req_t *req)
-{
- client_t *client;
- struct pcmcia_socket *s;
-
- s = req->Socket;
- if (!s)
- return CS_BAD_SOCKET;
-
- client = (client_t *) kmalloc(sizeof(client_t), GFP_KERNEL);
- if (!client)
- return CS_OUT_OF_RESOURCE;
- memset(client, '\0', sizeof(client_t));
- client->client_magic = CLIENT_MAGIC;
- strlcpy(client->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
- client->Socket = s;
- client->Function = req->Function;
- client->state = CLIENT_UNBOUND;
- client->next = s->clients;
- s->clients = client;
- ds_dbg(1, "%s: bind_device(): client 0x%p, dev %s\n",
- cs_socket_name(client->Socket), client, client->dev_info);
- return CS_SUCCESS;
-} /* bind_device */
-
-
-/*======================================================================
-
- Bind_mtd() associates a device driver with a particular memory
- region. It is normally called by Driver Services after it has
- identified a memory device type. An instance of the corresponding
- driver will then be able to register to control this region.
-
-======================================================================*/
-
-static int pcmcia_bind_mtd(mtd_bind_t *req)
-{
- struct pcmcia_socket *s;
- memory_handle_t region;
-
- s = req->Socket;
- if (!s)
- return CS_BAD_SOCKET;
-
- if (req->Attributes & REGION_TYPE_AM)
- region = s->a_region;
- else
- region = s->c_region;
-
- while (region) {
- if (region->info.CardOffset == req->CardOffset)
- break;
- region = region->info.next;
- }
- if (!region || (region->mtd != NULL))
- return CS_BAD_OFFSET;
- strlcpy(region->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
-
- ds_dbg(1, "%s: bind_mtd: attr 0x%x, offset 0x%x, dev %s\n",
- cs_socket_name(s), req->Attributes, req->CardOffset,
- (char *)req->dev_info);
- return CS_SUCCESS;
-} /* bind_mtd */
-
-
/* String tables for error messages */
typedef struct lookup_t {
@@ -314,8 +221,10 @@ int pcmcia_report_error(client_handle_t handle, error_info_t *err)
if (CHECK_HANDLE(handle))
printk(KERN_NOTICE);
- else
- printk(KERN_NOTICE "%s: ", handle->dev_info);
+ else {
+ struct pcmcia_device *p_dev = handle_to_pdev(handle);
+ printk(KERN_NOTICE "%s: ", p_dev->dev.bus_id);
+ }
for (i = 0; i < ARRAY_SIZE(service_table); i++)
if (service_table[i].key == err->func)
@@ -353,22 +262,22 @@ EXPORT_SYMBOL(cs_error);
static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info);
static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr);
-static void pcmcia_put_bus_socket(struct pcmcia_bus_socket *s)
+static void pcmcia_release_bus_socket(struct kref *refcount)
{
- if (atomic_dec_and_test(&s->refcount))
- kfree(s);
+ struct pcmcia_bus_socket *s = container_of(refcount, struct pcmcia_bus_socket, refcount);
+ pcmcia_put_socket(s->parent);
+ kfree(s);
}
-static struct pcmcia_bus_socket *pcmcia_get_bus_socket(int nr)
+static void pcmcia_put_bus_socket(struct pcmcia_bus_socket *s)
{
- struct pcmcia_bus_socket *s;
+ kref_put(&s->refcount, pcmcia_release_bus_socket);
+}
- s = get_socket_info_by_nr(nr);
- if (s) {
- WARN_ON(atomic_read(&s->refcount) == 0);
- atomic_inc(&s->refcount);
- }
- return s;
+static struct pcmcia_bus_socket *pcmcia_get_bus_socket(struct pcmcia_bus_socket *s)
+{
+ kref_get(&s->refcount);
+ return (s);
}
/**
@@ -381,8 +290,8 @@ int pcmcia_register_driver(struct pcmcia_driver *driver)
if (!driver)
return -EINVAL;
- driver->use_count = 0;
driver->drv.bus = &pcmcia_bus_type;
+ driver->drv.owner = driver->owner;
return driver_register(&driver->drv);
}
@@ -403,10 +312,16 @@ static struct proc_dir_entry *proc_pccard = NULL;
static int proc_read_drivers_callback(struct device_driver *driver, void *d)
{
char **p = d;
- struct pcmcia_driver *p_dev = container_of(driver,
+ struct pcmcia_driver *p_drv = container_of(driver,
struct pcmcia_driver, drv);
- *p += sprintf(*p, "%-24.24s 1 %d\n", driver->name, p_dev->use_count);
+ *p += sprintf(*p, "%-24.24s 1 %d\n", p_drv->drv.name,
+#ifdef CONFIG_MODULE_UNLOAD
+ (p_drv->owner) ? module_refcount(p_drv->owner) : 1
+#else
+ 1
+#endif
+ );
d = (void *) p;
return 0;
@@ -424,6 +339,31 @@ static int proc_read_drivers(char *buf, char **start, off_t pos,
}
#endif
+/* pcmcia_device handling */
+
+static struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev)
+{
+ struct device *tmp_dev;
+ tmp_dev = get_device(&p_dev->dev);
+ if (!tmp_dev)
+ return NULL;
+ return to_pcmcia_dev(tmp_dev);
+}
+
+static void pcmcia_put_dev(struct pcmcia_device *p_dev)
+{
+ put_device(&p_dev->dev);
+}
+
+static void pcmcia_release_dev(struct device *dev)
+{
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+ ds_dbg(1, "releasing dev %p\n", p_dev);
+ pcmcia_put_bus_socket(p_dev->socket->pcmcia);
+ kfree(p_dev);
+}
+
+
/*======================================================================
These manage a ring buffer of events pending for one user process
@@ -471,255 +411,494 @@ static int handle_request(struct pcmcia_bus_socket *s, event_t event)
return CS_SUCCESS;
}
-static void handle_removal(void *data)
-{
- struct pcmcia_bus_socket *s = data;
- handle_event(s, CS_EVENT_CARD_REMOVAL);
- s->state &= ~DS_SOCKET_REMOVAL_PENDING;
-}
-
/*======================================================================
The card status event handler.
======================================================================*/
-static int ds_event(event_t event, int priority,
- event_callback_args_t *args)
+struct send_event_data {
+ struct pcmcia_socket *skt;
+ event_t event;
+ int priority;
+};
+
+static int send_event_callback(struct device *dev, void * _data)
{
- struct pcmcia_bus_socket *s;
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+ struct send_event_data *data = _data;
- ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
- event, priority, args->client_handle);
- s = args->client_data;
-
- switch (event) {
-
- case CS_EVENT_CARD_REMOVAL:
- s->state &= ~DS_SOCKET_PRESENT;
- if (!(s->state & DS_SOCKET_REMOVAL_PENDING)) {
- s->state |= DS_SOCKET_REMOVAL_PENDING;
- schedule_delayed_work(&s->removal, HZ/10);
- }
- break;
-
- case CS_EVENT_CARD_INSERTION:
- s->state |= DS_SOCKET_PRESENT;
- handle_event(s, event);
- break;
+ /* we get called for all sockets, but may only pass the event
+ * for drivers _on the affected socket_ */
+ if (p_dev->socket != data->skt)
+ return 0;
- case CS_EVENT_EJECTION_REQUEST:
- return handle_request(s, event);
- break;
-
- default:
- handle_event(s, event);
- break;
- }
+ if (p_dev->client.state & (CLIENT_UNBOUND|CLIENT_STALE))
+ return 0;
- return 0;
-} /* ds_event */
+ if (p_dev->client.EventMask & data->event)
+ return EVENT(&p_dev->client, data->event, data->priority);
-/*======================================================================
+ return 0;
+}
- bind_mtd() connects a memory region with an MTD client.
-
-======================================================================*/
+static int send_event(struct pcmcia_socket *s, event_t event, int priority)
+{
+ int ret = 0;
+ struct send_event_data private;
+ struct pcmcia_bus_socket *skt = pcmcia_get_bus_socket(s->pcmcia);
+
+ if (!skt)
+ return 0;
+
+ private.skt = s;
+ private.event = event;
+ private.priority = priority;
-static int bind_mtd(struct pcmcia_bus_socket *bus_sock, mtd_info_t *mtd_info)
+ ret = bus_for_each_dev(&pcmcia_bus_type, NULL, &private, send_event_callback);
+
+ pcmcia_put_bus_socket(skt);
+ return ret;
+} /* send_event */
+
+
+/* Normally, the event is passed to individual drivers after
+ * informing userspace. Only for CS_EVENT_CARD_REMOVAL this
+ * is inversed to maintain historic compatibility.
+ */
+
+static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
{
- mtd_bind_t bind_req;
- int ret;
+ struct pcmcia_bus_socket *s = skt->pcmcia;
+ int ret = 0;
- bind_req.dev_info = &mtd_info->dev_info;
- bind_req.Attributes = mtd_info->Attributes;
- bind_req.Socket = bus_sock->parent;
- bind_req.CardOffset = mtd_info->CardOffset;
- ret = pcmcia_bind_mtd(&bind_req);
- if (ret != CS_SUCCESS) {
- cs_error(NULL, BindMTD, ret);
- printk(KERN_NOTICE "ds: unable to bind MTD '%s' to socket %d"
- " offset 0x%x\n",
- (char *)bind_req.dev_info, bus_sock->parent->sock, bind_req.CardOffset);
- return -ENODEV;
+ ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
+ event, priority, s);
+
+ switch (event) {
+
+ case CS_EVENT_CARD_REMOVAL:
+ s->state &= ~DS_SOCKET_PRESENT;
+ send_event(skt, event, priority);
+ unbind_request(s);
+ handle_event(s, event);
+ break;
+
+ case CS_EVENT_CARD_INSERTION:
+ s->state |= DS_SOCKET_PRESENT;
+ handle_event(s, event);
+ send_event(skt, event, priority);
+ break;
+
+ case CS_EVENT_EJECTION_REQUEST:
+ ret = handle_request(s, event);
+ if (ret)
+ break;
+ ret = send_event(skt, event, priority);
+ break;
+
+ default:
+ handle_event(s, event);
+ send_event(skt, event, priority);
+ break;
}
+
return 0;
-} /* bind_mtd */
+} /* ds_event */
+
/*======================================================================
+ bind_request() and bind_device() are merged by now. Register_client()
+ is called right at the end of bind_request(), during the driver's
+ ->attach() call. Individual descriptions:
+
bind_request() connects a socket to a particular client driver.
It looks up the specified device ID in the list of registered
drivers, binds it to the socket, and tries to create an instance
of the device. unbind_request() deletes a driver instance.
+ Bind_device() associates a device driver with a particular socket.
+ It is normally called by Driver Services after it has identified
+ a newly inserted card. An instance of that driver will then be
+ eligible to register as a client of this socket.
+
+ Register_client() uses the dev_info_t handle to match the
+ caller with a socket. The driver must have already been bound
+ to a socket with bind_device() -- in fact, bind_device()
+ allocates the client structure that will be used.
+
======================================================================*/
static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
{
- struct pcmcia_driver *driver;
- socket_bind_t *b;
- bind_req_t bind_req;
- int ret;
+ struct pcmcia_driver *p_drv;
+ struct pcmcia_device *p_dev, *tmp_dev;
+ unsigned long flags;
+ int ret = 0;
- if (!s)
- return -EINVAL;
-
- ds_dbg(2, "bind_request(%d, '%s')\n", s->parent->sock,
- (char *)bind_info->dev_info);
- driver = get_pcmcia_driver(&bind_info->dev_info);
- if (!driver)
- return -EINVAL;
-
- for (b = s->bind; b; b = b->next)
- if ((driver == b->driver) &&
- (bind_info->function == b->function))
- break;
- if (b != NULL) {
- bind_info->instance = b->instance;
- return -EBUSY;
- }
+ s = pcmcia_get_bus_socket(s);
+ if (!s)
+ return -EINVAL;
- if (!try_module_get(driver->owner))
- return -EINVAL;
-
- bind_req.Socket = s->parent;
- bind_req.Function = bind_info->function;
- bind_req.dev_info = (dev_info_t *) driver->drv.name;
- ret = pcmcia_bind_device(&bind_req);
- if (ret != CS_SUCCESS) {
- cs_error(NULL, BindDevice, ret);
- printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n",
- (char *)dev_info, s->parent->sock);
- module_put(driver->owner);
- return -ENODEV;
- }
+ ds_dbg(2, "bind_request(%d, '%s')\n", s->parent->sock,
+ (char *)bind_info->dev_info);
- /* Add binding to list for this socket */
- driver->use_count++;
- b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL);
- if (!b)
- {
- driver->use_count--;
- module_put(driver->owner);
- return -ENOMEM;
- }
- b->driver = driver;
- b->function = bind_info->function;
- b->instance = NULL;
- b->next = s->bind;
- s->bind = b;
-
- if (driver->attach) {
- b->instance = driver->attach();
- if (b->instance == NULL) {
- printk(KERN_NOTICE "ds: unable to create instance "
- "of '%s'!\n", (char *)bind_info->dev_info);
- module_put(driver->owner);
- return -ENODEV;
+ p_drv = get_pcmcia_driver(&bind_info->dev_info);
+ if (!p_drv) {
+ ret = -EINVAL;
+ goto err_put;
}
- }
-
- return 0;
+
+ if (!try_module_get(p_drv->owner)) {
+ ret = -EINVAL;
+ goto err_put_driver;
+ }
+
+ /* Currently, the userspace pcmcia cardmgr detects pcmcia devices.
+ * Here this information is translated into a kernel
+ * struct pcmcia_device.
+ */
+
+ p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
+ if (!p_dev) {
+ ret = -ENOMEM;
+ goto err_put_module;
+ }
+ memset(p_dev, 0, sizeof(struct pcmcia_device));
+
+ p_dev->socket = s->parent;
+ p_dev->device_no = (s->device_count++);
+ p_dev->func = bind_info->function;
+
+ p_dev->dev.bus = &pcmcia_bus_type;
+ p_dev->dev.parent = s->parent->dev.dev;
+ p_dev->dev.release = pcmcia_release_dev;
+ sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+ p_dev->dev.driver = &p_drv->drv;
+
+ /* compat */
+ p_dev->client.client_magic = CLIENT_MAGIC;
+ p_dev->client.Socket = s->parent;
+ p_dev->client.Function = bind_info->function;
+ p_dev->client.state = CLIENT_UNBOUND;
+
+ ret = device_register(&p_dev->dev);
+ if (ret) {
+ kfree(p_dev);
+ goto err_put_module;
+ }
+
+ /* Add to the list in pcmcia_bus_socket, but only if no device
+ * with the same func _and_ driver exists */
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) {
+ if ((tmp_dev->func == bind_info->function) &&
+ (tmp_dev->dev.driver == p_dev->dev.driver)){
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ bind_info->instance = tmp_dev->instance;
+ ret = -EBUSY;
+ goto err_unregister;
+ }
+ }
+ list_add_tail(&p_dev->socket_device_list, &s->devices_list);
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+ if (p_drv->attach) {
+ p_dev->instance = p_drv->attach();
+ if ((!p_dev->instance) || (p_dev->client.state & CLIENT_UNBOUND)) {
+ printk(KERN_NOTICE "ds: unable to create instance "
+ "of '%s'!\n", (char *)bind_info->dev_info);
+ ret = -ENODEV;
+ goto err_unregister;
+ }
+ }
+
+ put_driver(&p_drv->drv);
+
+ return 0;
+
+ err_unregister:
+ device_unregister(&p_dev->dev);
+ module_put(p_drv->owner);
+ put_driver(&p_drv->drv);
+ return (ret);
+
+ err_put_module:
+ module_put(p_drv->owner);
+ err_put_driver:
+ put_driver(&p_drv->drv);
+ err_put:
+ pcmcia_put_bus_socket(s);
+ return (ret);
} /* bind_request */
+int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
+{
+ client_t *client = NULL;
+ struct pcmcia_socket *s;
+ struct pcmcia_bus_socket *skt = NULL;
+ struct pcmcia_device *p_dev = NULL;
+
+ /* Look for unbound client with matching dev_info */
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
+ unsigned long flags;
+
+ if (s->state & SOCKET_CARDBUS)
+ continue;
+
+ skt = s->pcmcia;
+ if (!skt)
+ continue;
+ skt = pcmcia_get_bus_socket(skt);
+ if (!skt)
+ continue;
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_for_each_entry(p_dev, &skt->devices_list, socket_device_list) {
+ struct pcmcia_driver *p_drv;
+ p_dev = pcmcia_get_dev(p_dev);
+ if (!p_dev)
+ continue;
+ if ((!p_dev->client.state & CLIENT_UNBOUND) ||
+ (!p_dev->dev.driver)) {
+ pcmcia_put_dev(p_dev);
+ continue;
+ }
+ p_drv = to_pcmcia_drv(p_dev->dev.driver);
+ if (!strncmp(p_drv->drv.name, (char *)req->dev_info, DEV_NAME_LEN)) {
+ client = &p_dev->client;
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ goto found;
+ }
+ pcmcia_put_dev(p_dev);
+ }
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ pcmcia_put_bus_socket(skt);
+ }
+ found:
+ up_read(&pcmcia_socket_list_rwsem);
+ if (!p_dev || !client)
+ return -ENODEV;
+
+ pcmcia_put_bus_socket(skt); /* safe, as we already hold a reference from bind_device */
+
+ /*
+ * Prevent this racing with a card insertion.
+ */
+ down(&s->skt_sem);
+ *handle = client;
+ client->state &= ~CLIENT_UNBOUND;
+ client->Socket = s;
+ client->EventMask = req->EventMask;
+ client->event_handler = req->event_handler;
+ client->event_callback_args = req->event_callback_args;
+ client->event_callback_args.client_handle = client;
+
+ if (s->state & SOCKET_CARDBUS)
+ client->state |= CLIENT_CARDBUS;
+
+ if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) &&
+ (client->Function != BIND_FN_ALL)) {
+ cistpl_longlink_mfc_t mfc;
+ if (pccard_read_tuple(s, client->Function, CISTPL_LONGLINK_MFC, &mfc)
+ == CS_SUCCESS)
+ s->functions = mfc.nfn;
+ else
+ s->functions = 1;
+ s->config = kmalloc(sizeof(config_t) * s->functions,
+ GFP_KERNEL);
+ if (!s->config)
+ goto out_no_resource;
+ memset(s->config, 0, sizeof(config_t) * s->functions);
+ }
+
+ ds_dbg(1, "register_client(): client 0x%p, dev %s\n",
+ client, p_dev->dev.bus_id);
+ if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
+ EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW);
+
+ if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) {
+ if (client->EventMask & CS_EVENT_CARD_INSERTION)
+ EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
+ }
+
+ up(&s->skt_sem);
+ return CS_SUCCESS;
+
+ out_no_resource:
+ up(&s->skt_sem);
+ pcmcia_put_dev(p_dev);
+ return CS_OUT_OF_RESOURCE;
+} /* register_client */
+EXPORT_SYMBOL(pcmcia_register_client);
+
+
/*====================================================================*/
extern struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s);
static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info, int first)
{
- socket_bind_t *b;
- dev_node_t *node;
+ dev_node_t *node;
+ struct pcmcia_device *p_dev;
+ unsigned long flags;
+ int ret = 0;
#ifdef CONFIG_CARDBUS
- /*
- * Some unbelievably ugly code to associate the PCI cardbus
- * device and its driver with the PCMCIA "bind" information.
- */
- {
- struct pci_bus *bus;
-
- bus = pcmcia_lookup_bus(s->parent);
- if (bus) {
- struct list_head *list;
- struct pci_dev *dev = NULL;
-
- list = bus->devices.next;
- while (list != &bus->devices) {
- struct pci_dev *pdev = pci_dev_b(list);
- list = list->next;
-
- if (first) {
- dev = pdev;
- break;
- }
+ /*
+ * Some unbelievably ugly code to associate the PCI cardbus
+ * device and its driver with the PCMCIA "bind" information.
+ */
+ {
+ struct pci_bus *bus;
- /* Try to handle "next" here some way? */
- }
- if (dev && dev->driver) {
- strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN);
- bind_info->major = 0;
- bind_info->minor = 0;
- bind_info->next = NULL;
- return 0;
+ bus = pcmcia_lookup_bus(s->parent);
+ if (bus) {
+ struct list_head *list;
+ struct pci_dev *dev = NULL;
+
+ list = bus->devices.next;
+ while (list != &bus->devices) {
+ struct pci_dev *pdev = pci_dev_b(list);
+ list = list->next;
+
+ if (first) {
+ dev = pdev;
+ break;
+ }
+
+ /* Try to handle "next" here some way? */
+ }
+ if (dev && dev->driver) {
+ strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN);
+ bind_info->major = 0;
+ bind_info->minor = 0;
+ bind_info->next = NULL;
+ return 0;
+ }
}
}
- }
#endif
- for (b = s->bind; b; b = b->next)
- if ((strcmp((char *)b->driver->drv.name,
- (char *)bind_info->dev_info) == 0) &&
- (b->function == bind_info->function))
- break;
- if (b == NULL) return -ENODEV;
- if ((b->instance == NULL) ||
- (b->instance->state & DEV_CONFIG_PENDING))
- return -EAGAIN;
- if (first)
- node = b->instance->dev;
- else
- for (node = b->instance->dev; node; node = node->next)
- if (node == bind_info->next) break;
- if (node == NULL) return -ENODEV;
-
- strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN);
- bind_info->major = node->major;
- bind_info->minor = node->minor;
- bind_info->next = node->next;
-
- return 0;
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
+ if (p_dev->func == bind_info->function) {
+ p_dev = pcmcia_get_dev(p_dev);
+ if (!p_dev)
+ continue;
+ goto found;
+ }
+ }
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ return -ENODEV;
+
+ found:
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+ if ((!p_dev->instance) ||
+ (p_dev->instance->state & DEV_CONFIG_PENDING)) {
+ ret = -EAGAIN;
+ goto err_put;
+ }
+
+ if (first)
+ node = p_dev->instance->dev;
+ else
+ for (node = p_dev->instance->dev; node; node = node->next)
+ if (node == bind_info->next)
+ break;
+ if (!node) {
+ ret = -ENODEV;
+ goto err_put;
+ }
+
+ strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN);
+ bind_info->major = node->major;
+ bind_info->minor = node->minor;
+ bind_info->next = node->next;
+
+ err_put:
+ pcmcia_put_dev(p_dev);
+ return (ret);
} /* get_device_info */
/*====================================================================*/
-static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
+/* unbind _all_ devices attached to a given pcmcia_bus_socket. The
+ * drivers have been called with EVENT_CARD_REMOVAL before.
+ */
+static int unbind_request(struct pcmcia_bus_socket *s)
{
- socket_bind_t **b, *c;
-
- ds_dbg(2, "unbind_request(%d, '%s')\n", s->parent->sock,
- (char *)bind_info->dev_info);
- for (b = &s->bind; *b; b = &(*b)->next)
- if ((strcmp((char *)(*b)->driver->drv.name,
- (char *)bind_info->dev_info) == 0) &&
- ((*b)->function == bind_info->function))
- break;
- if (*b == NULL)
- return -ENODEV;
-
- c = *b;
- c->driver->use_count--;
- if (c->driver->detach) {
- if (c->instance)
- c->driver->detach(c->instance);
- }
- module_put(c->driver->owner);
- *b = c->next;
- kfree(c);
- return 0;
+ struct pcmcia_device *p_dev;
+ struct pcmcia_driver *p_drv;
+ unsigned long flags;
+
+ ds_dbg(2, "unbind_request(%d)\n", s->parent->sock);
+
+ s->device_count = 0;
+
+ for (;;) {
+ /* unregister all pcmcia_devices registered with this socket*/
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ if (list_empty(&s->devices_list)) {
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ return 0;
+ }
+ p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
+ list_del(&p_dev->socket_device_list);
+ p_dev->client.state |= CLIENT_STALE;
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+ /* detach the "instance" */
+ p_drv = to_pcmcia_drv(p_dev->dev.driver);
+ if (p_drv) {
+ if ((p_drv->detach) && (p_dev->instance))
+ p_drv->detach(p_dev->instance);
+ module_put(p_drv->owner);
+ }
+
+ device_unregister(&p_dev->dev);
+ }
+
+ return 0;
} /* unbind_request */
+int pcmcia_deregister_client(client_handle_t handle)
+{
+ struct pcmcia_socket *s;
+ int i;
+ struct pcmcia_device *p_dev = handle_to_pdev(handle);
+
+ if (CHECK_HANDLE(handle))
+ return CS_BAD_HANDLE;
+
+ s = SOCKET(handle);
+ ds_dbg(1, "deregister_client(%p)\n", handle);
+
+ if (handle->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
+ goto warn_out;
+ for (i = 0; i < MAX_WIN; i++)
+ if (handle->state & CLIENT_WIN_REQ(i))
+ goto warn_out;
+
+ if (handle->state & CLIENT_STALE) {
+ handle->client_magic = 0;
+ handle->state &= ~CLIENT_STALE;
+ pcmcia_put_dev(p_dev);
+ } else {
+ handle->state = CLIENT_UNBOUND;
+ handle->event_handler = NULL;
+ }
+
+ return CS_SUCCESS;
+ warn_out:
+ printk(KERN_WARNING "ds: deregister_client was called too early.\n");
+ return CS_IN_USE;
+} /* deregister_client */
+EXPORT_SYMBOL(pcmcia_deregister_client);
+
+
/*======================================================================
The user-mode PC Card device interface
@@ -734,19 +913,27 @@ static int ds_open(struct inode *inode, struct file *file)
ds_dbg(0, "ds_open(socket %d)\n", i);
- s = pcmcia_get_bus_socket(i);
+ s = get_socket_info_by_nr(i);
+ if (!s)
+ return -ENODEV;
+ s = pcmcia_get_bus_socket(s);
if (!s)
return -ENODEV;
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
- if (s->state & DS_SOCKET_BUSY)
- return -EBUSY;
+ if (s->state & DS_SOCKET_BUSY) {
+ pcmcia_put_bus_socket(s);
+ return -EBUSY;
+ }
else
s->state |= DS_SOCKET_BUSY;
}
user = kmalloc(sizeof(user_info_t), GFP_KERNEL);
- if (!user) return -ENOMEM;
+ if (!user) {
+ pcmcia_put_bus_socket(s);
+ return -ENOMEM;
+ }
user->event_tail = user->event_head = 0;
user->next = s->user;
user->user_magic = USER_MAGIC;
@@ -883,8 +1070,6 @@ static u_int ds_poll(struct file *file, poll_table *wait)
/*====================================================================*/
extern int pcmcia_adjust_resource_info(adjust_t *adj);
-extern int pccard_get_next_region(struct pcmcia_socket *s, region_info_t *rgn);
-extern int pccard_get_first_region(struct pcmcia_socket *s, region_info_t *rgn);
static int ds_ioctl(struct inode * inode, struct file * file,
u_int cmd, u_long arg)
@@ -893,7 +1078,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
void __user *uarg = (char __user *)arg;
u_int size;
int ret, err;
- ds_ioctl_arg_t buf;
+ ds_ioctl_arg_t *buf;
user_info_t *user;
ds_dbg(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg);
@@ -927,54 +1112,58 @@ static int ds_ioctl(struct inode * inode, struct file * file,
return err;
}
}
+ buf = kmalloc(sizeof(ds_ioctl_arg_t), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
err = ret = 0;
- if (cmd & IOC_IN) __copy_from_user((char *)&buf, uarg, size);
+ if (cmd & IOC_IN) __copy_from_user((char *)buf, uarg, size);
switch (cmd) {
case DS_ADJUST_RESOURCE_INFO:
- ret = pcmcia_adjust_resource_info(&buf.adjust);
+ ret = pcmcia_adjust_resource_info(&buf->adjust);
break;
case DS_GET_CARD_SERVICES_INFO:
- ret = pcmcia_get_card_services_info(&buf.servinfo);
+ ret = pcmcia_get_card_services_info(&buf->servinfo);
break;
case DS_GET_CONFIGURATION_INFO:
- if (buf.config.Function &&
- (buf.config.Function >= s->parent->functions))
+ if (buf->config.Function &&
+ (buf->config.Function >= s->parent->functions))
ret = CS_BAD_ARGS;
else
- ret = pccard_get_configuration_info(s->parent, buf.config.Function, &buf.config);
+ ret = pccard_get_configuration_info(s->parent,
+ buf->config.Function, &buf->config);
break;
case DS_GET_FIRST_TUPLE:
pcmcia_validate_mem(s->parent);
- ret = pccard_get_first_tuple(s->parent, BIND_FN_ALL, &buf.tuple);
+ ret = pccard_get_first_tuple(s->parent, BIND_FN_ALL, &buf->tuple);
break;
case DS_GET_NEXT_TUPLE:
- ret = pccard_get_next_tuple(s->parent, BIND_FN_ALL, &buf.tuple);
+ ret = pccard_get_next_tuple(s->parent, BIND_FN_ALL, &buf->tuple);
break;
case DS_GET_TUPLE_DATA:
- buf.tuple.TupleData = buf.tuple_parse.data;
- buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data);
- ret = pccard_get_tuple_data(s->parent, &buf.tuple);
+ buf->tuple.TupleData = buf->tuple_parse.data;
+ buf->tuple.TupleDataMax = sizeof(buf->tuple_parse.data);
+ ret = pccard_get_tuple_data(s->parent, &buf->tuple);
break;
case DS_PARSE_TUPLE:
- buf.tuple.TupleData = buf.tuple_parse.data;
- ret = pccard_parse_tuple(&buf.tuple, &buf.tuple_parse.parse);
+ buf->tuple.TupleData = buf->tuple_parse.data;
+ ret = pccard_parse_tuple(&buf->tuple, &buf->tuple_parse.parse);
break;
case DS_RESET_CARD:
ret = pccard_reset_card(s->parent);
break;
case DS_GET_STATUS:
- if (buf.status.Function &&
- (buf.status.Function >= s->parent->functions))
+ if (buf->status.Function &&
+ (buf->status.Function >= s->parent->functions))
ret = CS_BAD_ARGS;
else
- ret = pccard_get_status(s->parent, buf.status.Function, &buf.status);
+ ret = pccard_get_status(s->parent, buf->status.Function, &buf->status);
break;
case DS_VALIDATE_CIS:
pcmcia_validate_mem(s->parent);
- ret = pccard_validate_cis(s->parent, BIND_FN_ALL, &buf.cisinfo);
+ ret = pccard_validate_cis(s->parent, BIND_FN_ALL, &buf->cisinfo);
break;
case DS_SUSPEND_CARD:
ret = pcmcia_suspend_card(s->parent);
@@ -989,49 +1178,64 @@ static int ds_ioctl(struct inode * inode, struct file * file,
err = pcmcia_insert_card(s->parent);
break;
case DS_ACCESS_CONFIGURATION_REGISTER:
- if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (buf.conf_reg.Function &&
- (buf.conf_reg.Function >= s->parent->functions))
+ if ((buf->conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) {
+ err = -EPERM;
+ goto free_out;
+ }
+ if (buf->conf_reg.Function &&
+ (buf->conf_reg.Function >= s->parent->functions))
ret = CS_BAD_ARGS;
else
- ret = pccard_access_configuration_register(s->parent, buf.conf_reg.Function, &buf.conf_reg);
+ ret = pccard_access_configuration_register(s->parent,
+ buf->conf_reg.Function, &buf->conf_reg);
break;
case DS_GET_FIRST_REGION:
- ret = pccard_get_first_region(s->parent, &buf.region);
- break;
case DS_GET_NEXT_REGION:
- ret = pccard_get_next_region(s->parent, &buf.region);
+ case DS_BIND_MTD:
+ if (!capable(CAP_SYS_ADMIN)) {
+ err = -EPERM;
+ goto free_out;
+ } else {
+ static int printed = 0;
+ if (!printed) {
+ printk(KERN_WARNING "2.6. kernels use pcmciamtd instead of memory_cs.c and do not require special\n");
+ printk(KERN_WARNING "MTD handling any more.\n");
+ printed++;
+ }
+ }
+ ret = -EINVAL;
+ goto free_out;
break;
case DS_GET_FIRST_WINDOW:
- ret = pcmcia_get_window(s->parent, &buf.win_info.handle, 0, &buf.win_info.window);
+ ret = pcmcia_get_window(s->parent, &buf->win_info.handle, 0,
+ &buf->win_info.window);
break;
case DS_GET_NEXT_WINDOW:
- ret = pcmcia_get_window(s->parent, &buf.win_info.handle, buf.win_info.handle->index + 1, &buf.win_info.window);
+ ret = pcmcia_get_window(s->parent, &buf->win_info.handle,
+ buf->win_info.handle->index + 1, &buf->win_info.window);
break;
case DS_GET_MEM_PAGE:
- ret = pcmcia_get_mem_page(buf.win_info.handle,
- &buf.win_info.map);
+ ret = pcmcia_get_mem_page(buf->win_info.handle,
+ &buf->win_info.map);
break;
case DS_REPLACE_CIS:
- ret = pcmcia_replace_cis(s->parent, &buf.cisdump);
+ ret = pcmcia_replace_cis(s->parent, &buf->cisdump);
break;
case DS_BIND_REQUEST:
- if (!capable(CAP_SYS_ADMIN)) return -EPERM;
- err = bind_request(s, &buf.bind_info);
+ if (!capable(CAP_SYS_ADMIN)) {
+ err = -EPERM;
+ goto free_out;
+ }
+ err = bind_request(s, &buf->bind_info);
break;
case DS_GET_DEVICE_INFO:
- err = get_device_info(s, &buf.bind_info, 1);
+ err = get_device_info(s, &buf->bind_info, 1);
break;
case DS_GET_NEXT_DEVICE:
- err = get_device_info(s, &buf.bind_info, 0);
+ err = get_device_info(s, &buf->bind_info, 0);
break;
case DS_UNBIND_REQUEST:
- err = unbind_request(s, &buf.bind_info);
- break;
- case DS_BIND_MTD:
- if (!capable(CAP_SYS_ADMIN)) return -EPERM;
- err = bind_mtd(s, &buf.mtd_info);
+ err = 0;
break;
default:
err = -EINVAL;
@@ -1059,11 +1263,12 @@ static int ds_ioctl(struct inode * inode, struct file * file,
}
if (cmd & IOC_OUT) {
- if (__copy_to_user(uarg, (char *)&buf, size))
+ if (__copy_to_user(uarg, (char *)buf, size))
err = -EFAULT;
}
-
+free_out:
+ kfree(buf);
return err;
} /* ds_ioctl */
@@ -1081,9 +1286,7 @@ static struct file_operations ds_fops = {
static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
{
- struct pcmcia_socket *socket = class_dev->class_data;
- client_reg_t client_reg;
- bind_req_t bind;
+ struct pcmcia_socket *socket = class_get_devdata(class_dev);
struct pcmcia_bus_socket *s;
int ret;
@@ -1091,7 +1294,16 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
if(!s)
return -ENOMEM;
memset(s, 0, sizeof(struct pcmcia_bus_socket));
- atomic_set(&s->refcount, 1);
+
+ /* get reference to parent socket */
+ s->parent = pcmcia_get_socket(socket);
+ if (!s->parent) {
+ printk(KERN_ERR "PCMCIA obtaining reference to socket %p failed\n", socket);
+ kfree (s);
+ return -ENODEV;
+ }
+
+ kref_init(&s->refcount);
/*
* Ugly. But we want to wait for the socket threads to have started up.
@@ -1101,55 +1313,33 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
init_waitqueue_head(&s->queue);
init_waitqueue_head(&s->request);
-
- /* initialize data */
- INIT_WORK(&s->removal, handle_removal, s);
- s->parent = socket;
+ INIT_LIST_HEAD(&s->devices_list);
/* Set up hotline to Card Services */
- client_reg.dev_info = bind.dev_info = &dev_info;
-
- bind.Socket = socket;
- bind.Function = BIND_FN_ALL;
- ret = pcmcia_bind_device(&bind);
- if (ret != CS_SUCCESS) {
- cs_error(NULL, BindDevice, ret);
- kfree(s);
- return -EINVAL;
- }
+ s->callback.owner = THIS_MODULE;
+ s->callback.event = &ds_event;
+ socket->pcmcia = s;
- client_reg.Attributes = INFO_MASTER_CLIENT;
- client_reg.EventMask =
- CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
- CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
- CS_EVENT_EJECTION_REQUEST | CS_EVENT_INSERTION_REQUEST |
- CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
- client_reg.event_handler = &ds_event;
- client_reg.Version = 0x0210;
- client_reg.event_callback_args.client_data = s;
- ret = pcmcia_register_client(&s->handle, &client_reg);
- if (ret != CS_SUCCESS) {
- cs_error(NULL, RegisterClient, ret);
- kfree(s);
- return -EINVAL;
+ ret = pccard_register_pcmcia(socket, &s->callback);
+ if (ret) {
+ printk(KERN_ERR "PCMCIA registration PCCard core failed for socket %p\n", socket);
+ pcmcia_put_bus_socket(s);
+ socket->pcmcia = NULL;
+ return (ret);
}
- socket->pcmcia = s;
-
return 0;
}
static void pcmcia_bus_remove_socket(struct class_device *class_dev)
{
- struct pcmcia_socket *socket = class_dev->class_data;
+ struct pcmcia_socket *socket = class_get_devdata(class_dev);
if (!socket || !socket->pcmcia)
return;
- flush_scheduled_work();
-
- pcmcia_deregister_client(socket->pcmcia->handle);
+ pccard_register_pcmcia(socket, NULL);
socket->pcmcia->state |= DS_SOCKET_DEAD;
pcmcia_put_bus_socket(socket->pcmcia);
@@ -1177,6 +1367,8 @@ static int __init init_pcmcia_bus(void)
{
int i;
+ spin_lock_init(&pcmcia_dev_list_lock);
+
bus_register(&pcmcia_bus_type);
class_interface_register(&pcmcia_bus_interface);
@@ -1232,33 +1424,18 @@ static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr)
/* backwards-compatible accessing of driver --- by name! */
-struct cmp_data {
- void *dev_info;
- struct pcmcia_driver *drv;
-};
-
-static int cmp_drv_callback(struct device_driver *drv, void *data)
-{
- struct cmp_data *cmp = data;
- if (strncmp((char *)cmp->dev_info, (char *)drv->name,
- DEV_NAME_LEN) == 0) {
- cmp->drv = container_of(drv, struct pcmcia_driver, drv);
- return -EINVAL;
- }
- return 0;
-}
-
static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info)
{
- int ret;
- struct cmp_data cmp = {
- .dev_info = dev_info,
- };
-
- ret = bus_for_each_drv(&pcmcia_bus_type, NULL, &cmp, cmp_drv_callback);
- if (ret)
- return cmp.drv;
- return NULL;
+ struct device_driver *drv;
+ struct pcmcia_driver *p_drv;
+
+ drv = driver_find((char *) dev_info, &pcmcia_bus_type);
+ if (!drv)
+ return NULL;
+
+ p_drv = container_of(drv, struct pcmcia_driver, drv);
+
+ return (p_drv);
}
MODULE_ALIAS("ds");
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index 875c9cfaea3f..36d85f04e276 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -922,6 +922,7 @@ static int __init init_hs(void)
hs_set_voltages(&hs_sockets[i], 0, 0);
hs_sockets[i].socket.features |= SS_CAP_PCCARD | SS_CAP_STATIC_MAP; /* mappings are fixed in host memory */
+ hs_sockets[i].socket.resource_ops = &pccard_static_ops;
hs_sockets[i].socket.irq_mask = 0xffde;/*0xffff*/ /* IRQs mapped in s/w so can do any, really */
hs_sockets[i].socket.map_size = HD64465_PCC_WINDOW; /* 16MB fixed window size */
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index eb255238aef8..aa8ed192d21a 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -162,6 +162,7 @@ static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_de
for (i = 0; i<socket_count; i++) {
sockets[i].socket.dev.dev = &dev->dev;
sockets[i].socket.ops = &i82092aa_operations;
+ sockets[i].socket.resource_ops = &pccard_nonstatic_ops;
ret = pcmcia_register_socket(&sockets[i].socket);
if (ret) {
goto err_out_free_sockets;
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 56ced25d993c..0d9bb1505c2e 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -1400,6 +1400,7 @@ static int __init init_i82365(void)
for (i = 0; i < sockets; i++) {
socket[i].socket.dev.dev = &i82365_device.dev;
socket[i].socket.ops = &pcic_operations;
+ socket[i].socket.resource_ops = &pccard_nonstatic_ops;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i;
ret = pcmcia_register_socket(&socket[i].socket);
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 836058dfa2c0..023013d3e263 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -831,6 +831,7 @@ static int __init init_m32r_pcc(void)
for (i = 0 ; i < pcc_sockets ; i++) {
socket[i].socket.dev.dev = &pcc_device.dev;
socket[i].socket.ops = &pcc_operations;
+ socket[i].socket.resource_ops = &pccard_static_ops;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i;
ret = pcmcia_register_socket(&socket[i].socket);
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index aae7a16a1815..8c881ae73287 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -768,6 +768,7 @@ static int __init init_m32r_pcc(void)
for (i = 0 ; i < pcc_sockets ; i++) {
socket[i].socket.dev.dev = &pcc_device.dev;
socket[i].socket.ops = &pcc_operations;
+ socket[i].socket.resource_ops = &pccard_static_ops;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i;
ret = pcmcia_register_socket(&socket[i].socket);
diff --git a/drivers/pcmcia/pcmcia_compat.c b/drivers/pcmcia/pcmcia_compat.c
index 673d34576d3b..68b80084f83f 100644
--- a/drivers/pcmcia/pcmcia_compat.c
+++ b/drivers/pcmcia/pcmcia_compat.c
@@ -123,23 +123,3 @@ int pcmcia_access_configuration_register(client_handle_t handle,
}
EXPORT_SYMBOL(pcmcia_access_configuration_register);
-#ifdef CONFIG_PCMCIA_OBSOLETE
-
-int pcmcia_get_first_window(window_handle_t *win, win_req_t *req)
-{
- if ((win == NULL) || ((*win)->magic != WINDOW_MAGIC))
- return CS_BAD_HANDLE;
-
- return pcmcia_get_window(((client_handle_t)*win)->Socket, win, 0, req);
-}
-EXPORT_SYMBOL(pcmcia_get_first_window);
-
-int pcmcia_get_next_window(window_handle_t *win, win_req_t *req)
-{
- if ((win == NULL) || ((*win)->magic != WINDOW_MAGIC))
- return CS_BAD_HANDLE;
- return pcmcia_get_window((*win)->sock, win, (*win)->index+1, req);
-}
-EXPORT_SYMBOL(pcmcia_get_next_window);
-
-#endif
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 4f00c9dda075..1347f94260c7 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -29,7 +29,7 @@
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Driver for the Cirrus PD6729 PCI-PCMCIA bridge");
-MODULE_AUTHOR("Jun Komuro <komurojun@mbn.nifty.com>");
+MODULE_AUTHOR("Jun Komuro <komurojun-mbn@nifty.com>");
#define MAX_SOCKETS 2
@@ -39,11 +39,40 @@ MODULE_AUTHOR("Jun Komuro <komurojun@mbn.nifty.com>");
*/
#define to_cycles(ns) ((ns)/120)
+#ifndef NO_IRQ
+#define NO_IRQ ((unsigned int)(0))
+#endif
+
+/*
+ * PARAMETERS
+ * irq_mode=n
+ * Specifies the interrupt delivery mode. The default (1) is to use PCI
+ * interrupts; a value of 0 selects ISA interrupts. This must be set for
+ * correct operation of PCI card readers.
+ *
+ * irq_list=i,j,...
+ * This list limits the set of interrupts that can be used by PCMCIA
+ * cards.
+ * The default list is 3,4,5,7,9,10,11.
+ * (irq_list parameter is not used, if irq_mode = 1)
+ */
+
+static int irq_mode = 1; /* 0 = ISA interrupt, 1 = PCI interrupt */
+static int irq_list[16];
+static int irq_list_count = 0;
+
+module_param(irq_mode, int, 0444);
+module_param_array(irq_list, int, &irq_list_count, 0444);
+MODULE_PARM_DESC(irq_mode,
+ "interrupt delivery mode. 0 = ISA, 1 = PCI. default is 1");
+MODULE_PARM_DESC(irq_list, "interrupts that can be used by PCMCIA cards");
+
static spinlock_t port_lock = SPIN_LOCK_UNLOCKED;
/* basic value read/write functions */
-static unsigned char indirect_read(struct pd6729_socket *socket, unsigned short reg)
+static unsigned char indirect_read(struct pd6729_socket *socket,
+ unsigned short reg)
{
unsigned long port;
unsigned char val;
@@ -59,7 +88,8 @@ static unsigned char indirect_read(struct pd6729_socket *socket, unsigned short
return val;
}
-static unsigned short indirect_read16(struct pd6729_socket *socket, unsigned short reg)
+static unsigned short indirect_read16(struct pd6729_socket *socket,
+ unsigned short reg)
{
unsigned long port;
unsigned short tmp;
@@ -78,7 +108,8 @@ static unsigned short indirect_read16(struct pd6729_socket *socket, unsigned sho
return tmp;
}
-static void indirect_write(struct pd6729_socket *socket, unsigned short reg, unsigned char value)
+static void indirect_write(struct pd6729_socket *socket, unsigned short reg,
+ unsigned char value)
{
unsigned long port;
unsigned long flags;
@@ -91,7 +122,8 @@ static void indirect_write(struct pd6729_socket *socket, unsigned short reg, uns
spin_unlock_irqrestore(&port_lock, flags);
}
-static void indirect_setbit(struct pd6729_socket *socket, unsigned short reg, unsigned char mask)
+static void indirect_setbit(struct pd6729_socket *socket, unsigned short reg,
+ unsigned char mask)
{
unsigned long port;
unsigned char val;
@@ -108,7 +140,8 @@ static void indirect_setbit(struct pd6729_socket *socket, unsigned short reg, un
spin_unlock_irqrestore(&port_lock, flags);
}
-static void indirect_resetbit(struct pd6729_socket *socket, unsigned short reg, unsigned char mask)
+static void indirect_resetbit(struct pd6729_socket *socket, unsigned short reg,
+ unsigned char mask)
{
unsigned long port;
unsigned char val;
@@ -125,7 +158,8 @@ static void indirect_resetbit(struct pd6729_socket *socket, unsigned short reg,
spin_unlock_irqrestore(&port_lock, flags);
}
-static void indirect_write16(struct pd6729_socket *socket, unsigned short reg, unsigned short value)
+static void indirect_write16(struct pd6729_socket *socket, unsigned short reg,
+ unsigned short value)
{
unsigned long port;
unsigned char val;
@@ -160,7 +194,8 @@ static irqreturn_t pd6729_interrupt(int irq, void *dev, struct pt_regs *regs)
while (1) {
loopcount++;
if (loopcount > 20) {
- printk(KERN_ERR "pd6729: infinite eventloop in interrupt\n");
+ printk(KERN_ERR "pd6729: infinite eventloop "
+ "in interrupt\n");
break;
}
@@ -182,14 +217,19 @@ static irqreturn_t pd6729_interrupt(int irq, void *dev, struct pt_regs *regs)
dprintk("Card detected in socket %i!\n", i);
}
- if (indirect_read(&socket[i], I365_INTCTL) & I365_PC_IOCARD) {
+ if (indirect_read(&socket[i], I365_INTCTL)
+ & I365_PC_IOCARD) {
/* For IO/CARDS, bit 0 means "read the card" */
- events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
+ events |= (csc & I365_CSC_STSCHG)
+ ? SS_STSCHG : 0;
} else {
/* Check for battery/ready events */
- events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
- events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
- events |= (csc & I365_CSC_READY) ? SS_READY : 0;
+ events |= (csc & I365_CSC_BVD1)
+ ? SS_BATDEAD : 0;
+ events |= (csc & I365_CSC_BVD2)
+ ? SS_BATWARN : 0;
+ events |= (csc & I365_CSC_READY)
+ ? SS_READY : 0;
}
if (events) {
@@ -206,17 +246,18 @@ static irqreturn_t pd6729_interrupt(int irq, void *dev, struct pt_regs *regs)
/* socket functions */
-static void set_bridge_state(struct pd6729_socket *socket)
+static void pd6729_interrupt_wrapper(unsigned long data)
{
- indirect_write(socket, I365_GBLCTL, 0x00);
- indirect_write(socket, I365_GENCTL, 0x00);
+ struct pd6729_socket *socket = (struct pd6729_socket *) data;
- indirect_setbit(socket, I365_INTCTL, 0x08);
+ pd6729_interrupt(0, (void *)socket, NULL);
+ mod_timer(&socket->poll_timer, jiffies + HZ);
}
static int pd6729_get_status(struct pcmcia_socket *sock, u_int *value)
{
- struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
+ struct pd6729_socket *socket
+ = container_of(sock, struct pd6729_socket, socket);
unsigned int status;
unsigned int data;
struct pd6729_socket *t;
@@ -265,7 +306,8 @@ static int pd6729_get_status(struct pcmcia_socket *sock, u_int *value)
static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
- struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
+ struct pd6729_socket *socket
+ = container_of(sock, struct pd6729_socket, socket);
unsigned char reg, vcc, vpp;
state->flags = 0;
@@ -274,10 +316,7 @@ static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
state->io_irq = 0;
state->csc_mask = 0;
- /*
- * First the power status of the socket
- * PCTRL - Power Control Register
- */
+ /* First the power status of the socket */
reg = indirect_read(socket, I365_POWER);
if (reg & I365_PWR_AUTO)
@@ -302,10 +341,7 @@ static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
state->Vpp = 120;
}
- /*
- * Now the IO card, RESET flags and IO interrupt
- * IGENC, Interrupt and General Control
- */
+ /* Now the IO card, RESET flags and IO interrupt */
reg = indirect_read(socket, I365_INTCTL);
if ((reg & I365_PC_RESET) == 0)
@@ -314,12 +350,9 @@ static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
state->flags |= SS_IOCARD; /* This is an IO card */
/* Set the IRQ number */
- state->io_irq = socket->socket.pci_irq;
+ state->io_irq = socket->card_irq;
- /*
- * Card status change
- * CSCICR, Card Status Change Interrupt Configuration
- */
+ /* Card status change */
reg = indirect_read(socket, I365_CSCINT);
if (reg & I365_CSC_DETECT)
@@ -342,21 +375,23 @@ static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
- struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
- unsigned char reg;
+ struct pd6729_socket *socket
+ = container_of(sock, struct pd6729_socket, socket);
+ unsigned char reg, data;
/* First, set the global controller options */
-
- set_bridge_state(socket);
+ indirect_write(socket, I365_GBLCTL, 0x00);
+ indirect_write(socket, I365_GENCTL, 0x00);
/* Values for the IGENC register */
+ socket->card_irq = state->io_irq;
reg = 0;
/* The reset bit has "inverse" logic */
if (!(state->flags & SS_RESET))
- reg = reg | I365_PC_RESET;
+ reg |= I365_PC_RESET;
if (state->flags & SS_IOCARD)
- reg = reg | I365_PC_IOCARD;
+ reg |= I365_PC_IOCARD;
/* IGENC, Interrupt and General Control Register */
indirect_write(socket, I365_INTCTL, reg);
@@ -390,7 +425,8 @@ static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
indirect_resetbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
break;
default:
- dprintk("pd6729: pd6729_set_socket called with invalid VCC power value: %i\n",
+ dprintk("pd6729: pd6729_set_socket called with "
+ "invalid VCC power value: %i\n",
state->Vcc);
return -EINVAL;
}
@@ -418,9 +454,14 @@ static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
if (reg != indirect_read(socket, I365_POWER))
indirect_write(socket, I365_POWER, reg);
- /* Now, specifiy that all interrupts are to be done as PCI interrupts */
+ if (irq_mode == 1) {
+ /* all interrupts are to be done as PCI interrupts */
+ data = PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ;
+ } else
+ data = 0;
+
indirect_write(socket, PD67_EXT_INDEX, PD67_EXT_CTL_1);
- indirect_write(socket, PD67_EXT_DATA, PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ);
+ indirect_write(socket, PD67_EXT_DATA, data);
/* Enable specific interrupt events */
@@ -439,11 +480,15 @@ static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
if (state->csc_mask & SS_READY)
reg |= I365_CSC_READY;
}
- reg |= 0x30; /* management IRQ: PCI INTA# = "irq 3" */
+ if (irq_mode == 1)
+ reg |= 0x30; /* management IRQ: PCI INTA# = "irq 3" */
indirect_write(socket, I365_CSCINT, reg);
reg = indirect_read(socket, I365_INTCTL);
- reg |= 0x03; /* card IRQ: PCI INTA# = "irq 3" */
+ if (irq_mode == 1)
+ reg |= 0x03; /* card IRQ: PCI INTA# = "irq 3" */
+ else
+ reg |= socket->card_irq;
indirect_write(socket, I365_INTCTL, reg);
/* now clear the (probably bogus) pending stuff by doing a dummy read */
@@ -452,9 +497,11 @@ static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
return 0;
}
-static int pd6729_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
+static int pd6729_set_io_map(struct pcmcia_socket *sock,
+ struct pccard_io_map *io)
{
- struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
+ struct pd6729_socket *socket
+ = container_of(sock, struct pd6729_socket, socket);
unsigned char map, ioctl;
map = io->map;
@@ -469,7 +516,8 @@ static int pd6729_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *i
if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_IO(map))
indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_IO(map));
-/* dprintk("set_io_map: Setting range to %x - %x\n", io->start, io->stop);*/
+ /* dprintk("set_io_map: Setting range to %x - %x\n",
+ io->start, io->stop);*/
/* write the new values */
indirect_write16(socket, I365_IO(map)+I365_W_START, io->start);
@@ -490,9 +538,11 @@ static int pd6729_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *i
return 0;
}
-static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
+static int pd6729_set_mem_map(struct pcmcia_socket *sock,
+ struct pccard_mem_map *mem)
{
- struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
+ struct pd6729_socket *socket
+ = container_of(sock, struct pd6729_socket, socket);
unsigned short base, i;
unsigned char map;
@@ -504,8 +554,6 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
if ((mem->res->start > mem->res->end) || (mem->speed > 1000)) {
printk("pd6729_set_mem_map: invalid address / speed");
- /* printk("invalid mem map for socket %i : %lx to %lx with a start of %x\n",
- sock, mem->res->start, mem->res->end, mem->card_start); */
return -EINVAL;
}
@@ -551,11 +599,11 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
if (mem->flags & MAP_WRPROT)
i |= I365_MEM_WRPROT;
if (mem->flags & MAP_ATTRIB) {
-/* dprintk("requesting attribute memory for socket %i\n",
+ /* dprintk("requesting attribute memory for socket %i\n",
socket->number);*/
i |= I365_MEM_REG;
} else {
-/* dprintk("requesting normal memory for socket %i\n",
+ /* dprintk("requesting normal memory for socket %i\n",
socket->number);*/
}
indirect_write16(socket, base + I365_W_OFF, i);
@@ -604,13 +652,66 @@ static struct pccard_operations pd6729_operations = {
.set_mem_map = pd6729_set_mem_map,
};
-static int __devinit pd6729_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static irqreturn_t pd6729_test(int irq, void *dev, struct pt_regs *regs)
+{
+ dprintk("-> hit on irq %d\n", irq);
+ return IRQ_HANDLED;
+}
+
+static int pd6729_check_irq(int irq, int flags)
+{
+ if (request_irq(irq, pd6729_test, flags, "x", pd6729_test) != 0)
+ return -1;
+ free_irq(irq, pd6729_test);
+ return 0;
+}
+
+static u_int __init pd6729_isa_scan(void)
+{
+ u_int mask0, mask = 0;
+ int i;
+
+ if (irq_mode == 1) {
+ printk(KERN_INFO "pd6729: PCI card interrupts, "
+ "PCI status changes\n");
+ return 0;
+ }
+
+ if (irq_list_count == 0)
+ mask0 = 0xffff;
+ else
+ for (i = mask0 = 0; i < irq_list_count; i++)
+ mask0 |= (1<<irq_list[i]);
+
+ mask0 &= PD67_MASK;
+
+ /* just find interrupts that aren't in use */
+ for (i = 0; i < 16; i++)
+ if ((mask0 & (1 << i)) && (pd6729_check_irq(i, 0) == 0))
+ mask |= (1 << i);
+
+ printk(KERN_INFO "pd6729: ISA irqs = ");
+ for (i = 0; i < 16; i++)
+ if (mask & (1<<i))
+ printk("%s%d", ((mask & ((1<<i)-1)) ? "," : ""), i);
+
+ if (mask == 0) printk("none!");
+
+ printk(" polling status changes.\n");
+
+ return mask;
+}
+
+static int __devinit pd6729_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
{
int i, j, ret;
+ u_int mask;
char configbyte;
struct pd6729_socket *socket;
- socket = kmalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS, GFP_KERNEL);
+ socket = kmalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS,
+ GFP_KERNEL);
if (!socket)
return -ENOMEM;
@@ -619,13 +720,11 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev, const struct pci_devi
if ((ret = pci_enable_device(dev)))
goto err_out_free_mem;
- printk(KERN_INFO "pd6729: Cirrus PD6729 PCI to PCMCIA Bridge at 0x%lx on irq %d\n",
- pci_resource_start(dev, 0), dev->irq);
- printk(KERN_INFO "pd6729: configured as a %d socket device.\n", MAX_SOCKETS);
+ printk(KERN_INFO "pd6729: Cirrus PD6729 PCI to PCMCIA Bridge "
+ "at 0x%lx on irq %d\n", pci_resource_start(dev, 0), dev->irq);
/*
- * Since we have no memory BARs some firmware we may not
- * have had PCI_COMMAND_MEM enabled, yet the device needs
- * it.
+ * Since we have no memory BARs some firmware may not
+ * have had PCI_COMMAND_MEMORY enabled, yet the device needs it.
*/
pci_read_config_byte(dev, PCI_COMMAND, &configbyte);
if (!(configbyte & PCI_COMMAND_MEMORY)) {
@@ -640,33 +739,54 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev, const struct pci_devi
goto err_out_disable;
}
+ if (dev->irq == NO_IRQ)
+ irq_mode = 0; /* fall back to ISA interrupt mode */
+
+ mask = pd6729_isa_scan();
+ if (irq_mode == 0 && mask == 0) {
+ printk(KERN_INFO "pd6729: no ISA interrupt is available.\n");
+ goto err_out_free_res;
+ }
+
for (i = 0; i < MAX_SOCKETS; i++) {
socket[i].io_base = pci_resource_start(dev, 0);
socket[i].socket.features |= SS_CAP_PCCARD;
socket[i].socket.map_size = 0x1000;
- socket[i].socket.irq_mask = 0;
+ socket[i].socket.irq_mask = mask;
socket[i].socket.pci_irq = dev->irq;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i;
socket[i].socket.ops = &pd6729_operations;
+ socket[i].socket.resource_ops = &pccard_nonstatic_ops;
socket[i].socket.dev.dev = &dev->dev;
socket[i].socket.driver_data = &socket[i];
}
pci_set_drvdata(dev, socket);
-
- /* Register the interrupt handler */
- if ((ret = request_irq(dev->irq, pd6729_interrupt, SA_SHIRQ, "pd6729", socket))) {
- printk(KERN_ERR "pd6729: Failed to register irq %d, aborting\n", dev->irq);
- goto err_out_free_res;
+ if (irq_mode == 1) {
+ /* Register the interrupt handler */
+ if ((ret = request_irq(dev->irq, pd6729_interrupt, SA_SHIRQ,
+ "pd6729", socket))) {
+ printk(KERN_ERR "pd6729: Failed to register irq %d, "
+ "aborting\n", dev->irq);
+ goto err_out_free_res;
+ }
+ } else {
+ /* poll Card status change */
+ init_timer(&socket->poll_timer);
+ socket->poll_timer.function = pd6729_interrupt_wrapper;
+ socket->poll_timer.data = (unsigned long)socket;
+ socket->poll_timer.expires = jiffies + HZ;
+ add_timer(&socket->poll_timer);
}
for (i = 0; i < MAX_SOCKETS; i++) {
ret = pcmcia_register_socket(&socket[i].socket);
if (ret) {
- printk(KERN_INFO "pd6729: pcmcia_register_socket failed.\n");
+ printk(KERN_INFO "pd6729: pcmcia_register_socket "
+ "failed.\n");
for (j = 0; j < i ; j++)
pcmcia_unregister_socket(&socket[j].socket);
goto err_out_free_res2;
@@ -676,7 +796,10 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev, const struct pci_devi
return 0;
err_out_free_res2:
- free_irq(dev->irq, socket);
+ if (irq_mode == 1)
+ free_irq(dev->irq, socket);
+ else
+ del_timer_sync(&socket->poll_timer);
err_out_free_res:
pci_release_regions(dev);
err_out_disable:
@@ -692,10 +815,18 @@ static void __devexit pd6729_pci_remove(struct pci_dev *dev)
int i;
struct pd6729_socket *socket = pci_get_drvdata(dev);
- for (i = 0; i < MAX_SOCKETS; i++)
+ for (i = 0; i < MAX_SOCKETS; i++) {
+ /* Turn off all interrupt sources */
+ indirect_write(&socket[i], I365_CSCINT, 0);
+ indirect_write(&socket[i], I365_INTCTL, 0);
+
pcmcia_unregister_socket(&socket[i].socket);
+ }
- free_irq(dev->irq, socket);
+ if (irq_mode == 1)
+ free_irq(dev->irq, socket);
+ else
+ del_timer_sync(&socket->poll_timer);
pci_release_regions(dev);
pci_disable_device(dev);
diff --git a/drivers/pcmcia/pd6729.h b/drivers/pcmcia/pd6729.h
index 9e90520ef6cc..f392e458cdfd 100644
--- a/drivers/pcmcia/pd6729.h
+++ b/drivers/pcmcia/pd6729.h
@@ -16,13 +16,15 @@
#define PD67_EXD_VS1(s) (0x01 << ((s) << 1))
#define PD67_EXD_VS2(s) (0x02 << ((s) << 1))
-
-
+/* Default ISA interrupt mask */
+#define PD67_MASK 0x0eb8 /* irq 11,10,9,7,5,4,3 */
struct pd6729_socket {
int number;
+ int card_irq;
unsigned long io_base; /* base io address of the socket */
struct pcmcia_socket socket;
+ struct timer_list poll_timer;
};
#endif
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 4e0ca166dade..b3f1fe0b02ca 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -1,35 +1,16 @@
-/*======================================================================
-
- Resource management routines
-
- rsrc_mgr.c 1.79 2000/08/30 20:23:58
-
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The initial developer of the original code is David A. Hinds
- <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
-
- Alternatively, the contents of this file may be used under the
- terms of the GNU General Public License version 2 (the "GPL"), in which
- case the provisions of the GPL are applicable instead of the
- above. If you wish to allow the use of your version of this file
- only under the terms of the GPL and not to allow others to use
- your version of this file under the MPL, indicate your decision
- by deleting the provisions above and replace them with the notice
- 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.
-
-======================================================================*/
+/*
+ * rsrc_mgr.c -- Resource management routines
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ */
#include <linux/config.h>
#include <linux/module.h>
@@ -53,44 +34,7 @@
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
-/*====================================================================*/
-
-/* Parameters that can be set with 'insmod' */
-
-#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
-
-INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
-#ifdef CONFIG_PCMCIA_PROBE
-INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
-INT_MODULE_PARM(mem_limit, 0x10000);
-#endif
-
-/*======================================================================
-
- The resource_map_t structures are used to track what resources are
- available for allocation for PC Card devices.
-
-======================================================================*/
-
-typedef struct resource_map_t {
- u_long base, num;
- struct resource_map_t *next;
-} resource_map_t;
-
-/* Memory resource database */
-static resource_map_t mem_db = {
- .next = &mem_db,
-};
-
-/* IO port resource database */
-static resource_map_t io_db = {
- .next = &io_db,
-};
-
static DECLARE_MUTEX(rsrc_sem);
-static unsigned int rsrc_mem_probe;
-#define MEM_PROBE_LOW (1 << 0)
-#define MEM_PROBE_HIGH (1 << 1)
#ifdef CONFIG_PCMCIA_PROBE
@@ -105,617 +49,6 @@ static irq_info_t irq_table[NR_IRQS];
#endif
-/*======================================================================
-
- Linux resource management extensions
-
-======================================================================*/
-
-static struct resource *
-make_resource(unsigned long b, unsigned long n, int flags, char *name)
-{
- struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
-
- if (res) {
- memset(res, 0, sizeof(*res));
- res->name = name;
- res->start = b;
- res->end = b + n - 1;
- res->flags = flags;
- }
- return res;
-}
-
-static struct resource *
-claim_region(struct pcmcia_socket *s, unsigned long base, unsigned long size,
- int type, char *name)
-{
- struct resource *res, *parent;
-
- parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
- res = make_resource(base, size, type | IORESOURCE_BUSY, name);
-
- if (res) {
-#ifdef CONFIG_PCI
- if (s && s->cb_dev)
- parent = pci_find_parent_resource(s->cb_dev, res);
-#endif
- if (!parent || request_resource(parent, res)) {
- kfree(res);
- res = NULL;
- }
- }
- return res;
-}
-
-static void free_region(struct resource *res)
-{
- if (res) {
- release_resource(res);
- kfree(res);
- }
-}
-
-/*======================================================================
-
- These manage the internal databases of available resources.
-
-======================================================================*/
-
-static int add_interval(resource_map_t *map, u_long base, u_long num)
-{
- resource_map_t *p, *q;
-
- for (p = map; ; p = p->next) {
- if ((p != map) && (p->base+p->num-1 >= base))
- return -1;
- if ((p->next == map) || (p->next->base > base+num-1))
- break;
- }
- q = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
- if (!q) return CS_OUT_OF_RESOURCE;
- q->base = base; q->num = num;
- q->next = p->next; p->next = q;
- return CS_SUCCESS;
-}
-
-/*====================================================================*/
-
-static int sub_interval(resource_map_t *map, u_long base, u_long num)
-{
- resource_map_t *p, *q;
-
- for (p = map; ; p = q) {
- q = p->next;
- if (q == map)
- break;
- if ((q->base+q->num > base) && (base+num > q->base)) {
- if (q->base >= base) {
- if (q->base+q->num <= base+num) {
- /* Delete whole block */
- p->next = q->next;
- kfree(q);
- /* don't advance the pointer yet */
- q = p;
- } else {
- /* Cut off bit from the front */
- q->num = q->base + q->num - base - num;
- q->base = base + num;
- }
- } else if (q->base+q->num <= base+num) {
- /* Cut off bit from the end */
- q->num = base - q->base;
- } else {
- /* Split the block into two pieces */
- p = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
- if (!p) return CS_OUT_OF_RESOURCE;
- p->base = base+num;
- p->num = q->base+q->num - p->base;
- q->num = base - q->base;
- p->next = q->next ; q->next = p;
- }
- }
- }
- return CS_SUCCESS;
-}
-
-/*======================================================================
-
- These routines examine a region of IO or memory addresses to
- determine what ranges might be genuinely available.
-
-======================================================================*/
-
-#ifdef CONFIG_PCMCIA_PROBE
-static void do_io_probe(ioaddr_t base, ioaddr_t num)
-{
- struct resource *res;
- ioaddr_t i, j, bad, any;
- u_char *b, hole, most;
-
- printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
- base, base+num-1);
-
- /* First, what does a floating port look like? */
- b = kmalloc(256, GFP_KERNEL);
- if (!b) {
- printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
- return;
- }
- memset(b, 0, 256);
- for (i = base, most = 0; i < base+num; i += 8) {
- res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
- if (!res)
- continue;
- hole = inb(i);
- for (j = 1; j < 8; j++)
- if (inb(i+j) != hole) break;
- free_region(res);
- if ((j == 8) && (++b[hole] > b[most]))
- most = hole;
- if (b[most] == 127) break;
- }
- kfree(b);
-
- bad = any = 0;
- for (i = base; i < base+num; i += 8) {
- res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
- if (!res)
- continue;
- for (j = 0; j < 8; j++)
- if (inb(i+j) != most) break;
- free_region(res);
- if (j < 8) {
- if (!any)
- printk(" excluding");
- if (!bad)
- bad = any = i;
- } else {
- if (bad) {
- sub_interval(&io_db, bad, i-bad);
- printk(" %#04x-%#04x", bad, i-1);
- bad = 0;
- }
- }
- }
- if (bad) {
- if ((num > 16) && (bad == base) && (i == base+num)) {
- printk(" nothing: probe failed.\n");
- return;
- } else {
- sub_interval(&io_db, bad, i-bad);
- printk(" %#04x-%#04x", bad, i-1);
- }
- }
-
- printk(any ? "\n" : " clean.\n");
-}
-#endif
-
-/*======================================================================
-
- This is tricky... when we set up CIS memory, we try to validate
- the memory window space allocations.
-
-======================================================================*/
-
-/* Validation function for cards with a valid CIS */
-static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *info)
-{
- int ret = -1;
-
- s->cis_mem.res = res;
- s->cis_virt = ioremap(res->start, s->map_size);
- if (s->cis_virt) {
- ret = pccard_validate_cis(s, BIND_FN_ALL, info);
- /* invalidate mapping and CIS cache */
- iounmap(s->cis_virt);
- s->cis_virt = NULL;
- destroy_cis_cache(s);
- }
- s->cis_mem.res = NULL;
- if ((ret != 0) || (info->Chains == 0))
- return 0;
- return 1;
-}
-
-/* Validation function for simple memory cards */
-static int checksum(struct pcmcia_socket *s, struct resource *res)
-{
- pccard_mem_map map;
- int i, a = 0, b = -1, d;
- void __iomem *virt;
-
- virt = ioremap(res->start, s->map_size);
- if (virt) {
- map.map = 0;
- map.flags = MAP_ACTIVE;
- map.speed = 0;
- map.res = res;
- map.card_start = 0;
- s->ops->set_mem_map(s, &map);
-
- /* Don't bother checking every word... */
- for (i = 0; i < s->map_size; i += 44) {
- d = readl(virt+i);
- a += d;
- b &= d;
- }
-
- map.flags = 0;
- s->ops->set_mem_map(s, &map);
-
- iounmap(virt);
- }
-
- return (b == -1) ? -1 : (a>>1);
-}
-
-static int
-cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
-{
- struct resource *res1, *res2;
- cisinfo_t info1, info2;
- int ret = 0;
-
- res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
- res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
-
- if (res1 && res2) {
- ret = readable(s, res1, &info1);
- ret += readable(s, res2, &info2);
- }
-
- free_region(res2);
- free_region(res1);
-
- return (ret == 2) && (info1.Chains == info2.Chains);
-}
-
-static int
-checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
-{
- struct resource *res1, *res2;
- int a = -1, b = -1;
-
- res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
- res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
-
- if (res1 && res2) {
- a = checksum(s, res1);
- b = checksum(s, res2);
- }
-
- free_region(res2);
- free_region(res1);
-
- return (a == b) && (a >= 0);
-}
-
-/*======================================================================
-
- The memory probe. If the memory list includes a 64K-aligned block
- below 1MB, we probe in 64K chunks, and as soon as we accumulate at
- least mem_limit free space, we quit.
-
-======================================================================*/
-
-static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
-{
- u_long i, j, bad, fail, step;
-
- printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
- base, base+num-1);
- bad = fail = 0;
- step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
- /* cis_readable wants to map 2x map_size */
- if (step < 2 * s->map_size)
- step = 2 * s->map_size;
- for (i = j = base; i < base+num; i = j + step) {
- if (!fail) {
- for (j = i; j < base+num; j += step) {
- if (cis_readable(s, j, step))
- break;
- }
- fail = ((i == base) && (j == base+num));
- }
- if (fail) {
- for (j = i; j < base+num; j += 2*step)
- if (checksum_match(s, j, step) &&
- checksum_match(s, j + step, step))
- break;
- }
- if (i != j) {
- if (!bad) printk(" excluding");
- printk(" %#05lx-%#05lx", i, j-1);
- sub_interval(&mem_db, i, j-i);
- bad += j-i;
- }
- }
- printk(bad ? "\n" : " clean.\n");
- return (num - bad);
-}
-
-#ifdef CONFIG_PCMCIA_PROBE
-
-static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
-{
- u_long ok;
- if (m == &mem_db)
- return 0;
- ok = inv_probe(m->next, s);
- if (ok) {
- if (m->base >= 0x100000)
- sub_interval(&mem_db, m->base, m->num);
- return ok;
- }
- if (m->base < 0x100000)
- return 0;
- return do_mem_probe(m->base, m->num, s);
-}
-
-static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
-{
- resource_map_t *m, mm;
- static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
- u_long b, i, ok = 0;
-
- /* We do up to four passes through the list */
- if (probe_mask & MEM_PROBE_HIGH) {
- if (inv_probe(mem_db.next, s) > 0)
- return;
- printk(KERN_NOTICE "cs: warning: no high memory space "
- "available!\n");
- }
- if ((probe_mask & MEM_PROBE_LOW) == 0)
- return;
- for (m = mem_db.next; m != &mem_db; m = mm.next) {
- mm = *m;
- /* Only probe < 1 MB */
- if (mm.base >= 0x100000) continue;
- if ((mm.base | mm.num) & 0xffff) {
- ok += do_mem_probe(mm.base, mm.num, s);
- continue;
- }
- /* Special probe for 64K-aligned block */
- for (i = 0; i < 4; i++) {
- b = order[i] << 12;
- if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
- if (ok >= mem_limit)
- sub_interval(&mem_db, b, 0x10000);
- else
- ok += do_mem_probe(b, 0x10000, s);
- }
- }
- }
-}
-
-#else /* CONFIG_PCMCIA_PROBE */
-
-static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
-{
- resource_map_t *m, mm;
-
- for (m = mem_db.next; m != &mem_db; m = mm.next) {
- mm = *m;
- if (do_mem_probe(mm.base, mm.num, s))
- break;
- }
-}
-
-#endif /* CONFIG_PCMCIA_PROBE */
-
-/*
- * Locking note: this is the only place where we take
- * both rsrc_sem and skt_sem.
- */
-void pcmcia_validate_mem(struct pcmcia_socket *s)
-{
- if (probe_mem) {
- unsigned int probe_mask;
-
- down(&rsrc_sem);
-
- probe_mask = MEM_PROBE_LOW;
- if (s->features & SS_CAP_PAGE_REGS)
- probe_mask = MEM_PROBE_HIGH;
-
- if (probe_mask & ~rsrc_mem_probe) {
- rsrc_mem_probe |= probe_mask;
-
- down(&s->skt_sem);
-
- if (s->state & SOCKET_PRESENT)
- validate_mem(s, probe_mask);
-
- up(&s->skt_sem);
- }
-
- up(&rsrc_sem);
- }
-}
-
-EXPORT_SYMBOL(pcmcia_validate_mem);
-
-struct pcmcia_align_data {
- unsigned long mask;
- unsigned long offset;
- resource_map_t *map;
-};
-
-static void
-pcmcia_common_align(void *align_data, struct resource *res,
- unsigned long size, unsigned long align)
-{
- struct pcmcia_align_data *data = align_data;
- unsigned long start;
- /*
- * Ensure that we have the correct start address
- */
- start = (res->start & ~data->mask) + data->offset;
- if (start < res->start)
- start += data->mask + 1;
- res->start = start;
-}
-
-static void
-pcmcia_align(void *align_data, struct resource *res,
- unsigned long size, unsigned long align)
-{
- struct pcmcia_align_data *data = align_data;
- resource_map_t *m;
-
- pcmcia_common_align(data, res, size, align);
-
- for (m = data->map->next; m != data->map; m = m->next) {
- unsigned long start = m->base;
- unsigned long end = m->base + m->num - 1;
-
- /*
- * If the lower resources are not available, try aligning
- * to this entry of the resource database to see if it'll
- * fit here.
- */
- if (res->start < start) {
- res->start = start;
- pcmcia_common_align(data, res, size, align);
- }
-
- /*
- * If we're above the area which was passed in, there's
- * no point proceeding.
- */
- if (res->start >= res->end)
- break;
-
- if ((res->start + size - 1) <= end)
- break;
- }
-
- /*
- * If we failed to find something suitable, ensure we fail.
- */
- if (m == data->map)
- res->start = res->end;
-}
-
-/*
- * Adjust an existing IO region allocation, but making sure that we don't
- * encroach outside the resources which the user supplied.
- */
-int adjust_io_region(struct resource *res, unsigned long r_start,
- unsigned long r_end, struct pcmcia_socket *s)
-{
- resource_map_t *m;
- int ret = -ENOMEM;
-
- down(&rsrc_sem);
- for (m = io_db.next; m != &io_db; m = m->next) {
- unsigned long start = m->base;
- unsigned long end = m->base + m->num - 1;
-
- if (start > r_start || r_end > end)
- continue;
-
- ret = adjust_resource(res, r_start, r_end - r_start + 1);
- break;
- }
- up(&rsrc_sem);
-
- return ret;
-}
-
-/*======================================================================
-
- These find ranges of I/O ports or memory addresses that are not
- currently allocated by other devices.
-
- The 'align' field should reflect the number of bits of address
- that need to be preserved from the initial value of *base. It
- should be a power of two, greater than or equal to 'num'. A value
- of 0 means that all bits of *base are significant. *base should
- also be strictly less than 'align'.
-
-======================================================================*/
-
-struct resource *find_io_region(unsigned long base, int num,
- unsigned long align, char *name, struct pcmcia_socket *s)
-{
- struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id);
- struct pcmcia_align_data data;
- unsigned long min = base;
- int ret;
-
- if (align == 0)
- align = 0x10000;
-
- data.mask = align - 1;
- data.offset = base & data.mask;
- data.map = &io_db;
-
- down(&rsrc_sem);
-#ifdef CONFIG_PCI
- if (s->cb_dev) {
- ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
- min, 0, pcmcia_align, &data);
- } else
-#endif
- ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
- 1, pcmcia_align, &data);
- up(&rsrc_sem);
-
- if (ret != 0) {
- kfree(res);
- res = NULL;
- }
- return res;
-}
-
-struct resource *find_mem_region(u_long base, u_long num, u_long align,
- int low, char *name, struct pcmcia_socket *s)
-{
- struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id);
- struct pcmcia_align_data data;
- unsigned long min, max;
- int ret, i;
-
- low = low || !(s->features & SS_CAP_PAGE_REGS);
-
- data.mask = align - 1;
- data.offset = base & data.mask;
- data.map = &mem_db;
-
- for (i = 0; i < 2; i++) {
- if (low) {
- max = 0x100000UL;
- min = base < max ? base : 0;
- } else {
- max = ~0UL;
- min = 0x100000UL + base;
- }
-
- down(&rsrc_sem);
-#ifdef CONFIG_PCI
- if (s->cb_dev) {
- ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
- 1, min, 0,
- pcmcia_align, &data);
- } else
-#endif
- ret = allocate_resource(&iomem_resource, res, num, min,
- max, 1, pcmcia_align, &data);
- up(&rsrc_sem);
- if (ret == 0 || low)
- break;
- low = 1;
- }
-
- if (ret != 0) {
- kfree(res);
- res = NULL;
- }
- return res;
-}
/*======================================================================
@@ -842,85 +175,6 @@ void undo_irq(u_int Attributes, int irq)
#endif
-/*======================================================================
-
- The various adjust_* calls form the external interface to the
- resource database.
-
-======================================================================*/
-
-static int adjust_memory(adjust_t *adj)
-{
- u_long base, num;
- int ret;
-
- base = adj->resource.memory.Base;
- num = adj->resource.memory.Size;
- if ((num == 0) || (base+num-1 < base))
- return CS_BAD_SIZE;
-
- ret = CS_SUCCESS;
-
- down(&rsrc_sem);
- switch (adj->Action) {
- case ADD_MANAGED_RESOURCE:
- ret = add_interval(&mem_db, base, num);
- break;
- case REMOVE_MANAGED_RESOURCE:
- ret = sub_interval(&mem_db, base, num);
- if (ret == CS_SUCCESS) {
- struct pcmcia_socket *socket;
- down_read(&pcmcia_socket_list_rwsem);
- list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
- release_cis_mem(socket);
- up_read(&pcmcia_socket_list_rwsem);
- }
- break;
- default:
- ret = CS_UNSUPPORTED_FUNCTION;
- }
- up(&rsrc_sem);
-
- return ret;
-}
-
-/*====================================================================*/
-
-static int adjust_io(adjust_t *adj)
-{
- int base, num, ret = CS_SUCCESS;
-
- base = adj->resource.io.BasePort;
- num = adj->resource.io.NumPorts;
- if ((base < 0) || (base > 0xffff))
- return CS_BAD_BASE;
- if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
- return CS_BAD_SIZE;
-
- down(&rsrc_sem);
- switch (adj->Action) {
- case ADD_MANAGED_RESOURCE:
- if (add_interval(&io_db, base, num) != 0) {
- ret = CS_IN_USE;
- break;
- }
-#ifdef CONFIG_PCMCIA_PROBE
- if (probe_io)
- do_io_probe(base, num);
-#endif
- break;
- case REMOVE_MANAGED_RESOURCE:
- sub_interval(&io_db, base, num);
- break;
- default:
- ret = CS_UNSUPPORTED_FUNCTION;
- break;
- }
- up(&rsrc_sem);
-
- return ret;
-}
-
/*====================================================================*/
static int adjust_irq(adjust_t *adj)
@@ -971,37 +225,69 @@ static int adjust_irq(adjust_t *adj)
return ret;
}
-/*====================================================================*/
-
int pcmcia_adjust_resource_info(adjust_t *adj)
{
- switch (adj->Resource) {
- case RES_MEMORY_RANGE:
- return adjust_memory(adj);
- break;
- case RES_IO_RANGE:
- return adjust_io(adj);
- break;
- case RES_IRQ:
- return adjust_irq(adj);
- break;
- }
- return CS_UNSUPPORTED_FUNCTION;
+ struct pcmcia_socket *s;
+ int ret = CS_UNSUPPORTED_FUNCTION;
+
+ if (adj->Resource == RES_IRQ)
+ return adjust_irq(adj);
+
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
+ if (s->resource_ops->adjust_resource)
+ ret = s->resource_ops->adjust_resource(s, adj);
+ }
+ up_read(&pcmcia_socket_list_rwsem);
+
+ return (ret);
}
EXPORT_SYMBOL(pcmcia_adjust_resource_info);
-/*====================================================================*/
+void pcmcia_validate_mem(struct pcmcia_socket *s)
+{
+ if (s->resource_ops->validate_mem)
+ s->resource_ops->validate_mem(s);
+}
+EXPORT_SYMBOL(pcmcia_validate_mem);
+
+int adjust_io_region(struct resource *res, unsigned long r_start,
+ unsigned long r_end, struct pcmcia_socket *s)
+{
+ if (s->resource_ops->adjust_io_region)
+ return s->resource_ops->adjust_io_region(res, r_start, r_end, s);
+ return -ENOMEM;
+}
-void release_resource_db(void)
+struct resource *find_io_region(unsigned long base, int num,
+ unsigned long align, struct pcmcia_socket *s)
{
- resource_map_t *p, *q;
-
- for (p = mem_db.next; p != &mem_db; p = q) {
- q = p->next;
- kfree(p);
- }
- for (p = io_db.next; p != &io_db; p = q) {
- q = p->next;
- kfree(p);
- }
+ if (s->resource_ops->find_io)
+ return s->resource_ops->find_io(base, num, align, s);
+ return NULL;
+}
+
+struct resource *find_mem_region(u_long base, u_long num, u_long align,
+ int low, struct pcmcia_socket *s)
+{
+ if (s->resource_ops->find_mem)
+ return s->resource_ops->find_mem(base, num, align, low, s);
+ return NULL;
}
+
+void release_resource_db(struct pcmcia_socket *s)
+{
+ if (s->resource_ops->exit)
+ s->resource_ops->exit(s);
+}
+
+
+struct pccard_resource_ops pccard_static_ops = {
+ .validate_mem = NULL,
+ .adjust_io_region = NULL,
+ .find_io = NULL,
+ .find_mem = NULL,
+ .adjust_resource = NULL,
+ .exit = NULL,
+};
+EXPORT_SYMBOL(pccard_static_ops);
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
new file mode 100644
index 000000000000..cbc3440d161c
--- /dev/null
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -0,0 +1,816 @@
+/*
+ * rsrc_nonstatic.c -- Resource management routines for !SS_CAP_STATIC_MAP sockets
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * (C) 1999 David A. Hinds
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cistpl.h>
+#include "cs_internal.h"
+
+MODULE_AUTHOR("David A. Hinds, Dominik Brodowski");
+MODULE_LICENSE("GPL");
+
+/* Parameters that can be set with 'insmod' */
+
+#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
+
+INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
+#ifdef CONFIG_PCMCIA_PROBE
+INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
+INT_MODULE_PARM(mem_limit, 0x10000);
+#endif
+
+/* for io_db and mem_db */
+struct resource_map {
+ u_long base, num;
+ struct resource_map *next;
+};
+
+struct socket_data {
+ struct resource_map mem_db;
+ struct resource_map io_db;
+ unsigned int rsrc_mem_probe;
+};
+
+static DECLARE_MUTEX(rsrc_sem);
+#define MEM_PROBE_LOW (1 << 0)
+#define MEM_PROBE_HIGH (1 << 1)
+
+
+/*======================================================================
+
+ Linux resource management extensions
+
+======================================================================*/
+
+static struct resource *
+make_resource(unsigned long b, unsigned long n, int flags, char *name)
+{
+ struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
+
+ if (res) {
+ memset(res, 0, sizeof(*res));
+ res->name = name;
+ res->start = b;
+ res->end = b + n - 1;
+ res->flags = flags;
+ }
+ return res;
+}
+
+static struct resource *
+claim_region(struct pcmcia_socket *s, unsigned long base, unsigned long size,
+ int type, char *name)
+{
+ struct resource *res, *parent;
+
+ parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
+ res = make_resource(base, size, type | IORESOURCE_BUSY, name);
+
+ if (res) {
+#ifdef CONFIG_PCI
+ if (s && s->cb_dev)
+ parent = pci_find_parent_resource(s->cb_dev, res);
+#endif
+ if (!parent || request_resource(parent, res)) {
+ kfree(res);
+ res = NULL;
+ }
+ }
+ return res;
+}
+
+static void free_region(struct resource *res)
+{
+ if (res) {
+ release_resource(res);
+ kfree(res);
+ }
+}
+
+/*======================================================================
+
+ These manage the internal databases of available resources.
+
+======================================================================*/
+
+static int add_interval(struct resource_map *map, u_long base, u_long num)
+{
+ struct resource_map *p, *q;
+
+ for (p = map; ; p = p->next) {
+ if ((p != map) && (p->base+p->num-1 >= base))
+ return -1;
+ if ((p->next == map) || (p->next->base > base+num-1))
+ break;
+ }
+ q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
+ if (!q) return CS_OUT_OF_RESOURCE;
+ q->base = base; q->num = num;
+ q->next = p->next; p->next = q;
+ return CS_SUCCESS;
+}
+
+/*====================================================================*/
+
+static int sub_interval(struct resource_map *map, u_long base, u_long num)
+{
+ struct resource_map *p, *q;
+
+ for (p = map; ; p = q) {
+ q = p->next;
+ if (q == map)
+ break;
+ if ((q->base+q->num > base) && (base+num > q->base)) {
+ if (q->base >= base) {
+ if (q->base+q->num <= base+num) {
+ /* Delete whole block */
+ p->next = q->next;
+ kfree(q);
+ /* don't advance the pointer yet */
+ q = p;
+ } else {
+ /* Cut off bit from the front */
+ q->num = q->base + q->num - base - num;
+ q->base = base + num;
+ }
+ } else if (q->base+q->num <= base+num) {
+ /* Cut off bit from the end */
+ q->num = base - q->base;
+ } else {
+ /* Split the block into two pieces */
+ p = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
+ if (!p) return CS_OUT_OF_RESOURCE;
+ p->base = base+num;
+ p->num = q->base+q->num - p->base;
+ q->num = base - q->base;
+ p->next = q->next ; q->next = p;
+ }
+ }
+ }
+ return CS_SUCCESS;
+}
+
+/*======================================================================
+
+ These routines examine a region of IO or memory addresses to
+ determine what ranges might be genuinely available.
+
+======================================================================*/
+
+#ifdef CONFIG_PCMCIA_PROBE
+static void do_io_probe(struct pcmcia_socket *s, ioaddr_t base, ioaddr_t num)
+{
+ struct resource *res;
+ struct socket_data *s_data = s->resource_data;
+ ioaddr_t i, j, bad, any;
+ u_char *b, hole, most;
+
+ printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
+ base, base+num-1);
+
+ /* First, what does a floating port look like? */
+ b = kmalloc(256, GFP_KERNEL);
+ if (!b) {
+ printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
+ return;
+ }
+ memset(b, 0, 256);
+ for (i = base, most = 0; i < base+num; i += 8) {
+ res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
+ if (!res)
+ continue;
+ hole = inb(i);
+ for (j = 1; j < 8; j++)
+ if (inb(i+j) != hole) break;
+ free_region(res);
+ if ((j == 8) && (++b[hole] > b[most]))
+ most = hole;
+ if (b[most] == 127) break;
+ }
+ kfree(b);
+
+ bad = any = 0;
+ for (i = base; i < base+num; i += 8) {
+ res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
+ if (!res)
+ continue;
+ for (j = 0; j < 8; j++)
+ if (inb(i+j) != most) break;
+ free_region(res);
+ if (j < 8) {
+ if (!any)
+ printk(" excluding");
+ if (!bad)
+ bad = any = i;
+ } else {
+ if (bad) {
+ sub_interval(&s_data->io_db, bad, i-bad);
+ printk(" %#04x-%#04x", bad, i-1);
+ bad = 0;
+ }
+ }
+ }
+ if (bad) {
+ if ((num > 16) && (bad == base) && (i == base+num)) {
+ printk(" nothing: probe failed.\n");
+ return;
+ } else {
+ sub_interval(&s_data->io_db, bad, i-bad);
+ printk(" %#04x-%#04x", bad, i-1);
+ }
+ }
+
+ printk(any ? "\n" : " clean.\n");
+}
+#endif
+
+/*======================================================================
+
+ This is tricky... when we set up CIS memory, we try to validate
+ the memory window space allocations.
+
+======================================================================*/
+
+/* Validation function for cards with a valid CIS */
+static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *info)
+{
+ int ret = -1;
+
+ s->cis_mem.res = res;
+ s->cis_virt = ioremap(res->start, s->map_size);
+ if (s->cis_virt) {
+ ret = pccard_validate_cis(s, BIND_FN_ALL, info);
+ /* invalidate mapping and CIS cache */
+ iounmap(s->cis_virt);
+ s->cis_virt = NULL;
+ destroy_cis_cache(s);
+ }
+ s->cis_mem.res = NULL;
+ if ((ret != 0) || (info->Chains == 0))
+ return 0;
+ return 1;
+}
+
+/* Validation function for simple memory cards */
+static int checksum(struct pcmcia_socket *s, struct resource *res)
+{
+ pccard_mem_map map;
+ int i, a = 0, b = -1, d;
+ void __iomem *virt;
+
+ virt = ioremap(res->start, s->map_size);
+ if (virt) {
+ map.map = 0;
+ map.flags = MAP_ACTIVE;
+ map.speed = 0;
+ map.res = res;
+ map.card_start = 0;
+ s->ops->set_mem_map(s, &map);
+
+ /* Don't bother checking every word... */
+ for (i = 0; i < s->map_size; i += 44) {
+ d = readl(virt+i);
+ a += d;
+ b &= d;
+ }
+
+ map.flags = 0;
+ s->ops->set_mem_map(s, &map);
+
+ iounmap(virt);
+ }
+
+ return (b == -1) ? -1 : (a>>1);
+}
+
+static int
+cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
+{
+ struct resource *res1, *res2;
+ cisinfo_t info1, info2;
+ int ret = 0;
+
+ res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
+ res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
+
+ if (res1 && res2) {
+ ret = readable(s, res1, &info1);
+ ret += readable(s, res2, &info2);
+ }
+
+ free_region(res2);
+ free_region(res1);
+
+ return (ret == 2) && (info1.Chains == info2.Chains);
+}
+
+static int
+checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
+{
+ struct resource *res1, *res2;
+ int a = -1, b = -1;
+
+ res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
+ res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
+
+ if (res1 && res2) {
+ a = checksum(s, res1);
+ b = checksum(s, res2);
+ }
+
+ free_region(res2);
+ free_region(res1);
+
+ return (a == b) && (a >= 0);
+}
+
+/*======================================================================
+
+ The memory probe. If the memory list includes a 64K-aligned block
+ below 1MB, we probe in 64K chunks, and as soon as we accumulate at
+ least mem_limit free space, we quit.
+
+======================================================================*/
+
+static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
+{
+ struct socket_data *s_data = s->resource_data;
+ u_long i, j, bad, fail, step;
+
+ printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
+ base, base+num-1);
+ bad = fail = 0;
+ step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
+ /* cis_readable wants to map 2x map_size */
+ if (step < 2 * s->map_size)
+ step = 2 * s->map_size;
+ for (i = j = base; i < base+num; i = j + step) {
+ if (!fail) {
+ for (j = i; j < base+num; j += step) {
+ if (cis_readable(s, j, step))
+ break;
+ }
+ fail = ((i == base) && (j == base+num));
+ }
+ if (fail) {
+ for (j = i; j < base+num; j += 2*step)
+ if (checksum_match(s, j, step) &&
+ checksum_match(s, j + step, step))
+ break;
+ }
+ if (i != j) {
+ if (!bad) printk(" excluding");
+ printk(" %#05lx-%#05lx", i, j-1);
+ sub_interval(&s_data->mem_db, i, j-i);
+ bad += j-i;
+ }
+ }
+ printk(bad ? "\n" : " clean.\n");
+ return (num - bad);
+}
+
+#ifdef CONFIG_PCMCIA_PROBE
+
+static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
+{
+ struct socket_data *s_data = s->resource_data;
+ u_long ok;
+ if (m == &s_data->mem_db)
+ return 0;
+ ok = inv_probe(m->next, s);
+ if (ok) {
+ if (m->base >= 0x100000)
+ sub_interval(&s_data->mem_db, m->base, m->num);
+ return ok;
+ }
+ if (m->base < 0x100000)
+ return 0;
+ return do_mem_probe(m->base, m->num, s);
+}
+
+static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
+{
+ struct resource_map *m, mm;
+ static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
+ u_long b, i, ok = 0;
+ struct socket_data *s_data = s->resource_data;
+
+ /* We do up to four passes through the list */
+ if (probe_mask & MEM_PROBE_HIGH) {
+ if (inv_probe(s_data->mem_db.next, s) > 0)
+ return;
+ printk(KERN_NOTICE "cs: warning: no high memory space "
+ "available!\n");
+ }
+ if ((probe_mask & MEM_PROBE_LOW) == 0)
+ return;
+ for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
+ mm = *m;
+ /* Only probe < 1 MB */
+ if (mm.base >= 0x100000) continue;
+ if ((mm.base | mm.num) & 0xffff) {
+ ok += do_mem_probe(mm.base, mm.num, s);
+ continue;
+ }
+ /* Special probe for 64K-aligned block */
+ for (i = 0; i < 4; i++) {
+ b = order[i] << 12;
+ if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
+ if (ok >= mem_limit)
+ sub_interval(&s_data->mem_db, b, 0x10000);
+ else
+ ok += do_mem_probe(b, 0x10000, s);
+ }
+ }
+ }
+}
+
+#else /* CONFIG_PCMCIA_PROBE */
+
+static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
+{
+ struct resource_map *m, mm;
+ struct socket_data *s_data = s->resource_data;
+
+ for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
+ mm = *m;
+ if (do_mem_probe(mm.base, mm.num, s))
+ break;
+ }
+}
+
+#endif /* CONFIG_PCMCIA_PROBE */
+
+
+/*
+ * Locking note: this is the only place where we take
+ * both rsrc_sem and skt_sem.
+ */
+static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
+{
+ struct socket_data *s_data = s->resource_data;
+ if (probe_mem) {
+ unsigned int probe_mask;
+
+ down(&rsrc_sem);
+
+ probe_mask = MEM_PROBE_LOW;
+ if (s->features & SS_CAP_PAGE_REGS)
+ probe_mask = MEM_PROBE_HIGH;
+
+ if (probe_mask & ~s_data->rsrc_mem_probe) {
+ s_data->rsrc_mem_probe |= probe_mask;
+
+ down(&s->skt_sem);
+
+ if (s->state & SOCKET_PRESENT)
+ validate_mem(s, probe_mask);
+
+ up(&s->skt_sem);
+ }
+
+ up(&rsrc_sem);
+ }
+}
+
+struct pcmcia_align_data {
+ unsigned long mask;
+ unsigned long offset;
+ struct resource_map *map;
+};
+
+static void
+pcmcia_common_align(void *align_data, struct resource *res,
+ unsigned long size, unsigned long align)
+{
+ struct pcmcia_align_data *data = align_data;
+ unsigned long start;
+ /*
+ * Ensure that we have the correct start address
+ */
+ start = (res->start & ~data->mask) + data->offset;
+ if (start < res->start)
+ start += data->mask + 1;
+ res->start = start;
+}
+
+static void
+pcmcia_align(void *align_data, struct resource *res,
+ unsigned long size, unsigned long align)
+{
+ struct pcmcia_align_data *data = align_data;
+ struct resource_map *m;
+
+ pcmcia_common_align(data, res, size, align);
+
+ for (m = data->map->next; m != data->map; m = m->next) {
+ unsigned long start = m->base;
+ unsigned long end = m->base + m->num - 1;
+
+ /*
+ * If the lower resources are not available, try aligning
+ * to this entry of the resource database to see if it'll
+ * fit here.
+ */
+ if (res->start < start) {
+ res->start = start;
+ pcmcia_common_align(data, res, size, align);
+ }
+
+ /*
+ * If we're above the area which was passed in, there's
+ * no point proceeding.
+ */
+ if (res->start >= res->end)
+ break;
+
+ if ((res->start + size - 1) <= end)
+ break;
+ }
+
+ /*
+ * If we failed to find something suitable, ensure we fail.
+ */
+ if (m == data->map)
+ res->start = res->end;
+}
+
+/*
+ * Adjust an existing IO region allocation, but making sure that we don't
+ * encroach outside the resources which the user supplied.
+ */
+static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_start,
+ unsigned long r_end, struct pcmcia_socket *s)
+{
+ struct resource_map *m;
+ struct socket_data *s_data = s->resource_data;
+ int ret = -ENOMEM;
+
+ down(&rsrc_sem);
+ for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
+ unsigned long start = m->base;
+ unsigned long end = m->base + m->num - 1;
+
+ if (start > r_start || r_end > end)
+ continue;
+
+ ret = adjust_resource(res, r_start, r_end - r_start + 1);
+ break;
+ }
+ up(&rsrc_sem);
+
+ return ret;
+}
+
+/*======================================================================
+
+ These find ranges of I/O ports or memory addresses that are not
+ currently allocated by other devices.
+
+ The 'align' field should reflect the number of bits of address
+ that need to be preserved from the initial value of *base. It
+ should be a power of two, greater than or equal to 'num'. A value
+ of 0 means that all bits of *base are significant. *base should
+ also be strictly less than 'align'.
+
+======================================================================*/
+
+struct resource *nonstatic_find_io_region(unsigned long base, int num,
+ unsigned long align, struct pcmcia_socket *s)
+{
+ struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id);
+ struct socket_data *s_data = s->resource_data;
+ struct pcmcia_align_data data;
+ unsigned long min = base;
+ int ret;
+
+ if (align == 0)
+ align = 0x10000;
+
+ data.mask = align - 1;
+ data.offset = base & data.mask;
+ data.map = &s_data->io_db;
+
+ down(&rsrc_sem);
+#ifdef CONFIG_PCI
+ if (s->cb_dev) {
+ ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
+ min, 0, pcmcia_align, &data);
+ } else
+#endif
+ ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
+ 1, pcmcia_align, &data);
+ up(&rsrc_sem);
+
+ if (ret != 0) {
+ kfree(res);
+ res = NULL;
+ }
+ return res;
+}
+
+struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long align,
+ int low, struct pcmcia_socket *s)
+{
+ struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id);
+ struct socket_data *s_data = s->resource_data;
+ struct pcmcia_align_data data;
+ unsigned long min, max;
+ int ret, i;
+
+ low = low || !(s->features & SS_CAP_PAGE_REGS);
+
+ data.mask = align - 1;
+ data.offset = base & data.mask;
+ data.map = &s_data->mem_db;
+
+ for (i = 0; i < 2; i++) {
+ if (low) {
+ max = 0x100000UL;
+ min = base < max ? base : 0;
+ } else {
+ max = ~0UL;
+ min = 0x100000UL + base;
+ }
+
+ down(&rsrc_sem);
+#ifdef CONFIG_PCI
+ if (s->cb_dev) {
+ ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
+ 1, min, 0,
+ pcmcia_align, &data);
+ } else
+#endif
+ ret = allocate_resource(&iomem_resource, res, num, min,
+ max, 1, pcmcia_align, &data);
+ up(&rsrc_sem);
+ if (ret == 0 || low)
+ break;
+ low = 1;
+ }
+
+ if (ret != 0) {
+ kfree(res);
+ res = NULL;
+ }
+ return res;
+}
+
+
+static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj)
+{
+ u_long base, num;
+ struct socket_data *data = s->resource_data;
+ int ret;
+
+ base = adj->resource.memory.Base;
+ num = adj->resource.memory.Size;
+ if ((num == 0) || (base+num-1 < base))
+ return CS_BAD_SIZE;
+
+ ret = CS_SUCCESS;
+
+ down(&rsrc_sem);
+ switch (adj->Action) {
+ case ADD_MANAGED_RESOURCE:
+ ret = add_interval(&data->mem_db, base, num);
+ break;
+ case REMOVE_MANAGED_RESOURCE:
+ ret = sub_interval(&data->mem_db, base, num);
+ if (ret == CS_SUCCESS) {
+ struct pcmcia_socket *socket;
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
+ release_cis_mem(socket);
+ up_read(&pcmcia_socket_list_rwsem);
+ }
+ break;
+ default:
+ ret = CS_UNSUPPORTED_FUNCTION;
+ }
+ up(&rsrc_sem);
+
+ return ret;
+}
+
+
+static int adjust_io(struct pcmcia_socket *s, adjust_t *adj)
+{
+ struct socket_data *data = s->resource_data;
+ int base, num, ret = CS_SUCCESS;
+
+ base = adj->resource.io.BasePort;
+ num = adj->resource.io.NumPorts;
+ if ((base < 0) || (base > 0xffff))
+ return CS_BAD_BASE;
+ if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
+ return CS_BAD_SIZE;
+
+ down(&rsrc_sem);
+ switch (adj->Action) {
+ case ADD_MANAGED_RESOURCE:
+ if (add_interval(&data->io_db, base, num) != 0) {
+ ret = CS_IN_USE;
+ break;
+ }
+#ifdef CONFIG_PCMCIA_PROBE
+ if (probe_io)
+ do_io_probe(s, base, num);
+#endif
+ break;
+ case REMOVE_MANAGED_RESOURCE:
+ sub_interval(&data->io_db, base, num);
+ break;
+ default:
+ ret = CS_UNSUPPORTED_FUNCTION;
+ break;
+ }
+ up(&rsrc_sem);
+
+ return ret;
+}
+
+
+static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj)
+{
+ switch (adj->Resource) {
+ case RES_MEMORY_RANGE:
+ return adjust_memory(s, adj);
+ case RES_IO_RANGE:
+ return adjust_io(s, adj);
+ }
+ return CS_UNSUPPORTED_FUNCTION;
+}
+
+static int nonstatic_init(struct pcmcia_socket *s)
+{
+ struct socket_data *data;
+
+ data = kmalloc(sizeof(struct socket_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->mem_db.next = &data->mem_db;
+ data->io_db.next = &data->io_db;
+
+ s->resource_data = (void *) data;
+
+ return 0;
+}
+
+static void nonstatic_release_resource_db(struct pcmcia_socket *s)
+{
+ struct socket_data *data = s->resource_data;
+ struct resource_map *p, *q;
+
+ down(&rsrc_sem);
+ for (p = data->mem_db.next; p != &data->mem_db; p = q) {
+ q = p->next;
+ kfree(p);
+ }
+ for (p = data->io_db.next; p != &data->io_db; p = q) {
+ q = p->next;
+ kfree(p);
+ }
+ up(&rsrc_sem);
+}
+
+
+struct pccard_resource_ops pccard_nonstatic_ops = {
+ .validate_mem = pcmcia_nonstatic_validate_mem,
+ .adjust_io_region = nonstatic_adjust_io_region,
+ .find_io = nonstatic_find_io_region,
+ .find_mem = nonstatic_find_mem_region,
+ .adjust_resource = nonstatic_adjust_resource_info,
+ .init = nonstatic_init,
+ .exit = nonstatic_release_resource_db,
+};
+EXPORT_SYMBOL(pccard_nonstatic_ops);
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index a45fee3f4355..20dd66b245bc 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -758,6 +758,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
goto out_err_6;
skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD;
+ skt->socket.resource_ops = &pccard_static_ops;
skt->socket.irq_mask = 0;
skt->socket.map_size = PAGE_SIZE;
skt->socket.pci_irq = skt->irq;
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index a651309eb84f..e20438a7408f 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -531,8 +531,9 @@ static int __init init_tcic(void)
for (i = 0; i < sockets; i++) {
socket_table[i].socket.ops = &tcic_operations;
+ socket_table[i].socket.resource_ops = &pccard_nonstatic_ops;
socket_table[i].socket.dev.dev = &tcic_device.dev;
- ret = pcmcia_register_socket(&socket_table[i].socket);
+ ret = pcmcia_register_socket(&socket_table[i].socket);
if (ret && i)
pcmcia_unregister_socket(&socket_table[0].socket);
}
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index 315f634fd7f1..b9f3e3f21ad6 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -592,15 +592,20 @@ out:
static int ti12xx_override(struct yenta_socket *socket)
{
- u32 val;
+ u32 val, val_orig;
/* make sure that memory burst is active */
- val = config_readl(socket, TI113X_SYSTEM_CONTROL);
+ val_orig = val = config_readl(socket, TI113X_SYSTEM_CONTROL);
+ if (disable_clkrun && PCI_FUNC(socket->dev->devfn) == 0) {
+ printk(KERN_INFO "Yenta: Disabling CLKRUN feature\n");
+ val |= TI113X_SCR_KEEPCLK;
+ }
if (!(val & TI122X_SCR_MRBURSTUP)) {
printk(KERN_INFO "Yenta: Enabling burst memory read transactions\n");
val |= TI122X_SCR_MRBURSTUP;
- config_writel(socket, TI113X_SYSTEM_CONTROL, val);
}
+ if (val_orig != val)
+ config_writel(socket, TI113X_SYSTEM_CONTROL, val);
/*
* for EnE bridges only: clear testbit TLTEnable. this makes the
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 4b8b822bcca3..9fae06ac2761 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -28,6 +28,9 @@
#include "yenta_socket.h"
#include "i82365.h"
+static int disable_clkrun;
+module_param(disable_clkrun, bool, 0444);
+MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option");
#if 0
#define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args)
@@ -42,6 +45,10 @@
static int yenta_probe_cb_irq(struct yenta_socket *socket);
+static unsigned int override_bios;
+module_param(override_bios, uint, 0000);
+MODULE_PARM_DESC (override_bios, "yenta ignore bios resource allocation");
+
/*
* Generate easy-to-use ways of reading a cardbus sockets
* regular memory space ("cb_xxx"), configuration space
@@ -551,7 +558,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
start = config_readl(socket, offset) & mask;
end = config_readl(socket, offset+4) | ~mask;
- if (start && end > start) {
+ if (start && end > start && !override_bios) {
res->start = start;
res->end = end;
if (request_resource(root, res) == 0)
@@ -914,6 +921,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
/* prepare pcmcia_socket */
socket->socket.ops = &yenta_socket_operations;
+ socket->socket.resource_ops = &pccard_nonstatic_ops;
socket->socket.dev.dev = &dev->dev;
socket->socket.driver_data = socket;
socket->socket.owner = THIS_MODULE;
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index 5aba7890d16d..5d30a3ebfccd 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -231,18 +231,20 @@ static void __init sbus_bus_ranges_init(int parent_node, struct sbus_bus *sbus)
return;
}
sbus->num_sbus_ranges = len / sizeof(struct linux_prom_ranges);
+#ifdef CONFIG_SPARC32
if (sparc_cpu_model == sun4d) {
struct linux_prom_ranges iounit_ranges[PROMREG_MAX];
int num_iounit_ranges;
- len = prom_getproperty(parent_node, "ranges",
- (char *) iounit_ranges,
- sizeof (iounit_ranges));
+ len = prom_getproperty(parent_node, "ranges",
+ (char *) iounit_ranges,
+ sizeof (iounit_ranges));
if (len != -1) {
num_iounit_ranges = (len/sizeof(struct linux_prom_ranges));
prom_adjust_ranges (sbus->sbus_ranges, sbus->num_sbus_ranges, iounit_ranges, num_iounit_ranges);
}
}
+#endif
}
static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges,
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index f53956f77f28..a379bc9a1276 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -768,28 +768,6 @@ void aac_printf(struct aac_dev *dev, u32 val)
memset(cp, 0, 256);
}
-
-/**
- * aac_handle_aif - Handle a message from the firmware
- * @dev: Which adapter this fib is from
- * @fibptr: Pointer to fibptr from adapter
- *
- * This routine handles a driver notify fib from the adapter and
- * dispatches it to the appropriate routine for handling.
- */
-
-static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
-{
- struct hw_fib * hw_fib = fibptr->hw_fib;
- /*
- * Set the status of this FIB to be Invalid parameter.
- *
- * *(u32 *)fib->data = ST_INVAL;
- */
- *(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
- fib_adapter_complete(fibptr, sizeof(u32));
-}
-
/**
* aac_command_thread - command processing thread
* @dev: Adapter to monitor
@@ -859,7 +837,6 @@ int aac_command_thread(struct aac_dev * dev)
aifcmd = (struct aac_aifcmd *) hw_fib->data;
if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {
/* Handle Driver Notify Events */
- aac_handle_aif(dev, fib);
*(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
fib_adapter_complete(fib, sizeof(u32));
} else {
@@ -870,10 +847,6 @@ int aac_command_thread(struct aac_dev * dev)
u32 time_now, time_last;
unsigned long flagv;
- /* Sniff events */
- if (aifcmd->command == cpu_to_le32(AifCmdEventNotify))
- aac_handle_aif(dev, fib);
-
time_now = jiffies/HZ;
spin_lock_irqsave(&dev->fib_lock, flagv);
diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c
index d97a8b137fe0..c2b47f2bdffd 100644
--- a/drivers/scsi/aic7xxx/aic7770_osm.c
+++ b/drivers/scsi/aic7xxx/aic7770_osm.c
@@ -125,14 +125,8 @@ ahc_linux_eisa_init(void)
uint32_t eisa_id;
size_t id_size;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
- if (check_region(eisaBase, AHC_EISA_IOSIZE) != 0)
- continue;
- request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx");
-#else
if (request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx") == 0)
continue;
-#endif
eisa_id = 0;
id_size = sizeof(eisa_id);
@@ -207,14 +201,8 @@ aic7770_map_registers(struct ahc_softc *ahc, u_int port)
/*
* Lock out other contenders for our i/o space.
*/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
- if (check_region(port, AHC_EISA_IOSIZE) != 0)
- return (ENOMEM);
- request_region(port, AHC_EISA_IOSIZE, "aic7xxx");
-#else
if (request_region(port, AHC_EISA_IOSIZE, "aic7xxx") == 0)
return (ENOMEM);
-#endif
ahc->tag = BUS_SPACE_PIO;
ahc->bsh.ioport = port;
return (0);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index 539ae081f153..db3bd6321dd4 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -831,8 +831,6 @@ static inline void ahc_linux_eisa_exit(void) {
/******************************* PCI Routines *********************************/
#ifdef CONFIG_PCI
-void ahc_power_state_change(struct ahc_softc *ahc,
- ahc_power_state new_state);
int ahc_linux_pci_init(void);
void ahc_linux_pci_exit(void);
int ahc_pci_map_registers(struct ahc_softc *ahc);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index 49d799ac61e8..6f6674aa31ef 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -42,12 +42,6 @@
#include "aic7xxx_osm.h"
#include "aic7xxx_pci.h"
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-struct pci_device_id
-{
-};
-#endif
-
static int ahc_linux_pci_dev_probe(struct pci_dev *pdev,
const struct pci_device_id *ent);
static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc,
@@ -55,7 +49,6 @@ static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc,
static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
u_long *bus_addr,
uint8_t __iomem **maddr);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
static void ahc_linux_pci_dev_remove(struct pci_dev *pdev);
/* Define the macro locally since it's different for different class of chips.
@@ -169,7 +162,6 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev)
} else
ahc_list_unlock(&l);
}
-#endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */
static int
ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -219,7 +211,6 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahc = ahc_alloc(NULL, name);
if (ahc == NULL)
return (-ENOMEM);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
if (pci_enable_device(pdev)) {
ahc_free(ahc);
return (-ENODEV);
@@ -238,14 +229,12 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
ahc->platform_data->hw_dma_mask = DMA_32BIT_MASK;
}
-#endif
ahc->dev_softc = pci;
error = ahc_pci_config(ahc, entry);
if (error != 0) {
ahc_free(ahc);
return (-error);
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pci_set_drvdata(pdev, ahc);
if (aic7xxx_detect_complete) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
@@ -256,39 +245,14 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return (-ENODEV);
#endif
}
-#endif
return (0);
}
int
ahc_linux_pci_init(void)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
/* Translate error or zero return into zero or one */
return pci_module_init(&aic7xxx_pci_driver) ? 0 : 1;
-#else
- struct pci_dev *pdev;
- u_int class;
- int found;
-
- /* If we don't have a PCI bus, we can't find any adapters. */
- if (pci_present() == 0)
- return (0);
-
- found = 0;
- pdev = NULL;
- class = PCI_CLASS_STORAGE_SCSI << 8;
- while ((pdev = pci_find_class(class, pdev)) != NULL) {
- ahc_dev_softc_t pci;
- int error;
-
- pci = pdev;
- error = ahc_linux_pci_dev_probe(pdev, /*pci_devid*/NULL);
- if (error == 0)
- found++;
- }
- return (found);
-#endif
}
void
@@ -303,22 +267,11 @@ ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base)
if (aic7xxx_allow_memio == 0)
return (ENOMEM);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
*base = pci_resource_start(ahc->dev_softc, 0);
-#else
- *base = ahc_pci_read_config(ahc->dev_softc, PCIR_MAPS, 4);
- *base &= PCI_BASE_ADDRESS_IO_MASK;
-#endif
if (*base == 0)
return (ENOMEM);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
- if (check_region(*base, 256) != 0)
- return (ENOMEM);
- request_region(*base, 256, "aic7xxx");
-#else
if (request_region(*base, 256, "aic7xxx") == 0)
return (ENOMEM);
-#endif
return (0);
}
@@ -334,17 +287,13 @@ ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
start = pci_resource_start(ahc->dev_softc, 1);
if (start != 0) {
*bus_addr = start;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
if (request_mem_region(start, 0x1000, "aic7xxx") == 0)
error = ENOMEM;
-#endif
if (error == 0) {
*maddr = ioremap_nocache(start, 256);
if (*maddr == NULL) {
error = ENOMEM;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
release_mem_region(start, 0x1000);
-#endif
}
}
} else
@@ -387,10 +336,8 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
ahc_get_pci_slot(ahc->dev_softc),
ahc_get_pci_function(ahc->dev_softc));
iounmap(maddr);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
release_mem_region(ahc->platform_data->mem_busaddr,
0x1000);
-#endif
ahc->bsh.maddr = NULL;
maddr = NULL;
} else
@@ -440,41 +387,3 @@ ahc_pci_map_int(struct ahc_softc *ahc)
return (-error);
}
-void
-ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- pci_set_power_state(ahc->dev_softc, new_state);
-#else
- uint32_t cap;
- u_int cap_offset;
-
- /*
- * Traverse the capability list looking for
- * the power management capability.
- */
- cap = 0;
- cap_offset = ahc_pci_read_config(ahc->dev_softc,
- PCIR_CAP_PTR, /*bytes*/1);
- while (cap_offset != 0) {
-
- cap = ahc_pci_read_config(ahc->dev_softc,
- cap_offset, /*bytes*/4);
- if ((cap & 0xFF) == 1
- && ((cap >> 16) & 0x3) > 0) {
- uint32_t pm_control;
-
- pm_control = ahc_pci_read_config(ahc->dev_softc,
- cap_offset + 4,
- /*bytes*/4);
- pm_control &= ~0x3;
- pm_control |= new_state;
- ahc_pci_write_config(ahc->dev_softc,
- cap_offset + 4,
- pm_control, /*bytes*/2);
- break;
- }
- cap_offset = (cap >> 8) & 0xFF;
- }
-#endif
-}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index e3b50fcf62f7..7ddcc97fb243 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -721,7 +721,7 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
ahc->chip |= AHC_PCI;
ahc->description = entry->name;
- ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
+ pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0);
error = ahc_pci_map_registers(ahc);
if (error != 0)
@@ -2016,7 +2016,7 @@ static int
ahc_pci_resume(struct ahc_softc *ahc)
{
- ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
+ pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0);
/*
* We assume that the OS has restored our register
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index e710da4d00e1..d625fdebe052 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -1156,17 +1156,14 @@ scsi_show_extd_sense(unsigned char asc, unsigned char ascq)
}
/* Print sense information */
-static void
-print_sense_internal(const char *devclass,
- const unsigned char *sense_buffer,
- int sense_len,
- struct request *req)
+void
+__scsi_print_sense(const char *name, const unsigned char *sense_buffer,
+ int sense_len)
{
int k, num, res;
unsigned int info;
const char *error;
const char *sense_txt;
- const char *name = req->rq_disk ? req->rq_disk->disk_name : devclass;
struct scsi_sense_hdr ssh;
res = scsi_normalize_sense(sense_buffer, sense_len, &ssh);
@@ -1254,18 +1251,25 @@ print_sense_internal(const char *devclass,
printk("\n");
}
}
+EXPORT_SYMBOL(__scsi_print_sense);
void scsi_print_sense(const char *devclass, struct scsi_cmnd *cmd)
{
- print_sense_internal(devclass, cmd->sense_buffer,
- SCSI_SENSE_BUFFERSIZE, cmd->request);
+ const char *name = devclass;
+
+ if (cmd->request->rq_disk)
+ name = cmd->request->rq_disk->disk_name;
+ __scsi_print_sense(name, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
}
EXPORT_SYMBOL(scsi_print_sense);
void scsi_print_req_sense(const char *devclass, struct scsi_request *sreq)
{
- print_sense_internal(devclass, sreq->sr_sense_buffer,
- SCSI_SENSE_BUFFERSIZE, sreq->sr_request);
+ const char *name = devclass;
+
+ if (sreq->sr_request->rq_disk)
+ name = sreq->sr_request->rq_disk->disk_name;
+ __scsi_print_sense(name, sreq->sr_sense_buffer, SCSI_SENSE_BUFFERSIZE);
}
EXPORT_SYMBOL(scsi_print_req_sense);
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
index 32e0cd59752c..770930e2aec3 100644
--- a/drivers/scsi/fd_mcs.c
+++ b/drivers/scsi/fd_mcs.c
@@ -96,7 +96,6 @@
#include "scsi.h"
#include <scsi/scsi_host.h>
-#include "fd_mcs.h"
#define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>"
@@ -104,14 +103,12 @@
#define DEBUG 0 /* Enable debugging output */
#define ENABLE_PARITY 1 /* Enable SCSI Parity */
-#define DO_DETECT 0 /* Do device detection here (see scsi.c) */
/* END OF USER DEFINABLE OPTIONS */
#if DEBUG
#define EVERY_ACCESS 0 /* Write a line on every scsi access */
#define ERRORS_ONLY 1 /* Only write a line if there is an error */
-#define DEBUG_DETECT 1 /* Debug fd_mcs_detect() */
#define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */
#define DEBUG_ABORT 1 /* Debug abort() routine */
#define DEBUG_RESET 1 /* Debug reset() routine */
@@ -119,7 +116,6 @@
#else
#define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
#define ERRORS_ONLY 0
-#define DEBUG_DETECT 0
#define DEBUG_MESSAGES 0
#define DEBUG_ABORT 0
#define DEBUG_RESET 0
@@ -432,6 +428,7 @@ static int fd_mcs_detect(Scsi_Host_Template * tpnt)
FIFO_COUNT = user_fifo_count ? user_fifo_count : fd_mcs_adapters[loop].fifo_count;
FIFO_Size = user_fifo_size ? user_fifo_size : fd_mcs_adapters[loop].fifo_size;
+/* FIXME: Do we need to keep this bit of code inside NOT_USED around at all? */
#ifdef NOT_USED
/* *************************************************** */
/* Try to toggle 32-bit mode. This only
@@ -510,59 +507,6 @@ static int fd_mcs_detect(Scsi_Host_Template * tpnt)
outb(0, SCSI_Mode_Cntl_port);
outb(PARITY_MASK, TMC_Cntl_port);
/* done reset */
-
-#if DO_DETECT
- /* scan devices attached */
- {
- const int buflen = 255;
- int i, j, retcode;
- Scsi_Cmnd SCinit;
- unsigned char do_inquiry[] = { INQUIRY, 0, 0, 0, buflen, 0 };
- unsigned char do_request_sense[] = { REQUEST_SENSE,
- 0, 0, 0, buflen, 0
- };
- unsigned char do_read_capacity[] = { READ_CAPACITY,
- 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- unsigned char buf[buflen];
-
- SCinit.request_buffer = SCinit.buffer = buf;
- SCinit.request_bufflen = SCinit.bufflen = sizeof(buf) - 1;
- SCinit.use_sg = 0;
- SCinit.lun = 0;
- SCinit.host = shpnt;
-
- printk("fd_mcs: detection routine scanning for devices:\n");
- for (i = 0; i < 8; i++) {
- if (i == shpnt->this_id) /* Skip host adapter */
- continue;
- SCinit.target = i;
- memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
- retcode = fd_mcs_command(&SCinit);
- if (!retcode) {
- memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
- retcode = fd_mcs_command(&SCinit);
- if (!retcode) {
- printk(" SCSI ID %d: ", i);
- for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
- printk("%c", buf[j] >= 20 ? buf[j] : ' ');
- memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
- retcode = fd_mcs_command(&SCinit);
- if (!retcode) {
- unsigned long blocks, size, capacity;
-
- blocks = (buf[0] << 24) | (buf[1] << 16)
- | (buf[2] << 8) | buf[3];
- size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
- capacity = +(+(blocks / 1024L) * +(size * 10L)) / 1024L;
-
- printk("%lu MB (%lu byte blocks)\n", ((capacity + 5L) / 10L), size);
- }
- }
- }
- }
- }
-#endif
}
}
diff --git a/drivers/scsi/fd_mcs.h b/drivers/scsi/fd_mcs.h
deleted file mode 100644
index 011a7878a201..000000000000
--- a/drivers/scsi/fd_mcs.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* fd_mcs.h -- Header for Future Domain MCS 600/700 (or IBM OEM) driver
- *
- * fd_mcs.h v0.2 03/11/1998 ZP Gu (zpg@castle.net)
- *
-
- * 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, or (at your option) any
- * later version.
-
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-#ifndef _FD_MCS_H
-#define _FD_MCS_H
-
-static int fd_mcs_detect(Scsi_Host_Template *);
-static int fd_mcs_release(struct Scsi_Host *);
-static int fd_mcs_command(Scsi_Cmnd *);
-static int fd_mcs_abort(Scsi_Cmnd *);
-static int fd_mcs_bus_reset(Scsi_Cmnd *);
-static int fd_mcs_device_reset(Scsi_Cmnd *);
-static int fd_mcs_host_reset(Scsi_Cmnd *);
-static int fd_mcs_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
-static int fd_mcs_biosparam(struct scsi_device *, struct block_device *,
- sector_t, int *);
-static const char *fd_mcs_info(struct Scsi_Host *);
-
-#endif /* _FD_MCS_H */
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 2442ca46aeb0..4a092bec4bb7 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -397,11 +397,7 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/uaccess.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#include <linux/spinlock.h>
-#else
-#include <asm/spinlock.h>
-#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
#include <linux/blkdev.h>
#else
@@ -412,14 +408,11 @@
#include "scsi.h"
#include <scsi/scsi_host.h>
#include "gdth.h"
+#include "gdth_kcompat.h"
static void gdth_delay(int milliseconds);
static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static irqreturn_t gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-#else
-static void gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-#endif
static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
static int gdth_async_event(int hanum);
static void gdth_log_event(gdth_evt_data *dvr, char *buffer);
@@ -617,32 +610,6 @@ static unchar gdth_direction_tab[0x100] = {
DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
};
-/* __initfunc, __initdata macros */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-#define GDTH_INITFUNC(type, func) type __init func
-#include <linux/init.h>
-#else
-#define GDTH_INITFUNC(type, func) __initfunc(type func)
-#include <linux/init.h>
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-#define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock)
-#define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags)
-#define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags)
-
-#define GDTH_LOCK_SCSI_DONE(dev, flags) spin_lock_irqsave(dev->host_lock,flags)
-#define GDTH_UNLOCK_SCSI_DONE(dev, flags) spin_unlock_irqrestore(dev->host_lock,flags)
-
-#else
-#define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock)
-#define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags)
-#define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags)
-
-#define GDTH_LOCK_SCSI_DONE(flags) spin_lock_irqsave(&io_request_lock,flags)
-#define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(&io_request_lock,flags)
-#endif
-
/* LILO and modprobe/insmod parameters */
/* IRQ list for GDT3000/3020 EISA controllers */
static int irq[MAXHA] __initdata =
@@ -674,7 +641,6 @@ static int probe_eisa_isa = 0;
/* 64 bit DMA mode, support for drives > 2 TB, if force_dma32 = 0 */
static int force_dma32 = 0;
-#ifdef MODULE
/* parameters for modprobe/insmod */
module_param(irq, int, 0);
module_param(disable, int, 0);
@@ -689,33 +655,15 @@ module_param(shared_access, int, 0);
module_param(probe_eisa_isa, int, 0);
module_param(force_dma32, int, 0);
MODULE_AUTHOR("Achim Leubner");
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,11)
MODULE_LICENSE("GPL");
-#endif
-#endif
/* ioctl interface */
static struct file_operations gdth_fops = {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
.ioctl = gdth_ioctl,
.open = gdth_open,
.release = gdth_close,
-#else
- ioctl:gdth_ioctl,
- open:gdth_open,
- release:gdth_close,
-#endif
};
-/* /proc support */
-#include <linux/stat.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-struct proc_dir_entry proc_scsi_gdth = {
- PROC_SCSI_GDTH, 4, "gdth",
- S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-#endif
-
#include "gdth_proc.h"
#include "gdth_proc.c"
@@ -755,7 +703,7 @@ static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs
/* controller search and initialization functions */
-GDTH_INITFUNC(static int, gdth_search_eisa(ushort eisa_adr))
+static int __init gdth_search_eisa(ushort eisa_adr)
{
ulong32 id;
@@ -773,7 +721,7 @@ GDTH_INITFUNC(static int, gdth_search_eisa(ushort eisa_adr))
}
-GDTH_INITFUNC(static int, gdth_search_isa(ulong32 bios_adr))
+static int __init gdth_search_isa(ulong32 bios_adr)
{
void __iomem *addr;
ulong32 id;
@@ -789,7 +737,7 @@ GDTH_INITFUNC(static int, gdth_search_isa(ulong32 bios_adr))
}
-GDTH_INITFUNC(static int, gdth_search_pci(gdth_pci_str *pcistr))
+static int __init gdth_search_pci(gdth_pci_str *pcistr)
{
ushort device, cnt;
@@ -812,21 +760,19 @@ GDTH_INITFUNC(static int, gdth_search_pci(gdth_pci_str *pcistr))
return cnt;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
/* Vortex only makes RAID controllers.
* We do not really want to specify all 550 ids here, so wildcard match.
*/
-static struct pci_device_id gdthtable[] __devinitdata = {
+static struct pci_device_id gdthtable[] __attribute_used__ = {
{PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
{PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID},
{PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID},
{0}
};
MODULE_DEVICE_TABLE(pci,gdthtable);
-#endif
-GDTH_INITFUNC(static void, gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
- ushort vendor, ushort device))
+static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
+ ushort vendor, ushort device)
{
ulong base0, base1, base2;
struct pci_dev *pdev;
@@ -834,7 +780,6 @@ GDTH_INITFUNC(static void, gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
*cnt, vendor, device));
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pdev = NULL;
while ((pdev = pci_find_device(vendor, device, pdev))
!= NULL) {
@@ -872,52 +817,10 @@ GDTH_INITFUNC(static void, gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
pcistr[*cnt].irq, pcistr[*cnt].dpmem));
(*cnt)++;
}
-#else
- pdev = NULL;
- while ((pdev = pci_find_device(vendor, device, pdev))
- != NULL) {
- if (*cnt >= MAXHA)
- return;
- /* GDT PCI controller found, resources are already in pdev */
- pcistr[*cnt].pdev = pdev;
- pcistr[*cnt].vendor_id = vendor;
- pcistr[*cnt].device_id = device;
- pcistr[*cnt].bus = pdev->bus->number;
- pcistr[*cnt].device_fn = pdev->devfn;
- pcibios_read_config_word(pcistr[*cnt].bus, pcistr[*cnt].device_fn,
- PCI_SUBSYSTEM_ID, &pcistr[*cnt].subdevice_id);
- pcistr[*cnt].irq = pdev->irq;
- base0 = pdev->base_address[0];
- base1 = pdev->base_address[1];
- base2 = pdev->base_address[2];
- if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */
- device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */
- if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
- PCI_BASE_ADDRESS_SPACE_MEMORY)
- continue;
- pcistr[*cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
- } else { /* GDT6110, GDT6120, .. */
- if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
- PCI_BASE_ADDRESS_SPACE_MEMORY ||
- (base2 & PCI_BASE_ADDRESS_SPACE) !=
- PCI_BASE_ADDRESS_SPACE_MEMORY ||
- (base1 & PCI_BASE_ADDRESS_SPACE) !=
- PCI_BASE_ADDRESS_SPACE_IO)
- continue;
- pcistr[*cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
- pcistr[*cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
- pcistr[*cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK;
- }
- TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
- pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn),
- pcistr[*cnt].irq, pcistr[*cnt].dpmem));
- (*cnt)++;
- }
-#endif
}
-GDTH_INITFUNC(static void, gdth_sort_pci(gdth_pci_str *pcistr, int cnt))
+static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
{
gdth_pci_str temp;
int i, changed;
@@ -955,7 +858,7 @@ GDTH_INITFUNC(static void, gdth_sort_pci(gdth_pci_str *pcistr, int cnt))
}
-GDTH_INITFUNC(static int, gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
+static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
{
ulong32 retries,id;
unchar prot_ver,eisacf,i,irq_found;
@@ -1048,7 +951,7 @@ GDTH_INITFUNC(static int, gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
}
-GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
+static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
{
register gdt2_dpram_str __iomem *dp2_ptr;
int i;
@@ -1148,7 +1051,7 @@ GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
}
-GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
+static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
{
register gdt6_dpram_str __iomem *dp6_ptr;
register gdt6c_dpram_str __iomem *dp6c_ptr;
@@ -1168,9 +1071,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
ha->stype = (ulong32)pcistr->device_id;
ha->subdevice_id = pcistr->subdevice_id;
ha->irq = pcistr->irq;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
ha->pdev = pcistr->pdev;
-#endif
if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */
TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
@@ -1401,7 +1302,6 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
}
/* manipulate config. space to enable DPMEM, start RP controller */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
command |= 6;
pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
@@ -1412,18 +1312,6 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
gdth_delay(1);
pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
pci_resource_start(pcistr->pdev, 8));
-#else
- pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
- command |= 6;
- pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
- if (pcistr->pdev->rom_address == 1UL)
- pcistr->pdev->rom_address = 0UL;
- i = 0xFEFF0001UL;
- pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i);
- gdth_delay(1);
- pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
- pcistr->pdev->rom_address);
-#endif
dp6m_ptr = ha->brd;
@@ -1550,7 +1438,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
/* controller protocol functions */
-GDTH_INITFUNC(static void, gdth_enable_int(int hanum))
+static void __init gdth_enable_int(int hanum)
{
gdth_ha_str *ha;
ulong flags;
@@ -1560,7 +1448,7 @@ GDTH_INITFUNC(static void, gdth_enable_int(int hanum))
TRACE(("gdth_enable_int() hanum %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
if (ha->type == GDT_EISA) {
outb(0xff, ha->bmic + EDOORREG);
@@ -1585,7 +1473,7 @@ GDTH_INITFUNC(static void, gdth_enable_int(int hanum))
gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
&dp6m_ptr->i960r.edoor_en_reg);
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
@@ -1897,7 +1785,7 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
/* search for devices */
-GDTH_INITFUNC(static int, gdth_search_drives(int hanum))
+static int __init gdth_search_drives(int hanum)
{
register gdth_ha_str *ha;
ushort cdev_cnt, i;
@@ -2357,16 +2245,11 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
TRACE(("gdth_putq() priority %d\n",priority));
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
scp->SCp.this_residual = (int)priority;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
t = scp->device->id;
-#else
- b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
- t = scp->target;
-#endif
if (priority >= DEFAULT_PRI) {
if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
(b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) {
@@ -2389,7 +2272,7 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
pscp->SCp.ptr = (char *)scp;
scp->SCp.ptr = (char *)nscp;
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
#ifdef GDTH_STATISTICS
flags = 0;
@@ -2415,7 +2298,7 @@ static void gdth_next(int hanum)
TRACE(("gdth_next() hanum %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
if (!gdth_polling)
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->cmd_cnt = ha->cmd_offs_dpmem = 0;
this_cmd = firsttime = TRUE;
@@ -2425,15 +2308,9 @@ static void gdth_next(int hanum)
for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel;
t = nscp->device->id;
l = nscp->device->lun;
-#else
- b = virt_ctr ? NUMDATA(nscp->host)->busnum : nscp->channel;
- t = nscp->target;
- l = nscp->lun;
-#endif
if (nscp->SCp.this_residual >= DEFAULT_PRI) {
if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
(b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock))
@@ -2444,7 +2321,7 @@ static void gdth_next(int hanum)
if (gdth_test_busy(hanum)) { /* controller busy ? */
TRACE(("gdth_next() controller %d busy !\n",hanum));
if (!gdth_polling) {
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
return;
}
while (gdth_test_busy(hanum))
@@ -2513,14 +2390,8 @@ static void gdth_next(int hanum)
nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
- else {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ else
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
}
} else if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) {
if (!(cmd_index=gdth_special_cmd(hanum,nscp)))
@@ -2538,14 +2409,8 @@ static void gdth_next(int hanum)
nscp->result = DID_BAD_TARGET << 16;
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
- else {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ else
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
} else {
switch (nscp->cmnd[0]) {
case TEST_UNIT_READY:
@@ -2555,9 +2420,7 @@ static void gdth_next(int hanum)
case VERIFY:
case START_STOP:
case MODE_SENSE:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
case SERVICE_ACTION_IN:
-#endif
TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
nscp->cmnd[4],nscp->cmnd[5]));
@@ -2572,22 +2435,10 @@ static void gdth_next(int hanum)
nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
- else {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ else
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
- } else if (gdth_internal_cache_cmd(hanum,nscp)) {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ } else if (gdth_internal_cache_cmd(hanum,nscp))
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
break;
case ALLOW_MEDIUM_REMOVAL:
@@ -2600,14 +2451,8 @@ static void gdth_next(int hanum)
nscp->sense_buffer[0] = 0;
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
- else {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ else
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
} else {
nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
TRACE(("Prevent/allow r. %d rem. drive %d\n",
@@ -2629,10 +2474,8 @@ static void gdth_next(int hanum)
case WRITE_6:
case READ_10:
case WRITE_10:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
case READ_16:
case WRITE_16:
-#endif
if (ha->hdr[t].media_changed) {
/* return UNIT_ATTENTION */
TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
@@ -2644,14 +2487,8 @@ static void gdth_next(int hanum)
nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
- else {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ else
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
} else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
this_cmd = FALSE;
break;
@@ -2665,14 +2502,8 @@ static void gdth_next(int hanum)
nscp->result = DID_ABORT << 16;
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
- else {
- if (!gdth_polling)
- GDTH_UNLOCK_HA(ha,flags);
- /* io_request_lock already active ! */
+ else
nscp->scsi_done(nscp);
- if (!gdth_polling)
- GDTH_LOCK_HA(ha,flags);
- }
break;
}
}
@@ -2692,7 +2523,7 @@ static void gdth_next(int hanum)
}
if (!gdth_polling)
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
if (gdth_polling && ha->cmd_cnt > 0) {
if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT))
@@ -2708,7 +2539,6 @@ static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
ushort cpsum,cpnow;
struct scatterlist *sl;
gdth_ha_str *ha;
- int sgcnt;
char *address;
cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen;
@@ -2716,10 +2546,9 @@ static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
if (scp->use_sg) {
sl = (struct scatterlist *)scp->request_buffer;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
- sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,PCI_DMA_FROMDEVICE);
- for (i=0,cpsum=0; i<sgcnt; ++i,++sl) {
- cpnow = (ushort)sg_dma_len(sl);
+ for (i=0,cpsum=0; i<scp->use_sg; ++i,++sl) {
+ unsigned long flags;
+ cpnow = (ushort)sl->length;
TRACE(("copy_internal() now %d sum %d count %d %d\n",
cpnow,cpsum,cpcount,(ushort)scp->bufflen));
if (cpsum+cpnow > cpcount)
@@ -2730,30 +2559,16 @@ static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
hanum);
return;
}
- address = (char *)(page_address(sl->page) + sl->offset);
- memcpy(address,buffer,cpnow);
- if (cpsum == cpcount)
- break;
- buffer += cpnow;
- }
- pci_unmap_sg(ha->pdev,scp->request_buffer,
- scp->use_sg,PCI_DMA_FROMDEVICE);
-#else
- sgcnt = scp->use_sg;
- for (i=0,cpsum=0; i<sgcnt; ++i,++sl) {
- cpnow = (ushort)sl->length;
- TRACE(("copy_internal() now %d sum %d count %d %d\n",
- cpnow,cpsum,cpcount,(ushort)scp->bufflen));
- if (cpsum+cpnow > cpcount)
- cpnow = cpcount - cpsum;
- cpsum += cpnow;
- address = (char *)sl->address;
+ local_irq_save(flags);
+ address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset;
memcpy(address,buffer,cpnow);
+ flush_dcache_page(sl->page);
+ kunmap_atomic(address, KM_BIO_SRC_IRQ);
+ local_irq_restore(flags);
if (cpsum == cpcount)
break;
buffer += cpnow;
}
-#endif
} else {
TRACE(("copy_internal() count %d\n",cpcount));
memcpy((char*)scp->request_buffer,buffer,cpcount);
@@ -2770,11 +2585,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
gdth_modep_data mpd;
ha = HADATA(gdth_ctr_tab[hanum]);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
t = scp->device->id;
-#else
- t = scp->target;
-#endif
TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
scp->cmnd[0],t));
@@ -2839,7 +2650,6 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data));
break;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
case SERVICE_ACTION_IN:
if ((scp->cmnd[1] & 0x1f) == SAI_READ_CAPACITY_16 &&
(ha->cache_feat & GDT_64BIT)) {
@@ -2853,7 +2663,6 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
scp->result = DID_ABORT << 16;
}
break;
-#endif
default:
TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
@@ -2877,10 +2686,8 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
ulong64 no, blockno;
dma_addr_t phys_addr;
int i, cmd_index, read_write, sgcnt, mode64;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
struct page *page;
ulong offset;
-#endif
ha = HADATA(gdth_ctr_tab[hanum]);
cmdp = ha->pccb;
@@ -2922,10 +2729,7 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
else
cmdp->OpCode = GDT_FLUSH;
} else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10 ||
- scp->cmnd[0] == WRITE_12
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- || scp->cmnd[0] == WRITE_16
-#endif
+ scp->cmnd[0] == WRITE_12 || scp->cmnd[0] == WRITE_16
) {
read_write = 1;
if (gdth_write_through || ((ha->hdr[hdrive].rw_attribs & 1) &&
@@ -2976,7 +2780,6 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
if (scp->use_sg) {
sl = (struct scatterlist *)scp->request_buffer;
sgcnt = scp->use_sg;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
scp->SCp.Status = GDTH_MAP_SG;
scp->SCp.Message = (read_write == 1 ?
PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
@@ -3005,23 +2808,6 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl);
}
}
-#else
- if (mode64) {
- cmdp->u.cache64.DestAddr= (ulong64)-1;
- cmdp->u.cache64.sg_canz = sgcnt;
- for (i=0; i<sgcnt; ++i,++sl) {
- cmdp->u.cache64.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
- cmdp->u.cache64.sg_lst[i].sg_len = (ulong32)sl->length;
- }
- } else {
- cmdp->u.cache.DestAddr= 0xffffffff;
- cmdp->u.cache.sg_canz = sgcnt;
- for (i=0; i<sgcnt; ++i,++sl) {
- cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
- cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length;
- }
- }
-#endif
#ifdef GDTH_STATISTICS
if (max_sg < (ulong32)sgcnt) {
@@ -3031,7 +2817,6 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
#endif
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
scp->SCp.Status = GDTH_MAP_SINGLE;
scp->SCp.Message = (read_write == 1 ?
PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
@@ -3040,9 +2825,6 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
phys_addr = pci_map_page(ha->pdev,page,offset,
scp->request_bufflen,scp->SCp.Message);
scp->SCp.dma_handle = phys_addr;
-#else
- phys_addr = virt_to_bus(scp->request_buffer);
-#endif
if (mode64) {
if (ha->cache_feat & SCATTER_GATHER) {
cmdp->u.cache64.DestAddr = (ulong64)-1;
@@ -3114,19 +2896,12 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
dma_addr_t phys_addr, sense_paddr;
int cmd_index, sgcnt, mode64;
unchar t,l;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
struct page *page;
ulong offset;
-#endif
ha = HADATA(gdth_ctr_tab[hanum]);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
t = scp->device->id;
l = scp->device->lun;
-#else
- t = scp->target;
- l = scp->lun;
-#endif
cmdp = ha->pccb;
TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n",
scp->cmnd[0],b,t,l));
@@ -3166,7 +2941,6 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
}
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
page = virt_to_page(scp->sense_buffer);
offset = (ulong)scp->sense_buffer & ~PAGE_MASK;
sense_paddr = pci_map_page(ha->pdev,page,offset,
@@ -3174,9 +2948,6 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
scp->SCp.buffer = (struct scatterlist *)((ulong32)sense_paddr);
/* high part, if 64bit */
scp->host_scribble = (char *)(ulong32)((ulong64)sense_paddr >> 32);
-#else
- sense_paddr = virt_to_bus(scp->sense_buffer);
-#endif
cmdp->OpCode = GDT_WRITE; /* always */
cmdp->BoardNode = LOCALBOARD;
if (mode64) {
@@ -3215,7 +2986,6 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
if (scp->use_sg) {
sl = (struct scatterlist *)scp->request_buffer;
sgcnt = scp->use_sg;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
scp->SCp.Status = GDTH_MAP_SG;
scp->SCp.Message = PCI_DMA_BIDIRECTIONAL;
sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message);
@@ -3243,23 +3013,6 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl);
}
}
-#else
- if (mode64) {
- cmdp->u.raw64.sdata = (ulong64)-1;
- cmdp->u.raw64.sg_ranz = sgcnt;
- for (i=0; i<sgcnt; ++i,++sl) {
- cmdp->u.raw64.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
- cmdp->u.raw64.sg_lst[i].sg_len = (ulong32)sl->length;
- }
- } else {
- cmdp->u.raw.sdata = 0xffffffff;
- cmdp->u.raw.sg_ranz = sgcnt;
- for (i=0; i<sgcnt; ++i,++sl) {
- cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
- cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length;
- }
- }
-#endif
#ifdef GDTH_STATISTICS
if (max_sg < sgcnt) {
@@ -3269,7 +3022,6 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
#endif
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
scp->SCp.Status = GDTH_MAP_SINGLE;
scp->SCp.Message = PCI_DMA_BIDIRECTIONAL;
page = virt_to_page(scp->request_buffer);
@@ -3277,9 +3029,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
phys_addr = pci_map_page(ha->pdev,page,offset,
scp->request_bufflen,scp->SCp.Message);
scp->SCp.dma_handle = phys_addr;
-#else
- phys_addr = virt_to_bus(scp->request_buffer);
-#endif
+
if (mode64) {
if (ha->raw_feat & SCATTER_GATHER) {
cmdp->u.raw64.sdata = (ulong64)-1;
@@ -3461,7 +3211,7 @@ static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr)
ulong flags;
TRACE2(("gdth_read_event() handle %d\n", handle));
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
if (handle == -1)
eindex = eoldidx;
else
@@ -3469,7 +3219,7 @@ static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr)
estr->event_source = 0;
if (eindex >= MAX_EVENTS) {
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
return eindex;
}
e = &ebuffer[eindex];
@@ -3482,7 +3232,7 @@ static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr)
}
memcpy(estr, e, sizeof(gdth_evt_str));
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
return eindex;
}
@@ -3495,7 +3245,7 @@ static void gdth_readapp_event(gdth_ha_str *ha,
unchar found = FALSE;
TRACE2(("gdth_readapp_event() app. %d\n", application));
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
eindex = eoldidx;
for (;;) {
e = &ebuffer[eindex];
@@ -3515,7 +3265,7 @@ static void gdth_readapp_event(gdth_ha_str *ha,
memcpy(estr, e, sizeof(gdth_evt_str));
else
estr->event_source = 0;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
static void gdth_clear_events(void)
@@ -3529,12 +3279,9 @@ static void gdth_clear_events(void)
/* SCSI interface functions */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
-#else
-static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
-#endif
{
+ gdth_ha_str *ha2 = (gdth_ha_str *)dev_id;
register gdth_ha_str *ha;
gdt6m_dpram_str __iomem *dp6m_ptr = NULL;
gdt6_dpram_str __iomem *dp6_ptr;
@@ -3556,28 +3303,20 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
/* if polling and not from gdth_wait() -> return */
if (gdth_polling) {
if (!gdth_from_wait) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
return IRQ_HANDLED;
-#else
- return;
-#endif
}
}
if (!gdth_polling)
- GDTH_LOCK_HA((gdth_ha_str *)dev_id,flags);
+ spin_lock_irqsave(&ha2->smp_lock, flags);
wait_index = 0;
/* search controller */
if ((hanum = gdth_get_status(&IStatus,irq)) == -1) {
/* spurious interrupt */
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
return IRQ_HANDLED;
-#else
- return;
-#endif
}
ha = HADATA(gdth_ctr_tab[hanum]);
@@ -3711,12 +3450,8 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
} else {
TRACE2(("gdth_interrupt() unknown controller type\n"));
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
return IRQ_HANDLED;
-#else
- return;
-#endif
}
TRACE(("gdth_interrupt() index %d stat %d info %d\n",
@@ -3731,13 +3466,9 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
TRACE2(("gdth_interrupt() async. event\n"));
gdth_async_event(hanum);
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
gdth_next(hanum);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
return IRQ_HANDLED;
-#else
- return;
-#endif
}
if (IStatus == SPEZINDEX) {
@@ -3746,12 +3477,8 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
ha->dvr.eu.driver.ionode = hanum;
gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr);
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
return IRQ_HANDLED;
-#else
- return;
-#endif
}
scp = ha->cmd_tab[IStatus-2].cmnd;
Service = ha->cmd_tab[IStatus-2].service;
@@ -3763,40 +3490,24 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
ha->dvr.eu.driver.index = IStatus;
gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr);
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
return IRQ_HANDLED;
-#else
- return;
-#endif
}
if (scp == INTERNAL_CMND) {
TRACE(("gdth_interrupt() answer to internal command\n"));
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
return IRQ_HANDLED;
-#else
- return;
-#endif
}
TRACE(("gdth_interrupt() sync. status\n"));
rval = gdth_sync_event(hanum,Service,IStatus,scp);
if (!gdth_polling)
- GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+ spin_unlock_irqrestore(&ha2->smp_lock, flags);
if (rval == 2) {
gdth_putq(hanum,scp,scp->SCp.this_residual);
} else if (rval == 1) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- GDTH_LOCK_SCSI_DONE(scp->device->host, flags);
- scp->scsi_done(scp);
- GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags);
-#else
- GDTH_LOCK_SCSI_DONE(flags);
scp->scsi_done(scp);
- GDTH_UNLOCK_SCSI_DONE(flags);
-#endif
}
#ifdef INT_COAL
@@ -3825,9 +3536,7 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
#endif
gdth_next(hanum);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
return IRQ_HANDLED;
-#endif
}
static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
@@ -3911,13 +3620,8 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
printk("\n");
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
t = scp->device->id;
-#else
- b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
- t = scp->target;
-#endif
if (scp->SCp.sent_command == -1 && b != ha->virt_bus) {
ha->raw[BUS_L2P(ha,b)].io_cnt[t]--;
}
@@ -3929,7 +3633,6 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
/* retry */
return 2;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
if (scp->SCp.Status == GDTH_MAP_SG)
pci_unmap_sg(ha->pdev,scp->request_buffer,
scp->use_sg,scp->SCp.Message);
@@ -3943,7 +3646,7 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
addr += (dma_addr_t)((ulong64)(ulong32)scp->host_scribble << 32);
pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE);
}
-#endif
+
if (ha->status == S_OK) {
scp->SCp.Status = S_OK;
scp->SCp.Message = ha->info;
@@ -4340,7 +4043,7 @@ void gdth_timeout(ulong data)
int hanum = 0;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
for (act_stats=0,i=0; i<GDTH_MAXCMDS; ++i)
if (ha->cmd_tab[i].cmnd != UNUSED_CMND)
@@ -4355,11 +4058,11 @@ void gdth_timeout(ulong data)
gdth_timer.expires = jiffies + 30 * HZ;
add_timer(&gdth_timer);
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
#endif
-GDTH_INITFUNC(void, internal_setup(char *str,int *ints))
+void __init internal_setup(char *str,int *ints)
{
int i, argc;
char *cur_str, *argv;
@@ -4432,7 +4135,7 @@ GDTH_INITFUNC(void, internal_setup(char *str,int *ints))
}
}
-GDTH_INITFUNC(int, option_setup(char *str))
+int __init option_setup(char *str)
{
int ints[MAXHA];
char *cur = str;
@@ -4450,7 +4153,7 @@ GDTH_INITFUNC(int, option_setup(char *str))
return 1;
}
-GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
+int __init gdth_detect(Scsi_Host_Template *shtp)
{
struct Scsi_Host *shp;
gdth_pci_str pcistr[MAXHA];
@@ -4540,7 +4243,6 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
ha->pccb = CMDDATA(shp);
ha->ccb_phys = 0L;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
ha->pdev = NULL;
ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
&scratch_dma_handle);
@@ -4554,21 +4256,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
MAXOFFSETS, &scratch_dma_handle);
ha->coal_stat_phys = scratch_dma_handle;
#endif
-#else
- ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
- if (ha->pscratch)
- ha->scratch_phys = virt_to_bus(ha->pscratch);
- ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA);
- if (ha->pmsg)
- ha->msg_phys = virt_to_bus(ha->pmsg);
-#ifdef INT_COAL
- ha->coal_stat =
- scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS,
- GFP_ATOMIC | GFP_DMA);
- if (ha->coal_stat)
- ha->coal_stat_phys = virt_to_bus(ha->coal_stat);
-#endif
-#endif
+
ha->scratch_busy = FALSE;
ha->req_first = NULL;
ha->tid_cnt = MAX_HDRIVES;
@@ -4583,7 +4271,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
printk("GDT-ISA: Error during device scan\n");
--gdth_ctr_count;
--gdth_ctr_vcount;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+
#ifdef INT_COAL
if (ha->coal_stat)
pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
@@ -4596,17 +4284,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
if (ha->pmsg)
pci_free_consistent(ha->pdev, sizeof(gdth_msg_str),
ha->pmsg, ha->msg_phys);
-#else
-#ifdef INT_COAL
- if (ha->coal_stat)
- scsi_init_free((void *)ha->coal_stat,
- sizeof(gdth_coal_status) * MAXOFFSETS);
-#endif
- if (ha->pscratch)
- scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
- if (ha->pmsg)
- scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
-#endif
+
free_irq(ha->irq,ha);
scsi_unregister(shp);
continue;
@@ -4615,14 +4293,13 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
hdr_channel = ha->bus_cnt;
ha->virt_bus = hdr_channel;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \
LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
shp->highmem_io = 0;
#endif
if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT)
shp->max_cmd_len = 16;
-#endif
+
shp->max_id = ha->tid_cnt;
shp->max_lun = MAXLUN;
shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
@@ -4640,7 +4317,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
}
}
- GDTH_INIT_LOCK_HA(ha);
+ spin_lock_init(&ha->smp_lock);
gdth_enable_int(hanum);
#endif /* !__ia64__ */
}
@@ -4686,7 +4363,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
ha->pccb = CMDDATA(shp);
ha->ccb_phys = 0L;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+
ha->pdev = NULL;
ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
&scratch_dma_handle);
@@ -4703,22 +4380,6 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
ha->ccb_phys =
pci_map_single(ha->pdev,ha->pccb,
sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
-#else
- ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
- if (ha->pscratch)
- ha->scratch_phys = virt_to_bus(ha->pscratch);
- ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA);
- if (ha->pmsg)
- ha->msg_phys = virt_to_bus(ha->pmsg);
-#ifdef INT_COAL
- ha->coal_stat =
- scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS,
- GFP_ATOMIC | GFP_DMA);
- if (ha->coal_stat)
- ha->coal_stat_phys = virt_to_bus(ha->coal_stat);
-#endif
- ha->ccb_phys = virt_to_bus(ha->pccb);
-#endif
ha->scratch_busy = FALSE;
ha->req_first = NULL;
ha->tid_cnt = MAX_HDRIVES;
@@ -4733,7 +4394,6 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
printk("GDT-EISA: Error during device scan\n");
--gdth_ctr_count;
--gdth_ctr_vcount;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#ifdef INT_COAL
if (ha->coal_stat)
pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
@@ -4749,17 +4409,6 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
if (ha->ccb_phys)
pci_unmap_single(ha->pdev,ha->ccb_phys,
sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
-#else
-#ifdef INT_COAL
- if (ha->coal_stat)
- scsi_init_free((void *)ha->coal_stat,
- sizeof(gdth_coal_status) * MAXOFFSETS);
-#endif
- if (ha->pscratch)
- scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
- if (ha->pmsg)
- scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
-#endif
free_irq(ha->irq,ha);
scsi_unregister(shp);
continue;
@@ -4768,14 +4417,13 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
hdr_channel = ha->bus_cnt;
ha->virt_bus = hdr_channel;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \
LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
shp->highmem_io = 0;
#endif
if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT)
shp->max_cmd_len = 16;
-#endif
+
shp->max_id = ha->tid_cnt;
shp->max_lun = MAXLUN;
shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
@@ -4793,7 +4441,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
}
}
- GDTH_INIT_LOCK_HA(ha);
+ spin_lock_init(&ha->smp_lock);
gdth_enable_int(hanum);
}
}
@@ -4841,7 +4489,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
ha->pccb = CMDDATA(shp);
ha->ccb_phys = 0L;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+
ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH,
&scratch_dma_handle);
ha->scratch_phys = scratch_dma_handle;
@@ -4854,21 +4502,6 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
MAXOFFSETS, &scratch_dma_handle);
ha->coal_stat_phys = scratch_dma_handle;
#endif
-#else
- ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
- if (ha->pscratch)
- ha->scratch_phys = virt_to_bus(ha->pscratch);
- ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA);
- if (ha->pmsg)
- ha->msg_phys = virt_to_bus(ha->pmsg);
-#ifdef INT_COAL
- ha->coal_stat =
- scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS,
- GFP_ATOMIC | GFP_DMA);
- if (ha->coal_stat)
- ha->coal_stat_phys = virt_to_bus(ha->coal_stat);
-#endif
-#endif
ha->scratch_busy = FALSE;
ha->req_first = NULL;
ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES;
@@ -4887,7 +4520,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
hdr_channel = ha->bus_cnt;
ha->virt_bus = hdr_channel;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
scsi_set_device(shp, &pcistr[ctr].pdev->dev);
#else
@@ -4909,14 +4542,12 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
err = TRUE;
}
}
-#endif
}
if (err) {
printk("GDT-PCI %d: Error during device scan\n", hanum);
--gdth_ctr_count;
--gdth_ctr_vcount;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#ifdef INT_COAL
if (ha->coal_stat)
pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
@@ -4929,17 +4560,6 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
if (ha->pmsg)
pci_free_consistent(ha->pdev, sizeof(gdth_msg_str),
ha->pmsg, ha->msg_phys);
-#else
-#ifdef INT_COAL
- if (ha->coal_stat)
- scsi_init_free((void *)ha->coal_stat,
- sizeof(gdth_coal_status) * MAXOFFSETS);
-#endif
- if (ha->pscratch)
- scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
- if (ha->pmsg)
- scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
-#endif
free_irq(ha->irq,ha);
scsi_unregister(shp);
continue;
@@ -4962,8 +4582,7 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
}
}
-
- GDTH_INIT_LOCK_HA(ha);
+ spin_lock_init(&ha->smp_lock);
gdth_enable_int(hanum);
}
@@ -4994,12 +4613,10 @@ int gdth_release(struct Scsi_Host *shp)
if (NUMDATA(shp)->busnum == 0) {
hanum = NUMDATA(shp)->hanum;
ha = HADATA(gdth_ctr_tab[hanum]);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
if (ha->sdev) {
scsi_free_host_dev(ha->sdev);
ha->sdev = NULL;
}
-#endif
gdth_flush(hanum);
if (shp->irq) {
@@ -5010,7 +4627,6 @@ int gdth_release(struct Scsi_Host *shp)
free_dma(shp->dma_channel);
}
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#ifdef INT_COAL
if (ha->coal_stat)
pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
@@ -5025,17 +4641,6 @@ int gdth_release(struct Scsi_Host *shp)
if (ha->ccb_phys)
pci_unmap_single(ha->pdev,ha->ccb_phys,
sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
-#else
-#ifdef INT_COAL
- if (ha->coal_stat)
- scsi_init_free((void *)ha->coal_stat,
- sizeof(gdth_coal_status) * MAXOFFSETS);
-#endif
- if (ha->pscratch)
- scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
- if (ha->pmsg)
- scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
-#endif
gdth_ctr_released++;
TRACE2(("gdth_release(): HA %d of %d\n",
gdth_ctr_released, gdth_ctr_count));
@@ -5098,21 +4703,6 @@ const char *gdth_info(struct Scsi_Host *shp)
return ((const char *)ha->binfo.type_string);
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-/* old error handling */
-int gdth_abort(Scsi_Cmnd *scp)
-{
- TRACE2(("gdth_abort() reason %d\n",scp->abort_reason));
- return SCSI_ABORT_SNOOZE;
-}
-
-int gdth_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
-{
- TRACE2(("gdth_reset()\n"));
- return SCSI_RESET_PUNT;
-}
-#endif
-
/* new error handling */
int gdth_eh_abort(Scsi_Cmnd *scp)
{
@@ -5135,33 +4725,25 @@ int gdth_eh_bus_reset(Scsi_Cmnd *scp)
unchar b;
TRACE2(("gdth_eh_bus_reset()\n"));
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+
hanum = NUMDATA(scp->device->host)->hanum;
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
-#else
- hanum = NUMDATA(scp->host)->hanum;
- b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
-#endif
ha = HADATA(gdth_ctr_tab[hanum]);
/* clear command tab */
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
for (i = 0; i < GDTH_MAXCMDS; ++i) {
cmnd = ha->cmd_tab[i].cmnd;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
if (!SPECIAL_SCP(cmnd) && cmnd->device->channel == b)
-#else
- if (!SPECIAL_SCP(cmnd) && cmnd->channel == b)
-#endif
ha->cmd_tab[i].cmnd = UNUSED_CMND;
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
if (b == ha->virt_bus) {
/* host drives */
for (i = 0; i < MAX_HDRIVES; ++i) {
if (ha->hdr[i].present) {
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
gdth_polling = TRUE;
while (gdth_test_busy(hanum))
gdth_delay(0);
@@ -5169,12 +4751,12 @@ int gdth_eh_bus_reset(Scsi_Cmnd *scp)
GDT_CLUST_RESET, i, 0, 0))
ha->hdr[i].cluster_type &= ~CLUSTER_RESERVED;
gdth_polling = FALSE;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
}
} else {
/* raw devices */
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
for (i = 0; i < MAXID; ++i)
ha->raw[BUS_L2P(ha,b)].io_cnt[i] = 0;
gdth_polling = TRUE;
@@ -5183,7 +4765,7 @@ int gdth_eh_bus_reset(Scsi_Cmnd *scp)
gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS,
BUS_L2P(ha,b), 0, 0);
gdth_polling = FALSE;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
return SUCCESS;
}
@@ -5249,11 +4831,8 @@ int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
scp->SCp.sent_command = -1;
scp->SCp.Status = GDTH_MAP_NONE;
scp->SCp.buffer = (struct scatterlist *)NULL;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+
hanum = NUMDATA(scp->device->host)->hanum;
-#else
- hanum = NUMDATA(scp->host)->hanum;
-#endif
#ifdef GDTH_STATISTICS
++act_ios;
#endif
@@ -5270,7 +4849,6 @@ int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
static int gdth_open(struct inode *inode, struct file *filep)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
gdth_ha_str *ha;
int i;
@@ -5279,7 +4857,6 @@ static int gdth_open(struct inode *inode, struct file *filep)
if (!ha->sdev)
ha->sdev = scsi_get_host_dev(gdth_ctr_tab[i]);
}
-#endif
TRACE(("gdth_open()\n"));
return 0;
@@ -5311,10 +4888,10 @@ static int ioc_event(void __user *arg)
evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync);
else
evt.event.event_data.size=sizeof(evt.event.event_data.eu.async);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
gdth_store_event(ha, evt.event.event_source, evt.event.event_idx,
&evt.event.event_data);
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
} else if (evt.erase == 0xfe) {
gdth_clear_events();
} else if (evt.erase == 0) {
@@ -5344,15 +4921,15 @@ static int ioc_lockdrv(void __user *arg)
if (j >= MAX_HDRIVES || !ha->hdr[j].present)
continue;
if (ldrv.lock) {
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->hdr[j].lock = 1;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j);
gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j);
} else {
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->hdr[j].lock = 0;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j);
gdth_next(ldrv.ionode);
}
@@ -5367,11 +4944,9 @@ static int ioc_resetdrv(void __user *arg, char *cmnd)
int hanum;
gdth_ha_str *ha;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- Scsi_Request *srp;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- Scsi_Cmnd *scp;
+ Scsi_Request *srp;
#else
- Scsi_Cmnd scp;
+ Scsi_Cmnd *scp;
#endif
if (copy_from_user(&res, arg, sizeof(gdth_ioctl_reset)) ||
@@ -5398,7 +4973,7 @@ static int ioc_resetdrv(void __user *arg, char *cmnd)
gdth_do_req(srp, &cmd, cmnd, 30);
res.status = (ushort)srp->sr_command->SCp.Status;
scsi_release_request(srp);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scp = scsi_allocate_device(ha->sdev, 1, FALSE);
if (!scp)
return -ENOMEM;
@@ -5407,15 +4982,8 @@ static int ioc_resetdrv(void __user *arg, char *cmnd)
gdth_do_cmd(scp, &cmd, cmnd, 30);
res.status = (ushort)scp->SCp.Status;
scsi_release_command(scp);
-#else
- memset(&ha->sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
- ha->sdev.id = scp.target = ha->sdev.host->this_id;
- scp.device = &ha->sdev;
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
- res.status = (ushort)scp.SCp.Status;
#endif
+
if (copy_to_user(arg, &res, sizeof(gdth_ioctl_reset)))
return -EFAULT;
return 0;
@@ -5430,10 +4998,8 @@ static int ioc_general(void __user *arg, char *cmnd)
gdth_ha_str *ha;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *srp;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- Scsi_Cmnd *scp;
#else
- Scsi_Cmnd scp;
+ Scsi_Cmnd *scp;
#endif
if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)) ||
@@ -5536,7 +5102,7 @@ static int ioc_general(void __user *arg, char *cmnd)
gen.status = srp->sr_command->SCp.Status;
gen.info = srp->sr_command->SCp.Message;
scsi_release_request(srp);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scp = scsi_allocate_device(ha->sdev, 1, FALSE);
if (!scp)
return -ENOMEM;
@@ -5546,15 +5112,6 @@ static int ioc_general(void __user *arg, char *cmnd)
gen.status = scp->SCp.Status;
gen.info = scp->SCp.Message;
scsi_release_command(scp);
-#else
- memset(&ha->sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
- ha->sdev.id = scp.target = ha->sdev.host->this_id;
- scp.device = &ha->sdev;
- gdth_do_cmd(&scp, &gen.command, cmnd, gen.timeout);
- gen.status = scp.SCp.Status;
- gen.info = scp.SCp.Message;
#endif
if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf,
@@ -5573,185 +5130,183 @@ static int ioc_general(void __user *arg, char *cmnd)
static int ioc_hdrlist(void __user *arg, char *cmnd)
{
- gdth_ioctl_rescan rsc;
- gdth_cmd_str cmd;
+ gdth_ioctl_rescan *rsc;
+ gdth_cmd_str *cmd;
gdth_ha_str *ha;
unchar i;
- int hanum;
+ int hanum, rc = -ENOMEM;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *srp;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- Scsi_Cmnd *scp;
#else
- Scsi_Cmnd scp;
+ Scsi_Cmnd *scp;
#endif
- if (copy_from_user(&rsc, arg, sizeof(gdth_ioctl_rescan)) ||
- rsc.ionode >= gdth_ctr_count)
- return -EFAULT;
- hanum = rsc.ionode;
+ rsc = kmalloc(sizeof(*rsc), GFP_KERNEL);
+ cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!rsc || !cmd)
+ goto free_fail;
+
+ if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
+ rsc->ionode >= gdth_ctr_count) {
+ rc = -EFAULT;
+ goto free_fail;
+ }
+ hanum = rsc->ionode;
ha = HADATA(gdth_ctr_tab[hanum]);
- memset(&cmd, 0, sizeof(gdth_cmd_str));
+ memset(cmd, 0, sizeof(gdth_cmd_str));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
srp = scsi_allocate_request(ha->sdev, GFP_KERNEL);
if (!srp)
- return -ENOMEM;
+ goto free_fail;
srp->sr_cmd_len = 12;
srp->sr_use_sg = 0;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scp = scsi_allocate_device(ha->sdev, 1, FALSE);
if (!scp)
- return -ENOMEM;
+ goto free_fail;
scp->cmd_len = 12;
scp->use_sg = 0;
-#else
- memset(&ha->sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
- ha->sdev.id = scp.target = ha->sdev.host->this_id;
- scp.device = &ha->sdev;
#endif
for (i = 0; i < MAX_HDRIVES; ++i) {
if (!ha->hdr[i].present) {
- rsc.hdr_list[i].bus = 0xff;
+ rsc->hdr_list[i].bus = 0xff;
continue;
}
- rsc.hdr_list[i].bus = ha->virt_bus;
- rsc.hdr_list[i].target = i;
- rsc.hdr_list[i].lun = 0;
- rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
+ rsc->hdr_list[i].bus = ha->virt_bus;
+ rsc->hdr_list[i].target = i;
+ rsc->hdr_list[i].lun = 0;
+ rsc->hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) {
- cmd.Service = CACHESERVICE;
- cmd.OpCode = GDT_CLUST_INFO;
+ cmd->Service = CACHESERVICE;
+ cmd->OpCode = GDT_CLUST_INFO;
if (ha->cache_feat & GDT_64BIT)
- cmd.u.cache64.DeviceNo = i;
+ cmd->u.cache64.DeviceNo = i;
else
- cmd.u.cache.DeviceNo = i;
+ cmd->u.cache.DeviceNo = i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(srp, &cmd, cmnd, 30);
+ gdth_do_req(srp, cmd, cmnd, 30);
if (srp->sr_command->SCp.Status == S_OK)
- rsc.hdr_list[i].cluster_type = srp->sr_command->SCp.Message;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &cmd, cmnd, 30);
- if (scp->SCp.Status == S_OK)
- rsc.hdr_list[i].cluster_type = scp->SCp.Message;
+ rsc->hdr_list[i].cluster_type = srp->sr_command->SCp.Message;
#else
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
- if (scp.SCp.Status == S_OK)
- rsc.hdr_list[i].cluster_type = scp.SCp.Message;
+ gdth_do_cmd(scp, cmd, cmnd, 30);
+ if (scp->SCp.Status == S_OK)
+ rsc->hdr_list[i].cluster_type = scp->SCp.Message;
#endif
}
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
scsi_release_request(srp);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scsi_release_command(scp);
#endif
- if (copy_to_user(arg, &rsc, sizeof(gdth_ioctl_rescan)))
- return -EFAULT;
- return 0;
+ if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan)))
+ rc = -EFAULT;
+ else
+ rc = 0;
+
+free_fail:
+ kfree(rsc);
+ kfree(cmd);
+ return rc;
}
static int ioc_rescan(void __user *arg, char *cmnd)
{
- gdth_ioctl_rescan rsc;
- gdth_cmd_str cmd;
+ gdth_ioctl_rescan *rsc;
+ gdth_cmd_str *cmd;
ushort i, status, hdr_cnt;
ulong32 info;
int hanum, cyls, hds, secs;
+ int rc = -ENOMEM;
ulong flags;
gdth_ha_str *ha;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *srp;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- Scsi_Cmnd *scp;
#else
- Scsi_Cmnd scp;
+ Scsi_Cmnd *scp;
#endif
-
- if (copy_from_user(&rsc, arg, sizeof(gdth_ioctl_rescan)) ||
- rsc.ionode >= gdth_ctr_count)
- return -EFAULT;
- hanum = rsc.ionode;
+
+ rsc = kmalloc(sizeof(*rsc), GFP_KERNEL);
+ cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd || !rsc)
+ goto free_fail;
+
+ if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
+ rsc->ionode >= gdth_ctr_count) {
+ rc = -EFAULT;
+ goto free_fail;
+ }
+ hanum = rsc->ionode;
ha = HADATA(gdth_ctr_tab[hanum]);
- memset(&cmd, 0, sizeof(gdth_cmd_str));
+ memset(cmd, 0, sizeof(gdth_cmd_str));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
srp = scsi_allocate_request(ha->sdev, GFP_KERNEL);
if (!srp)
- return -ENOMEM;
+ goto free_fail;
srp->sr_cmd_len = 12;
srp->sr_use_sg = 0;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scp = scsi_allocate_device(ha->sdev, 1, FALSE);
if (!scp)
- return -ENOMEM;
+ goto free_fail;
scp->cmd_len = 12;
scp->use_sg = 0;
-#else
- memset(&ha->sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
- ha->sdev.id = scp.target = ha->sdev.host->this_id;
- scp.device = &ha->sdev;
#endif
- if (rsc.flag == 0) {
+ if (rsc->flag == 0) {
/* old method: re-init. cache service */
- cmd.Service = CACHESERVICE;
+ cmd->Service = CACHESERVICE;
if (ha->cache_feat & GDT_64BIT) {
- cmd.OpCode = GDT_X_INIT_HOST;
- cmd.u.cache64.DeviceNo = LINUX_OS;
+ cmd->OpCode = GDT_X_INIT_HOST;
+ cmd->u.cache64.DeviceNo = LINUX_OS;
} else {
- cmd.OpCode = GDT_INIT;
- cmd.u.cache.DeviceNo = LINUX_OS;
+ cmd->OpCode = GDT_INIT;
+ cmd->u.cache.DeviceNo = LINUX_OS;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(srp, &cmd, cmnd, 30);
+ gdth_do_req(srp, cmd, cmnd, 30);
status = (ushort)srp->sr_command->SCp.Status;
info = (ulong32)srp->sr_command->SCp.Message;
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &cmd, cmnd, 30);
+ gdth_do_cmd(scp, cmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
#else
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
+ gdth_do_cmd(&scp, cmd, cmnd, 30);
status = (ushort)scp.SCp.Status;
info = (ulong32)scp.SCp.Message;
#endif
i = 0;
hdr_cnt = (status == S_OK ? (ushort)info : 0);
} else {
- i = rsc.hdr_no;
+ i = rsc->hdr_no;
hdr_cnt = i + 1;
}
+
for (; i < hdr_cnt && i < MAX_HDRIVES; ++i) {
- cmd.Service = CACHESERVICE;
- cmd.OpCode = GDT_INFO;
+ cmd->Service = CACHESERVICE;
+ cmd->OpCode = GDT_INFO;
if (ha->cache_feat & GDT_64BIT)
- cmd.u.cache64.DeviceNo = i;
+ cmd->u.cache64.DeviceNo = i;
else
- cmd.u.cache.DeviceNo = i;
+ cmd->u.cache.DeviceNo = i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(srp, &cmd, cmnd, 30);
+ gdth_do_req(srp, cmd, cmnd, 30);
status = (ushort)srp->sr_command->SCp.Status;
info = (ulong32)srp->sr_command->SCp.Message;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &cmd, cmnd, 30);
+#else
+ gdth_do_cmd(scp, cmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
-#else
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
- status = (ushort)scp.SCp.Status;
- info = (ulong32)scp.SCp.Message;
#endif
- GDTH_LOCK_HA(ha, flags);
- rsc.hdr_list[i].bus = ha->virt_bus;
- rsc.hdr_list[i].target = i;
- rsc.hdr_list[i].lun = 0;
+ spin_lock_irqsave(&ha->smp_lock, flags);
+ rsc->hdr_list[i].bus = ha->virt_bus;
+ rsc->hdr_list[i].target = i;
+ rsc->hdr_list[i].lun = 0;
if (status != S_OK) {
ha->hdr[i].present = FALSE;
} else {
@@ -5765,7 +5320,7 @@ static int ioc_rescan(void __user *arg, char *cmnd)
/* round size */
ha->hdr[i].size = cyls * hds * secs;
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
if (status != S_OK)
continue;
@@ -5773,99 +5328,87 @@ static int ioc_rescan(void __user *arg, char *cmnd)
/* but we need ha->info2, not yet stored in scp->SCp */
/* devtype, cluster info, R/W attribs */
- cmd.Service = CACHESERVICE;
- cmd.OpCode = GDT_DEVTYPE;
+ cmd->Service = CACHESERVICE;
+ cmd->OpCode = GDT_DEVTYPE;
if (ha->cache_feat & GDT_64BIT)
- cmd.u.cache64.DeviceNo = i;
+ cmd->u.cache64.DeviceNo = i;
else
- cmd.u.cache.DeviceNo = i;
+ cmd->u.cache.DeviceNo = i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(srp, &cmd, cmnd, 30);
+ gdth_do_req(srp, cmd, cmnd, 30);
status = (ushort)srp->sr_command->SCp.Status;
info = (ulong32)srp->sr_command->SCp.Message;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &cmd, cmnd, 30);
+#else
+ gdth_do_cmd(scp, cmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
-#else
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
- status = (ushort)scp.SCp.Status;
- info = (ulong32)scp.SCp.Message;
#endif
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0);
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
- cmd.Service = CACHESERVICE;
- cmd.OpCode = GDT_CLUST_INFO;
+ cmd->Service = CACHESERVICE;
+ cmd->OpCode = GDT_CLUST_INFO;
if (ha->cache_feat & GDT_64BIT)
- cmd.u.cache64.DeviceNo = i;
+ cmd->u.cache64.DeviceNo = i;
else
- cmd.u.cache.DeviceNo = i;
+ cmd->u.cache.DeviceNo = i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(srp, &cmd, cmnd, 30);
+ gdth_do_req(srp, cmd, cmnd, 30);
status = (ushort)srp->sr_command->SCp.Status;
info = (ulong32)srp->sr_command->SCp.Message;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &cmd, cmnd, 30);
+#else
+ gdth_do_cmd(scp, cmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
-#else
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
- status = (ushort)scp.SCp.Status;
- info = (ulong32)scp.SCp.Message;
#endif
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->hdr[i].cluster_type =
((status == S_OK && !shared_access) ? (ushort)info : 0);
- GDTH_UNLOCK_HA(ha, flags);
- rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
+ rsc->hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
- cmd.Service = CACHESERVICE;
- cmd.OpCode = GDT_RW_ATTRIBS;
+ cmd->Service = CACHESERVICE;
+ cmd->OpCode = GDT_RW_ATTRIBS;
if (ha->cache_feat & GDT_64BIT)
- cmd.u.cache64.DeviceNo = i;
+ cmd->u.cache64.DeviceNo = i;
else
- cmd.u.cache.DeviceNo = i;
+ cmd->u.cache.DeviceNo = i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(srp, &cmd, cmnd, 30);
+ gdth_do_req(srp, cmd, cmnd, 30);
status = (ushort)srp->sr_command->SCp.Status;
info = (ulong32)srp->sr_command->SCp.Message;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &cmd, cmnd, 30);
+#else
+ gdth_do_cmd(scp, cmd, cmnd, 30);
status = (ushort)scp->SCp.Status;
info = (ulong32)scp->SCp.Message;
-#else
- gdth_do_cmd(&scp, &cmd, cmnd, 30);
- status = (ushort)scp.SCp.Status;
- info = (ulong32)scp.SCp.Message;
#endif
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0);
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
scsi_release_request(srp);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scsi_release_command(scp);
#endif
- if (copy_to_user(arg, &rsc, sizeof(gdth_ioctl_rescan)))
- return -EFAULT;
- return 0;
+ if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan)))
+ rc = -EFAULT;
+ else
+ rc = 0;
+
+free_fail:
+ kfree(rsc);
+ kfree(cmd);
+ return rc;
}
static int gdth_ioctl(struct inode *inode, struct file *filep,
unsigned int cmd, unsigned long arg)
{
gdth_ha_str *ha;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Cmnd *scp;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- Scsi_Cmnd *scp;
-#else
- Scsi_Cmnd scp;
-#endif
ulong flags;
char cmnd[MAX_COMMAND_SIZE];
void __user *argp = (void __user *)arg;
@@ -5956,17 +5499,17 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
i = lchn.channel;
if (i < ha->bus_cnt) {
if (lchn.lock) {
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->raw[i].lock = 1;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
for (j = 0; j < ha->tid_cnt; ++j) {
gdth_wait_completion(lchn.ionode, i, j);
gdth_stop_timeout(lchn.ionode, i, j);
}
} else {
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ha->raw[i].lock = 0;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
for (j = 0; j < ha->tid_cnt; ++j) {
gdth_start_timeout(lchn.ionode, i, j);
gdth_next(lchn.ionode);
@@ -6004,7 +5547,7 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
rval = gdth_eh_bus_reset(scp);
res.status = (rval == SUCCESS ? S_OK : S_GENERR);
scsi_put_command(scp);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scp = scsi_allocate_device(ha->sdev, 1, FALSE);
if (!scp)
return -ENOMEM;
@@ -6014,15 +5557,6 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
rval = gdth_eh_bus_reset(scp);
res.status = (rval == SUCCESS ? S_OK : S_GENERR);
scsi_release_command(scp);
-#else
- memset(&ha->sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
- ha->sdev.id = scp.target = ha->sdev.host->this_id;
- scp.device = &ha->sdev;
- scp.channel = virt_ctr ? 0 : res.number;
- rval = gdth_eh_bus_reset(&scp);
- res.status = (rval == SUCCESS ? S_OK : S_GENERR);
#endif
if (copy_to_user(argp, &res, sizeof(gdth_ioctl_reset)))
return -EFAULT;
@@ -6047,14 +5581,10 @@ static void gdth_flush(int hanum)
gdth_cmd_str gdtcmd;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *srp;
- Scsi_Device *sdev;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- Scsi_Cmnd *scp;
- Scsi_Device *sdev;
#else
- Scsi_Cmnd scp;
- Scsi_Device sdev;
+ Scsi_Cmnd *scp;
#endif
+ Scsi_Device *sdev;
char cmnd[MAX_COMMAND_SIZE];
memset(cmnd, 0xff, MAX_COMMAND_SIZE);
@@ -6068,19 +5598,13 @@ static void gdth_flush(int hanum)
return;
srp->sr_cmd_len = 12;
srp->sr_use_sg = 0;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
scp = scsi_allocate_device(sdev, 1, FALSE);
if (!scp)
return;
scp->cmd_len = 12;
scp->use_sg = 0;
-#else
- memset(&sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- sdev.host = scp.host = gdth_ctr_tab[hanum];
- sdev.id = scp.target = sdev.host->this_id;
- scp.device = &sdev;
#endif
for (i = 0; i < MAX_HDRIVES; ++i) {
@@ -6100,17 +5624,15 @@ static void gdth_flush(int hanum)
TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
gdth_do_req(srp, &gdtcmd, cmnd, 30);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+ gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
#endif
}
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
scsi_release_request(srp);
scsi_free_host_dev(sdev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scsi_release_command(scp);
scsi_free_host_dev(sdev);
#endif
@@ -6125,12 +5647,9 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *srp;
Scsi_Device *sdev;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
Scsi_Cmnd *scp;
Scsi_Device *sdev;
-#else
- Scsi_Cmnd scp;
- Scsi_Device sdev;
#endif
char cmnd[MAX_COMMAND_SIZE];
#endif
@@ -6162,7 +5681,7 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
gdth_do_req(srp, &gdtcmd, cmnd, 10);
scsi_release_request(srp);
scsi_free_host_dev(sdev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
scp = scsi_allocate_device(sdev, 1, FALSE);
if (!scp) {
@@ -6174,13 +5693,6 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
gdth_do_cmd(scp, &gdtcmd, cmnd, 10);
scsi_release_command(scp);
scsi_free_host_dev(sdev);
-#else
- memset(&sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- sdev.host = scp.host = gdth_ctr_tab[hanum];
- sdev.id = scp.target = sdev.host->this_id;
- scp.device = &sdev;
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 10);
#endif
#endif
}
@@ -6193,19 +5705,6 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
return NOTIFY_OK;
}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) && !defined(MODULE)
-
-GDTH_INITFUNC(void, gdth_setup(char *str,int *ints))
-{
- TRACE2(("gdth_setup() str %s ints[0] %d\n",
- str ? str:"NULL", ints ? ints[0]:0));
- internal_setup(str, ints);
-}
-
-#else
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
static Scsi_Host_Template driver_template = {
.proc_name = "gdth",
.proc_info = gdth_proc_info,
@@ -6232,13 +5731,8 @@ static Scsi_Host_Template driver_template = {
#endif
#endif
};
-#else
-static Scsi_Host_Template driver_template = GDTH;
-#endif
#include "scsi_module.c"
#ifndef MODULE
__setup("gdth=", option_setup);
#endif
-
-#endif
diff --git a/drivers/scsi/gdth_kcompat.h b/drivers/scsi/gdth_kcompat.h
new file mode 100644
index 000000000000..e6cf0edfa0ca
--- /dev/null
+++ b/drivers/scsi/gdth_kcompat.h
@@ -0,0 +1,21 @@
+
+
+#ifndef IRQ_HANDLED
+typedef void irqreturn_t;
+#define IRQ_NONE
+#define IRQ_HANDLED
+#endif
+
+#ifndef MODULE_LICENSE
+#define MODULE_LICENSE(x)
+#endif
+
+#ifndef SERVICE_ACTION_IN
+#define SERVICE_ACTION_IN 0x9e
+#endif
+#ifndef READ_16
+#define READ_16 0x88
+#endif
+#ifndef WRITE_16
+#define WRITE_16 0x8a
+#endif
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index e37faaaeb0e5..1bd02f8d1e6a 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -2,9 +2,7 @@
* $Id: gdth_proc.c,v 1.42 2004/03/05 15:50:20 achim Exp $
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
#include <linux/completion.h>
-#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
int gdth_proc_info(struct Scsi_Host *host, char *buffer,char **start,off_t offset,int length,
@@ -57,12 +55,9 @@ static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *scp;
Scsi_Device *sdev;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
Scsi_Cmnd *scp;
Scsi_Device *sdev;
-#else
- Scsi_Cmnd scp;
- Scsi_Device sdev;
#endif
TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum));
@@ -73,19 +68,13 @@ static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
return -ENOMEM;
scp->sr_cmd_len = 12;
scp->sr_use_sg = 0;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
sdev = scsi_get_host_dev(host);
scp = scsi_allocate_device(sdev, 1, FALSE);
if (!scp)
return -ENOMEM;
scp->cmd_len = 12;
scp->use_sg = 0;
-#else
- memset(&sdev,0,sizeof(Scsi_Device));
- memset(&scp, 0,sizeof(Scsi_Cmnd));
- sdev.host = scp.host = host;
- sdev.id = scp.target = sdev.host->this_id;
- scp.device = &sdev;
#endif
if (length >= 4) {
@@ -98,7 +87,7 @@ static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
scsi_release_request(scp);
scsi_free_host_dev(sdev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scsi_release_command(scp);
scsi_free_host_dev(sdev);
#endif
@@ -107,10 +96,8 @@ static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
#else
-static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
+static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
#endif
{
int orig_length, drive, wb_mode;
@@ -161,10 +148,8 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
gdth_do_req(scp, &gdtcmd, cmnd, 30);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+ gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
#endif
}
}
@@ -219,10 +204,8 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
pcpar->write_back = wb_mode==1 ? 0:1;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
gdth_do_req(scp, &gdtcmd, cmnd, 30);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+ gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
#endif
gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr);
printk("Done.\n");
@@ -243,18 +226,16 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
int no_mdrv = 0, drv_no, is_mirr;
ulong32 cnt;
ulong64 paddr;
+ int rc = -ENOMEM;
- gdth_cmd_str gdtcmd;
- gdth_evt_str estr;
+ gdth_cmd_str *gdtcmd;
+ gdth_evt_str *estr;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
Scsi_Request *scp;
Scsi_Device *sdev;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
Scsi_Cmnd *scp;
Scsi_Device *sdev;
-#else
- Scsi_Cmnd scp;
- Scsi_Device sdev;
#endif
char hrec[161];
struct timeval tv;
@@ -266,10 +247,15 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
gdth_defcnt_str *pdef;
gdth_cdrinfo_str *pcdi;
gdth_hget_str *phg;
-
char cmnd[MAX_COMMAND_SIZE];
+
+ gdtcmd = kmalloc(sizeof(*gdtcmd), GFP_KERNEL);
+ estr = kmalloc(sizeof(*estr), GFP_KERNEL);
+ if (!gdtcmd || !estr)
+ goto free_fail;
+
memset(cmnd, 0xff, 12);
- memset(&gdtcmd, 0, sizeof(gdth_cmd_str));
+ memset(gdtcmd, 0, sizeof(gdth_cmd_str));
TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum));
ha = HADATA(gdth_ctr_tab[hanum]);
@@ -278,14 +264,14 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
sdev = scsi_get_host_dev(host);
scp = scsi_allocate_request(sdev, GFP_KERNEL);
if (!scp)
- return -ENOMEM;
+ goto free_fail;
scp->sr_cmd_len = 12;
scp->sr_use_sg = 0;
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
sdev = scsi_get_host_dev(host);
scp = scsi_allocate_device(sdev, 1, FALSE);
if (!scp)
- return -ENOMEM;
+ goto free_fail;
scp->cmd_len = 12;
scp->use_sg = 0;
#else
@@ -387,12 +373,12 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
/* 2.a statistics (and retries/reassigns) */
TRACE2(("pdr_statistics() chn %d\n",i));
pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4);
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_IOCTL;
- gdtcmd.u.ioctl.p_param = paddr + GDTH_SCRATCH/4;
- gdtcmd.u.ioctl.param_size = 3*GDTH_SCRATCH/4;
- gdtcmd.u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN;
- gdtcmd.u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL;
+ gdtcmd->Service = CACHESERVICE;
+ gdtcmd->OpCode = GDT_IOCTL;
+ gdtcmd->u.ioctl.p_param = paddr + GDTH_SCRATCH/4;
+ gdtcmd->u.ioctl.param_size = 3*GDTH_SCRATCH/4;
+ gdtcmd->u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN;
+ gdtcmd->u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL;
pds->bid = ha->raw[i].local_no;
pds->first = 0;
pds->entries = ha->raw[i].pdev_cnt;
@@ -401,14 +387,11 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
if (pds->entries > cnt)
pds->entries = cnt;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(scp, &gdtcmd, cmnd, 30);
+ gdth_do_req(scp, gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status != S_OK)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
- if (scp->SCp.Status != S_OK)
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
- if (scp.SCp.Status != S_OK)
+ gdth_do_cmd(scp, gdtcmd, cmnd, 30);
+ if (scp->SCp.Status != S_OK)
#endif
{
pds->count = 0;
@@ -420,22 +403,19 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
TRACE2(("scsi_drv_info() chn %d dev %d\n",
i, ha->raw[i].id_list[j]));
pdi = (gdth_diskinfo_str *)buf;
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_IOCTL;
- gdtcmd.u.ioctl.p_param = paddr;
- gdtcmd.u.ioctl.param_size = sizeof(gdth_diskinfo_str);
- gdtcmd.u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
- gdtcmd.u.ioctl.channel =
+ gdtcmd->Service = CACHESERVICE;
+ gdtcmd->OpCode = GDT_IOCTL;
+ gdtcmd->u.ioctl.p_param = paddr;
+ gdtcmd->u.ioctl.param_size = sizeof(gdth_diskinfo_str);
+ gdtcmd->u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
+ gdtcmd->u.ioctl.channel =
ha->raw[i].address | ha->raw[i].id_list[j];
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(scp, &gdtcmd, cmnd, 30);
+ gdth_do_req(scp, gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status == S_OK)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
- if (scp->SCp.Status == S_OK)
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
- if (scp.SCp.Status == S_OK)
+ gdth_do_cmd(scp, gdtcmd, cmnd, 30);
+ if (scp->SCp.Status == S_OK)
#endif
{
strncpy(hrec,pdi->vendor,8);
@@ -478,23 +458,20 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
TRACE2(("scsi_drv_defcnt() chn %d dev %d\n",
i, ha->raw[i].id_list[j]));
pdef = (gdth_defcnt_str *)buf;
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_IOCTL;
- gdtcmd.u.ioctl.p_param = paddr;
- gdtcmd.u.ioctl.param_size = sizeof(gdth_defcnt_str);
- gdtcmd.u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN;
- gdtcmd.u.ioctl.channel =
+ gdtcmd->Service = CACHESERVICE;
+ gdtcmd->OpCode = GDT_IOCTL;
+ gdtcmd->u.ioctl.p_param = paddr;
+ gdtcmd->u.ioctl.param_size = sizeof(gdth_defcnt_str);
+ gdtcmd->u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN;
+ gdtcmd->u.ioctl.channel =
ha->raw[i].address | ha->raw[i].id_list[j];
pdef->sddc_type = 0x08;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(scp, &gdtcmd, cmnd, 30);
+ gdth_do_req(scp, gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status == S_OK)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
- if (scp->SCp.Status == S_OK)
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
- if (scp.SCp.Status == S_OK)
+ gdth_do_cmd(scp, gdtcmd, cmnd, 30);
+ if (scp->SCp.Status == S_OK)
#endif
{
size = sprintf(buffer+len,
@@ -536,21 +513,18 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
/* 3.a log. drive info */
TRACE2(("cache_drv_info() drive no %d\n",drv_no));
pcdi = (gdth_cdrinfo_str *)buf;
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_IOCTL;
- gdtcmd.u.ioctl.p_param = paddr;
- gdtcmd.u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
- gdtcmd.u.ioctl.subfunc = CACHE_DRV_INFO;
- gdtcmd.u.ioctl.channel = drv_no;
+ gdtcmd->Service = CACHESERVICE;
+ gdtcmd->OpCode = GDT_IOCTL;
+ gdtcmd->u.ioctl.p_param = paddr;
+ gdtcmd->u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
+ gdtcmd->u.ioctl.subfunc = CACHE_DRV_INFO;
+ gdtcmd->u.ioctl.channel = drv_no;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(scp, &gdtcmd, cmnd, 30);
+ gdth_do_req(scp, gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status != S_OK)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
- if (scp->SCp.Status != S_OK)
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
- if (scp.SCp.Status != S_OK)
+ gdth_do_cmd(scp, gdtcmd, cmnd, 30);
+ if (scp->SCp.Status != S_OK)
#endif
{
break;
@@ -649,21 +623,18 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
/* 4.a array drive info */
TRACE2(("array_info() drive no %d\n",i));
pai = (gdth_arrayinf_str *)buf;
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_IOCTL;
- gdtcmd.u.ioctl.p_param = paddr;
- gdtcmd.u.ioctl.param_size = sizeof(gdth_arrayinf_str);
- gdtcmd.u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
- gdtcmd.u.ioctl.channel = i;
+ gdtcmd->Service = CACHESERVICE;
+ gdtcmd->OpCode = GDT_IOCTL;
+ gdtcmd->u.ioctl.p_param = paddr;
+ gdtcmd->u.ioctl.param_size = sizeof(gdth_arrayinf_str);
+ gdtcmd->u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
+ gdtcmd->u.ioctl.channel = i;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(scp, &gdtcmd, cmnd, 30);
+ gdth_do_req(scp, gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status == S_OK)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
- if (scp->SCp.Status == S_OK)
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
- if (scp.SCp.Status == S_OK)
+ gdth_do_cmd(scp, gdtcmd, cmnd, 30);
+ if (scp->SCp.Status == S_OK)
#endif
{
if (pai->ai_state == 0)
@@ -731,23 +702,20 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
/* 5.a get host drive list */
TRACE2(("host_get() drv_no %d\n",i));
phg = (gdth_hget_str *)buf;
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_IOCTL;
- gdtcmd.u.ioctl.p_param = paddr;
- gdtcmd.u.ioctl.param_size = sizeof(gdth_hget_str);
- gdtcmd.u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN;
- gdtcmd.u.ioctl.channel = i;
+ gdtcmd->Service = CACHESERVICE;
+ gdtcmd->OpCode = GDT_IOCTL;
+ gdtcmd->u.ioctl.p_param = paddr;
+ gdtcmd->u.ioctl.param_size = sizeof(gdth_hget_str);
+ gdtcmd->u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN;
+ gdtcmd->u.ioctl.channel = i;
phg->entries = MAX_HDRIVES;
phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- gdth_do_req(scp, &gdtcmd, cmnd, 30);
+ gdth_do_req(scp, gdtcmd, cmnd, 30);
if (scp->sr_command->SCp.Status != S_OK)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
- if (scp->SCp.Status != S_OK)
#else
- gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
- if (scp.SCp.Status != S_OK)
+ gdth_do_cmd(scp, gdtcmd, cmnd, 30);
+ if (scp->SCp.Status != S_OK)
#endif
{
ha->hdr[i].ldr_no = i;
@@ -799,14 +767,14 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
len += size; pos = begin + len;
for (id = -1;;) {
- id = gdth_read_event(ha, id, &estr);
- if (estr.event_source == 0)
+ id = gdth_read_event(ha, id, estr);
+ if (estr->event_source == 0)
break;
- if (estr.event_data.eu.driver.ionode == hanum &&
- estr.event_source == ES_ASYNC) {
- gdth_log_event(&estr.event_data, hrec);
+ if (estr->event_data.eu.driver.ionode == hanum &&
+ estr->event_source == ES_ASYNC) {
+ gdth_log_event(&estr->event_data, hrec);
do_gettimeofday(&tv);
- sec = (int)(tv.tv_sec - estr.first_stamp);
+ sec = (int)(tv.tv_sec - estr->first_stamp);
if (sec < 0) sec = 0;
size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n",
sec/3600, sec%3600/60, sec%60, hrec);
@@ -826,7 +794,7 @@ stop_output:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
scsi_release_request(scp);
scsi_free_host_dev(sdev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
scsi_release_command(scp);
scsi_free_host_dev(sdev);
#endif
@@ -836,7 +804,12 @@ stop_output:
len = length;
TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n",
len,(int)pos,(int)begin,(int)offset,length,size));
- return(len);
+ rc = len;
+
+free_fail:
+ kfree(gdtcmd);
+ kfree(estr);
+ return rc;
}
@@ -864,13 +837,7 @@ static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd,
char *cmnd, int timeout)
{
unsigned bufflen;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
DECLARE_COMPLETION(wait);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- DECLARE_MUTEX_LOCKED(sem);
-#else
- struct semaphore sem = MUTEX_LOCKED;
-#endif
TRACE2(("gdth_do_cmd()\n"));
if (gdtcmd != NULL) {
@@ -880,22 +847,11 @@ static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd,
scp->SCp.this_residual = DEFAULT_PRI;
bufflen = 0;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
+
scp->request.rq_status = RQ_SCSI_BUSY;
scp->request.waiting = &wait;
scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
wait_for_completion(&wait);
-#else
- scp->request.sem = &sem;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
- scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
-#else
- spin_lock_irq(&io_request_lock);
- scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
- spin_unlock_irq(&io_request_lock);
-#endif
- down(&sem);
-#endif
}
#endif
@@ -907,14 +863,10 @@ void gdth_scsi_done(Scsi_Cmnd *scp)
scp->request->rq_status = RQ_SCSI_DONE;
if (scp->request->waiting != NULL)
complete(scp->request->waiting);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
+#else
scp->request.rq_status = RQ_SCSI_DONE;
if (scp->request.waiting != NULL)
complete(scp->request.waiting);
-#else
- scp->request.rq_status = RQ_SCSI_DONE;
- if (scp->request.sem != NULL)
- up(scp->request.sem);
#endif
}
@@ -929,7 +881,7 @@ static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
return NULL;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
if (!ha->scratch_busy && size <= GDTH_SCRATCH) {
ha->scratch_busy = TRUE;
@@ -938,19 +890,13 @@ static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
} else if (scratch) {
ret_val = NULL;
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
dma_addr_t dma_addr;
ret_val = pci_alloc_consistent(ha->pdev, size, &dma_addr);
*paddr = dma_addr;
-#else
- ret_val = scsi_init_malloc(size, GFP_ATOMIC | GFP_DMA);
- if (ret_val)
- *paddr = virt_to_bus(ret_val);
-#endif
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
return ret_val;
}
@@ -960,19 +906,15 @@ static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr)
ulong flags;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
if (buf == ha->pscratch) {
ha->scratch_busy = FALSE;
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pci_free_consistent(ha->pdev, size, buf, paddr);
-#else
- scsi_init_free((void *)buf, size);
-#endif
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
#ifdef GDTH_IOCTL_PROC
@@ -983,14 +925,14 @@ static int gdth_ioctl_check_bin(int hanum, ushort size)
int ret_val;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
ret_val = FALSE;
if (ha->scratch_busy) {
if (((gdth_iord_str *)ha->pscratch)->size == (ulong32)size)
ret_val = TRUE;
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
return ret_val;
}
#endif
@@ -1004,36 +946,23 @@ static void gdth_wait_completion(int hanum, int busnum, int id)
unchar b, t;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
for (i = 0; i < GDTH_MAXCMDS; ++i) {
scp = ha->cmd_tab[i].cmnd;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
t = scp->device->id;
-#else
- b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
- t = scp->target;
-#endif
if (!SPECIAL_SCP(scp) && t == (unchar)id &&
b == (unchar)busnum) {
scp->SCp.have_data_in = 0;
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
while (!scp->SCp.have_data_in)
barrier();
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- GDTH_LOCK_SCSI_DONE(scp->device->host, flags);
- scp->scsi_done(scp);
- GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags);
-#else
- GDTH_LOCK_SCSI_DONE(flags);
- scp->scsi_done(scp);
- GDTH_UNLOCK_SCSI_DONE(flags);
-#endif
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
}
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
static void gdth_stop_timeout(int hanum, int busnum, int id)
@@ -1044,22 +973,17 @@ static void gdth_stop_timeout(int hanum, int busnum, int id)
unchar b, t;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
t = scp->device->id;
-#else
- b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
- t = scp->target;
-#endif
if (t == (unchar)id && b == (unchar)busnum) {
TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
}
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
static void gdth_start_timeout(int hanum, int busnum, int id)
@@ -1070,22 +994,17 @@ static void gdth_start_timeout(int hanum, int busnum, int id)
unchar b, t;
ha = HADATA(gdth_ctr_tab[hanum]);
- GDTH_LOCK_HA(ha, flags);
+ spin_lock_irqsave(&ha->smp_lock, flags);
for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
t = scp->device->id;
-#else
- b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
- t = scp->target;
-#endif
if (t == (unchar)id && b == (unchar)busnum) {
TRACE2(("gdth_start_timeout(): update_timeout()\n"));
gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual);
}
}
- GDTH_UNLOCK_HA(ha, flags);
+ spin_unlock_irqrestore(&ha->smp_lock, flags);
}
static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout)
diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h
index 5fb191625c33..295e825e2c60 100644
--- a/drivers/scsi/gdth_proc.h
+++ b/drivers/scsi/gdth_proc.h
@@ -14,14 +14,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
static void gdth_do_req(Scsi_Request *srp, gdth_cmd_str *cmd,
char *cmnd, int timeout);
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#else
static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd,
char *cmnd, int timeout);
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp);
-#else
-static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd,
- char *cmnd, int timeout);
-static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp);
#endif
static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index f8721d9f558f..e89f76e5dd53 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -87,7 +87,7 @@ static int max_channel = 3;
static int init_timeout = 5;
static int max_requests = 50;
-#define IBMVSCSI_VERSION "1.5.1"
+#define IBMVSCSI_VERSION "1.5.5"
MODULE_DESCRIPTION("IBM Virtual SCSI");
MODULE_AUTHOR("Dave Boutcher");
@@ -256,6 +256,7 @@ static void init_event_struct(struct srp_event_struct *evt_struct,
{
evt_struct->cmnd = NULL;
evt_struct->cmnd_done = NULL;
+ evt_struct->sync_srp = NULL;
evt_struct->crq.format = format;
evt_struct->crq.timeout = timeout;
evt_struct->done = done;
@@ -467,7 +468,7 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
struct ibmvscsi_host_data *hostdata)
{
- struct scsi_cmnd *cmnd = evt_struct->cmnd;
+ struct scsi_cmnd *cmnd;
u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
int rc;
@@ -479,22 +480,15 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) &&
(atomic_dec_if_positive(&hostdata->request_limit) < 0)) {
/* See if the adapter is disabled */
- if (atomic_read(&hostdata->request_limit) < 0) {
- if (cmnd)
- cmnd->result = DID_ERROR << 16;
- if (evt_struct->cmnd_done)
- evt_struct->cmnd_done(cmnd);
- unmap_cmd_data(&evt_struct->iu.srp.cmd,
- hostdata->dev);
- free_event_struct(&hostdata->pool, evt_struct);
- return 0;
- } else {
- printk("ibmvscsi: Warning, request_limit exceeded\n");
- unmap_cmd_data(&evt_struct->iu.srp.cmd,
- hostdata->dev);
- free_event_struct(&hostdata->pool, evt_struct);
- return SCSI_MLQUEUE_HOST_BUSY;
- }
+ if (atomic_read(&hostdata->request_limit) < 0)
+ goto send_error;
+
+ printk(KERN_WARNING
+ "ibmvscsi: Warning, request_limit exceeded\n");
+ unmap_cmd_data(&evt_struct->iu.srp.cmd,
+ hostdata->dev);
+ free_event_struct(&hostdata->pool, evt_struct);
+ return SCSI_MLQUEUE_HOST_BUSY;
}
/* Copy the IU into the transfer area */
@@ -511,18 +505,24 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
list_del(&evt_struct->list);
- cmnd = evt_struct->cmnd;
printk(KERN_ERR "ibmvscsi: failed to send event struct rc %d\n",
rc);
- unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
- free_event_struct(&hostdata->pool, evt_struct);
- if (cmnd)
- cmnd->result = DID_ERROR << 16;
- if (evt_struct->cmnd_done)
- evt_struct->cmnd_done(cmnd);
+ goto send_error;
}
return 0;
+
+ send_error:
+ unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
+
+ if ((cmnd = evt_struct->cmnd) != NULL) {
+ cmnd->result = DID_ERROR << 16;
+ evt_struct->cmnd_done(cmnd);
+ } else if (evt_struct->done)
+ evt_struct->done(evt_struct);
+
+ free_event_struct(&hostdata->pool, evt_struct);
+ return 0;
}
/**
@@ -537,6 +537,13 @@ static void handle_cmd_rsp(struct srp_event_struct *evt_struct)
struct srp_rsp *rsp = &evt_struct->xfer_iu->srp.rsp;
struct scsi_cmnd *cmnd = evt_struct->cmnd;
+ if (unlikely(rsp->type != SRP_RSP_TYPE)) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING
+ "ibmvscsi: bad SRP RSP type %d\n",
+ rsp->type);
+ }
+
if (cmnd) {
cmnd->result = rsp->status;
if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION)
@@ -641,11 +648,16 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct)
evt_struct->xfer_iu->mad.adapter_info.common.status);
} else {
printk("ibmvscsi: host srp version: %s, "
- "host partition %s (%d), OS %d\n",
+ "host partition %s (%d), OS %d, max io %u\n",
hostdata->madapter_info.srp_version,
hostdata->madapter_info.partition_name,
hostdata->madapter_info.partition_number,
- hostdata->madapter_info.os_type);
+ hostdata->madapter_info.os_type,
+ hostdata->madapter_info.port_max_txu[0]);
+
+ if (hostdata->madapter_info.port_max_txu[0])
+ hostdata->host->max_sectors =
+ hostdata->madapter_info.port_max_txu[0] >> 9;
}
}
@@ -796,6 +808,10 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata)
*/
static void sync_completion(struct srp_event_struct *evt_struct)
{
+ /* copy the response back */
+ if (evt_struct->sync_srp)
+ *evt_struct->sync_srp = *evt_struct->xfer_iu;
+
complete(&evt_struct->comp);
}
@@ -810,6 +826,8 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
struct srp_tsk_mgmt *tsk_mgmt;
struct srp_event_struct *evt;
struct srp_event_struct *tmp_evt, *found_evt;
+ union viosrp_iu srp_rsp;
+ int rsp_rc;
u16 lun = lun_from_dev(cmd->device);
/* First, find this command in our sent list so we can figure
@@ -849,6 +867,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",
tsk_mgmt->lun, tsk_mgmt->managed_task_tag);
+ evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
@@ -859,6 +878,29 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
wait_for_completion(&evt->comp);
spin_lock_irq(hostdata->host->host_lock);
+ /* make sure we got a good response */
+ if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING
+ "ibmvscsi: abort bad SRP RSP type %d\n",
+ srp_rsp.srp.generic.type);
+ return FAILED;
+ }
+
+ if (srp_rsp.srp.rsp.rspvalid)
+ rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
+ else
+ rsp_rc = srp_rsp.srp.rsp.status;
+
+ if (rsp_rc) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING
+ "ibmvscsi: abort code %d for task tag 0x%lx\n",
+ rsp_rc,
+ tsk_mgmt->managed_task_tag);
+ return FAILED;
+ }
+
/* Because we dropped the spinlock above, it's possible
* The event is no longer in our list. Make sure it didn't
* complete while we were aborting
@@ -871,13 +913,17 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
}
}
+ if (found_evt == NULL) {
+ printk(KERN_INFO
+ "ibmvscsi: aborted task tag 0x%lx completed\n",
+ tsk_mgmt->managed_task_tag);
+ return SUCCESS;
+ }
+
printk(KERN_INFO
"ibmvscsi: successfully aborted task tag 0x%lx\n",
tsk_mgmt->managed_task_tag);
- if (found_evt == NULL)
- return SUCCESS;
-
cmd->result = (DID_ABORT << 16);
list_del(&found_evt->list);
unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev);
@@ -899,6 +945,8 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
struct srp_tsk_mgmt *tsk_mgmt;
struct srp_event_struct *evt;
struct srp_event_struct *tmp_evt, *pos;
+ union viosrp_iu srp_rsp;
+ int rsp_rc;
u16 lun = lun_from_dev(cmd->device);
evt = get_event_struct(&hostdata->pool);
@@ -923,6 +971,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",
tsk_mgmt->lun);
+ evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
@@ -933,6 +982,29 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
wait_for_completion(&evt->comp);
spin_lock_irq(hostdata->host->host_lock);
+ /* make sure we got a good response */
+ if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING
+ "ibmvscsi: reset bad SRP RSP type %d\n",
+ srp_rsp.srp.generic.type);
+ return FAILED;
+ }
+
+ if (srp_rsp.srp.rsp.rspvalid)
+ rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
+ else
+ rsp_rc = srp_rsp.srp.rsp.status;
+
+ if (rsp_rc) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING
+ "ibmvscsi: reset code %d for task tag 0x%lx\n",
+ rsp_rc,
+ tsk_mgmt->managed_task_tag);
+ return FAILED;
+ }
+
/* We need to find all commands for this LUN that have not yet been
* responded to, and fail them with DID_RESET
*/
@@ -1048,6 +1120,13 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
return;
}
+ if (atomic_read(&evt_struct->free)) {
+ printk(KERN_ERR
+ "ibmvscsi: received duplicate correlation_token 0x%p!\n",
+ (void *)crq->IU_data_ptr);
+ return;
+ }
+
if (crq->format == VIOSRP_SRP_FORMAT)
atomic_add(evt_struct->xfer_iu->srp.rsp.request_limit_delta,
&hostdata->request_limit);
@@ -1295,6 +1374,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
hostdata->host = host;
hostdata->dev = dev;
atomic_set(&hostdata->request_limit, -1);
+ hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
if (ibmvscsi_init_crq_queue(&hostdata->queue, hostdata,
max_requests) != 0) {
@@ -1326,7 +1406,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
*/
for (wait_switch = jiffies + (init_timeout * HZ);
time_before(jiffies, wait_switch) &&
- atomic_read(&hostdata->request_limit) < 0;) {
+ atomic_read(&hostdata->request_limit) < 2;) {
msleep(10);
}
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index dbe1735e5934..1030b703c30e 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -67,6 +67,7 @@ struct srp_event_struct {
union viosrp_iu iu;
void (*cmnd_done) (struct scsi_cmnd *);
struct completion comp;
+ union viosrp_iu *sync_srp;
};
/* a pool of event structs for use */
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index ad8a86184dea..f0059b1f7a01 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -2610,23 +2610,19 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) { return 0; };
#endif
/**
- * ipr_store_queue_depth - Change the device's queue depth
- * @dev: device struct
- * @buf: buffer
+ * ipr_change_queue_depth - Change the device's queue depth
+ * @sdev: scsi device struct
+ * @qdepth: depth to set
*
* Return value:
- * number of bytes printed to buffer
+ * actual depth set
**/
-static ssize_t ipr_store_queue_depth(struct device *dev,
- const char *buf, size_t count)
+static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
- struct scsi_device *sdev = to_scsi_device(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
struct ipr_resource_entry *res;
- int qdepth = simple_strtoul(buf, NULL, 10);
int tagged = 0;
unsigned long lock_flags = 0;
- ssize_t len = -ENXIO;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
res = (struct ipr_resource_entry *)sdev->hostdata;
@@ -2635,23 +2631,13 @@ static ssize_t ipr_store_queue_depth(struct device *dev,
if (ipr_is_gscsi(res) && res->tcq_active)
tagged = MSG_ORDERED_TAG;
-
- len = strlen(buf);
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
scsi_adjust_queue_depth(sdev, tagged, qdepth);
- return len;
+ return qdepth;
}
-static struct device_attribute ipr_queue_depth_attr = {
- .attr = {
- .name = "queue_depth",
- .mode = S_IRUSR | S_IWUSR,
- },
- .store = ipr_store_queue_depth
-};
-
/**
* ipr_show_tcq_enable - Show if the device is enabled for tcqing
* @dev: device struct
@@ -2760,7 +2746,6 @@ static struct device_attribute ipr_adapter_handle_attr = {
};
static struct device_attribute *ipr_dev_attrs[] = {
- &ipr_queue_depth_attr,
&ipr_tcqing_attr,
&ipr_adapter_handle_attr,
NULL,
@@ -3961,6 +3946,7 @@ static struct scsi_host_template driver_template = {
.slave_alloc = ipr_slave_alloc,
.slave_configure = ipr_slave_configure,
.slave_destroy = ipr_slave_destroy,
+ .change_queue_depth = ipr_change_queue_depth,
.bios_param = ipr_biosparam,
.can_queue = IPR_MAX_COMMANDS,
.this_id = -1,
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index 35110f4d13c5..25729f3f8164 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -54,13 +54,33 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
-#include "lasi700.h"
#include "53c700.h"
MODULE_AUTHOR("James Bottomley");
MODULE_DESCRIPTION("lasi700 SCSI Driver");
MODULE_LICENSE("GPL");
+#define LASI_700_SVERSION 0x00071
+#define LASI_710_SVERSION 0x00082
+
+#define LASI700_ID_TABLE { \
+ .hw_type = HPHW_FIO, \
+ .sversion = LASI_700_SVERSION, \
+ .hversion = HVERSION_ANY_ID, \
+ .hversion_rev = HVERSION_REV_ANY_ID, \
+}
+
+#define LASI710_ID_TABLE { \
+ .hw_type = HPHW_FIO, \
+ .sversion = LASI_710_SVERSION, \
+ .hversion = HVERSION_ANY_ID, \
+ .hversion_rev = HVERSION_REV_ANY_ID, \
+}
+
+#define LASI700_CLOCK 25
+#define LASI710_CLOCK 40
+#define LASI_SCSI_CORE_OFFSET 0x100
+
static struct parisc_device_id lasi700_ids[] = {
LASI700_ID_TABLE,
LASI710_ID_TABLE,
diff --git a/drivers/scsi/lasi700.h b/drivers/scsi/lasi700.h
deleted file mode 100644
index 244a648824ee..000000000000
--- a/drivers/scsi/lasi700.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8 -*- */
-
-/* PARISC LASI driver for the 53c700 chip
- *
- * Copyright (C) 2001 by James.Bottomley@HansenPartnership.com
-**-----------------------------------------------------------------------------
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**-----------------------------------------------------------------------------
- */
-
-#ifndef _LASI700_H
-#define _LASI700_H
-
-#define LASI_710_SVERSION 0x082
-#define LASI_700_SVERSION 0x071
-
-#define LASI700_ID_TABLE { \
- .hw_type = HPHW_FIO, \
- .sversion = LASI_700_SVERSION, \
- .hversion = HVERSION_ANY_ID, \
- .hversion_rev = HVERSION_REV_ANY_ID, \
-}
-
-#define LASI710_ID_TABLE { \
- .hw_type = HPHW_FIO, \
- .sversion = LASI_710_SVERSION, \
- .hversion = HVERSION_ANY_ID, \
- .hversion_rev = HVERSION_REV_ANY_ID, \
-}
-
-#define LASI700_CLOCK 25
-#define LASI710_CLOCK 40
-#define LASI_SCSI_CORE_OFFSET 0x100
-
-#endif
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 8b81553a3ab6..4aff0d68298d 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -13,18 +13,18 @@
order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
- Copyright 1992 - 2002 Kai Makisara / Willem Riede
- email Kai.Makisara@metla.fi / osst@riede.org
+ Copyright 1992 - 2002 Kai Makisara / 2000 - 2004 Willem Riede
+ email osst@riede.org
- $Header: /cvsroot/osst/Driver/osst.c,v 1.70 2003/12/23 14:22:12 wriede Exp $
+ $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
Microscopic alterations - Rik Ling, 2000/12/21
Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
Some small formal changes - aeb, 950809
*/
-static const char * cvsid = "$Id: osst.c,v 1.70 2003/12/23 14:22:12 wriede Exp $";
-const char * osst_version = "0.99.1";
+static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
+const char * osst_version = "0.99.3";
/* The "failure to reconnect" firmware bug */
#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
@@ -36,6 +36,7 @@ const char * osst_version = "0.99.1";
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/proc_fs.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/string.h>
@@ -46,6 +47,7 @@ const char * osst_version = "0.99.1";
#include <linux/spinlock.h>
#include <linux/vmalloc.h>
#include <linux/blkdev.h>
+#include <linux/moduleparam.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
@@ -82,13 +84,13 @@ MODULE_AUTHOR("Willem Riede");
MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
MODULE_LICENSE("GPL");
-module_param(max_dev, int, 0);
+module_param(max_dev, int, 0444);
MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
-module_param(write_threshold_kbs, int, 0);
+module_param(write_threshold_kbs, int, 0644);
MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
-module_param(max_sg_segs, int, 0);
+module_param(max_sg_segs, int, 0644);
MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
#else
static struct osst_dev_parm {
@@ -119,10 +121,10 @@ static int debugging = 1;
// #define OSST_INJECT_ERRORS 1
#endif
-#define MAX_RETRIES 2
-#define MAX_READ_RETRIES 0
-#define MAX_WRITE_RETRIES 0
-#define MAX_READY_RETRIES 0
+/* Do not retry! The drive firmware already retries when appropriate,
+ and when it tries to tell us something, we had better listen... */
+#define MAX_RETRIES 0
+
#define NO_TAPE NOT_READY
#define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
@@ -147,19 +149,19 @@ static int osst_max_sg_segs = OSST_MAX_SG;
static int osst_max_dev = OSST_MAX_TAPES;
static int osst_nr_dev;
-static OS_Scsi_Tape **os_scsi_tapes = NULL;
-static rwlock_t os_scsi_tapes_lock = RW_LOCK_UNLOCKED;
+static struct osst_tape **os_scsi_tapes = NULL;
+static rwlock_t os_scsi_tapes_lock = RW_LOCK_UNLOCKED;
static int modes_defined = FALSE;
-static OSST_buffer *new_tape_buffer(int, int, int);
-static int enlarge_buffer(OSST_buffer *, int);
-static void normalize_buffer(OSST_buffer *);
-static int append_to_buffer(const char __user *, OSST_buffer *, int);
-static int from_buffer(OSST_buffer *, char __user *, int);
-static int osst_zero_buffer_tail(OSST_buffer *);
-static int osst_copy_to_buffer(OSST_buffer *, unsigned char *);
-static int osst_copy_from_buffer(OSST_buffer *, unsigned char *);
+static struct osst_buffer *new_tape_buffer(int, int, int);
+static int enlarge_buffer(struct osst_buffer *, int);
+static void normalize_buffer(struct osst_buffer *);
+static int append_to_buffer(const char __user *, struct osst_buffer *, int);
+static int from_buffer(struct osst_buffer *, char __user *, int);
+static int osst_zero_buffer_tail(struct osst_buffer *);
+static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
+static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
static int osst_probe(struct device *);
static int osst_remove(struct device *);
@@ -173,17 +175,18 @@ struct scsi_driver osst_template = {
}
};
-static int osst_int_ioctl(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, unsigned int cmd_in,unsigned long arg);
+static int osst_int_ioctl(struct osst_tape *STp, struct scsi_request ** aSRpnt,
+ unsigned int cmd_in, unsigned long arg);
-static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int frame, int skip);
+static int osst_set_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt, int frame, int skip);
-static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
+static int osst_get_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt);
-static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
+static int osst_flush_write_buffer(struct osst_tape *STp, struct scsi_request ** aSRpnt);
-static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending);
+static int osst_write_error_recovery(struct osst_tape * STp, struct scsi_request ** aSRpnt, int pending);
-static inline char *tape_name(OS_Scsi_Tape *tape)
+static inline char *tape_name(struct osst_tape *tape)
{
return tape->drive->disk_name;
}
@@ -191,7 +194,7 @@ static inline char *tape_name(OS_Scsi_Tape *tape)
/* Routines that handle the interaction with mid-layer SCSI routines */
/* Convert the result to success code */
-static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
+static int osst_chk_result(struct osst_tape * STp, struct scsi_request * SRpnt)
{
char *name = tape_name(STp);
int result = SRpnt->sr_result;
@@ -222,7 +225,7 @@ static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
if (driver_byte(result) & DRIVER_SENSE)
print_req_sense("osst ", SRpnt);
}
-// else
+ else
#endif
if (!(driver_byte(result) & DRIVER_SENSE) ||
((sense[0] & 0x70) == 0x70 &&
@@ -234,7 +237,7 @@ static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
SRpnt->sr_cmnd[0] != MODE_SENSE &&
SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
if (driver_byte(result) & DRIVER_SENSE) {
- printk(KERN_WARNING "%s:W: Command with sense data: ", name);
+ printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
print_req_sense("osst:", SRpnt);
}
else {
@@ -281,7 +284,7 @@ static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
/* Wakeup from interrupt */
static void osst_sleep_done (Scsi_Cmnd * SCpnt)
{
- OS_Scsi_Tape * STp = container_of(SCpnt->request->rq_disk->private_data, OS_Scsi_Tape, driver);
+ struct osst_tape * STp = container_of(SCpnt->request->rq_disk->private_data, struct osst_tape, driver);
if ((STp->buffer)->writing &&
(SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
@@ -307,7 +310,7 @@ static void osst_sleep_done (Scsi_Cmnd * SCpnt)
/* Do the scsi command. Waits until command performed if do_wait is true.
Otherwise osst_write_behind_check() is used to check that the command
has finished. */
-static Scsi_Request * osst_do_scsi(Scsi_Request *SRpnt, OS_Scsi_Tape *STp,
+static struct scsi_request * osst_do_scsi(struct scsi_request *SRpnt, struct osst_tape *STp,
unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
{
unsigned char *bp;
@@ -366,9 +369,9 @@ static Scsi_Request * osst_do_scsi(Scsi_Request *SRpnt, OS_Scsi_Tape *STp,
/* Handle the write-behind checking (downs the semaphore) */
-static void osst_write_behind_check(OS_Scsi_Tape *STp)
+static void osst_write_behind_check(struct osst_tape *STp)
{
- OSST_buffer * STbuffer;
+ struct osst_buffer * STbuffer;
STbuffer = STp->buffer;
@@ -406,7 +409,7 @@ static void osst_write_behind_check(OS_Scsi_Tape *STp)
/*
* Initialize the OnStream AUX
*/
-static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int frame_seq_number,
+static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
int logical_blk_num, int blk_sz, int blk_cnt)
{
os_aux_t *aux = STp->buffer->aux;
@@ -468,13 +471,13 @@ static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int frame_seq_numb
/*
* Verify that we have the correct tape frame
*/
-static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet)
+static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
{
- char * name = tape_name(STp);
- os_aux_t * aux = STp->buffer->aux;
- os_partition_t * par = &(aux->partition);
- struct st_partstat * STps = &(STp->ps[STp->partition]);
- int blk_cnt, blk_sz, i;
+ char * name = tape_name(STp);
+ os_aux_t * aux = STp->buffer->aux;
+ os_partition_t * par = &(aux->partition);
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ int blk_cnt, blk_sz, i;
if (STp->raw) {
if (STp->buffer->syscall_result) {
@@ -602,14 +605,15 @@ err_out:
/*
* Wait for the unit to become Ready
*/
-static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout, int initial_delay)
+static int osst_wait_ready(struct osst_tape * STp, struct scsi_request ** aSRpnt,
+ unsigned timeout, int initial_delay)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- unsigned long startwait = jiffies;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ unsigned long startwait = jiffies;
#if DEBUG
- int dbg = debugging;
- char * name = tape_name(STp);
+ int dbg = debugging;
+ char * name = tape_name(STp);
printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
#endif
@@ -620,7 +624,7 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (!SRpnt) return (-EBUSY);
@@ -641,7 +645,7 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
}
*aSRpnt = SRpnt;
#if DEBUG
@@ -666,14 +670,14 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned
/*
* Wait for a tape to be inserted in the unit
*/
-static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout)
+static int osst_wait_for_medium(struct osst_tape * STp, struct scsi_request ** aSRpnt, unsigned timeout)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- unsigned long startwait = jiffies;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ unsigned long startwait = jiffies;
#if DEBUG
- int dbg = debugging;
- char * name = tape_name(STp);
+ int dbg = debugging;
+ char * name = tape_name(STp);
printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
#endif
@@ -681,7 +685,7 @@ static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsi
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (!SRpnt) return (-EBUSY);
@@ -700,7 +704,7 @@ static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsi
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
}
*aSRpnt = SRpnt;
#if DEBUG
@@ -722,7 +726,7 @@ static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsi
return 1;
}
-static int osst_position_tape_and_confirm(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame)
+static int osst_position_tape_and_confirm(struct osst_tape * STp, struct scsi_request ** aSRpnt, int frame)
{
int retval;
@@ -736,15 +740,14 @@ static int osst_position_tape_and_confirm(OS_Scsi_Tape * STp, Scsi_Request ** aS
/*
* Wait for write(s) to complete
*/
-static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_flush_drive_buffer(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
-
- int result = 0;
- int delay = OSST_WAIT_WRITE_COMPLETE;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ int result = 0;
+ int delay = OSST_WAIT_WRITE_COMPLETE;
#if DEBUG
- char * name = tape_name(STp);
+ char * name = tape_name(STp);
printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
#endif
@@ -753,7 +756,7 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
cmd[0] = WRITE_FILEMARKS;
cmd[1] = 1;
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (!SRpnt) return (-EBUSY);
if (STp->buffer->syscall_result) {
@@ -771,12 +774,12 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
}
#define OSST_POLL_PER_SEC 10
-static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr, int minlast, int to)
+static int osst_wait_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int curr, int minlast, int to)
{
- unsigned long startwait = jiffies;
- char * name = tape_name(STp);
+ unsigned long startwait = jiffies;
+ char * name = tape_name(STp);
#if DEBUG
- char notyetprinted = 1;
+ char notyetprinted = 1;
#endif
if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
@@ -784,7 +787,7 @@ static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr,
while (time_before (jiffies, startwait + to*HZ))
{
int result;
- result = osst_get_frame_position (STp, aSRpnt);
+ result = osst_get_frame_position(STp, aSRpnt);
if (result == -EIO)
if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
return 0; /* successful recovery leaves drive ready for frame */
@@ -826,23 +829,79 @@ static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr,
return -EBUSY;
}
+static int osst_recover_wait_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int writing)
+{
+ struct scsi_request * SRpnt;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ unsigned long startwait = jiffies;
+ int retval = 1;
+ char * name = tape_name(STp);
+
+ if (writing) {
+ char mybuf[24];
+ char * olddata = STp->buffer->b_data;
+ int oldsize = STp->buffer->buffer_size;
+
+ /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
+
+ memset(cmd, 0, MAX_COMMAND_SIZE);
+ cmd[0] = WRITE_FILEMARKS;
+ cmd[1] = 1;
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout,
+ MAX_RETRIES, TRUE);
+
+ while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
+
+ if (STp->buffer->syscall_result && (SRpnt->sr_sense_buffer[2] & 0x0f) != 2) {
+
+ /* some failure - not just not-ready */
+ retval = osst_write_error_recovery(STp, aSRpnt, 0);
+ break;
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout (HZ / OSST_POLL_PER_SEC);
+
+ STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
+ memset(cmd, 0, MAX_COMMAND_SIZE);
+ cmd[0] = READ_POSITION;
+
+ SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, SCSI_DATA_READ, STp->timeout,
+ MAX_RETRIES, TRUE);
+
+ retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
+ STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
+ }
+ if (retval)
+ printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
+ } else
+ /* TODO - figure out which error conditions can be handled */
+ if (STp->buffer->syscall_result)
+ printk(KERN_WARNING
+ "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
+ (*aSRpnt)->sr_sense_buffer[ 2] & 0x0f,
+ (*aSRpnt)->sr_sense_buffer[12],
+ (*aSRpnt)->sr_sense_buffer[13]);
+
+ return retval;
+}
+
/*
* Read the next OnStream tape frame at the current location
*/
-static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeout)
+static int osst_read_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int timeout)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- int retval = 0;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ int retval = 0;
#if DEBUG
- os_aux_t * aux = STp->buffer->aux;
- char * name = tape_name(STp);
+ os_aux_t * aux = STp->buffer->aux;
+ char * name = tape_name(STp);
#endif
- /* TODO: Error handling */
if (STp->poll)
- retval = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout);
-
+ if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
+ retval = osst_recover_wait_frame(STp, aSRpnt, 0);
+
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = READ_6;
cmd[1] = 1;
@@ -850,13 +909,13 @@ static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeo
#if DEBUG
if (debugging)
- printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
+ printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
#endif
SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
- STp->timeout, MAX_READ_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (!SRpnt)
- return (-EBUSY);
+ return (-EBUSY);
if ((STp->buffer)->syscall_result) {
retval = 1;
@@ -900,15 +959,13 @@ static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeo
return (retval);
}
-static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_initiate_read(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
- struct st_partstat * STps = &(STp->ps[STp->partition]);
- Scsi_Request * SRpnt ;
- unsigned char cmd[MAX_COMMAND_SIZE];
- int retval = 0;
-#if DEBUG
- char * name = tape_name(STp);
-#endif
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ struct scsi_request * SRpnt ;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ int retval = 0;
+ char * name = tape_name(STp);
if (STps->rw != ST_READING) { /* Initialize read operation */
if (STps->rw == ST_WRITING || STp->dirty) {
@@ -930,23 +987,25 @@ static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
#endif
- SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READ_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
- retval = STp->buffer->syscall_result;
+ if ((retval = STp->buffer->syscall_result))
+ printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
}
return retval;
}
-static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame_seq_number, int quiet)
+static int osst_get_logical_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt,
+ int frame_seq_number, int quiet)
{
struct st_partstat * STps = &(STp->ps[STp->partition]);
- char * name = tape_name(STp);
- int cnt = 0,
- bad = 0,
- past = 0,
- x,
- position;
+ char * name = tape_name(STp);
+ int cnt = 0,
+ bad = 0,
+ past = 0,
+ x,
+ position;
/*
* If we want just any frame (-1) and there is a frame in the buffer, return it
@@ -971,6 +1030,7 @@ static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, in
name, STp->read_error_frame);
#endif
STp->read_error_frame = 0;
+ STp->abort_count++;
}
return (-EIO);
}
@@ -988,10 +1048,11 @@ static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, in
position = 0xbb8;
else if (position > STp->eod_frame_ppos || ++bad == 10) {
position = STp->read_error_frame - 1;
+ bad = 0;
}
else {
- position += 39;
- cnt += 20;
+ position += 29;
+ cnt += 19;
}
#if DEBUG
printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
@@ -1064,10 +1125,10 @@ static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, in
return (STps->eof);
}
-static int osst_seek_logical_blk(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int logical_blk_num)
+static int osst_seek_logical_blk(struct osst_tape * STp, struct scsi_request ** aSRpnt, int logical_blk_num)
{
struct st_partstat * STps = &(STp->ps[STp->partition]);
- char * name = tape_name(STp);
+ char * name = tape_name(STp);
int retries = 0;
int frame_seq_estimate, ppos_estimate, move;
@@ -1173,7 +1234,7 @@ error:
#define OSST_SECTOR_SHIFT 9
#define OSST_SECTOR_MASK 0x03F
-static int osst_get_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_get_sector(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
int sector;
#if DEBUG
@@ -1203,12 +1264,12 @@ static int osst_get_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
return sector;
}
-static int osst_seek_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sector)
+static int osst_seek_sector(struct osst_tape * STp, struct scsi_request ** aSRpnt, int sector)
{
- struct st_partstat * STps = &(STp->ps[STp->partition]);
- int frame = sector >> OSST_FRAME_SHIFT,
- offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
- r;
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ int frame = sector >> OSST_FRAME_SHIFT,
+ offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
+ r;
#if DEBUG
char * name = tape_name(STp);
@@ -1266,23 +1327,23 @@ static int osst_seek_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sect
* Precondition for this function to work: all frames in the
* drive's buffer must be of one type (DATA, MARK or EOD)!
*/
-static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
- unsigned int frame, unsigned int skip, int pending)
+static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi_request ** aSRpnt,
+ unsigned int frame, unsigned int skip, int pending)
{
- Scsi_Request * SRpnt = * aSRpnt;
- unsigned char * buffer, * p;
- unsigned char cmd[MAX_COMMAND_SIZE];
- int flag, new_frame, i;
- int nframes = STp->cur_frames;
- int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
- int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
+ struct scsi_request * SRpnt = * aSRpnt;
+ unsigned char * buffer, * p;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ int flag, new_frame, i;
+ int nframes = STp->cur_frames;
+ int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
+ int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
- (nframes + pending - 1);
- int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
+ int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
- (nframes + pending - 1) * blks_per_frame;
- char * name = tape_name(STp);
- unsigned long startwait = jiffies;
+ char * name = tape_name(STp);
+ unsigned long startwait = jiffies;
#if DEBUG
- int dbg = debugging;
+ int dbg = debugging;
#endif
if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
@@ -1308,7 +1369,7 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request **
cmd[8] = 32768 & 0xff;
SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
- STp->timeout, MAX_READ_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
if ((STp->buffer)->syscall_result || !SRpnt) {
printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
@@ -1357,8 +1418,8 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request **
vfree((void *)buffer);
return (-EIO);
}
- flag = 0;
if ( i >= nframes + pending ) break;
+ flag = 0;
}
osst_copy_to_buffer(STp->buffer, p);
/*
@@ -1380,7 +1441,7 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request **
p[0], p[1], p[2], p[3]);
#endif
SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
- STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
if (STp->buffer->syscall_result)
flag = 1;
@@ -1396,7 +1457,7 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request **
cmd[0] = WRITE_FILEMARKS;
cmd[1] = 1;
SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
- STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
#if DEBUG
if (debugging) {
printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
@@ -1411,7 +1472,7 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request **
cmd[0] = TEST_UNIT_READY;
SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout,
- MAX_READY_RETRIES, TRUE);
+ MAX_RETRIES, TRUE);
if (SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&
(SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8)) {
@@ -1448,29 +1509,34 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request **
#endif
osst_get_frame_position(STp, aSRpnt);
#if DEBUG
- printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
- name, STp->first_frame_position, STp->last_frame_position);
+ printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
+ name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
#endif
}
- }
+ }
+ if (flag) {
+ /* error recovery did not successfully complete */
+ printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
+ STp->write_type == OS_WRITE_HEADER?"header":"body");
+ }
if (!pending)
osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */
vfree((void *)buffer);
return 0;
}
-static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_reposition_and_retry(struct osst_tape * STp, struct scsi_request ** aSRpnt,
unsigned int frame, unsigned int skip, int pending)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- char * name = tape_name(STp);
- int expected = 0;
- int attempts = 1000 / skip;
- int flag = 1;
- unsigned long startwait = jiffies;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ char * name = tape_name(STp);
+ int expected = 0;
+ int attempts = 1000 / skip;
+ int flag = 1;
+ unsigned long startwait = jiffies;
#if DEBUG
- int dbg = debugging;
+ int dbg = debugging;
#endif
while (attempts && time_before(jiffies, startwait + 60*HZ)) {
@@ -1512,7 +1578,7 @@ static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
name, STp->frame_seq_number-1, STp->first_frame_position);
#endif
SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
- STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (STp->buffer->syscall_result) { /* additional write error */
@@ -1550,6 +1616,7 @@ static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
debugging = 0;
}
#endif
+ set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ / 10);
}
printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
@@ -1563,14 +1630,14 @@ static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
* Error recovery algorithm for the OnStream tape.
*/
-static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending)
+static int osst_write_error_recovery(struct osst_tape * STp, struct scsi_request ** aSRpnt, int pending)
{
- Scsi_Request * SRpnt = * aSRpnt;
+ struct scsi_request * SRpnt = * aSRpnt;
struct st_partstat * STps = & STp->ps[STp->partition];
- char * name = tape_name(STp);
- int retval = 0;
- int rw_state;
- unsigned int frame, skip;
+ char * name = tape_name(STp);
+ int retval = 0;
+ int rw_state;
+ unsigned int frame, skip;
rw_state = STps->rw;
@@ -1635,12 +1702,14 @@ static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
if (retval == 0) {
STp->recover_count++;
STp->recover_erreg++;
- }
+ } else
+ STp->abort_count++;
+
STps->rw = rw_state;
return retval;
}
-static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct scsi_request ** aSRpnt,
int mt_op, int mt_count)
{
char * name = tape_name(STp);
@@ -1739,7 +1808,7 @@ found:
*
* Just scans for the filemark sequentially.
*/
-static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct scsi_request ** aSRpnt,
int mt_op, int mt_count)
{
int cnt = 0;
@@ -1793,7 +1862,7 @@ static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Reque
/*
* Fast linux specific version of OnStream FSF
*/
-static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
+static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct scsi_request ** aSRpnt,
int mt_op, int mt_count)
{
char * name = tape_name(STp);
@@ -1944,11 +2013,11 @@ static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Reque
* to test the error recovery mechanism.
*/
#if DEBUG
-static void osst_set_retries(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int retries)
+static void osst_set_retries(struct osst_tape * STp, struct scsi_request ** aSRpnt, int retries)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt = * aSRpnt;
- char * name = tape_name(STp);
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt = * aSRpnt;
+ char * name = tape_name(STp);
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = MODE_SELECT;
@@ -1976,7 +2045,7 @@ static void osst_set_retries(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int ret
#endif
-static int osst_write_filemark(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_write_filemark(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
int result;
int this_mark_ppos = STp->first_frame_position;
@@ -2004,7 +2073,7 @@ static int osst_write_filemark(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
return result;
}
-static int osst_write_eod(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_write_eod(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
int result;
#if DEBUG
@@ -2027,7 +2096,7 @@ static int osst_write_eod(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
return result;
}
-static int osst_write_filler(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
+static int osst_write_filler(struct osst_tape * STp, struct scsi_request ** aSRpnt, int where, int count)
{
char * name = tape_name(STp);
@@ -2052,7 +2121,7 @@ static int osst_write_filler(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int whe
return osst_flush_drive_buffer(STp, aSRpnt);
}
-static int __osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
+static int __osst_write_header(struct osst_tape * STp, struct scsi_request ** aSRpnt, int where, int count)
{
char * name = tape_name(STp);
int result;
@@ -2079,7 +2148,7 @@ static int __osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int w
return result;
}
-static int osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int locate_eod)
+static int osst_write_header(struct osst_tape * STp, struct scsi_request ** aSRpnt, int locate_eod)
{
os_header_t * header;
int result;
@@ -2153,7 +2222,7 @@ static int osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int loc
return result;
}
-static int osst_reset_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_reset_header(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
if (STp->header_cache != NULL)
memset(STp->header_cache, 0, sizeof(os_header_t));
@@ -2166,7 +2235,7 @@ static int osst_reset_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
return osst_write_header(STp, aSRpnt, 1);
}
-static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int ppos)
+static int __osst_analyze_headers(struct osst_tape * STp, struct scsi_request ** aSRpnt, int ppos)
{
char * name = tape_name(STp);
os_header_t * header;
@@ -2343,7 +2412,7 @@ static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, in
return 1;
}
-static int osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_analyze_headers(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
int position, ppos;
int first, last;
@@ -2398,7 +2467,7 @@ static int osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
return 1;
}
-static int osst_verify_position(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
+static int osst_verify_position(struct osst_tape * STp, struct scsi_request ** aSRpnt)
{
int frame_position = STp->first_frame_position;
int frame_seq_numbr = STp->frame_seq_number;
@@ -2474,11 +2543,11 @@ static unsigned int osst_parse_firmware_rev (const char * str)
/*
* Configure the OnStream SCII tape drive for default operation
*/
-static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
+static int osst_configure_onstream(struct osst_tape *STp, struct scsi_request ** aSRpnt)
{
unsigned char cmd[MAX_COMMAND_SIZE];
char * name = tape_name(STp);
- Scsi_Request * SRpnt = * aSRpnt;
+ struct scsi_request * SRpnt = * aSRpnt;
osst_mode_parameter_header_t * header;
osst_block_size_page_t * bs;
osst_capabilities_page_t * cp;
@@ -2645,7 +2714,7 @@ static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
/* Step over EOF if it has been inadvertently crossed (ioctl not used because
it messes up the block number). */
-static int cross_eof(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int forward)
+static int cross_eof(struct osst_tape *STp, struct scsi_request ** aSRpnt, int forward)
{
int result;
char * name = tape_name(STp);
@@ -2674,18 +2743,18 @@ static int cross_eof(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int forward)
/* Get the tape position. */
-static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
+static int osst_get_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt)
{
- unsigned char scmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- int result = 0;
+ unsigned char scmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ int result = 0;
+ char * name = tape_name(STp);
/* KG: We want to be able to use it for checking Write Buffer availability
* and thus don't want to risk to overwrite anything. Exchange buffers ... */
char mybuf[24];
char * olddata = STp->buffer->b_data;
int oldsize = STp->buffer->buffer_size;
- char * name = tape_name(STp);
if (STp->ready != ST_READY) return (-EIO);
@@ -2702,13 +2771,12 @@ static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
*aSRpnt = SRpnt;
if (STp->buffer->syscall_result)
- result = ((SRpnt->sr_sense_buffer[2] & 0x0f) == 3) ? -EIO : -EINVAL;
+ result = ((SRpnt->sr_sense_buffer[2] & 0x0f) == 3) ? -EIO : -EINVAL; /* 3: Write Error */
if (result == -EINVAL)
printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
else {
-
- if (result == -EIO) { /* re-read position */
+ if (result == -EIO) { /* re-read position - this needs to preserve media errors */
unsigned char mysense[16];
memcpy (mysense, SRpnt->sr_sense_buffer, 16);
memset (scmd, 0, MAX_COMMAND_SIZE);
@@ -2716,8 +2784,15 @@ static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, SCSI_DATA_READ,
STp->timeout, MAX_RETRIES, TRUE);
+#if DEBUG
+ printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
+ name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
+ SRpnt->sr_sense_buffer[2],SRpnt->sr_sense_buffer[12],SRpnt->sr_sense_buffer[13]);
+#endif
if (!STp->buffer->syscall_result)
memcpy (SRpnt->sr_sense_buffer, mysense, 16);
+ else
+ printk(KERN_WARNING "%s:W: Double error in get position\n", name);
}
STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
+ ((STp->buffer)->b_data[5] << 16)
@@ -2739,7 +2814,7 @@ static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
#endif
if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
#if DEBUG
- printk(KERN_WARNING "%s:D: Correcting read position %d, %d, %d\n", name,
+ printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
#endif
STp->first_frame_position = STp->last_frame_position;
@@ -2752,14 +2827,14 @@ static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
/* Set the tape block */
-static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int ppos, int skip)
+static int osst_set_frame_position(struct osst_tape *STp, struct scsi_request ** aSRpnt, int ppos, int skip)
{
- unsigned char scmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- struct st_partstat * STps;
- int result = 0;
- int pp = (ppos == 3000 && !skip)? 0 : ppos;
- char * name = tape_name(STp);
+ unsigned char scmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ struct st_partstat * STps;
+ int result = 0;
+ int pp = (ppos == 3000 && !skip)? 0 : ppos;
+ char * name = tape_name(STp);
if (STp->ready != ST_READY) return (-EIO);
@@ -2810,7 +2885,7 @@ static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, in
return result;
}
-static int osst_write_trailer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int leave_at_EOT)
+static int osst_write_trailer(struct osst_tape *STp, struct scsi_request ** aSRpnt, int leave_at_EOT)
{
struct st_partstat * STps = &(STp->ps[STp->partition]);
int result = 0;
@@ -2837,26 +2912,26 @@ out:
/* osst versions of st functions - augmented and stripped to suit OnStream only */
/* Flush the write buffer (never need to write if variable blocksize). */
-static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
+static int osst_flush_write_buffer(struct osst_tape *STp, struct scsi_request ** aSRpnt)
{
- int offset, transfer, blks = 0;
- int result = 0;
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt = *aSRpnt;
- struct st_partstat * STps;
- char * name = tape_name(STp);
+ int offset, transfer, blks = 0;
+ int result = 0;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt = *aSRpnt;
+ struct st_partstat * STps;
+ char * name = tape_name(STp);
if ((STp->buffer)->writing) {
if (SRpnt == (STp->buffer)->last_SRpnt)
#if DEBUG
{ printk(OSST_DEB_MSG
- "%s:D: aSRpnt points to Scsi_Request that write_behind_check will release -- cleared\n", name);
+ "%s:D: aSRpnt points to scsi_request that write_behind_check will release -- cleared\n", name);
#endif
*aSRpnt = SRpnt = NULL;
#if DEBUG
} else if (SRpnt)
printk(OSST_DEB_MSG
- "%s:D: aSRpnt does not point to Scsi_Request that write_behind_check will release -- strange\n", name);
+ "%s:D: aSRpnt does not point to scsi_request that write_behind_check will release -- strange\n", name);
#endif
osst_write_behind_check(STp);
if ((STp->buffer)->syscall_result) {
@@ -2884,9 +2959,9 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
if (offset < OS_DATA_SIZE)
osst_zero_buffer_tail(STp->buffer);
- /* TODO: Error handling! */
if (STp->poll)
- result = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120);
+ if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
+ result = osst_recover_wait_frame(STp, aSRpnt, 1);
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = WRITE_6;
@@ -2925,7 +3000,7 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
#endif
SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, SCSI_DATA_WRITE,
- STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
*aSRpnt = SRpnt;
if (!SRpnt)
return (-EBUSY);
@@ -2967,12 +3042,12 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
/* Flush the tape buffer. The tape will be positioned correctly unless
seek_next is true. */
-static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int seek_next)
+static int osst_flush_buffer(struct osst_tape * STp, struct scsi_request ** aSRpnt, int seek_next)
{
struct st_partstat * STps;
- int backspace = 0, result = 0;
+ int backspace = 0, result = 0;
#if DEBUG
- char * name = tape_name(STp);
+ char * name = tape_name(STp);
#endif
/*
@@ -3029,13 +3104,13 @@ static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int see
return result;
}
-static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int synchronous)
+static int osst_write_frame(struct osst_tape * STp, struct scsi_request ** aSRpnt, int synchronous)
{
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt;
- int blks;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt;
+ int blks;
#if DEBUG
- char * name = tape_name(STp);
+ char * name = tape_name(STp);
#endif
if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
@@ -3055,8 +3130,9 @@ static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sync
}
if (STp->poll)
- osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 60);
- /* TODO: Check for an error ! */
+ if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
+ if (osst_recover_wait_frame(STp, aSRpnt, 1))
+ return (-EIO);
// osst_build_stats(STp, &SRpnt);
@@ -3081,7 +3157,7 @@ static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sync
STp->write_pending = 1;
#endif
SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE, STp->timeout,
- MAX_WRITE_RETRIES, synchronous);
+ MAX_RETRIES, synchronous);
if (!SRpnt)
return (-EBUSY);
*aSRpnt = SRpnt;
@@ -3111,8 +3187,8 @@ static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sync
return 0;
}
-/* Lock or unlock the drive door. Don't use when Scsi_Request allocated. */
-static int do_door_lock(OS_Scsi_Tape * STp, int do_lock)
+/* Lock or unlock the drive door. Don't use when struct scsi_request allocated. */
+static int do_door_lock(struct osst_tape * STp, int do_lock)
{
int retval, cmd;
@@ -3131,7 +3207,7 @@ static int do_door_lock(OS_Scsi_Tape * STp, int do_lock)
}
/* Set the internal state after reset */
-static void reset_state(OS_Scsi_Tape *STp)
+static void reset_state(struct osst_tape *STp)
{
int i;
struct st_partstat *STps;
@@ -3154,16 +3230,16 @@ static void reset_state(OS_Scsi_Tape *STp)
/* Write command */
static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
{
- ssize_t total, retval = 0;
- ssize_t i, do_count, blks, transfer;
- int write_threshold;
- int doing_write = 0;
+ ssize_t total, retval = 0;
+ ssize_t i, do_count, blks, transfer;
+ int write_threshold;
+ int doing_write = 0;
const char __user * b_point;
- Scsi_Request * SRpnt = NULL;
+ struct scsi_request * SRpnt = NULL;
struct st_modedef * STm;
struct st_partstat * STps;
- OS_Scsi_Tape * STp = filp->private_data;
- char * name = tape_name(STp);
+ struct osst_tape * STp = filp->private_data;
+ char * name = tape_name(STp);
if (down_interruptible(&STp->lock))
@@ -3477,14 +3553,14 @@ out:
/* Read command */
static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
{
- ssize_t total, retval = 0;
- ssize_t i, transfer;
- int special;
- struct st_modedef * STm;
+ ssize_t total, retval = 0;
+ ssize_t i, transfer;
+ int special;
+ struct st_modedef * STm;
struct st_partstat * STps;
- Scsi_Request * SRpnt = NULL;
- OS_Scsi_Tape * STp = filp->private_data;
- char * name = tape_name(STp);
+ struct scsi_request * SRpnt = NULL;
+ struct osst_tape * STp = filp->private_data;
+ char * name = tape_name(STp);
if (down_interruptible(&STp->lock))
@@ -3660,8 +3736,7 @@ out:
/* Set the driver options */
-static void osst_log_options(OS_Scsi_Tape *STp, struct st_modedef *STm,
- char *name)
+static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
{
printk(KERN_INFO
"%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
@@ -3684,12 +3759,12 @@ static void osst_log_options(OS_Scsi_Tape *STp, struct st_modedef *STm,
}
-static int osst_set_options(OS_Scsi_Tape *STp, long options)
+static int osst_set_options(struct osst_tape *STp, long options)
{
- int value;
- long code;
+ int value;
+ long code;
struct st_modedef * STm;
- char * name = tape_name(STp);
+ char * name = tape_name(STp);
STm = &(STp->modes[STp->current_mode]);
if (!STm->defined) {
@@ -3840,18 +3915,19 @@ static int osst_set_options(OS_Scsi_Tape *STp, long options)
/* Internal ioctl function */
-static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned int cmd_in, unsigned long arg)
+static int osst_int_ioctl(struct osst_tape * STp, struct scsi_request ** aSRpnt,
+ unsigned int cmd_in, unsigned long arg)
{
- int timeout;
- long ltmp;
- int i, ioctl_result;
- int chg_eof = TRUE;
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt = * aSRpnt;
- struct st_partstat * STps;
- int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
- int datalen = 0, direction = SCSI_DATA_NONE;
- char * name = tape_name(STp);
+ int timeout;
+ long ltmp;
+ int i, ioctl_result;
+ int chg_eof = TRUE;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt = * aSRpnt;
+ struct st_partstat * STps;
+ int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
+ int datalen = 0, direction = SCSI_DATA_NONE;
+ char * name = tape_name(STp);
if (STp->ready != ST_READY && cmd_in != MTLOAD) {
if (STp->ready == ST_NO_TAPE)
@@ -4227,16 +4303,16 @@ os_bypass:
/* Open the device */
static int os_scsi_tape_open(struct inode * inode, struct file * filp)
{
- unsigned short flags;
- int i, b_size, new_session = FALSE, retval = 0;
- unsigned char cmd[MAX_COMMAND_SIZE];
- Scsi_Request * SRpnt = NULL;
- OS_Scsi_Tape * STp;
- struct st_modedef * STm;
+ unsigned short flags;
+ int i, b_size, new_session = FALSE, retval = 0;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ struct scsi_request * SRpnt = NULL;
+ struct osst_tape * STp;
+ struct st_modedef * STm;
struct st_partstat * STps;
- char * name;
- int dev = TAPE_NR(inode);
- int mode = TAPE_MODE(inode);
+ char * name;
+ int dev = TAPE_NR(inode);
+ int mode = TAPE_MODE(inode);
nonseekable_open(inode, filp);
write_lock(&os_scsi_tapes_lock);
@@ -4327,9 +4403,9 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
memset (cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
- SRpnt = osst_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
+ SRpnt = osst_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
if (!SRpnt) {
- retval = (STp->buffer)->syscall_result;
+ retval = (STp->buffer)->syscall_result; /* FIXME - valid? */
goto err_out;
}
if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
@@ -4348,7 +4424,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
cmd[1] = 1;
cmd[4] = 1;
SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
- STp->timeout, MAX_READY_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
}
osst_wait_ready(STp, &SRpnt, (SRpnt->sr_sense_buffer[13]==1?15:3) * 60, 0);
}
@@ -4365,7 +4441,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
cmd[0] = TEST_UNIT_READY;
SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
- STp->timeout, MAX_READY_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
(SRpnt->sr_sense_buffer[2] & 0x0f) != UNIT_ATTENTION)
break;
@@ -4386,6 +4462,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
}
new_session = TRUE;
STp->recover_count = 0;
+ STp->abort_count = 0;
}
/*
* if we have valid headers from before, and the drive/tape seem untouched,
@@ -4473,7 +4550,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
cmd[0] = TEST_UNIT_READY;
SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
- STp->timeout, MAX_READY_RETRIES, TRUE);
+ STp->timeout, MAX_RETRIES, TRUE);
if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
(SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY)
break;
@@ -4588,12 +4665,12 @@ err_out:
/* Flush the tape buffer before close */
static int os_scsi_tape_flush(struct file * filp)
{
- int result = 0, result2;
- OS_Scsi_Tape * STp = filp->private_data;
- struct st_modedef * STm = &(STp->modes[STp->current_mode]);
- struct st_partstat * STps = &(STp->ps[STp->partition]);
- Scsi_Request * SRpnt = NULL;
- char * name = tape_name(STp);
+ int result = 0, result2;
+ struct osst_tape * STp = filp->private_data;
+ struct st_modedef * STm = &(STp->modes[STp->current_mode]);
+ struct st_partstat * STps = &(STp->ps[STp->partition]);
+ struct scsi_request * SRpnt = NULL;
+ char * name = tape_name(STp);
if (file_count(filp) > 1)
return 0;
@@ -4657,14 +4734,19 @@ out:
}
if (SRpnt) scsi_release_request(SRpnt);
- if (STp->recover_count) {
- printk(KERN_INFO "%s:I: %d recovered errors in", name, STp->recover_count);
+ if (STp->abort_count || STp->recover_count) {
+ printk(KERN_INFO "%s:I:", name);
+ if (STp->abort_count)
+ printk(" %d unrecovered errors", STp->abort_count);
+ if (STp->recover_count)
+ printk(" %d recovered errors", STp->recover_count);
if (STp->write_count)
- printk(" %d frames written", STp->write_count);
+ printk(" in %d frames written", STp->write_count);
if (STp->read_count)
- printk(" %d frames read", STp->read_count);
+ printk(" in %d frames read", STp->read_count);
printk("\n");
STp->recover_count = 0;
+ STp->abort_count = 0;
}
STp->write_count = 0;
STp->read_count = 0;
@@ -4676,9 +4758,9 @@ out:
/* Close the device and release it */
static int os_scsi_tape_close(struct inode * inode, struct file * filp)
{
- int result = 0;
- OS_Scsi_Tape * STp = filp->private_data;
- Scsi_Request * SRpnt = NULL;
+ int result = 0;
+ struct osst_tape * STp = filp->private_data;
+ struct scsi_request * SRpnt = NULL;
if (SRpnt) scsi_release_request(SRpnt);
@@ -4703,14 +4785,14 @@ static int os_scsi_tape_close(struct inode * inode, struct file * filp)
static int osst_ioctl(struct inode * inode,struct file * file,
unsigned int cmd_in, unsigned long arg)
{
- int i, cmd_nr, cmd_type, retval = 0;
- unsigned int blk;
- struct st_modedef * STm;
+ int i, cmd_nr, cmd_type, retval = 0;
+ unsigned int blk;
+ struct st_modedef * STm;
struct st_partstat * STps;
- Scsi_Request * SRpnt = NULL;
- OS_Scsi_Tape * STp = file->private_data;
- char * name = tape_name(STp);
- void __user *p = (void __user *)arg;
+ struct scsi_request * SRpnt = NULL;
+ struct osst_tape * STp = file->private_data;
+ char * name = tape_name(STp);
+ void __user * p = (void __user *)arg;
if (down_interruptible(&STp->lock))
return -ERESTARTSYS;
@@ -5039,18 +5121,18 @@ out:
/* Memory handling routines */
/* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
-static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
+static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
{
int i, priority;
- OSST_buffer *tb;
+ struct osst_buffer *tb;
if (from_initialization)
priority = GFP_ATOMIC;
else
priority = GFP_KERNEL;
- i = sizeof(OSST_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
- tb = (OSST_buffer *)kmalloc(i, priority);
+ i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
+ tb = (struct osst_buffer *)kmalloc(i, priority);
if (!tb) {
printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
return NULL;
@@ -5071,7 +5153,7 @@ static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma, int
}
/* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
-static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma)
+static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
{
int segs, nbr, max_segs, b_size, priority, order, got;
@@ -5087,12 +5169,10 @@ static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma)
if (nbr <= 2)
return FALSE;
- priority = GFP_KERNEL;
+ priority = GFP_KERNEL /* | __GFP_NOWARN */;
if (need_dma)
priority |= GFP_DMA;
- priority |= __GFP_NOWARN;
-
/* Try to allocate the first segment up to OS_DATA_SIZE and the others
big enough to reach the goal (code assumes no segments in place) */
for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
@@ -5150,7 +5230,7 @@ static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma)
/* Release the segments */
-static void normalize_buffer(OSST_buffer *STbuffer)
+static void normalize_buffer(struct osst_buffer *STbuffer)
{
int i, order, b_size;
@@ -5174,7 +5254,7 @@ static void normalize_buffer(OSST_buffer *STbuffer)
/* Move data from the user buffer to the tape buffer. Returns zero (success) or
negative error code. */
-static int append_to_buffer(const char __user *ubp, OSST_buffer *st_bp, int do_count)
+static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
{
int i, cnt, res, offset;
@@ -5207,7 +5287,7 @@ static int append_to_buffer(const char __user *ubp, OSST_buffer *st_bp, int do_c
/* Move data from the tape buffer to the user buffer. Returns zero (success) or
negative error code. */
-static int from_buffer(OSST_buffer *st_bp, char __user *ubp, int do_count)
+static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
{
int i, cnt, res, offset;
@@ -5239,7 +5319,7 @@ static int from_buffer(OSST_buffer *st_bp, char __user *ubp, int do_count)
/* Sets the tail of the buffer after fill point to zero.
Returns zero (success) or negative error code. */
-static int osst_zero_buffer_tail(OSST_buffer *st_bp)
+static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
{
int i, offset, do_count, cnt;
@@ -5267,7 +5347,7 @@ static int osst_zero_buffer_tail(OSST_buffer *st_bp)
/* Copy a osst 32K chunk of memory into the buffer.
Returns zero (success) or negative error code. */
-static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr)
+static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
{
int i, cnt, do_count = OS_DATA_SIZE;
@@ -5288,7 +5368,7 @@ static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr)
/* Copy a osst 32K chunk of memory from the buffer.
Returns zero (success) or negative error code. */
-static int osst_copy_from_buffer(OSST_buffer *st_bp, unsigned char *ptr)
+static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
{
int i, cnt, do_count = OS_DATA_SIZE;
@@ -5406,18 +5486,163 @@ static struct osst_support_data support_list[] = {
}
/*
+ * sysfs support for osst driver parameter information
+ */
+
+static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
+}
+
+static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
+
+static void osst_create_driverfs_files(struct device_driver *driverfs)
+{
+ driver_create_file(driverfs, &driver_attr_version);
+}
+
+static void osst_remove_driverfs_files(struct device_driver *driverfs)
+{
+ driver_remove_file(driverfs, &driver_attr_version);
+}
+
+/*
+ * sysfs support for accessing ADR header information
+ */
+
+static ssize_t osst_adr_rev_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
+
+static ssize_t osst_linux_media_version_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
+
+static ssize_t osst_capacity_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
+
+static ssize_t osst_first_data_ppos_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
+
+static ssize_t osst_eod_frame_ppos_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
+
+static ssize_t osst_filemark_cnt_show(struct class_device *class_dev, char *buf)
+{
+ struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
+ return l;
+}
+
+CLASS_DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
+
+static struct class_simple * osst_sysfs_class;
+
+static int osst_sysfs_valid = 0;
+
+static void osst_sysfs_init(void)
+{
+ osst_sysfs_class = class_simple_create(THIS_MODULE, "onstream_tape");
+ if ( IS_ERR(osst_sysfs_class) )
+ printk(KERN_WARNING "osst :W: Unable to register sysfs class\n");
+ else
+ osst_sysfs_valid = TRUE;
+}
+
+static void osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
+{
+ struct class_device *osst_class_member;
+
+ if (!osst_sysfs_valid) return;
+
+ osst_class_member = class_simple_device_add(osst_sysfs_class, dev, device, "%s", name);
+ if (IS_ERR(osst_class_member)) {
+ printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
+ return;
+ }
+ class_set_devdata(osst_class_member, STp);
+ class_device_create_file(osst_class_member, &class_device_attr_ADR_rev);
+ class_device_create_file(osst_class_member, &class_device_attr_media_version);
+ class_device_create_file(osst_class_member, &class_device_attr_capacity);
+ class_device_create_file(osst_class_member, &class_device_attr_BOT_frame);
+ class_device_create_file(osst_class_member, &class_device_attr_EOD_frame);
+ class_device_create_file(osst_class_member, &class_device_attr_file_count);
+}
+
+static void osst_sysfs_destroy(dev_t dev)
+{
+ if (!osst_sysfs_valid) return;
+
+ class_simple_device_remove(dev);
+}
+
+static void osst_sysfs_cleanup(void)
+{
+ if (osst_sysfs_valid) {
+ class_simple_destroy(osst_sysfs_class);
+ osst_sysfs_valid = 0;
+ }
+}
+
+/*
* osst startup / cleanup code
*/
static int osst_probe(struct device *dev)
{
- Scsi_Device * SDp = to_scsi_device(dev);
- OS_Scsi_Tape * tpnt;
- struct st_modedef * STm;
- struct st_partstat * STps;
- OSST_buffer * buffer;
- struct gendisk * drive;
- int i, mode, dev_num;
+ Scsi_Device * SDp = to_scsi_device(dev);
+ struct osst_tape * tpnt;
+ struct st_modedef * STm;
+ struct st_partstat * STps;
+ struct osst_buffer * buffer;
+ struct gendisk * drive;
+ int i, mode, dev_num;
if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
return -ENODEV;
@@ -5432,7 +5657,7 @@ static int osst_probe(struct device *dev)
write_lock(&os_scsi_tapes_lock);
if (os_scsi_tapes == NULL) {
os_scsi_tapes =
- (OS_Scsi_Tape **)kmalloc(osst_max_dev * sizeof(OS_Scsi_Tape *),
+ (struct osst_tape **)kmalloc(osst_max_dev * sizeof(struct osst_tape *),
GFP_ATOMIC);
if (os_scsi_tapes == NULL) {
write_unlock(&os_scsi_tapes_lock);
@@ -5453,14 +5678,14 @@ static int osst_probe(struct device *dev)
if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
dev_num = i;
- /* allocate a OS_Scsi_Tape for this device */
- tpnt = (OS_Scsi_Tape *)kmalloc(sizeof(OS_Scsi_Tape), GFP_ATOMIC);
+ /* allocate a struct osst_tape for this device */
+ tpnt = (struct osst_tape *)kmalloc(sizeof(struct osst_tape), GFP_ATOMIC);
if (tpnt == NULL) {
write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
goto out_put_disk;
}
- memset(tpnt, 0, sizeof(OS_Scsi_Tape));
+ memset(tpnt, 0, sizeof(struct osst_tape));
/* allocate a buffer for this device */
i = SDp->host->sg_tablesize;
@@ -5545,7 +5770,14 @@ static int osst_probe(struct device *dev)
init_MUTEX(&tpnt->lock);
osst_nr_dev++;
write_unlock(&os_scsi_tapes_lock);
-
+ {
+ char name[8];
+ /* Rewind entry */
+ osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
+ /* No-rewind entry */
+ snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
+ osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
+ }
for (mode = 0; mode < ST_NBR_MODES; ++mode) {
/* Rewind entry */
devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)),
@@ -5572,8 +5804,8 @@ out_put_disk:
static int osst_remove(struct device *dev)
{
- Scsi_Device * SDp = to_scsi_device(dev);
- OS_Scsi_Tape * tpnt;
+ Scsi_Device * SDp = to_scsi_device(dev);
+ struct osst_tape * tpnt;
int i, mode;
if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
@@ -5582,6 +5814,8 @@ static int osst_remove(struct device *dev)
write_lock(&os_scsi_tapes_lock);
for(i=0; i < osst_max_dev; i++) {
if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
+ osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
+ osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
tpnt->device = NULL;
for (mode = 0; mode < ST_NBR_MODES; ++mode) {
devfs_remove("%s/ot%s", SDp->devfs_name, osst_formats[mode]);
@@ -5610,11 +5844,14 @@ static int __init init_osst(void)
printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
validate_options();
-
+ osst_sysfs_init();
+
if ((register_chrdev(OSST_MAJOR,"osst", &osst_fops) < 0) || scsi_register_driver(&osst_template.gendrv)) {
printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
+ osst_sysfs_cleanup();
return 1;
}
+ osst_create_driverfs_files(&osst_template.gendrv);
return 0;
}
@@ -5622,10 +5859,12 @@ static int __init init_osst(void)
static void __exit exit_osst (void)
{
int i;
- OS_Scsi_Tape * STp;
+ struct osst_tape * STp;
+ osst_remove_driverfs_files(&osst_template.gendrv);
scsi_unregister_driver(&osst_template.gendrv);
unregister_chrdev(OSST_MAJOR, "osst");
+ osst_sysfs_cleanup();
if (os_scsi_tapes) {
for (i=0; i < osst_max_dev; ++i) {
diff --git a/drivers/scsi/osst.h b/drivers/scsi/osst.h
index 84bbc591a8ce..1561d4ded72b 100644
--- a/drivers/scsi/osst.h
+++ b/drivers/scsi/osst.h
@@ -1,5 +1,5 @@
/*
- * $Header: /cvsroot/osst/Driver/osst.h,v 1.14 2003/12/14 14:34:38 wriede Exp $
+ * $Header: /cvsroot/osst/Driver/osst.h,v 1.16 2005/01/01 21:13:35 wriede Exp $
*/
#include <asm/byteorder.h>
@@ -70,7 +70,7 @@ typedef struct {
#define BLOCK_SIZE_PAGE_LENGTH 4
#define BUFFER_FILLING_PAGE 0x33
-#define BUFFER_FILLING_PAGE_LENGTH
+#define BUFFER_FILLING_PAGE_LENGTH 4
#define VENDOR_IDENT_PAGE 0x36
#define VENDOR_IDENT_PAGE_LENGTH 8
@@ -508,7 +508,7 @@ typedef struct os_header_s {
//#define OSST_MAX_SG 2
/* The OnStream tape buffer descriptor. */
-typedef struct {
+struct osst_buffer {
unsigned char in_use;
unsigned char dma; /* DMA-able buffer */
int buffer_size;
@@ -525,16 +525,16 @@ typedef struct {
unsigned short sg_segs; /* number of segments in s/g list */
unsigned short orig_sg_segs; /* number of segments allocated at first try */
struct scatterlist sg[1]; /* MUST BE last item */
-} OSST_buffer;
+} ;
/* The OnStream tape drive descriptor */
-typedef struct {
+struct osst_tape {
struct scsi_driver *driver;
unsigned capacity;
Scsi_Device* device;
struct semaphore lock; /* for serialization */
struct completion wait; /* for SCSI commands */
- OSST_buffer * buffer;
+ struct osst_buffer * buffer;
/* Drive characteristics */
unsigned char omit_blklims;
@@ -577,6 +577,7 @@ typedef struct {
int min_block;
int max_block;
int recover_count; /* from tape opening */
+ int abort_count;
int write_count;
int read_count;
int recover_erreg; /* from last status call */
@@ -623,7 +624,7 @@ typedef struct {
unsigned char last_sense[16];
#endif
struct gendisk *drive;
-} OS_Scsi_Tape;
+} ;
/* Values of write_type */
#define OS_WRITE_DATA 0
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index c0b9e1cc20ca..97d69da43825 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -145,7 +145,6 @@ static dev_link_t *aha152x_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.event_handler = &aha152x_event;
client_reg.EventMask =
CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
@@ -347,10 +346,7 @@ static int __init init_aha152x_cs(void)
static void __exit exit_aha152x_cs(void)
{
pcmcia_unregister_driver(&aha152x_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- aha152x_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_aha152x_cs);
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index c841137e73a9..343b67578706 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -131,7 +131,6 @@ static dev_link_t *fdomain_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.event_handler = &fdomain_event;
client_reg.EventMask =
CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
@@ -328,10 +327,7 @@ static int __init init_fdomain_cs(void)
static void __exit exit_fdomain_cs(void)
{
pcmcia_unregister_driver(&fdomain_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- fdomain_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_fdomain_cs);
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 0d0bbd26a5f2..8aae1ae9fa9b 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1672,7 +1672,6 @@ static dev_link_t *nsp_cs_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -2194,10 +2193,9 @@ static void __exit nsp_cs_exit(void)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
pcmcia_unregister_driver(&nsp_driver);
+ BUG_ON(dev_list != NULL);
#else
unregister_pcmcia_driver(&dev_info);
-#endif
-
/* XXX: this really needs to move into generic code.. */
while (dev_list != NULL) {
if (dev_list->state & DEV_CONFIG) {
@@ -2205,6 +2203,7 @@ static void __exit nsp_cs_exit(void)
}
nsp_cs_detach(dev_list);
}
+#endif
}
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 584b51314041..4b66969ace4a 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -212,7 +212,6 @@ static dev_link_t *qlogic_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.event_handler = &qlogic_event;
client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
client_reg.Version = 0x0210;
@@ -432,10 +431,7 @@ static int __init init_qlogic_cs(void)
static void __exit exit_qlogic_cs(void)
{
pcmcia_unregister_driver(&qlogic_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- qlogic_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
MODULE_AUTHOR("Tom Zerucha, Michael Griffith");
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 84d06345614e..be3d3369cae6 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -995,7 +995,6 @@ SYM53C500_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.event_handler = &SYM53C500_event;
client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index f1eb31b95579..df89d2b7c30f 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -3400,7 +3400,8 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
sp->flags |= SRB_SENT;
ha->actthreads++;
WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
- (void) RD_REG_WORD(&reg->mailbox4); /* PCI posted write flush */
+ /* Enforce mmio write ordering; see comment in qla1280_isp_cmd(). */
+ mmiowb();
out:
if (status)
@@ -3668,7 +3669,8 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
sp->flags |= SRB_SENT;
ha->actthreads++;
WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
- (void) RD_REG_WORD(&reg->mailbox4); /* PCI posted write flush */
+ /* Enforce mmio write ordering; see comment in qla1280_isp_cmd(). */
+ mmiowb();
out:
if (status)
@@ -3778,9 +3780,21 @@ qla1280_isp_cmd(struct scsi_qla_host *ha)
} else
ha->request_ring_ptr++;
- /* Set chip new ring index. */
+ /*
+ * Update request index to mailbox4 (Request Queue In).
+ * The mmiowb() ensures that this write is ordered with writes by other
+ * CPUs. Without the mmiowb(), it is possible for the following:
+ * CPUA posts write of index 5 to mailbox4
+ * CPUA releases host lock
+ * CPUB acquires host lock
+ * CPUB posts write of index 6 to mailbox4
+ * On PCI bus, order reverses and write of 6 posts, then index 5,
+ * causing chip to issue full queue of stale commands
+ * The mmiowb() prevents future writes from crossing the barrier.
+ * See Documentation/DocBook/deviceiobook.tmpl for more information.
+ */
WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
- (void) RD_REG_WORD(&reg->mailbox4); /* PCI posted write flush */
+ mmiowb();
LEAVE("qla1280_isp_cmd");
}
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 80e75bd5a439..2952d9e159fb 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -71,6 +71,8 @@ static struct pci_device_id sil_pci_tbl[] = {
{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
+ { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+ { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ } /* terminate list */
};
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 82c7b0ab4047..63e5224eee0a 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1083,6 +1083,28 @@ struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *shost,
EXPORT_SYMBOL(__scsi_iterate_devices);
/**
+ * starget_for_each_device - helper to walk all devices of a target
+ * @starget: target whose devices we want to iterate over.
+ *
+ * This traverses over each devices of @shost. The devices have
+ * a reference that must be released by scsi_host_put when breaking
+ * out of the loop.
+ */
+void starget_for_each_device(struct scsi_target *starget, void * data,
+ void (*fn)(struct scsi_device *, void *))
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, shost) {
+ if ((sdev->channel == starget->channel) &&
+ (sdev->id == starget->id))
+ fn(sdev, data);
+ }
+}
+EXPORT_SYMBOL(starget_for_each_device);
+
+/**
* scsi_device_lookup - find a device given the host (UNLOCKED)
* @shost: SCSI host pointer
* @channel: SCSI channel (zero if only one channel)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 73660628b520..38f165070c94 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1782,31 +1782,29 @@ scsi_device_resume(struct scsi_device *sdev)
}
EXPORT_SYMBOL(scsi_device_resume);
-static int
-device_quiesce_fn(struct device *dev, void *data)
+static void
+device_quiesce_fn(struct scsi_device *sdev, void *data)
{
- scsi_device_quiesce(to_scsi_device(dev));
- return 0;
+ scsi_device_quiesce(sdev);
}
void
scsi_target_quiesce(struct scsi_target *starget)
{
- device_for_each_child(&starget->dev, NULL, device_quiesce_fn);
+ starget_for_each_device(starget, NULL, device_quiesce_fn);
}
EXPORT_SYMBOL(scsi_target_quiesce);
-static int
-device_resume_fn(struct device *dev, void *data)
+static void
+device_resume_fn(struct scsi_device *sdev, void *data)
{
- scsi_device_resume(to_scsi_device(dev));
- return 0;
+ scsi_device_resume(sdev);
}
void
scsi_target_resume(struct scsi_target *starget)
{
- device_for_each_child(&starget->dev, NULL, device_resume_fn);
+ starget_for_each_device(starget, NULL, device_resume_fn);
}
EXPORT_SYMBOL(scsi_target_resume);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 926cec15e5f2..1aca210eabd1 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -270,6 +270,16 @@ static int fc_setup_host_transport_attrs(struct Scsi_Host *shost)
sizeof(fc_host_symbolic_name(shost)));
fc_host_supported_speeds(shost) = FC_PORTSPEED_UNKNOWN;
fc_host_maxframe_size(shost) = -1;
+ memset(fc_host_hardware_version(shost), 0,
+ sizeof(fc_host_hardware_version(shost)));
+ memset(fc_host_firmware_version(shost), 0,
+ sizeof(fc_host_firmware_version(shost)));
+ memset(fc_host_serial_number(shost), 0,
+ sizeof(fc_host_serial_number(shost)));
+ memset(fc_host_opt_rom_version(shost), 0,
+ sizeof(fc_host_opt_rom_version(shost)));
+ memset(fc_host_driver_version(shost), 0,
+ sizeof(fc_host_driver_version(shost)));
fc_host_port_id(shost) = -1;
fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
@@ -536,6 +546,11 @@ fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1));
fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
+fc_private_host_rd_attr(hardware_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
+fc_private_host_rd_attr(firmware_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
+fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
+fc_private_host_rd_attr(opt_rom_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
+fc_private_host_rd_attr(driver_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
/* Dynamic Host Attributes */
@@ -772,6 +787,11 @@ fc_attach_transport(struct fc_function_template *ft)
SETUP_HOST_ATTRIBUTE_RD(symbolic_name);
SETUP_HOST_ATTRIBUTE_RD(supported_speeds);
SETUP_HOST_ATTRIBUTE_RD(maxframe_size);
+ SETUP_HOST_ATTRIBUTE_RD(hardware_version);
+ SETUP_HOST_ATTRIBUTE_RD(firmware_version);
+ SETUP_HOST_ATTRIBUTE_RD(serial_number);
+ SETUP_HOST_ATTRIBUTE_RD(opt_rom_version);
+ SETUP_HOST_ATTRIBUTE_RD(driver_version);
SETUP_HOST_ATTRIBUTE_RD(port_id);
SETUP_HOST_ATTRIBUTE_RD(port_type);
@@ -808,10 +828,9 @@ EXPORT_SYMBOL(fc_release_transport);
* @dev: scsi device
* @data: unused
**/
-static int fc_device_block(struct device *dev, void *data)
+static void fc_device_block(struct scsi_device *sdev, void *data)
{
- scsi_internal_device_block(to_scsi_device(dev));
- return 0;
+ scsi_internal_device_block(sdev);
}
/**
@@ -819,10 +838,9 @@ static int fc_device_block(struct device *dev, void *data)
* @dev: scsi device
* @data: unused
**/
-static int fc_device_unblock(struct device *dev, void *data)
+static void fc_device_unblock(struct scsi_device *sdev, void *data)
{
- scsi_internal_device_unblock(to_scsi_device(dev));
- return 0;
+ scsi_internal_device_unblock(sdev);
}
/**
@@ -842,7 +860,7 @@ static void fc_timeout_blocked_tgt(void *data)
* unblock this device, then IO errors will probably
* result if the host still isn't ready.
*/
- device_for_each_child(&starget->dev, NULL, fc_device_unblock);
+ starget_for_each_device(starget, NULL, fc_device_unblock);
}
/**
@@ -870,7 +888,7 @@ fc_target_block(struct scsi_target *starget)
if (timeout < 0 || timeout > SCSI_DEVICE_BLOCK_MAX_TIMEOUT)
return -EINVAL;
- device_for_each_child(&starget->dev, NULL, fc_device_block);
+ starget_for_each_device(starget, NULL, fc_device_block);
/* The scsi lld blocks this target for the timeout period only. */
schedule_delayed_work(work, timeout * HZ);
@@ -901,7 +919,7 @@ fc_target_unblock(struct scsi_target *starget)
if (cancel_delayed_work(&fc_starget_dev_loss_work(starget)))
flush_scheduled_work();
- device_for_each_child(&starget->dev, NULL, fc_device_unblock);
+ starget_for_each_device(starget, NULL, fc_device_unblock);
}
EXPORT_SYMBOL(fc_target_unblock);
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index f01133b4c580..d8bdde36fe44 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -31,6 +31,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_request.h>
+#include <scsi/scsi_eh.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
@@ -378,10 +379,16 @@ static CLASS_DEVICE_ATTR(signalling, S_IRUGO | S_IWUSR,
#define DV_RETRIES 3 /* should only need at most
* two cc/ua clears */
+enum spi_compare_returns {
+ SPI_COMPARE_SUCCESS,
+ SPI_COMPARE_FAILURE,
+ SPI_COMPARE_SKIP_TEST,
+};
+
/* This is for read/write Domain Validation: If the device supports
* an echo buffer, we do read/write tests to it */
-static int
+static enum spi_compare_returns
spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
u8 *ptr, const int retries)
{
@@ -438,9 +445,23 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
scsi_wait_req(sreq, spi_write_buffer, buffer, len,
DV_TIMEOUT, DV_RETRIES);
if(sreq->sr_result || !scsi_device_online(sdev)) {
+ struct scsi_sense_hdr sshdr;
+
scsi_device_set_state(sdev, SDEV_QUIESCE);
+ if (scsi_request_normalize_sense(sreq, &sshdr)
+ && sshdr.sense_key == ILLEGAL_REQUEST
+ /* INVALID FIELD IN CDB */
+ && sshdr.asc == 0x24 && sshdr.ascq == 0x00)
+ /* This would mean that the drive lied
+ * to us about supporting an echo
+ * buffer (unfortunately some Western
+ * Digital drives do precisely this)
+ */
+ return SPI_COMPARE_SKIP_TEST;
+
+
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result);
- return 0;
+ return SPI_COMPARE_FAILURE;
}
memset(ptr, 0, len);
@@ -451,14 +472,14 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
scsi_device_set_state(sdev, SDEV_QUIESCE);
if (memcmp(buffer, ptr, len) != 0)
- return 0;
+ return SPI_COMPARE_FAILURE;
}
- return 1;
+ return SPI_COMPARE_SUCCESS;
}
/* This is for the simplest form of Domain Validation: a read test
* on the inquiry data from the device */
-static int
+static enum spi_compare_returns
spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
u8 *ptr, const int retries)
{
@@ -480,7 +501,7 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
if(sreq->sr_result || !scsi_device_online(sdev)) {
scsi_device_set_state(sdev, SDEV_QUIESCE);
- return 0;
+ return SPI_COMPARE_FAILURE;
}
/* If we don't have the inquiry data already, the
@@ -493,24 +514,28 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
if (memcmp(buffer, ptr, len) != 0)
/* failure */
- return 0;
+ return SPI_COMPARE_FAILURE;
}
- return 1;
+ return SPI_COMPARE_SUCCESS;
}
-static int
+static enum spi_compare_returns
spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
- int (*compare_fn)(struct scsi_request *, u8 *, u8 *, int))
+ enum spi_compare_returns
+ (*compare_fn)(struct scsi_request *, u8 *, u8 *, int))
{
struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
struct scsi_device *sdev = sreq->sr_device;
int period = 0, prevperiod = 0;
+ enum spi_compare_returns retval;
for (;;) {
int newperiod;
- if (compare_fn(sreq, buffer, ptr, DV_LOOPS))
- /* Successful DV */
+ retval = compare_fn(sreq, buffer, ptr, DV_LOOPS);
+
+ if (retval == SPI_COMPARE_SUCCESS
+ || retval == SPI_COMPARE_SKIP_TEST)
break;
/* OK, retrain, fallback */
@@ -527,13 +552,13 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
/* Total failure; set to async and return */
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n");
DV_SET(offset, 0);
- return 0;
+ return SPI_COMPARE_FAILURE;
}
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation detected failure, dropping back\n");
DV_SET(period, period);
prevperiod = period;
}
- return 1;
+ return retval;
}
static int
@@ -599,7 +624,8 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
DV_SET(offset, 0);
DV_SET(width, 0);
- if (!spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)) {
+ if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)
+ != SPI_COMPARE_SUCCESS) {
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
/* FIXME: should probably offline the device here? */
return;
@@ -609,9 +635,10 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
if (i->f->set_width && sdev->wdtr) {
i->f->set_width(sdev->sdev_target, 1);
- if (!spi_dv_device_compare_inquiry(sreq, buffer,
+ if (spi_dv_device_compare_inquiry(sreq, buffer,
buffer + len,
- DV_LOOPS)) {
+ DV_LOOPS)
+ != SPI_COMPARE_SUCCESS) {
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Wide Transfers Fail\n");
i->f->set_width(sdev->sdev_target, 0);
}
@@ -624,31 +651,39 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
if(!sdev->ppr && !sdev->sdtr)
return;
- /* now set up to the maximum */
- DV_SET(offset, 255);
- DV_SET(period, 1);
- if (!spi_dv_retrain(sreq, buffer, buffer + len,
- spi_dv_device_compare_inquiry))
- return;
-
- /* OK, now we have our initial speed set by the read only inquiry
- * test, now try an echo buffer test (if the device allows it) */
+ /* see if the device has an echo buffer. If it does we can
+ * do the SPI pattern write tests */
len = 0;
if (sdev->ppr)
len = spi_dv_device_get_echo_buffer(sreq, buffer);
+ retry:
+
+ /* now set up to the maximum */
+ DV_SET(offset, 255);
+ DV_SET(period, 1);
+
if (len == 0) {
SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n");
+ spi_dv_retrain(sreq, buffer, buffer + len,
+ spi_dv_device_compare_inquiry);
return;
}
+
if (len > SPI_MAX_ECHO_BUFFER_SIZE) {
SPI_PRINTK(sdev->sdev_target, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE);
len = SPI_MAX_ECHO_BUFFER_SIZE;
}
- spi_dv_retrain(sreq, buffer, buffer + len,
- spi_dv_device_echo_buffer);
+ if (spi_dv_retrain(sreq, buffer, buffer + len,
+ spi_dv_device_echo_buffer)
+ == SPI_COMPARE_SKIP_TEST) {
+ /* OK, the stupid drive can't do a write echo buffer
+ * test after all, fall back to the read tests */
+ len = 0;
+ goto retry;
+ }
}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 0d10f106701d..86ee1e143580 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1082,9 +1082,12 @@ repeat:
" READ CAPACITY(16).\n", diskname);
longrc = 1;
goto repeat;
- } else {
- printk(KERN_ERR "%s: too big for kernel. Assuming maximum 2Tb\n", diskname);
}
+ printk(KERN_ERR "%s: too big for this kernel. Use a "
+ "kernel compiled with support for large block "
+ "devices.\n", diskname);
+ sdkp->capacity = 0;
+ goto got_data;
}
sdkp->capacity = 1 + (((sector_t)buffer[0] << 24) |
(buffer[1] << 16) |
diff --git a/drivers/scsi/sym53c8xx_2/sym_conf.h b/drivers/scsi/sym53c8xx_2/sym_conf.h
index b0f58e72570b..30bb92c90fc6 100644
--- a/drivers/scsi/sym53c8xx_2/sym_conf.h
+++ b/drivers/scsi/sym53c8xx_2/sym_conf.h
@@ -79,14 +79,6 @@
/* #define SYM_CONF_IARB_SUPPORT */
/*
- * Number of lists for the optimization of the IO timeout handling.
- * Not used under FreeBSD and Linux.
- */
-#ifndef SYM_CONF_TIMEOUT_ORDER_MAX
-#define SYM_CONF_TIMEOUT_ORDER_MAX (8)
-#endif
-
-/*
* Only relevant if IARB support configured.
* - Max number of successive settings of IARB hints.
* - Set IARB on arbitration lost.
diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
index 2e1d89f5de35..d27071dcb28b 100644
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h
@@ -40,30 +40,10 @@
#ifndef SYM_DEFS_H
#define SYM_DEFS_H
-#define SYM_VERSION "2.1.18m"
+#define SYM_VERSION "2.1.18n"
#define SYM_DRIVER_NAME "sym-" SYM_VERSION
/*
- * PCI device identifier of SYMBIOS chips.
- */
-#define PCI_ID_SYM53C810 PCI_DEVICE_ID_NCR_53C810
-#define PCI_ID_SYM53C810AP PCI_DEVICE_ID_LSI_53C810AP
-#define PCI_ID_SYM53C815 PCI_DEVICE_ID_NCR_53C815
-#define PCI_ID_SYM53C820 PCI_DEVICE_ID_NCR_53C820
-#define PCI_ID_SYM53C825 PCI_DEVICE_ID_NCR_53C825
-#define PCI_ID_SYM53C860 PCI_DEVICE_ID_NCR_53C860
-#define PCI_ID_SYM53C875 PCI_DEVICE_ID_NCR_53C875
-#define PCI_ID_SYM53C875_2 PCI_DEVICE_ID_NCR_53C875J
-#define PCI_ID_SYM53C885 PCI_DEVICE_ID_NCR_53C885
-#define PCI_ID_SYM53C895 PCI_DEVICE_ID_NCR_53C895
-#define PCI_ID_SYM53C896 PCI_DEVICE_ID_NCR_53C896
-#define PCI_ID_SYM53C895A PCI_DEVICE_ID_LSI_53C895A
-#define PCI_ID_SYM53C875A PCI_DEVICE_ID_LSI_53C875A
-#define PCI_ID_LSI53C1010_33 PCI_DEVICE_ID_LSI_53C1010_33
-#define PCI_ID_LSI53C1010_66 PCI_DEVICE_ID_LSI_53C1010_66
-#define PCI_ID_LSI53C1510D PCI_DEVICE_ID_LSI_53C1510
-
-/*
* SYM53C8XX device features descriptor.
*/
struct sym_pci_chip {
@@ -764,27 +744,27 @@ struct sym_tblsel {
#define M_RESTORE_DP RESTORE_POINTERS
#define M_DISCONNECT DISCONNECT
#define M_ID_ERROR INITIATOR_ERROR
-#define M_ABORT ABORT
+#define M_ABORT ABORT_TASK_SET
#define M_REJECT MESSAGE_REJECT
#define M_NOOP NOP
#define M_PARITY MSG_PARITY_ERROR
#define M_LCOMPLETE LINKED_CMD_COMPLETE
#define M_FCOMPLETE LINKED_FLG_CMD_COMPLETE
-#define M_RESET BUS_DEVICE_RESET
-#define M_ABORT_TAG (0x0d)
-#define M_CLEAR_QUEUE (0x0e)
+#define M_RESET TARGET_RESET
+#define M_ABORT_TAG ABORT_TASK
+#define M_CLEAR_QUEUE CLEAR_TASK_SET
#define M_INIT_REC INITIATE_RECOVERY
#define M_REL_REC RELEASE_RECOVERY
#define M_TERMINATE (0x11)
#define M_SIMPLE_TAG SIMPLE_QUEUE_TAG
#define M_HEAD_TAG HEAD_OF_QUEUE_TAG
#define M_ORDERED_TAG ORDERED_QUEUE_TAG
-#define M_IGN_RESIDUE (0x23)
+#define M_IGN_RESIDUE IGNORE_WIDE_RESIDUE
#define M_X_MODIFY_DP EXTENDED_MODIFY_DATA_POINTER
#define M_X_SYNC_REQ EXTENDED_SDTR
#define M_X_WIDE_REQ EXTENDED_WDTR
-#define M_X_PPR_REQ (0x04)
+#define M_X_PPR_REQ EXTENDED_PPR
/*
* PPR protocol options
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c
index c30d5cd65e97..1c6d0d182d2c 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw.c
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.c
@@ -223,13 +223,13 @@ sym_fw2_patch(struct sym_hcb *np)
* Remove a couple of work-arounds specific to C1010 if
* they are not desirable. See `sym_fw2.h' for more details.
*/
- if (!(np->device_id == PCI_ID_LSI53C1010_66 &&
+ if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_66 &&
np->revision_id < 0x1 &&
np->pciclk_khz < 60000)) {
scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP);
scripta0->datao_phase[1] = cpu_to_scr(0);
}
- if (!(np->device_id == PCI_ID_LSI53C1010_33 &&
+ if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
/* np->revision_id < 0xff */ 1)) {
scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP);
scripta0->sel_done[1] = cpu_to_scr(0);
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 4c64761be9c6..c389e55c3204 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -55,6 +55,15 @@
#define NAME53C "sym53c"
#define NAME53C8XX "sym53c8xx"
+/* SPARC just has to be different ... */
+#ifdef __sparc__
+#define IRQ_FMT "%s"
+#define IRQ_PRM(x) __irq_itoa(x)
+#else
+#define IRQ_FMT "%d"
+#define IRQ_PRM(x) (x)
+#endif
+
struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
unsigned int sym_debug_flags = 0;
@@ -147,7 +156,7 @@ pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
}
/* This lock protects only the memory allocation/free. */
-spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
static struct scsi_transport_template *sym2_transport_template = NULL;
@@ -285,7 +294,7 @@ void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb)
ccb->scsi_done(ccb);
}
-void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *ccb, int cam_status)
+static void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *ccb, int cam_status)
{
sym_set_cam_status(ccb, cam_status);
sym_xpt_done(np, ccb);
@@ -379,7 +388,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
/*
* Bounce back the sense data to user.
*/
- bzero(&csio->sense_buffer, sizeof(csio->sense_buffer));
+ memset(&csio->sense_buffer, 0, sizeof(csio->sense_buffer));
memcpy(csio->sense_buffer, cp->sns_bbuf,
min(sizeof(csio->sense_buffer),
(size_t)SYM_SNS_BBUF_LEN));
@@ -513,7 +522,7 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb)
}
/*
- * Retreive the target descriptor.
+ * Retrieve the target descriptor.
*/
tp = &np->target[ccb->device->id];
@@ -1277,7 +1286,7 @@ static int sym_user_command(struct sym_hcb *np, char *buffer, int length)
int arg_len;
u_long target;
- bzero(uc, sizeof(*uc));
+ memset(uc, 0, sizeof(*uc));
if (len > 0 && ptr[len-1] == '\n')
--len;
@@ -1467,18 +1476,8 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
"revision id 0x%x\n",
np->s.chip_name, np->device_id, np->revision_id);
- copy_info(&info, "At PCI address %s, "
-#ifdef __sparc__
- "IRQ %s\n",
-#else
- "IRQ %d\n",
-#endif
- pci_name(np->s.device),
-#ifdef __sparc__
- __irq_itoa(np->s.irq));
-#else
- (int) np->s.irq);
-#endif
+ copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n",
+ pci_name(np->s.device), IRQ_PRM(np->s.irq));
copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",
(int) (np->minsync_dt ? np->minsync_dt : np->minsync),
np->maxwide ? "Wide" : "Narrow",
@@ -1558,32 +1557,23 @@ static void sym_free_resources(struct sym_hcb *np)
*/
static int sym_setup_bus_dma_mask(struct sym_hcb *np)
{
-#if SYM_CONF_DMA_ADDRESSING_MODE == 0
- if (pci_set_dma_mask(np->s.device, 0xffffffffUL))
- goto out_err32;
-#else
+#if SYM_CONF_DMA_ADDRESSING_MODE > 0
#if SYM_CONF_DMA_ADDRESSING_MODE == 1
-#define PciDmaMask 0xffffffffffULL
+#define DMA_DAC_MASK 0x000000ffffffffffULL /* 40-bit */
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
-#define PciDmaMask 0xffffffffffffffffULL
+#define DMA_DAC_MASK DMA_64BIT_MASK
#endif
- if (np->features & FE_DAC) {
- if (!pci_set_dma_mask(np->s.device, PciDmaMask)) {
- np->use_dac = 1;
- printf_info("%s: using 64 bit DMA addressing\n",
- sym_name(np));
- } else {
- if (pci_set_dma_mask(np->s.device, 0xffffffffUL))
- goto out_err32;
- }
+ if ((np->features & FE_DAC) &&
+ !pci_set_dma_mask(np->s.device, DMA_DAC_MASK)) {
+ np->use_dac = 1;
+ return 0;
}
-#undef PciDmaMask
#endif
- return 0;
-out_err32:
- printf_warning("%s: 32 BIT DMA ADDRESSING NOT SUPPORTED\n",
- sym_name(np));
+ if (!pci_set_dma_mask(np->s.device, DMA_32BIT_MASK))
+ return 0;
+
+ printf_warning("%s: No suitable DMA available\n", sym_name(np));
return -1;
}
@@ -1606,19 +1596,9 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
struct sym_fw *fw;
printk(KERN_INFO
- "sym%d: <%s> rev 0x%x at pci %s "
-#ifdef __sparc__
- "irq %s\n",
-#else
- "irq %d\n",
-#endif
+ "sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n",
unit, dev->chip.name, dev->chip.revision_id,
- pci_name(dev->pdev),
-#ifdef __sparc__
- __irq_itoa(dev->s.irq));
-#else
- dev->s.irq);
-#endif
+ pci_name(dev->pdev), IRQ_PRM(dev->s.irq));
/*
* Get the firmware for this chip.
@@ -1672,9 +1652,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
strlcpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name));
sprintf(np->s.inst_name, "sym%d", np->s.unit);
- /*
- * Ask/tell the system about DMA addressing.
- */
if (sym_setup_bus_dma_mask(np))
goto attach_failed;
@@ -2010,7 +1987,7 @@ sym_init_device(struct pci_dev *pdev, struct sym_device *device)
* the preset SCSI ID (which may be zero) must be read in from
* a special configuration space register of the 875.
*/
-void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
+static void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
{
int slot;
u8 tmp;
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index df1b9af12d87..7cfb1b21b69a 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -58,13 +58,6 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
-#ifndef bzero
-#define bzero(d, n) memset((d), 0, (n))
-#endif
-
-/*
- * General driver includes.
- */
#include "sym_conf.h"
#include "sym_defs.h"
#include "sym_misc.h"
@@ -123,14 +116,6 @@
typedef struct sym_tcb *tcb_p;
typedef struct sym_lcb *lcb_p;
typedef struct sym_ccb *ccb_p;
-typedef struct sym_hcb *hcb_p;
-
-/*
- * Define a reference to the O/S dependent IO request.
- */
-typedef struct scsi_cmnd *cam_ccb_p; /* Generic */
-typedef struct scsi_cmnd *cam_scsiio_p;/* SCSI I/O */
-
/*
* IO functions definition for big/little endian CPU support.
@@ -525,7 +510,7 @@ sym_get_cam_status(struct scsi_cmnd *ccb)
/*
* Async handler for negotiations.
*/
-void sym_xpt_async_nego_wide(hcb_p np, int target);
+void sym_xpt_async_nego_wide(struct sym_hcb *np, int target);
#define sym_xpt_async_nego_sync(np, target) \
sym_announce_transfer_rate(np, target)
#define sym_xpt_async_nego_ppr(np, target) \
@@ -534,14 +519,14 @@ void sym_xpt_async_nego_wide(hcb_p np, int target);
/*
* Build CAM result for a successful IO and for a failed IO.
*/
-static __inline void sym_set_cam_result_ok(hcb_p np, ccb_p cp, int resid)
+static __inline void sym_set_cam_result_ok(struct sym_hcb *np, ccb_p cp, int resid)
{
struct scsi_cmnd *cmd = cp->cam_ccb;
cmd->resid = resid;
cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f));
}
-void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid);
+void sym_set_cam_result_error(struct sym_hcb *np, ccb_p cp, int resid);
/*
* Other O/S specific methods.
@@ -549,13 +534,12 @@ void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid);
#define sym_cam_target_id(ccb) (ccb)->target
#define sym_cam_target_lun(ccb) (ccb)->lun
#define sym_freeze_cam_ccb(ccb) do { ; } while (0)
-void sym_xpt_done(hcb_p np, cam_ccb_p ccb);
-void sym_xpt_done2(hcb_p np, cam_ccb_p ccb, int cam_status);
+void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb);
void sym_print_addr (ccb_p cp);
-void sym_xpt_async_bus_reset(hcb_p np);
-void sym_xpt_async_sent_bdr(hcb_p np, int target);
-int sym_setup_data_and_start (hcb_p np, cam_scsiio_p csio, ccb_p cp);
-void sym_log_bus_error(hcb_p np);
-void sym_sniff_inquiry(hcb_p np, struct scsi_cmnd *cmd, int resid);
+void sym_xpt_async_bus_reset(struct sym_hcb *np);
+void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target);
+int sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp);
+void sym_log_bus_error(struct sym_hcb *np);
+void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid);
#endif /* SYM_GLUE_H */
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 383f48b1014e..8b7aa921e487 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -47,14 +47,14 @@
/*
* Needed function prototypes.
*/
-static void sym_int_ma (hcb_p np);
-static void sym_int_sir (hcb_p np);
-static ccb_p sym_alloc_ccb(hcb_p np);
-static ccb_p sym_ccb_from_dsa(hcb_p np, u32 dsa);
-static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln);
-static void sym_complete_error (hcb_p np, ccb_p cp);
-static void sym_complete_ok (hcb_p np, ccb_p cp);
-static int sym_compute_residual(hcb_p np, ccb_p cp);
+static void sym_int_ma (struct sym_hcb *np);
+static void sym_int_sir (struct sym_hcb *np);
+static ccb_p sym_alloc_ccb(struct sym_hcb *np);
+static ccb_p sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa);
+static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln);
+static void sym_complete_error (struct sym_hcb *np, ccb_p cp);
+static void sym_complete_ok (struct sym_hcb *np, ccb_p cp);
+static int sym_compute_residual(struct sym_hcb *np, ccb_p cp);
/*
* Returns the name of this driver.
@@ -86,12 +86,12 @@ static void sym_printl_hex (char *label, u_char *p, int n)
* Print something which allows to retrieve the controler type,
* unit, target, lun concerned by a kernel message.
*/
-static void sym_print_target (hcb_p np, int target)
+static void sym_print_target (struct sym_hcb *np, int target)
{
printf ("%s:%d:", sym_name(np), target);
}
-static void sym_print_lun(hcb_p np, int target, int lun)
+static void sym_print_lun(struct sym_hcb *np, int target, int lun)
{
printf ("%s:%d:%d:", sym_name(np), target, lun);
}
@@ -126,7 +126,7 @@ static void sym_print_msg (ccb_p cp, char *label, u_char *msg)
printf (".\n");
}
-static void sym_print_nego_msg (hcb_p np, int target, char *label, u_char *msg)
+static void sym_print_nego_msg (struct sym_hcb *np, int target, char *label, u_char *msg)
{
PRINT_TARGET(np, target);
if (label)
@@ -184,7 +184,7 @@ static char *sym_scsi_bus_mode(int mode)
* On the other hand, LVD devices need some delay
* to settle and report actual BUS mode in STEST4.
*/
-static void sym_chip_reset (hcb_p np)
+static void sym_chip_reset (struct sym_hcb *np)
{
OUTB (nc_istat, SRST);
UDELAY (10);
@@ -201,7 +201,7 @@ static void sym_chip_reset (hcb_p np)
* So, we need to abort the current operation prior to
* soft resetting the chip.
*/
-static void sym_soft_reset (hcb_p np)
+static void sym_soft_reset (struct sym_hcb *np)
{
u_char istat = 0;
int i;
@@ -234,12 +234,12 @@ do_chip_reset:
*
* The interrupt handler will reinitialize the chip.
*/
-static void sym_start_reset(hcb_p np)
+static void sym_start_reset(struct sym_hcb *np)
{
(void) sym_reset_scsi_bus(np, 1);
}
-int sym_reset_scsi_bus(hcb_p np, int enab_int)
+int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int)
{
u32 term;
int retv = 0;
@@ -293,7 +293,7 @@ out:
/*
* Select SCSI clock frequency
*/
-static void sym_selectclock(hcb_p np, u_char scntl3)
+static void sym_selectclock(struct sym_hcb *np, u_char scntl3)
{
/*
* If multiplier not present or not selected, leave here.
@@ -348,7 +348,7 @@ static void sym_selectclock(hcb_p np, u_char scntl3)
/*
* calculate SCSI clock frequency (in KHz)
*/
-static unsigned getfreq (hcb_p np, int gen)
+static unsigned getfreq (struct sym_hcb *np, int gen)
{
unsigned int ms = 0;
unsigned int f;
@@ -420,7 +420,7 @@ static unsigned getfreq (hcb_p np, int gen)
return f;
}
-static unsigned sym_getfreq (hcb_p np)
+static unsigned sym_getfreq (struct sym_hcb *np)
{
u_int f1, f2;
int gen = 8;
@@ -435,7 +435,7 @@ static unsigned sym_getfreq (hcb_p np)
/*
* Get/probe chip SCSI clock frequency
*/
-static void sym_getclock (hcb_p np, int mult)
+static void sym_getclock (struct sym_hcb *np, int mult)
{
unsigned char scntl3 = np->sv_scntl3;
unsigned char stest1 = np->sv_stest1;
@@ -492,7 +492,7 @@ static void sym_getclock (hcb_p np, int mult)
/*
* Get/probe PCI clock frequency
*/
-static int sym_getpciclock (hcb_p np)
+static int sym_getpciclock (struct sym_hcb *np)
{
int f = 0;
@@ -528,7 +528,7 @@ static u32 div_10M[] = {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M};
* synchronous factor period.
*/
static int
-sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp, u_char *fakp)
+sym_getsync(struct sym_hcb *np, u_char dt, u_char sfac, u_char *divp, u_char *fakp)
{
u32 clk = np->clock_khz; /* SCSI clock frequency in kHz */
int div = np->clock_divn; /* Number of divisors supported */
@@ -648,7 +648,7 @@ sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp, u_char *fakp)
/*
* Set initial io register bits from burst code.
*/
-static __inline void sym_init_burst(hcb_p np, u_char bc)
+static __inline void sym_init_burst(struct sym_hcb *np, u_char bc)
{
np->rv_ctest4 &= ~0x80;
np->rv_dmode &= ~(0x3 << 6);
@@ -668,7 +668,7 @@ static __inline void sym_init_burst(hcb_p np, u_char bc)
/*
* Print out the list of targets that have some flag disabled by user.
*/
-static void sym_print_targets_flag(hcb_p np, int mask, char *msg)
+static void sym_print_targets_flag(struct sym_hcb *np, int mask, char *msg)
{
int cnt;
int i;
@@ -696,7 +696,7 @@ static void sym_print_targets_flag(hcb_p np, int mask, char *msg)
* is not safe on paper, but it seems to work quite
* well. :)
*/
-static void sym_save_initial_setting (hcb_p np)
+static void sym_save_initial_setting (struct sym_hcb *np)
{
np->sv_scntl0 = INB(nc_scntl0) & 0x0a;
np->sv_scntl3 = INB(nc_scntl3) & 0x07;
@@ -716,44 +716,11 @@ static void sym_save_initial_setting (hcb_p np)
np->sv_ctest5 = INB(nc_ctest5) & 0x24;
}
-#ifdef CONFIG_PARISC
-static u32 parisc_setup_hcb(hcb_p np, u32 period)
-{
- unsigned long pdc_period;
- char scsi_mode;
- struct hardware_path hwpath;
-
- /* Host firmware (PDC) keeps a table for crippling SCSI capabilities.
- * Many newer machines export one channel of 53c896 chip
- * as SE, 50-pin HD. Also used for Multi-initiator SCSI clusters
- * to set the SCSI Initiator ID.
- */
- get_pci_node_path(np->s.device, &hwpath);
- if (!pdc_get_initiator(&hwpath, &np->myaddr, &pdc_period,
- &np->maxwide, &scsi_mode))
- return period;
-
- if (scsi_mode >= 0) {
- /* C3000 PDC reports period/mode */
- SYM_SETUP_SCSI_DIFF = 0;
- switch(scsi_mode) {
- case 0: np->scsi_mode = SMODE_SE; break;
- case 1: np->scsi_mode = SMODE_HVD; break;
- case 2: np->scsi_mode = SMODE_LVD; break;
- default: break;
- }
- }
-
- return (u32) pdc_period;
-}
-#else
-static inline int parisc_setup_hcb(hcb_p np, u32 period) { return period; }
-#endif
/*
* Prepare io register values used by sym_start_up()
* according to selected and supported features.
*/
-static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
+static int sym_prepare_setting(struct sym_hcb *np, struct sym_nvram *nvram)
{
u_char burst_max;
u32 period;
@@ -816,8 +783,6 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
*/
period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz;
- period = parisc_setup_hcb(np, period);
-
if (period <= 250) np->minsync = 10;
else if (period <= 303) np->minsync = 11;
else if (period <= 500) np->minsync = 12;
@@ -880,7 +845,7 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
* In dual channel mode, contention occurs if internal cycles
* are used. Disable internal cycles.
*/
- if (np->device_id == PCI_ID_LSI53C1010_33 &&
+ if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
np->revision_id < 0x1)
np->rv_ccntl0 |= DILS;
@@ -904,9 +869,9 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
* this driver. The generic ncr driver that does not use
* LOAD/STORE instructions does not need this work-around.
*/
- if ((np->device_id == PCI_ID_SYM53C810 &&
+ if ((np->device_id == PCI_DEVICE_ID_NCR_53C810 &&
np->revision_id >= 0x10 && np->revision_id <= 0x11) ||
- (np->device_id == PCI_ID_SYM53C860 &&
+ (np->device_id == PCI_DEVICE_ID_NCR_53C860 &&
np->revision_id <= 0x1))
np->features &= ~(FE_WRIE|FE_ERL|FE_ERMP);
@@ -1000,7 +965,7 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
if ((SYM_SETUP_SCSI_LED ||
(nvram->type == SYM_SYMBIOS_NVRAM ||
(nvram->type == SYM_TEKRAM_NVRAM &&
- np->device_id == PCI_ID_SYM53C895))) &&
+ np->device_id == PCI_DEVICE_ID_NCR_53C895))) &&
!(np->features & FE_LEDC) && !(np->sv_gpcntl & 0x01))
np->features |= FE_LED0;
@@ -1091,7 +1056,7 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
* Has to be called with interrupts disabled.
*/
#ifndef SYM_CONF_IOMAPPED
-static int sym_regtest (hcb_p np)
+static int sym_regtest (struct sym_hcb *np)
{
register volatile u32 data;
/*
@@ -1115,7 +1080,7 @@ static int sym_regtest (hcb_p np)
}
#endif
-static int sym_snooptest (hcb_p np)
+static int sym_snooptest (struct sym_hcb *np)
{
u32 sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat;
int i, err=0;
@@ -1241,7 +1206,7 @@ restart_test:
* First 24 register of the chip:
* r0..rf
*/
-static void sym_log_hard_error(hcb_p np, u_short sist, u_char dstat)
+static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat)
{
u32 dsp;
int script_ofs;
@@ -1299,85 +1264,85 @@ static void sym_log_hard_error(hcb_p np, u_short sist, u_char dstat)
}
static struct sym_pci_chip sym_pci_dev_table[] = {
- {PCI_ID_SYM53C810, 0x0f, "810", 4, 8, 4, 64,
+ {PCI_DEVICE_ID_NCR_53C810, 0x0f, "810", 4, 8, 4, 64,
FE_ERL}
,
#ifdef SYM_DEBUG_GENERIC_SUPPORT
- {PCI_ID_SYM53C810, 0xff, "810a", 4, 8, 4, 1,
+ {PCI_DEVICE_ID_NCR_53C810, 0xff, "810a", 4, 8, 4, 1,
FE_BOF}
,
#else
- {PCI_ID_SYM53C810, 0xff, "810a", 4, 8, 4, 1,
+ {PCI_DEVICE_ID_NCR_53C810, 0xff, "810a", 4, 8, 4, 1,
FE_CACHE_SET|FE_LDSTR|FE_PFEN|FE_BOF}
,
#endif
- {PCI_ID_SYM53C815, 0xff, "815", 4, 8, 4, 64,
+ {PCI_DEVICE_ID_NCR_53C815, 0xff, "815", 4, 8, 4, 64,
FE_BOF|FE_ERL}
,
- {PCI_ID_SYM53C825, 0x0f, "825", 6, 8, 4, 64,
+ {PCI_DEVICE_ID_NCR_53C825, 0x0f, "825", 6, 8, 4, 64,
FE_WIDE|FE_BOF|FE_ERL|FE_DIFF}
,
- {PCI_ID_SYM53C825, 0xff, "825a", 6, 8, 4, 2,
+ {PCI_DEVICE_ID_NCR_53C825, 0xff, "825a", 6, 8, 4, 2,
FE_WIDE|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM|FE_DIFF}
,
- {PCI_ID_SYM53C860, 0xff, "860", 4, 8, 5, 1,
+ {PCI_DEVICE_ID_NCR_53C860, 0xff, "860", 4, 8, 5, 1,
FE_ULTRA|FE_CACHE_SET|FE_BOF|FE_LDSTR|FE_PFEN}
,
- {PCI_ID_SYM53C875, 0x01, "875", 6, 16, 5, 2,
+ {PCI_DEVICE_ID_NCR_53C875, 0x01, "875", 6, 16, 5, 2,
FE_WIDE|FE_ULTRA|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_DIFF|FE_VARCLK}
,
- {PCI_ID_SYM53C875, 0xff, "875", 6, 16, 5, 2,
+ {PCI_DEVICE_ID_NCR_53C875, 0xff, "875", 6, 16, 5, 2,
FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_DIFF|FE_VARCLK}
,
- {PCI_ID_SYM53C875_2, 0xff, "875", 6, 16, 5, 2,
+ {PCI_DEVICE_ID_NCR_53C875J, 0xff, "875J", 6, 16, 5, 2,
FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_DIFF|FE_VARCLK}
,
- {PCI_ID_SYM53C885, 0xff, "885", 6, 16, 5, 2,
+ {PCI_DEVICE_ID_NCR_53C885, 0xff, "885", 6, 16, 5, 2,
FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE0_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_DIFF|FE_VARCLK}
,
#ifdef SYM_DEBUG_GENERIC_SUPPORT
- {PCI_ID_SYM53C895, 0xff, "895", 6, 31, 7, 2,
+ {PCI_DEVICE_ID_NCR_53C895, 0xff, "895", 6, 31, 7, 2,
FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|
FE_RAM|FE_LCKFRQ}
,
#else
- {PCI_ID_SYM53C895, 0xff, "895", 6, 31, 7, 2,
+ {PCI_DEVICE_ID_NCR_53C895, 0xff, "895", 6, 31, 7, 2,
FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_LCKFRQ}
,
#endif
- {PCI_ID_SYM53C896, 0xff, "896", 6, 31, 7, 4,
+ {PCI_DEVICE_ID_NCR_53C896, 0xff, "896", 6, 31, 7, 4,
FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
,
- {PCI_ID_SYM53C895A, 0xff, "895a", 6, 31, 7, 4,
+ {PCI_DEVICE_ID_LSI_53C895A, 0xff, "895a", 6, 31, 7, 4,
FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
,
- {PCI_ID_SYM53C875A, 0xff, "875a", 6, 31, 7, 4,
+ {PCI_DEVICE_ID_LSI_53C875A, 0xff, "875a", 6, 31, 7, 4,
FE_WIDE|FE_ULTRA|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
,
- {PCI_ID_LSI53C1010_33, 0x00, "1010-33", 6, 31, 7, 8,
+ {PCI_DEVICE_ID_LSI_53C1010_33, 0x00, "1010-33", 6, 31, 7, 8,
FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC|
FE_C10}
,
- {PCI_ID_LSI53C1010_33, 0xff, "1010-33", 6, 31, 7, 8,
+ {PCI_DEVICE_ID_LSI_53C1010_33, 0xff, "1010-33", 6, 31, 7, 8,
FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC|
FE_C10|FE_U3EN}
,
- {PCI_ID_LSI53C1010_66, 0xff, "1010-66", 6, 31, 7, 8,
+ {PCI_DEVICE_ID_LSI_53C1010_66, 0xff, "1010-66", 6, 31, 7, 8,
FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_66MHZ|FE_CRC|
FE_C10|FE_U3EN}
,
- {PCI_ID_LSI53C1510D, 0xff, "1510d", 6, 31, 7, 4,
+ {PCI_DEVICE_ID_LSI_53C1510, 0xff, "1510d", 6, 31, 7, 4,
FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_IO256|FE_LEDC}
};
@@ -1415,7 +1380,7 @@ sym_lookup_pci_chip_table (u_short device_id, u_char revision)
* This is only used if the direct mapping
* has been unsuccessful.
*/
-int sym_lookup_dmap(hcb_p np, u32 h, int s)
+int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s)
{
int i;
@@ -1448,7 +1413,7 @@ new:
* Update IO registers scratch C..R so they will be
* in sync. with queued CCB expectations.
*/
-static void sym_update_dmap_regs(hcb_p np)
+static void sym_update_dmap_regs(struct sym_hcb *np)
{
int o, i;
@@ -1463,13 +1428,12 @@ static void sym_update_dmap_regs(hcb_p np)
}
#endif
+/* Enforce all the fiddly SPI rules and the chip limitations */
static void sym_check_goals(struct scsi_device *sdev)
{
struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
struct sym_trans *st = &np->target[sdev->id].tinfo.goal;
- /* here we enforce all the fiddly SPI rules */
-
if (!scsi_device_wide(sdev))
st->width = 0;
@@ -1479,7 +1443,7 @@ static void sym_check_goals(struct scsi_device *sdev)
st->offset = 0;
return;
}
-
+
if (scsi_device_dt(sdev)) {
if (scsi_device_dt_only(sdev))
st->options |= PPR_OPT_DT;
@@ -1490,7 +1454,8 @@ static void sym_check_goals(struct scsi_device *sdev)
st->options &= ~PPR_OPT_DT;
}
- if (!(np->features & FE_ULTRA3))
+ /* Some targets fail to properly negotiate DT in SE mode */
+ if ((np->scsi_mode != SMODE_LVD) || !(np->features & FE_U3EN))
st->options &= ~PPR_OPT_DT;
if (st->options & PPR_OPT_DT) {
@@ -1520,38 +1485,31 @@ static void sym_check_goals(struct scsi_device *sdev)
* negotiation and the nego_status field of the CCB.
* Returns the size of the message in bytes.
*/
-static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
+static int sym_prepare_nego(struct sym_hcb *np, ccb_p cp, u_char *msgptr)
{
tcb_p tp = &np->target[cp->target];
- int msglen = 0;
struct scsi_device *sdev = tp->sdev;
+ struct sym_trans *goal = &tp->tinfo.goal;
+ struct sym_trans *curr = &tp->tinfo.curr;
+ int msglen = 0;
+ int nego;
if (likely(sdev))
sym_check_goals(sdev);
/*
- * Early C1010 chips need a work-around for DT
- * data transfer to work.
+ * Many devices implement PPR in a buggy way, so only use it if we
+ * really want to.
*/
- if (!(np->features & FE_U3EN))
- tp->tinfo.goal.options = 0;
- /*
- * negotiate using PPR ?
- */
- if (scsi_device_dt(sdev)) {
+ if ((goal->options & PPR_OPT_MASK) || (goal->period < 0xa)) {
nego = NS_PPR;
+ } else if (curr->width != goal->width) {
+ nego = NS_WIDE;
+ } else if (curr->period != goal->period ||
+ curr->offset != goal->offset) {
+ nego = NS_SYNC;
} else {
- /*
- * negotiate wide transfers ?
- */
- if (tp->tinfo.curr.width != tp->tinfo.goal.width)
- nego = NS_WIDE;
- /*
- * negotiate synchronous transfers?
- */
- else if (tp->tinfo.curr.period != tp->tinfo.goal.period ||
- tp->tinfo.curr.offset != tp->tinfo.goal.offset)
- nego = NS_SYNC;
+ nego = 0;
}
switch (nego) {
@@ -1559,24 +1517,24 @@ static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
msgptr[msglen++] = M_EXTENDED;
msgptr[msglen++] = 3;
msgptr[msglen++] = M_X_SYNC_REQ;
- msgptr[msglen++] = tp->tinfo.goal.period;
- msgptr[msglen++] = tp->tinfo.goal.offset;
+ msgptr[msglen++] = goal->period;
+ msgptr[msglen++] = goal->offset;
break;
case NS_WIDE:
msgptr[msglen++] = M_EXTENDED;
msgptr[msglen++] = 2;
msgptr[msglen++] = M_X_WIDE_REQ;
- msgptr[msglen++] = tp->tinfo.goal.width;
+ msgptr[msglen++] = goal->width;
break;
case NS_PPR:
msgptr[msglen++] = M_EXTENDED;
msgptr[msglen++] = 6;
msgptr[msglen++] = M_X_PPR_REQ;
- msgptr[msglen++] = tp->tinfo.goal.period;
+ msgptr[msglen++] = goal->period;
msgptr[msglen++] = 0;
- msgptr[msglen++] = tp->tinfo.goal.offset;
- msgptr[msglen++] = tp->tinfo.goal.width;
- msgptr[msglen++] = tp->tinfo.goal.options & PPR_OPT_MASK;
+ msgptr[msglen++] = goal->offset;
+ msgptr[msglen++] = goal->width;
+ msgptr[msglen++] = goal->options & PPR_OPT_MASK;
break;
};
@@ -1598,7 +1556,7 @@ static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
/*
* Insert a job into the start queue.
*/
-void sym_put_start_queue(hcb_p np, ccb_p cp)
+void sym_put_start_queue(struct sym_hcb *np, ccb_p cp)
{
u_short qidx;
@@ -1630,13 +1588,6 @@ void sym_put_start_queue(hcb_p np, ccb_p cp)
#endif
/*
- * Optionnaly, set the IO timeout condition.
- */
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- sym_timeout_ccb(np, cp, sym_cam_timeout(cp->cam_ccb));
-#endif
-
- /*
* Insert first the idle task and then our job.
* The MBs should ensure proper ordering.
*/
@@ -1664,7 +1615,7 @@ void sym_put_start_queue(hcb_p np, ccb_p cp)
/*
* Start next ready-to-start CCBs.
*/
-void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn)
+void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn)
{
SYM_QUEHEAD *qp;
ccb_p cp;
@@ -1718,7 +1669,7 @@ void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn)
* prevent out of order LOADs by the CPU from having
* prefetched stale data prior to DMA having occurred.
*/
-static int sym_wakeup_done (hcb_p np)
+static int sym_wakeup_done (struct sym_hcb *np)
{
ccb_p cp;
int i, n;
@@ -1752,10 +1703,64 @@ static int sym_wakeup_done (hcb_p np)
}
/*
+ * Complete all CCBs queued to the COMP queue.
+ *
+ * These CCBs are assumed:
+ * - Not to be referenced either by devices or
+ * SCRIPTS-related queues and datas.
+ * - To have to be completed with an error condition
+ * or requeued.
+ *
+ * The device queue freeze count is incremented
+ * for each CCB that does not prevent this.
+ * This function is called when all CCBs involved
+ * in error handling/recovery have been reaped.
+ */
+static void sym_flush_comp_queue(struct sym_hcb *np, int cam_status)
+{
+ SYM_QUEHEAD *qp;
+ ccb_p cp;
+
+ while ((qp = sym_remque_head(&np->comp_ccbq)) != 0) {
+ struct scsi_cmnd *ccb;
+ cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+ sym_insque_tail(&cp->link_ccbq, &np->busy_ccbq);
+ /* Leave quiet CCBs waiting for resources */
+ if (cp->host_status == HS_WAIT)
+ continue;
+ ccb = cp->cam_ccb;
+ if (cam_status)
+ sym_set_cam_status(ccb, cam_status);
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
+ if (sym_get_cam_status(ccb) == CAM_REQUEUE_REQ) {
+ tcb_p tp = &np->target[cp->target];
+ lcb_p lp = sym_lp(np, tp, cp->lun);
+ if (lp) {
+ sym_remque(&cp->link2_ccbq);
+ sym_insque_tail(&cp->link2_ccbq,
+ &lp->waiting_ccbq);
+ if (cp->started) {
+ if (cp->tag != NO_TAG)
+ --lp->started_tags;
+ else
+ --lp->started_no_tag;
+ }
+ }
+ cp->started = 0;
+ continue;
+ }
+#endif
+ sym_free_ccb(np, cp);
+ sym_freeze_cam_ccb(ccb);
+ sym_xpt_done(np, ccb);
+ }
+}
+
+/*
* Complete all active CCBs with error.
* Used on CHIP/SCSI RESET.
*/
-static void sym_flush_busy_queue (hcb_p np, int cam_status)
+static void sym_flush_busy_queue (struct sym_hcb *np, int cam_status)
{
/*
* Move all active CCBs to the COMP queue
@@ -1774,7 +1779,7 @@ static void sym_flush_busy_queue (hcb_p np, int cam_status)
* 1: SCSI BUS RESET delivered or received.
* 2: SCSI BUS MODE changed.
*/
-void sym_start_up (hcb_p np, int reason)
+void sym_start_up (struct sym_hcb *np, int reason)
{
int i;
u32 phys;
@@ -1865,7 +1870,7 @@ void sym_start_up (hcb_p np, int reason)
/*
* For now, disable AIP generation on C1010-66.
*/
- if (np->device_id == PCI_ID_LSI53C1010_66)
+ if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)
OUTB (nc_aipcntl1, DISAIP);
/*
@@ -1875,7 +1880,7 @@ void sym_start_up (hcb_p np, int reason)
* that from SCRIPTS for each selection/reselection, but
* I just don't want. :)
*/
- if (np->device_id == PCI_ID_LSI53C1010_33 &&
+ if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
np->revision_id < 1)
OUTB (nc_stest1, INB(nc_stest1) | 0x30);
@@ -1884,9 +1889,9 @@ void sym_start_up (hcb_p np, int reason)
* Disable overlapped arbitration for some dual function devices,
* regardless revision id (kind of post-chip-design feature. ;-))
*/
- if (np->device_id == PCI_ID_SYM53C875)
+ if (np->device_id == PCI_DEVICE_ID_NCR_53C875)
OUTB (nc_ctest0, (1<<5));
- else if (np->device_id == PCI_ID_SYM53C896)
+ else if (np->device_id == PCI_DEVICE_ID_NCR_53C896)
np->rv_ccntl0 |= DPR;
/*
@@ -2010,7 +2015,7 @@ void sym_start_up (hcb_p np, int reason)
/*
* Switch trans mode for current job and it's target.
*/
-static void sym_settrans(hcb_p np, int target, u_char opts, u_char ofs,
+static void sym_settrans(struct sym_hcb *np, int target, u_char opts, u_char ofs,
u_char per, u_char wide, u_char div, u_char fak)
{
SYM_QUEHEAD *qp;
@@ -2119,7 +2124,7 @@ static void sym_settrans(hcb_p np, int target, u_char opts, u_char ofs,
* We received a WDTR.
* Let everything be aware of the changes.
*/
-static void sym_setwide(hcb_p np, int target, u_char wide)
+static void sym_setwide(struct sym_hcb *np, int target, u_char wide)
{
tcb_p tp = &np->target[target];
@@ -2138,7 +2143,7 @@ static void sym_setwide(hcb_p np, int target, u_char wide)
* Let everything be aware of the changes.
*/
static void
-sym_setsync(hcb_p np, int target,
+sym_setsync(struct sym_hcb *np, int target,
u_char ofs, u_char per, u_char div, u_char fak)
{
tcb_p tp = &np->target[target];
@@ -2164,7 +2169,7 @@ sym_setsync(hcb_p np, int target,
* Let everything be aware of the changes.
*/
static void
-sym_setpprot(hcb_p np, int target, u_char opts, u_char ofs,
+sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs,
u_char per, u_char wide, u_char div, u_char fak)
{
tcb_p tp = &np->target[target];
@@ -2205,7 +2210,7 @@ sym_setpprot(hcb_p np, int target, u_char opts, u_char ofs,
* pushes a DSA into a queue, we can trust it when it
* points to a CCB.
*/
-static void sym_recover_scsi_int (hcb_p np, u_char hsts)
+static void sym_recover_scsi_int (struct sym_hcb *np, u_char hsts)
{
u32 dsp = INL (nc_dsp);
u32 dsa = INL (nc_dsa);
@@ -2256,7 +2261,7 @@ reset_all:
/*
* chip exception handler for selection timeout
*/
-static void sym_int_sto (hcb_p np)
+static void sym_int_sto (struct sym_hcb *np)
{
u32 dsp = INL (nc_dsp);
@@ -2271,7 +2276,7 @@ static void sym_int_sto (hcb_p np)
/*
* chip exception handler for unexpected disconnect
*/
-static void sym_int_udc (hcb_p np)
+static void sym_int_udc (struct sym_hcb *np)
{
printf ("%s: unexpected disconnect\n", sym_name(np));
sym_recover_scsi_int(np, HS_UNEXPECTED);
@@ -2287,7 +2292,7 @@ static void sym_int_udc (hcb_p np)
* mode to eight bit asynchronous, etc...
* So, just reinitializing all except chip should be enough.
*/
-static void sym_int_sbmc (hcb_p np)
+static void sym_int_sbmc (struct sym_hcb *np)
{
u_char scsi_mode = INB (nc_stest4) & SMODE;
@@ -2328,7 +2333,7 @@ static void sym_int_sbmc (hcb_p np)
* The chip will load the DSP with the phase mismatch
* JUMP address and interrupt the host processor.
*/
-static void sym_int_par (hcb_p np, u_short sist)
+static void sym_int_par (struct sym_hcb *np, u_short sist)
{
u_char hsts = INB (HS_PRT);
u32 dsp = INL (nc_dsp);
@@ -2416,7 +2421,7 @@ reset_all:
* We have to construct a new transfer descriptor,
* to transfer the rest of the current block.
*/
-static void sym_int_ma (hcb_p np)
+static void sym_int_ma (struct sym_hcb *np)
{
u32 dbc;
u32 rest;
@@ -2826,7 +2831,7 @@ reset_all:
* Use at your own decision and risk.
*/
-void sym_interrupt (hcb_p np)
+void sym_interrupt (struct sym_hcb *np)
{
u_char istat, istatc;
u_char dstat;
@@ -2981,7 +2986,7 @@ unknown_int:
* It is called with SCRIPTS not running.
*/
static int
-sym_dequeue_from_squeue(hcb_p np, int i, int target, int lun, int task)
+sym_dequeue_from_squeue(struct sym_hcb *np, int i, int target, int lun, int task)
{
int j;
ccb_p cp;
@@ -3025,60 +3030,6 @@ sym_dequeue_from_squeue(hcb_p np, int i, int target, int lun, int task)
}
/*
- * Complete all CCBs queued to the COMP queue.
- *
- * These CCBs are assumed:
- * - Not to be referenced either by devices or
- * SCRIPTS-related queues and datas.
- * - To have to be completed with an error condition
- * or requeued.
- *
- * The device queue freeze count is incremented
- * for each CCB that does not prevent this.
- * This function is called when all CCBs involved
- * in error handling/recovery have been reaped.
- */
-void sym_flush_comp_queue(hcb_p np, int cam_status)
-{
- SYM_QUEHEAD *qp;
- ccb_p cp;
-
- while ((qp = sym_remque_head(&np->comp_ccbq)) != 0) {
- cam_ccb_p ccb;
- cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
- sym_insque_tail(&cp->link_ccbq, &np->busy_ccbq);
- /* Leave quiet CCBs waiting for resources */
- if (cp->host_status == HS_WAIT)
- continue;
- ccb = cp->cam_ccb;
- if (cam_status)
- sym_set_cam_status(ccb, cam_status);
-#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
- if (sym_get_cam_status(ccb) == CAM_REQUEUE_REQ) {
- tcb_p tp = &np->target[cp->target];
- lcb_p lp = sym_lp(np, tp, cp->lun);
- if (lp) {
- sym_remque(&cp->link2_ccbq);
- sym_insque_tail(&cp->link2_ccbq,
- &lp->waiting_ccbq);
- if (cp->started) {
- if (cp->tag != NO_TAG)
- --lp->started_tags;
- else
- --lp->started_no_tag;
- }
- }
- cp->started = 0;
- continue;
- }
-#endif
- sym_free_ccb(np, cp);
- sym_freeze_cam_ccb(ccb);
- sym_xpt_done(np, ccb);
- }
-}
-
-/*
* chip handler for bad SCSI status condition
*
* In case of bad SCSI status, we unqueue all the tasks
@@ -3096,14 +3047,13 @@ void sym_flush_comp_queue(hcb_p np, int cam_status)
* SCRATCHA is assumed to have been loaded with STARTPOS
* before the SCRIPTS called the C code.
*/
-static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp)
+static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, ccb_p cp)
{
tcb_p tp = &np->target[cp->target];
u32 startp;
u_char s_status = cp->ssss_status;
u_char h_flags = cp->host_flags;
int msglen;
- int nego;
int i;
/*
@@ -3178,16 +3128,7 @@ static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp)
* cp->nego_status is filled by sym_prepare_nego().
*/
cp->nego_status = 0;
- nego = 0;
- if (tp->tinfo.curr.options & PPR_OPT_MASK)
- nego = NS_PPR;
- else if (tp->tinfo.curr.width != BUS_8_BIT)
- nego = NS_WIDE;
- else if (tp->tinfo.curr.offset != 0)
- nego = NS_SYNC;
- if (nego)
- msglen +=
- sym_prepare_nego (np,cp, nego, &cp->scsi_smsg2[msglen]);
+ msglen += sym_prepare_nego(np, cp, &cp->scsi_smsg2[msglen]);
/*
* Message table indirect structure.
*/
@@ -3213,7 +3154,7 @@ static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp)
/*
* sense data
*/
- bzero(cp->sns_bbuf, SYM_SNS_BBUF_LEN);
+ memset(cp->sns_bbuf, 0, SYM_SNS_BBUF_LEN);
cp->phys.sense.addr = cpu_to_scr(vtobus(cp->sns_bbuf));
cp->phys.sense.size = cpu_to_scr(SYM_SNS_BBUF_LEN);
@@ -3263,7 +3204,7 @@ static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp)
* - lun=-1 means any logical UNIT otherwise a given one.
* - task=-1 means any task, otherwise a given one.
*/
-int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task)
+int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task)
{
SYM_QUEHEAD qtmp, *qp;
int i = 0;
@@ -3282,7 +3223,7 @@ int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task)
* the BUSY queue.
*/
while ((qp = sym_remque_head(&qtmp)) != 0) {
- cam_ccb_p ccb;
+ struct scsi_cmnd *ccb;
cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
ccb = cp->cam_ccb;
if (cp->host_status != HS_DISCONNECT ||
@@ -3346,7 +3287,7 @@ printf("XXXX TASK @%p CLEARED\n", cp);
* all the CCBs that should have been aborted by the
* target according to our message.
*/
-static void sym_sir_task_recovery(hcb_p np, int num)
+static void sym_sir_task_recovery(struct sym_hcb *np, int num)
{
SYM_QUEHEAD *qp;
ccb_p cp;
@@ -3698,7 +3639,7 @@ static void sym_sir_task_recovery(hcb_p np, int num)
* the corresponding values of dp_sg and dp_ofs.
*/
-static int sym_evaluate_dp(hcb_p np, ccb_p cp, u32 scr, int *ofs)
+static int sym_evaluate_dp(struct sym_hcb *np, ccb_p cp, u32 scr, int *ofs)
{
u32 dp_scr;
int dp_ofs, dp_sg, dp_sgmin;
@@ -3816,7 +3757,7 @@ out_err:
* is equivalent to a MODIFY DATA POINTER (offset=-1).
*/
-static void sym_modify_dp(hcb_p np, tcb_p tp, ccb_p cp, int ofs)
+static void sym_modify_dp(struct sym_hcb *np, tcb_p tp, ccb_p cp, int ofs)
{
int dp_ofs = ofs;
u32 dp_scr = sym_get_script_dp (np, cp);
@@ -3915,7 +3856,7 @@ out_reject:
* a relevant information. :)
*/
-int sym_compute_residual(hcb_p np, ccb_p cp)
+int sym_compute_residual(struct sym_hcb *np, ccb_p cp)
{
int dp_sg, dp_sgmin, resid = 0;
int dp_ofs = 0;
@@ -4015,7 +3956,7 @@ int sym_compute_residual(hcb_p np, ccb_p cp)
* chip handler for SYNCHRONOUS DATA TRANSFER REQUEST (SDTR) message.
*/
static int
-sym_sync_nego_check(hcb_p np, int req, int target)
+sym_sync_nego_check(struct sym_hcb *np, int req, int target)
{
u_char chg, ofs, per, fak, div;
@@ -4096,7 +4037,7 @@ reject_it:
return -1;
}
-static void sym_sync_nego(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_sync_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
{
int req = 1;
int result;
@@ -4133,7 +4074,7 @@ reject_it:
* chip handler for PARALLEL PROTOCOL REQUEST (PPR) message.
*/
static int
-sym_ppr_nego_check(hcb_p np, int req, int target)
+sym_ppr_nego_check(struct sym_hcb *np, int req, int target)
{
tcb_p tp = &np->target[target];
unsigned char fak, div;
@@ -4176,7 +4117,7 @@ sym_ppr_nego_check(hcb_p np, int req, int target)
if (ofs) {
unsigned char minsync = dt ? np->minsync_dt : np->minsync;
- if (per < np->minsync_dt) {
+ if (per < minsync) {
chg = 1;
per = minsync;
}
@@ -4242,7 +4183,7 @@ reject_it:
return -1;
}
-static void sym_ppr_nego(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_ppr_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
{
int req = 1;
int result;
@@ -4279,7 +4220,7 @@ reject_it:
* chip handler for WIDE DATA TRANSFER REQUEST (WDTR) message.
*/
static int
-sym_wide_nego_check(hcb_p np, int req, int target)
+sym_wide_nego_check(struct sym_hcb *np, int req, int target)
{
u_char chg, wide;
@@ -4344,7 +4285,7 @@ reject_it:
return -1;
}
-static void sym_wide_nego(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_wide_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
{
int req = 1;
int result;
@@ -4413,7 +4354,7 @@ reject_it:
* So, if a PPR makes problems, we may just want to
* try a legacy negotiation later.
*/
-static void sym_nego_default(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_nego_default(struct sym_hcb *np, tcb_p tp, ccb_p cp)
{
switch (cp->nego_status) {
case NS_PPR:
@@ -4443,7 +4384,7 @@ static void sym_nego_default(hcb_p np, tcb_p tp, ccb_p cp)
* chip handler for MESSAGE REJECT received in response to
* PPR, WIDE or SYNCHRONOUS negotiation.
*/
-static void sym_nego_rejected(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_nego_rejected(struct sym_hcb *np, tcb_p tp, ccb_p cp)
{
sym_nego_default(np, tp, cp);
OUTB (HS_PRT, HS_BUSY);
@@ -4452,7 +4393,7 @@ static void sym_nego_rejected(hcb_p np, tcb_p tp, ccb_p cp)
/*
* chip exception handler for programmed interrupts.
*/
-static void sym_int_sir (hcb_p np)
+static void sym_int_sir (struct sym_hcb *np)
{
u_char num = INB (nc_dsps);
u32 dsa = INL (nc_dsa);
@@ -4726,7 +4667,7 @@ out_stuck:
/*
* Acquire a control block
*/
-ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order)
+ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order)
{
tcb_p tp = &np->target[tn];
lcb_p lp = sym_lp(np, tp, ln);
@@ -4875,7 +4816,7 @@ out_free:
/*
* Release one control block
*/
-void sym_free_ccb (hcb_p np, ccb_p cp)
+void sym_free_ccb (struct sym_hcb *np, ccb_p cp)
{
tcb_p tp = &np->target[cp->target];
lcb_p lp = sym_lp(np, tp, cp->lun);
@@ -4960,13 +4901,6 @@ void sym_free_ccb (hcb_p np, ccb_p cp)
sym_remque(&cp->link_ccbq);
sym_insque_head(&cp->link_ccbq, &np->free_ccbq);
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- /*
- * Cancel any pending timeout condition.
- */
- sym_untimeout_ccb(np, cp);
-#endif
-
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
if (lp) {
sym_remque(&cp->link2_ccbq);
@@ -4985,7 +4919,7 @@ void sym_free_ccb (hcb_p np, ccb_p cp)
/*
* Allocate a CCB from memory and initialize its fixed part.
*/
-static ccb_p sym_alloc_ccb(hcb_p np)
+static ccb_p sym_alloc_ccb(struct sym_hcb *np)
{
ccb_p cp = NULL;
int hcode;
@@ -5053,9 +4987,6 @@ static ccb_p sym_alloc_ccb(hcb_p np)
/*
* Chain into optionnal lists.
*/
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
-#endif
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
sym_insque_head(&cp->link2_ccbq, &np->dummy_ccbq);
#endif
@@ -5072,7 +5003,7 @@ out_free:
/*
* Look up a CCB from a DSA value.
*/
-static ccb_p sym_ccb_from_dsa(hcb_p np, u32 dsa)
+static ccb_p sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa)
{
int hcode;
ccb_p cp;
@@ -5092,7 +5023,7 @@ static ccb_p sym_ccb_from_dsa(hcb_p np, u32 dsa)
* Target control block initialisation.
* Nothing important to do at the moment.
*/
-static void sym_init_tcb (hcb_p np, u_char tn)
+static void sym_init_tcb (struct sym_hcb *np, u_char tn)
{
#if 0 /* Hmmm... this checking looks paranoid. */
/*
@@ -5108,7 +5039,7 @@ static void sym_init_tcb (hcb_p np, u_char tn)
/*
* Lun control block allocation and initialization.
*/
-lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln)
+lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
{
tcb_p tp = &np->target[tn];
lcb_p lp = sym_lp(np, tp, ln);
@@ -5210,7 +5141,7 @@ fail:
/*
* Allocate LCB resources for tagged command queuing.
*/
-static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln)
+static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln)
{
tcb_p tp = &np->target[tn];
lcb_p lp = sym_lp(np, tp, ln);
@@ -5262,7 +5193,7 @@ fail:
/*
* Queue a SCSI IO to the controller.
*/
-int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp)
+int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp)
{
tcb_p tp;
lcb_p lp;
@@ -5273,7 +5204,7 @@ int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp)
/*
* Keep track of the IO in our CCB.
*/
- cp->cam_ccb = (cam_ccb_p) csio;
+ cp->cam_ccb = csio;
/*
* Retrieve the target descriptor.
@@ -5351,7 +5282,7 @@ int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp)
tp->tinfo.curr.offset != tp->tinfo.goal.offset ||
tp->tinfo.curr.options != tp->tinfo.goal.options) {
if (!tp->nego_cp && lp)
- msglen += sym_prepare_nego(np, cp, 0, msgptr + msglen);
+ msglen += sym_prepare_nego(np, cp, msgptr + msglen);
}
/*
@@ -5401,7 +5332,7 @@ int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp)
/*
* Reset a SCSI target (all LUNs of this target).
*/
-int sym_reset_scsi_target(hcb_p np, int target)
+int sym_reset_scsi_target(struct sym_hcb *np, int target)
{
tcb_p tp;
@@ -5420,7 +5351,7 @@ int sym_reset_scsi_target(hcb_p np, int target)
/*
* Abort a SCSI IO.
*/
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out)
+int sym_abort_ccb(struct sym_hcb *np, ccb_p cp, int timed_out)
{
/*
* Check that the IO is active.
@@ -5450,7 +5381,7 @@ int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out)
return 0;
}
-int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out)
+int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out)
{
ccb_p cp;
SYM_QUEHEAD *qp;
@@ -5480,7 +5411,7 @@ int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out)
* SCRATCHA is assumed to have been loaded with STARTPOS
* before the SCRIPTS called the C code.
*/
-void sym_complete_error (hcb_p np, ccb_p cp)
+void sym_complete_error (struct sym_hcb *np, ccb_p cp)
{
tcb_p tp;
lcb_p lp;
@@ -5614,11 +5545,11 @@ finish:
* The SCRIPTS processor is running while we are
* completing successful commands.
*/
-void sym_complete_ok (hcb_p np, ccb_p cp)
+void sym_complete_ok (struct sym_hcb *np, ccb_p cp)
{
tcb_p tp;
lcb_p lp;
- cam_ccb_p ccb;
+ struct scsi_cmnd *ccb;
int resid;
/*
@@ -5724,7 +5655,7 @@ if (resid)
/*
* Soft-attach the controller.
*/
-int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram)
+int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvram)
{
int i;
@@ -5815,17 +5746,9 @@ int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram)
sym_que_init(&np->comp_ccbq);
/*
- * Initializations for optional handling
- * of IO timeouts and device queueing.
+ * Initialization for optional handling
+ * of device queueing.
*/
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- sym_que_init(&np->tmo0_ccbq);
- np->tmo_ccbq =
- sym_calloc(2*SYM_CONF_TIMEOUT_ORDER_MAX*sizeof(SYM_QUEHEAD),
- "TMO_CCBQ");
- for (i = 0 ; i < 2*SYM_CONF_TIMEOUT_ORDER_MAX ; i++)
- sym_que_init(&np->tmo_ccbq[i]);
-#endif
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
sym_que_init(&np->dummy_ccbq);
#endif
@@ -5957,7 +5880,7 @@ attach_failed:
/*
* Free everything that has been allocated for this device.
*/
-void sym_hcb_free(hcb_p np)
+void sym_hcb_free(struct sym_hcb *np)
{
SYM_QUEHEAD *qp;
ccb_p cp;
@@ -5971,12 +5894,6 @@ void sym_hcb_free(hcb_p np)
sym_mfree_dma(np->scriptb0, np->scriptb_sz, "SCRIPTB0");
if (np->scripta0)
sym_mfree_dma(np->scripta0, np->scripta_sz, "SCRIPTA0");
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- if (np->tmo_ccbq)
- sym_mfree(np->tmo_ccbq,
- 2*SYM_CONF_TIMEOUT_ORDER_MAX*sizeof(SYM_QUEHEAD),
- "TMO_CCBQ");
-#endif
if (np->squeue)
sym_mfree_dma(np->squeue, sizeof(u32)*(MAX_QUEUE*2), "SQUEUE");
if (np->dqueue)
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index 4d3b98953952..e3509d4c879c 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -749,7 +749,7 @@ struct sym_ccb {
/*
* Pointer to CAM ccb and related stuff.
*/
- cam_ccb_p cam_ccb; /* CAM scsiio ccb */
+ struct scsi_cmnd *cam_ccb; /* CAM scsiio ccb */
u8 cdb_buf[16]; /* Copy of CDB */
u8 *sns_bbuf; /* Bounce buffer for sense data */
#ifndef SYM_SNS_BBUF_LEN
@@ -796,10 +796,6 @@ struct sym_ccb {
/*
* Other fields.
*/
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- SYM_QUEHEAD tmo_linkq; /* Optional timeout handling */
- u_int tmo_clock; /* (link and dealine value) */
-#endif
u32 ccb_ba; /* BUS address of this CCB */
u_short tag; /* Tag for this transfer */
/* NO_TAG means no tag */
@@ -946,8 +942,8 @@ struct sym_hcb {
struct sym_fwa_ba fwa_bas; /* Useful SCRIPTA bus addresses */
struct sym_fwb_ba fwb_bas; /* Useful SCRIPTB bus addresses */
struct sym_fwz_ba fwz_bas; /* Useful SCRIPTZ bus addresses */
- void (*fw_setup)(hcb_p np, struct sym_fw *fw);
- void (*fw_patch)(hcb_p np);
+ void (*fw_setup)(struct sym_hcb *np, struct sym_fw *fw);
+ void (*fw_patch)(struct sym_hcb *np);
char *fw_name;
/*
@@ -1025,15 +1021,6 @@ struct sym_hcb {
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
SYM_QUEHEAD dummy_ccbq;
#endif
- /*
- * Optional handling of IO timeouts.
- */
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- SYM_QUEHEAD tmo0_ccbq;
- SYM_QUEHEAD *tmo_ccbq; /* [2*SYM_TIMEOUT_ORDER_MAX] */
- u_int tmo_clock;
- u_int tmo_actq;
-#endif
/*
* IMMEDIATE ARBITRATION (IARB) control.
@@ -1082,54 +1069,39 @@ struct sym_hcb {
* FIRMWARES (sym_fw.c)
*/
struct sym_fw * sym_find_firmware(struct sym_pci_chip *chip);
-void sym_fw_bind_script (hcb_p np, u32 *start, int len);
+void sym_fw_bind_script (struct sym_hcb *np, u32 *start, int len);
/*
* Driver methods called from O/S specific code.
*/
char *sym_driver_name(void);
void sym_print_xerr(ccb_p cp, int x_status);
-int sym_reset_scsi_bus(hcb_p np, int enab_int);
+int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);
struct sym_pci_chip *
sym_lookup_pci_chip_table (u_short device_id, u_char revision);
-void sym_put_start_queue(hcb_p np, ccb_p cp);
+void sym_put_start_queue(struct sym_hcb *np, ccb_p cp);
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
-void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn);
+void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn);
#endif
-void sym_start_up (hcb_p np, int reason);
-void sym_interrupt (hcb_p np);
-void sym_flush_comp_queue(hcb_p np, int cam_status);
-int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task);
-ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order);
-void sym_free_ccb (hcb_p np, ccb_p cp);
-lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln);
-int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp);
-int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out);
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
-int sym_reset_scsi_target(hcb_p np, int target);
-void sym_hcb_free(hcb_p np);
-int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram);
-
-/*
- * Optionnaly, the driver may handle IO timeouts.
- */
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
-void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks);
-static void __inline sym_untimeout_ccb(hcb_p np, ccb_p cp)
-{
- sym_remque(&cp->tmo_linkq);
- sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
-}
-void sym_clock(hcb_p np);
-#endif /* SYM_OPT_HANDLE_IO_TIMEOUT */
+void sym_start_up (struct sym_hcb *np, int reason);
+void sym_interrupt (struct sym_hcb *np);
+int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task);
+ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order);
+void sym_free_ccb (struct sym_hcb *np, ccb_p cp);
+lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln);
+int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp);
+int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out);
+int sym_abort_ccb(struct sym_hcb *np, ccb_p cp, int timed_out);
+int sym_reset_scsi_target(struct sym_hcb *np, int target);
+void sym_hcb_free(struct sym_hcb *np);
+int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvram);
/*
* Optionnaly, the driver may provide a function
* to announce transfer rate changes.
*/
#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
-void sym_announce_transfer_rate(hcb_p np, int target);
+void sym_announce_transfer_rate(struct sym_hcb *np, int target);
#endif
/*
@@ -1153,9 +1125,9 @@ do { \
(data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len); \
} while (0)
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
-int sym_lookup_dmap(hcb_p np, u32 h, int s);
+int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s);
static __inline void
-sym_build_sge(hcb_p np, struct sym_tblmove *data, u64 badd, int len)
+sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
{
u32 h = (badd>>32);
int s = (h&SYM_DMAP_MASK);
diff --git a/drivers/scsi/sym53c8xx_2/sym_malloc.c b/drivers/scsi/sym53c8xx_2/sym_malloc.c
index 567a6dd31a27..01f380a2d28f 100644
--- a/drivers/scsi/sym53c8xx_2/sym_malloc.c
+++ b/drivers/scsi/sym53c8xx_2/sym_malloc.c
@@ -170,7 +170,7 @@ static void *__sym_calloc2(m_pool_p mp, int size, char *name, int uflags)
}
if (p)
- bzero(p, size);
+ memset(p, 0, size);
else if (uflags & SYM_MEM_WARN)
printf ("__sym_calloc2: failed to allocate %s[%d]\n", name, size);
return p;
diff --git a/drivers/scsi/sym53c8xx_2/sym_misc.c b/drivers/scsi/sym53c8xx_2/sym_misc.c
index f27f52e651dc..0b678ae73acc 100644
--- a/drivers/scsi/sym53c8xx_2/sym_misc.c
+++ b/drivers/scsi/sym53c8xx_2/sym_misc.c
@@ -37,109 +37,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifdef __FreeBSD__
-#include <dev/sym/sym_glue.h>
-#else
#include "sym_glue.h"
-#endif
-
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
-/*
- * Optional CCB timeout handling.
- *
- * This code is useful for O/Ses that allow or expect
- * SIMs (low-level drivers) to handle SCSI IO timeouts.
- * It uses a power-of-two based algorithm of my own:)
- * that avoids scanning of lists, provided that:
- *
- * - The IO does complete in less than half the associated
- * timeout value.
- * - The greatest delay between the queuing of the IO and
- * its completion is less than
- * (1<<(SYM_CONF_TIMEOUT_ORDER_MAX-1))/2 ticks.
- *
- * For example, if tick is 1 second and the max order is 8,
- * any IO that is completed within less than 64 seconds will
- * just be put into some list at queuing and be removed
- * at completion without any additionnal overhead.
- */
-
-/*
- * Set a timeout condition on a CCB.
- */
-void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks)
-{
- sym_remque(&cp->tmo_linkq);
- cp->tmo_clock = np->tmo_clock + ticks;
- if (!ticks) {
- sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
- }
- else {
- int i = SYM_CONF_TIMEOUT_ORDER_MAX - 1;
- while (i > 0) {
- if (ticks >= (1<<(i+1)))
- break;
- --i;
- }
- if (!(np->tmo_actq & (1<<i)))
- i += SYM_CONF_TIMEOUT_ORDER_MAX;
- sym_insque_head(&cp->tmo_linkq, &np->tmo_ccbq[i]);
- }
-}
-
-/*
- * Walk a list of CCB and handle timeout conditions.
- * Should never be called in normal situations.
- */
-static void sym_walk_ccb_tmo_list(hcb_p np, SYM_QUEHEAD *tmoq)
-{
- SYM_QUEHEAD qtmp, *qp;
- ccb_p cp;
-
- sym_que_move(tmoq, &qtmp);
- while ((qp = sym_remque_head(&qtmp)) != 0) {
- sym_insque_head(qp, &np->tmo0_ccbq);
- cp = sym_que_entry(qp, struct sym_ccb, tmo_linkq);
- if (cp->tmo_clock != np->tmo_clock &&
- cp->tmo_clock + 1 != np->tmo_clock)
- sym_timeout_ccb(np, cp, cp->tmo_clock - np->tmo_clock);
- else
- sym_abort_ccb(np, cp, 1);
- }
-}
-
-/*
- * Our clock handler called from the O/S specific side.
- */
-void sym_clock(hcb_p np)
-{
- int i, j;
- u_int tmp;
-
- tmp = np->tmo_clock;
- tmp ^= (++np->tmo_clock);
-
- for (i = 0; i < SYM_CONF_TIMEOUT_ORDER_MAX; i++, tmp >>= 1) {
- if (!(tmp & 1))
- continue;
- j = i;
- if (np->tmo_actq & (1<<i))
- j += SYM_CONF_TIMEOUT_ORDER_MAX;
-
- if (!sym_que_empty(&np->tmo_ccbq[j])) {
- sym_walk_ccb_tmo_list(np, &np->tmo_ccbq[j]);
- }
- np->tmo_actq ^= (1<<i);
- }
-}
-#endif /* SYM_OPT_HANDLE_IO_TIMEOUT */
-
#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
/*
* Announce transfer rate if anything changed since last announcement.
*/
-void sym_announce_transfer_rate(hcb_p np, int target)
+void sym_announce_transfer_rate(struct sym_hcb *np, int target)
{
tcb_p tp = &np->target[target];
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c
index f3621324a73b..0809437706e8 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.c
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c
@@ -68,6 +68,21 @@ void sym_nvram_setup_host(struct sym_hcb *np, struct sym_nvram *nvram)
case SYM_TEKRAM_NVRAM:
np->myaddr = nvram->data.Tekram.host_id & 0x0f;
break;
+#ifdef CONFIG_PARISC
+ case SYM_PARISC_PDC:
+ if (nvram->data.parisc.host_id != -1)
+ np->myaddr = nvram->data.parisc.host_id;
+ if (nvram->data.parisc.factor != -1)
+ np->minsync = nvram->data.parisc.factor;
+ if (nvram->data.parisc.width != -1)
+ np->maxwide = nvram->data.parisc.width;
+ switch (nvram->data.parisc.mode) {
+ case 0: np->scsi_mode = SMODE_SE; break;
+ case 1: np->scsi_mode = SMODE_HVD; break;
+ case 2: np->scsi_mode = SMODE_LVD; break;
+ default: break;
+ }
+#endif
default:
break;
}
@@ -702,6 +717,28 @@ static int sym_read_Tekram_nvram (struct sym_device *np, Tekram_nvram *nvram)
return 0;
}
+#ifdef CONFIG_PARISC
+/*
+ * Host firmware (PDC) keeps a table for altering SCSI capabilities.
+ * Many newer machines export one channel of 53c896 chip as SE, 50-pin HD.
+ * Also used for Multi-initiator SCSI clusters to set the SCSI Initiator ID.
+ */
+static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *pdc)
+{
+ struct hardware_path hwpath;
+ get_pci_node_path(np->pdev, &hwpath);
+ if (!pdc_get_initiator(&hwpath, pdc))
+ return 0;
+
+ return SYM_PARISC_PDC;
+}
+#else
+static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *x)
+{
+ return 0;
+}
+#endif
+
/*
* Try reading Symbios or Tekram NVRAM
*/
@@ -714,7 +751,7 @@ int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp)
nvp->type = SYM_TEKRAM_NVRAM;
sym_display_Tekram_nvram(np, &nvp->data.Tekram);
} else {
- nvp->type = 0;
+ nvp->type = sym_read_parisc_pdc(np, &nvp->data.parisc);
}
return nvp->type;
}
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.h b/drivers/scsi/sym53c8xx_2/sym_nvram.h
index a6bd02afba40..9572f87b599a 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.h
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.h
@@ -171,6 +171,10 @@ struct Tekram_nvram {
typedef struct Tekram_nvram Tekram_nvram;
typedef struct Tekram_target Tekram_target;
+#ifndef CONFIG_PARISC
+struct pdc_initiator { int dummy; };
+#endif
+
/*
* Union of supported NVRAM formats.
*/
@@ -178,10 +182,12 @@ struct sym_nvram {
int type;
#define SYM_SYMBIOS_NVRAM (1)
#define SYM_TEKRAM_NVRAM (2)
+#define SYM_PARISC_PDC (3)
#if SYM_CONF_NVRAM_SUPPORT
union {
Symbios_nvram Symbios;
Tekram_nvram Tekram;
+ struct pdc_initiator parisc;
} data;
#endif
};
diff --git a/drivers/scsi/sym53c8xx_comm.h b/drivers/scsi/sym53c8xx_comm.h
index 7ca14db34754..04ebe5486d5b 100644
--- a/drivers/scsi/sym53c8xx_comm.h
+++ b/drivers/scsi/sym53c8xx_comm.h
@@ -505,8 +505,6 @@ static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd)
#define unmap_scsi_data(np, cmd) __unmap_scsi_data(np->dev, cmd)
#define map_scsi_single_data(np, cmd) __map_scsi_single_data(np->dev, cmd)
#define map_scsi_sg_data(np, cmd) __map_scsi_sg_data(np->dev, cmd)
-#define sync_scsi_data_for_cpu(np, cmd) __sync_scsi_data_for_cpu(np->dev, cmd)
-#define sync_scsi_data_for_device(np, cmd) __sync_scsi_data_for_device(np->dev, cmd)
/*==========================================================
**
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index c2afeb777563..31ba6a9168c7 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -87,7 +87,7 @@ zalon_probe(struct parisc_device *dev)
{
struct gsc_irq gsc_irq;
u32 zalon_vers;
- int irq, error = -ENODEV;
+ int error = -ENODEV;
unsigned long zalon = dev->hpa;
unsigned long io_port = zalon + GSC_SCSI_ZALON_OFFSET;
static int unit = 0;
@@ -107,10 +107,10 @@ zalon_probe(struct parisc_device *dev)
/* Setup the interrupts first.
** Later on request_irq() will register the handler.
*/
- irq = gsc_alloc_irq(&gsc_irq);
+ dev->irq = gsc_alloc_irq(&gsc_irq);
printk("%s: Zalon vers field is 0x%x, IRQ %d\n", __FUNCTION__,
- zalon_vers, irq);
+ zalon_vers, dev->irq);
__raw_writel(gsc_irq.txn_addr | gsc_irq.txn_data, dev->hpa + IO_MODULE_EIM);
@@ -130,16 +130,16 @@ zalon_probe(struct parisc_device *dev)
device.dev = &dev->dev;
device.slot.base = (u_long)io_port;
device.slot.base_c = (u_long)io_port;
- device.slot.irq = irq;
+ device.slot.irq = dev->irq;
device.differential = 2;
host = ncr_attach(&zalon7xx_template, unit, &device);
if (!host)
goto fail;
- if (request_irq(irq, ncr53c8xx_intr, SA_SHIRQ, dev->dev.bus_id, host)) {
+ if (request_irq(dev->irq, ncr53c8xx_intr, SA_SHIRQ, "zalon", host)) {
printk(KERN_ERR "%s: irq problem with %d, detaching\n ",
- dev->dev.bus_id, irq);
+ dev->dev.bus_id, dev->irq);
goto fail;
}
@@ -155,7 +155,7 @@ zalon_probe(struct parisc_device *dev)
return 0;
fail_free_irq:
- free_irq(irq, host);
+ free_irq(dev->irq, host);
fail:
ncr53c8xx_release(host);
return error;
@@ -171,18 +171,16 @@ MODULE_DEVICE_TABLE(parisc, zalon_tbl);
static int __exit zalon_remove(struct parisc_device *dev)
{
struct Scsi_Host *host = dev_get_drvdata(&dev->dev);
- int irq = host->irq;
scsi_remove_host(host);
ncr53c8xx_release(host);
- free_irq(irq, host);
+ free_irq(dev->irq, host);
return 0;
}
-
static struct parisc_driver zalon_driver = {
- .name = "GSC SCSI (Zalon)",
+ .name = "zalon",
.id_table = zalon_tbl,
.probe = zalon_probe,
.remove = __devexit_p(zalon_remove),
@@ -201,6 +199,7 @@ static int __init zalon7xx_init(void)
static void __exit zalon7xx_exit(void)
{
unregister_parisc_driver(&zalon_driver);
+ ncr53c8xx_exit();
}
module_init(zalon7xx_init);
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 6be72e5a2c4f..59dd5560fa1f 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -237,7 +237,6 @@ static dev_link_t *serial_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -749,10 +748,7 @@ static int __init init_serial_cs(void)
static void __exit exit_serial_cs(void)
{
pcmcia_unregister_driver(&serial_cs_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- serial_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(init_serial_cs);
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index f216f6a6db52..e1ef0d7ee8d1 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -69,7 +69,6 @@ static dev_link_t *ixj_attach(void)
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
@@ -313,10 +312,7 @@ static int __init ixj_pcmcia_init(void)
static void ixj_pcmcia_exit(void)
{
pcmcia_unregister_driver(&ixj_driver);
-
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL)
- ixj_detach(dev_list);
+ BUG_ON(dev_list != NULL);
}
module_init(ixj_pcmcia_init);
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 0fdf9af099d3..470428e91245 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -2477,8 +2477,10 @@ module_param(noinit, int, 0);
MODULE_PARM_DESC(noinit, "Disables W/SG/SD-RAM and bus interface initialization (0 or 1=do not initialize) (default=0)");
module_param(memtype, int, 0);
MODULE_PARM_DESC(memtype, "Memory type for G200/G400 (see Documentation/fb/matroxfb.txt for explanation) (default=3 for G200, 0 for G400)");
+#ifdef CONFIG_MTRR
module_param(mtrr, int, 0);
MODULE_PARM_DESC(mtrr, "This speeds up video memory accesses (0=disabled or 1) (default=1)");
+#endif
module_param(sgram, int, 0);
MODULE_PARM_DESC(sgram, "Indicates that G100/G200/G400 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)");
module_param(inv24, int, 0);
diff --git a/fs/Kconfig b/fs/Kconfig
index e2661f504c5d..17e4eb1b97a8 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -578,9 +578,8 @@ config FAT_FS
tristate
select NLS
help
- If you want to use one of the FAT-based file systems (the MS-DOS,
- VFAT (Windows 95) and UMSDOS (used to run Linux on top of an
- ordinary DOS partition) file systems), then you must say Y or M here
+ If you want to use one of the FAT-based file systems (the MS-DOS and
+ VFAT (Windows 95) file systems), then you must say Y or M here
to include FAT support. You will then be able to mount partitions or
diskettes with FAT-based file systems and transparently access the
files on them, i.e. MSDOS files will look and behave just like all
@@ -612,9 +611,6 @@ config FAT_FS
fat. Note that if you compile the FAT support as a module, you
cannot compile any of the FAT-based file systems into the kernel
-- they will have to be modules as well.
- The file system of your root partition (the one containing the
- directory /) cannot be a module, so don't say M here if you intend
- to use UMSDOS as your root file system.
config MSDOS_FS
tristate "MSDOS fs support"
@@ -631,10 +627,6 @@ config MSDOS_FS
transparent, i.e. the MSDOS files look and behave just like all
other Unix files.
- If you want to use UMSDOS, the Unix-like file system on top of a
- DOS file system, which allows you to run Linux from within a DOS
- partition without repartitioning, you'll have to say Y or M here.
-
If you have Windows 95 or Windows NT installed on your MSDOS
partitions, you should use the VFAT file system (say Y to "VFAT fs
support" below), or you will not be able to see the long filenames
@@ -654,11 +646,6 @@ config VFAT_FS
used by Windows 95, Windows 98, Windows NT 4.0, and the Unix
programs from the mtools package.
- You cannot use the VFAT file system for your Linux root partition
- (the one containing the directory /); use UMSDOS instead if you
- want to run Linux from within a DOS partition (i.e. say Y to
- "Unix like fs on top of std MSDOS fs", below).
-
The VFAT support enlarges your kernel by about 10 KB and it only
works if you said Y to the "DOS FAT fs support" above. Please read
the file <file:Documentation/filesystems/vfat.txt> for details. If
@@ -689,35 +676,6 @@ config FAT_DEFAULT_IOCHARSET
If unsure, you shouldn't set "utf8" here.
See <file:Documentation/filesystems/vfat.txt> for more information.
-config UMSDOS_FS
-#dep_tristate ' UMSDOS: Unix-like file system on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS
-# UMSDOS is temprory broken
- bool
- help
- Say Y here if you want to run Linux from within an existing DOS
- partition of your hard drive. The advantage of this is that you can
- get away without repartitioning your hard drive (which often implies
- backing everything up and restoring afterwards) and hence you're
- able to quickly try out Linux or show it to your friends; the
- disadvantage is that Linux becomes susceptible to DOS viruses and
- that UMSDOS is somewhat slower than ext2fs. Another use of UMSDOS
- is to write files with long unix filenames to MSDOS floppies; it
- also allows Unix-style soft-links and owner/permissions of files on
- MSDOS floppies. You will need a program called umssync in order to
- make use of UMSDOS; read
- <file:Documentation/filesystems/umsdos.txt>.
-
- To get utilities for initializing/checking UMSDOS file system, or
- latest patches and/or information, visit the UMSDOS home page at
- <http://www.voyager.hr/~mnalis/umsdos/>.
-
- This option enlarges your kernel by about 28 KB and it only works if
- you said Y to both "DOS FAT fs support" and "MSDOS fs support"
- above. To compile this as a module, choose M here: the module will be
- called umsdos. Note that the file system of your root partition
- (the one containing the directory /) cannot be a module, so saying M
- could be dangerous. If unsure, say N.
-
config NTFS_FS
tristate "NTFS file system support"
select NLS
diff --git a/fs/Makefile b/fs/Makefile
index 82dbf96892fa..443f2bc56ccf 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -57,7 +57,6 @@ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
obj-$(CONFIG_CODA_FS) += coda/
obj-$(CONFIG_MINIX_FS) += minix/
obj-$(CONFIG_FAT_FS) += fat/
-obj-$(CONFIG_UMSDOS_FS) += umsdos/
obj-$(CONFIG_MSDOS_FS) += msdos/
obj-$(CONFIG_VFAT_FS) += vfat/
obj-$(CONFIG_BFS_FS) += bfs/
diff --git a/fs/attr.c b/fs/attr.c
index 468f3396006d..d8524fc01e10 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -171,6 +171,9 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
if (!attr->ia_valid)
return 0;
+ if (ia_valid & ATTR_SIZE)
+ down_write(&dentry->d_inode->i_alloc_sem);
+
if (inode->i_op && inode->i_op->setattr) {
error = security_inode_setattr(dentry, attr);
if (!error)
@@ -187,6 +190,10 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
error = inode_setattr(inode, attr);
}
}
+
+ if (ia_valid & ATTR_SIZE)
+ up_write(&dentry->d_inode->i_alloc_sem);
+
if (!error) {
unsigned long dn_mask = setattr_mask(ia_valid);
if (dn_mask)
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index acdd53848566..a53d9a9e0de4 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -50,7 +50,10 @@ static int set_brk(unsigned long start, unsigned long end)
start = PAGE_ALIGN(start);
end = PAGE_ALIGN(end);
if (end > start) {
- unsigned long addr = do_brk(start, end - start);
+ unsigned long addr;
+ down_write(&current->mm->mmap_sem);
+ addr = do_brk(start, end - start);
+ up_write(&current->mm->mmap_sem);
if (BAD_ADDR(addr))
return addr;
}
@@ -112,7 +115,7 @@ static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
set_fs(KERNEL_DS);
has_dumped = 1;
current->flags |= PF_DUMPCORE;
- strncpy(dump.u_comm, current->comm, sizeof(current->comm));
+ strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm));
#ifndef __sparc__
dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
#endif
@@ -323,10 +326,14 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
loff_t pos = fd_offset;
/* Fuck me plenty... */
/* <AOL></AOL> */
+ down_write(&current->mm->mmap_sem);
error = do_brk(N_TXTADDR(ex), ex.a_text);
+ up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
ex.a_text, &pos);
+ down_write(&current->mm->mmap_sem);
error = do_brk(N_DATADDR(ex), ex.a_data);
+ up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex),
ex.a_data, &pos);
goto beyond_if;
@@ -346,8 +353,9 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
pos = 32;
map_size = ex.a_text+ex.a_data;
#endif
-
+ down_write(&current->mm->mmap_sem);
error = do_brk(text_addr & PAGE_MASK, map_size);
+ up_write(&current->mm->mmap_sem);
if (error != (text_addr & PAGE_MASK)) {
send_sig(SIGKILL, current, 0);
return error;
@@ -382,7 +390,9 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
loff_t pos = fd_offset;
+ down_write(&current->mm->mmap_sem);
do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
+ up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file,
(char __user *)N_TXTADDR(ex),
ex.a_text+ex.a_data, &pos);
@@ -487,8 +497,9 @@ static int load_aout_library(struct file *file)
file->f_dentry->d_name.name);
error_time = jiffies;
}
-
+ down_write(&current->mm->mmap_sem);
do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+ up_write(&current->mm->mmap_sem);
file->f_op->read(file, (char __user *)start_addr,
ex.a_text + ex.a_data, &pos);
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 0ecc44fb0551..6eb6971bdee2 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -88,7 +88,10 @@ static int set_brk(unsigned long start, unsigned long end)
start = ELF_PAGEALIGN(start);
end = ELF_PAGEALIGN(end);
if (end > start) {
- unsigned long addr = do_brk(start, end - start);
+ unsigned long addr;
+ down_write(&current->mm->mmap_sem);
+ addr = do_brk(start, end - start);
+ up_write(&current->mm->mmap_sem);
if (BAD_ADDR(addr))
return addr;
}
@@ -322,7 +325,8 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
*/
if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))
goto out;
- if (interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr))
+ if (interp_elf_ex->e_phnum < 1 ||
+ interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr))
goto out;
/* Now read in all of the header information */
@@ -408,7 +412,9 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
/* Map the last of the bss segment */
if (last_bss > elf_bss) {
+ down_write(&current->mm->mmap_sem);
error = do_brk(elf_bss, last_bss - elf_bss);
+ up_write(&current->mm->mmap_sem);
if (BAD_ADDR(error))
goto out_close;
}
@@ -448,7 +454,9 @@ static unsigned long load_aout_interp(struct exec * interp_ex,
goto out;
}
+ down_write(&current->mm->mmap_sem);
do_brk(0, text_data);
+ up_write(&current->mm->mmap_sem);
if (!interpreter->f_op || !interpreter->f_op->read)
goto out;
if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0)
@@ -456,8 +464,11 @@ static unsigned long load_aout_interp(struct exec * interp_ex,
flush_icache_range((unsigned long)addr,
(unsigned long)addr + text_data);
+
+ down_write(&current->mm->mmap_sem);
do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
interp_ex->a_bss);
+ up_write(&current->mm->mmap_sem);
elf_entry = interp_ex->a_entry;
out:
@@ -524,12 +535,13 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
/* Now read in all of the header information */
- retval = -ENOMEM;
if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr))
goto out;
- if (loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
+ if (loc->elf_ex.e_phnum < 1 ||
+ loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
goto out;
size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr);
+ retval = -ENOMEM;
elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
if (!elf_phdata)
goto out;
@@ -575,10 +587,12 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
* is an a.out format binary
*/
- retval = -ENOMEM;
+ retval = -ENOEXEC;
if (elf_ppnt->p_filesz > PATH_MAX ||
- elf_ppnt->p_filesz == 0)
+ elf_ppnt->p_filesz < 2)
goto out_free_file;
+
+ retval = -ENOMEM;
elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
GFP_KERNEL);
if (!elf_interpreter)
@@ -593,7 +607,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
goto out_free_interp;
}
/* make sure path is NULL terminated */
- retval = -EINVAL;
+ retval = -ENOEXEC;
if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
goto out_free_interp;
@@ -868,8 +882,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
interpreter,
&interp_load_addr);
if (BAD_ADDR(elf_entry)) {
- printk(KERN_ERR "Unable to load interpreter\n");
- send_sig(SIGSEGV, current, 0);
+ printk(KERN_ERR "Unable to load interpreter %.128s\n",
+ elf_interpreter);
+ force_sig(SIGSEGV, current);
retval = -ENOEXEC; /* Nobody gets to see this, but.. */
goto out_free_dentry;
}
@@ -1215,16 +1230,16 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
* this and each other thread to finish dying after the
* core dump synchronization phase.
*/
- jiffies_to_timeval(p->utime + p->signal->utime,
+ cputime_to_timeval(cputime_add(p->utime, p->signal->utime),
&prstatus->pr_utime);
- jiffies_to_timeval(p->stime + p->signal->stime,
+ cputime_to_timeval(cputime_add(p->stime, p->signal->stime),
&prstatus->pr_stime);
} else {
- jiffies_to_timeval(p->utime, &prstatus->pr_utime);
- jiffies_to_timeval(p->stime, &prstatus->pr_stime);
+ cputime_to_timeval(p->utime, &prstatus->pr_utime);
+ cputime_to_timeval(p->stime, &prstatus->pr_stime);
}
- jiffies_to_timeval(p->signal->cutime, &prstatus->pr_cutime);
- jiffies_to_timeval(p->signal->cstime, &prstatus->pr_cstime);
+ cputime_to_timeval(p->signal->cutime, &prstatus->pr_cutime);
+ cputime_to_timeval(p->signal->cstime, &prstatus->pr_cstime);
}
static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
diff --git a/fs/bio.c b/fs/bio.c
index 3580d5ce64df..3e55a58714f9 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -98,12 +98,7 @@ static void bio_destructor(struct bio *bio)
BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS);
- /*
- * cloned bio doesn't own the veclist
- */
- if (!bio_flagged(bio, BIO_CLONED))
- mempool_free(bio->bi_io_vec, bp->pool);
-
+ mempool_free(bio->bi_io_vec, bp->pool);
mempool_free(bio, bio_pool);
}
@@ -210,7 +205,9 @@ inline int bio_hw_segments(request_queue_t *q, struct bio *bio)
*/
inline void __bio_clone(struct bio *bio, struct bio *bio_src)
{
- bio->bi_io_vec = bio_src->bi_io_vec;
+ request_queue_t *q = bdev_get_queue(bio_src->bi_bdev);
+
+ memcpy(bio->bi_io_vec, bio_src->bi_io_vec, bio_src->bi_max_vecs * sizeof(struct bio_vec));
bio->bi_sector = bio_src->bi_sector;
bio->bi_bdev = bio_src->bi_bdev;
@@ -222,21 +219,9 @@ inline void __bio_clone(struct bio *bio, struct bio *bio_src)
* for the clone
*/
bio->bi_vcnt = bio_src->bi_vcnt;
- bio->bi_idx = bio_src->bi_idx;
- if (bio_flagged(bio, BIO_SEG_VALID)) {
- bio->bi_phys_segments = bio_src->bi_phys_segments;
- bio->bi_hw_segments = bio_src->bi_hw_segments;
- bio->bi_flags |= (1 << BIO_SEG_VALID);
- }
bio->bi_size = bio_src->bi_size;
-
- /*
- * cloned bio does not own the bio_vec, so users cannot fiddle with
- * it. clear bi_max_vecs and clear the BIO_POOL_BITS to make this
- * apparent
- */
- bio->bi_max_vecs = 0;
- bio->bi_flags &= (BIO_POOL_MASK - 1);
+ bio_phys_segments(q, bio);
+ bio_hw_segments(q, bio);
}
/**
@@ -248,7 +233,7 @@ inline void __bio_clone(struct bio *bio, struct bio *bio_src)
*/
struct bio *bio_clone(struct bio *bio, int gfp_mask)
{
- struct bio *b = bio_alloc(gfp_mask, 0);
+ struct bio *b = bio_alloc(gfp_mask, bio->bi_max_vecs);
if (b)
__bio_clone(b, bio);
diff --git a/fs/buffer.c b/fs/buffer.c
index 7a31850892cb..341ba4c58a18 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -311,10 +311,10 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
{
struct inode * inode = dentry->d_inode;
struct super_block * sb;
- int ret;
+ int ret, err;
/* sync the inode to buffers */
- write_inode_now(inode, 0);
+ ret = write_inode_now(inode, 0);
/* sync the superblock to buffers */
sb = inode->i_sb;
@@ -324,7 +324,9 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
unlock_super(sb);
/* .. finally sync the buffers to disk */
- ret = sync_blockdev(sb->s_bdev);
+ err = sync_blockdev(sb->s_bdev);
+ if (!ret)
+ ret = err;
return ret;
}
diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c
index 6bf72ebb1c57..23aeef5aa814 100644
--- a/fs/coda/cnode.c
+++ b/fs/coda/cnode.c
@@ -11,7 +11,7 @@
#include <linux/coda_fs_i.h>
#include <linux/coda_psdev.h>
-inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)
+static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)
{
return memcmp(fid1, fid2, sizeof(*fid1)) == 0;
}
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 7397d7c93bd4..2391766e9c7c 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -29,7 +29,6 @@
/* dir inode-ops */
static int coda_create(struct inode *dir, struct dentry *new, int mode, struct nameidata *nd);
-static int coda_mknod(struct inode *dir, struct dentry *new, int mode, dev_t rdev);
static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, struct nameidata *nd);
static int coda_link(struct dentry *old_dentry, struct inode *dir_inode,
struct dentry *entry);
@@ -53,9 +52,14 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir,
void *dirent, struct dentry *dir);
int coda_fsync(struct file *, struct dentry *dentry, int datasync);
-int coda_hasmknod;
+/* same as fs/bad_inode.c */
+static int coda_return_EIO(void)
+{
+ return -EIO;
+}
+#define CODA_EIO_ERROR ((void *) (coda_return_EIO))
-struct dentry_operations coda_dentry_operations =
+static struct dentry_operations coda_dentry_operations =
{
.d_revalidate = coda_dentry_revalidate,
.d_delete = coda_dentry_delete,
@@ -70,7 +74,7 @@ struct inode_operations coda_dir_inode_operations =
.symlink = coda_symlink,
.mkdir = coda_mkdir,
.rmdir = coda_rmdir,
- .mknod = coda_mknod,
+ .mknod = CODA_EIO_ERROR,
.rename = coda_rename,
.permission = coda_permission,
.getattr = coda_getattr,
@@ -208,7 +212,7 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode, struct na
}
error = venus_create(dir->i_sb, coda_i2f(dir), name, length,
- 0, mode, 0, &newfid, &attrs);
+ 0, mode, &newfid, &attrs);
if ( error ) {
unlock_kernel();
@@ -230,52 +234,6 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode, struct na
return 0;
}
-static int coda_mknod(struct inode *dir, struct dentry *de, int mode, dev_t rdev)
-{
- int error=0;
- const char *name=de->d_name.name;
- int length=de->d_name.len;
- struct inode *inode;
- struct CodaFid newfid;
- struct coda_vattr attrs;
-
- if ( coda_hasmknod == 0 )
- return -EIO;
-
- if (!old_valid_dev(rdev))
- return -EINVAL;
-
- lock_kernel();
- coda_vfs_stat.create++;
-
- if (coda_isroot(dir) && coda_iscontrol(name, length)) {
- unlock_kernel();
- return -EPERM;
- }
-
- error = venus_create(dir->i_sb, coda_i2f(dir), name, length,
- 0, mode, rdev, &newfid, &attrs);
-
- if ( error ) {
- unlock_kernel();
- d_drop(de);
- return error;
- }
-
- inode = coda_iget(dir->i_sb, &newfid, &attrs);
- if ( IS_ERR(inode) ) {
- unlock_kernel();
- d_drop(de);
- return PTR_ERR(inode);
- }
-
- /* invalidate the directory cnode's attributes */
- coda_dir_changed(dir, 0);
- unlock_kernel();
- d_instantiate(de, inode);
- return 0;
-}
-
static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
{
struct inode *inode;
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 960bda823d58..e6bc022568f3 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -26,7 +26,7 @@
/* if CODA_STORE fails with EOPNOTSUPP, venus clearly doesn't support
* CODA_STORE/CODA_RELEASE and we fall back on using the CODA_CLOSE upcall */
-int use_coda_close;
+static int use_coda_close;
static ssize_t
coda_file_read(struct file *coda_file, char __user *buf, size_t count, loff_t *ppos)
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 6a891bfc01de..04a73fb4848f 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -89,7 +89,7 @@ static int coda_remount(struct super_block *sb, int *flags, char *data)
}
/* exported operations */
-struct super_operations coda_super_operations =
+static struct super_operations coda_super_operations =
{
.alloc_inode = coda_alloc_inode,
.destroy_inode = coda_destroy_inode,
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index f115e41d4cca..ef001a9313e6 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -309,8 +309,7 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
static int coda_psdev_release(struct inode * inode, struct file * file)
{
struct venus_comm *vcp = (struct venus_comm *) file->private_data;
- struct upc_req *req;
- struct list_head *lh, *next;
+ struct upc_req *req, *tmp;
lock_kernel();
if ( !vcp->vc_inuse ) {
@@ -325,8 +324,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
}
/* Wakeup clients so they can return. */
- list_for_each_safe(lh, next, &vcp->vc_pending) {
- req = list_entry(lh, struct upc_req, uc_chain);
+ list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) {
/* Async requests need to be freed here */
if (req->uc_flags & REQ_ASYNC) {
CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr));
@@ -360,13 +358,12 @@ static struct file_operations coda_psdev_fops = {
static int init_coda_psdev(void)
{
int i, err = 0;
- if (register_chrdev(CODA_PSDEV_MAJOR,"coda_psdev",
- &coda_psdev_fops)) {
+ if (register_chrdev(CODA_PSDEV_MAJOR, "coda", &coda_psdev_fops)) {
printk(KERN_ERR "coda_psdev: unable to get major %d\n",
CODA_PSDEV_MAJOR);
return -EIO;
}
- coda_psdev_class = class_simple_create(THIS_MODULE, "coda_psdev");
+ coda_psdev_class = class_simple_create(THIS_MODULE, "coda");
if (IS_ERR(coda_psdev_class)) {
err = PTR_ERR(coda_psdev_class);
goto out_chrdev;
@@ -388,7 +385,7 @@ out_class:
class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i));
class_simple_destroy(coda_psdev_class);
out_chrdev:
- unregister_chrdev(CODA_PSDEV_MAJOR, "coda_psdev");
+ unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
out:
return err;
}
@@ -433,7 +430,7 @@ out:
}
class_simple_destroy(coda_psdev_class);
devfs_remove("coda");
- unregister_chrdev(CODA_PSDEV_MAJOR,"coda_psdev");
+ unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
coda_sysctl_clean();
out1:
coda_destroy_inodecache();
@@ -455,7 +452,7 @@ static void __exit exit_coda(void)
}
class_simple_destroy(coda_psdev_class);
devfs_remove("coda");
- unregister_chrdev(CODA_PSDEV_MAJOR, "coda_psdev");
+ unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
coda_sysctl_clean();
coda_destroy_inodecache();
}
diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c
index 5b71f47e27dd..f0b10757288f 100644
--- a/fs/coda/sysctl.c
+++ b/fs/coda/sysctl.c
@@ -41,35 +41,22 @@ static struct ctl_table_header *fs_table_header;
#define CODA_CACHE_INV 9 /* cache invalidation statistics */
#define CODA_FAKE_STATFS 10 /* don't query venus for actual cache usage */
-static ctl_table coda_table[] = {
- {CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec},
- {CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec},
- {CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats},
- {CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats},
- {CODA_FAKE_STATFS, "fake_statfs", &coda_fake_statfs, sizeof(int), 0600, NULL, &proc_dointvec},
- { 0 }
-};
-
-static ctl_table fs_table[] = {
- {FS_CODA, "coda", NULL, 0, 0555, coda_table},
- {0}
-};
-
struct coda_vfs_stats coda_vfs_stat;
-struct coda_cache_inv_stats coda_cache_inv_stat;
+static struct coda_cache_inv_stats coda_cache_inv_stat;
-void reset_coda_vfs_stats( void )
+static void reset_coda_vfs_stats( void )
{
memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) );
}
-void reset_coda_cache_inv_stats( void )
+static void reset_coda_cache_inv_stats( void )
{
memset( &coda_cache_inv_stat, 0, sizeof( coda_cache_inv_stat ) );
}
-int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
- void __user * buffer, size_t * lenp, loff_t * ppos )
+static int do_reset_coda_vfs_stats( ctl_table * table, int write,
+ struct file * filp, void __user * buffer,
+ size_t * lenp, loff_t * ppos )
{
if ( write ) {
reset_coda_vfs_stats();
@@ -82,9 +69,10 @@ int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
return 0;
}
-int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
- struct file * filp, void __user * buffer,
- size_t * lenp, loff_t * ppos )
+static int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
+ struct file * filp,
+ void __user * buffer,
+ size_t * lenp, loff_t * ppos )
{
if ( write ) {
reset_coda_cache_inv_stats();
@@ -97,8 +85,8 @@ int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
return 0;
}
-int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
- int length)
+static int coda_vfs_stats_get_info( char * buffer, char ** start,
+ off_t offset, int length)
{
int len=0;
off_t begin;
@@ -158,8 +146,8 @@ int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
return len;
}
-int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
- int length)
+static int coda_cache_inv_stats_get_info( char * buffer, char ** start,
+ off_t offset, int length)
{
int len=0;
off_t begin;
@@ -196,6 +184,20 @@ int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
return len;
}
+static ctl_table coda_table[] = {
+ {CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec},
+ {CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec},
+ {CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats},
+ {CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats},
+ {CODA_FAKE_STATFS, "fake_statfs", &coda_fake_statfs, sizeof(int), 0600, NULL, &proc_dointvec},
+ { 0 }
+};
+
+static ctl_table fs_table[] = {
+ {FS_CODA, "coda", NULL, 0, 0555, coda_table},
+ {0}
+};
+
#ifdef CONFIG_PROC_FS
@@ -207,7 +209,7 @@ int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
*/
-struct proc_dir_entry* proc_fs_coda;
+static struct proc_dir_entry* proc_fs_coda;
#endif
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 569e144c661a..107dbfae7d13 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -331,7 +331,7 @@ int venus_rename(struct super_block *sb, struct CodaFid *old_fid,
}
int venus_create(struct super_block *sb, struct CodaFid *dirfid,
- const char *name, int length, int excl, int mode, dev_t rdev,
+ const char *name, int length, int excl, int mode,
struct CodaFid *newfid, struct coda_vattr *attrs)
{
union inputArgs *inp;
@@ -345,7 +345,6 @@ int venus_create(struct super_block *sb, struct CodaFid *dirfid,
inp->coda_create.VFid = *dirfid;
inp->coda_create.attr.va_mode = mode;
- inp->coda_create.attr.va_rdev = huge_encode_dev(rdev);
inp->coda_create.excl = excl;
inp->coda_create.mode = mode;
inp->coda_create.name = offset;
@@ -555,6 +554,11 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
goto exit;
}
+ if (data->vi.out_size > VC_MAXDATASIZE) {
+ error = -EINVAL;
+ goto exit;
+ }
+
inp->coda_ioctl.VFid = *fid;
/* the cmd field was mutated by increasing its size field to
@@ -583,19 +587,26 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
error, coda_f2s(fid));
goto exit;
}
+
+ if (outsize < (long)outp->coda_ioctl.data + outp->coda_ioctl.len) {
+ error = -EINVAL;
+ goto exit;
+ }
/* Copy out the OUT buffer. */
if (outp->coda_ioctl.len > data->vi.out_size) {
error = -EINVAL;
- } else {
- if (copy_to_user(data->vi.out,
- (char *)outp + (long)outp->coda_ioctl.data,
- data->vi.out_size)) {
- error = -EFAULT;
- goto exit;
- }
+ goto exit;
}
+ /* Copy out the OUT buffer. */
+ if (copy_to_user(data->vi.out,
+ (char *)outp + (long)outp->coda_ioctl.data,
+ outp->coda_ioctl.len)) {
+ error = -EFAULT;
+ goto exit;
+ }
+
exit:
CODA_FREE(inp, insize);
return error;
diff --git a/fs/direct-io.c b/fs/direct-io.c
index e370bb2b9da8..283268396a15 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -215,7 +215,7 @@ static void dio_complete(struct dio *dio, loff_t offset, ssize_t bytes)
{
if (dio->end_io && dio->result)
dio->end_io(dio->inode, offset, bytes, dio->map_bh.b_private);
- if (dio->lock_type != DIO_NO_LOCKING)
+ if (dio->lock_type == DIO_LOCKING)
up_read(&dio->inode->i_alloc_sem);
}
@@ -1201,8 +1201,8 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
* readers need to grab i_sem and i_alloc_sem
* writers need to grab i_alloc_sem only (i_sem is already held)
* For regular files using DIO_OWN_LOCKING,
- * readers need to grab i_alloc_sem only (i_sem is already held)
- * writers need to grab i_alloc_sem only
+ * neither readers nor writers take any locks here
+ * (i_sem is already held and release for writers here)
*/
dio->lock_type = dio_lock_type;
if (dio_lock_type != DIO_NO_LOCKING) {
@@ -1219,14 +1219,15 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
kfree(dio);
goto out;
}
- down_read(&inode->i_alloc_sem);
+
if (dio_lock_type == DIO_OWN_LOCKING) {
up(&inode->i_sem);
reader_with_isem = 0;
}
- } else {
- down_read(&inode->i_alloc_sem);
}
+
+ if (dio_lock_type == DIO_LOCKING)
+ down_read(&inode->i_alloc_sem);
}
/*
diff --git a/fs/dquot.c b/fs/dquot.c
index ce53e60bd227..8455855e751a 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -128,6 +128,9 @@ static char *quotatypes[] = INITQFNAMES;
static struct quota_format_type *quota_formats; /* List of registered formats */
static struct quota_module_name module_names[] = INIT_QUOTA_MODULE_NAMES;
+/* SLAB cache for dquot structures */
+static kmem_cache_t *dquot_cachep;
+
int register_quota_format(struct quota_format_type *fmt)
{
spin_lock(&dq_list_lock);
@@ -199,7 +202,7 @@ static void put_quota_format(struct quota_format_type *fmt)
static LIST_HEAD(inuse_list);
static LIST_HEAD(free_dquots);
-unsigned int dq_hash_bits, dq_hash_mask;
+static unsigned int dq_hash_bits, dq_hash_mask;
static struct hlist_head *dquot_hash;
struct dqstats dqstats;
@@ -1781,9 +1784,6 @@ static ctl_table sys_table[] = {
{ .ctl_name = 0 },
};
-/* SLAB cache for dquot structures */
-kmem_cache_t *dquot_cachep;
-
static int __init dquot_init(void)
{
int i;
diff --git a/fs/efs/super.c b/fs/efs/super.c
index af4d01e2730a..d8d5ea9a9997 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -32,6 +32,26 @@ static struct file_system_type efs_fs_type = {
.fs_flags = FS_REQUIRES_DEV,
};
+static struct pt_types sgi_pt_types[] = {
+ {0x00, "SGI vh"},
+ {0x01, "SGI trkrepl"},
+ {0x02, "SGI secrepl"},
+ {0x03, "SGI raw"},
+ {0x04, "SGI bsd"},
+ {SGI_SYSV, "SGI sysv"},
+ {0x06, "SGI vol"},
+ {SGI_EFS, "SGI efs"},
+ {0x08, "SGI lv"},
+ {0x09, "SGI rlv"},
+ {0x0A, "SGI xfs"},
+ {0x0B, "SGI xfslog"},
+ {0x0C, "SGI xlv"},
+ {0x82, "Linux swap"},
+ {0x83, "Linux native"},
+ {0, NULL}
+};
+
+
static kmem_cache_t * efs_inode_cachep;
static struct inode *efs_alloc_inode(struct super_block *sb)
diff --git a/fs/exec.c b/fs/exec.c
index c401dc74226e..ffe22877ca94 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -963,6 +963,7 @@ void compute_creds(struct linux_binprm *bprm)
unsafe = unsafe_exec(current);
security_bprm_apply_creds(bprm, unsafe);
task_unlock(current);
+ security_bprm_post_apply_creds(bprm);
}
EXPORT_SYMBOL(compute_creds);
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 457abba28519..e78fb7c65212 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -137,17 +137,6 @@ ext2_xattr_handler(int name_index)
}
/*
- * Inode operation listxattr()
- *
- * dentry->d_inode->i_sem: don't care
- */
-ssize_t
-ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
-{
- return ext2_xattr_list(dentry->d_inode, buffer, size);
-}
-
-/*
* ext2_xattr_get()
*
* Copy an extended attribute into the buffer
@@ -260,7 +249,7 @@ cleanup:
* Returns a negative error number on failure, or the number of bytes
* used / required on success.
*/
-int
+static int
ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
{
struct buffer_head *bh = NULL;
@@ -335,6 +324,17 @@ cleanup:
}
/*
+ * Inode operation listxattr()
+ *
+ * dentry->d_inode->i_sem: don't care
+ */
+ssize_t
+ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+ return ext2_xattr_list(dentry->d_inode, buffer, size);
+}
+
+/*
* If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
* not set, set it.
*/
diff --git a/fs/ext2/xattr.h b/fs/ext2/xattr.h
index 65ea5f9e723d..0b7ad429fe00 100644
--- a/fs/ext2/xattr.h
+++ b/fs/ext2/xattr.h
@@ -66,7 +66,6 @@ extern struct xattr_handler ext2_xattr_security_handler;
extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
-extern int ext2_xattr_list(struct inode *, char *, size_t);
extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
extern void ext2_xattr_delete_inode(struct inode *);
@@ -87,12 +86,6 @@ ext2_xattr_get(struct inode *inode, int name_index,
}
static inline int
-ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
-{
- return -EOPNOTSUPP;
-}
-
-static inline int
ext2_xattr_set(struct inode *inode, int name_index, const char *name,
const void *value, size_t size, int flags)
{
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 4631ae139bf7..3f1b811ef2ad 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -1451,7 +1451,7 @@ static inline int test_root(int a, int b)
}
}
-int ext3_group_sparse(int group)
+static int ext3_group_sparse(int group)
{
return (test_root(group, 3) || test_root(group, 5) ||
test_root(group, 7));
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index b2bb90817371..832867aef3dc 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -306,7 +306,7 @@ static void free_rb_tree_fname(struct rb_root *root)
}
-struct dir_private_info *create_dir_info(loff_t pos)
+static struct dir_private_info *create_dir_info(loff_t pos)
{
struct dir_private_info *p;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 1132ad886f5a..0a92408946a9 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -39,6 +39,8 @@
#include "xattr.h"
#include "acl.h"
+static int ext3_writepage_trans_blocks(struct inode *inode);
+
/*
* Test whether an inode is a fast symlink.
*/
@@ -2807,7 +2809,7 @@ err_out:
* block and work out the exact number of indirects which are touched. Pah.
*/
-int ext3_writepage_trans_blocks(struct inode *inode)
+static int ext3_writepage_trans_blocks(struct inode *inode)
{
int bpp = ext3_journal_blocks_per_page(inode);
int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c
index b2786fac330d..2c9f81278d5d 100644
--- a/fs/ext3/resize.c
+++ b/fs/ext3/resize.c
@@ -285,8 +285,8 @@ exit_journal:
* sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
* For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
*/
-unsigned ext3_list_backups(struct super_block *sb, unsigned *three,
- unsigned *five, unsigned *seven)
+static unsigned ext3_list_backups(struct super_block *sb, unsigned *three,
+ unsigned *five, unsigned *seven)
{
unsigned *min = three;
int mult = 3;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 9b654f7f29d7..d962d89e9ce1 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -50,6 +50,13 @@ static void ext3_mark_recovery_complete(struct super_block * sb,
static void ext3_clear_journal_err(struct super_block * sb,
struct ext3_super_block * es);
static int ext3_sync_fs(struct super_block *sb, int wait);
+static const char *ext3_decode_error(struct super_block * sb, int errno,
+ char nbuf[16]);
+static int ext3_remount (struct super_block * sb, int * flags, char * data);
+static int ext3_statfs (struct super_block * sb, struct kstatfs * buf);
+static void ext3_unlockfs(struct super_block *sb);
+static void ext3_write_super (struct super_block * sb);
+static void ext3_write_super_lockfs(struct super_block *sb);
/*
* Wrappers for journal_start/end.
@@ -178,7 +185,8 @@ void ext3_error (struct super_block * sb, const char * function,
ext3_handle_error(sb);
}
-const char *ext3_decode_error(struct super_block * sb, int errno, char nbuf[16])
+static const char *ext3_decode_error(struct super_block * sb, int errno,
+ char nbuf[16])
{
char *errstr = NULL;
@@ -261,29 +269,6 @@ void ext3_abort (struct super_block * sb, const char * function,
journal_abort(EXT3_SB(sb)->s_journal, -EIO);
}
-/* Deal with the reporting of failure conditions while running, such as
- * inconsistencies in operation or invalid system states.
- *
- * Use ext3_error() for cases of invalid filesystem states, as that will
- * record an error on disk and force a filesystem check on the next boot.
- */
-NORET_TYPE void ext3_panic (struct super_block * sb, const char * function,
- const char * fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- printk(KERN_CRIT "EXT3-fs error (device %s): %s: ",sb->s_id, function);
- vprintk(fmt, args);
- printk("\n");
- va_end(args);
-
- /* this is to prevent panic from syncing this filesystem */
- /* AKPM: is this sufficient? */
- sb->s_flags |= MS_RDONLY;
- panic ("EXT3-fs panic forced\n");
-}
-
void ext3_warning (struct super_block * sb, const char * function,
const char * fmt, ...)
{
@@ -386,7 +371,7 @@ static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi)
}
}
-void ext3_put_super (struct super_block * sb)
+static void ext3_put_super (struct super_block * sb)
{
struct ext3_sb_info *sbi = EXT3_SB(sb);
struct ext3_super_block *es = sbi->s_es;
@@ -2018,7 +2003,7 @@ int ext3_force_commit(struct super_block *sb)
* This implicitly triggers the writebehind on sync().
*/
-void ext3_write_super (struct super_block * sb)
+static void ext3_write_super (struct super_block * sb)
{
if (down_trylock(&sb->s_lock) == 0)
BUG();
@@ -2041,7 +2026,7 @@ static int ext3_sync_fs(struct super_block *sb, int wait)
* LVM calls this function before a (read-only) snapshot is created. This
* gives us a chance to flush the journal completely and mark the fs clean.
*/
-void ext3_write_super_lockfs(struct super_block *sb)
+static void ext3_write_super_lockfs(struct super_block *sb)
{
sb->s_dirt = 0;
@@ -2062,7 +2047,7 @@ void ext3_write_super_lockfs(struct super_block *sb)
* Called by LVM after the snapshot is done. We need to reset the RECOVER
* flag here, even though the filesystem is not technically dirty yet.
*/
-void ext3_unlockfs(struct super_block *sb)
+static void ext3_unlockfs(struct super_block *sb)
{
if (!(sb->s_flags & MS_RDONLY)) {
lock_super(sb);
@@ -2074,7 +2059,7 @@ void ext3_unlockfs(struct super_block *sb)
}
}
-int ext3_remount (struct super_block * sb, int * flags, char * data)
+static int ext3_remount (struct super_block * sb, int * flags, char * data)
{
struct ext3_super_block * es;
struct ext3_sb_info *sbi = EXT3_SB(sb);
@@ -2146,7 +2131,7 @@ int ext3_remount (struct super_block * sb, int * flags, char * data)
return 0;
}
-int ext3_statfs (struct super_block * sb, struct kstatfs * buf)
+static int ext3_statfs (struct super_block * sb, struct kstatfs * buf)
{
struct ext3_super_block *es = EXT3_SB(sb)->s_es;
unsigned long overhead;
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 935778cc834f..31ef0eef09a3 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -139,22 +139,11 @@ ext3_xattr_handler(int name_index)
}
/*
- * Inode operation listxattr()
- *
- * dentry->d_inode->i_sem: don't care
- */
-ssize_t
-ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
-{
- return ext3_xattr_list(dentry->d_inode, buffer, size);
-}
-
-/*
* ext3_xattr_block_get()
*
* routine looks for attribute in EA block and returns it's value and size
*/
-int
+static int
ext3_xattr_block_get(struct inode *inode, int name_index, const char *name,
void *buffer, size_t buffer_size)
{
@@ -250,7 +239,7 @@ cleanup:
*
* routine looks for attribute in inode body and returns it's value and size
*/
-int
+static int
ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
void *buffer, size_t buffer_size)
{
@@ -352,7 +341,7 @@ ext3_xattr_get(struct inode *inode, int name_index, const char *name,
*
* generate list of attributes stored in EA block
*/
-int
+static int
ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
{
struct buffer_head *bh = NULL;
@@ -428,7 +417,7 @@ cleanup:
*
* generate list of attributes stored in inode body
*/
-int
+static int
ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
{
struct ext3_xattr_entry *last;
@@ -507,7 +496,7 @@ cleanup:
* Returns a negative error number on failure, or the number of bytes
* used / required on success.
*/
-int
+static int
ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
{
int size = buffer_size;
@@ -546,6 +535,17 @@ cleanup:
}
/*
+ * Inode operation listxattr()
+ *
+ * dentry->d_inode->i_sem: don't care
+ */
+ssize_t
+ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+ return ext3_xattr_list(dentry->d_inode, buffer, size);
+}
+
+/*
* If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
* not set, set it.
*/
@@ -571,7 +571,7 @@ static void ext3_xattr_update_super_block(handle_t *handle,
* search attribute and calculate free space in inode body
* NOTE: free space includes space our attribute hold
*/
-int
+static int
ext3_xattr_ibody_find(struct inode *inode, int name_index,
const char *name, int *free)
{
@@ -638,7 +638,7 @@ ext3_xattr_ibody_find(struct inode *inode, int name_index,
* search attribute and calculate free space in EA block (if it allocated)
* NOTE: free space includes space our attribute hold
*/
-int
+static int
ext3_xattr_block_find(struct inode *inode, int name_index,
const char *name, int *free)
{
@@ -698,7 +698,7 @@ bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
*
* this routine add/remove/replace attribute in inode body
*/
-int
+static int
ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index,
const char *name, const void *value, size_t value_len,
int flags)
@@ -846,112 +846,11 @@ done:
}
/*
- * ext3_xattr_set_handle()
- *
- * Create, replace or remove an extended attribute for this inode. Buffer
- * is NULL to remove an existing extended attribute, and non-NULL to
- * either replace an existing extended attribute, or create a new extended
- * attribute. The flags XATTR_REPLACE and XATTR_CREATE
- * specify that an extended attribute must exist and must not exist
- * previous to the call, respectively.
- *
- * Returns 0, or a negative error number on failure.
- */
-int
-ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
- const char *name, const void *value, size_t value_len,
- int flags)
-{
- int free1 = -1, free2 = -1;
- int err, where = 0, total;
- int name_len;
-
- ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
- name_index, name, value, (long)value_len);
-
- if (IS_RDONLY(inode))
- return -EROFS;
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- return -EPERM;
- if (value == NULL)
- value_len = 0;
- if (name == NULL)
- return -EINVAL;
- name_len = strlen(name);
- if (name_len > 255 || value_len > inode->i_sb->s_blocksize)
- return -ERANGE;
- down_write(&EXT3_I(inode)->xattr_sem);
-
-#define EX_FOUND_IN_IBODY 1
-#define EX_FOUND_IN_BLOCK 2
-
- /* try to find attribute in inode body */
- err = ext3_xattr_ibody_find(inode, name_index, name, &free1);
- if (err == 0) {
- /* found EA in inode */
- where = EX_FOUND_IN_IBODY;
- } else if (err == -ENOENT) {
- /* there is no such attribute in inode body */
- /* try to find attribute in dedicated block */
- err = ext3_xattr_block_find(inode, name_index, name, &free2);
- if (err != 0 && err != -ENOENT) {
- /* not found EA in block */
- goto finish;
- } else if (err == 0) {
- /* found EA in block */
- where = EX_FOUND_IN_BLOCK;
- }
- } else
- goto finish;
-
- /* check flags: may replace? may create ? */
- if (where && (flags & XATTR_CREATE)) {
- err = -EEXIST;
- goto finish;
- } else if (!where && (flags & XATTR_REPLACE)) {
- err = -ENODATA;
- goto finish;
- }
-
- /* check if we have enough space to store attribute */
- total = EXT3_XATTR_LEN(strlen(name)) + value_len;
- if (total > free1 && free2 > 0 && total > free2) {
- /* have no enough space */
- err = -ENOSPC;
- goto finish;
- }
-
- /* there are two cases when we want to remove EA from original storage:
- * a) EA is stored in the inode, but new value doesn't fit
- * b) EA is stored in the block, but new value fit in inode
- */
- if (where == EX_FOUND_IN_IBODY && total > free1)
- ext3_xattr_ibody_set(handle, inode, name_index, name,
- NULL, 0, flags);
- else if (where == EX_FOUND_IN_BLOCK && total <= free1)
- ext3_xattr_block_set(handle, inode, name_index,
- name, NULL, 0, flags);
-
- /* try to store EA in inode body */
- err = ext3_xattr_ibody_set(handle, inode, name_index, name,
- value, value_len, flags);
- if (err) {
- /* can't store EA in inode body: try to store in block */
- err = ext3_xattr_block_set(handle, inode, name_index, name,
- value, value_len, flags);
- }
-
-finish:
- up_write(&EXT3_I(inode)->xattr_sem);
- return err;
-}
-
-/*
* ext3_xattr_block_set()
*
* this routine add/remove/replace attribute in EA block
*/
-int
+static int
ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index,
const char *name, const void *value, size_t value_len,
int flags)
@@ -1206,6 +1105,107 @@ cleanup:
}
/*
+ * ext3_xattr_set_handle()
+ *
+ * Create, replace or remove an extended attribute for this inode. Buffer
+ * is NULL to remove an existing extended attribute, and non-NULL to
+ * either replace an existing extended attribute, or create a new extended
+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE
+ * specify that an extended attribute must exist and must not exist
+ * previous to the call, respectively.
+ *
+ * Returns 0, or a negative error number on failure.
+ */
+int
+ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
+ const char *name, const void *value, size_t value_len,
+ int flags)
+{
+ int free1 = -1, free2 = -1;
+ int err, where = 0, total;
+ int name_len;
+
+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
+ name_index, name, value, (long)value_len);
+
+ if (IS_RDONLY(inode))
+ return -EROFS;
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ return -EPERM;
+ if (value == NULL)
+ value_len = 0;
+ if (name == NULL)
+ return -EINVAL;
+ name_len = strlen(name);
+ if (name_len > 255 || value_len > inode->i_sb->s_blocksize)
+ return -ERANGE;
+ down_write(&EXT3_I(inode)->xattr_sem);
+
+#define EX_FOUND_IN_IBODY 1
+#define EX_FOUND_IN_BLOCK 2
+
+ /* try to find attribute in inode body */
+ err = ext3_xattr_ibody_find(inode, name_index, name, &free1);
+ if (err == 0) {
+ /* found EA in inode */
+ where = EX_FOUND_IN_IBODY;
+ } else if (err == -ENOENT) {
+ /* there is no such attribute in inode body */
+ /* try to find attribute in dedicated block */
+ err = ext3_xattr_block_find(inode, name_index, name, &free2);
+ if (err != 0 && err != -ENOENT) {
+ /* not found EA in block */
+ goto finish;
+ } else if (err == 0) {
+ /* found EA in block */
+ where = EX_FOUND_IN_BLOCK;
+ }
+ } else
+ goto finish;
+
+ /* check flags: may replace? may create ? */
+ if (where && (flags & XATTR_CREATE)) {
+ err = -EEXIST;
+ goto finish;
+ } else if (!where && (flags & XATTR_REPLACE)) {
+ err = -ENODATA;
+ goto finish;
+ }
+
+ /* check if we have enough space to store attribute */
+ total = EXT3_XATTR_LEN(strlen(name)) + value_len;
+ if (total > free1 && free2 > 0 && total > free2) {
+ /* have no enough space */
+ err = -ENOSPC;
+ goto finish;
+ }
+
+ /* there are two cases when we want to remove EA from original storage:
+ * a) EA is stored in the inode, but new value doesn't fit
+ * b) EA is stored in the block, but new value fit in inode
+ */
+ if (where == EX_FOUND_IN_IBODY && total > free1)
+ ext3_xattr_ibody_set(handle, inode, name_index, name,
+ NULL, 0, flags);
+ else if (where == EX_FOUND_IN_BLOCK && total <= free1)
+ ext3_xattr_block_set(handle, inode, name_index,
+ name, NULL, 0, flags);
+
+ /* try to store EA in inode body */
+ err = ext3_xattr_ibody_set(handle, inode, name_index, name,
+ value, value_len, flags);
+ if (err) {
+ /* can't store EA in inode body: try to store in block */
+ err = ext3_xattr_block_set(handle, inode, name_index, name,
+ value, value_len, flags);
+ }
+
+finish:
+ up_write(&EXT3_I(inode)->xattr_sem);
+ return err;
+}
+
+/*
* Second half of ext3_xattr_set_handle(): Update the file system.
*/
static int
diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h
index b677cf7ac568..b2b25ad82451 100644
--- a/fs/ext3/xattr.h
+++ b/fs/ext3/xattr.h
@@ -65,10 +65,8 @@ extern struct xattr_handler ext3_xattr_security_handler;
extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
-extern int ext3_xattr_list(struct inode *, char *, size_t);
extern int ext3_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *,const void *,size_t,int);
-extern int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *,const void *,size_t,int);
extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
extern void ext3_xattr_put_super(struct super_block *);
@@ -88,12 +86,6 @@ ext3_xattr_get(struct inode *inode, int name_index, const char *name,
}
static inline int
-ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
-{
- return -EOPNOTSUPP;
-}
-
-static inline int
ext3_xattr_set(struct inode *inode, int name_index, const char *name,
const void *value, size_t size, int flags)
{
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 26f234a0da93..6d0e70efd399 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -558,22 +558,24 @@ void sync_inodes(int wait)
* dirty. This is primarily needed by knfsd.
*/
-void write_inode_now(struct inode *inode, int sync)
+int write_inode_now(struct inode *inode, int sync)
{
+ int ret;
struct writeback_control wbc = {
.nr_to_write = LONG_MAX,
.sync_mode = WB_SYNC_ALL,
};
if (inode->i_mapping->backing_dev_info->memory_backed)
- return;
+ return 0;
might_sleep();
spin_lock(&inode_lock);
- __writeback_single_inode(inode, &wbc);
+ ret = __writeback_single_inode(inode, &wbc);
spin_unlock(&inode_lock);
if (sync)
wait_on_inode(inode);
+ return ret;
}
EXPORT_SYMBOL(write_inode_now);
@@ -642,8 +644,11 @@ int generic_osync_inode(struct inode *inode, struct address_space *mapping, int
need_write_inode_now = 1;
spin_unlock(&inode_lock);
- if (need_write_inode_now)
- write_inode_now(inode, 1);
+ if (need_write_inode_now) {
+ err2 = write_inode_now(inode, 1);
+ if (!err)
+ err = err2;
+ }
else
wait_on_inode(inode);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 05175eced239..03019e040d0b 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -168,7 +168,7 @@ static int hugetlbfs_commit_write(struct file *file,
return -EINVAL;
}
-void huge_pagevec_release(struct pagevec *pvec)
+static void huge_pagevec_release(struct pagevec *pvec)
{
int i;
@@ -178,7 +178,7 @@ void huge_pagevec_release(struct pagevec *pvec)
pagevec_reinit(pvec);
}
-void truncate_huge_page(struct page *page)
+static void truncate_huge_page(struct page *page)
{
clear_page_dirty(page);
ClearPageUptodate(page);
@@ -186,7 +186,7 @@ void truncate_huge_page(struct page *page)
put_page(page);
}
-void truncate_hugepages(struct address_space *mapping, loff_t lstart)
+static void truncate_hugepages(struct address_space *mapping, loff_t lstart)
{
const pgoff_t start = lstart >> HPAGE_SHIFT;
struct pagevec pvec;
@@ -495,7 +495,7 @@ static int hugetlbfs_symlink(struct inode *dir,
/*
* For direct-IO reads into hugetlb pages
*/
-int hugetlbfs_set_page_dirty(struct page *page)
+static int hugetlbfs_set_page_dirty(struct page *page)
{
return 0;
}
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c
index 0b5a3a0ed767..fb42c3f3bf0d 100644
--- a/fs/isofs/compress.c
+++ b/fs/isofs/compress.c
@@ -28,7 +28,6 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/errno.h>
-#include <linux/cdrom.h>
#include <linux/init.h>
#include <linux/nls.h>
#include <linux/ctype.h>
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index c5c9983e3a60..aa5f22435d0c 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -337,6 +337,9 @@ write_out_data:
}
spin_unlock(&journal->j_list_lock);
+ if (err)
+ __journal_abort_hard(journal);
+
journal_write_revoke_records(journal, commit_transaction);
jbd_debug(3, "JBD: commit phase 2\n");
diff --git a/fs/libfs.c b/fs/libfs.c
index 275e4b7e392b..141533232c62 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -524,6 +524,7 @@ EXPORT_SYMBOL(dcache_dir_lseek);
EXPORT_SYMBOL(dcache_dir_open);
EXPORT_SYMBOL(dcache_readdir);
EXPORT_SYMBOL(generic_read_dir);
+EXPORT_SYMBOL(get_sb_pseudo);
EXPORT_SYMBOL(simple_commit_write);
EXPORT_SYMBOL(simple_dir_inode_operations);
EXPORT_SYMBOL(simple_dir_operations);
diff --git a/fs/open.c b/fs/open.c
index 95266c0bafb5..03a7fbc84769 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -203,10 +203,9 @@ int do_truncate(struct dentry *dentry, loff_t length)
newattrs.ia_size = length;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
+
down(&dentry->d_inode->i_sem);
- down_write(&dentry->d_inode->i_alloc_sem);
err = notify_change(dentry, &newattrs);
- up_write(&dentry->d_inode->i_alloc_sem);
up(&dentry->d_inode->i_sem);
return err;
}
diff --git a/fs/proc/array.c b/fs/proc/array.c
index e4bd14aa005d..eb5c084ede4a 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -313,8 +313,9 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
int num_threads = 0;
struct mm_struct *mm;
unsigned long long start_time;
- unsigned long cmin_flt = 0, cmaj_flt = 0, cutime = 0, cstime = 0;
- unsigned long min_flt = 0, maj_flt = 0, utime = 0, stime = 0;
+ unsigned long cmin_flt = 0, cmaj_flt = 0;
+ unsigned long min_flt = 0, maj_flt = 0;
+ cputime_t cutime, cstime, utime, stime;
unsigned long rsslim = 0;
struct task_struct *t;
char tcomm[sizeof(task->comm)];
@@ -332,6 +333,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
sigemptyset(&sigign);
sigemptyset(&sigcatch);
+ cutime = cstime = utime = stime = cputime_zero;
read_lock(&tasklist_lock);
if (task->sighand) {
spin_lock_irq(&task->sighand->siglock);
@@ -344,8 +346,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
do {
min_flt += t->min_flt;
maj_flt += t->maj_flt;
- utime += t->utime;
- stime += t->stime;
+ utime = cputime_add(utime, t->utime);
+ stime = cputime_add(stime, t->stime);
t = next_thread(t);
} while (t != task);
}
@@ -367,8 +369,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
if (whole) {
min_flt += task->signal->min_flt;
maj_flt += task->signal->maj_flt;
- utime += task->signal->utime;
- stime += task->signal->stime;
+ utime = cputime_add(utime, task->signal->utime);
+ stime = cputime_add(stime, task->signal->stime);
}
}
ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0;
@@ -411,10 +413,10 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
cmin_flt,
maj_flt,
cmaj_flt,
- jiffies_to_clock_t(utime),
- jiffies_to_clock_t(stime),
- jiffies_to_clock_t(cutime),
- jiffies_to_clock_t(cstime),
+ cputime_to_clock_t(utime),
+ cputime_to_clock_t(stime),
+ cputime_to_clock_t(cutime),
+ cputime_to_clock_t(cstime),
priority,
nice,
num_threads,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index d3488902459b..f198e17edc83 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -360,7 +360,7 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer)
char *modname;
const char *sym_name;
unsigned long wchan, size, offset;
- char namebuf[128];
+ char namebuf[KSYM_NAME_LEN+1];
wchan = get_wchan(task);
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 5cc4361de09a..0a71cf365ed8 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -264,8 +264,7 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
unsigned long start;
read_lock(&kclist_lock);
- tsz = get_kcore_size(&nphdr, &elf_buflen);
- proc_root_kcore->size = size = tsz + elf_buflen;
+ proc_root_kcore->size = size = get_kcore_size(&nphdr, &elf_buflen);
if (buflen == 0 || *fpos >= size) {
read_unlock(&kclist_lock);
return 0;
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index c7322cfefe13..89d09007df5d 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -101,10 +101,10 @@ static int uptime_read_proc(char *page, char **start, off_t off,
struct timespec uptime;
struct timespec idle;
int len;
- u64 idle_jiffies = init_task.utime + init_task.stime;
+ cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
do_posix_clock_monotonic_gettime(&uptime);
- jiffies_to_timespec(idle_jiffies, &idle);
+ cputime_to_timespec(idletime, &idle);
len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
(unsigned long) uptime.tv_sec,
(uptime.tv_nsec / (NSEC_PER_SEC / 100)),
@@ -322,9 +322,11 @@ static int show_stat(struct seq_file *p, void *v)
{
int i;
unsigned long jif;
- u64 sum = 0, user = 0, nice = 0, system = 0,
- idle = 0, iowait = 0, irq = 0, softirq = 0;
+ cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
+ u64 sum = 0;
+ user = nice = system = idle = iowait =
+ irq = softirq = steal = cputime64_zero;
jif = - wall_to_monotonic.tv_sec;
if (wall_to_monotonic.tv_nsec)
--jif;
@@ -332,25 +334,27 @@ static int show_stat(struct seq_file *p, void *v)
for_each_cpu(i) {
int j;
- user += kstat_cpu(i).cpustat.user;
- nice += kstat_cpu(i).cpustat.nice;
- system += kstat_cpu(i).cpustat.system;
- idle += kstat_cpu(i).cpustat.idle;
- iowait += kstat_cpu(i).cpustat.iowait;
- irq += kstat_cpu(i).cpustat.irq;
- softirq += kstat_cpu(i).cpustat.softirq;
+ user = cputime64_add(user, kstat_cpu(i).cpustat.user);
+ nice = cputime64_add(nice, kstat_cpu(i).cpustat.nice);
+ system = cputime64_add(system, kstat_cpu(i).cpustat.system);
+ idle = cputime64_add(idle, kstat_cpu(i).cpustat.idle);
+ iowait = cputime64_add(iowait, kstat_cpu(i).cpustat.iowait);
+ irq = cputime64_add(irq, kstat_cpu(i).cpustat.irq);
+ softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
+ steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
for (j = 0 ; j < NR_IRQS ; j++)
sum += kstat_cpu(i).irqs[j];
}
- seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu\n",
- (unsigned long long)jiffies_64_to_clock_t(user),
- (unsigned long long)jiffies_64_to_clock_t(nice),
- (unsigned long long)jiffies_64_to_clock_t(system),
- (unsigned long long)jiffies_64_to_clock_t(idle),
- (unsigned long long)jiffies_64_to_clock_t(iowait),
- (unsigned long long)jiffies_64_to_clock_t(irq),
- (unsigned long long)jiffies_64_to_clock_t(softirq));
+ seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu %llu\n",
+ (unsigned long long)cputime64_to_clock_t(user),
+ (unsigned long long)cputime64_to_clock_t(nice),
+ (unsigned long long)cputime64_to_clock_t(system),
+ (unsigned long long)cputime64_to_clock_t(idle),
+ (unsigned long long)cputime64_to_clock_t(iowait),
+ (unsigned long long)cputime64_to_clock_t(irq),
+ (unsigned long long)cputime64_to_clock_t(softirq),
+ (unsigned long long)cputime64_to_clock_t(steal));
for_each_online_cpu(i) {
/* Copy values here to work around gcc-2.95.3, gcc-2.96 */
@@ -361,15 +365,17 @@ static int show_stat(struct seq_file *p, void *v)
iowait = kstat_cpu(i).cpustat.iowait;
irq = kstat_cpu(i).cpustat.irq;
softirq = kstat_cpu(i).cpustat.softirq;
- seq_printf(p, "cpu%d %llu %llu %llu %llu %llu %llu %llu\n",
+ steal = kstat_cpu(i).cpustat.steal;
+ seq_printf(p, "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu\n",
i,
- (unsigned long long)jiffies_64_to_clock_t(user),
- (unsigned long long)jiffies_64_to_clock_t(nice),
- (unsigned long long)jiffies_64_to_clock_t(system),
- (unsigned long long)jiffies_64_to_clock_t(idle),
- (unsigned long long)jiffies_64_to_clock_t(iowait),
- (unsigned long long)jiffies_64_to_clock_t(irq),
- (unsigned long long)jiffies_64_to_clock_t(softirq));
+ (unsigned long long)cputime64_to_clock_t(user),
+ (unsigned long long)cputime64_to_clock_t(nice),
+ (unsigned long long)cputime64_to_clock_t(system),
+ (unsigned long long)cputime64_to_clock_t(idle),
+ (unsigned long long)cputime64_to_clock_t(iowait),
+ (unsigned long long)cputime64_to_clock_t(irq),
+ (unsigned long long)cputime64_to_clock_t(softirq),
+ (unsigned long long)cputime64_to_clock_t(steal));
}
seq_printf(p, "intr %llu", (unsigned long long)sum);
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index e4e2f6b5e9c1..15c4455b09eb 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -32,10 +32,8 @@ static void show_tty_range(struct seq_file *m, struct tty_driver *p,
seq_printf(m, "%-20s ", p->driver_name ? p->driver_name : "unknown");
seq_printf(m, "/dev/%-8s ", p->name);
if (p->num > 1) {
- char range[20];
- sprintf(range, "%d-%d", MINOR(from),
+ seq_printf(m, "%3d %d-%d ", MAJOR(from), MINOR(from),
MINOR(from) + num - 1);
- seq_printf(m, "%3d %7s ", MAJOR(from), range);
} else {
seq_printf(m, "%3d %7d ", MAJOR(from), MINOR(from));
}
diff --git a/fs/quota.c b/fs/quota.c
index e69e8d1ada84..d59ccf2358b5 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -136,7 +136,7 @@ restart:
return NULL;
}
-void quota_sync_sb(struct super_block *sb, int type)
+static void quota_sync_sb(struct super_block *sb, int type)
{
int cnt;
struct inode *discard[MAXQUOTAS];
diff --git a/fs/quota_v2.c b/fs/quota_v2.c
index d80480712e6c..19bdb7b86ca7 100644
--- a/fs/quota_v2.c
+++ b/fs/quota_v2.c
@@ -396,7 +396,7 @@ static int v2_write_dquot(struct dquot *dquot)
/* dq_off is guarded by dqio_sem */
if (!dquot->dq_off)
if ((ret = dq_insert_tree(dquot)) < 0) {
- printk(KERN_ERR "VFS: Error %d occurred while creating quota.\n", ret);
+ printk(KERN_ERR "VFS: Error %zd occurred while creating quota.\n", ret);
return ret;
}
spin_lock(&dq_data_lock);
diff --git a/fs/readdir.c b/fs/readdir.c
index b95ded581471..b03579bc0210 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -287,9 +287,10 @@ asmlinkage long sys_getdents64(unsigned int fd, struct linux_dirent64 __user * d
lastdirent = buf.previous;
if (lastdirent) {
typeof(lastdirent->d_off) d_off = file->f_pos;
- error = count - buf.count;
+ error = -EFAULT;
if (__put_user(d_off, &lastdirent->d_off))
- error = -EFAULT;
+ goto out_putf;
+ error = count - buf.count;
}
out_putf:
diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c
index 1bffb65798b7..e4f64be9e15b 100644
--- a/fs/reiserfs/fix_node.c
+++ b/fs/reiserfs/fix_node.c
@@ -510,9 +510,10 @@ static int get_num_ver (int mode, struct tree_balance * tb, int h,
// s2bytes
snum012[4] = op_unit_num (&vn->vn_vi[split_item_num]) - snum012[4] - bytes_to_r - bytes_to_l - bytes_to_S1new;
- if (vn->vn_vi[split_item_num].vi_index != TYPE_DIRENTRY)
+ if (vn->vn_vi[split_item_num].vi_index != TYPE_DIRENTRY &&
+ vn->vn_vi[split_item_num].vi_index != TYPE_INDIRECT)
reiserfs_warning (tb->tb_sb, "vs-8115: get_num_ver: not "
- "directory item");
+ "directory or indirect item");
}
/* now we know S2bytes, calculate S1bytes */
diff --git a/fs/smbfs/ChangeLog b/fs/smbfs/ChangeLog
deleted file mode 100644
index f1ceadace589..000000000000
--- a/fs/smbfs/ChangeLog
+++ /dev/null
@@ -1,160 +0,0 @@
-ChangeLog for smbfs.
-
-2002-04-19 John Newbigin <jn@it.swin.edu.au>
-
- * Implementation of CIFS Extensions for UNIX systems, including soft
- and hard links.
-
-2001-08-03 Urban Widmark <urban@teststation.com>
-
- * *.c: Unicode support
-
-2001-08-23 Jochen Dolze <dolze@epcnet.de>
-
- * proc.c: Correct rsize/wsize computation for readX/writeX
-
-2001-0?-?? Urban Widmark <urban@teststation.com>
-
- * *.c: Add LFS
- * *.c: Move to a "driver" style handling of different servertypes.
- (Not all operations are done this way. yet.)
-2001-12-31 René Scharfe <l.s.r@web.de>
-
- * inode.c: added smb_show_options to show mount options in /proc/mounts
- * inode.c, getopt.c, getopt.h: merged flag and has_arg in struct option
- * inode.c: use S_IRWXUGO where appropriate
-
-2001-12-22 Urban Widmark <urban@teststation.com>
-
- * file.c, proc.c: Fix problems triggered by the "fsx test"
-
-2001-09-17 Urban Widmark <urban@teststation.com>
-
- * proc.c: Use 4096 (was 512) as the blocksize for better write
- performance (patch originally by Jan Kratochvil)
- * proc.c: Skip disconnect smb, allows umount on unreachable servers.
- * proc.c: Go back to the interruptible sleep as reconnects seem to
- handle it now.
- * *.c: use autogenerated and private proto.h
-
-2000-11-22 Igor Zhbanov <bsg@uniyar.ac.ru>
-
- * proc.c: fixed date_unix2dos for dates earlier than 01/01/1980
- and date_dos2unix for date==0 (from 2.2)
-
-2001-07-13 Rob Radez <rob@osinvestor.com>
-
- * proc.c: make smb_errno return negative error values
-
-2001-07-09 Jochen Dolze <dolze@epcnet.de>
-
- * inode.c: smb_statfs always returned success.
- * proc.c, ioctl.c: Allow smbmount to signal failure to reconnect with
- a NULL argument to SMB_IOC_NEWCONN (speeds up error detection).
- * proc.c: Add some of the missing error codes to smb_errno
-
-2001-06-12 Urban Widmark <urban@teststation.com>
-
- * proc.c: replace the win95-flush fix with smb_seek, when needed.
- * proc.c: readdir 'lastname' bug (NetApp dir listing fix)
-
-2001-05-08 Urban Widmark <urban@teststation.com>
-
- * inode.c: Fix for changes on the server side not being detected
- properly. Must always drop cached pages when updating an inode with
- new size.
-
-2001-05-05 Urban Widmark <urban@teststation.com>
-
- * file.c, proc.c: Drop SMB_F_LOCALWRITE to detect changes made on
- both server and client, using flush with to force win9x to remember
- the right filesize.
-
-2001-04-25 René Scharfe <l.s.r@web.de>
-
- * inode.c: Don't clear s_flags and allow ro mounts
-
-2001-04-21 Urban Widmark <urban@teststation.com>
-
- * dir.c, proc.c: replace tests on conn_pid with tests on state to
- fix smbmount reconnect on smb_retry timeout and up the timeout to 30s.
- * proc.c: smb_newconn must have the server locked while updating it.
- * inode.c, proc.c: need flush after truncate on some servers (win9x)
- * file.c: add call to send SMBflush on fsync
- (as suggested by Jochen Dolze <dolze@epcnet.de>)
-
-2001-03-06 Urban Widmark <urban@teststation.com>
-
- * cache.c: d_add on hashed dentries corrupts d_hash list and
- causes loops in d_lookup. Inherited bug. :)
- * inode.c: tail -f fix for non-readonly opened files
- (related to the smb_proc_open change).
- * inode.c: tail -f fix for fast size changes with the same mtime.
-
-2001-03-02 Michael Kockelkorn <m.kockelkorn@biodata.com>
-
- * proc.c: fix smb_proc_open to allow open being called more than once
- with different modes (O_RDONLY -> O_WRONLY) without closing.
-
-2001-02-10 Urban Widmark <urban@teststation.com>
-
- * dir.c, cache.c: replace non-bigmem safe cache with cache code
- from ncpfs and fix some other bigmem bugs in smbfs.
- * inode.c: root dentry not properly initialized
- * proc.c, sock.c: adjust max parameters & max data to follow max_xmit
- lots of servers were having find_next trouble with this.
- * proc.c: use documented write method of truncating (NetApp fix)
-
-2000-08-14 Urban Widmark <urban@svenskatest.se>
-
- * dir.c: support case sensitive shares
- * inode.c: ascii mount options
- * proc.c: check length of paths to avoid buffer overflow
- * proc.c: don't do interruptable_sleep in smb_retry to avoid signal
- problem/race.
- * proc.c: O_RDONLY & smb_revalidate_inode fix (tail -f)
- * proc.c: add nls support
- * sock.c: attempt to fix smb_data_callback (avoid infinite loop)
-
-2000-07-25 Urban Widmark <urban@svenskatest.se>
-
- * proc.c: fix 3 places where bad server responses could cause an Oops.
-
-2000-07-15 Urban Widmark <urban@svenskatest.se>
-
- * *.c: more debug (%.*s) & indent fixes
-
-2000-06-24: Matt Maynard <matthewm@corel.com>
-
- * dir.c: dentry->d_inode->i_mtime isn't updated for all servers
- (NT?) and all operations (mv oldfile.txt newfile.txt) Removed for
- less efficient but better working directory cache.
- * proc.c: included aDIR smbclient fix for renaming directories on
- OS/2 servers (win95/98?) (orig by John Janosik)
-
-2000-07-01 Urban Widmark <urban@svenskatest.se>
-
- * *.c: replace ugly #ifdef's with less ugly debug macros.
-
-2000-01-03 Christian Groessler <cpg@aladdin.de>
-
- * proc.c: added posix semantics for unlink
-
-1999-11-16 Andrew Tridgell
-
- * proc.c: use level 260 for most conns, or level 1 for <NT1
- * proc.c: don't sleep every time with win95 on a FINDNEXT
- * proc.c: fixed loop_count bug
- * proc.c: got rid of resume_key
-
-[there are a few missing here :) ]
-
-1997-09-28 Riccardo Facchetti
-
- * proc.c: Fixed smb_d_path [now smb_build_path()] to be non-recursive
-
-1996-06-28 Yuri Per
-
- * proc.c: Fixed long file name support (smb_proc_readdir_long)
-
-You are in the wrong end for adding new entries. New entries at the top.
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index e4680598c3c1..4765aaac9fd2 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -493,7 +493,7 @@ smb_put_super(struct super_block *sb)
smb_kfree(server);
}
-int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
+static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
{
struct smb_sb_info *server;
struct smb_mount_data_kernel *mnt;
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index 512f14e9bb61..f1a9d2ce0226 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -74,7 +74,7 @@ smb_proc_setattr_core(struct smb_sb_info *server, struct dentry *dentry,
static int
smb_proc_setattr_ext(struct smb_sb_info *server,
struct inode *inode, struct smb_fattr *fattr);
-int
+static int
smb_proc_query_cifsunix(struct smb_sb_info *server);
static void
install_ops(struct smb_ops *dst, struct smb_ops *src);
@@ -2075,7 +2075,7 @@ out:
return result;
}
-void smb_decode_unix_basic(struct smb_fattr *fattr, struct smb_sb_info *server, char *p)
+static void smb_decode_unix_basic(struct smb_fattr *fattr, struct smb_sb_info *server, char *p)
{
u64 size, disk_bytes;
@@ -3392,7 +3392,7 @@ out:
return result;
}
-int
+static int
smb_proc_query_cifsunix(struct smb_sb_info *server)
{
int result;
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h
index 97e52d16518a..e866ec8660d0 100644
--- a/fs/smbfs/proto.h
+++ b/fs/smbfs/proto.h
@@ -25,7 +25,6 @@ extern int smb_proc_unlink(struct dentry *dentry);
extern int smb_proc_flush(struct smb_sb_info *server, __u16 fileid);
extern void smb_init_root_dirent(struct smb_sb_info *server, struct smb_fattr *fattr,
struct super_block *sb);
-extern void smb_decode_unix_basic(struct smb_fattr *fattr, struct smb_sb_info *server, char *p);
extern int smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr);
extern int smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr);
extern int smb_proc_setattr_unix(struct dentry *d, struct iattr *attr, unsigned int major, unsigned int minor);
@@ -34,7 +33,6 @@ extern int smb_proc_dskattr(struct super_block *sb, struct kstatfs *attr);
extern int smb_proc_read_link(struct smb_sb_info *server, struct dentry *d, char *buffer, int len);
extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const char *oldpath);
extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry);
-extern int smb_proc_query_cifsunix(struct smb_sb_info *server);
extern void smb_install_null_ops(struct smb_ops *ops);
/* dir.c */
extern struct file_operations smb_dir_operations;
@@ -62,7 +60,6 @@ extern void smb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr);
extern void smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr);
extern void smb_invalidate_inodes(struct smb_sb_info *server);
extern int smb_revalidate_inode(struct dentry *dentry);
-extern int smb_fill_super(struct super_block *sb, void *raw_data, int silent);
extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
/* file.c */
@@ -81,10 +78,8 @@ extern int smbiod_retry(struct smb_sb_info *server);
extern int smb_init_request_cache(void);
extern void smb_destroy_request_cache(void);
extern struct smb_request *smb_alloc_request(struct smb_sb_info *server, int bufsize);
-extern void smb_rget(struct smb_request *req);
extern void smb_rput(struct smb_request *req);
extern int smb_add_request(struct smb_request *req);
-extern int smb_request_send_req(struct smb_request *req);
extern int smb_request_send_server(struct smb_sb_info *server);
extern int smb_request_recv(struct smb_sb_info *server);
/* symlink.c */
diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c
index 60567c1fe960..de40d377c7a0 100644
--- a/fs/smbfs/request.c
+++ b/fs/smbfs/request.c
@@ -27,6 +27,8 @@
/* cache for request structures */
static kmem_cache_t *req_cachep;
+static int smb_request_send_req(struct smb_request *req);
+
/*
/proc/slabinfo:
name, active, num, objsize, active_slabs, num_slaps, #pages
@@ -132,7 +134,7 @@ static void smb_free_request(struct smb_request *req)
* What prevents a rget to race with a rput? The count must never drop to zero
* while it is in use. Only rput if it is ok that it is free'd.
*/
-void smb_rget(struct smb_request *req)
+static void smb_rget(struct smb_request *req)
{
atomic_inc(&req->rq_count);
}
@@ -379,7 +381,7 @@ int smb_add_request(struct smb_request *req)
* Send a request and place it on the recvq if successfully sent.
* Must be called with the server lock held.
*/
-int smb_request_send_req(struct smb_request *req)
+static int smb_request_send_req(struct smb_request *req)
{
struct smb_sb_info *server = req->rq_server;
int result;
diff --git a/fs/umsdos/Makefile b/fs/umsdos/Makefile
deleted file mode 100644
index 7de26124539a..000000000000
--- a/fs/umsdos/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# Makefile for the umsdos Unix-like filesystem routines.
-#
-
-obj-$(CONFIG_UMSDOS) += umsdos.o
-
-umsdos-objs := dir.o inode.o ioctl.o mangle.o namei.o rdir.o emd.o
-
-p:
- proto *.c >/usr/include/linux/umsdos_fs.p
-
-doc:
- nadoc -i -p umsdos.doc - /tmp/umsdos.mpg
diff --git a/fs/umsdos/README-WIP.txt b/fs/umsdos/README-WIP.txt
deleted file mode 100644
index 14643c738f6e..000000000000
--- a/fs/umsdos/README-WIP.txt
+++ /dev/null
@@ -1,114 +0,0 @@
-Changes by Matija Nalis (mnalis@jagor.srce.hr) on umsdos dentry fixing
-(started by Peter T. Waltenberg <peterw@karaka.chch.cri.nz>)
-(Final conversion to dentries Bill Hawes <whawes@star.net>)
-
-There is no warning any more.
-Both read-only and read-write stuff is fixed, both in
-msdos-compatibile mode, and in umsdos EMD mode, and it seems stable.
-
-Userland NOTE: new umsdos_progs (umssync, umssetup, udosctl & friends) that
-will compile and work on 2.2.x+ kernels and glibc based systems, as well as
-kernel patches and other umsdos related information may be found at
-http://linux.voyager.hr/umsdos/
-
-Information below is getting outdated slowly -- I'll fix it one day when I
-get enough time - there are more important things to fix right now.
-
-Legend: those lines marked with '+' on the beggining of line indicates it
-passed all of my tests, and performed perfect in all of them.
-
-Current status (010125) - UMSDOS 0.86j:
-
-(1) pure MSDOS (no --linux-.--- EMD file):
-
-READ:
-+ readdir - works
-+ lookup - works
-+ read file - works
-
-WRITE:
-+ creat file - works
-+ unlink file - works
-+ write file - works
-+ rename file (same dir) - works
-+ rename file (dif. dir) - works
-+ rename dir (same dir) - works
-+ rename dir (dif. dir) - works
-+ mkdir - works
-+ rmdir - works
-
-
-(2) umsdos (with --linux-.--- EMD file):
-
-READ:
-+ readdir - works
-+ lookup - works
-+ permissions/owners stuff - works
-+ long file names - works
-+ read file - works
-+ switching MSDOS/UMSDOS - works
-+ switching UMSDOS/MSDOS - works
-- pseudo root things - works mostly. See notes below.
-+ resolve symlink - works
-+ dereference symlink - works
-+ dangling symlink - works
-+ hard links - works
-+ special files (block/char devices, FIFOs, sockets...) - works
-+ various umsdos ioctls - works
-
-
-WRITE:
-+ create symlink - works
-+ create hardlink - works
-+ create file - works
-+ create special file - works
-+ write to file - works
-+ rename file (same dir) - works
-+ rename file (dif. dir) - works
-+ rename hardlink (same dir) - works
-- rename hardlink (dif. dir) - works, but see notes below.
-+ rename symlink (same dir) - works
-+ rename symlink (dif. dir) - works
-+ rename dir (same dir) - works
-+ rename dir (dif. dir) - works
-+ unlink file - works
-+ notify_change (chown,perms) - works
-+ notify_change for hardlinks - works
-+ unlink hardlink - works
-+ mkdir - works
-+ rmdir - works
-+ umssyncing (many ioctls) - works
-
-
-- CVF-FAT stuff (compressed DOS filesystem) - there is some support from Frank
- Gockel <gockel@sent13.uni-duisburg.de> to use it even under umsdosfs, but I
- have no way of testing it -- please let me know if there are problems specific
- to umsdos (for instance, it works under msdosfs, but not under umsdosfs).
-
-
-Some current notes:
-
-Note: creating and using pseudo-hardlinks is always non-perfect, especially
-in filesystems that might be externally modified like umsdos. There is
-example is specs file about it. Specifically, moving directory which
-contains hardlinks will break them.
-
-Note: (about creating hardlinks in pseudoroot mode) - hardlinks created in
-pseudoroot mode are now again compatibile with 'normal' hardlinks, and vice
-versa. Thanks to Sorin Iordachescu <sorin@rodae.ro> for providing fix.
-See http://linux.voyager.hr/umsdos/hlbug.html for more info and upgrade
-procedure if you used broken versions...
-
-------------------------------------------------------------------------------
-
-Some general notes:
-
-Good idea when running development kernels is to have SysRq support compiled
-in kernel, and use Sync/Emergency-remount-RO if you bump into problems (like
-not being able to umount(2) umsdosfs, and because of it root partition also,
-or panics which force you to reboot etc.)
-
-I'm unfortunately somewhat out of time to read linux-kernel@vger, but I do
-check for messages having "UMSDOS" in the subject, and read them. I might
-miss some in all that volume, though. I should reply to any direct e-mail
-in few days. If I don't, probably I never got your message.
diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c
deleted file mode 100644
index 775f02021128..000000000000
--- a/fs/umsdos/dir.c
+++ /dev/null
@@ -1,810 +0,0 @@
-/*
- * linux/fs/umsdos/dir.c
- *
- * Written 1993 by Jacques Gelinas
- * Inspired from linux/fs/msdos/... : Werner Almesberger
- *
- * Extended MS-DOS directory handling functions
- */
-
-#include <linux/time.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/msdos_fs.h>
-#include <linux/errno.h>
-#include <linux/stat.h>
-#include <linux/limits.h>
-#include <linux/umsdos_fs.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/smp_lock.h>
-
-#define UMSDOS_SPECIAL_DIRFPOS 3
-extern struct dentry *saved_root;
-extern struct inode *pseudo_root;
-
-/* #define UMSDOS_DEBUG_VERBOSE 1 */
-
-/*
- * Dentry operations routines
- */
-
-/* nothing for now ... */
-static int umsdos_dentry_validate(struct dentry *dentry, struct nameidata *nd)
-{
- return 1;
-}
-
-/* for now, drop everything to force lookups ... */
-/* ITYM s/everything/& positive/... */
-static int umsdos_dentry_dput(struct dentry *dentry)
-{
- struct inode *inode = dentry->d_inode;
- if (inode) {
- return 1;
- }
- return 0;
-}
-
-struct dentry_operations umsdos_dentry_operations =
-{
- .d_revalidate = umsdos_dentry_validate,
- .d_delete = umsdos_dentry_dput,
-};
-
-struct UMSDOS_DIR_ONCE {
- void *dirbuf;
- filldir_t filldir;
- int count;
- int stop;
-};
-
-/*
- * Record a single entry the first call.
- * Return -EINVAL the next one.
- * NOTE: filldir DOES NOT use a dentry
- */
-
-static int umsdos_dir_once ( void *buf,
- const char *name,
- int len,
- loff_t offset,
- ino_t ino,
- unsigned type)
-{
- int ret = -EINVAL;
- struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf;
-
- if (d->count == 0) {
- PRINTK ((KERN_DEBUG "dir_once :%.*s: offset %Ld\n",
- len, name, offset));
- ret = d->filldir (d->dirbuf, name, len, offset, ino, DT_UNKNOWN);
- d->stop = ret < 0;
- d->count = 1;
- }
- return ret;
-}
-
-
-/*
- * Read count directory entries from directory filp
- * Return a negative value from linux/errno.h.
- * Return > 0 if success (the number of bytes written by filldir).
- *
- * This function is used by the normal readdir VFS entry point,
- * and in order to get the directory entry from a file's dentry.
- * See umsdos_dentry_to_entry() below.
- */
-
-static int umsdos_readdir_x (struct inode *dir, struct file *filp,
- void *dirbuf, struct umsdos_dirent *u_entry,
- filldir_t filldir)
-{
- struct dentry *demd;
- off_t start_fpos;
- int ret = 0;
- loff_t pos;
-
- umsdos_startlookup (dir);
-
- if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS && dir == pseudo_root) {
-
- /*
- * We don't need to simulate this pseudo directory
- * when umsdos_readdir_x is called for internal operation
- * of umsdos. This is why dirent_in_fs is tested
- */
- /* #Specification: pseudo root / directory /DOS
- * When umsdos operates in pseudo root mode (C:\linux is the
- * linux root), it simulate a directory /DOS which points to
- * the real root of the file system.
- */
-
- Printk ((KERN_WARNING "umsdos_readdir_x: pseudo_root thing UMSDOS_SPECIAL_DIRFPOS\n"));
- if (filldir (dirbuf, "DOS", 3,
- UMSDOS_SPECIAL_DIRFPOS, UMSDOS_ROOT_INO, DT_DIR) == 0) {
- filp->f_pos++;
- }
- goto out_end;
- }
-
- if (filp->f_pos < 2 ||
- (dir->i_ino != UMSDOS_ROOT_INO && filp->f_pos == 32)) {
-
- int last_f_pos = filp->f_pos;
- struct UMSDOS_DIR_ONCE bufk;
-
- Printk (("umsdos_readdir_x: . or .. /mn/?\n"));
-
- bufk.dirbuf = dirbuf;
- bufk.filldir = filldir;
- bufk.count = 0;
-
- ret = fat_readdir (filp, &bufk, umsdos_dir_once);
- if (last_f_pos > 0 && filp->f_pos > last_f_pos)
- filp->f_pos = UMSDOS_SPECIAL_DIRFPOS;
- if (u_entry != NULL)
- u_entry->flags = 0;
- goto out_end;
- }
-
- Printk (("umsdos_readdir_x: normal file /mn/?\n"));
-
- /* get the EMD dentry */
- demd = umsdos_get_emd_dentry(filp->f_dentry);
- ret = PTR_ERR(demd);
- if (IS_ERR(demd))
- goto out_end;
- ret = -EIO;
- if (!demd->d_inode) {
- printk(KERN_WARNING
- "umsdos_readir_x: EMD file %s/%s not found\n",
- demd->d_parent->d_name.name, demd->d_name.name);
- goto out_dput;
- }
-
- pos = filp->f_pos;
- start_fpos = filp->f_pos;
-
- if (pos <= UMSDOS_SPECIAL_DIRFPOS + 1)
- pos = 0;
- ret = 0;
- while (pos < demd->d_inode->i_size) {
- off_t cur_f_pos = pos;
- struct dentry *dret;
- struct inode *inode;
- struct umsdos_dirent entry;
- struct umsdos_info info;
-
- ret = -EIO;
- if (umsdos_emd_dir_readentry (demd, &pos, &entry) != 0)
- break;
- if (entry.name_len == 0)
- continue;
-#ifdef UMSDOS_DEBUG_VERBOSE
-if (entry.flags & UMSDOS_HLINK)
-printk("umsdos_readdir_x: %s/%s is hardlink\n",
-filp->f_dentry->d_name.name, entry.name);
-#endif
-
- umsdos_parse (entry.name, entry.name_len, &info);
- info.f_pos = cur_f_pos;
- umsdos_manglename (&info);
- /*
- * Do a real lookup on the short name.
- */
- dret = umsdos_covered(filp->f_dentry, info.fake.fname,
- info.fake.len);
- ret = PTR_ERR(dret);
- if (IS_ERR(dret))
- break;
- /*
- * If the file wasn't found, remove it from the EMD.
- */
- inode = dret->d_inode;
- if (!inode)
- goto remove_name;
-#ifdef UMSDOS_DEBUG_VERBOSE
-if (UMSDOS_I(inode)->i_is_hlink)
-printk("umsdos_readdir_x: %s/%s already resolved, ino=%ld\n",
-dret->d_parent->d_name.name, dret->d_name.name, inode->i_ino);
-#endif
-
-Printk (("Found %s/%s, ino=%ld, flags=%x\n",
-dret->d_parent->d_name.name, info.fake.fname, dret->d_inode->i_ino,
-entry.flags));
- /* check whether to resolve a hard-link */
- if ((entry.flags & UMSDOS_HLINK) &&
- !UMSDOS_I(inode)->i_is_hlink) {
- dret = umsdos_solve_hlink (dret);
- ret = PTR_ERR(dret);
- if (IS_ERR(dret))
- break;
- inode = dret->d_inode;
- if (!inode) {
-printk("umsdos_readdir_x: %s/%s negative after link\n",
-dret->d_parent->d_name.name, dret->d_name.name);
- goto clean_up;
- }
- }
-
- /* #Specification: pseudo root / reading real root
- * The pseudo root (/linux) is logically
- * erased from the real root. This means that
- * ls /DOS, won't show "linux". This avoids
- * infinite recursion (/DOS/linux/DOS/linux/...) while
- * walking the file system.
- */
- if (inode != pseudo_root && !(entry.flags & UMSDOS_HIDDEN)) {
- if (filldir (dirbuf, entry.name, entry.name_len,
- cur_f_pos, inode->i_ino, DT_UNKNOWN) < 0) {
- pos = cur_f_pos;
- }
-Printk(("umsdos_readdir_x: got %s/%s, ino=%ld\n",
-dret->d_parent->d_name.name, dret->d_name.name, inode->i_ino));
- if (u_entry != NULL)
- *u_entry = entry;
- dput(dret);
- ret = 0;
- break;
- }
- clean_up:
- dput(dret);
- continue;
-
- remove_name:
- /* #Specification: umsdos / readdir / not in MSDOS
- * During a readdir operation, if the file is not
- * in the MS-DOS directory any more, the entry is
- * removed from the EMD file silently.
- */
-#ifdef UMSDOS_PARANOIA
-printk("umsdos_readdir_x: %s/%s out of sync, erasing\n",
-filp->f_dentry->d_name.name, info.entry.name);
-#endif
- ret = umsdos_delentry(filp->f_dentry, &info,
- S_ISDIR(info.entry.mode));
- if (ret)
- printk(KERN_WARNING
- "umsdos_readdir_x: delentry %s, err=%d\n",
- info.entry.name, ret);
- goto clean_up;
- }
- /*
- * If the fillbuf has failed, f_pos is back to 0.
- * To avoid getting back into the . and .. state
- * (see comments at the beginning), we put back
- * the special offset.
- */
- filp->f_pos = pos;
- if (filp->f_pos == 0)
- filp->f_pos = start_fpos;
-out_dput:
- dput(demd);
-
-out_end:
- umsdos_endlookup (dir);
-
- Printk ((KERN_DEBUG "read dir %p pos %Ld ret %d\n",
- dir, filp->f_pos, ret));
- return ret;
-}
-
-
-/*
- * Read count directory entries from directory filp.
- * Return a negative value from linux/errno.h.
- * Return 0 or positive if successful.
- */
-
-static int UMSDOS_readdir (struct file *filp, void *dirbuf, filldir_t filldir)
-{
- struct inode *dir = filp->f_dentry->d_inode;
- int ret = 0, count = 0;
- struct UMSDOS_DIR_ONCE bufk;
-
- lock_kernel();
-
- bufk.dirbuf = dirbuf;
- bufk.filldir = filldir;
- bufk.stop = 0;
-
- Printk (("UMSDOS_readdir in\n"));
- while (ret == 0 && bufk.stop == 0) {
- struct umsdos_dirent entry;
-
- bufk.count = 0;
- ret = umsdos_readdir_x (dir, filp, &bufk, &entry,
- umsdos_dir_once);
- if (bufk.count == 0)
- break;
- count += bufk.count;
- }
- unlock_kernel();
- Printk (("UMSDOS_readdir out %d count %d pos %Ld\n",
- ret, count, filp->f_pos));
- return count ? : ret;
-}
-
-
-/*
- * Complete the inode content with info from the EMD file.
- *
- * This function modifies the state of a dir inode. It decides
- * whether the dir is a UMSDOS or DOS directory. This is done
- * deeper in umsdos_patch_inode() called at the end of this function.
- *
- * Because it is does disk access, umsdos_patch_inode() may block.
- * At the same time, another process may get here to initialise
- * the same directory inode. There are three cases.
- *
- * 1) The inode is already initialised. We do nothing.
- * 2) The inode is not initialised. We lock access and do it.
- * 3) Like 2 but another process has locked the inode, so we try
- * to lock it and check right afterward check whether
- * initialisation is still needed.
- *
- *
- * Thanks to the "mem" option of the kernel command line, it was
- * possible to consistently reproduce this problem by limiting
- * my memory to 4 MB and running X.
- *
- * Do this only if the inode is freshly read, because we will lose
- * the current (updated) content.
- *
- * A lookup of a mount point directory yield the inode into
- * the other fs, so we don't care about initialising it. iget()
- * does this automatically.
- */
-
-void umsdos_lookup_patch_new(struct dentry *dentry, struct umsdos_info *info)
-{
- struct inode *inode = dentry->d_inode;
- struct umsdos_dirent *entry = &info->entry;
-
- /*
- * This part of the initialization depends only on i_patched.
- */
- if (UMSDOS_I(inode)->i_patched)
- goto out;
- UMSDOS_I(inode)->i_patched = 1;
- if (S_ISREG (entry->mode))
- entry->mtime = inode->i_mtime;
- inode->i_mode = entry->mode;
- inode->i_rdev = to_kdev_t (entry->rdev);
- inode->i_atime = entry->atime;
- inode->i_ctime = entry->ctime;
- inode->i_mtime = entry->mtime;
- inode->i_uid = entry->uid;
- inode->i_gid = entry->gid;
-
- /* #Specification: umsdos / i_nlink
- * The nlink field of an inode is maintained by the MSDOS file system
- * for directory and by UMSDOS for other files. The logic is that
- * MSDOS is already figuring out what to do for directories and
- * does nothing for other files. For MSDOS, there are no hard links
- * so all file carry nlink==1. UMSDOS use some info in the
- * EMD file to plug the correct value.
- */
- if (!S_ISDIR (entry->mode)) {
- if (entry->nlink > 0) {
- inode->i_nlink = entry->nlink;
- } else {
- printk (KERN_ERR
- "UMSDOS: lookup_patch entry->nlink < 1 ???\n");
- }
- }
- /*
- * The mode may have changed, so patch the inode again.
- */
- umsdos_patch_dentry_inode(dentry, info->f_pos);
- umsdos_set_dirinfo_new(dentry, info->f_pos);
-
-out:
- return;
-}
-
-
-/*
- * Return != 0 if an entry is the pseudo DOS entry in the pseudo root.
- */
-
-int umsdos_is_pseudodos (struct inode *dir, struct dentry *dentry)
-{
- /* #Specification: pseudo root / DOS hard coded
- * The pseudo sub-directory DOS in the pseudo root is hard coded.
- * The name is DOS. This is done this way to help standardised
- * the umsdos layout. The idea is that from now on /DOS is
- * a reserved path and nobody will think of using such a path
- * for a package.
- */
- return dir == pseudo_root
- && dentry->d_name.len == 3
- && dentry->d_name.name[0] == 'D'
- && dentry->d_name.name[1] == 'O'
- && dentry->d_name.name[2] == 'S';
-}
-
-
-/*
- * Check whether a file exists in the current directory.
- * Return 0 if OK, negative error code if not (ex: -ENOENT).
- *
- * fills dentry->d_inode with found inode, and increments its count.
- * if not found, return -ENOENT.
- */
-/* #Specification: umsdos / lookup
- * A lookup for a file is done in two steps. First, we
- * locate the file in the EMD file. If not present, we
- * return an error code (-ENOENT). If it is there, we
- * repeat the operation on the msdos file system. If
- * this fails, it means that the file system is not in
- * sync with the EMD file. We silently remove this
- * entry from the EMD file, and return ENOENT.
- */
-
-struct dentry *umsdos_lookup_x (struct inode *dir, struct dentry *dentry, int nopseudo)
-{
- struct dentry *dret = NULL;
- struct inode *inode;
- int ret = -ENOENT;
- struct umsdos_info info;
-
-#ifdef UMSDOS_DEBUG_VERBOSE
-printk("umsdos_lookup_x: looking for %s/%s\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
-#endif
-
- umsdos_startlookup (dir);
- if (umsdos_is_pseudodos (dir, dentry)) {
- /* #Specification: pseudo root / lookup(DOS)
- * A lookup of DOS in the pseudo root will always succeed
- * and return the inode of the real root.
- */
- Printk ((KERN_DEBUG "umsdos_lookup_x: following /DOS\n"));
- inode = saved_root->d_inode;
- goto out_add;
- }
-
- ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
- if (ret) {
-printk("umsdos_lookup_x: %s/%s parse failed, ret=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, ret);
- goto out;
- }
-
- ret = umsdos_findentry (dentry->d_parent, &info, 0);
- if (ret) {
-if (ret != -ENOENT)
-printk("umsdos_lookup_x: %s/%s findentry failed, ret=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, ret);
- goto out;
- }
-Printk (("lookup %.*s pos %lu ret %d len %d ",
-info.fake.len, info.fake.fname, info.f_pos, ret, info.fake.len));
-
- /* do a real lookup to get the short name ... */
- dret = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
- ret = PTR_ERR(dret);
- if (IS_ERR(dret)) {
-printk("umsdos_lookup_x: %s/%s real lookup failed, ret=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, ret);
- goto out;
- }
- inode = dret->d_inode;
- if (!inode)
- goto out_remove;
- umsdos_lookup_patch_new(dret, &info);
-#ifdef UMSDOS_DEBUG_VERBOSE
-printk("umsdos_lookup_x: found %s/%s, ino=%ld\n",
-dret->d_parent->d_name.name, dret->d_name.name, dret->d_inode->i_ino);
-#endif
-
- /* Check for a hard link */
- if ((info.entry.flags & UMSDOS_HLINK) &&
- !UMSDOS_I(inode)->i_is_hlink) {
- dret = umsdos_solve_hlink (dret);
- ret = PTR_ERR(dret);
- if (IS_ERR(dret))
- goto out;
- ret = -ENOENT;
- inode = dret->d_inode;
- if (!inode) {
-printk("umsdos_lookup_x: %s/%s negative after link\n",
-dret->d_parent->d_name.name, dret->d_name.name);
- goto out_dput;
- }
- }
-
- if (inode == pseudo_root && !nopseudo) {
- /* #Specification: pseudo root / dir lookup
- * For the same reason as readdir, a lookup in /DOS for
- * the pseudo root directory (linux) will fail.
- */
- /*
- * This has to be allowed for resolving hard links
- * which are recorded independently of the pseudo-root
- * mode.
- */
-printk("umsdos_lookup_x: skipping DOS/linux\n");
- ret = -ENOENT;
- goto out_dput;
- }
-
- /*
- * We've found it OK. Now hash the dentry with the inode.
- */
-out_add:
- atomic_inc(&inode->i_count);
- d_add (dentry, inode);
- dentry->d_op = &umsdos_dentry_operations;
- ret = 0;
-
-out_dput:
- if (dret && dret != dentry)
- d_drop(dret);
- dput(dret);
-out:
- umsdos_endlookup (dir);
- return ERR_PTR(ret);
-
-out_remove:
- printk(KERN_WARNING "UMSDOS: entry %s/%s out of sync, erased\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
- umsdos_delentry (dentry->d_parent, &info, S_ISDIR (info.entry.mode));
- ret = -ENOENT;
- goto out_dput;
-}
-
-
-/*
- * Check whether a file exists in the current directory.
- * Return 0 if OK, negative error code if not (ex: -ENOENT).
- *
- * Called by VFS; should fill dentry->d_inode via d_add.
- */
-
-struct dentry *UMSDOS_lookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
- struct dentry *ret;
-
- ret = umsdos_lookup_x (dir, dentry, 0);
-
- /* Create negative dentry if not found. */
- if (ret == ERR_PTR(-ENOENT)) {
- Printk ((KERN_DEBUG
- "UMSDOS_lookup: converting -ENOENT to negative\n"));
- d_add (dentry, NULL);
- dentry->d_op = &umsdos_dentry_operations;
- ret = NULL;
- }
- return ret;
-}
-
-struct dentry *umsdos_covered(struct dentry *parent, char *name, int len)
-{
- struct dentry *result, *dentry;
- struct qstr qstr;
-
- qstr.name = name;
- qstr.len = len;
- qstr.hash = full_name_hash(name, len);
- result = ERR_PTR(-ENOMEM);
- dentry = d_alloc(parent, &qstr);
- if (dentry) {
- /* XXXXXXXXXXXXXXXXXXX Race alert! */
- result = UMSDOS_rlookup(parent->d_inode, dentry);
- d_drop(dentry);
- if (result)
- goto out_fail;
- return dentry;
- }
-out:
- return result;
-
-out_fail:
- dput(dentry);
- goto out;
-}
-
-/*
- * Lookup or create a dentry from within the filesystem.
- *
- * We need to use this instead of lookup_dentry, as the
- * directory semaphore lock is already held.
- */
-struct dentry *umsdos_lookup_dentry(struct dentry *parent, char *name, int len,
- int real)
-{
- struct dentry *result, *dentry;
- struct qstr qstr;
-
- qstr.name = name;
- qstr.len = len;
- qstr.hash = full_name_hash(name, len);
- result = d_lookup(parent, &qstr);
- if (!result) {
- result = ERR_PTR(-ENOMEM);
- dentry = d_alloc(parent, &qstr);
- if (dentry) {
- result = real ?
- UMSDOS_rlookup(parent->d_inode, dentry) :
- UMSDOS_lookup(parent->d_inode, dentry);
- if (result)
- goto out_fail;
- return dentry;
- }
- }
-out:
- return result;
-
-out_fail:
- dput(dentry);
- goto out;
-}
-
-/*
- * Return a path relative to our root.
- */
-char * umsdos_d_path(struct dentry *dentry, char * buffer, int len)
-{
- struct dentry * old_root;
- char * path;
-
- read_lock(&current->fs->lock);
- old_root = dget(current->fs->root);
- read_unlock(&current->fs->lock);
- spin_lock(&dcache_lock);
- path = __d_path(dentry, current->fs->rootmnt, dentry->d_sb->s_root, current->fs->rootmnt, buffer, len); /* FIXME: current->fs->rootmnt */
- spin_unlock(&dcache_lock);
-
- if (*path == '/')
- path++; /* skip leading '/' */
-
- if (current->fs->root->d_inode == pseudo_root)
- {
- *(path-1) = '/';
- path -= (UMSDOS_PSDROOT_LEN+1);
- memcpy(path, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN);
- }
- dput(old_root);
-
- return path;
-}
-
-/*
- * Return the dentry which points to a pseudo-hardlink.
- *
- * it should try to find file it points to
- * if file is found, return new dentry/inode
- * The resolved inode will have i_is_hlink set.
- *
- * Note: the original dentry is always dput(), even if an error occurs.
- */
-
-struct dentry *umsdos_solve_hlink (struct dentry *hlink)
-{
- /* root is our root for resolving pseudo-hardlink */
- struct dentry *base = hlink->d_sb->s_root;
- struct dentry *dentry_dst;
- char *path, *pt;
- int len;
- struct address_space *mapping = hlink->d_inode->i_mapping;
- struct page *page;
-
- page=read_cache_page(mapping,0,(filler_t *)mapping->a_ops->readpage,NULL);
- dentry_dst=(struct dentry *)page;
- if (IS_ERR(page))
- goto out;
- wait_on_page_locked(page);
- if (!PageUptodate(page))
- goto async_fail;
-
- dentry_dst = ERR_PTR(-ENOMEM);
- path = (char *) kmalloc (PATH_MAX, GFP_KERNEL);
- if (path == NULL)
- goto out_release;
- memcpy(path, kmap(page), hlink->d_inode->i_size);
- kunmap(page);
- page_cache_release(page);
-
- len = hlink->d_inode->i_size;
-
- /* start at root dentry */
- dentry_dst = dget(base);
- path[len] = '\0';
-
- pt = path;
- if (*path == '/')
- pt++; /* skip leading '/' */
-
- if (base->d_inode == pseudo_root)
- pt += (UMSDOS_PSDROOT_LEN + 1);
-
- while (1) {
- struct dentry *dir = dentry_dst, *demd;
- char *start = pt;
- int real;
-
- while (*pt != '\0' && *pt != '/') pt++;
- len = (int) (pt - start);
- if (*pt == '/') *pt++ = '\0';
-
- real = 1;
- demd = umsdos_get_emd_dentry(dir);
- if (!IS_ERR(demd)) {
- if (demd->d_inode)
- real = 0;
- dput(demd);
- }
-
-#ifdef UMSDOS_DEBUG_VERBOSE
-printk ("umsdos_solve_hlink: dir %s/%s, name=%s, real=%d\n",
-dir->d_parent->d_name.name, dir->d_name.name, start, real);
-#endif
- dentry_dst = umsdos_lookup_dentry(dir, start, len, real);
-/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
- if (real)
- d_drop(dir);
- dput (dir);
- if (IS_ERR(dentry_dst))
- break;
- /* not found? stop search ... */
- if (!dentry_dst->d_inode) {
- break;
- }
- if (*pt == '\0') /* we're finished! */
- break;
- } /* end while */
-
- if (!IS_ERR(dentry_dst)) {
- struct inode *inode = dentry_dst->d_inode;
- if (inode) {
- UMSDOS_I(inode)->i_is_hlink = 1;
-#ifdef UMSDOS_DEBUG_VERBOSE
-printk ("umsdos_solve_hlink: resolved link %s/%s, ino=%ld\n",
-dentry_dst->d_parent->d_name.name, dentry_dst->d_name.name, inode->i_ino);
-#endif
- } else {
-#ifdef UMSDOS_DEBUG_VERBOSE
-printk ("umsdos_solve_hlink: resolved link %s/%s negative!\n",
-dentry_dst->d_parent->d_name.name, dentry_dst->d_name.name);
-#endif
- }
- } else
- printk(KERN_WARNING
- "umsdos_solve_hlink: err=%ld\n", PTR_ERR(dentry_dst));
- kfree (path);
-
-out:
- dput(hlink); /* original hlink no longer needed */
- return dentry_dst;
-
-async_fail:
- dentry_dst = ERR_PTR(-EIO);
-out_release:
- page_cache_release(page);
- goto out;
-}
-
-
-struct file_operations umsdos_dir_operations =
-{
- .read = generic_read_dir,
- .readdir = UMSDOS_readdir,
- .ioctl = UMSDOS_ioctl_dir,
-};
-
-struct inode_operations umsdos_dir_inode_operations =
-{
- .create = UMSDOS_create,
- .lookup = UMSDOS_lookup,
- .link = UMSDOS_link,
- .unlink = UMSDOS_unlink,
- .symlink = UMSDOS_symlink,
- .mkdir = UMSDOS_mkdir,
- .rmdir = UMSDOS_rmdir,
- .mknod = UMSDOS_mknod,
- .rename = UMSDOS_rename,
- .setattr = UMSDOS_notify_change,
-};
diff --git a/fs/umsdos/emd.c b/fs/umsdos/emd.c
deleted file mode 100644
index 16a15d75dcd7..000000000000
--- a/fs/umsdos/emd.c
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * linux/fs/umsdos/emd.c
- *
- * Written 1993 by Jacques Gelinas
- *
- * Extended MS-DOS directory handling functions
- */
-
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/msdos_fs.h>
-#include <linux/umsdos_fs.h>
-#include <linux/dcache.h>
-#include <linux/pagemap.h>
-#include <linux/delay.h>
-
-void put_entry (struct umsdos_dirent *p, struct umsdos_dirent *q)
-{
- p->name_len = q->name_len;
- p->flags = q->flags;
- p->nlink = cpu_to_le16(q->nlink);
- p->uid = cpu_to_le16(q->uid);
- p->gid = cpu_to_le16(q->gid);
- p->atime = cpu_to_le32(q->atime);
- p->mtime = cpu_to_le32(q->mtime);
- p->ctime = cpu_to_le32(q->ctime);
- p->rdev = cpu_to_le16(q->rdev);
- p->mode = cpu_to_le16(q->mode);
-}
-
-static void get_entry(struct umsdos_dirent *p, struct umsdos_dirent *q)
-{
- p->name_len = q->name_len;
- p->name[p->name_len]='\0';
- p->flags = q->flags;
- p->nlink = le16_to_cpu (q->nlink);
- /* FIXME -- 32bit UID/GID issues */
- p->uid = le16_to_cpu (q->uid);
- p->gid = le16_to_cpu (q->gid);
- p->atime = le32_to_cpu (q->atime);
- p->mtime = le32_to_cpu (q->mtime);
- p->ctime = le32_to_cpu (q->ctime);
- p->rdev = le16_to_cpu (q->rdev);
- p->mode = le16_to_cpu (q->mode);
-}
-
-/*
- * Lookup the EMD dentry for a directory.
- *
- * Note: the caller must hold a lock on the parent directory.
- */
-struct dentry *umsdos_get_emd_dentry(struct dentry *parent)
-{
- struct dentry *demd;
-
- demd = umsdos_lookup_dentry(parent, UMSDOS_EMD_FILE,
- UMSDOS_EMD_NAMELEN, 1);
- return demd;
-}
-
-/*
- * Check whether a directory has an EMD file.
- *
- * Note: the caller must hold a lock on the parent directory.
- */
-int umsdos_have_emd(struct dentry *dir)
-{
- struct dentry *demd = umsdos_get_emd_dentry (dir);
- int found = 0;
-
- if (!IS_ERR(demd)) {
- if (demd->d_inode)
- found = 1;
- dput(demd);
- }
- return found;
-}
-
-/*
- * Create the EMD file for a directory if it doesn't
- * already exist. Returns 0 or an error code.
- *
- * Note: the caller must hold a lock on the parent directory.
- */
-int umsdos_make_emd(struct dentry *parent)
-{
- struct dentry *demd = umsdos_get_emd_dentry(parent);
- int err = PTR_ERR(demd);
-
- if (IS_ERR(demd)) {
- printk("umsdos_make_emd: can't get dentry in %s, err=%d\n",
- parent->d_name.name, err);
- goto out;
- }
-
- /* already created? */
- err = 0;
- if (demd->d_inode)
- goto out_set;
-
-Printk(("umsdos_make_emd: creating EMD %s/%s\n",
-parent->d_name.name, demd->d_name.name));
-
- err = msdos_create(parent->d_inode, demd, S_IFREG | 0777, NULL);
- if (err) {
- printk (KERN_WARNING
- "umsdos_make_emd: create %s/%s failed, err=%d\n",
- parent->d_name.name, demd->d_name.name, err);
- }
-out_set:
- dput(demd);
-out:
- return err;
-}
-
-
-/*
- * Read an entry from the EMD file.
- * Support variable length record.
- * Return -EIO if error, 0 if OK.
- *
- * does not change {d,i}_count
- */
-
-int umsdos_emd_dir_readentry (struct dentry *demd, loff_t *pos, struct umsdos_dirent *entry)
-{
- struct address_space *mapping = demd->d_inode->i_mapping;
- struct page *page;
- struct umsdos_dirent *p;
- int offs = *pos & ~PAGE_CACHE_MASK;
- int recsize;
- int ret = 0;
-
- page = read_cache_page(mapping, *pos>>PAGE_CACHE_SHIFT,
- (filler_t*)mapping->a_ops->readpage, NULL);
- if (IS_ERR(page))
- goto sync_fail;
- wait_on_page_locked(page);
- if (!PageUptodate(page))
- goto async_fail;
- p = (struct umsdos_dirent*)(kmap(page)+offs);
-
- /* if this is an invalid entry (invalid name length), ignore it */
- if( p->name_len > UMSDOS_MAXNAME )
- {
- printk (KERN_WARNING "Ignoring invalid EMD entry with size %d\n", entry->name_len);
- p->name_len = 0;
- ret = -ENAMETOOLONG; /* notify umssync(8) code that something is wrong */
- /* FIXME: does not work if we did 'ls -l' before 'udosctl uls' ?! */
- }
-
- recsize = umsdos_evalrecsize(p->name_len);
- if (offs + recsize > PAGE_CACHE_SIZE) {
- struct page *page2;
- int part = (char *)(page_address(page) + PAGE_CACHE_SIZE) - p->spare;
- page2 = read_cache_page(mapping, 1+(*pos>>PAGE_CACHE_SHIFT),
- (filler_t*)mapping->a_ops->readpage, NULL);
- if (IS_ERR(page2)) {
- kunmap(page);
- page_cache_release(page);
- page = page2;
- goto sync_fail;
- }
- wait_on_page_locked(page2);
- if (!PageUptodate(page2)) {
- kunmap(page);
- page_cache_release(page2);
- goto async_fail;
- }
- memcpy(entry->spare,p->spare,part);
- memcpy(entry->spare+part,kmap(page2),
- recsize+offs-PAGE_CACHE_SIZE);
- kunmap(page2);
- page_cache_release(page2);
- } else
- memcpy(entry->spare,p->spare,((char*)p+recsize)-p->spare);
- get_entry(entry, p);
- kunmap(page);
- page_cache_release(page);
- *pos += recsize;
- return ret;
-async_fail:
- page_cache_release(page);
- page = ERR_PTR(-EIO);
-sync_fail:
- return PTR_ERR(page);
-}
-
-
-/*
- * Write an entry in the EMD file.
- * Return 0 if OK, -EIO if some error.
- *
- * Note: the caller must hold a lock on the parent directory.
- */
-int umsdos_writeentry (struct dentry *parent, struct umsdos_info *info,
- int free_entry)
-{
- struct inode *dir = parent->d_inode;
- struct umsdos_dirent *entry = &info->entry;
- struct dentry *emd_dentry;
- int ret;
- struct umsdos_dirent entry0,*p;
- struct address_space *mapping;
- struct page *page, *page2 = NULL;
- int offs;
-
- emd_dentry = umsdos_get_emd_dentry(parent);
- ret = PTR_ERR(emd_dentry);
- if (IS_ERR(emd_dentry))
- goto out;
- /* make sure there's an EMD file */
- ret = -EIO;
- if (!emd_dentry->d_inode) {
- printk(KERN_WARNING
- "umsdos_writeentry: no EMD file in %s/%s\n",
- parent->d_parent->d_name.name, parent->d_name.name);
- goto out_dput;
- }
-
- if (free_entry) {
- /* #Specification: EMD file / empty entries
- * Unused entries in the EMD file are identified
- * by the name_len field equal to 0. However to
- * help future extension (or bug correction :-( ),
- * empty entries are filled with 0.
- */
- memset (&entry0, 0, sizeof (entry0));
- entry = &entry0;
- } else if (entry->name_len > 0) {
- memset (entry->name + entry->name_len, '\0',
- sizeof (entry->name) - entry->name_len);
- /* #Specification: EMD file / spare bytes
- * 10 bytes are unused in each record of the EMD. They
- * are set to 0 all the time, so it will be possible
- * to do new stuff and rely on the state of those
- * bytes in old EMD files.
- */
- memset (entry->spare, 0, sizeof (entry->spare));
- }
-
- /* write the entry and update the parent timestamps */
- mapping = emd_dentry->d_inode->i_mapping;
- offs = info->f_pos & ~PAGE_CACHE_MASK;
- ret = -ENOMEM;
- page = grab_cache_page(mapping, info->f_pos>>PAGE_CACHE_SHIFT);
- if (!page)
- goto out_dput;
- p = (struct umsdos_dirent *) (page_address(page) + offs);
- if (offs + info->recsize > PAGE_CACHE_SIZE) {
- ret = mapping->a_ops->prepare_write(NULL,page,offs,
- PAGE_CACHE_SIZE);
- if (ret)
- goto out_unlock;
- page2 = grab_cache_page(mapping,
- (info->f_pos>>PAGE_CACHE_SHIFT)+1);
- if (!page2)
- goto out_unlock2;
- ret = mapping->a_ops->prepare_write(NULL,page2,0,
- offs+info->recsize-PAGE_CACHE_SIZE);
- if (ret)
- goto out_unlock3;
- put_entry (p, entry);
- memcpy(p->spare,entry->spare,
- (char *)(page_address(page) + PAGE_CACHE_SIZE) - p->spare);
- memcpy(page_address(page2),
- ((char*)entry)+PAGE_CACHE_SIZE-offs,
- offs+info->recsize-PAGE_CACHE_SIZE);
- ret = mapping->a_ops->commit_write(NULL,page2,0,
- offs+info->recsize-PAGE_CACHE_SIZE);
- if (ret)
- goto out_unlock3;
- ret = mapping->a_ops->commit_write(NULL,page,offs,
- PAGE_CACHE_SIZE);
- unlock_page(page2);
- page_cache_release(page2);
- if (ret)
- goto out_unlock;
- } else {
- ret = mapping->a_ops->prepare_write(NULL,page,offs,
- offs + info->recsize);
- if (ret)
- goto out_unlock;
- put_entry (p, entry);
- memcpy(p->spare,entry->spare,((char*)p+info->recsize)-p->spare);
- ret = mapping->a_ops->commit_write(NULL,page,offs,
- offs + info->recsize);
- if (ret)
- goto out_unlock;
- }
- unlock_page(page);
- page_cache_release(page);
-
- dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
- mark_inode_dirty(dir);
-
-out_dput:
- dput(emd_dentry);
-out:
- Printk (("umsdos_writeentry /mn/: returning %d...\n", ret));
- return ret;
-out_unlock3:
- unlock_page(page2);
- page_cache_release(page2);
-out_unlock2:
- ClearPageUptodate(page);
- kunmap(page);
-out_unlock:
- unlock_page(page);
- page_cache_release(page);
- printk ("UMSDOS: problem with EMD file: can't write\n");
- goto out_dput;
-}
-
-/*
- * General search, locate a name in the EMD file or an empty slot to
- * store it. if info->entry.name_len == 0, search the first empty
- * slot (of the proper size).
- *
- * Return 0 if found, -ENOENT if not found, another error code if
- * other problem.
- *
- * So this routine is used to either find an existing entry or to
- * create a new one, while making sure it is a new one. After you
- * get -ENOENT, you make sure the entry is stuffed correctly and
- * call umsdos_writeentry().
- *
- * To delete an entry, you find it, zero out the entry (memset)
- * and call umsdos_writeentry().
- *
- * All this to say that umsdos_writeentry must be called after this
- * function since it relies on the f_pos field of info.
- *
- * Note: the caller must hold a lock on the parent directory.
- */
-/* #Specification: EMD file structure
- * The EMD file uses a fairly simple layout. It is made of records
- * (UMSDOS_REC_SIZE == 64). When a name can't be written in a single
- * record, multiple contiguous records are allocated.
- */
-
-static int umsdos_find (struct dentry *demd, struct umsdos_info *info)
-{
- struct umsdos_dirent *entry = &info->entry;
- int recsize = info->recsize;
- struct inode *emd_dir;
- int ret = -ENOENT;
- struct {
- off_t posok; /* Position available to store the entry */
- off_t one; /* One empty position -> maybe <- large enough */
- } empty;
- int found = 0;
- int empty_size = 0;
- struct address_space *mapping;
- filler_t *readpage;
- struct page *page = NULL;
- int index = -1;
- int offs = PAGE_CACHE_SIZE,max_offs = PAGE_CACHE_SIZE;
- char *p = NULL;
- loff_t pos = 0;
-
- /* make sure there's an EMD file ... */
- ret = -ENOENT;
- emd_dir = demd->d_inode;
- if (!emd_dir)
- goto out_dput;
- mapping = emd_dir->i_mapping;
- readpage = (filler_t*)mapping->a_ops->readpage;
-
- empty.posok = emd_dir->i_size;
- while (1) {
- struct umsdos_dirent *rentry;
- int entry_size;
-
- if (offs >= max_offs) {
- if (page) {
- kunmap(page);
- page_cache_release(page);
- page = NULL;
- }
- if (pos >= emd_dir->i_size) {
- info->f_pos = empty.posok;
- break;
- }
- if (++index == (emd_dir->i_size>>PAGE_CACHE_SHIFT))
- max_offs = emd_dir->i_size & ~PAGE_CACHE_MASK;
- offs -= PAGE_CACHE_SIZE;
- page = read_cache_page(mapping,index,readpage,NULL);
- if (IS_ERR(page))
- goto sync_fail;
- wait_on_page_locked(page);
- if (!PageUptodate(page))
- goto async_fail;
- p = kmap(page);
- }
-
- rentry = (struct umsdos_dirent *)(p+offs);
-
- if (rentry->name_len == 0) {
- /* We are looking for an empty section at least */
- /* as large as recsize. */
- if (entry->name_len == 0) {
- info->f_pos = pos;
- ret = 0;
- break;
- }
- offs += UMSDOS_REC_SIZE;
- pos += UMSDOS_REC_SIZE;
- if (found)
- continue;
- if (!empty_size)
- empty.one = pos-UMSDOS_REC_SIZE;
- empty_size += UMSDOS_REC_SIZE;
- if (empty_size == recsize) {
- /* Here is a large enough section. */
- empty.posok = empty.one;
- found = 1;
- }
- continue;
- }
-
- entry_size = umsdos_evalrecsize(rentry->name_len);
- if (entry_size > PAGE_CACHE_SIZE)
- goto async_fail;
- empty_size = 0;
- if (entry->name_len != rentry->name_len)
- goto skip_it;
-
- if (entry_size + offs > PAGE_CACHE_SIZE) {
- /* Sucker spans the page boundary */
- int len = (p+PAGE_CACHE_SIZE)-rentry->name;
- struct page *next_page;
- char *q;
- next_page = read_cache_page(mapping,index+1,readpage,NULL);
- if (IS_ERR(next_page)) {
- page_cache_release(page);
- page = next_page;
- goto sync_fail;
- }
- wait_on_page_locked(next_page);
- if (!PageUptodate(next_page)) {
- page_cache_release(page);
- page = next_page;
- goto async_fail;
- }
- q = kmap(next_page);
- if (memcmp(entry->name, rentry->name, len) ||
- memcmp(entry->name+len, q, entry->name_len-len)) {
- kunmap(next_page);
- page_cache_release(next_page);
- goto skip_it;
- }
- kunmap(next_page);
- page_cache_release(next_page);
- } else if (memcmp (entry->name, rentry->name, entry->name_len))
- goto skip_it;
-
- info->f_pos = pos;
- get_entry(entry, rentry);
- ret = 0;
- break;
-skip_it:
- offs+=entry_size;
- pos+=entry_size;
- }
- if (page) {
- kunmap(page);
- page_cache_release(page);
- }
- umsdos_manglename (info);
-
-out_dput:
- dput(demd);
- return ret;
-
-async_fail:
- page_cache_release(page);
- page = ERR_PTR(-EIO);
-sync_fail:
- return PTR_ERR(page);
-}
-
-
-/*
- * Add a new entry in the EMD file.
- * Return 0 if OK or a negative error code.
- * Return -EEXIST if the entry already exists.
- *
- * Complete the information missing in info.
- *
- * N.B. What if the EMD file doesn't exist?
- */
-
-int umsdos_newentry (struct dentry *parent, struct umsdos_info *info)
-{
- int err, ret = -EEXIST;
- struct dentry *demd = umsdos_get_emd_dentry(parent);
-
- ret = PTR_ERR(demd);
- if (IS_ERR(demd))
- goto out;
- err = umsdos_find (demd, info);
- if (err && err == -ENOENT) {
- ret = umsdos_writeentry (parent, info, 0);
- Printk (("umsdos_writeentry EMD ret = %d\n", ret));
- }
-out:
- return ret;
-}
-
-
-/*
- * Create a new hidden link.
- * Return 0 if OK, an error code if not.
- */
-
-/* #Specification: hard link / hidden name
- * When a hard link is created, the original file is renamed
- * to a hidden name. The name is "..LINKNNN" where NNN is a
- * number define from the entry offset in the EMD file.
- */
-int umsdos_newhidden (struct dentry *parent, struct umsdos_info *info)
-{
- int ret;
- struct dentry *demd = umsdos_get_emd_dentry(parent);
- ret = PTR_ERR(demd);
- if (IS_ERR(demd))
- goto out;
-
- umsdos_parse ("..LINK", 6, info);
- info->entry.name_len = 0;
- ret = umsdos_find (demd, info);
- if (ret == -ENOENT || ret == 0) {
- info->entry.name_len = sprintf (info->entry.name,
- "..LINK%ld", info->f_pos);
- ret = 0;
- }
-out:
- return ret;
-}
-
-
-/*
- * Remove an entry from the EMD file.
- * Return 0 if OK, a negative error code otherwise.
- *
- * Complete the information missing in info.
- */
-
-int umsdos_delentry (struct dentry *parent, struct umsdos_info *info, int isdir)
-{
- int ret;
- struct dentry *demd = umsdos_get_emd_dentry(parent);
-
- ret = PTR_ERR(demd);
- if (IS_ERR(demd))
- goto out;
- ret = umsdos_find (demd, info);
- if (ret)
- goto out;
- if (info->entry.name_len == 0)
- goto out;
-
- if ((isdir != 0) != (S_ISDIR (info->entry.mode) != 0)) {
- if (S_ISDIR (info->entry.mode)) {
- ret = -EISDIR;
- } else {
- ret = -ENOTDIR;
- }
- goto out;
- }
- ret = umsdos_writeentry (parent, info, 1);
-
-out:
- return ret;
-}
-
-
-/*
- * Verify that an EMD directory is empty.
- * Return:
- * 0 if not empty,
- * 1 if empty (except for EMD file),
- * 2 if empty or no EMD file.
- */
-
-int umsdos_isempty (struct dentry *dentry)
-{
- struct dentry *demd;
- int ret = 2;
- loff_t pos = 0;
-
- demd = umsdos_get_emd_dentry(dentry);
- if (IS_ERR(demd))
- goto out;
- /* If the EMD file does not exist, it is certainly empty. :-) */
- if (!demd->d_inode)
- goto out_dput;
-
- ret = 1;
- while (pos < demd->d_inode->i_size) {
- struct umsdos_dirent entry;
-
- if (umsdos_emd_dir_readentry (demd, &pos, &entry) != 0) {
- ret = 0;
- break;
- }
- if (entry.name_len != 0) {
- ret = 0;
- break;
- }
- }
-
-out_dput:
- dput(demd);
-out:
- return ret;
-}
-
-/*
- * Locate an entry in a EMD directory.
- * Return 0 if OK, error code if not, generally -ENOENT.
- *
- * expect argument:
- * 0: anything
- * 1: file
- * 2: directory
- */
-
-int umsdos_findentry (struct dentry *parent, struct umsdos_info *info,
- int expect)
-{
- int ret;
- struct dentry *demd = umsdos_get_emd_dentry(parent);
-
- ret = PTR_ERR(demd);
- if (IS_ERR(demd))
- goto out;
- ret = umsdos_find (demd, info);
- if (ret)
- goto out;
-
- switch (expect) {
- case 1:
- if (S_ISDIR (info->entry.mode))
- ret = -EISDIR;
- break;
- case 2:
- if (!S_ISDIR (info->entry.mode))
- ret = -ENOTDIR;
- }
-
-out:
- Printk (("umsdos_findentry: returning %d\n", ret));
- return ret;
-}
diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c
deleted file mode 100644
index 778feedf4642..000000000000
--- a/fs/umsdos/inode.c
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * linux/fs/umsdos/inode.c
- *
- * Written 1993 by Jacques Gelinas
- * Inspired from linux/fs/msdos/... by Werner Almesberger
- */
-
-#include <linux/module.h>
-
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/msdos_fs.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/errno.h>
-#include <asm/uaccess.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/umsdos_fs.h>
-#include <linux/list.h>
-#include <linux/pagemap.h>
-
-extern struct dentry_operations umsdos_dentry_operations;
-
-struct dentry *saved_root; /* Original root if changed */
-struct inode *pseudo_root; /* Useful to simulate the pseudo DOS */
- /* directory. See UMSDOS_readdir_x() */
-
-static struct dentry *check_pseudo_root(struct super_block *);
-
-
-void UMSDOS_put_inode (struct inode *inode)
-{
- PRINTK ((KERN_DEBUG
- "put inode %p (%lu) pos %lu count=%d\n"
- ,inode, inode->i_ino
- ,UMSDOS_I(inode)->pos
- ,atomic_read(&inode->i_count)));
-
- if (inode == pseudo_root) {
- Printk ((KERN_ERR "Umsdos: debug: releasing pseudo_root - ino=%lu count=%d\n", inode->i_ino, atomic_read(&inode->i_count)));
- }
-
- if (atomic_read(&inode->i_count) == 1)
- UMSDOS_I(inode)->i_patched = 0;
-}
-
-
-void UMSDOS_put_super (struct super_block *sb)
-{
- Printk ((KERN_DEBUG "UMSDOS_put_super: entering\n"));
- if (saved_root && pseudo_root && kdev_same(sb->s_dev, ROOT_DEV)) {
- shrink_dcache_parent(saved_root);
- dput(saved_root);
- saved_root = NULL;
- pseudo_root = NULL;
- }
- fat_put_super (sb);
-}
-
-
-/*
- * Complete the setup of a directory dentry based on its
- * EMD/non-EMD status. If it has an EMD, then plug the
- * umsdos function table. If not, use the msdos one.
- */
-void umsdos_setup_dir(struct dentry *dir)
-{
- struct inode *inode = dir->d_inode;
- struct umsdos_inode_info *ui = UMSDOS_I(inode);
-
- if (!S_ISDIR(inode->i_mode))
- printk(KERN_ERR "umsdos_setup_dir: %s/%s not a dir!\n",
- dir->d_parent->d_name.name, dir->d_name.name);
-
- init_waitqueue_head (&ui->dir_info.p);
- ui->dir_info.looking = 0;
- ui->dir_info.creating = 0;
- ui->dir_info.pid = 0;
-
- inode->i_op = &umsdos_rdir_inode_operations;
- inode->i_fop = &umsdos_rdir_operations;
- if (umsdos_have_emd(dir)) {
-Printk((KERN_DEBUG "umsdos_setup_dir: %s/%s using EMD\n",
-dir->d_parent->d_name.name, dir->d_name.name));
- inode->i_op = &umsdos_dir_inode_operations;
- inode->i_fop = &umsdos_dir_operations;
- }
-}
-
-
-/*
- * Add some info into an inode so it can find its owner quickly
- */
-void umsdos_set_dirinfo_new (struct dentry *dentry, off_t f_pos)
-{
- struct inode *inode = dentry->d_inode;
- struct dentry *demd;
-
- UMSDOS_I(inode)->pos = f_pos;
-
- /* now check the EMD file */
- demd = umsdos_get_emd_dentry(dentry->d_parent);
- if (!IS_ERR(demd)) {
- dput(demd);
- }
- return;
-}
-
-static struct inode_operations umsdos_file_inode_operations = {
- .truncate = fat_truncate,
- .setattr = UMSDOS_notify_change,
-};
-
-static struct inode_operations umsdos_symlink_inode_operations = {
- .readlink = page_readlink,
- .follow_link = page_follow_link,
- .setattr = UMSDOS_notify_change,
-};
-
-/*
- * Connect the proper tables in the inode and add some info.
- */
-/* #Specification: inode / umsdos info
- * The first time an inode is seen (inode->i_count == 1),
- * the inode number of the EMD file which controls this inode
- * is tagged to this inode. It allows operations such as
- * notify_change to be handled.
- */
-void umsdos_patch_dentry_inode(struct dentry *dentry, off_t f_pos)
-{
- struct inode *inode = dentry->d_inode;
-
-PRINTK (("umsdos_patch_dentry_inode: inode=%lu\n", inode->i_ino));
-
- /*
- * Classify the inode based on EMD/non-EMD status.
- */
-PRINTK (("umsdos_patch_inode: call umsdos_set_dirinfo_new(%p,%lu)\n",
-dentry, f_pos));
- umsdos_set_dirinfo_new(dentry, f_pos);
-
- inode->i_op = &umsdos_file_inode_operations;
- if (S_ISREG (inode->i_mode)) {
- /* address_space operations already set */
- } else if (S_ISDIR (inode->i_mode)) {
- umsdos_setup_dir(dentry);
- } else if (S_ISLNK (inode->i_mode)) {
- /* address_space operations already set */
- inode->i_op = &umsdos_symlink_inode_operations;
- } else
- init_special_inode(inode, inode->i_mode,
- kdev_t_to_nr(inode->i_rdev));
-}
-
-
-/*
- * lock the parent dir before starting ...
- * also handles hardlink converting
- */
-int UMSDOS_notify_change (struct dentry *dentry, struct iattr *attr)
-{
- struct inode *dir, *inode;
- struct umsdos_info info;
- struct dentry *temp, *old_dentry = NULL;
- int ret;
-
- lock_kernel();
-
- ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len,
- &info);
- if (ret)
- goto out;
- ret = umsdos_findentry (dentry->d_parent, &info, 0);
- if (ret) {
-printk("UMSDOS_notify_change: %s/%s not in EMD, ret=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, ret);
- goto out;
- }
-
- if (info.entry.flags & UMSDOS_HLINK) {
- /*
- * In order to get the correct (real) inode, we just drop
- * the original dentry.
- */
- d_drop(dentry);
-Printk(("UMSDOS_notify_change: hard link %s/%s, fake=%s\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, info.fake.fname));
-
- /* Do a real lookup to get the short name dentry */
- temp = umsdos_covered(dentry->d_parent, info.fake.fname,
- info.fake.len);
- ret = PTR_ERR(temp);
- if (IS_ERR(temp))
- goto out;
-
- /* now resolve the link ... */
- temp = umsdos_solve_hlink(temp);
- ret = PTR_ERR(temp);
- if (IS_ERR(temp))
- goto out;
- old_dentry = dentry;
- dentry = temp; /* so umsdos_notify_change_locked will operate on that */
- }
-
- dir = dentry->d_parent->d_inode;
- inode = dentry->d_inode;
-
- ret = inode_change_ok (inode, attr);
- if (ret)
- goto out;
-
- ret = umsdos_notify_change_locked(dentry, attr);
- if (ret == 0)
- ret = inode_setattr (inode, attr);
-out:
- if (old_dentry)
- dput (dentry); /* if we had to use fake dentry for hardlinks, dput() it now */
- unlock_kernel();
- return ret;
-}
-
-
-/*
- * Must be called with the parent lock held.
- */
-int umsdos_notify_change_locked(struct dentry *dentry, struct iattr *attr)
-{
- struct inode *inode = dentry->d_inode;
- struct dentry *demd;
- struct address_space *mapping;
- struct page *page;
- int ret = 0;
- struct umsdos_dirent *entry;
- int offs;
-
-Printk(("UMSDOS_notify_change: entering for %s/%s (%d)\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, UMSDOS_I(inode)->i_patched));
-
- if (inode->i_nlink == 0)
- goto out;
- if (inode->i_ino == UMSDOS_ROOT_INO)
- goto out;
-
- /* get the EMD file dentry */
- demd = umsdos_get_emd_dentry(dentry->d_parent);
- ret = PTR_ERR(demd);
- if (IS_ERR(demd))
- goto out;
- ret = 0;
- /* don't do anything if directory is not promoted to umsdos yet */
- if (!demd->d_inode) {
- Printk((KERN_DEBUG
- "UMSDOS_notify_change: no EMD file %s/%s\n",
- demd->d_parent->d_name.name, demd->d_name.name));
- goto out_dput;
- }
-
- /* don't do anything if this is the EMD itself */
- if (inode == demd->d_inode)
- goto out_dput;
-
- /* This inode is not a EMD file nor an inode used internally
- * by MSDOS, so we can update its status.
- * See emd.c
- */
-
- /* Read only the start of the entry since we don't touch the name */
- mapping = demd->d_inode->i_mapping;
- offs = UMSDOS_I(inode)->pos & ~PAGE_CACHE_MASK;
- ret = -ENOMEM;
- page=grab_cache_page(mapping,UMSDOS_I(inode)->pos>>PAGE_CACHE_SHIFT);
- if (!page)
- goto out_dput;
- ret=mapping->a_ops->prepare_write(NULL,page,offs,offs+UMSDOS_REC_SIZE);
- if (ret)
- goto out_unlock;
- entry = (struct umsdos_dirent *) (page_address(page) + offs);
- if (attr->ia_valid & ATTR_UID)
- entry->uid = cpu_to_le16(attr->ia_uid);
- if (attr->ia_valid & ATTR_GID)
- entry->gid = cpu_to_le16(attr->ia_gid);
- if (attr->ia_valid & ATTR_MODE)
- entry->mode = cpu_to_le16(attr->ia_mode);
- if (attr->ia_valid & ATTR_ATIME)
- entry->atime = cpu_to_le32(attr->ia_atime);
- if (attr->ia_valid & ATTR_MTIME)
- entry->mtime = cpu_to_le32(attr->ia_mtime);
- if (attr->ia_valid & ATTR_CTIME)
- entry->ctime = cpu_to_le32(attr->ia_ctime);
- entry->nlink = cpu_to_le16(inode->i_nlink);
- ret=mapping->a_ops->commit_write(NULL,page,offs,offs+UMSDOS_REC_SIZE);
- if (ret)
- printk(KERN_WARNING
- "umsdos_notify_change: %s/%s EMD write error, ret=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,ret);
-
- /* #Specification: notify_change / msdos fs
- * notify_change operation are done only on the
- * EMD file. The msdos fs is not even called.
- */
-out_unlock:
- unlock_page(page);
- page_cache_release(page);
-out_dput:
- dput(demd);
-out:
- return ret;
-}
-
-
-/*
- * Update the disk with the inode content
- */
-int UMSDOS_write_inode (struct inode *inode, int wait)
-{
- struct iattr newattrs;
- int ret;
-
- ret = fat_write_inode (inode, wait);
- newattrs.ia_mtime = inode->i_mtime;
- newattrs.ia_atime = inode->i_atime;
- newattrs.ia_ctime = inode->i_ctime;
- newattrs.ia_valid = ATTR_MTIME | ATTR_ATIME | ATTR_CTIME;
- /*
- * UMSDOS_notify_change is convenient to call here
- * to update the EMD entry associated with this inode.
- * But it has the side effect to re"dirt" the inode.
- */
-/*
- * UMSDOS_notify_change (inode, &newattrs);
-
- * inode->i_state &= ~I_DIRTY; / * FIXME: this doesn't work. We need to remove ourselves from list on dirty inodes. /mn/ */
- return ret;
-}
-
-
-static struct super_operations umsdos_sops =
-{
- .write_inode = UMSDOS_write_inode,
- .put_inode = UMSDOS_put_inode,
- .delete_inode = fat_delete_inode,
- .put_super = UMSDOS_put_super,
- .statfs = UMSDOS_statfs,
- .clear_inode = fat_clear_inode,
-};
-
-int UMSDOS_statfs(struct super_block *sb,struct statfs *buf)
-{
- int ret;
- ret = fat_statfs (sb, buf);
- if (!ret)
- buf->f_namelen = UMSDOS_MAXNAME;
- return ret;
-}
-
-/*
- * Read the super block of an Extended MS-DOS FS.
- */
-struct super_block *UMSDOS_read_super (struct super_block *sb, void *data,
- int silent)
-{
- struct super_block *res;
- struct dentry *new_root;
-
- /*
- * Call msdos-fs to mount the disk.
- * Note: this returns res == sb or NULL
- */
- MSDOS_SB(sb)->options.isvfat = 0;
- res = fat_read_super(sb, data, silent, &umsdos_rdir_inode_operations);
-
- if (IS_ERR(res))
- return NULL;
- if (res == NULL) {
- if (!silent)
- printk(KERN_INFO "VFS: Can't find a valid "
- "UMSDOS filesystem on dev %s.\n", sb->s_id);
- return NULL;
- }
-
- printk (KERN_INFO "UMSDOS 0.86k "
- "(compatibility level %d.%d, fast msdos)\n",
- UMSDOS_VERSION, UMSDOS_RELEASE);
-
- sb->s_op = &umsdos_sops;
- MSDOS_SB(sb)->options.dotsOK = 0; /* disable hidden==dotfile */
-
- /* install our dentry operations ... */
- sb->s_root->d_op = &umsdos_dentry_operations;
-
- umsdos_patch_dentry_inode(sb->s_root, 0);
-
- /* Check whether to change to the /linux root */
- new_root = check_pseudo_root(sb);
-
- if (new_root) {
- /* sanity check */
- if (new_root->d_op != &umsdos_dentry_operations)
- printk("umsdos_read_super: pseudo-root wrong ops!\n");
-
- pseudo_root = new_root->d_inode;
- saved_root = sb->s_root;
- printk(KERN_INFO "UMSDOS: changed to alternate root\n");
- dget (sb->s_root); sb->s_root = dget(new_root);
- }
- return sb;
-}
-
-/*
- * Check for an alternate root if we're the root device.
- */
-
-extern kdev_t ROOT_DEV;
-static struct dentry *check_pseudo_root(struct super_block *sb)
-{
- struct dentry *root, *sbin, *init;
-
- /*
- * Check whether we're mounted as the root device.
- * must check like this, because we can be used with initrd
- */
-
- if (!kdev_same(sb->s_dev, ROOT_DEV))
- goto out_noroot;
-
- /*
- * lookup_dentry needs a (so far non-existent) root.
- */
- printk(KERN_INFO "check_pseudo_root: mounted as root\n");
- root = lookup_one_len(UMSDOS_PSDROOT_NAME, sb->s_root,UMSDOS_PSDROOT_LEN);
- if (IS_ERR(root))
- goto out_noroot;
-
- if (!root->d_inode || !S_ISDIR(root->d_inode->i_mode))
- goto out_dput;
-
-printk(KERN_INFO "check_pseudo_root: found %s/%s\n",
-root->d_parent->d_name.name, root->d_name.name);
-
- /* look for /sbin/init */
- sbin = lookup_one_len("sbin", root, 4);
- if (IS_ERR(sbin))
- goto out_dput;
- if (!sbin->d_inode || !S_ISDIR(sbin->d_inode->i_mode))
- goto out_dput_sbin;
- init = lookup_one_len("init", sbin, 4);
- if (IS_ERR(init))
- goto out_dput_sbin;
- if (!init->d_inode)
- goto out_dput_init;
- printk(KERN_INFO "check_pseudo_root: found %s/%s, enabling pseudo-root\n", init->d_parent->d_name.name, init->d_name.name);
- dput(sbin);
- dput(init);
- return root;
-
- /* Alternate root not found ... */
-out_dput_init:
- dput(init);
-out_dput_sbin:
- dput(sbin);
-out_dput:
- dput(root);
-out_noroot:
- return NULL;
-}
-
-
-static DECLARE_FSTYPE_DEV(umsdos_fs_type, "umsdos", UMSDOS_read_super);
-
-static int __init init_umsdos_fs (void)
-{
- return register_filesystem (&umsdos_fs_type);
-}
-
-static void __exit exit_umsdos_fs (void)
-{
- unregister_filesystem (&umsdos_fs_type);
-}
-
-module_init(init_umsdos_fs)
-module_exit(exit_umsdos_fs)
-MODULE_LICENSE("GPL");
diff --git a/fs/umsdos/ioctl.c b/fs/umsdos/ioctl.c
deleted file mode 100644
index fc300030afd1..000000000000
--- a/fs/umsdos/ioctl.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * linux/fs/umsdos/ioctl.c
- *
- * Written 1993 by Jacques Gelinas
- *
- * Extended MS-DOS ioctl directory handling functions
- *
- * Changes:
- * 11/07/2003 Daniele Bellucci <bellucda@tiscali.it>
- * - audit copy_to_user/put_user in umsdos_ioctl_fill.
- */
-
-#include <asm/uaccess.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/fs.h>
-#include <linux/msdos_fs.h>
-#include <linux/umsdos_fs.h>
-
-struct UMSDOS_DIR_ONCE {
- struct dirent *ent;
- int count;
-};
-
-/*
- * Record a single entry the first call.
- * Return -EINVAL the next one.
- */
-static int umsdos_ioctl_fill (
- void *buf,
- const char *name,
- int name_len,
- loff_t offset,
- ino_t ino,
- unsigned type)
-{
- int ret = -EINVAL;
- struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf;
-
- if (d->count == 0) {
- if (copy_to_user (d->ent->d_name, name, name_len) ||
- put_user ('\0', d->ent->d_name + name_len) ||
- put_user (name_len, &d->ent->d_reclen) ||
- put_user (ino, &d->ent->d_ino) ||
- put_user (offset, &d->ent->d_off))
- return -EFAULT;
- d->count = 1;
- ret = 0;
- }
- return ret;
-}
-
-
-/*
- * Perform special function on a directory
- */
-/* #Specification: ioctl / prototypes
- * The official prototype for the umsdos ioctl on directory
- * is:
- *
- * int ioctl (
- * int fd, // File handle of the directory
- * int cmd, // command
- * struct umsdos_ioctl *data)
- *
- * The struct and the commands are defined in linux/umsdos_fs.h.
- *
- * umsdos_progs/umsdosio.c provide an interface in C++ to all
- * these ioctl. umsdos_progs/udosctl is a small utility showing
- * all this.
- *
- * These ioctl generally allow one to work on the EMD or the
- * DOS directory independently. These are essential to implement
- * the synchronise.
- */
-int UMSDOS_ioctl_dir(struct inode *dir, struct file *filp, unsigned int cmd,
- unsigned long data_ptr)
-{
- struct dentry *dentry = filp->f_dentry;
- struct umsdos_ioctl *idata = (struct umsdos_ioctl *) data_ptr;
- int ret;
- struct umsdos_ioctl data;
-
-Printk(("UMSDOS_ioctl_dir: %s/%s, cmd=%d, data=%08lx\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, cmd, data_ptr));
-
- /* forward non-umsdos ioctls - this hopefully doesn't cause conflicts */
- if (cmd != UMSDOS_GETVERSION
- && cmd != UMSDOS_READDIR_DOS
- && cmd != UMSDOS_READDIR_EMD
- && cmd != UMSDOS_INIT_EMD
- && cmd != UMSDOS_CREAT_EMD
- && cmd != UMSDOS_RENAME_DOS
- && cmd != UMSDOS_UNLINK_EMD
- && cmd != UMSDOS_UNLINK_DOS
- && cmd != UMSDOS_RMDIR_DOS
- && cmd != UMSDOS_STAT_DOS
- && cmd != UMSDOS_DOS_SETUP)
- return fat_dir_ioctl (dir, filp, cmd, data_ptr);
-
- /* #Specification: ioctl / access
- * Only root (effective id) is allowed to do IOCTL on directory
- * in UMSDOS. EPERM is returned for other user.
- */
- /*
- * Well, not all cases require write access, but it simplifies
- * the code, and let's face it, there is only one client (umssync)
- * for all this.
- */
- ret = verify_area (VERIFY_WRITE, (void *) data_ptr,
- sizeof (struct umsdos_ioctl));
- if (ret < 0)
- goto out;
-
- ret = -EPERM;
- if (current->euid != 0 && cmd != UMSDOS_GETVERSION)
- goto out;
-
- ret = -EINVAL;
- if (cmd == UMSDOS_GETVERSION) {
- /* #Specification: ioctl / UMSDOS_GETVERSION
- * The field version and release of the structure
- * umsdos_ioctl are filled with the version and release
- * number of the fs code in the kernel. This will allow
- * some form of checking. Users won't be able to run
- * incompatible utility such as the synchroniser (umssync).
- * umsdos_progs/umsdosio.c enforce this checking.
- *
- * Return always 0.
- */
- put_user (UMSDOS_VERSION, &idata->version);
- put_user (UMSDOS_RELEASE, &idata->release);
- ret = 0;
- goto out;
- }
- if (cmd == UMSDOS_READDIR_DOS) {
- /* #Specification: ioctl / UMSDOS_READDIR_DOS
- * One entry is read from the DOS directory at the current
- * file position. The entry is put as is in the dos_dirent
- * field of struct umsdos_ioctl.
- *
- * Return > 0 if success.
- */
- struct UMSDOS_DIR_ONCE bufk;
-
- bufk.count = 0;
- bufk.ent = &idata->dos_dirent;
-
- fat_readdir (filp, &bufk, umsdos_ioctl_fill);
-
- ret = bufk.count == 1 ? 1 : 0;
- goto out;
- }
- if (cmd == UMSDOS_READDIR_EMD) {
- /* #Specification: ioctl / UMSDOS_READDIR_EMD
- * One entry is read from the EMD at the current
- * file position. The entry is put as is in the umsdos_dirent
- * field of struct umsdos_ioctl. The corresponding mangled
- * DOS entry name is put in the dos_dirent field.
- *
- * All entries are read including hidden links. Blank
- * entries are skipped.
- *
- * Return > 0 if success.
- */
- struct dentry *demd;
- loff_t pos = filp->f_pos;
-
- /* The absence of the EMD is simply seen as an EOF */
- demd = umsdos_get_emd_dentry(dentry);
- ret = PTR_ERR(demd);
- if (IS_ERR(demd))
- goto out;
- ret = 0;
- if (!demd->d_inode)
- goto read_dput;
-
- while (pos < demd->d_inode->i_size) {
- off_t f_pos = pos;
- struct umsdos_dirent entry;
- struct umsdos_info info;
-
- ret = umsdos_emd_dir_readentry (demd, &pos, &entry);
-
- if (ret == -ENAMETOOLONG) {
- printk (KERN_INFO "Fixing EMD entry with invalid size -- zeroing out\n");
- memset (&info, 0, sizeof (info));
- info.f_pos = f_pos;
- info.recsize = UMSDOS_REC_SIZE;
- ret = umsdos_writeentry (dentry, &info, 1);
- continue;
- }
-
- if (ret)
- break;
- if (entry.name_len <= 0)
- continue;
-
- umsdos_parse (entry.name, entry.name_len, &info);
- info.f_pos = f_pos;
- umsdos_manglename (&info);
- ret = -EFAULT;
- if (copy_to_user (&idata->umsdos_dirent, &entry,
- sizeof (entry)))
- break;
- if (copy_to_user (&idata->dos_dirent.d_name,
- info.fake.fname,
- info.fake.len + 1))
- break;
- ret = entry.name_len;
- break;
- }
- /* update the original f_pos */
- filp->f_pos = pos;
- read_dput:
- d_drop(demd);
- dput(demd);
- goto out;
- }
- if (cmd == UMSDOS_INIT_EMD) {
- /* #Specification: ioctl / UMSDOS_INIT_EMD
- * The UMSDOS_INIT_EMD command makes sure the EMD
- * exists for a directory. If it does not, it is
- * created. Also, it makes sure the directory function
- * table (struct inode_operations) is set to the UMSDOS
- * semantic. This mean that umssync may be applied to
- * an "opened" msdos directory, and it will change behavior
- * on the fly.
- *
- * Return 0 if success.
- */
-
- ret = umsdos_make_emd(dentry);
-Printk(("UMSDOS_ioctl_dir: INIT_EMD %s/%s, ret=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, ret));
- umsdos_setup_dir (dentry);
- goto out;
- }
-
- ret = -EFAULT;
- if (copy_from_user (&data, idata, sizeof (data)))
- goto out;
-
- if (cmd == UMSDOS_CREAT_EMD) {
- /* #Specification: ioctl / UMSDOS_CREAT_EMD
- * The umsdos_dirent field of the struct umsdos_ioctl is used
- * as is to create a new entry in the EMD of the directory.
- * The DOS directory is not modified.
- * No validation is done (yet).
- *
- * Return 0 if success.
- */
- struct umsdos_info info;
-
- /* This makes sure info.entry and info in general
- * is correctly initialised
- */
- memcpy (&info.entry, &data.umsdos_dirent,
- sizeof (data.umsdos_dirent));
- umsdos_parse (data.umsdos_dirent.name
- ,data.umsdos_dirent.name_len, &info);
- ret = umsdos_newentry (dentry, &info);
- goto out;
- }
- else if (cmd == UMSDOS_RENAME_DOS) {
- struct dentry *old_dentry, *new_dentry; /* FIXME */
-
- /* #Specification: ioctl / UMSDOS_RENAME_DOS
- * A file or directory is renamed in a DOS directory
- * (not moved across directory). The source name
- * is in the dos_dirent.name field and the destination
- * is in umsdos_dirent.name field.
- *
- * This ioctl allows umssync to rename a mangled file
- * name before syncing it back in the EMD.
- */
- old_dentry = umsdos_lookup_dentry (dentry,
- data.dos_dirent.d_name,
- data.dos_dirent.d_reclen ,1);
- ret = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto out;
- new_dentry = umsdos_lookup_dentry (dentry,
- data.umsdos_dirent.name,
- data.umsdos_dirent.name_len, 1);
- ret = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
-printk("umsdos_ioctl: renaming %s/%s to %s/%s\n",
-old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
-new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
- ret = msdos_rename (dir, old_dentry, dir, new_dentry);
- d_drop(new_dentry);
- d_drop(old_dentry);
- dput(new_dentry);
- }
- dput(old_dentry);
- goto out;
- }
- else if (cmd == UMSDOS_UNLINK_EMD) {
- /* #Specification: ioctl / UMSDOS_UNLINK_EMD
- * The umsdos_dirent field of the struct umsdos_ioctl is used
- * as is to remove an entry from the EMD of the directory.
- * No validation is done (yet). The mode field is used
- * to validate S_ISDIR or S_ISREG.
- *
- * Return 0 if success.
- */
- struct umsdos_info info;
-
- /* This makes sure info.entry and info in general
- * is correctly initialised
- */
- memcpy (&info.entry, &data.umsdos_dirent,
- sizeof (data.umsdos_dirent));
- umsdos_parse (data.umsdos_dirent.name,
- data.umsdos_dirent.name_len, &info);
- ret = umsdos_delentry (dentry, &info,
- S_ISDIR (data.umsdos_dirent.mode));
- if (ret) {
- printk(KERN_WARNING
- "umsdos_ioctl: delentry %s/%s failed, ret=%d\n",
- dentry->d_name.name, info.entry.name, ret);
- }
- goto out;
- }
- else if (cmd == UMSDOS_UNLINK_DOS) {
- struct dentry *temp;
-
- /* #Specification: ioctl / UMSDOS_UNLINK_DOS
- * The dos_dirent field of the struct umsdos_ioctl is used to
- * execute a msdos_unlink operation. The d_name and d_reclen
- * fields are used.
- *
- * Return 0 if success.
- */
- temp = umsdos_lookup_dentry(dentry, data.dos_dirent.d_name,
- data.dos_dirent.d_reclen, 1);
- ret = PTR_ERR(temp);
- if (IS_ERR(temp))
- goto out;
- ret = -ENOENT;
- if (temp->d_inode) {
- ret = -EISDIR;
- if (!S_ISDIR(temp->d_inode->i_mode))
- ret = msdos_unlink (dir, temp);
- if (!ret)
- d_delete(temp);
- }
- dput (temp);
- goto out;
- }
- else if (cmd == UMSDOS_RMDIR_DOS) {
- struct dentry *temp;
-
- /* #Specification: ioctl / UMSDOS_RMDIR_DOS
- * The dos_dirent field of the struct umsdos_ioctl is used to
- * execute a msdos_rmdir operation. The d_name and d_reclen
- * fields are used.
- *
- * Return 0 if success.
- */
- temp = umsdos_lookup_dentry(dentry, data.dos_dirent.d_name,
- data.dos_dirent.d_reclen, 1);
- ret = PTR_ERR(temp);
- if (IS_ERR(temp))
- goto out;
- ret = -ENOENT;
- if (temp->d_inode) {
- ret = -ENOTDIR;
- if (S_ISDIR(temp->d_inode->i_mode))
- ret = msdos_rmdir (dir, temp);
- if (!ret)
- d_delete(temp);
- }
- dput (temp);
- goto out;
-
- } else if (cmd == UMSDOS_STAT_DOS) {
- /* #Specification: ioctl / UMSDOS_STAT_DOS
- * The dos_dirent field of the struct umsdos_ioctl is
- * used to execute a stat operation in the DOS directory.
- * The d_name and d_reclen fields are used.
- *
- * The following field of umsdos_ioctl.stat are filled.
- *
- * st_ino,st_mode,st_size,st_atime,st_mtime,st_ctime,
- * Return 0 if success.
- */
- struct dentry *dret;
- struct inode *inode;
-
- dret = umsdos_lookup_dentry(dentry, data.dos_dirent.d_name,
- data.dos_dirent.d_reclen, 1);
- ret = PTR_ERR(dret);
- if (IS_ERR(dret))
- goto out;
- ret = -ENOENT;
- inode = dret->d_inode;
- if (inode) {
- data.stat.st_ino = inode->i_ino;
- data.stat.st_mode = inode->i_mode;
- data.stat.st_size = inode->i_size;
- data.stat.st_atime = inode->i_atime;
- data.stat.st_ctime = inode->i_ctime;
- data.stat.st_mtime = inode->i_mtime;
- ret = -EFAULT;
- if (!copy_to_user (&idata->stat, &data.stat,
- sizeof (data.stat)))
- ret = 0;
- }
- dput(dret);
- goto out;
- }
- else if (cmd == UMSDOS_DOS_SETUP) {
- /* #Specification: ioctl / UMSDOS_DOS_SETUP
- * The UMSDOS_DOS_SETUP ioctl allow changing the
- * default permission of the MS-DOS filesystem driver
- * on the fly. The MS-DOS driver applies global permissions
- * to every file and directory. Normally these permissions
- * are controlled by a mount option. This is not
- * available for root partition, so a special utility
- * (umssetup) is provided to do this, normally in
- * /etc/rc.local.
- *
- * Be aware that this applies ONLY to MS-DOS directories
- * (those without EMD --linux-.---). Umsdos directory
- * have independent (standard) permission for each
- * and every file.
- *
- * The field umsdos_dirent provide the information needed.
- * umsdos_dirent.uid and gid sets the owner and group.
- * umsdos_dirent.mode set the permissions flags.
- */
- dir->i_sb->u.msdos_sb.options.fs_uid = data.umsdos_dirent.uid;
- dir->i_sb->u.msdos_sb.options.fs_gid = data.umsdos_dirent.gid;
- dir->i_sb->u.msdos_sb.options.fs_fmask =
- dir->i_sb->u.msdos_sb.options.fs_dmask =
- data.umsdos_dirent.mode;
- ret = 0;
- }
-out:
- Printk (("ioctl %d, returning %d\n", cmd, ret));
- return ret;
-}
diff --git a/fs/umsdos/mangle.c b/fs/umsdos/mangle.c
deleted file mode 100644
index 0451123594d9..000000000000
--- a/fs/umsdos/mangle.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * linux/fs/umsdos/mangle.c
- *
- * Written 1993 by Jacques Gelinas
- *
- * Control the mangling of file name to fit msdos name space.
- * Many optimisations by GLU == dglaude@is1.vub.ac.be (Glaude David)
- */
-
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/umsdos_fs.h>
-
-/* (This file is used outside of the kernel) */
-#ifndef __KERNEL__
-#define KERN_WARNING
-#endif
-
-/*
- * Complete the mangling of the MSDOS fake name
- * based on the position of the entry in the EMD file.
- *
- * Simply complete the job of umsdos_parse; fill the extension.
- *
- * Beware that info->f_pos must be set.
- */
-void umsdos_manglename (struct umsdos_info *info)
-{
- if (info->msdos_reject) {
- /* #Specification: file name / non MSDOS conforming / mangling
- * Each non MSDOS conforming file has a special extension
- * build from the entry position in the EMD file.
- *
- * This number is then transform in a base 32 number, where
- * each digit is expressed like hexadecimal number, using
- * digit and letter, except it uses 22 letters from 'a' to 'v'.
- * The number 32 comes from 2**5. It is faster to split a binary
- * number using a base which is a power of two. And I was 32
- * when I started this project. Pick your answer :-) .
- *
- * If the result is '0', it is replace with '_', simply
- * to make it odd.
- *
- * This is true for the first two character of the extension.
- * The last one is taken from a list of odd character, which
- * are:
- *
- * { } ( ) ! ` ^ & @
- *
- * With this scheme, we can produce 9216 ( 9* 32 * 32)
- * different extensions which should not clash with any useful
- * extension already popular or meaningful. Since most directory
- * have much less than 32 * 32 files in it, the first character
- * of the extension of any mangled name will be {.
- *
- * Here are the reason to do this (this kind of mangling).
- *
- * -The mangling is deterministic. Just by the extension, we
- * are able to locate the entry in the EMD file.
- *
- * -By keeping to beginning of the file name almost unchanged,
- * we are helping the MSDOS user.
- *
- * -The mangling produces names not too ugly, so an msdos user
- * may live with it (remember it, type it, etc...).
- *
- * -The mangling produces names ugly enough so no one will
- * ever think of using such a name in real life. This is not
- * fool proof. I don't think there is a total solution to this.
- */
- int entry_num;
- char *pt = info->fake.fname + info->fake.len;
- /* lookup for encoding the last character of the extension
- * It contains valid character after the ugly one to make sure
- * even if someone overflows the 32 * 32 * 9 limit, it still
- * does something
- */
-#define SPECIAL_MANGLING '{','}','(',')','!','`','^','&','@'
- static char lookup3[] =
- {
- SPECIAL_MANGLING,
- /* This is the start of lookup12 */
- '_', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
- 'p', 'q', 'r', 's', 't', 'u', 'v'
- };
-
-#define lookup12 (lookup3+9)
- entry_num = info->f_pos / UMSDOS_REC_SIZE;
- if (entry_num > (9* 32 * 32)){
- printk (KERN_WARNING "UMSDOS: more than 9216 files in a directory.\n"
- "This may break the mangling strategy.\n"
- "Not a killer problem. See doc.\n");
- }
- *pt++ = '.';
- *pt++ = lookup3 [(entry_num >> 10) & 31];
- *pt++ = lookup12[(entry_num >> 5) & 31];
- *pt++ = lookup12[entry_num & 31];
- *pt = '\0'; /* help doing printk */
- info->fake.len += 4;
- info->msdos_reject = 0; /* Avoid mangling twice */
- }
-}
-
-/*
- * Evaluate the record size needed to store of name of len character.
- * The value returned is a multiple of UMSDOS_REC_SIZE.
- */
-int umsdos_evalrecsize (int len)
-{
- struct umsdos_dirent dirent;
- int nbrec = 1 + ((len - 1 + (dirent.name - (char *) &dirent))
- / UMSDOS_REC_SIZE);
-
- return nbrec * UMSDOS_REC_SIZE;
- /*
- * GLU This should be inlined or something to speed it up to the max.
- * GLU nbrec is absolutely not needed to return the value.
- */
-}
-#ifdef TEST
-int umsdos_evalrecsize_old (int len)
-{
- struct umsdos_dirent dirent;
- int size = len + (dirent.name - (char *) &dirent);
- int nbrec = size / UMSDOS_REC_SIZE;
- int extra = size % UMSDOS_REC_SIZE;
-
- if (extra > 0)
- nbrec++;
- return nbrec * UMSDOS_REC_SIZE;
-}
-#endif
-
-
-/*
- * Fill the struct info with the full and msdos name of a file
- * Return 0 if all is OK, a negative error code otherwise.
- */
-int umsdos_parse (
- const char *fname,
- int len,
- struct umsdos_info *info)
-{
- int ret = -ENAMETOOLONG;
-
- /* #Specification: file name / too long
- * If a file name exceed UMSDOS maxima, the file name is silently
- * truncated. This makes it conformant with the other file system
- * of Linux (minix and ext2 at least).
- */
- if (len > UMSDOS_MAXNAME)
- len = UMSDOS_MAXNAME;
- {
- const char *firstpt = NULL; /* First place we saw a "." in fname */
-
- /* #Specification: file name / non MSDOS conforming / base length 0
- * file names beginning with a period '.' are invalid for MS-DOS.
- * It needs absolutely a base name. So the file name is mangled
- */
- int ivldchar = fname[0] == '.'; /* At least one invalid character */
- int msdos_len = len;
- int base_len;
-
- /*
- * cardinal_per_size tells if there exists at least one
- * DOS pseudo device on length n. See the test below.
- */
- static const char cardinal_per_size[9] =
- {
- 0, 0, 0, 1, 1, 0, 1, 0, 1
- };
-
- /*
- * lkp translate all character to acceptable character (for DOS).
- * When lkp[n] == n, it means also it is an acceptable one.
- * So it serves both as a flag and as a translator.
- */
- static char lkp[256];
- static char is_init;
-
- if (!is_init) {
- /*
- * Initialisation of the array is easier and less error
- * prone like this.
- */
- int i;
- static const char *spc = "\"*+,/:;<=>?[\\]|~";
-
- is_init = 1;
- for (i = 0; i <= 32; i++)
- lkp[i] = '#';
- for (i = 33; i < 'A'; i++)
- lkp[i] = (char) i;
- for (i = 'A'; i <= 'Z'; i++)
- lkp[i] = (char) (i + ('a' - 'A'));
- for (i = 'Z' + 1; i < 127; i++)
- lkp[i] = (char) i;
- for (i = 128; i < 256; i++)
- lkp[i] = '#';
-
- lkp['.'] = '_';
- while (*spc != '\0')
- lkp[(unsigned char) (*spc++)] = '#';
- }
- /* GLU
- * File names longer than 8+'.'+3 are invalid for MS-DOS,
- * so the file name is to be mangled--no further test is needed.
- * This speeds up handling of long names.
- * The position of the last point is no more necessary anyway.
- */
- if (len <= (8 + 1 + 3)) {
- const char *pt = fname;
- const char *endpt = fname + len;
-
- while (pt < endpt) {
- if (*pt == '.') {
- if (firstpt != NULL) {
- /* 2 . in a file name. Reject */
- ivldchar = 1;
- break;
- } else {
- int extlen = (int) (endpt - pt);
-
- firstpt = pt;
- if (firstpt - fname > 8) {
- /* base name longer than 8: reject */
- ivldchar = 1;
- break;
- } else if (extlen > 4) {
- /* Extension longer than 4 (including .): reject */
- ivldchar = 1;
- break;
- } else if (extlen == 1) {
- /* #Specification: file name / non MSDOS conforming / last char == .
- * If the last character of a file name is
- * a period, mangling is applied. MS-DOS does
- * not support those file names.
- */
- ivldchar = 1;
- break;
- } else if (extlen == 4) {
- /* #Specification: file name / non MSDOS conforming / mangling clash
- * To avoid clash with the umsdos mangling, any file
- * with a special character as the first character
- * of the extension will be mangled. This solves the
- * following problem:
- *
- * #
- * touch FILE
- * # FILE is invalid for DOS, so mangling is applied
- * # file.{_1 is created in the DOS directory
- * touch file.{_1
- * # To UMSDOS file point to a single DOS entry.
- * # So file.{_1 has to be mangled.
- * #
- */
- static char special[] =
- {
- SPECIAL_MANGLING, '\0'
- };
-
- if (strchr (special, firstpt[1]) != NULL) {
- ivldchar = 1;
- break;
- }
- }
- }
- } else if (lkp[(unsigned char) (*pt)] != *pt) {
- ivldchar = 1;
- break;
- }
- pt++;
- }
- } else {
- ivldchar = 1;
- }
- if (ivldchar
- || (firstpt == NULL && len > 8)
- || (len == UMSDOS_EMD_NAMELEN
- && memcmp (fname, UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN) == 0)) {
- /* #Specification: file name / --linux-.---
- * The name of the EMD file --linux-.--- is map to a mangled
- * name. So UMSDOS does not restrict its use.
- */
- /* #Specification: file name / non MSDOS conforming / mangling
- * Non MSDOS conforming file names must use some alias to fit
- * in the MSDOS name space.
- *
- * The strategy is simple. The name is simply truncated to
- * 8 char. points are replace with underscore and a
- * number is given as an extension. This number correspond
- * to the entry number in the EMD file. The EMD file
- * only need to carry the real name.
- *
- * Upper case is also converted to lower case.
- * Control character are converted to #.
- * Spaces are converted to #.
- * The following characters are also converted to #.
- * #
- * " * + , / : ; < = > ? [ \ ] | ~
- * #
- *
- * Sometimes the problem is not in MS-DOS itself but in
- * command.com.
- */
- int i;
- char *pt = info->fake.fname;
-
- base_len = msdos_len = (msdos_len > 8) ? 8 : msdos_len;
- /*
- * There is no '.' any more so we know for a fact that
- * the base length is the length.
- */
- memcpy (info->fake.fname, fname, msdos_len);
- for (i = 0; i < msdos_len; i++, pt++)
- *pt = lkp[(unsigned char) (*pt)];
- *pt = '\0'; /* GLU We force null termination. */
- info->msdos_reject = 1;
- /*
- * The numeric extension is added only when we know
- * the position in the EMD file, in umsdos_newentry(),
- * umsdos_delentry(), and umsdos_findentry().
- * See umsdos_manglename().
- */
- } else {
- /* Conforming MSDOS file name */
- strncpy (info->fake.fname, fname, len);
- info->msdos_reject = 0;
- base_len = firstpt != NULL ? (int) (firstpt - fname) : len;
- }
- if (cardinal_per_size[base_len]) {
- /* #Specification: file name / MSDOS devices / mangling
- * To avoid unreachable file from MS-DOS, any MS-DOS conforming
- * file with a basename equal to one of the MS-DOS pseudo
- * devices will be mangled.
- *
- * If a file such as "prn" was created, it would be unreachable
- * under MS-DOS because "prn" is assumed to be the printer, even
- * if the file does have an extension.
- *
- * Since the extension is unimportant to MS-DOS, we must patch
- * the basename also. We simply insert a minus '-'. To avoid
- * conflict with valid file with a minus in front (such as
- * "-prn"), we add an mangled extension like any other
- * mangled file name.
- *
- * Here is the list of DOS pseudo devices:
- *
- * #
- * "prn","con","aux","nul",
- * "lpt1","lpt2","lpt3","lpt4",
- * "com1","com2","com3","com4",
- * "clock$"
- * #
- *
- * and some standard ones for common DOS programs
- *
- * "emmxxxx0","xmsxxxx0","setverxx"
- *
- * (Thanks to Chris Hall <cah17@phoenix.cambridge.ac.uk>
- * for pointing these out to me).
- *
- * Is there one missing?
- */
- /* This table must be ordered by length */
- static const char *tbdev[] =
- {
- "prn", "con", "aux", "nul",
- "lpt1", "lpt2", "lpt3", "lpt4",
- "com1", "com2", "com3", "com4",
- "clock$",
- "emmxxxx0", "xmsxxxx0", "setverxx"
- };
-
- /* Tell where to find in tbdev[], the first name of */
- /* a certain length */
- static const char start_ind_dev[9] =
- {
- 0, 0, 0, 4, 12, 12, 13, 13, 16
- };
- char basen[9];
- int i;
-
- for (i = start_ind_dev[base_len - 1]; i < start_ind_dev[base_len]; i++) {
- if (memcmp (info->fake.fname, tbdev[i], base_len) == 0) {
- memcpy (basen, info->fake.fname, base_len);
- basen[base_len] = '\0'; /* GLU We force null termination. */
- /*
- * GLU We do that only if necessary; we try to do the
- * GLU simple thing in the usual circumstance.
- */
- info->fake.fname[0] = '-';
- strcpy (info->fake.fname + 1, basen); /* GLU We already guaranteed a null would be at the end. */
- msdos_len = (base_len == 8) ? 8 : base_len + 1;
- info->msdos_reject = 1;
- break;
- }
- }
- }
- info->fake.fname[msdos_len] = '\0'; /* Help doing printk */
- /* GLU This zero should (always?) be there already. */
- info->fake.len = msdos_len;
- /* Why not use info->fake.len everywhere? Is it longer?
- */
- memcpy (info->entry.name, fname, len);
- info->entry.name[len] = '\0'; /* for printk */
- info->entry.name_len = len;
- ret = 0;
- }
- /*
- * Evaluate how many records are needed to store this entry.
- */
- info->recsize = umsdos_evalrecsize (len);
- return ret;
-}
-
-#ifdef TEST
-
-struct MANG_TEST {
- char *fname; /* Name to validate */
- int msdos_reject; /* Expected msdos_reject flag */
- char *msname; /* Expected msdos name */
-};
-
-struct MANG_TEST tb[] =
-{
- "hello", 0, "hello",
- "hello.1", 0, "hello.1",
- "hello.1_", 0, "hello.1_",
- "prm", 0, "prm",
-
-#ifdef PROPOSITION
- "HELLO", 1, "hello",
- "Hello.1", 1, "hello.1",
- "Hello.c", 1, "hello.c",
-#else
-/*
- * I find the three examples below very unfortunate. I propose to
- * convert them to lower case in a quick preliminary pass, then test
- * whether there are other troublesome characters. I have not made
- * this change, because it is not easy, but I wanted to mention the
- * principle. Obviously something like that would increase the chance
- * of collisions, for example between "HELLO" and "Hello", but these
- * can be treated elsewhere along with the other collisions.
- */
-
- "HELLO", 1, "hello",
- "Hello.1", 1, "hello_1",
- "Hello.c", 1, "hello_c",
-#endif
-
- "hello.{_1", 1, "hello_{_",
- "hello\t", 1, "hello#",
- "hello.1.1", 1, "hello_1_",
- "hel,lo", 1, "hel#lo",
- "Salut.Tu.vas.bien?", 1, "salut_tu",
- ".profile", 1, "_profile",
- ".xv", 1, "_xv",
- "toto.", 1, "toto_",
- "clock$.x", 1, "-clock$",
- "emmxxxx0", 1, "-emmxxxx",
- "emmxxxx0.abcd", 1, "-emmxxxx",
- "aux", 1, "-aux",
- "prn", 1, "-prn",
- "prn.abc", 1, "-prn",
- "PRN", 1, "-prn",
- /*
- * GLU WARNING: the results of these are different with my version
- * GLU of mangling compared to the original one.
- * GLU CAUSE: the manner of calculating the baselen variable.
- * GLU For you they are always 3.
- * GLU For me they are respectively 7, 8, and 8.
-
- */
- "PRN.abc", 1, "prn_abc",
- "Prn.abcd", 1, "prn_abcd",
- "prn.abcd", 1, "prn_abcd",
- "Prn.abcdefghij", 1, "prn_abcd"
-};
-
-int main (int argc, char *argv[])
-{
- int i, rold, rnew;
-
- printf ("Testing the umsdos_parse.\n");
- for (i = 0; i < sizeof (tb) / sizeof (tb[0]); i++) {
- struct MANG_TEST *pttb = tb + i;
- struct umsdos_info info;
- int ok = umsdos_parse (pttb->fname, strlen (pttb->fname), &info);
-
- if (strcmp (info.fake.fname, pttb->msname) != 0) {
- printf ("**** %s -> ", pttb->fname);
- printf ("%s <> %s\n", info.fake.fname, pttb->msname);
- } else if (info.msdos_reject != pttb->msdos_reject) {
- printf ("**** %s -> %s ", pttb->fname, pttb->msname);
- printf ("%d <> %d\n", info.msdos_reject, pttb->msdos_reject);
- } else {
- printf (" %s -> %s %d\n", pttb->fname, pttb->msname
- ,pttb->msdos_reject);
- }
- }
- printf ("Testing the new umsdos_evalrecsize.");
- for (i = 0; i < UMSDOS_MAXNAME; i++) {
- rnew = umsdos_evalrecsize (i);
- rold = umsdos_evalrecsize_old (i);
- if (!(i % UMSDOS_REC_SIZE)) {
- printf ("\n%d:\t", i);
- }
- if (rnew != rold) {
- printf ("**** %d newres: %d != %d \n", i, rnew, rold);
- } else {
- printf (".");
- }
- }
- printf ("\nEnd of Testing.\n");
-
- return 0;
-}
-
-#endif
diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c
deleted file mode 100644
index 2d8a64af1aed..000000000000
--- a/fs/umsdos/namei.c
+++ /dev/null
@@ -1,1124 +0,0 @@
-/*
- * linux/fs/umsdos/namei.c
- *
- * Written 1993 by Jacques Gelinas
- * Inspired from linux/fs/msdos/... by Werner Almesberger
- *
- * Maintain and access the --linux alternate directory file.
- */
- /*
- * You are in the maze of twisted functions - half of them shouldn't
- * be here...
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/msdos_fs.h>
-#include <linux/umsdos_fs.h>
-#include <linux/slab.h>
-
-#define UMSDOS_DIR_LOCK
-
-#ifdef UMSDOS_DIR_LOCK
-
-static inline void u_sleep_on (struct inode *dir)
-{
- sleep_on (&UMSDOS_I(dir)->dir_info.p);
-}
-
-static inline void u_wake_up (struct inode *dir)
-{
- wake_up (&UMSDOS_I(dir)->dir_info.p);
-}
-
-/*
- * Wait for creation exclusivity.
- * Return 0 if the dir was already available.
- * Return 1 if a wait was necessary.
- * When 1 is return, it means a wait was done. It does not
- * mean the directory is available.
- */
-static int umsdos_waitcreate (struct inode *dir)
-{
- int ret = 0;
-
- if (UMSDOS_I(dir)->dir_info.creating
- && UMSDOS_I(dir)->dir_info.pid != current->pid) {
- PRINTK (("creating && dir_info.pid=%lu, current->pid=%u\n", UMSDOS_I(dir)->dir_info.pid, current->pid));
- u_sleep_on (dir);
- ret = 1;
- }
- return ret;
-}
-
-/*
- * Wait for any lookup process to finish
- */
-static void umsdos_waitlookup (struct inode *dir)
-{
- while (UMSDOS_I(dir)->dir_info.looking) {
- u_sleep_on (dir);
- }
-}
-
-/*
- * Lock all other process out of this directory.
- */
-/* #Specification: file creation / not atomic
- * File creation is a two step process. First we create (allocate)
- * an entry in the EMD file and then (using the entry offset) we
- * build a unique name for MSDOS. We create this name in the msdos
- * space.
- *
- * We have to use semaphore (sleep_on/wake_up) to prevent lookup
- * into a directory when we create a file or directory and to
- * prevent creation while a lookup is going on. Since many lookup
- * may happen at the same time, the semaphore is a counter.
- *
- * Only one creation is allowed at the same time. This protection
- * may not be necessary. The problem arise mainly when a lookup
- * or a readdir is done while a file is partially created. The
- * lookup process see that as a "normal" problem and silently
- * erase the file from the EMD file. Normal because a file
- * may be erased during a MSDOS session, but not removed from
- * the EMD file.
- *
- * The locking is done on a directory per directory basis. Each
- * directory inode has its wait_queue.
- *
- * For some operation like hard link, things even get worse. Many
- * creation must occur at once (atomic). To simplify the design
- * a process is allowed to recursively lock the directory for
- * creation. The pid of the locking process is kept along with
- * a counter so a second level of locking is granted or not.
- */
-void umsdos_lockcreate (struct inode *dir)
-{
- /*
- * Wait for any creation process to finish except
- * if we (the process) own the lock
- */
- while (umsdos_waitcreate (dir) != 0);
- UMSDOS_I(dir)->dir_info.creating++;
- UMSDOS_I(dir)->dir_info.pid = current->pid;
- umsdos_waitlookup (dir);
-}
-
-/*
- * Lock all other process out of those two directories.
- */
-static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2)
-{
- /*
- * We must check that both directory are available before
- * locking anyone of them. This is to avoid some deadlock.
- * Thanks to dglaude@is1.vub.ac.be (GLAUDE DAVID) for pointing
- * this to me.
- */
- while (1) {
- if (umsdos_waitcreate (dir1) == 0
- && umsdos_waitcreate (dir2) == 0) {
- /* We own both now */
- UMSDOS_I(dir1)->dir_info.creating++;
- UMSDOS_I(dir1)->dir_info.pid = current->pid;
- UMSDOS_I(dir2)->dir_info.creating++;
- UMSDOS_I(dir2)->dir_info.pid = current->pid;
- break;
- }
- }
- umsdos_waitlookup (dir1);
- umsdos_waitlookup (dir2);
-}
-
-/*
- * Wait until creation is finish in this directory.
- */
-void umsdos_startlookup (struct inode *dir)
-{
- while (umsdos_waitcreate (dir) != 0);
- UMSDOS_I(dir)->dir_info.looking++;
-}
-
-/*
- * Unlock the directory.
- */
-void umsdos_unlockcreate (struct inode *dir)
-{
- UMSDOS_I(dir)->dir_info.creating--;
- if (UMSDOS_I(dir)->dir_info.creating < 0) {
- printk ("UMSDOS: UMSDOS_I(dir)->dir_info.creating < 0: %d"
- ,UMSDOS_I(dir)->dir_info.creating);
- }
- u_wake_up (dir);
-}
-
-/*
- * Tell directory lookup is over.
- */
-void umsdos_endlookup (struct inode *dir)
-{
- UMSDOS_I(dir)->dir_info.looking--;
- if (UMSDOS_I(dir)->dir_info.looking < 0) {
- printk ("UMSDOS: UMSDOS_I(dir)->dir_info.looking < 0: %d"
- ,UMSDOS_I(dir)->dir_info.looking);
- }
- u_wake_up (dir);
-}
-
-#else
-static void umsdos_lockcreate (struct inode *dir)
-{
-}
-static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2)
-{
-}
-void umsdos_startlookup (struct inode *dir)
-{
-}
-static void umsdos_unlockcreate (struct inode *dir)
-{
-}
-void umsdos_endlookup (struct inode *dir)
-{
-}
-
-#endif
-
-static int umsdos_nevercreat (struct inode *dir, struct dentry *dentry,
- int errcod)
-{
- int ret = 0;
-
- if (umsdos_is_pseudodos (dir, dentry)) {
- /* #Specification: pseudo root / any file creation /DOS
- * The pseudo sub-directory /DOS can't be created!
- * EEXIST is returned.
- *
- * The pseudo sub-directory /DOS can't be removed!
- * EPERM is returned.
- */
- ret = errcod;
- }
- return ret;
-}
-
-/*
- * Add a new file (ordinary or special) into the alternate directory.
- * The file is added to the real MSDOS directory. If successful, it
- * is then added to the EMD file.
- *
- * Return the status of the operation. 0 mean success.
- *
- * #Specification: create / file exists in DOS
- * Here is a situation: we are trying to create a file with
- * UMSDOS. The file is unknown to UMSDOS but already
- * exists in the DOS directory.
- *
- * Here is what we are NOT doing:
- *
- * We could silently assume that everything is fine
- * and allows the creation to succeed.
- *
- * It is possible not all files in the partition
- * are meant to be visible from linux. By trying to create
- * those file in some directory, one user may get access
- * to those file without proper permissions. Looks like
- * a security hole to me. Off course sharing a file system
- * with DOS is some kind of security hole :-)
- *
- * So ?
- *
- * We return EEXIST in this case.
- * The same is true for directory creation.
- */
-static int umsdos_create_any (struct inode *dir, struct dentry *dentry,
- int mode, dev_t rdev, char flags)
-{
- struct dentry *fake;
- struct inode *inode;
- int ret;
- struct umsdos_info info;
-
- ret = umsdos_nevercreat (dir, dentry, -EEXIST);
- if (ret)
- goto out;
-
- ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
- if (ret)
- goto out;
-
- info.entry.mode = mode;
- info.entry.rdev = rdev;
- info.entry.flags = flags;
- info.entry.uid = current->fsuid;
- info.entry.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
- info.entry.ctime = info.entry.atime = info.entry.mtime = get_seconds();
- info.entry.nlink = 1;
- ret = umsdos_newentry (dentry->d_parent, &info);
- if (ret)
- goto out;
-
- /* do a real lookup to get the short name dentry */
- fake = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
- ret = PTR_ERR(fake);
- if (IS_ERR(fake))
- goto out_remove;
-
- /* should not exist yet ... */
- ret = -EEXIST;
- if (fake->d_inode)
- goto out_remove_dput;
-
- ret = msdos_create (dir, fake, S_IFREG | 0777, NULL);
- if (ret)
- goto out_remove_dput;
-
- inode = fake->d_inode;
- atomic_inc(&inode->i_count);
- d_instantiate (dentry, inode);
- dput(fake);
- if (atomic_read(&inode->i_count) > 1) {
- printk(KERN_WARNING
- "umsdos_create_any: %s/%s, ino=%ld, icount=%d??\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- inode->i_ino, atomic_read(&inode->i_count));
- }
- umsdos_lookup_patch_new(dentry, &info);
-
-out:
- return ret;
-
- /* Creation failed ... remove the EMD entry */
-out_remove_dput:
- dput(fake);
-out_remove:
- if (ret == -EEXIST)
- printk(KERN_WARNING "UMSDOS: out of sync, deleting %s/%s\n",
- dentry->d_parent->d_name.name, info.fake.fname);
- umsdos_delentry (dentry->d_parent, &info, S_ISDIR (info.entry.mode));
- goto out;
-}
-
-/*
- * Add a new file into the alternate directory.
- * The file is added to the real MSDOS directory. If successful, it
- * is then added to the EMD file.
- *
- * Return the status of the operation. 0 mean success.
- */
-int UMSDOS_create (struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
-{
- return umsdos_create_any (dir, dentry, mode, 0, 0);
-}
-
-
-/*
- * Initialise the new_entry from the old for a rename operation.
- * (Only useful for umsdos_rename_f() below).
- */
-static void umsdos_ren_init (struct umsdos_info *new_info,
- struct umsdos_info *old_info)
-{
- new_info->entry.mode = old_info->entry.mode;
- new_info->entry.rdev = old_info->entry.rdev;
- new_info->entry.uid = old_info->entry.uid;
- new_info->entry.gid = old_info->entry.gid;
- new_info->entry.ctime = old_info->entry.ctime;
- new_info->entry.atime = old_info->entry.atime;
- new_info->entry.mtime = old_info->entry.mtime;
- new_info->entry.flags = old_info->entry.flags;
- new_info->entry.nlink = old_info->entry.nlink;
-}
-
-/*
- * Rename a file (move) in the file system.
- */
-
-static int umsdos_rename_f (struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry,
- int flags)
-{
- struct inode *old_inode = old_dentry->d_inode;
- struct dentry *old, *new, *old_emd;
- int err, ret;
- struct umsdos_info old_info;
- struct umsdos_info new_info;
-
- ret = -EPERM;
- err = umsdos_parse (old_dentry->d_name.name,
- old_dentry->d_name.len, &old_info);
- if (err)
- goto out;
- err = umsdos_parse (new_dentry->d_name.name,
- new_dentry->d_name.len, &new_info);
- if (err)
- goto out;
-
- /* Get the EMD dentry for the old parent */
- old_emd = umsdos_get_emd_dentry(old_dentry->d_parent);
- ret = PTR_ERR(old_emd);
- if (IS_ERR(old_emd))
- goto out;
-
- umsdos_lockcreate2 (old_dir, new_dir);
-
- ret = umsdos_findentry(old_emd->d_parent, &old_info, 0);
- if (ret)
- goto out_unlock;
-
- err = umsdos_findentry(new_dentry->d_parent, &new_info, 0);
- if (err == 0) {
- /* check whether it _really_ exists ... */
- ret = -EEXIST;
- if (new_dentry->d_inode)
- goto out_unlock;
-
- /* bogus lookup? complain and fix up the EMD ... */
- printk(KERN_WARNING
- "umsdos_rename_f: entry %s/%s exists, inode NULL??\n",
- new_dentry->d_parent->d_name.name, new_info.entry.name);
- err = umsdos_delentry(new_dentry->d_parent, &new_info,
- S_ISDIR(new_info.entry.mode));
- }
-
- umsdos_ren_init (&new_info, &old_info);
- if (flags)
- new_info.entry.flags = flags;
- ret = umsdos_newentry (new_dentry->d_parent, &new_info);
- if (ret)
- goto out_unlock;
-
- /* If we're moving a hardlink, drop it first */
- if (old_info.entry.flags & UMSDOS_HLINK) {
- d_drop(old_dentry);
- }
-
- old = umsdos_covered(old_dentry->d_parent, old_info.fake.fname,
- old_info.fake.len);
- ret = PTR_ERR(old);
- if (IS_ERR(old))
- goto out_unlock;
- /* make sure it's the same inode! */
- ret = -ENOENT;
- /*
- * note: for hardlinks they will be different!
- * old_inode will contain inode of .LINKxxx file containing data, and
- * old->d_inode will contain inode of file containing path to .LINKxxx file
- */
- if (!(old_info.entry.flags & UMSDOS_HLINK)) {
- if (old->d_inode != old_inode)
- goto out_dput;
- }
-
- new = umsdos_covered(new_dentry->d_parent, new_info.fake.fname,
- new_info.fake.len);
- ret = PTR_ERR(new);
- if (IS_ERR(new))
- goto out_dput;
-
- /* Do the msdos-level rename */
- ret = msdos_rename (old_dir, old, new_dir, new);
-
- dput(new);
-
- /* If the rename failed, remove the new EMD entry */
- if (ret != 0) {
- umsdos_delentry (new_dentry->d_parent, &new_info,
- S_ISDIR (new_info.entry.mode));
- goto out_dput;
- }
-
- /*
- * Rename successful ... remove the old name from the EMD.
- * Note that we use the EMD parent here, as the old dentry
- * may have moved to a new parent ...
- */
- err = umsdos_delentry (old_emd->d_parent, &old_info,
- S_ISDIR (old_info.entry.mode));
- if (err) {
- /* Failed? Complain a bit, but don't fail the operation */
- printk(KERN_WARNING
- "umsdos_rename_f: delentry %s/%s failed, error=%d\n",
- old_emd->d_parent->d_name.name, old_info.entry.name,
- err);
- }
-
- /*
- * Update f_pos so notify_change will succeed
- * if the file was already in use.
- */
- umsdos_set_dirinfo_new(old_dentry, new_info.f_pos);
-
- /* dput() the dentry if we haven't already */
-out_dput:
- dput(old);
-
-out_unlock:
- dput(old_emd);
- umsdos_unlockcreate (old_dir);
- umsdos_unlockcreate (new_dir);
-
-out:
- Printk ((" _ret=%d\n", ret));
- return ret;
-}
-
-/*
- * Setup a Symbolic link or a (pseudo) hard link
- * Return a negative error code or 0 if OK.
- */
-/* #Specification: symbolic links / strategy
- * A symbolic link is simply a file which holds a path. It is
- * implemented as a normal MSDOS file (not very space efficient :-()
- *
- * I see two different ways to do this: One is to place the link data
- * in unused entries of the EMD file; the other is to have a separate
- * file dedicated to hold all symbolic links data.
- *
- * Let's go for simplicity...
- */
-
-/*
- * AV. Should be called with dir->i_sem down.
- */
-static int umsdos_symlink_x (struct inode *dir, struct dentry *dentry,
- const char *symname, int mode, char flags)
-{
- int ret, len;
-
- ret = umsdos_create_any (dir, dentry, mode, 0, flags);
- if (ret) {
- printk(KERN_WARNING
- "umsdos_symlink: create failed, ret=%d\n", ret);
- goto out;
- }
-
- len = strlen (symname) + 1;
- ret = page_symlink(dentry->d_inode, symname, len);
- if (ret < 0)
- goto out_unlink;
-out:
- return ret;
-
-out_unlink:
- printk(KERN_WARNING "umsdos_symlink: write failed, unlinking\n");
- UMSDOS_unlink (dir, dentry);
- d_drop(dentry);
- goto out;
-}
-
-/*
- * Setup a Symbolic link.
- * Return a negative error code or 0 if OK.
- */
-int UMSDOS_symlink ( struct inode *dir, struct dentry *dentry,
- const char *symname)
-{
- return umsdos_symlink_x (dir, dentry, symname, S_IFLNK | 0777, 0);
-}
-
-/*
- * Add a link to an inode in a directory
- */
-int UMSDOS_link (struct dentry *olddentry, struct inode *dir,
- struct dentry *dentry)
-{
- struct inode *oldinode = olddentry->d_inode;
- struct inode *olddir = olddentry->d_parent->d_inode;
- struct dentry *temp;
- char *path;
- unsigned long buffer;
- int ret;
- struct umsdos_info old_info;
- struct umsdos_info hid_info;
-
-#ifdef UMSDOS_DEBUG_VERBOSE
-printk("umsdos_link: new %s/%s -> %s/%s\n",
-dentry->d_parent->d_name.name, dentry->d_name.name,
-olddentry->d_parent->d_name.name, olddentry->d_name.name);
-#endif
-
- ret = -EPERM;
- if (S_ISDIR (oldinode->i_mode))
- goto out;
-
- ret = umsdos_nevercreat (dir, dentry, -EPERM);
- if (ret)
- goto out;
-
- ret = -ENOMEM;
- buffer = get_zeroed_page(GFP_KERNEL);
- if (!buffer)
- goto out;
-
- /*
- * Lock the link parent if it's not the same directory.
- */
- ret = -EDEADLOCK;
- if (olddir != dir) {
- if (atomic_read(&olddir->i_sem.count) < 1)
- goto out_free;
- down(&olddir->i_sem);
- }
-
- /*
- * Parse the name and get the visible directory entry.
- */
- ret = umsdos_parse (olddentry->d_name.name, olddentry->d_name.len,
- &old_info);
- if (ret)
- goto out_unlock;
- ret = umsdos_findentry (olddentry->d_parent, &old_info, 1);
- if (ret) {
-printk("UMSDOS_link: %s/%s not in EMD, ret=%d\n",
-olddentry->d_parent->d_name.name, olddentry->d_name.name, ret);
- goto out_unlock;
- }
-
- /*
- * If the visible dentry is a pseudo-hardlink, the original
- * file must be already hidden.
- */
- if (!(old_info.entry.flags & UMSDOS_HLINK)) {
- int err;
-
- /* create a hidden link name */
- ret = umsdos_newhidden (olddentry->d_parent, &hid_info);
- if (ret) {
-printk("umsdos_link: can't make hidden %s/%s, ret=%d\n",
-olddentry->d_parent->d_name.name, hid_info.entry.name, ret);
- goto out_unlock;
- }
-
- /*
- * Make a dentry and rename the original file ...
- */
- temp = umsdos_lookup_dentry(olddentry->d_parent,
- hid_info.entry.name,
- hid_info.entry.name_len, 0);
- ret = PTR_ERR(temp);
- if (IS_ERR(temp)) {
-printk("umsdos_link: lookup %s/%s failed, ret=%d\n",
-dentry->d_parent->d_name.name, hid_info.entry.name, ret);
- goto cleanup;
- }
- /* rename the link to the hidden location ... */
- ret = umsdos_rename_f(olddir, olddentry, olddir, temp,
- UMSDOS_HIDDEN);
- d_move(olddentry, temp);
- dput(temp);
- if (ret) {
-printk("umsdos_link: rename to %s/%s failed, ret=%d\n",
-temp->d_parent->d_name.name, temp->d_name.name, ret);
- goto cleanup;
- }
- /* mark the inode as a hardlink */
- UMSDOS_I(oldinode)->i_is_hlink = 1;
-
- /*
- * Capture the path to the hidden link.
- */
- path = umsdos_d_path(olddentry, (char *) buffer, PAGE_SIZE);
-Printk(("umsdos_link: hidden link path=%s\n", path));
-
- /*
- * Recreate a dentry for the original name and symlink it,
- * then symlink the new dentry. Don't give up if one fails,
- * or we'll lose the file completely!
- *
- * Note: this counts as the "original" reference, so we
- * don't increment i_nlink for this one.
- */
- temp = umsdos_lookup_dentry(olddentry->d_parent,
- old_info.entry.name,
- old_info.entry.name_len, 0);
- ret = PTR_ERR(temp);
- if (!IS_ERR(temp)) {
- ret = umsdos_symlink_x (olddir, temp, path,
- S_IFREG | 0777, UMSDOS_HLINK);
- dput(temp);
- }
-
- /* This symlink increments i_nlink (see below.) */
- err = umsdos_symlink_x (dir, dentry, path,
- S_IFREG | 0777, UMSDOS_HLINK);
- /* fold the two errors */
- if (!ret)
- ret = err;
- goto out_unlock;
-
- /* creation failed ... remove the link entry */
- cleanup:
-printk("umsdos_link: link failed, ret=%d, removing %s/%s\n",
-ret, olddentry->d_parent->d_name.name, hid_info.entry.name);
- err = umsdos_delentry(olddentry->d_parent, &hid_info, 0);
- goto out_unlock;
- }
-
-Printk(("UMSDOS_link: %s/%s already hidden\n",
-olddentry->d_parent->d_name.name, olddentry->d_name.name));
- /*
- * The original file is already hidden, and we need to get
- * the dentry for its real name, not the visible name.
- * N.B. make sure it's the hidden inode ...
- */
- if (!UMSDOS_I(oldinode)->i_is_hlink)
- printk("UMSDOS_link: %s/%s hidden, ino=%ld not hlink??\n",
- olddentry->d_parent->d_name.name,
- olddentry->d_name.name, oldinode->i_ino);
-
- /*
- * In order to get the correct (real) inode, we just drop
- * the original dentry.
- */
- d_drop(olddentry);
-Printk(("UMSDOS_link: hard link %s/%s, fake=%s\n",
-olddentry->d_parent->d_name.name, olddentry->d_name.name, old_info.fake.fname));
-
- /* Do a real lookup to get the short name dentry */
- temp = umsdos_covered(olddentry->d_parent, old_info.fake.fname,
- old_info.fake.len);
- ret = PTR_ERR(temp);
- if (IS_ERR(temp))
- goto out_unlock;
-
- /* now resolve the link ... */
- temp = umsdos_solve_hlink(temp);
- ret = PTR_ERR(temp);
- if (IS_ERR(temp))
- goto out_unlock;
- path = umsdos_d_path(temp, (char *) buffer, PAGE_SIZE);
- dput(temp);
-Printk(("umsdos_link: %s/%s already hidden, path=%s\n",
-olddentry->d_parent->d_name.name, olddentry->d_name.name, path));
-
- /* finally we can symlink it ... */
- ret = umsdos_symlink_x (dir, dentry, path, S_IFREG | 0777,UMSDOS_HLINK);
-
-out_unlock:
- /* remain locked for the call to notify_change ... */
- if (ret == 0) {
- struct iattr newattrs;
-
- /* Do a real lookup to get the short name dentry */
- temp = umsdos_covered(olddentry->d_parent,
- old_info.fake.fname,
- old_info.fake.len);
- ret = PTR_ERR(temp);
- if (IS_ERR(temp))
- goto out_unlock2;
-
- /* now resolve the link ... */
- temp = umsdos_solve_hlink(temp);
- ret = PTR_ERR(temp);
- if (IS_ERR(temp))
- goto out_unlock2;
-
-
-#ifdef UMSDOS_PARANOIA
-if (!UMSDOS_I(oldinode)->i_is_hlink)
-printk("UMSDOS_link: %s/%s, ino=%ld, not marked as hlink!\n",
-olddentry->d_parent->d_name.name, olddentry->d_name.name, oldinode->i_ino);
-#endif
- temp->d_inode->i_nlink++;
-Printk(("UMSDOS_link: linked %s/%s, ino=%ld, nlink=%d\n",
-olddentry->d_parent->d_name.name, olddentry->d_name.name,
-oldinode->i_ino, oldinode->i_nlink));
- newattrs.ia_valid = 0;
- ret = umsdos_notify_change_locked(temp, &newattrs);
- if (ret == 0)
- mark_inode_dirty(temp->d_inode);
- dput(temp);
-out_unlock2:
- if (ret == 0)
- mark_inode_dirty(olddentry->d_inode);
- }
- if (olddir != dir)
- up(&olddir->i_sem);
-
-out_free:
- free_page(buffer);
-out:
- Printk (("umsdos_link %d\n", ret));
- return ret;
-}
-
-
-/*
- * Add a sub-directory in a directory
- */
-/* #Specification: mkdir / Directory already exist in DOS
- * We do the same thing as for file creation.
- * For all user it is an error.
- */
-/* #Specification: mkdir / umsdos directory / create EMD
- * When we created a new sub-directory in a UMSDOS
- * directory (one with full UMSDOS semantics), we
- * create immediately an EMD file in the new
- * sub-directory so it inherits UMSDOS semantics.
- */
-int UMSDOS_mkdir (struct inode *dir, struct dentry *dentry, int mode)
-{
- struct dentry *temp;
- struct inode *inode;
- int ret, err;
- struct umsdos_info info;
-
- ret = umsdos_nevercreat (dir, dentry, -EEXIST);
- if (ret)
- goto out;
-
- ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
- if (ret)
- goto out;
-
- info.entry.mode = mode | S_IFDIR;
- info.entry.rdev = 0;
- info.entry.uid = current->fsuid;
- info.entry.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
- info.entry.ctime = info.entry.atime = info.entry.mtime = get_seconds();
- info.entry.flags = 0;
- info.entry.nlink = 1;
- ret = umsdos_newentry (dentry->d_parent, &info);
- if (ret)
- goto out;
-
- /* lookup the short name dentry */
- temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
- ret = PTR_ERR(temp);
- if (IS_ERR(temp))
- goto out_remove;
-
- /* Make sure the short name doesn't exist */
- ret = -EEXIST;
- if (temp->d_inode) {
-printk("umsdos_mkdir: short name %s/%s exists\n",
-dentry->d_parent->d_name.name, info.fake.fname);
- goto out_remove_dput;
- }
-
- ret = msdos_mkdir (dir, temp, mode);
- if (ret)
- goto out_remove_dput;
-
- /*
- * Lock the inode to protect the EMD creation ...
- */
- inode = temp->d_inode;
- down(&inode->i_sem);
-
- atomic_inc(&inode->i_count);
- d_instantiate(dentry, inode);
-
- /* N.B. this should have an option to create the EMD ... */
- umsdos_lookup_patch_new(dentry, &info);
-
- /*
- * Create the EMD file, and set up the dir so it is
- * promoted to EMD with the EMD file invisible.
- *
- * N.B. error return if EMD fails?
- */
- err = umsdos_make_emd(dentry);
- umsdos_setup_dir(dentry);
-
- up(&inode->i_sem);
- dput(temp);
-
-out:
- Printk(("umsdos_mkdir: %s/%s, ret=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name, ret));
- return ret;
-
- /* an error occurred ... remove EMD entry. */
-out_remove_dput:
- dput(temp);
-out_remove:
- umsdos_delentry (dentry->d_parent, &info, 1);
- goto out;
-}
-
-/*
- * Add a new device special file into a directory.
- *
- * #Specification: Special files / strategy
- * Device special file, pipes, etc ... are created like normal
- * file in the msdos file system. Of course they remain empty.
- *
- * One strategy was to create those files only in the EMD file
- * since they were not important for MSDOS. The problem with
- * that, is that there were not getting inode number allocated.
- * The MSDOS filesystems is playing a nice game to fake inode
- * number, so why not use it.
- *
- * The absence of inode number compatible with those allocated
- * for ordinary files was causing major trouble with hard link
- * in particular and other parts of the kernel I guess.
- */
-int UMSDOS_mknod (struct inode *dir, struct dentry *dentry,
- int mode, dev_t rdev)
-{
- return umsdos_create_any (dir, dentry, mode, rdev, 0);
-}
-
-/*
- * Remove a sub-directory.
- */
-int UMSDOS_rmdir (struct inode *dir, struct dentry *dentry)
-{
- struct dentry *temp;
- int ret, err, empty;
- struct umsdos_info info;
-
- ret = umsdos_nevercreat (dir, dentry, -EPERM);
- if (ret)
- goto out;
-
- ret = -EBUSY;
- if (!d_unhashed(dentry))
- goto out;
-
- /* check whether the EMD is empty */
- ret = -ENOTEMPTY;
- empty = umsdos_isempty (dentry);
-
- /* Have to remove the EMD file? */
- if (empty == 1) {
- struct dentry *demd;
-
- demd = umsdos_get_emd_dentry(dentry);
- if (!IS_ERR(demd)) {
- err = -ENOENT;
- if (demd->d_inode)
- err = msdos_unlink (dentry->d_inode, demd);
-Printk (("UMSDOS_rmdir: unlinking empty EMD err=%d", err));
-#ifdef UMSDOS_PARANOIA
-if (err)
-printk("umsdos_rmdir: EMD %s/%s unlink failed, err=%d\n",
-demd->d_parent->d_name.name, demd->d_name.name, err);
-#endif
- if (!err) {
- d_delete(demd);
- ret = 0;
- }
- dput(demd);
- }
- } else if (empty == 2)
- ret = 0;
- if (ret)
- goto out;
-
- umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
- /* Call findentry to complete the mangling */
- umsdos_findentry (dentry->d_parent, &info, 2);
- temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
- ret = PTR_ERR(temp);
- if (IS_ERR(temp))
- goto out;
- /*
- * Attempt to remove the msdos name.
- */
- ret = msdos_rmdir (dir, temp);
- if (ret && ret != -ENOENT)
- goto out_dput;
-
- d_delete(temp);
- /* OK so far ... remove the name from the EMD */
- ret = umsdos_delentry (dentry->d_parent, &info, 1);
-#ifdef UMSDOS_PARANOIA
-if (ret)
-printk("umsdos_rmdir: delentry %s failed, ret=%d\n", info.entry.name, ret);
-#endif
-
- /* dput() temp if we didn't do it above */
-out_dput:
- dput(temp);
-
-out:
- Printk (("umsdos_rmdir %d\n", ret));
- return ret;
-}
-
-
-/*
- * Remove a file from the directory.
- *
- * #Specification: hard link / deleting a link
- * When we delete a file and this file is a link,
- * we must subtract 1 from the nlink field of the
- * hidden link.
- *
- * If the count goes to 0, we delete this hidden
- * link too.
- */
-int UMSDOS_unlink (struct inode *dir, struct dentry *dentry)
-{
- struct dentry *temp, *link = NULL;
- struct inode *inode;
- int ret;
- struct umsdos_info info;
-
-Printk(("UMSDOS_unlink: entering %s/%s\n",
-dentry->d_parent->d_name.name, dentry->d_name.name));
-
- ret = umsdos_nevercreat (dir, dentry, -EPERM);
- if (ret)
- goto out;
-
- ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
- if (ret)
- goto out;
-
- umsdos_lockcreate (dir);
- ret = umsdos_findentry (dentry->d_parent, &info, 1);
- if (ret) {
-printk("UMSDOS_unlink: %s/%s not in EMD, ret=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, ret);
- goto out_unlock;
- }
-
-Printk (("UMSDOS_unlink %.*s ", info.fake.len, info.fake.fname));
-
- /*
- * Note! If this is a hardlink and the names are aliased,
- * the short-name lookup will return the hardlink dentry.
- * In order to get the correct (real) inode, we just drop
- * the original dentry.
- */
- if (info.entry.flags & UMSDOS_HLINK) {
- d_drop(dentry);
- }
-
- /* Do a real lookup to get the short name dentry */
- temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
- ret = PTR_ERR(temp);
- if (IS_ERR(temp))
- goto out_unlock;
-
- /*
- * Resolve hardlinks now, but defer processing until later.
- */
- if (info.entry.flags & UMSDOS_HLINK) {
- link = umsdos_solve_hlink(dget(temp));
- }
-
- /* Delete the EMD entry */
- ret = umsdos_delentry (dentry->d_parent, &info, 0);
- if (ret && ret != -ENOENT) {
- printk(KERN_WARNING "UMSDOS_unlink: delentry %s, error=%d\n",
- info.entry.name, ret);
- goto out_dput;
- }
-
- ret = msdos_unlink(dir, temp);
- if (!ret)
- d_delete(temp);
-#ifdef UMSDOS_PARANOIA
-if (ret)
-printk("umsdos_unlink: %s/%s unlink failed, ret=%d\n",
-temp->d_parent->d_name.name, temp->d_name.name, ret);
-#endif
-
- /* dput() temp if we didn't do it above */
-out_dput:
- dput(temp);
-
-out_unlock:
- umsdos_unlockcreate (dir);
-
- /*
- * Now check for deferred handling of a hardlink.
- */
- if (!link)
- goto out;
-
- if (IS_ERR(link)) {
-printk("umsdos_unlink: failed to resolve %s/%s\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
- if (!ret)
- ret = PTR_ERR(link);
- goto out;
- }
-
-Printk(("umsdos_unlink: link %s/%s deferred, pending ret=%d\n",
-link->d_parent->d_name.name, link->d_name.name, ret));
-
- /* already have an error? */
- if (ret)
- goto out_cleanup;
-
- /* make sure the link exists ... */
- inode = link->d_inode;
- if (!inode) {
- printk(KERN_WARNING "umsdos_unlink: hard link not found\n");
- goto out_cleanup;
- }
-
- /*
- * If this was the last linked reference, delete it now.
- *
- * N.B. Deadlock problem? We should be holding the lock
- * for the hardlink's parent, but another process might
- * be holding that lock waiting for us to finish ...
- */
- if (inode->i_nlink <= 1) {
- ret = UMSDOS_unlink (link->d_parent->d_inode, link);
- if (ret) {
- printk(KERN_WARNING
- "umsdos_unlink: link removal failed, ret=%d\n",
- ret);
- } else
- d_delete(link);
- } else {
- struct iattr newattrs;
- inode->i_nlink--;
- newattrs.ia_valid = 0;
- ret = umsdos_notify_change_locked(link, &newattrs);
- if (!ret)
- mark_inode_dirty(link->d_inode);
- }
-
-out_cleanup:
- d_drop(link);
- dput(link);
-
-out:
- Printk (("umsdos_unlink %d\n", ret));
- return ret;
-}
-
-/*
- * Rename (move) a file.
- */
-int UMSDOS_rename (struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
-{
- int ret;
-
- ret = umsdos_nevercreat (new_dir, new_dentry, -EEXIST);
- if (ret)
- return ret;
-
- /*
- * If the target already exists, delete it first.
- */
- if (new_dentry->d_inode) {
- dget(new_dentry);
- if (S_ISDIR(old_dentry->d_inode->i_mode))
- ret = UMSDOS_rmdir (new_dir, new_dentry);
- else
- ret = UMSDOS_unlink (new_dir, new_dentry);
- if (!ret)
- d_drop(new_dentry);
- dput(new_dentry);
- if (ret)
- return ret;
- }
- ret = umsdos_rename_f(old_dir, old_dentry, new_dir, new_dentry, 0);
- return ret;
-}
diff --git a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c
deleted file mode 100644
index 2f32539b1a37..000000000000
--- a/fs/umsdos/rdir.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * linux/fs/umsdos/rdir.c
- *
- * Written 1994 by Jacques Gelinas
- *
- * Extended MS-DOS directory pure MS-DOS handling functions
- * (For directory without EMD file).
- */
-
-#include <linux/time.h>
-#include <linux/fs.h>
-#include <linux/msdos_fs.h>
-#include <linux/errno.h>
-#include <linux/stat.h>
-#include <linux/limits.h>
-#include <linux/umsdos_fs.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-
-#include <asm/uaccess.h>
-
-
-extern struct dentry *saved_root;
-extern struct inode *pseudo_root;
-extern struct dentry_operations umsdos_dentry_operations;
-
-struct RDIR_FILLDIR {
- void *dirbuf;
- filldir_t filldir;
- int real_root;
-};
-
-static int rdir_filldir ( void *buf,
- const char *name,
- int name_len,
- loff_t offset,
- ino_t ino,
- unsigned int d_type)
-{
- int ret = 0;
- struct RDIR_FILLDIR *d = (struct RDIR_FILLDIR *) buf;
-
- if (d->real_root) {
- PRINTK ((KERN_DEBUG "rdir_filldir /mn/: real root!\n"));
- /* real root of a pseudo_rooted partition */
- if (name_len != UMSDOS_PSDROOT_LEN
- || memcmp (name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN) != 0) {
- /* So it is not the /linux directory */
- if (name_len == 2 && name[0] == '.' && name[1] == '.') {
- /* Make sure the .. entry points back to the pseudo_root */
- ino = pseudo_root->i_ino;
- }
- ret = d->filldir (d->dirbuf, name, name_len, offset, ino, DT_UNKNOWN);
- }
- } else {
- /* Any DOS directory */
- ret = d->filldir (d->dirbuf, name, name_len, offset, ino, DT_UNKNOWN);
- }
- return ret;
-}
-
-
-static int UMSDOS_rreaddir (struct file *filp, void *dirbuf, filldir_t filldir)
-{
- struct inode *dir = filp->f_dentry->d_inode;
- struct RDIR_FILLDIR bufk;
- int ret;
-
- lock_kernel();
- bufk.filldir = filldir;
- bufk.dirbuf = dirbuf;
- bufk.real_root = pseudo_root && (dir == saved_root->d_inode);
- ret = fat_readdir (filp, &bufk, rdir_filldir);
- unlock_kernel();
- return ret;
-}
-
-
-/*
- * Lookup into a non promoted directory.
- * If the result is a directory, make sure we find out if it is
- * a promoted one or not (calling umsdos_setup_dir_inode(inode)).
- */
-/* #Specification: pseudo root / DOS/..
- * In the real root directory (c:\), the directory ..
- * is the pseudo root (c:\linux).
- */
-struct dentry *umsdos_rlookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo)
-{
- struct dentry *ret;
-
- if (saved_root && dir == saved_root->d_inode && !nopseudo &&
- dentry->d_name.len == UMSDOS_PSDROOT_LEN &&
- memcmp (dentry->d_name.name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN) == 0) {
- /* #Specification: pseudo root / DOS/linux
- * Even in the real root directory (c:\), the directory
- * /linux won't show
- */
-
- ret = ERR_PTR(-ENOENT);
- goto out;
- }
-
- ret = msdos_lookup (dir, dentry, NULL);
- if (ret) {
- printk(KERN_WARNING
- "umsdos_rlookup_x: %s/%s failed, ret=%ld\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- PTR_ERR(ret));
- goto out;
- }
- if (dentry->d_inode) {
- /* We must install the proper function table
- * depending on whether this is an MS-DOS or
- * a UMSDOS directory
- */
-Printk ((KERN_DEBUG "umsdos_rlookup_x: patch_dentry_inode %s/%s\n",
-dentry->d_parent->d_name.name, dentry->d_name.name));
-/* only patch if needed (because we get called even for lookup
- (not only rlookup) stuff sometimes, like in umsdos_covered() */
- if (UMSDOS_I(dentry->d_inode)->i_patched == 0)
- umsdos_patch_dentry_inode(dentry, 0);
-
- }
-out:
- /* always install our dentry ops ... */
- dentry->d_op = &umsdos_dentry_operations;
- return ret;
-}
-
-
-struct dentry *UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
- return umsdos_rlookup_x (dir, dentry, 0);
-}
-
-
-/* #Specification: dual mode / rmdir in a DOS directory
- * In a DOS (not EMD in it) directory, we use a reverse strategy
- * compared with a UMSDOS directory. We assume that a subdirectory
- * of a DOS directory is also a DOS directory. This is not always
- * true (umssync may be used anywhere), but makes sense.
- *
- * So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
- * then we check if it is a Umsdos directory. We check if it is
- * really empty (only . .. and --linux-.--- in it). If it is true
- * we remove the EMD and do a msdos_rmdir() again.
- *
- * In a Umsdos directory, we assume all subdirectories are also
- * Umsdos directories, so we check the EMD file first.
- */
-/* #Specification: pseudo root / rmdir /DOS
- * The pseudo sub-directory /DOS can't be removed!
- * This is done even if the pseudo root is not a Umsdos
- * directory anymore (very unlikely), but an accident (under
- * MS-DOS) is always possible.
- *
- * EPERM is returned.
- */
-static int UMSDOS_rrmdir ( struct inode *dir, struct dentry *dentry)
-{
- int ret, empty;
-
- ret = -EPERM;
- if (umsdos_is_pseudodos (dir, dentry))
- goto out;
-
- ret = -EBUSY;
- if (!d_unhashed(dentry))
- goto out;
-
- ret = msdos_rmdir (dir, dentry);
- if (ret != -ENOTEMPTY)
- goto out;
-
- empty = umsdos_isempty (dentry);
- if (empty == 1) {
- struct dentry *demd;
- /* We have to remove the EMD file. */
- demd = umsdos_get_emd_dentry(dentry);
- ret = PTR_ERR(demd);
- if (!IS_ERR(demd)) {
- ret = 0;
- if (demd->d_inode)
- ret = msdos_unlink (dentry->d_inode, demd);
- if (!ret)
- d_delete(demd);
- dput(demd);
- }
- }
- if (ret)
- goto out;
-
- /* now retry the original ... */
- ret = msdos_rmdir (dir, dentry);
-
-out:
- return ret;
-}
-
-/* #Specification: dual mode / introduction
- * One goal of UMSDOS is to allow a practical and simple coexistence
- * between MS-DOS and Linux in a single partition. Using the EMD file
- * in each directory, UMSDOS adds Unix semantics and capabilities to
- * a normal DOS filesystem. To help and simplify coexistence, here is
- * the logic related to the EMD file.
- *
- * If it is missing, then the directory is managed by the MS-DOS driver.
- * The names are limited to DOS limits (8.3). No links, no device special
- * and pipe and so on.
- *
- * If it is there, it is the directory. If it is there but empty, then
- * the directory looks empty. The utility umssync allows synchronisation
- * of the real DOS directory and the EMD.
- *
- * Whenever umssync is applied to a directory without EMD, one is
- * created on the fly. The directory is promoted to full Unix semantics.
- * Of course, the ls command will show exactly the same content as before
- * the umssync session.
- *
- * It is believed that the user/admin will promote directories to Unix
- * semantics as needed.
- *
- * The strategy to implement this is to use two function table (struct
- * inode_operations). One for true UMSDOS directory and one for directory
- * with missing EMD.
- *
- * Functions related to the DOS semantic (but aware of UMSDOS) generally
- * have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate
- * from the one with full UMSDOS semantics.
- */
-struct file_operations umsdos_rdir_operations =
-{
- .read = generic_read_dir,
- .readdir = UMSDOS_rreaddir,
- .ioctl = UMSDOS_ioctl_dir,
-};
-
-struct inode_operations umsdos_rdir_inode_operations =
-{
- .create = msdos_create,
- .lookup = UMSDOS_rlookup,
- .unlink = msdos_unlink,
- .mkdir = msdos_mkdir,
- .rmdir = UMSDOS_rrmdir,
- .rename = msdos_rename,
- .setattr = UMSDOS_notify_change,
-};
diff --git a/fs/umsdos/specs b/fs/umsdos/specs
deleted file mode 100644
index 0f7d68c0aef6..000000000000
--- a/fs/umsdos/specs
+++ /dev/null
@@ -1,289 +0,0 @@
-/* #Specification: umsdos / readdir
- * umsdos_readdir() should fill a struct dirent with
- * an inode number. The cheap way to get it is to
- * do a lookup in the MSDOS directory for each
- * entry processed by the readdir() function.
- * This is not very efficient, but very simple. The
- * other way around is to maintain a copy of the inode
- * number in the EMD file. This is a problem because
- * this has to be maintained in sync using tricks.
- * Remember that MSDOS (the OS) does not update the
- * modification time (mtime) of a directory. There is
- * no easy way to tell that a directory was modified
- * during a DOS session and synchronise the EMD file.
- */
- /* #Specification: readdir / . and ..
- * The msdos filesystem manages the . and .. entry properly
- * so the EMD file won't hold any info about it.
- *
- * In readdir, we assume that for the root directory
- * the read position will be 0 for ".", 1 for "..". For
- * a non root directory, the read position will be 0 for "."
- * and 32 for "..".
- */
- /*
- * This is a trick used by the msdos file system (fs/msdos/dir.c)
- * to manage . and .. for the root directory of a file system.
- * Since there is no such entry in the root, fs/msdos/dir.c
- * use the following:
- *
- * if f_pos == 0, return ".".
- * if f_pos == 1, return "..".
- *
- * So let msdos handle it
- *
- * Since umsdos entries are much larger, we share the same f_pos.
- * if f_pos is 0 or 1 or 32, we are clearly looking at . and
- * ..
- *
- * As soon as we get f_pos == 2 or f_pos == 64, then back to
- * 0, but this time we are reading the EMD file.
- *
- * Well, not so true. The problem, is that UMSDOS_REC_SIZE is
- * also 64, so as soon as we read the first record in the
- * EMD, we are back at offset 64. So we set the offset
- * to UMSDOS_SPECIAL_DIRFPOS(3) as soon as we have read the
- * .. entry from msdos.
- *
- * Now (linux 1.3), umsdos_readdir can read more than one
- * entry even if we limit (umsdos_dir_once) to only one:
- * It skips over hidden file. So we switch to
- * UMSDOS_SPECIAL_DIRFPOS as soon as we have read successfully
- * the .. entry.
- */
- /* #Specification: umsdos / lookup / inode info
- * After successfully reading an inode from the MSDOS
- * filesystem, we use the EMD file to complete it.
- * We update the following field.
- *
- * uid, gid, atime, ctime, mtime, mode.
- *
- * We rely on MSDOS for mtime. If the file
- * was modified during an MSDOS session, at least
- * mtime will be meaningful. We do this only for regular
- * file.
- *
- * We don't rely on MS-DOS for mtime for directories
- * because the MS-DOS date on a directory is its
- * creation time (strange MSDOS behavior) which
- * corresponds to none of the three Unix time stamps.
- */
- /* #Specification: umsdos / conversion mode
- * The msdos filesystem can do some inline conversion
- * of the data of a file. It can translate silently
- * from the MS-DOS text file format to the Unix one
- * (CRLF -> LF) while reading, and the reverse
- * while writing. This is activated using the mount
- * option conv=....
- *
- * This is not useful for Linux files in a promoted
- * directory. It can even be harmful. For this
- * reason, the binary (no conversion) mode is
- * always activated.
- */
- /* #Specification: umsdos / conversion mode / todo
- * A flag could be added to file and directories
- * forcing an automatic conversion mode (as
- * done with the msdos filesystem).
- *
- * This flag could be setup on a directory basis
- * (instead of file) and all files in it would
- * logically inherit it. If the conversion mode
- * is active (conv=) then the i_binary flag would
- * be left untouched in those directories.
- *
- * It was proposed that the sticky bit be used to set
- * this. A problem with that is that new files would
- * be written incorrectly. The other problem is that
- * the sticky bit has a meaning for directories. So
- * another bit should be used (there is some space
- * in the EMD file for it) and a special utility
- * would be used to assign the flag to a directory).
- * I don't think it is useful to assign this flag
- * on a single file.
- */
- * #Specification: weakness / rename
- * There is a case where UMSDOS rename has a different behavior
- * than a normal Unix file system. Renaming an open file across
- * directory boundary does not work. Renaming an open file within
- * a directory does work, however.
- *
- * The problem may is in Linux VFS driver for msdos.
- * I believe this is not a bug but a design feature, because
- * an inode number represents some sort of directory address
- * in the MSDOS directory structure, so moving the file into
- * another directory does not preserve the inode number.
- */
-/* #Specification: rename / new name exist
- * If the destination name already exists, it will
- * silently be removed. EXT2 does it this way
- * and this is the spec of SunOS. So does UMSDOS.
- *
- * If the destination is an empty directory it will
- * also be removed.
- */
-/* #Specification: rename / new name exist / possible flaw
- * The code to handle the deletion of the target (file
- * and directory) use to be in umsdos_rename_f, surrounded
- * by proper directory locking. This was ensuring that only
- * one process could achieve a rename (modification) operation
- * in the source and destination directory. This was also
- * ensuring the operation was "atomic".
- *
- * This has been changed because this was creating a
- * stack overflow (the stack is only 4 kB) in the kernel. To avoid
- * the code doing the deletion of the target (if exist) has
- * been moved to a upper layer. umsdos_rename_f is tried
- * once and if it fails with EEXIST, the target is removed
- * and umsdos_rename_f is done again.
- *
- * This makes the code cleaner and may solve a
- * deadlock problem one tester was experiencing.
- *
- * The point is to mention that possibly, the semantic of
- * "rename" may be wrong. Anyone dare to check that :-)
- * Be aware that IF it is wrong, to produce the problem you
- * will need two process trying to rename a file to the
- * same target at the same time. Again, I am not sure it
- * is a problem at all.
- */
-
-/* #Specification: hard link / strategy
- * Hard links are difficult to implement on top of an MS-DOS FAT file
- * system. Unlike Unix file systems, there are no inodes. A directory
- * entry holds the functionality of the inode and the entry.
- *
- * We will used the same strategy as a normal Unix file system
- * (with inodes) except we will do it symbolically (using paths).
- *
- * Because anything can happen during a DOS session (defragment,
- * directory sorting, etc.), we can't rely on an MS-DOS pseudo
- * inode number to record the link. For this reason, the link
- * will be done using hidden symbolic links. The following
- * scenario illustrates how it works.
- *
- * Given a file /foo/file
- *
- * #
- * ln /foo/file /tmp/file2
- *
- * become internally
- *
- * mv /foo/file /foo/-LINK1
- * ln -s /foo/-LINK1 /foo/file
- * ln -s /foo/-LINK1 /tmp/file2
- * #
- *
- * Using this strategy, we can operate on /foo/file or /foo/file2.
- * We can remove one and keep the other, like a normal Unix hard link.
- * We can rename /foo/file or /tmp/file2 independently.
- *
- * The entry -LINK1 will be hidden. It will hold a link count.
- * When all link are erased, the hidden file is erased too.
- */
-
-/* #Specification: weakness / hard link
- * The strategy for hard link introduces a side effect that
- * may or may not be acceptable. Here is the sequence
- *
- * #
- * mkdir subdir1
- * touch subdir1/file
- * mkdir subdir2
- * ln subdir1/file subdir2/file
- * rm subdir1/file
- * rmdir subdir1
- * rmdir: subdir1: Directory not empty
- * #
- *
- * This happen because there is an invisible file (--link) in
- * subdir1 which is referenced by subdir2/file.
- *
- * Any idea ?
- */
-/* #Specification: weakness / hard link / rename directory
- * Another weakness of hard link come from the fact that
- * it is based on hidden symbolic links. Here is an example.
- *
- * #
- * mkdir /subdir1
- * touch /subdir1/file
- * mkdir /subdir2
- * ln /subdir1/file subdir2/file
- * mv /subdir1 subdir3
- * ls -l /subdir2/file
- * #
- *
- * Since /subdir2/file is a hidden symbolic link
- * to /subdir1/..hlinkNNN, accessing it will fail since
- * /subdir1 does not exist anymore (has been renamed).
- */
-/* #Specification: hard link / directory
- * A hard link can't be made on a directory. EPERM is returned
- * in this case.
- */
-/* #Specification: hard link / first hard link
- * The first time a hard link is done on a file, this
- * file must be renamed and hidden. Then an internal
- * symbolic link must be done on the hidden file.
- *
- * The second link is done after on this hidden file.
- *
- * It is expected that the Linux MSDOS file system
- * keeps the same pseudo inode when a rename operation
- * is done on a file in the same directory.
- */
-/* #Specification: function name / convention
- * A simple convention for function names has been used in
- * the UMSDOS filesystem. First, all functions use the prefix
- * umsdos_ to avoid name clashes with other parts of the kernel.
- *
- * Standard VFS entry points use the prefix UMSDOS (upper case)
- * so it's easier to tell them apart.
- * N.B. (FIXME) PTW, the order and contents of this struct changed.
- */
-
-/* #Specification: mount / options
- * Umsdos run on top of msdos. Currently, it supports no
- * mount option, but happily pass all option received to
- * the msdos driver. I am not sure if all msdos mount option
- * make sense with Umsdos. Here are at least those who
- * are useful.
- * uid=
- * gid=
- *
- * These options affect the operation of umsdos in directories
- * which do not have an EMD file. They behave like normal
- * msdos directory, with all limitation of msdos.
- */
-
-/* #Specification: pseudo root / mount
- * When a umsdos fs is mounted, a special handling is done
- * if it is the root partition. We check for the presence
- * of the file /linux/etc/init or /linux/etc/rc or
- * /linux/sbin/init. If one is there, we do a chroot("/linux").
- *
- * We check both because (see init/main.c) the kernel
- * try to exec init at different place and if it fails
- * it tries /bin/sh /etc/rc. To be consistent with
- * init/main.c, many more test would have to be done
- * to locate init. Any complain ?
- *
- * The chroot is done manually in init/main.c but the
- * info (the inode) is located at mount time and store
- * in a global variable (pseudo_root) which is used at
- * different place in the umsdos driver. There is no
- * need to store this variable elsewhere because it
- * will always be one, not one per mount.
- *
- * This feature allows the installation
- * of a linux system within a DOS system in a subdirectory.
- *
- * A user may install its linux stuff in c:\linux
- * avoiding any clash with existing DOS file and subdirectory.
- * When linux boots, it hides this fact, showing a normal
- * root directory with /etc /bin /tmp ...
- *
- * The word "linux" is hardcoded in /usr/include/linux/umsdos_fs.h
- * in the macro UMSDOS_PSDROOT_NAME.
- */
diff --git a/include/asm-alpha/cputime.h b/include/asm-alpha/cputime.h
new file mode 100644
index 000000000000..19577fd93230
--- /dev/null
+++ b/include/asm-alpha/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __ALPHA_CPUTIME_H
+#define __ALPHA_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __ALPHA_CPUTIME_H */
diff --git a/include/asm-alpha/io_trivial.h b/include/asm-alpha/io_trivial.h
index cfe1f86c33db..b10d1aa4cdd1 100644
--- a/include/asm-alpha/io_trivial.h
+++ b/include/asm-alpha/io_trivial.h
@@ -26,7 +26,7 @@ IO_CONCAT(__IO_PREFIX,iowrite8)(u8 b, void __iomem *a)
__EXTERN_INLINE void
IO_CONCAT(__IO_PREFIX,iowrite16)(u16 b, void __iomem *a)
{
- __kernel_stb(b, *(volatile u16 __force *)a);
+ __kernel_stw(b, *(volatile u16 __force *)a);
}
#endif
@@ -66,7 +66,7 @@ IO_CONCAT(__IO_PREFIX,writeb)(u8 b, volatile void __iomem *a)
__EXTERN_INLINE void
IO_CONCAT(__IO_PREFIX,writew)(u16 b, volatile void __iomem *a)
{
- __kernel_stb(b, *(volatile u16 __force *)a);
+ __kernel_stw(b, *(volatile u16 __force *)a);
}
#elif IO_CONCAT(__IO_PREFIX,trivial_rw_bw) == 2
__EXTERN_INLINE u8
diff --git a/include/asm-arm/arch-pxa/corgi.h b/include/asm-arm/arch-pxa/corgi.h
new file mode 100644
index 000000000000..9de52f035ba6
--- /dev/null
+++ b/include/asm-arm/arch-pxa/corgi.h
@@ -0,0 +1,135 @@
+/*
+ * Hardware specific definitions for SL-C7xx series of PDAs
+ *
+ * Copyright (c) 2004-2005 Richard Purdie
+ *
+ * Based on Sharp's 2.4 kernel patches
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_ARCH_CORGI_H
+#define __ASM_ARCH_CORGI_H 1
+
+
+/*
+ * Corgi (Non Standard) GPIO Definitions
+ */
+#define CORGI_GPIO_KEY_INT (0) /* Keyboard Interrupt */
+#define CORGI_GPIO_AC_IN (1)
+#define CORGI_GPIO_WAKEUP (3)
+#define CORGI_GPIO_AK_INT (4) /* IR Controller Interrupt */
+#define CORGI_GPIO_TP_INT (5) /* Touch Panel Interrupt */
+#define CORGI_GPIO_nSD_WP (7)
+#define CORGI_GPIO_nSD_DETECT (9) /* MMC/SD Card Detect */
+#define CORGI_GPIO_nSD_INT (10)
+#define CORGI_GPIO_MAIN_BAT_LOW (11)
+#define CORGI_GPIO_BAT_COVER (11)
+#define CORGI_GPIO_LED_ORANGE (13)
+#define CORGI_GPIO_CF_CD (14) /* Compact Flash Card Detect */
+#define CORGI_GPIO_CHRG_FULL (16)
+#define CORGI_GPIO_CF_IRQ (17) /* Compact Flash Interrupt */
+#define CORGI_GPIO_LCDCON_CS (19) /* LCD Control Chip Select */
+#define CORGI_GPIO_MAX1111_CS (20) /* MAX111 Chip Select */
+#define CORGI_GPIO_ADC_TEMP_ON (21)
+#define CORGI_GPIO_IR_ON (22)
+#define CORGI_GPIO_ADS7846_CS (24) /* ADS7846 Chip Select */
+#define CORGI_GPIO_SD_PWR (33) /* MMC/SD Power */
+#define CORGI_GPIO_CHRG_ON (38)
+#define CORGI_GPIO_DISCHARGE_ON (42)
+#define CORGI_GPIO_HSYNC (44) /* LCD HSync Pulse */
+#define CORGI_GPIO_USB_PULLUP (45)
+
+
+/*
+ * Corgi Keyboard Definitions
+ */
+#define CORGI_KEY_STROBE_NUM (12)
+#define CORGI_KEY_SENSE_NUM (8)
+#define CORGI_GPIO_ALL_STROBE_BIT (0x00003ffc)
+#define CORGI_GPIO_HIGH_SENSE_BIT (0xfc000000)
+#define CORGI_GPIO_HIGH_SENSE_RSHIFT (26)
+#define CORGI_GPIO_LOW_SENSE_BIT (0x00000003)
+#define CORGI_GPIO_LOW_SENSE_LSHIFT (6)
+#define CORGI_GPIO_STROBE_BIT(a) GPIO_bit(66+(a))
+#define CORGI_GPIO_SENSE_BIT(a) GPIO_bit(58+(a))
+#define CORGI_GAFR_ALL_STROBE_BIT (0x0ffffff0)
+#define CORGI_GAFR_HIGH_SENSE_BIT (0xfff00000)
+#define CORGI_GAFR_LOW_SENSE_BIT (0x0000000f)
+#define CORGI_GPIO_KEY_SENSE(a) (58+(a))
+#define CORGI_GPIO_KEY_STROBE(a) (66+(a))
+
+
+/*
+ * Corgi Interrupts
+ */
+#define CORGI_IRQ_GPIO_KEY_INT IRQ_GPIO(0)
+#define CORGI_IRQ_GPIO_AC_IN IRQ_GPIO(1)
+#define CORGI_IRQ_GPIO_WAKEUP IRQ_GPIO(3)
+#define CORGI_IRQ_GPIO_AK_INT IRQ_GPIO(4)
+#define CORGI_IRQ_GPIO_TP_INT IRQ_GPIO(5)
+#define CORGI_IRQ_GPIO_nSD_DETECT IRQ_GPIO(9)
+#define CORGI_IRQ_GPIO_nSD_INT IRQ_GPIO(10)
+#define CORGI_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO(11)
+#define CORGI_IRQ_GPIO_CF_CD IRQ_GPIO(14)
+#define CORGI_IRQ_GPIO_CHRG_FULL IRQ_GPIO(16) /* Battery fully charged */
+#define CORGI_IRQ_GPIO_CF_IRQ IRQ_GPIO(17)
+#define CORGI_IRQ_GPIO_KEY_SENSE(a) IRQ_GPIO(58+(a)) /* Keyboard Sense lines */
+
+
+/*
+ * Corgi SCOOP GPIOs and Config
+ */
+#define CORGI_SCP_LED_GREEN SCOOP_GPCR_PA11
+#define CORGI_SCP_SWA SCOOP_GPCR_PA12 /* Hinge Switch A */
+#define CORGI_SCP_SWB SCOOP_GPCR_PA13 /* Hinge Switch B */
+#define CORGI_SCP_MUTE_L SCOOP_GPCR_PA14
+#define CORGI_SCP_MUTE_R SCOOP_GPCR_PA15
+#define CORGI_SCP_AKIN_PULLUP SCOOP_GPCR_PA16
+#define CORGI_SCP_APM_ON SCOOP_GPCR_PA17
+#define CORGI_SCP_BACKLIGHT_CONT SCOOP_GPCR_PA18
+#define CORGI_SCP_MIC_BIAS SCOOP_GPCR_PA19
+
+#define CORGI_SCOOP_IO_DIR ( CORGI_SCP_LED_GREEN | CORGI_SCP_MUTE_L | CORGI_SCP_MUTE_R | \
+ CORGI_SCP_AKIN_PULLUP | CORGI_SCP_APM_ON | CORGI_SCP_BACKLIGHT_CONT | \
+ CORGI_SCP_MIC_BIAS )
+#define CORGI_SCOOP_IO_OUT ( CORGI_SCP_MUTE_L | CORGI_SCP_MUTE_R )
+
+/*
+ * Corgi Parameter Area Definitions
+ */
+#define FLASH_MEM_BASE 0xa0000a00
+#define FLASH_MAGIC_CHG(a,b,c,d) ( ( d << 24 ) | ( c << 16 ) | ( b << 8 ) | a )
+
+#define FLASH_COMADJ_MAJIC FLASH_MAGIC_CHG('C','M','A','D')
+#define FLASH_COMADJ_MAGIC_ADR 0x00
+#define FLASH_COMADJ_DATA_ADR 0x04
+
+#define FLASH_PHAD_MAJIC FLASH_MAGIC_CHG('P','H','A','D')
+#define FLASH_PHAD_MAGIC_ADR 0x38
+#define FLASH_PHAD_DATA_ADR 0x3C
+
+struct sharpsl_flash_param_info {
+ unsigned int comadj_keyword;
+ unsigned int comadj;
+
+ unsigned int uuid_keyword;
+ unsigned char uuid[16];
+
+ unsigned int touch_keyword;
+ unsigned int touch1;
+ unsigned int touch2;
+ unsigned int touch3;
+ unsigned int touch4;
+
+ unsigned int adadj_keyword;
+ unsigned int adadj;
+
+ unsigned int phad_keyword;
+ unsigned int phadadj;
+};
+
+#endif /* __ASM_ARCH_CORGI_H */
+
diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S
index ee4b3cff87d3..4cc886ed1dbb 100644
--- a/include/asm-arm/arch-s3c2410/entry-macro.S
+++ b/include/asm-arm/arch-s3c2410/entry-macro.S
@@ -8,16 +8,15 @@
* warranty of any kind, whether express or implied.
*/
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-30000:
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+
mov \tmp, #S3C2410_VA_IRQ
ldr \irqnr, [ \tmp, #0x14 ] @ get irq no
+30000:
teq \irqnr, #4
teqne \irqnr, #5
beq 1002f @ external irq reg
- teq \irqnr, #16
- beq 1003f @ lcd controller
@ debug check to see if interrupt reported is the same
@ as the offset....
@@ -29,15 +28,17 @@
tst \irqstat, #1
bne 20002f
+ /* debug/warning if we get an invalud response from the
+ * INTOFFSET register */
#if 1
- stmfd r13!, { r0 - r4 , r14 }
- ldr r1, [ \tmp, #0x14 ] @ intoffset
+ stmfd r13!, { r0 - r4 , r8-r12, r14 }
+ ldr r1, [ \tmp, #0x14 ] @ INTOFFSET
ldr r2, [ \tmp, #0x10 ] @ INTPND
ldr r3, [ \tmp, #0x00 ] @ SRCPND
adr r0, 20003f
bl printk
b 20004f
-#endif
+
20003:
.ascii "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n"
.byte 0
@@ -45,9 +46,10 @@
20004:
mov r1, #1
mov \tmp, #S3C2410_VA_IRQ
- ldmfd r13!, { r0 - r4 , r14 }
+ ldmfd r13!, { r0 - r4 , r8-r12, r14 }
+#endif
- @ try working out interript number for ourselves
+ @ try working out interrupt number for ourselves
mov \irqnr, #0
ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
10021:
@@ -98,19 +100,6 @@
@ found no interrupt, set Z flag and leave
movs \irqnr, #0
- b 1001f
-
-1003:
- @ lcd interrupt has been asserted...
- add \tmp, \tmp, #S3C2410_VA_LCD - S3C2410_VA_IRQ
- ldr \irqstat, [ \tmp, # 0x54 ] @ lcd int pending
-
- tst \irqstat, #2
- movne \irqnr, #IRQ_LCD_FRAME
- tst \irqstat, #1
- movne \irqnr, #IRQ_LCD_FIFO
-
- @ fall through to exit with flags updated
1004: @ ensure Z flag clear in case our MOVS shifted out the last bit
teq \irqnr, #0
diff --git a/include/asm-arm/arch-s3c2410/timex.h b/include/asm-arm/arch-s3c2410/timex.h
index 44aa0dcf8fcc..3558a3a750bf 100644
--- a/include/asm-arm/arch-s3c2410/timex.h
+++ b/include/asm-arm/arch-s3c2410/timex.h
@@ -1,6 +1,6 @@
/* linux/include/asm-arm/arch-s3c2410/timex.h
*
- * (c) 2003,2004 Simtec Electronics
+ * (c) 2003-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 - time parameters
@@ -13,21 +13,19 @@
* 02-Sep-2003 BJD Created file
* 05-Jan-2004 BJD Updated for Linux 2.6.0
* 22-Nov-2004 BJD Fixed CLOCK_TICK_RATE
+ * 10-Jan-2004 BJD Removed s3c2410_clock_tick_rate
*/
#ifndef __ASM_ARCH_TIMEX_H
#define __ASM_ARCH_TIMEX_H
-#if 0
-/* todo - this does not seem to work with 2.6.0 -> division by zero
- * in header files
- */
-extern int s3c2410_clock_tick_rate;
+/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
+ * a variable is useless. It seems as long as we make our timers an
+ * exact multiple of HZ, any value that makes a 1->1 correspondence
+ * for the time conversion functions to/from jiffies is acceptable.
+*/
-#define CLOCK_TICK_RATE (s3c2410_clock_tick_rate)
-#endif
-/* currently, the BAST uses 12MHz as a base clock rate */
#define CLOCK_TICK_RATE 12000000
diff --git a/include/asm-arm/cpu.h b/include/asm-arm/cpu.h
index 0f99a8881a8b..fcbdd40cb667 100644
--- a/include/asm-arm/cpu.h
+++ b/include/asm-arm/cpu.h
@@ -17,7 +17,6 @@ struct cpuinfo_arm {
struct cpu cpu;
#ifdef CONFIG_SMP
unsigned int loops_per_jiffy;
- unsigned long ipi_count;
#endif
};
diff --git a/include/asm-arm/cputime.h b/include/asm-arm/cputime.h
new file mode 100644
index 000000000000..3a8002a5fec7
--- /dev/null
+++ b/include/asm-arm/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __ARM_CPUTIME_H
+#define __ARM_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __ARM_CPUTIME_H */
diff --git a/include/asm-arm/hardware/scoop.h b/include/asm-arm/hardware/scoop.h
new file mode 100644
index 000000000000..669b7df6e570
--- /dev/null
+++ b/include/asm-arm/hardware/scoop.h
@@ -0,0 +1,47 @@
+/*
+ * Definitions for the SCOOP interface found on various Sharp PDAs
+ *
+ * Copyright (c) 2004 Richard Purdie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define SCOOP_MCR 0x00
+#define SCOOP_CDR 0x04
+#define SCOOP_CSR 0x08
+#define SCOOP_CPR 0x0C
+#define SCOOP_CCR 0x10
+#define SCOOP_IRR 0x14
+#define SCOOP_IRM 0x14
+#define SCOOP_IMR 0x18
+#define SCOOP_ISR 0x1C
+#define SCOOP_GPCR 0x20
+#define SCOOP_GPWR 0x24
+#define SCOOP_GPRR 0x28
+
+#define SCOOP_GPCR_PA22 ( 1 << 12 )
+#define SCOOP_GPCR_PA21 ( 1 << 11 )
+#define SCOOP_GPCR_PA20 ( 1 << 10 )
+#define SCOOP_GPCR_PA19 ( 1 << 9 )
+#define SCOOP_GPCR_PA18 ( 1 << 8 )
+#define SCOOP_GPCR_PA17 ( 1 << 7 )
+#define SCOOP_GPCR_PA16 ( 1 << 6 )
+#define SCOOP_GPCR_PA15 ( 1 << 5 )
+#define SCOOP_GPCR_PA14 ( 1 << 4 )
+#define SCOOP_GPCR_PA13 ( 1 << 3 )
+#define SCOOP_GPCR_PA12 ( 1 << 2 )
+#define SCOOP_GPCR_PA11 ( 1 << 1 )
+
+struct scoop_config {
+ unsigned short io_out;
+ unsigned short io_dir;
+};
+
+void reset_scoop(void);
+unsigned short set_scoop_gpio(unsigned short bit);
+unsigned short reset_scoop_gpio(unsigned short bit);
+unsigned short read_scoop_reg(unsigned short reg);
+void write_scoop_reg(unsigned short reg, unsigned short data);
diff --git a/include/asm-arm/mach/irq.h b/include/asm-arm/mach/irq.h
index c6ae545e4237..a43a353f6c7b 100644
--- a/include/asm-arm/mach/irq.h
+++ b/include/asm-arm/mach/irq.h
@@ -47,6 +47,13 @@ struct irqchip {
* Set wakeup-enable on the selected IRQ
*/
int (*wake)(unsigned int, unsigned int);
+
+#ifdef CONFIG_SMP
+ /*
+ * Route an interrupt to a CPU
+ */
+ void (*set_cpu)(struct irqdesc *desc, unsigned int irq, unsigned int cpu);
+#endif
};
struct irqdesc {
@@ -67,6 +74,13 @@ struct irqdesc {
unsigned int noautoenable : 1; /* don't automatically enable IRQ */
unsigned int unused :25;
+ struct proc_dir_entry *procdir;
+
+#ifdef CONFIG_SMP
+ cpumask_t affinity;
+ unsigned int cpu;
+#endif
+
/*
* IRQ lock detection
*/
diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h
index 06ab5f106a0f..4a9845997a75 100644
--- a/include/asm-arm/processor.h
+++ b/include/asm-arm/processor.h
@@ -19,7 +19,6 @@
#ifdef __KERNEL__
-#include <asm/atomic.h>
#include <asm/ptrace.h>
#include <asm/procinfo.h>
#include <asm/types.h>
diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h
index 0b012dfc098a..f21fd8f6bcdd 100644
--- a/include/asm-arm/smp.h
+++ b/include/asm-arm/smp.h
@@ -32,6 +32,13 @@ extern cpumask_t cpu_present_mask;
*/
#define PROC_CHANGE_PENALTY 15
+struct seq_file;
+
+/*
+ * generate IPI list text
+ */
+extern void show_ipi_list(struct seq_file *p);
+
/*
* Move global data into per-processor storage.
*/
@@ -46,6 +53,6 @@ extern void smp_cross_call(cpumask_t callmap);
* Boot a secondary CPU, and assign it the specified idle task.
* This also gives us the initial stack to use for this CPU.
*/
-extern int __init boot_secondary(unsigned int cpu, struct task_struct *);
+extern int boot_secondary(unsigned int cpu, struct task_struct *);
#endif /* ifndef __ASM_ARM_SMP_H */
diff --git a/include/asm-arm/tlb.h b/include/asm-arm/tlb.h
index ab3cad4fb53d..0843a876b3ce 100644
--- a/include/asm-arm/tlb.h
+++ b/include/asm-arm/tlb.h
@@ -91,4 +91,6 @@ tlb_is_full_mm(struct mmu_gather *tlb)
#define pte_free_tlb(tlb,ptep) pte_free(ptep)
#define pmd_free_tlb(tlb,pmdp) pmd_free(pmdp)
+#define tlb_migrate_finish(mm) do { } while (0)
+
#endif
diff --git a/include/asm-arm26/cputime.h b/include/asm-arm26/cputime.h
new file mode 100644
index 000000000000..d2783a9e47b3
--- /dev/null
+++ b/include/asm-arm26/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __ARM26_CPUTIME_H
+#define __ARM26_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __ARM26_CPUTIME_H */
diff --git a/include/asm-cris/cputime.h b/include/asm-cris/cputime.h
new file mode 100644
index 000000000000..4446a65656fa
--- /dev/null
+++ b/include/asm-cris/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __CRIS_CPUTIME_H
+#define __CRIS_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __CRIS_CPUTIME_H */
diff --git a/include/asm-generic/cputime.h b/include/asm-generic/cputime.h
new file mode 100644
index 000000000000..c9968a09f8ab
--- /dev/null
+++ b/include/asm-generic/cputime.h
@@ -0,0 +1,64 @@
+#ifndef _ASM_GENERIC_CPUTIME_H
+#define _ASM_GENERIC_CPUTIME_H
+
+#include <linux/time.h>
+#include <linux/jiffies.h>
+
+typedef unsigned long cputime_t;
+
+#define cputime_zero (0UL)
+#define cputime_max ((~0UL >> 1) - 1)
+#define cputime_add(__a, __b) ((__a) + (__b))
+#define cputime_sub(__a, __b) ((__a) - (__b))
+#define cputime_eq(__a, __b) ((__a) == (__b))
+#define cputime_gt(__a, __b) ((__a) > (__b))
+#define cputime_ge(__a, __b) ((__a) >= (__b))
+#define cputime_lt(__a, __b) ((__a) < (__b))
+#define cputime_le(__a, __b) ((__a) <= (__b))
+#define cputime_to_jiffies(__ct) (__ct)
+#define jiffies_to_cputime(__hz) (__hz)
+
+typedef u64 cputime64_t;
+
+#define cputime64_zero (0ULL)
+#define cputime64_add(__a, __b) ((__a) + (__b))
+#define cputime64_to_jiffies64(__ct) (__ct)
+#define cputime_to_cputime64(__ct) ((u64) __ct)
+
+
+/*
+ * Convert cputime to milliseconds and back.
+ */
+#define cputime_to_msecs(__ct) jiffies_to_msecs(__ct)
+#define msecs_to_cputime(__msecs) msecs_to_jiffies(__msecs)
+
+/*
+ * Convert cputime to seconds and back.
+ */
+#define cputime_to_secs(__ct) (jiffies_to_msecs(__ct) / HZ)
+#define secs_to_cputime(__secs) (msecs_to_jiffies(__secs * HZ))
+
+/*
+ * Convert cputime to timespec and back.
+ */
+#define timespec_to_cputime(__val) timespec_to_jiffies(__val)
+#define cputime_to_timespec(__ct,__val) jiffies_to_timespec(__ct,__val)
+
+/*
+ * Convert cputime to timeval and back.
+ */
+#define timeval_to_cputime(__val) timeval_to_jiffies(__val)
+#define cputime_to_timeval(__ct,__val) jiffies_to_timeval(__ct,__val)
+
+/*
+ * Convert cputime to clock and back.
+ */
+#define cputime_to_clock_t(__ct) jiffies_to_clock_t(__ct)
+#define clock_t_to_cputime(__x) clock_t_to_jiffies(__x)
+
+/*
+ * Convert cputime64 to clock.
+ */
+#define cputime64_to_clock_t(__ct) jiffies_64_to_clock_t(__ct)
+
+#endif
diff --git a/include/asm-h8300/cputime.h b/include/asm-h8300/cputime.h
new file mode 100644
index 000000000000..092e187c7b08
--- /dev/null
+++ b/include/asm-h8300/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __H8300_CPUTIME_H
+#define __H8300_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __H8300_CPUTIME_H */
diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
index fdbd65ca669e..e147cabd3bfe 100644
--- a/include/asm-i386/cpufeature.h
+++ b/include/asm-i386/cpufeature.h
@@ -9,7 +9,7 @@
#include <linux/bitops.h>
-#define NCAPINTS 6 /* Currently we have 6 32-bit words worth of info */
+#define NCAPINTS 7 /* N 32-bit words worth of info */
/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */
@@ -77,6 +77,7 @@
#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */
#define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */
#define X86_FEATURE_CID (4*32+10) /* Context ID */
+#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */
#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */
/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
@@ -85,6 +86,9 @@
#define X86_FEATURE_XCRYPT (5*32+ 6) /* on-CPU crypto (xcrypt insn) */
#define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* on-CPU crypto enabled */
+/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
+#define X86_FEATURE_LAHF_LM (5*32+ 0) /* LAHF/SAHF in long mode */
+#define X86_FEATURE_CMP_LEGACY (5*32+ 1) /* If yes HyperThreading not valid */
#define cpu_has(c, bit) test_bit(bit, (c)->x86_capability)
#define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability)
diff --git a/include/asm-i386/cputime.h b/include/asm-i386/cputime.h
new file mode 100644
index 000000000000..398ed7cd171d
--- /dev/null
+++ b/include/asm-i386/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __I386_CPUTIME_H
+#define __I386_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __I386_CPUTIME_H */
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 0d4e4acc3b12..70a48f509d24 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -65,6 +65,7 @@ struct cpuinfo_x86 {
int f00f_bug;
int coma_bug;
unsigned long loops_per_jiffy;
+ unsigned char x86_num_cores;
} __attribute__((__aligned__(SMP_CACHE_BYTES)));
#define X86_VENDOR_INTEL 0
@@ -96,6 +97,7 @@ extern struct cpuinfo_x86 cpu_data[];
#define current_cpu_data boot_cpu_data
#endif
+extern int phys_proc_id[NR_CPUS];
extern char ignore_fpu_irq;
extern void identify_cpu(struct cpuinfo_x86 *);
@@ -103,6 +105,12 @@ extern void print_cpu_info(struct cpuinfo_x86 *);
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
extern void dodgy_tsc(void);
+#ifdef CONFIG_X86_HT
+extern void detect_ht(struct cpuinfo_x86 *c);
+#else
+static inline void detect_ht(struct cpuinfo_x86 *c) {}
+#endif
+
/*
* EFLAGS bits
*/
diff --git a/include/asm-ia64/cputime.h b/include/asm-ia64/cputime.h
new file mode 100644
index 000000000000..72400a78002a
--- /dev/null
+++ b/include/asm-ia64/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __IA64_CPUTIME_H
+#define __IA64_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __IA64_CPUTIME_H */
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
index 0749f1a1454e..8ef0f02635d4 100644
--- a/include/asm-ia64/machvec.h
+++ b/include/asm-ia64/machvec.h
@@ -20,6 +20,7 @@ struct scatterlist;
struct irq_desc;
struct page;
struct mm_struct;
+struct pci_bus;
typedef void ia64_mv_setup_t (char **);
typedef void ia64_mv_cpu_init_t (void);
@@ -31,6 +32,11 @@ typedef void ia64_mv_tlb_migrate_finish_t (struct mm_struct *);
typedef struct irq_desc *ia64_mv_irq_desc (unsigned int);
typedef u8 ia64_mv_irq_to_vector (unsigned int);
typedef unsigned int ia64_mv_local_vector_to_irq (u8);
+typedef char *ia64_mv_pci_get_legacy_mem_t (struct pci_bus *);
+typedef int ia64_mv_pci_legacy_read_t (struct pci_bus *, u16 port, u32 *val,
+ u8 size);
+typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val,
+ u8 size);
/* DMA-mapping interface: */
typedef void ia64_mv_dma_init (void);
@@ -94,6 +100,8 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);
# include <asm/machvec_dig.h>
# elif defined (CONFIG_IA64_HP_ZX1)
# include <asm/machvec_hpzx1.h>
+# elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB)
+# include <asm/machvec_hpzx1_swiotlb.h>
# elif defined (CONFIG_IA64_SGI_SN2)
# include <asm/machvec_sn2.h>
# elif defined (CONFIG_IA64_GENERIC)
@@ -125,6 +133,9 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);
# define platform_irq_desc ia64_mv.irq_desc
# define platform_irq_to_vector ia64_mv.irq_to_vector
# define platform_local_vector_to_irq ia64_mv.local_vector_to_irq
+# define platform_pci_get_legacy_mem ia64_mv.pci_get_legacy_mem
+# define platform_pci_legacy_read ia64_mv.pci_legacy_read
+# define platform_pci_legacy_write ia64_mv.pci_legacy_write
# define platform_inb ia64_mv.inb
# define platform_inw ia64_mv.inw
# define platform_inl ia64_mv.inl
@@ -172,6 +183,9 @@ struct ia64_machine_vector {
ia64_mv_irq_desc *irq_desc;
ia64_mv_irq_to_vector *irq_to_vector;
ia64_mv_local_vector_to_irq *local_vector_to_irq;
+ ia64_mv_pci_get_legacy_mem_t *pci_get_legacy_mem;
+ ia64_mv_pci_legacy_read_t *pci_legacy_read;
+ ia64_mv_pci_legacy_write_t *pci_legacy_write;
ia64_mv_inb_t *inb;
ia64_mv_inw_t *inw;
ia64_mv_inl_t *inl;
@@ -215,6 +229,9 @@ struct ia64_machine_vector {
platform_irq_desc, \
platform_irq_to_vector, \
platform_local_vector_to_irq, \
+ platform_pci_get_legacy_mem, \
+ platform_pci_legacy_read, \
+ platform_pci_legacy_write, \
platform_inb, \
platform_inw, \
platform_inl, \
@@ -330,6 +347,15 @@ extern ia64_mv_dma_supported swiotlb_dma_supported;
#ifndef platform_local_vector_to_irq
# define platform_local_vector_to_irq __ia64_local_vector_to_irq
#endif
+#ifndef platform_pci_get_legacy_mem
+# define platform_pci_get_legacy_mem ia64_pci_get_legacy_mem
+#endif
+#ifndef platform_pci_legacy_read
+# define platform_pci_legacy_read ia64_pci_legacy_read
+#endif
+#ifndef platform_pci_legacy_write
+# define platform_pci_legacy_write ia64_pci_legacy_write
+#endif
#ifndef platform_inb
# define platform_inb __ia64_inb
#endif
diff --git a/include/asm-ia64/machvec_hpzx1_swiotlb.h b/include/asm-ia64/machvec_hpzx1_swiotlb.h
new file mode 100644
index 000000000000..9924b1b00a6c
--- /dev/null
+++ b/include/asm-ia64/machvec_hpzx1_swiotlb.h
@@ -0,0 +1,43 @@
+#ifndef _ASM_IA64_MACHVEC_HPZX1_SWIOTLB_h
+#define _ASM_IA64_MACHVEC_HPZX1_SWIOTLB_h
+
+extern ia64_mv_setup_t dig_setup;
+extern ia64_mv_dma_init hwsw_init;
+extern ia64_mv_dma_alloc_coherent hwsw_alloc_coherent;
+extern ia64_mv_dma_free_coherent hwsw_free_coherent;
+extern ia64_mv_dma_map_single hwsw_map_single;
+extern ia64_mv_dma_unmap_single hwsw_unmap_single;
+extern ia64_mv_dma_map_sg hwsw_map_sg;
+extern ia64_mv_dma_unmap_sg hwsw_unmap_sg;
+extern ia64_mv_dma_supported hwsw_dma_supported;
+extern ia64_mv_dma_mapping_error hwsw_dma_mapping_error;
+extern ia64_mv_dma_sync_single_for_cpu hwsw_sync_single_for_cpu;
+extern ia64_mv_dma_sync_sg_for_cpu hwsw_sync_sg_for_cpu;
+extern ia64_mv_dma_sync_single_for_device hwsw_sync_single_for_device;
+extern ia64_mv_dma_sync_sg_for_device hwsw_sync_sg_for_device;
+
+/*
+ * This stuff has dual use!
+ *
+ * For a generic kernel, the macros are used to initialize the
+ * platform's machvec structure. When compiling a non-generic kernel,
+ * the macros are used directly.
+ */
+#define platform_name "hpzx1_swiotlb"
+
+#define platform_setup dig_setup
+#define platform_dma_init hwsw_init
+#define platform_dma_alloc_coherent hwsw_alloc_coherent
+#define platform_dma_free_coherent hwsw_free_coherent
+#define platform_dma_map_single hwsw_map_single
+#define platform_dma_unmap_single hwsw_unmap_single
+#define platform_dma_map_sg hwsw_map_sg
+#define platform_dma_unmap_sg hwsw_unmap_sg
+#define platform_dma_supported hwsw_dma_supported
+#define platform_dma_mapping_error hwsw_dma_mapping_error
+#define platform_dma_sync_single_for_cpu hwsw_sync_single_for_cpu
+#define platform_dma_sync_sg_for_cpu hwsw_sync_sg_for_cpu
+#define platform_dma_sync_single_for_device hwsw_sync_single_for_device
+#define platform_dma_sync_sg_for_device hwsw_sync_sg_for_device
+
+#endif /* _ASM_IA64_MACHVEC_HPZX1_SWIOTLB_h */
diff --git a/include/asm-ia64/machvec_init.h b/include/asm-ia64/machvec_init.h
index 0d7386a13422..cb19becd3937 100644
--- a/include/asm-ia64/machvec_init.h
+++ b/include/asm-ia64/machvec_init.h
@@ -5,6 +5,9 @@ extern ia64_mv_global_tlb_purge_t ia64_global_tlb_purge;
extern ia64_mv_irq_desc __ia64_irq_desc;
extern ia64_mv_irq_to_vector __ia64_irq_to_vector;
extern ia64_mv_local_vector_to_irq __ia64_local_vector_to_irq;
+extern ia64_mv_pci_get_legacy_mem_t ia64_pci_get_legacy_mem;
+extern ia64_mv_pci_legacy_read_t ia64_pci_legacy_read;
+extern ia64_mv_pci_legacy_write_t ia64_pci_legacy_write;
extern ia64_mv_inb_t __ia64_inb;
extern ia64_mv_inw_t __ia64_inw;
diff --git a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h
index 299a57f83f29..bd0ed509a4cc 100644
--- a/include/asm-ia64/machvec_sn2.h
+++ b/include/asm-ia64/machvec_sn2.h
@@ -43,6 +43,9 @@ extern ia64_mv_tlb_migrate_finish_t sn_tlb_migrate_finish;
extern ia64_mv_irq_desc sn_irq_desc;
extern ia64_mv_irq_to_vector sn_irq_to_vector;
extern ia64_mv_local_vector_to_irq sn_local_vector_to_irq;
+extern ia64_mv_pci_get_legacy_mem_t sn_pci_get_legacy_mem;
+extern ia64_mv_pci_legacy_read_t sn_pci_legacy_read;
+extern ia64_mv_pci_legacy_write_t sn_pci_legacy_write;
extern ia64_mv_inb_t __sn_inb;
extern ia64_mv_inw_t __sn_inw;
extern ia64_mv_inl_t __sn_inl;
@@ -105,6 +108,9 @@ extern ia64_mv_dma_supported sn_dma_supported;
#define platform_irq_desc sn_irq_desc
#define platform_irq_to_vector sn_irq_to_vector
#define platform_local_vector_to_irq sn_local_vector_to_irq
+#define platform_pci_get_legacy_mem sn_pci_get_legacy_mem
+#define platform_pci_legacy_read sn_pci_legacy_read
+#define platform_pci_legacy_write sn_pci_legacy_write
#define platform_dma_init machvec_noop
#define platform_dma_alloc_coherent sn_dma_alloc_coherent
#define platform_dma_free_coherent sn_dma_free_coherent
diff --git a/include/asm-ia64/numnodes.h b/include/asm-ia64/numnodes.h
index 4fed3ac3c442..21cff4da5485 100644
--- a/include/asm-ia64/numnodes.h
+++ b/include/asm-ia64/numnodes.h
@@ -4,7 +4,7 @@
#ifdef CONFIG_IA64_DIG
/* Max 8 Nodes */
#define NODES_SHIFT 3
-#elif defined(CONFIG_IA64_HP_ZX1)
+#elif defined(CONFIG_IA64_HP_ZX1) || defined(CONFIG_IA64_HP_ZX1_SWIOTLB)
/* Max 32 Nodes */
#define NODES_SHIFT 5
#elif defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
diff --git a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h
index 898f4eca65b5..48e565fb5e0f 100644
--- a/include/asm-ia64/pci.h
+++ b/include/asm-ia64/pci.h
@@ -85,6 +85,20 @@ extern int pcibios_prep_mwi (struct pci_dev *);
#define HAVE_PCI_MMAP
extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine);
+#define HAVE_PCI_LEGACY
+extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
+ struct vm_area_struct *vma);
+extern ssize_t pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off,
+ size_t count);
+extern ssize_t pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off,
+ size_t count);
+extern int pci_mmap_legacy_mem(struct kobject *kobj,
+ struct bin_attribute *attr,
+ struct vm_area_struct *vma);
+
+#define pci_get_legacy_mem platform_pci_get_legacy_mem
+#define pci_legacy_read platform_pci_legacy_read
+#define pci_legacy_write platform_pci_legacy_write
struct pci_window {
struct resource resource;
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index 51485f7d66a8..347bbe6a0af0 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -203,7 +203,7 @@ ia64_sn_get_master_baseio_nasid(void)
return ret_stuff.v0;
}
-static inline u64
+static inline char *
ia64_sn_get_klconfig_addr(nasid_t nasid)
{
struct ia64_sal_retval ret_stuff;
@@ -223,7 +223,7 @@ ia64_sn_get_klconfig_addr(nasid_t nasid)
if (ret_stuff.status != 0) {
panic("ia64_sn_get_klconfig_addr: Returned error %lx\n", ret_stuff.status);
}
- return(ret_stuff.v0);
+ return ret_stuff.v0 ? __va(ret_stuff.v0) : NULL;
}
/*
@@ -474,6 +474,52 @@ ia64_sn_pod_mode(void)
return isrv.v0;
}
+/**
+ * ia64_sn_probe_mem - read from memory safely
+ * @addr: address to probe
+ * @size: number bytes to read (1,2,4,8)
+ * @data_ptr: address to store value read by probe (-1 returned if probe fails)
+ *
+ * Call into the SAL to do a memory read. If the read generates a machine
+ * check, this routine will recover gracefully and return -1 to the caller.
+ * @addr is usually a kernel virtual address in uncached space (i.e. the
+ * address starts with 0xc), but if called in physical mode, @addr should
+ * be a physical address.
+ *
+ * Return values:
+ * 0 - probe successful
+ * 1 - probe failed (generated MCA)
+ * 2 - Bad arg
+ * <0 - PAL error
+ */
+static inline u64
+ia64_sn_probe_mem(long addr, long size, void *data_ptr)
+{
+ struct ia64_sal_retval isrv;
+
+ SAL_CALL(isrv, SN_SAL_PROBE, addr, size, 0, 0, 0, 0, 0);
+
+ if (data_ptr) {
+ switch (size) {
+ case 1:
+ *((u8*)data_ptr) = (u8)isrv.v0;
+ break;
+ case 2:
+ *((u16*)data_ptr) = (u16)isrv.v0;
+ break;
+ case 4:
+ *((u32*)data_ptr) = (u32)isrv.v0;
+ break;
+ case 8:
+ *((u64*)data_ptr) = (u64)isrv.v0;
+ break;
+ default:
+ isrv.status = 2;
+ }
+ }
+ return isrv.status;
+}
+
/*
* Retrieve the system serial number as an ASCII string.
*/
diff --git a/include/asm-m32r/cputime.h b/include/asm-m32r/cputime.h
new file mode 100644
index 000000000000..0a47550df2b7
--- /dev/null
+++ b/include/asm-m32r/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __M32R_CPUTIME_H
+#define __M32R_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __M32R_CPUTIME_H */
diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h
index a506573b7b69..f71dfa15db74 100644
--- a/include/asm-m32r/unistd.h
+++ b/include/asm-m32r/unistd.h
@@ -25,26 +25,26 @@
#define __NR_time 13
#define __NR_mknod 14
#define __NR_chmod 15
-#define __NR_lchown 16
-#define __NR_break 17
-#define __NR_oldstat 18
+/* 16 is unused */
+/* 17 is unused */
+/* 18 is unused */
#define __NR_lseek 19
#define __NR_getpid 20
#define __NR_mount 21
#define __NR_umount 22
-#define __NR_setuid 23
-#define __NR_getuid 24
+/* 23 is unused */
+/* 24 is unused */
#define __NR_stime 25
#define __NR_ptrace 26
#define __NR_alarm 27
-#define __NR_oldfstat 28
+/* 28 is unused */
#define __NR_pause 29
#define __NR_utime 30
-#define __NR_cacheflush 31 /* old #define __NR_stty 31*/
+/* 31 is unused */
#define __NR_cachectl 32 /* old #define __NR_gtty 32*/
#define __NR_access 33
-#define __NR_nice 34
-#define __NR_ftime 35
+/* 34 is unused */
+/* 35 is unused */
#define __NR_sync 36
#define __NR_kill 37
#define __NR_rename 38
@@ -53,22 +53,22 @@
#define __NR_dup 41
#define __NR_pipe 42
#define __NR_times 43
-#define __NR_prof 44
+/* 44 is unused */
#define __NR_brk 45
-#define __NR_setgid 46
-#define __NR_getgid 47
-#define __NR_signal 48
-#define __NR_geteuid 49
-#define __NR_getegid 50
+/* 46 is unused */
+/* 47 is unused (getgid16) */
+/* 48 is unused */
+/* 49 is unused */
+/* 50 is unused */
#define __NR_acct 51
#define __NR_umount2 52
-#define __NR_lock 53
+/* 53 is unused */
#define __NR_ioctl 54
-#define __NR_fcntl 55
-#define __NR_mpx 56
+/* 55 is unused (fcntl) */
+/* 56 is unused */
#define __NR_setpgid 57
-#define __NR_ulimit 58
-#define __NR_oldolduname 59
+/* 58 is unused */
+/* 59 is unused */
#define __NR_umask 60
#define __NR_chroot 61
#define __NR_ustat 62
@@ -76,41 +76,41 @@
#define __NR_getppid 64
#define __NR_getpgrp 65
#define __NR_setsid 66
-#define __NR_sigaction 67
-#define __NR_sgetmask 68
-#define __NR_ssetmask 69
-#define __NR_setreuid 70
-#define __NR_setregid 71
-#define __NR_sigsuspend 72
-#define __NR_sigpending 73
+/* 67 is unused */
+/* 68 is unused*/
+/* 69 is unused*/
+/* 70 is unused */
+/* 71 is unused */
+/* 72 is unused */
+/* 73 is unused */
#define __NR_sethostname 74
#define __NR_setrlimit 75
-#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
+/* 76 is unused (old getrlimit) */
#define __NR_getrusage 77
#define __NR_gettimeofday 78
#define __NR_settimeofday 79
-#define __NR_getgroups 80
-#define __NR_setgroups 81
-#define __NR_select 82
+/* 80 is unused */
+/* 81 is unused */
+/* 82 is unused */
#define __NR_symlink 83
-#define __NR_oldlstat 84
+/* 84 is unused */
#define __NR_readlink 85
#define __NR_uselib 86
#define __NR_swapon 87
#define __NR_reboot 88
-#define __NR_readdir 89
-#define __NR_mmap 90
+/* 89 is unused */
+/* 90 is unused */
#define __NR_munmap 91
#define __NR_truncate 92
#define __NR_ftruncate 93
#define __NR_fchmod 94
-#define __NR_fchown 95
+/* 95 is unused */
#define __NR_getpriority 96
#define __NR_setpriority 97
-#define __NR_profil 98
+/* 98 is unused */
#define __NR_statfs 99
#define __NR_fstatfs 100
-#define __NR_ioperm 101
+/* 101 is unused */
#define __NR_socketcall 102
#define __NR_syslog 103
#define __NR_setitimer 104
@@ -118,37 +118,37 @@
#define __NR_stat 106
#define __NR_lstat 107
#define __NR_fstat 108
-#define __NR_olduname 109
-#define __NR_iopl 110
+/* 109 is unused */
+/* 110 is unused */
#define __NR_vhangup 111
-#define __NR_idle 112
-#define __NR_vm86old 113
+/* 112 is unused */
+/* 113 is unused */
#define __NR_wait4 114
#define __NR_swapoff 115
#define __NR_sysinfo 116
#define __NR_ipc 117
#define __NR_fsync 118
-#define __NR_sigreturn 119
+/* 119 is unused */
#define __NR_clone 120
#define __NR_setdomainname 121
#define __NR_uname 122
-#define __NR_modify_ldt 123
+/* 123 is unused */
#define __NR_adjtimex 124
#define __NR_mprotect 125
-#define __NR_sigprocmask 126
-#define __NR_create_module 127
+/* 126 is unused */
+/* 127 is unused */
#define __NR_init_module 128
#define __NR_delete_module 129
-#define __NR_get_kernel_syms 130
+/* 130 is unused */
#define __NR_quotactl 131
#define __NR_getpgid 132
#define __NR_fchdir 133
#define __NR_bdflush 134
#define __NR_sysfs 135
#define __NR_personality 136
-#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
-#define __NR_setfsuid 138
-#define __NR_setfsgid 139
+/* 137 is unused */
+/* 138 is unused */
+/* 139 is unused */
#define __NR__llseek 140
#define __NR_getdents 141
#define __NR__newselect 142
@@ -173,14 +173,14 @@
#define __NR_sched_rr_get_interval 161
#define __NR_nanosleep 162
#define __NR_mremap 163
-#define __NR_setresuid 164
-#define __NR_getresuid 165
+/* 164 is unused */
+/* 165 is unused */
#define __NR_tas 166
-#define __NR_query_module 167
+/* 167 is unused */
#define __NR_poll 168
#define __NR_nfsservctl 169
-#define __NR_setresgid 170
-#define __NR_getresgid 171
+/* 170 is unused */
+/* 171 is unused */
#define __NR_prctl 172
#define __NR_rt_sigreturn 173
#define __NR_rt_sigaction 174
@@ -191,14 +191,14 @@
#define __NR_rt_sigsuspend 179
#define __NR_pread64 180
#define __NR_pwrite64 181
-#define __NR_chown 182
+/* 182 is unused */
#define __NR_getcwd 183
#define __NR_capget 184
#define __NR_capset 185
#define __NR_sigaltstack 186
#define __NR_sendfile 187
-#define __NR_getpmsg 188 /* some people actually want streams */
-#define __NR_putpmsg 189 /* some people actually want streams */
+/* 188 is unused */
+/* 189 is unused */
#define __NR_vfork 190
#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */
#define __NR_mmap2 192
@@ -229,71 +229,71 @@
#define __NR_pivot_root 217
#define __NR_mincore 218
#define __NR_madvise 219
-#define __NR_madvise1 219 /* delete when C lib stub is removed */
#define __NR_getdents64 220
#define __NR_fcntl64 221
-#define __NR_security 223 /* syscall for security modules */
-#define __NR_gettid 224
-#define __NR_readahead 225
-#define __NR_setxattr 226
-#define __NR_lsetxattr 227
-#define __NR_fsetxattr 228
-#define __NR_getxattr 229
-#define __NR_lgetxattr 230
-#define __NR_fgetxattr 231
-#define __NR_listxattr 232
-#define __NR_llistxattr 233
-#define __NR_flistxattr 234
-#define __NR_removexattr 235
-#define __NR_lremovexattr 236
-#define __NR_fremovexattr 237
+/* 222 is unused */
+/* 223 is unused */
+#define __NR_gettid 224
+#define __NR_readahead 225
+#define __NR_setxattr 226
+#define __NR_lsetxattr 227
+#define __NR_fsetxattr 228
+#define __NR_getxattr 229
+#define __NR_lgetxattr 230
+#define __NR_fgetxattr 231
+#define __NR_listxattr 232
+#define __NR_llistxattr 233
+#define __NR_flistxattr 234
+#define __NR_removexattr 235
+#define __NR_lremovexattr 236
+#define __NR_fremovexattr 237
#define __NR_tkill 238
#define __NR_sendfile64 239
#define __NR_futex 240
#define __NR_sched_setaffinity 241
#define __NR_sched_getaffinity 242
-#define __NR_set_thread_area 243
-#define __NR_get_thread_area 244
-#define __NR_io_setup 245
-#define __NR_io_destroy 246
-#define __NR_io_getevents 247
-#define __NR_io_submit 248
-#define __NR_io_cancel 249
-#define __NR_fadvise64 250
-
-#define __NR_exit_group 252
-#define __NR_lookup_dcookie 253
-#define __NR_epoll_create 254
-#define __NR_epoll_ctl 255
-#define __NR_epoll_wait 256
-#define __NR_remap_file_pages 257
-#define __NR_set_tid_address 258
-#define __NR_timer_create 259
-#define __NR_timer_settime (__NR_timer_create+1)
-#define __NR_timer_gettime (__NR_timer_create+2)
-#define __NR_timer_getoverrun (__NR_timer_create+3)
-#define __NR_timer_delete (__NR_timer_create+4)
-#define __NR_clock_settime (__NR_timer_create+5)
-#define __NR_clock_gettime (__NR_timer_create+6)
-#define __NR_clock_getres (__NR_timer_create+7)
-#define __NR_clock_nanosleep (__NR_timer_create+8)
-#define __NR_statfs64 268
-#define __NR_fstatfs64 269
-#define __NR_tgkill 270
-#define __NR_utimes 271
-#define __NR_fadvise64_64 272
-#define __NR_vserver 273
-#define __NR_mbind 274
-#define __NR_get_mempolicy 275
-#define __NR_set_mempolicy 276
-#define __NR_mq_open 277
-#define __NR_mq_unlink (__NR_mq_open+1)
-#define __NR_mq_timedsend (__NR_mq_open+2)
-#define __NR_mq_timedreceive (__NR_mq_open+3)
-#define __NR_mq_notify (__NR_mq_open+4)
-#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_sys_kexec_load 283
-#define __NR_waitid 284
+#define __NR_set_thread_area 243
+#define __NR_get_thread_area 244
+#define __NR_io_setup 245
+#define __NR_io_destroy 246
+#define __NR_io_getevents 247
+#define __NR_io_submit 248
+#define __NR_io_cancel 249
+#define __NR_fadvise64 250
+/* 251 is unused */
+#define __NR_exit_group 252
+#define __NR_lookup_dcookie 253
+#define __NR_epoll_create 254
+#define __NR_epoll_ctl 255
+#define __NR_epoll_wait 256
+#define __NR_remap_file_pages 257
+#define __NR_set_tid_address 258
+#define __NR_timer_create 259
+#define __NR_timer_settime (__NR_timer_create+1)
+#define __NR_timer_gettime (__NR_timer_create+2)
+#define __NR_timer_getoverrun (__NR_timer_create+3)
+#define __NR_timer_delete (__NR_timer_create+4)
+#define __NR_clock_settime (__NR_timer_create+5)
+#define __NR_clock_gettime (__NR_timer_create+6)
+#define __NR_clock_getres (__NR_timer_create+7)
+#define __NR_clock_nanosleep (__NR_timer_create+8)
+#define __NR_statfs64 268
+#define __NR_fstatfs64 269
+#define __NR_tgkill 270
+#define __NR_utimes 271
+#define __NR_fadvise64_64 272
+#define __NR_vserver 273
+#define __NR_mbind 274
+#define __NR_get_mempolicy 275
+#define __NR_set_mempolicy 276
+#define __NR_mq_open 277
+#define __NR_mq_unlink (__NR_mq_open+1)
+#define __NR_mq_timedsend (__NR_mq_open+2)
+#define __NR_mq_timedreceive (__NR_mq_open+3)
+#define __NR_mq_notify (__NR_mq_open+4)
+#define __NR_mq_getsetattr (__NR_mq_open+5)
+#define __NR_sys_kexec_load 283
+#define __NR_waitid 284
#define NR_syscalls 285
@@ -407,14 +407,10 @@ __syscall_return(type,__res); \
#ifdef __KERNEL__
#define __ARCH_WANT_IPC_PARSE_VERSION
-#define __ARCH_WANT_OLD_READDIR
-#define __ARCH_WANT_OLD_STAT
#define __ARCH_WANT_STAT64
#define __ARCH_WANT_SYS_ALARM
#define __ARCH_WANT_SYS_GETHOSTNAME
#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_SGETMASK
-#define __ARCH_WANT_SYS_SIGNAL
#define __ARCH_WANT_SYS_TIME
#define __ARCH_WANT_SYS_UTIME
#define __ARCH_WANT_SYS_WAITPID
@@ -422,11 +418,8 @@ __syscall_return(type,__res); \
#define __ARCH_WANT_SYS_FADVISE64
#define __ARCH_WANT_SYS_GETPGRP
#define __ARCH_WANT_SYS_LLSEEK
-#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLD_GETRLIMIT /*will be unused*/
#define __ARCH_WANT_SYS_OLDUMOUNT
-#define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
#endif
@@ -451,7 +444,6 @@ __syscall_return(type,__res); \
*/
static __inline__ _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
-asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount);
asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff);
@@ -461,7 +453,6 @@ asmlinkage int sys_fork(struct pt_regs regs);
asmlinkage int sys_vfork(struct pt_regs regs);
asmlinkage int sys_pipe(unsigned long __user *fildes);
asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
-asmlinkage long sys_iopl(unsigned long unused);
struct sigaction;
asmlinkage long sys_rt_sigaction(int sig,
const struct sigaction __user *act,
diff --git a/include/asm-m68k/atari_SCCserial.h b/include/asm-m68k/atari_SCCserial.h
deleted file mode 100644
index de3af56c6874..000000000000
--- a/include/asm-m68k/atari_SCCserial.h
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef _ATARI_SCCSERIAL_H
-#define _ATARI_SCCSERIAL_H
-
-/* Special configuration ioctls for the Atari SCC5380 Serial
- * Communications Controller
- */
-
-/* ioctl command codes */
-
-#define TIOCGATSCC 0x54c0 /* get SCC configuration */
-#define TIOCSATSCC 0x54c1 /* set SCC configuration */
-#define TIOCDATSCC 0x54c2 /* reset configuration to defaults */
-
-/* Clock sources */
-
-#define CLK_RTxC 0
-#define CLK_TRxC 1
-#define CLK_PCLK 2
-
-/* baud_bases for the common clocks in the Atari. These are the real
- * frequencies divided by 16.
- */
-
-#define SCC_BAUD_BASE_TIMC 19200 /* 0.3072 MHz from TT-MFP, Timer C */
-#define SCC_BAUD_BASE_BCLK 153600 /* 2.4576 MHz */
-#define SCC_BAUD_BASE_PCLK4 229500 /* 3.6720 MHz */
-#define SCC_BAUD_BASE_PCLK 503374 /* 8.0539763 MHz */
-#define SCC_BAUD_BASE_NONE 0 /* for not connected or unused
- * clock sources */
-
-#define SCC_BAUD_BASE_M147_PCLK 312500 /* 5 MHz */
-#define SCC_BAUD_BASE_M147 312500 /* 5 MHz */
-#define SCC_BAUD_BASE_MVME_PCLK 781250 /* 12.5 MHz */
-#define SCC_BAUD_BASE_MVME 625000 /* 10.000 MHz */
-#define SCC_BAUD_BASE_BVME_PCLK 781250 /* 12.5 MHz */ /* XXX ??? */
-#define SCC_BAUD_BASE_BVME 460800 /* 7.3728 MHz */
-
-/* The SCC configuration structure */
-
-struct atari_SCCserial {
- unsigned RTxC_base; /* base_baud of RTxC */
- unsigned TRxC_base; /* base_baud of TRxC */
- unsigned PCLK_base; /* base_baud of PCLK, for both channels! */
- struct {
- unsigned clksrc; /* CLK_RTxC, CLK_TRxC or CLK_PCLK */
- unsigned divisor; /* divisor for base baud, valid values:
- * see below */
- } baud_table[17]; /* For 50, 75, 110, 135, 150, 200, 300,
- * 600, 1200, 1800, 2400, 4800, 9600,
- * 19200, 38400, 57600 and 115200 bps. The
- * last two could be replaced by other
- * rates > 38400 if they're not possible.
- */
-};
-
-/* The following divisors are valid:
- *
- * - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use
- * the BRG)
- *
- * - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible)
- *
- * - CLK_PCLK: >= 4 and even (no direct modes, only BRG)
- *
- */
-
-#endif /* _ATARI_SCCSERIAL_H */
diff --git a/include/asm-m68k/cputime.h b/include/asm-m68k/cputime.h
new file mode 100644
index 000000000000..c79c5e892305
--- /dev/null
+++ b/include/asm-m68k/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __M68K_CPUTIME_H
+#define __M68K_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __M68K_CPUTIME_H */
diff --git a/include/asm-m68knommu/cputime.h b/include/asm-m68knommu/cputime.h
new file mode 100644
index 000000000000..a0c4a660878d
--- /dev/null
+++ b/include/asm-m68knommu/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __M68KNOMMU_CPUTIME_H
+#define __M68KNOMMU_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __M68KNOMMU_CPUTIME_H */
diff --git a/include/asm-mips/cputime.h b/include/asm-mips/cputime.h
new file mode 100644
index 000000000000..c00eacbdd979
--- /dev/null
+++ b/include/asm-mips/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __MIPS_CPUTIME_H
+#define __MIPS_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __MIPS_CPUTIME_H */
diff --git a/include/asm-parisc/cputime.h b/include/asm-parisc/cputime.h
new file mode 100644
index 000000000000..dcdf2fbd7e72
--- /dev/null
+++ b/include/asm-parisc/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __PARISC_CPUTIME_H
+#define __PARISC_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __PARISC_CPUTIME_H */
diff --git a/include/asm-ppc/cputime.h b/include/asm-ppc/cputime.h
new file mode 100644
index 000000000000..8e9faf5ce720
--- /dev/null
+++ b/include/asm-ppc/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __PPC_CPUTIME_H
+#define __PPC_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __PPC_CPUTIME_H */
diff --git a/include/asm-ppc/reg.h b/include/asm-ppc/reg.h
index 73eab4528eb9..48c0706466ca 100644
--- a/include/asm-ppc/reg.h
+++ b/include/asm-ppc/reg.h
@@ -329,6 +329,7 @@
#define MMCR0_PMC2_CYCLES 0x1
#define MMCR0_PMC2_ITLB 0x7
#define MMCR0_PMC2_LOADMISSTIME 0x5
+#define MMCR0_PMXE (1 << 26)
/* Short-hand versions for a number of the above SPRNs */
#define CTR SPRN_CTR /* Counter Register */
diff --git a/include/asm-ppc64/bug.h b/include/asm-ppc64/bug.h
index 790bc56091d6..db31dd22233c 100644
--- a/include/asm-ppc64/bug.h
+++ b/include/asm-ppc64/bug.h
@@ -18,6 +18,8 @@ struct bug_entry {
const char *function;
};
+struct bug_entry *find_bug(unsigned long bugaddr);
+
/*
* If this bit is set in the line number it means that the trap
* is for WARN_ON rather than BUG or BUG_ON.
diff --git a/include/asm-ppc64/cputime.h b/include/asm-ppc64/cputime.h
new file mode 100644
index 000000000000..8e9faf5ce720
--- /dev/null
+++ b/include/asm-ppc64/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __PPC_CPUTIME_H
+#define __PPC_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __PPC_CPUTIME_H */
diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
index ae1c4fd4a7cf..476d2185ffd1 100644
--- a/include/asm-ppc64/machdep.h
+++ b/include/asm-ppc64/machdep.h
@@ -28,9 +28,10 @@ struct smp_ops_t {
int (*probe)(void);
void (*kick_cpu)(int nr);
void (*setup_cpu)(int nr);
- void (*late_setup_cpu)(int nr);
void (*take_timebase)(void);
void (*give_timebase)(void);
+ int (*cpu_disable)(void);
+ void (*cpu_die)(unsigned int nr);
};
#endif
diff --git a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h
index 51cfa8b72812..c4f9023ea5ed 100644
--- a/include/asm-ppc64/pci-bridge.h
+++ b/include/asm-ppc64/pci-bridge.h
@@ -11,18 +11,10 @@
* 2 of the License, or (at your option) any later version.
*/
-struct device_node;
-struct pci_controller;
-
-/* Get the PCI host controller for an OF device */
-extern struct pci_controller*
-pci_find_hose_for_OF_device(struct device_node* node);
-
/*
* Structure of a PCI controller (host bridge)
*/
struct pci_controller {
- char what[8]; /* Eye catcher */
struct pci_bus *bus;
char is_dynamic;
void *arch_data;
@@ -49,7 +41,6 @@ struct pci_controller {
*/
struct resource io_resource;
struct resource mem_resources[3];
- int mem_resource_count;
int global_number;
int local_number;
unsigned long buid;
@@ -57,14 +48,6 @@ struct pci_controller {
unsigned long dma_window_size;
};
-/*
- * pci_device_loc returns the bus number and device/function number
- * for a device on a PCI bus, given its device_node struct.
- * It returns 0 if OK, -1 on error.
- */
-extern int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
- unsigned char *devfn_ptr);
-
struct device_node *fetch_dev_dn(struct pci_dev *dev);
/* Get a device_node from a pci_dev. This code must be fast except in the case
@@ -72,8 +55,9 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev);
*/
static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
{
- struct device_node *dn = (struct device_node *)(dev->sysdata);
- if (dn->devfn == dev->devfn && dn->busno == (dev->bus->number&0xff))
+ struct device_node *dn = dev->sysdata;
+
+ if (dn->devfn == dev->devfn && dn->busno == dev->bus->number)
return dn; /* fast path. sysdata is good */
else
return fetch_dev_dn(dev);
@@ -102,6 +86,5 @@ static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
return busdn->phb;
}
-
#endif
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
index d5b23b426efa..1cf388538595 100644
--- a/include/asm-ppc64/processor.h
+++ b/include/asm-ppc64/processor.h
@@ -331,8 +331,8 @@
#define MMCR0_FCECE 0x02000000UL /* freeze counters on enabled condition or event */
/* time base exception enable */
#define MMCR0_TBEE 0x00400000UL /* time base exception enable */
-#define MMCR0_PMC1INTCONTROL 0x00008000UL /* PMC1 count enable*/
-#define MMCR0_PMCNINTCONTROL 0x00004000UL /* PMCn count enable*/
+#define MMCR0_PMC1CE 0x00008000UL /* PMC1 count enable*/
+#define MMCR0_PMCjCE 0x00004000UL /* PMCj count enable*/
#define MMCR0_TRIGGER 0x00002000UL /* TRIGGER enable */
#define MMCR0_PMAO 0x00000080UL /* performance monitor alert has occurred, set to 0 after handling exception */
#define MMCR0_SHRFC 0x00000040UL /* SHRre freeze conditions between threads */
diff --git a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h
index a405a871919e..dc2879cc4981 100644
--- a/include/asm-ppc64/rtas.h
+++ b/include/asm-ppc64/rtas.h
@@ -241,4 +241,6 @@ extern void rtas_stop_self(void);
/* RMO buffer reserved for user-space RTAS use */
extern unsigned long rtas_rmo_buf;
+#define GLOBAL_INTERRUPT_QUEUE 9005
+
#endif /* _PPC64_RTAS_H */
diff --git a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h
index 6121d21355bc..965980bbbb57 100644
--- a/include/asm-ppc64/smp.h
+++ b/include/asm-ppc64/smp.h
@@ -38,7 +38,7 @@ struct pt_regs;
extern void smp_message_recv(int, struct pt_regs *);
-#define smp_processor_id() (get_paca()->paca_index)
+#define __smp_processor_id() (get_paca()->paca_index)
#define hard_smp_processor_id() (get_paca()->hw_cpu_id)
extern cpumask_t cpu_sibling_map[NR_CPUS];
diff --git a/include/asm-ppc64/spinlock.h b/include/asm-ppc64/spinlock.h
index 58e5dc61d9d8..e194599dbe50 100644
--- a/include/asm-ppc64/spinlock.h
+++ b/include/asm-ppc64/spinlock.h
@@ -222,8 +222,6 @@ static void __inline__ _raw_read_unlock(rwlock_t *rw)
: "cr0", "memory");
}
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
-
/*
* This returns the old value in the lock,
* so we got the write lock if the return value is 0.
diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h
index dc3153fa414e..6785e69e8b9e 100644
--- a/include/asm-ppc64/system.h
+++ b/include/asm-ppc64/system.h
@@ -108,7 +108,6 @@ extern void show_regs(struct pt_regs * regs);
extern void low_hash_fault(struct pt_regs *regs, unsigned long address);
extern int die(const char *str, struct pt_regs *regs, long err);
-extern void flush_instruction_cache(void);
extern int _get_PVR(void);
extern void giveup_fpu(struct task_struct *);
extern void disable_kernel_fp(void);
diff --git a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h
index 595d67ef4b6f..e823d119ffcf 100644
--- a/include/asm-ppc64/thread_info.h
+++ b/include/asm-ppc64/thread_info.h
@@ -12,6 +12,7 @@
#ifndef __ASSEMBLY__
#include <linux/config.h>
+#include <linux/cache.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <linux/stringify.h>
@@ -22,12 +23,13 @@
struct thread_info {
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
- unsigned long flags; /* low level flags */
int cpu; /* cpu we're on */
int preempt_count;
struct restart_block restart_block;
/* set by force_successful_syscall_return */
unsigned char syscall_noerror;
+ /* low level flags - has atomic operations done on it */
+ unsigned long flags ____cacheline_aligned_in_smp;
};
/*
@@ -39,12 +41,12 @@ struct thread_info {
{ \
.task = &tsk, \
.exec_domain = &default_exec_domain, \
- .flags = 0, \
.cpu = 0, \
.preempt_count = 1, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
+ .flags = 0, \
}
#define init_thread_info (init_thread_union.thread_info)
diff --git a/include/asm-ppc64/tlbflush.h b/include/asm-ppc64/tlbflush.h
index 183bdfba9f0c..45411a67e082 100644
--- a/include/asm-ppc64/tlbflush.h
+++ b/include/asm-ppc64/tlbflush.h
@@ -32,10 +32,11 @@ extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch);
static inline void flush_tlb_pending(void)
{
- struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
+ struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch);
if (batch->index)
__flush_tlb_pending(batch);
+ put_cpu_var(ppc64_tlb_batch);
}
#define flush_tlb_mm(mm) flush_tlb_pending()
diff --git a/include/asm-ppc64/xics.h b/include/asm-ppc64/xics.h
index 560f4fd99e21..0027da4364ac 100644
--- a/include/asm-ppc64/xics.h
+++ b/include/asm-ppc64/xics.h
@@ -18,6 +18,8 @@ void xics_init_IRQ(void);
int xics_get_irq(struct pt_regs *);
void xics_setup_cpu(void);
void xics_cause_IPI(int cpu);
+void xics_request_IPIs(void);
+void xics_migrate_irqs_away(void);
/* first argument is ignored for now*/
void pSeriesLP_cppr_info(int n_cpu, u8 value);
@@ -28,4 +30,7 @@ struct xics_ipi_struct {
extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
+extern unsigned int default_distrib_server;
+extern unsigned int interrupt_server_size;
+
#endif /* _PPC64_KERNEL_XICS_H */
diff --git a/include/asm-s390/cputime.h b/include/asm-s390/cputime.h
new file mode 100644
index 000000000000..216d861337e6
--- /dev/null
+++ b/include/asm-s390/cputime.h
@@ -0,0 +1,168 @@
+/*
+ * include/asm-s390/cputime.h
+ *
+ * (C) Copyright IBM Corp. 2004
+ *
+ * Author: Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef _S390_CPUTIME_H
+#define _S390_CPUTIME_H
+
+/* We want to use micro-second resolution. */
+
+typedef unsigned long long cputime_t;
+typedef unsigned long long cputime64_t;
+
+#ifndef __s390x__
+
+static inline unsigned int
+__div(unsigned long long n, unsigned int base)
+{
+ register_pair rp;
+
+ rp.pair = n >> 1;
+ asm ("dr %0,%1" : "+d" (rp) : "d" (base >> 1));
+ return rp.subreg.odd;
+}
+
+#else /* __s390x__ */
+
+static inline unsigned int
+__div(unsigned long long n, unsigned int base)
+{
+ return n / base;
+}
+
+#endif /* __s390x__ */
+
+#define cputime_zero (0ULL)
+#define cputime_max ((~0UL >> 1) - 1)
+#define cputime_add(__a, __b) ((__a) + (__b))
+#define cputime_sub(__a, __b) ((__a) - (__b))
+#define cputime_eq(__a, __b) ((__a) == (__b))
+#define cputime_gt(__a, __b) ((__a) > (__b))
+#define cputime_ge(__a, __b) ((__a) >= (__b))
+#define cputime_lt(__a, __b) ((__a) < (__b))
+#define cputime_le(__a, __b) ((__a) <= (__b))
+#define cputime_to_jiffies(__ct) (__div((__ct), 1000000 / HZ))
+#define jiffies_to_cputime(__hz) ((cputime_t)(__hz) * (1000000 / HZ))
+
+#define cputime64_zero (0ULL)
+#define cputime64_add(__a, __b) ((__a) + (__b))
+#define cputime_to_cputime64(__ct) (__ct)
+
+static inline u64
+cputime64_to_jiffies64(cputime64_t cputime)
+{
+ do_div(cputime, 1000000 / HZ);
+ return cputime;
+}
+
+/*
+ * Convert cputime to milliseconds and back.
+ */
+static inline unsigned int
+cputime_to_msecs(const cputime_t cputime)
+{
+ return __div(cputime, 1000);
+}
+
+static inline cputime_t
+msecs_to_cputime(const unsigned int m)
+{
+ return (cputime_t) m * 1000;
+}
+
+/*
+ * Convert cputime to milliseconds and back.
+ */
+static inline unsigned int
+cputime_to_secs(const cputime_t cputime)
+{
+ return __div(cputime, 1000000);
+}
+
+static inline cputime_t
+secs_to_cputime(const unsigned int s)
+{
+ return (cputime_t) s * 1000000;
+}
+
+/*
+ * Convert cputime to timespec and back.
+ */
+static inline cputime_t
+timespec_to_cputime(const struct timespec *value)
+{
+ return value->tv_nsec / 1000 + (u64) value->tv_sec * 1000000;
+}
+
+static inline void
+cputime_to_timespec(const cputime_t cputime, struct timespec *value)
+{
+#ifndef __s390x__
+ register_pair rp;
+
+ rp.pair = cputime >> 1;
+ asm ("dr %0,%1" : "+d" (rp) : "d" (1000000 >> 1));
+ value->tv_nsec = rp.subreg.even * 1000;
+ value->tv_sec = rp.subreg.odd;
+#else
+ value->tv_nsec = (cputime % 1000000) * 1000;
+ value->tv_sec = cputime / 1000000;
+#endif
+}
+
+/*
+ * Convert cputime to timeval and back.
+ * Since cputime and timeval have the same resolution (microseconds)
+ * this is easy.
+ */
+static inline cputime_t
+timeval_to_cputime(const struct timeval *value)
+{
+ return value->tv_usec + (u64) value->tv_sec * 1000000;
+}
+
+static inline void
+cputime_to_timeval(const cputime_t cputime, struct timeval *value)
+{
+#ifndef __s390x__
+ register_pair rp;
+
+ rp.pair = cputime >> 1;
+ asm ("dr %0,%1" : "+d" (rp) : "d" (1000000 >> 1));
+ value->tv_usec = rp.subreg.even;
+ value->tv_sec = rp.subreg.odd;
+#else
+ value->tv_usec = cputime % 1000000;
+ value->tv_sec = cputime / 1000000;
+#endif
+}
+
+/*
+ * Convert cputime to clock and back.
+ */
+static inline clock_t
+cputime_to_clock_t(cputime_t cputime)
+{
+ return __div(cputime, 1000000 / USER_HZ);
+}
+
+static inline cputime_t
+clock_t_to_cputime(unsigned long x)
+{
+ return (cputime_t) x * (1000000 / USER_HZ);
+}
+
+/*
+ * Convert cputime64 to clock.
+ */
+static inline clock_t
+cputime64_to_clock_t(cputime64_t cputime)
+{
+ return __div(cputime, 1000000 / USER_HZ);
+}
+
+#endif /* _S390_CPUTIME_H */
diff --git a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h
index 1580b7b2b05e..53e59b4760c5 100644
--- a/include/asm-s390/hardirq.h
+++ b/include/asm-s390/hardirq.h
@@ -16,6 +16,7 @@
#include <linux/threads.h>
#include <linux/sched.h>
#include <linux/cache.h>
+#include <linux/interrupt.h>
#include <asm/lowcore.h>
/* irq_cpustat_t is unused currently, but could be converted
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index 0aa1c0f1e705..df5172fc589d 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -56,13 +56,18 @@
#define __LC_RETURN_PSW 0x200
-#define __LC_IRB 0x210
-
-#define __LC_DIAG44_OPCODE 0x250
-
#define __LC_SAVE_AREA 0xC00
#ifndef __s390x__
+#define __LC_IRB 0x208
+#define __LC_SYNC_ENTER_TIMER 0x248
+#define __LC_ASYNC_ENTER_TIMER 0x250
+#define __LC_EXIT_TIMER 0x258
+#define __LC_LAST_UPDATE_TIMER 0x260
+#define __LC_USER_TIMER 0x268
+#define __LC_SYSTEM_TIMER 0x270
+#define __LC_LAST_UPDATE_CLOCK 0x278
+#define __LC_STEAL_CLOCK 0x280
#define __LC_KERNEL_STACK 0xC40
#define __LC_THREAD_INFO 0xC44
#define __LC_ASYNC_STACK 0xC48
@@ -76,6 +81,16 @@
#define __LC_CURRENT 0xC90
#define __LC_INT_CLOCK 0xC98
#else /* __s390x__ */
+#define __LC_IRB 0x210
+#define __LC_SYNC_ENTER_TIMER 0x250
+#define __LC_ASYNC_ENTER_TIMER 0x258
+#define __LC_EXIT_TIMER 0x260
+#define __LC_LAST_UPDATE_TIMER 0x268
+#define __LC_USER_TIMER 0x270
+#define __LC_SYSTEM_TIMER 0x278
+#define __LC_LAST_UPDATE_CLOCK 0x280
+#define __LC_STEAL_CLOCK 0x288
+#define __LC_DIAG44_OPCODE 0x290
#define __LC_KERNEL_STACK 0xD40
#define __LC_THREAD_INFO 0xD48
#define __LC_ASYNC_STACK 0xD50
@@ -87,7 +102,7 @@
#define __LC_IPLDEV 0xDB8
#define __LC_JIFFY_TIMER 0xDC0
#define __LC_CURRENT 0xDD8
-#define __LC_INT_CLOCK 0xDe8
+#define __LC_INT_CLOCK 0xDE8
#endif /* __s390x__ */
#define __LC_PANIC_MAGIC 0xE00
@@ -169,7 +184,15 @@ struct _lowcore
psw_t return_psw; /* 0x200 */
__u8 irb[64]; /* 0x208 */
- __u8 pad8[0xc00-0x248]; /* 0x248 */
+ __u64 sync_enter_timer; /* 0x248 */
+ __u64 async_enter_timer; /* 0x250 */
+ __u64 exit_timer; /* 0x258 */
+ __u64 last_update_timer; /* 0x260 */
+ __u64 user_timer; /* 0x268 */
+ __u64 system_timer; /* 0x270 */
+ __u64 last_update_clock; /* 0x278 */
+ __u64 steal_clock; /* 0x280 */
+ __u8 pad8[0xc00-0x288]; /* 0x288 */
/* System info area */
__u32 save_area[16]; /* 0xc00 */
@@ -250,8 +273,16 @@ struct _lowcore
psw_t io_new_psw; /* 0x1f0 */
psw_t return_psw; /* 0x200 */
__u8 irb[64]; /* 0x210 */
- __u32 diag44_opcode; /* 0x250 */
- __u8 pad8[0xc00-0x254]; /* 0x254 */
+ __u64 sync_enter_timer; /* 0x250 */
+ __u64 async_enter_timer; /* 0x258 */
+ __u64 exit_timer; /* 0x260 */
+ __u64 last_update_timer; /* 0x268 */
+ __u64 user_timer; /* 0x270 */
+ __u64 system_timer; /* 0x278 */
+ __u64 last_update_clock; /* 0x280 */
+ __u64 steal_clock; /* 0x288 */
+ __u32 diag44_opcode; /* 0x290 */
+ __u8 pad8[0xc00-0x294]; /* 0x294 */
/* System info area */
__u64 save_area[16]; /* 0xc00 */
__u8 pad9[0xd40-0xc80]; /* 0xc80 */
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index d9f3498136e1..e8596077e057 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -105,11 +105,29 @@ static inline void restore_access_regs(unsigned int *acrs)
#define prepare_arch_switch(rq, next) do { } while(0)
#define task_running(rq, p) ((rq)->curr == (p))
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+extern void account_user_vtime(struct task_struct *);
+extern void account_system_vtime(struct task_struct *);
+
+#define finish_arch_switch(rq, prev) do { \
+ set_fs(current->thread.mm_segment); \
+ spin_unlock(&(rq)->lock); \
+ account_system_vtime(prev); \
+ local_irq_enable(); \
+} while (0)
+
+#else
+
+#define account_system_vtime(prev)
+
#define finish_arch_switch(rq, prev) do { \
set_fs(current->thread.mm_segment); \
spin_unlock_irq(&(rq)->lock); \
} while (0)
+#endif
+
#define nop() __asm__ __volatile__ ("nop")
#define xchg(ptr,x) \
diff --git a/include/asm-s390/timer.h b/include/asm-s390/timer.h
index 454d1ea85c54..ea0788967c51 100644
--- a/include/asm-s390/timer.h
+++ b/include/asm-s390/timer.h
@@ -37,8 +37,6 @@ struct vtimer_queue {
__u64 idle; /* temp var for idle */
};
-void set_vtimer(__u64 expires);
-
extern void init_virt_timer(struct vtimer_list *timer);
extern void add_virt_timer(void *new);
extern void add_virt_timer_periodic(void *new);
diff --git a/include/asm-sh/cputime.h b/include/asm-sh/cputime.h
new file mode 100644
index 000000000000..6ca395d1393e
--- /dev/null
+++ b/include/asm-sh/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __SH_CPUTIME_H
+#define __SH_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __SH_CPUTIME_H */
diff --git a/include/asm-sh64/cputime.h b/include/asm-sh64/cputime.h
new file mode 100644
index 000000000000..0fd89da2aa86
--- /dev/null
+++ b/include/asm-sh64/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __SH64_CPUTIME_H
+#define __SH64_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __SH64_CPUTIME_H */
diff --git a/include/asm-sparc/cputime.h b/include/asm-sparc/cputime.h
new file mode 100644
index 000000000000..1a642b81e019
--- /dev/null
+++ b/include/asm-sparc/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __SPARC_CPUTIME_H
+#define __SPARC_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __SPARC_CPUTIME_H */
diff --git a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h
index 1289af2416c7..74850fac74c2 100644
--- a/include/asm-sparc64/bitops.h
+++ b/include/asm-sparc64/bitops.h
@@ -223,7 +223,8 @@ extern unsigned long find_next_bit(const unsigned long *, unsigned long,
* on Linus's ALPHA routines, which are pretty portable BTW.
*/
-extern unsigned long find_next_zero_bit(unsigned long *, unsigned long, unsigned long);
+extern unsigned long find_next_zero_bit(const unsigned long *,
+ unsigned long, unsigned long);
#define find_first_zero_bit(addr, size) \
find_next_zero_bit((addr), (size), 0)
diff --git a/include/asm-sparc64/cputime.h b/include/asm-sparc64/cputime.h
new file mode 100644
index 000000000000..dec2fc7a36f8
--- /dev/null
+++ b/include/asm-sparc64/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __SPARC64_CPUTIME_H
+#define __SPARC64_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __SPARC64_CPUTIME_H */
diff --git a/include/asm-um/apic.h b/include/asm-um/apic.h
new file mode 100644
index 000000000000..876dee84ab11
--- /dev/null
+++ b/include/asm-um/apic.h
@@ -0,0 +1,4 @@
+#ifndef __UM_APIC_H
+#define __UM_APIC_H
+
+#endif
diff --git a/include/asm-um/archparam-i386.h b/include/asm-um/archparam-i386.h
index 0d3bad3efc3f..5b5df118d9a5 100644
--- a/include/asm-um/archparam-i386.h
+++ b/include/asm-um/archparam-i386.h
@@ -66,6 +66,13 @@ extern unsigned long __kernel_vsyscall;
#define VSYSCALL_END vsyscall_end
/*
+ * This is the range that is readable by user mode, and things
+ * acting like user mode such as get_user_pages.
+ */
+#define FIXADDR_USER_START VSYSCALL_BASE
+#define FIXADDR_USER_END VSYSCALL_END
+
+/*
* Architecture-neutral AT_ values in 0-17, leave some room
* for more of them, start the x86-specific ones at 32.
*/
@@ -136,10 +143,6 @@ if ( vsyscall_ehdr ) { \
#define R_386_GOTPC 10
#define R_386_NUM 11
-/********* Bits for asm-um/delay.h **********/
-
-typedef unsigned long um_udelay_t;
-
/********* Nothing for asm-um/hardirq.h **********/
/********* Nothing for asm-um/hw_irq.h **********/
diff --git a/include/asm-um/archparam-ppc.h b/include/asm-um/archparam-ppc.h
index 9b8b27e29551..0ebced92a762 100644
--- a/include/asm-um/archparam-ppc.h
+++ b/include/asm-um/archparam-ppc.h
@@ -21,10 +21,6 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_PPC
-/********* Bits for asm-um/delay.h **********/
-
-typedef unsigned int um_udelay_t;
-
/********* Bits for asm-um/hw_irq.h **********/
struct hw_interrupt_type;
diff --git a/include/asm-um/archparam-x86_64.h b/include/asm-um/archparam-x86_64.h
new file mode 100644
index 000000000000..96321c4892f1
--- /dev/null
+++ b/include/asm-um/archparam-x86_64.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_ARCHPARAM_X86_64_H
+#define __UM_ARCHPARAM_X86_64_H
+
+#include <asm/user.h>
+
+#define ELF_PLATFORM "x86_64"
+
+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
+
+typedef unsigned long elf_greg_t;
+typedef struct { } elf_fpregset_t;
+
+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+#define ELF_DATA ELFDATA2LSB
+#define ELF_ARCH EM_X86_64
+
+#define ELF_PLAT_INIT(regs, load_addr) do { \
+ PT_REGS_RBX(regs) = 0; \
+ PT_REGS_RCX(regs) = 0; \
+ PT_REGS_RDX(regs) = 0; \
+ PT_REGS_RSI(regs) = 0; \
+ PT_REGS_RDI(regs) = 0; \
+ PT_REGS_RBP(regs) = 0; \
+ PT_REGS_RAX(regs) = 0; \
+ PT_REGS_R8(regs) = 0; \
+ PT_REGS_R9(regs) = 0; \
+ PT_REGS_R10(regs) = 0; \
+ PT_REGS_R11(regs) = 0; \
+ PT_REGS_R12(regs) = 0; \
+ PT_REGS_R13(regs) = 0; \
+ PT_REGS_R14(regs) = 0; \
+ PT_REGS_R15(regs) = 0; \
+} while (0)
+
+#ifdef TIF_IA32 /* XXX */
+ clear_thread_flag(TIF_IA32);
+#endif
+
+/* No user-accessible fixmap addresses, i.e. vsyscall */
+#define FIXADDR_USER_START 0
+#define FIXADDR_USER_END 0
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/include/asm-um/calling.h b/include/asm-um/calling.h
new file mode 100644
index 000000000000..0b2384cc99fd
--- /dev/null
+++ b/include/asm-um/calling.h
@@ -0,0 +1,9 @@
+# Copyright 2003 - 2004 Pathscale, Inc
+# Released under the GPL
+
+#ifndef __UM_CALLING_H /* XXX x86_64 */
+#define __UM_CALLING_H
+
+#include "asm/arch/calling.h"
+
+#endif
diff --git a/include/asm-um/cputime.h b/include/asm-um/cputime.h
new file mode 100644
index 000000000000..c84acbadfa2f
--- /dev/null
+++ b/include/asm-um/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __UM_CPUTIME_H
+#define __UM_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __UM_CPUTIME_H */
diff --git a/include/asm-um/dwarf2.h b/include/asm-um/dwarf2.h
new file mode 100644
index 000000000000..d1a02e762931
--- /dev/null
+++ b/include/asm-um/dwarf2.h
@@ -0,0 +1,11 @@
+/* Copyright 2003 - 2004 Pathscale, Inc
+ * Released under the GPL
+ */
+
+/* Needed on x86_64 by thunk.S */
+#ifndef __UM_DWARF2_H
+#define __UM_DWARF2_H
+
+#include "asm/arch/dwarf2.h"
+
+#endif
diff --git a/include/asm-um/elf.h b/include/asm-um/elf.h
index b689a770a83f..b3a7258f9971 100644
--- a/include/asm-um/elf.h
+++ b/include/asm-um/elf.h
@@ -1,6 +1,7 @@
#ifndef __UM_ELF_H
#define __UM_ELF_H
+#include "linux/config.h"
#include "asm/archparam.h"
extern long elf_aux_hwcap;
@@ -12,7 +13,11 @@ extern long elf_aux_hwcap;
#define elf_check_arch(x) (1)
+#ifdef CONFIG_64_BIT
+#define ELF_CLASS ELFCLASS64
+#else
#define ELF_CLASS ELFCLASS32
+#endif
#define USE_ELF_CORE_DUMP
diff --git a/include/asm-um/fixmap.h b/include/asm-um/fixmap.h
index 0fb5779088b0..900f3fbb9fab 100644
--- a/include/asm-um/fixmap.h
+++ b/include/asm-um/fixmap.h
@@ -64,13 +64,6 @@ extern unsigned long get_kmem_end(void);
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
-/*
- * This is the range that is readable by user mode, and things
- * acting like user mode such as get_user_pages.
- */
-#define FIXADDR_USER_START VSYSCALL_BASE
-#define FIXADDR_USER_END VSYSCALL_END
-
extern void __this_fixmap_does_not_exist(void);
/*
diff --git a/include/asm-um/module-x86_64.h b/include/asm-um/module-x86_64.h
new file mode 100644
index 000000000000..35b5491d3e96
--- /dev/null
+++ b/include/asm-um/module-x86_64.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_MODULE_X86_64_H
+#define __UM_MODULE_X86_64_H
+
+/* UML is simple */
+struct mod_arch_specific
+{
+};
+
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define Elf_Ehdr Elf64_Ehdr
+
+#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/include/asm-um/page.h b/include/asm-um/page.h
index f69b0f1c270e..3620a08dc9f3 100644
--- a/include/asm-um/page.h
+++ b/include/asm-um/page.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright 2003 PathScale, Inc.
* Licensed under the GPL
*/
@@ -8,18 +9,82 @@
struct page;
-#include "asm/arch/page.h"
+#include <linux/config.h>
+#include <asm/vm-flags.h>
-#undef __pa
-#undef __va
-#undef pfn_to_page
-#undef page_to_pfn
-#undef virt_to_page
-#undef pfn_valid
-#undef virt_addr_valid
-#undef VALID_PAGE
-#undef PAGE_OFFSET
-#undef KERNELBASE
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+/*
+ * These are used to make use of C type-checking..
+ */
+
+#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+
+#define clear_user_page(page, vaddr, pg) clear_page(page)
+#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
+
+#if defined(CONFIG_3_LEVEL_PGTABLES) && !defined(CONFIG_64_BIT)
+
+typedef struct { unsigned long pte_low, pte_high; } pte_t;
+typedef struct { unsigned long long pmd; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+#define pte_val(x) ((x).pte_low | ((unsigned long long) (x).pte_high << 32))
+
+#define pte_get_bits(pte, bits) ((pte).pte_low & (bits))
+#define pte_set_bits(pte, bits) ((pte).pte_low |= (bits))
+#define pte_clear_bits(pte, bits) ((pte).pte_low &= ~(bits))
+#define pte_copy(to, from) ({ (to).pte_high = (from).pte_high; \
+ smp_wmb(); \
+ (to).pte_low = (from).pte_low; })
+#define pte_is_zero(pte) (!((pte).pte_low & ~_PAGE_NEWPAGE) && !(pte).pte_high)
+#define pte_set_val(pte, phys, prot) \
+ ({ (pte).pte_high = (phys) >> 32; \
+ (pte).pte_low = (phys) | pgprot_val(prot); })
+
+typedef unsigned long long pfn_t;
+typedef unsigned long long phys_t;
+
+#else
+
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pgd; } pgd_t;
+
+#ifdef CONFIG_3_LEVEL_PGTABLES
+typedef struct { unsigned long pmd; } pmd_t;
+#define pmd_val(x) ((x).pmd)
+#define __pmd(x) ((pmd_t) { (x) } )
+#endif
+
+#define pte_val(x) ((x).pte)
+
+
+#define pte_get_bits(p, bits) ((p).pte & (bits))
+#define pte_set_bits(p, bits) ((p).pte |= (bits))
+#define pte_clear_bits(p, bits) ((p).pte &= ~(bits))
+#define pte_copy(to, from) ((to).pte = (from).pte)
+#define pte_is_zero(p) (!((p).pte & ~_PAGE_NEWPAGE))
+#define pte_set_val(p, phys, prot) (p).pte = (phys | pgprot_val(prot))
+
+typedef unsigned long pfn_t;
+typedef unsigned long phys_t;
+
+#endif
+
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pgd_val(x) ((x).pgd)
+#define pgprot_val(x) ((x).pgprot)
+
+#define __pte(x) ((pte_t) { (x) } )
+#define __pgd(x) ((pgd_t) { (x) } )
+#define __pgprot(x) ((pgprot_t) { (x) } )
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
extern unsigned long uml_physmem;
@@ -30,7 +95,6 @@ extern unsigned long uml_physmem;
extern unsigned long to_phys(void *virt);
extern void *to_virt(unsigned long phys);
-
#define __pa(virt) to_phys((void *) virt)
#define __va(phys) to_virt((unsigned long) phys)
@@ -42,7 +106,21 @@ extern void *to_virt(unsigned long phys);
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))
-
+
+/* Pure 2^n version of get_order */
+static __inline__ int get_order(unsigned long size)
+{
+ int order;
+
+ size = (size-1) >> (PAGE_SHIFT-1);
+ order = -1;
+ do {
+ size >>= 1;
+ order++;
+ } while (size);
+ return order;
+}
+
extern struct page *arch_validate(struct page *page, int mask, int order);
#define HAVE_ARCH_VALIDATE
diff --git a/include/asm-um/pda.h b/include/asm-um/pda.h
new file mode 100644
index 000000000000..0d8bf33ffd42
--- /dev/null
+++ b/include/asm-um/pda.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PDA_X86_64_H
+#define __UM_PDA_X86_64_H
+
+/* XXX */
+struct foo {
+ unsigned int __softirq_pending;
+ unsigned int __nmi_count;
+};
+
+extern struct foo me;
+
+#define read_pda(me) (&me)
+
+#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/include/asm-um/pgalloc.h b/include/asm-um/pgalloc.h
index 73973aeaf482..8fcb2fc0a892 100644
--- a/include/asm-um/pgalloc.h
+++ b/include/asm-um/pgalloc.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright 2003 PathScale, Inc.
* Derived from include/asm-i386/pgalloc.h and include/asm-i386/pgtable.h
* Licensed under the GPL
*/
@@ -7,18 +8,21 @@
#ifndef __UM_PGALLOC_H
#define __UM_PGALLOC_H
+#include "linux/config.h"
#include "linux/mm.h"
#include "asm/fixmap.h"
#define pmd_populate_kernel(mm, pmd, pte) \
- set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) __pa(pte)))
+ set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) __pa(pte)))
-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
- struct page *pte)
-{
- set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte)));
-}
+#define pmd_populate(mm, pmd, pte) \
+ set_pmd(pmd, __pmd(_PAGE_TABLE + \
+ ((unsigned long long)page_to_pfn(pte) << \
+ (unsigned long long) PAGE_SHIFT)))
+/*
+ * Allocate and free page tables.
+ */
extern pgd_t *pgd_alloc(struct mm_struct *);
extern void pgd_free(pgd_t *pgd);
@@ -37,15 +41,13 @@ static inline void pte_free(struct page *pte)
#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
+#ifdef CONFIG_3_LEVEL_PGTABLES
/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
+ * In the 3-level case we free the pmds as part of the pgd.
*/
-
-#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
#define pmd_free(x) do { } while (0)
#define __pmd_free_tlb(tlb,x) do { } while (0)
-#define pgd_populate(mm, pmd, pte) BUG()
+#endif
#define check_pgt_cache() do { } while (0)
diff --git a/include/asm-um/pgtable-2level.h b/include/asm-um/pgtable-2level.h
new file mode 100644
index 000000000000..f6263d11f205
--- /dev/null
+++ b/include/asm-um/pgtable-2level.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright 2003 PathScale, Inc.
+ * Derived from include/asm-i386/pgtable.h
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PGTABLE_2LEVEL_H
+#define __UM_PGTABLE_2LEVEL_H
+
+#include <asm-generic/pgtable-nopmd.h>
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+
+#define PGDIR_SHIFT 22
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+
+/*
+ * entries per page directory level: the i386 is two-level, so
+ * we don't really have any PMD directory physically.
+ */
+#define PTRS_PER_PTE 1024
+#define PTRS_PER_PMD 1
+#define USER_PTRS_PER_PGD ((TASK_SIZE + (PGDIR_SIZE - 1)) / PGDIR_SIZE)
+#define PTRS_PER_PGD 1024
+#define FIRST_USER_PGD_NR 0
+
+#define pte_ERROR(e) \
+ printk("%s:%d: bad pte %p(%08lx).\n", __FILE__, __LINE__, &(e), \
+ pte_val(e))
+#define pgd_ERROR(e) \
+ printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), \
+ pgd_val(e))
+
+static inline int pgd_newpage(pgd_t pgd) { return 0; }
+static inline void pgd_mkuptodate(pgd_t pgd) { }
+
+#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
+
+static inline pte_t pte_mknewprot(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_NEWPROT;
+ return(pte);
+}
+
+static inline pte_t pte_mknewpage(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_NEWPAGE;
+ return(pte);
+}
+
+static inline void set_pte(pte_t *pteptr, pte_t pteval)
+{
+ /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so
+ * fix_range knows to unmap it. _PAGE_NEWPROT is specific to
+ * mapped pages.
+ */
+ *pteptr = pte_mknewpage(pteval);
+ if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
+}
+
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
+
+#define pte_page(x) pfn_to_page(pte_pfn(x))
+#define pte_none(x) !(pte_val(x) & ~_PAGE_NEWPAGE)
+#define pte_pfn(x) phys_to_pfn(pte_val(x))
+#define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot))
+#define pfn_pmd(pfn, prot) __pmd(pfn_to_phys(pfn) | pgprot_val(prot))
+
+#define pmd_page_kernel(pmd) \
+ ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
+/*
+ * Bits 0 through 3 are taken
+ */
+#define PTE_FILE_MAX_BITS 28
+
+#define pte_to_pgoff(pte) (pte_val(pte) >> 4)
+
+#define pgoff_to_pte(off) ((pte_t) { ((off) << 4) + _PAGE_FILE })
+
+#endif
diff --git a/include/asm-um/pgtable-3level.h b/include/asm-um/pgtable-3level.h
new file mode 100644
index 000000000000..acebb593cfd6
--- /dev/null
+++ b/include/asm-um/pgtable-3level.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2003 PathScale Inc
+ * Derived from include/asm-i386/pgtable.h
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PGTABLE_3LEVEL_H
+#define __UM_PGTABLE_3LEVEL_H
+
+#include <asm-generic/pgtable-nopud.h>
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+
+#define PGDIR_SHIFT 30
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+
+/* PMD_SHIFT determines the size of the area a second-level page table can
+ * map
+ */
+
+#define PMD_SHIFT 21
+#define PMD_SIZE (1UL << PMD_SHIFT)
+#define PMD_MASK (~(PMD_SIZE-1))
+
+/*
+ * entries per page directory level
+ */
+
+#define PTRS_PER_PTE 512
+#define PTRS_PER_PMD 512
+#define USER_PTRS_PER_PGD ((TASK_SIZE + (PGDIR_SIZE - 1)) / PGDIR_SIZE)
+#define PTRS_PER_PGD 512
+#define FIRST_USER_PGD_NR 0
+
+#define pte_ERROR(e) \
+ printk("%s:%d: bad pte %p(%016lx).\n", __FILE__, __LINE__, &(e), \
+ pte_val(e))
+#define pmd_ERROR(e) \
+ printk("%s:%d: bad pmd %p(%016lx).\n", __FILE__, __LINE__, &(e), \
+ pmd_val(e))
+#define pgd_ERROR(e) \
+ printk("%s:%d: bad pgd %p(%016lx).\n", __FILE__, __LINE__, &(e), \
+ pgd_val(e))
+
+#define pud_none(x) (!(pud_val(x) & ~_PAGE_NEWPAGE))
+#define pud_bad(x) ((pud_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
+#define pud_present(x) (pud_val(x) & _PAGE_PRESENT)
+#define pud_populate(mm, pud, pmd) \
+ set_pud(pud, __pud(_PAGE_TABLE + __pa(pmd)))
+
+#define set_pud(pudptr, pudval) set_64bit((phys_t *) (pudptr), pud_val(pudval))
+static inline int pgd_newpage(pgd_t pgd)
+{
+ return(pgd_val(pgd) & _PAGE_NEWPAGE);
+}
+
+static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEWPAGE; }
+
+
+#define pte_present(x) pte_get_bits(x, (_PAGE_PRESENT | _PAGE_PROTNONE))
+
+static inline pte_t pte_mknewprot(pte_t pte)
+{
+ pte_set_bits(pte, _PAGE_NEWPROT);
+ return(pte);
+}
+
+static inline pte_t pte_mknewpage(pte_t pte)
+{
+ pte_set_bits(pte, _PAGE_NEWPAGE);
+ return(pte);
+}
+
+static inline void set_pte(pte_t *pteptr, pte_t pteval)
+{
+ pte_copy(*pteptr, pteval);
+
+ /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so
+ * fix_range knows to unmap it. _PAGE_NEWPROT is specific to
+ * mapped pages.
+ */
+
+ *pteptr = pte_mknewpage(*pteptr);
+ if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
+}
+
+#define set_pmd(pmdptr, pmdval) set_64bit((phys_t *) (pmdptr), pmd_val(pmdval))
+
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
+
+ if(pmd)
+ memset(pmd, 0, PAGE_SIZE);
+
+ return pmd;
+}
+
+static inline void pmd_free(pmd_t *pmd){
+ free_page((unsigned long) pmd);
+}
+
+#define __pmd_free_tlb(tlb,x) do { } while (0)
+
+static inline void pud_clear (pud_t * pud) { }
+
+#define pud_page(pud) \
+ ((struct page *) __va(pud_val(pud) & PAGE_MASK))
+
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
+ pmd_index(address))
+
+#define pte_page(x) pfn_to_page(pte_pfn(x))
+
+static inline int pte_none(pte_t pte)
+{
+ return pte_is_zero(pte);
+}
+
+static inline unsigned long pte_pfn(pte_t pte)
+{
+ return phys_to_pfn(pte_val(pte));
+}
+
+static inline pte_t pfn_pte(pfn_t page_nr, pgprot_t pgprot)
+{
+ pte_t pte;
+ phys_t phys = pfn_to_phys(page_nr);
+
+ pte_set_val(pte, phys, pgprot);
+ return pte;
+}
+
+static inline pmd_t pfn_pmd(pfn_t page_nr, pgprot_t pgprot)
+{
+ return __pmd((page_nr << PAGE_SHIFT) | pgprot_val(pgprot));
+}
+
+/*
+ * Bits 0 through 3 are taken in the low part of the pte,
+ * put the 32 bits of offset into the high part.
+ */
+#define PTE_FILE_MAX_BITS 32
+
+#ifdef CONFIG_64_BIT
+
+#define pte_to_pgoff(p) ((p).pte >> 32)
+
+#define pgoff_to_pte(off) ((pte_t) { ((off) < 32) | _PAGE_FILE })
+
+#else
+
+#define pte_to_pgoff(pte) ((pte).pte_high)
+
+#define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) })
+
+#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/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index a747f7dd4ff4..7f980a262334 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright 2003 PathScale, Inc.
* Derived from include/asm-i386/pgtable.h
* Licensed under the GPL
*/
@@ -7,13 +8,29 @@
#ifndef __UM_PGTABLE_H
#define __UM_PGTABLE_H
-#include <asm-generic/4level-fixup.h>
-
#include "linux/sched.h"
#include "asm/processor.h"
#include "asm/page.h"
#include "asm/fixmap.h"
+#define _PAGE_PRESENT 0x001
+#define _PAGE_NEWPAGE 0x002
+#define _PAGE_NEWPROT 0x004
+#define _PAGE_FILE 0x008 /* set:pagecache unset:swap */
+#define _PAGE_PROTNONE 0x010 /* If not present */
+#define _PAGE_RW 0x020
+#define _PAGE_USER 0x040
+#define _PAGE_ACCESSED 0x080
+#define _PAGE_DIRTY 0x100
+
+#ifdef CONFIG_3_LEVEL_PGTABLES
+#include "asm/pgtable-3level.h"
+#else
+#include "asm/pgtable-2level.h"
+#endif
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
extern void *um_virt_to_phys(struct task_struct *task, unsigned long virt,
pte_t *pte_out);
@@ -22,35 +39,6 @@ extern unsigned long *empty_zero_page;
#define pgtable_cache_init() do ; while (0)
-/* PMD_SHIFT determines the size of the area a second-level page table can map */
-#define PMD_SHIFT 22
-#define PMD_SIZE (1UL << PMD_SHIFT)
-#define PMD_MASK (~(PMD_SIZE-1))
-
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT 22
-#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
-#define PGDIR_MASK (~(PGDIR_SIZE-1))
-
-/*
- * entries per page directory level: the i386 is two-level, so
- * we don't really have any PMD directory physically.
- */
-#define PTRS_PER_PTE 1024
-#define PTRS_PER_PMD 1
-#define PTRS_PER_PGD 1024
-#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
-#define FIRST_USER_PGD_NR 0
-
-#define pte_ERROR(e) \
- printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
-#define pmd_ERROR(e) \
- printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
-#define pgd_ERROR(e) \
- printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
-
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-
/*
* pgd entries used up by user/kernel:
*/
@@ -70,7 +58,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
extern unsigned long end_iomem;
#define VMALLOC_OFFSET (__va_space)
-#define VMALLOC_START ((end_iomem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_START ((end_iomem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
#ifdef CONFIG_HIGHMEM
# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)
@@ -78,18 +66,8 @@ extern unsigned long end_iomem;
# define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE)
#endif
-#define _PAGE_PRESENT 0x001
-#define _PAGE_NEWPAGE 0x002
-#define _PAGE_NEWPROT 0x004
-#define _PAGE_FILE 0x008 /* set:pagecache unset:swap */
-#define _PAGE_PROTNONE 0x010 /* If not present */
-#define _PAGE_RW 0x020
-#define _PAGE_USER 0x040
-#define _PAGE_ACCESSED 0x080
-#define _PAGE_DIRTY 0x100
-
-#define REGION_MASK 0xf0000000
-#define REGION_SHIFT 28
+#define REGION_SHIFT (sizeof(pte_t) * 8 - 4)
+#define REGION_MASK (((unsigned long) 0xf) << REGION_SHIFT)
#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
@@ -157,16 +135,13 @@ extern pte_t * __bad_pagetable(void);
/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
/* 64-bit machines, beware! SRB. */
-#define SIZEOF_PTR_LOG2 2
+#define SIZEOF_PTR_LOG2 3
/* to find an entry in a page-table */
#define PAGE_PTR(address) \
((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
-#define pte_none(x) !(pte_val(x) & ~_PAGE_NEWPAGE)
-#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
-
-#define pte_clear(xp) do { pte_val(*(xp)) = _PAGE_NEWPAGE; } while (0)
+#define pte_clear(xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEWPAGE))
#define pmd_none(x) (!(pmd_val(x) & ~_PAGE_NEWPAGE))
#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
@@ -176,67 +151,22 @@ extern pte_t * __bad_pagetable(void);
#define pmd_newpage(x) (pmd_val(x) & _PAGE_NEWPAGE)
#define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEWPAGE)
-/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
- */
-static inline int pgd_none(pgd_t pgd) { return 0; }
-static inline int pgd_bad(pgd_t pgd) { return 0; }
-static inline int pgd_present(pgd_t pgd) { return 1; }
-static inline void pgd_clear(pgd_t * pgdp) { }
-
-
-#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
+#define pud_newpage(x) (pud_val(x) & _PAGE_NEWPAGE)
+#define pud_mkuptodate(x) (pud_val(x) &= ~_PAGE_NEWPAGE)
-#define pte_page(pte) phys_to_page(pte_val(pte))
-#define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK)
-
-#define pte_pfn(x) phys_to_pfn(pte_val(x))
-#define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot))
-
-extern struct page *phys_to_page(const unsigned long phys);
-extern struct page *__virt_to_page(const unsigned long virt);
-#define virt_to_page(addr) __virt_to_page((const unsigned long) addr)
-
-/*
- * Bits 0 through 3 are taken
- */
-#define PTE_FILE_MAX_BITS 28
-
-#define pte_to_pgoff(pte) ((pte).pte_low >> 4)
-
-#define pgoff_to_pte(off) \
- ((pte_t) { ((off) << 4) + _PAGE_FILE })
-
-static inline pte_t pte_mknewprot(pte_t pte)
+static inline pud_t *__pud_alloc(struct mm_struct *mm, pgd_t *pgd,
+ unsigned long addr)
{
- pte_val(pte) |= _PAGE_NEWPROT;
- return(pte);
+ BUG();
}
-static inline pte_t pte_mknewpage(pte_t pte)
-{
- pte_val(pte) |= _PAGE_NEWPAGE;
- return(pte);
-}
+#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
-static inline void set_pte(pte_t *pteptr, pte_t pteval)
-{
- /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so
- * fix_range knows to unmap it. _PAGE_NEWPROT is specific to
- * mapped pages.
- */
- *pteptr = pte_mknewpage(pteval);
- if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
-}
+#define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK)
-/*
- * (pmds are folded into pgds so this doesn't get actually called,
- * but the define is needed for a generic inline function.)
- */
-#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
-#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval)
+#define pte_address(x) (__va(pte_val(x) & PAGE_MASK))
+#define mk_phys(a, r) ((a) + (((unsigned long) r) << REGION_SHIFT))
+#define phys_addr(p) ((p) & ~REGION_MASK)
/*
* The following only work if pte_present() is true.
@@ -244,25 +174,25 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
*/
static inline int pte_user(pte_t pte)
{
- return((pte_val(pte) & _PAGE_USER) &&
- !(pte_val(pte) & _PAGE_PROTNONE));
+ return((pte_get_bits(pte, _PAGE_USER)) &&
+ !(pte_get_bits(pte, _PAGE_PROTNONE)));
}
static inline int pte_read(pte_t pte)
{
- return((pte_val(pte) & _PAGE_USER) &&
- !(pte_val(pte) & _PAGE_PROTNONE));
+ return((pte_get_bits(pte, _PAGE_USER)) &&
+ !(pte_get_bits(pte, _PAGE_PROTNONE)));
}
static inline int pte_exec(pte_t pte){
- return((pte_val(pte) & _PAGE_USER) &&
- !(pte_val(pte) & _PAGE_PROTNONE));
+ return((pte_get_bits(pte, _PAGE_USER)) &&
+ !(pte_get_bits(pte, _PAGE_PROTNONE)));
}
static inline int pte_write(pte_t pte)
{
- return((pte_val(pte) & _PAGE_RW) &&
- !(pte_val(pte) & _PAGE_PROTNONE));
+ return((pte_get_bits(pte, _PAGE_RW)) &&
+ !(pte_get_bits(pte, _PAGE_PROTNONE)));
}
/*
@@ -270,85 +200,98 @@ static inline int pte_write(pte_t pte)
*/
static inline int pte_file(pte_t pte)
{
- return (pte).pte_low & _PAGE_FILE;
+ return pte_get_bits(pte, _PAGE_FILE);
+}
+
+static inline int pte_dirty(pte_t pte)
+{
+ return pte_get_bits(pte, _PAGE_DIRTY);
+}
+
+static inline int pte_young(pte_t pte)
+{
+ return pte_get_bits(pte, _PAGE_ACCESSED);
+}
+
+static inline int pte_newpage(pte_t pte)
+{
+ return pte_get_bits(pte, _PAGE_NEWPAGE);
}
-static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
-static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
-static inline int pte_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; }
static inline int pte_newprot(pte_t pte)
{
- return(pte_present(pte) && (pte_val(pte) & _PAGE_NEWPROT));
+ return(pte_present(pte) && (pte_get_bits(pte, _PAGE_NEWPROT)));
}
static inline pte_t pte_rdprotect(pte_t pte)
{
- pte_val(pte) &= ~_PAGE_USER;
+ pte_clear_bits(pte, _PAGE_USER);
return(pte_mknewprot(pte));
}
static inline pte_t pte_exprotect(pte_t pte)
{
- pte_val(pte) &= ~_PAGE_USER;
+ pte_clear_bits(pte, _PAGE_USER);
return(pte_mknewprot(pte));
}
static inline pte_t pte_mkclean(pte_t pte)
{
- pte_val(pte) &= ~_PAGE_DIRTY;
+ pte_clear_bits(pte, _PAGE_DIRTY);
return(pte);
}
static inline pte_t pte_mkold(pte_t pte)
{
- pte_val(pte) &= ~_PAGE_ACCESSED;
+ pte_clear_bits(pte, _PAGE_ACCESSED);
return(pte);
}
static inline pte_t pte_wrprotect(pte_t pte)
{
- pte_val(pte) &= ~_PAGE_RW;
+ pte_clear_bits(pte, _PAGE_RW);
return(pte_mknewprot(pte));
}
static inline pte_t pte_mkread(pte_t pte)
{
- pte_val(pte) |= _PAGE_USER;
+ pte_set_bits(pte, _PAGE_RW);
return(pte_mknewprot(pte));
}
static inline pte_t pte_mkexec(pte_t pte)
{
- pte_val(pte) |= _PAGE_USER;
+ pte_set_bits(pte, _PAGE_USER);
return(pte_mknewprot(pte));
}
static inline pte_t pte_mkdirty(pte_t pte)
{
- pte_val(pte) |= _PAGE_DIRTY;
+ pte_set_bits(pte, _PAGE_DIRTY);
return(pte);
}
static inline pte_t pte_mkyoung(pte_t pte)
{
- pte_val(pte) |= _PAGE_ACCESSED;
+ pte_set_bits(pte, _PAGE_ACCESSED);
return(pte);
}
static inline pte_t pte_mkwrite(pte_t pte)
{
- pte_val(pte) |= _PAGE_RW;
+ pte_set_bits(pte, _PAGE_RW);
return(pte_mknewprot(pte));
}
static inline pte_t pte_mkuptodate(pte_t pte)
{
- pte_val(pte) &= ~_PAGE_NEWPAGE;
- if(pte_present(pte)) pte_val(pte) &= ~_PAGE_NEWPROT;
+ pte_clear_bits(pte, _PAGE_NEWPAGE);
+ if(pte_present(pte))
+ pte_clear_bits(pte, _PAGE_NEWPROT);
return(pte);
}
-extern unsigned long page_to_phys(struct page *page);
+extern phys_t page_to_phys(struct page *page);
/*
* Conversion functions: convert a page and protection to a page entry,
@@ -357,11 +300,9 @@ extern unsigned long page_to_phys(struct page *page);
extern pte_t mk_pte(struct page *page, pgprot_t pgprot);
-#define pte_set_val(p, phys, prot) pte_val(p) = (phys | pgprot_val(prot))
-
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
- pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+ pte_set_val(pte, (pte_val(pte) & _PAGE_CHG_MASK), newprot);
if(pte_present(pte)) pte = pte_mknewpage(pte_mknewprot(pte));
return pte;
}
@@ -374,15 +315,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
* this macro returns the index of the entry in the pgd page which would
* control the given virtual address
*/
-#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+
+#define pgd_index_k(addr) pgd_index(addr)
/*
* pgd_offset() returns a (pgd_t *)
* pgd_index() is used get the offset into the pgd page's array of pgd_t's;
*/
-#define pgd_offset(mm, address) \
-((mm)->pgd + ((address) >> PGDIR_SHIFT))
-
+#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
/*
* a shortcut which implies the use of the kernel's pgd, instead
@@ -390,14 +331,13 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
*/
#define pgd_offset_k(address) pgd_offset(&init_mm, address)
-#define pmd_index(address) \
- (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
-
-/* Find an entry in the second-level page table.. */
-static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
-{
- return (pmd_t *) dir;
-}
+/*
+ * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
+ *
+ * this macro returns the index of the entry in the pmd page which would
+ * control the given virtual address
+ */
+#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
/*
* the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
@@ -430,9 +370,15 @@ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
#include <asm-generic/pgtable.h>
-#endif
+#include <asm-generic/pgtable-nopud.h>
#endif
+#endif
+
+extern struct page *phys_to_page(const unsigned long phys);
+extern struct page *__virt_to_page(const unsigned long virt);
+#define virt_to_page(addr) __virt_to_page((const unsigned long) addr)
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/include/asm-um/prctl.h b/include/asm-um/prctl.h
new file mode 100644
index 000000000000..64b6d099bdd5
--- /dev/null
+++ b/include/asm-um/prctl.h
@@ -0,0 +1,6 @@
+#ifndef __UM_PRCTL_H
+#define __UM_PRCTL_H
+
+#include "asm/arch/prctl.h"
+
+#endif
diff --git a/include/asm-um/processor-i386.h b/include/asm-um/processor-i386.h
index b276481cc6cb..cb44bb56836f 100644
--- a/include/asm-um/processor-i386.h
+++ b/include/asm-um/processor-i386.h
@@ -24,7 +24,8 @@ struct arch_thread {
* instruction pointer ("program counter"). Stolen
* from asm-i386/processor.h
*/
-#define current_text_addr() ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
+#define current_text_addr() \
+ ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
#include "asm/processor-generic.h"
diff --git a/include/asm-um/processor-x86_64.h b/include/asm-um/processor-x86_64.h
new file mode 100644
index 000000000000..0b8d4e2d8efc
--- /dev/null
+++ b/include/asm-um/processor-x86_64.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PROCESSOR_X86_64_H
+#define __UM_PROCESSOR_X86_64_H
+
+#include "asm/arch/user.h"
+
+struct arch_thread {
+};
+
+#define INIT_ARCH_THREAD { }
+
+#define current_text_addr() \
+ ({ void *pc; __asm__("movq $1f,%0\n1:":"=g" (pc)); pc; })
+
+#include "asm/processor-generic.h"
+
+#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/include/asm-um/ptrace-generic.h b/include/asm-um/ptrace-generic.h
index a1bb25f8e85b..46599ac44037 100644
--- a/include/asm-um/ptrace-generic.h
+++ b/include/asm-um/ptrace-generic.h
@@ -12,16 +12,17 @@
#define pt_regs pt_regs_subarch
#define show_regs show_regs_subarch
+#define send_sigtrap send_sigtrap_subarch
#include "asm/arch/ptrace.h"
#undef pt_regs
#undef show_regs
+#undef send_sigtrap
#undef user_mode
#undef instruction_pointer
#include "sysdep/ptrace.h"
-#include "skas_ptrace.h"
struct pt_regs {
union uml_pt_regs regs;
@@ -56,6 +57,9 @@ extern int set_fpxregs(unsigned long buf, struct task_struct *tsk);
extern void show_regs(struct pt_regs *regs);
+extern void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs,
+ int error_code);
+
#endif
#endif
diff --git a/include/asm-um/ptrace-x86_64.h b/include/asm-um/ptrace-x86_64.h
new file mode 100644
index 000000000000..c34be39b78b2
--- /dev/null
+++ b/include/asm-um/ptrace-x86_64.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PTRACE_X86_64_H
+#define __UM_PTRACE_X86_64_H
+
+#include "linux/compiler.h"
+
+#define signal_fault signal_fault_x86_64
+#define __FRAME_OFFSETS /* Needed to get the R* macros */
+#include "asm/ptrace-generic.h"
+#undef signal_fault
+
+void signal_fault(struct pt_regs_subarch *regs, void *frame, char *where);
+
+#define FS_BASE (21 * sizeof(unsigned long))
+#define GS_BASE (22 * sizeof(unsigned long))
+#define DS (23 * sizeof(unsigned long))
+#define ES (24 * sizeof(unsigned long))
+#define FS (25 * sizeof(unsigned long))
+#define GS (26 * sizeof(unsigned long))
+
+#define PT_REGS_RBX(r) UPT_RBX(&(r)->regs)
+#define PT_REGS_RCX(r) UPT_RCX(&(r)->regs)
+#define PT_REGS_RDX(r) UPT_RDX(&(r)->regs)
+#define PT_REGS_RSI(r) UPT_RSI(&(r)->regs)
+#define PT_REGS_RDI(r) UPT_RDI(&(r)->regs)
+#define PT_REGS_RBP(r) UPT_RBP(&(r)->regs)
+#define PT_REGS_RAX(r) UPT_RAX(&(r)->regs)
+#define PT_REGS_R8(r) UPT_R8(&(r)->regs)
+#define PT_REGS_R9(r) UPT_R9(&(r)->regs)
+#define PT_REGS_R10(r) UPT_R10(&(r)->regs)
+#define PT_REGS_R11(r) UPT_R11(&(r)->regs)
+#define PT_REGS_R12(r) UPT_R12(&(r)->regs)
+#define PT_REGS_R13(r) UPT_R13(&(r)->regs)
+#define PT_REGS_R14(r) UPT_R14(&(r)->regs)
+#define PT_REGS_R15(r) UPT_R15(&(r)->regs)
+
+#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
+#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
+#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
+#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
+#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
+#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
+
+#define PT_REGS_ORIG_RAX(r) UPT_ORIG_RAX(&(r)->regs)
+#define PT_REGS_RIP(r) UPT_IP(&(r)->regs)
+#define PT_REGS_RSP(r) UPT_SP(&(r)->regs)
+
+#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
+
+/* XXX */
+#define user_mode(r) UPT_IS_USER(&(r)->regs)
+#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_RAX(r)
+#define PT_REGS_SYSCALL_RET(r) PT_REGS_RAX(r)
+
+#define PT_FIX_EXEC_STACK(sp) do ; while(0)
+
+#define profile_pc(regs) PT_REGS_IP(regs)
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/include/ptrace-tt.h b/include/asm-um/sigcontext-x86_64.h
index 3084c1db8678..b600e0b01e48 100644
--- a/arch/um/kernel/tt/include/ptrace-tt.h
+++ b/include/asm-um/sigcontext-x86_64.h
@@ -1,16 +1,12 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+/* Copyright 2003 PathScale, Inc.
+ *
* Licensed under the GPL
*/
-#ifndef __PTRACE_TT_H
-#define __PTRACE_TT_H
+#ifndef __UM_SIGCONTEXT_X86_64_H
+#define __UM_SIGCONTEXT_X86_64_H
-#include "uml-config.h"
-
-#ifdef UML_CONFIG_MODE_TT
-#include "sysdep/sc.h"
-#endif
+#include "asm/sigcontext-generic.h"
#endif
diff --git a/include/asm-um/system-x86_64.h b/include/asm-um/system-x86_64.h
new file mode 100644
index 000000000000..e1b61b580734
--- /dev/null
+++ b/include/asm-um/system-x86_64.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_SYSTEM_X86_64_H
+#define __UM_SYSTEM_X86_64_H
+
+#include "asm/system-generic.h"
+
+#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/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 6550ed4355c2..7797873890c2 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -47,7 +47,7 @@ static inline struct thread_info *current_thread_info(void)
struct thread_info *ti;
unsigned long mask = PAGE_SIZE *
(1 << CONFIG_KERNEL_STACK_ORDER) - 1;
- __asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~mask));
+ ti = (struct thread_info *) (((unsigned long) &ti) & ~mask);
return ti;
}
diff --git a/include/asm-um/uaccess.h b/include/asm-um/uaccess.h
index d42d5f8dcdfd..801710d00a40 100644
--- a/include/asm-um/uaccess.h
+++ b/include/asm-um/uaccess.h
@@ -55,7 +55,7 @@
#define get_user(x, ptr) \
({ \
- const __typeof__((*(ptr))) *private_ptr = (ptr); \
+ const __typeof__((*(ptr))) __user *private_ptr = (ptr); \
(access_ok(VERIFY_READ, private_ptr, sizeof(*private_ptr)) ? \
__get_user(x, private_ptr) : ((x) = 0, -EFAULT)); \
})
@@ -75,7 +75,7 @@
#define put_user(x, ptr) \
({ \
- __typeof__(*(ptr)) *private_ptr = (ptr); \
+ __typeof__(*(ptr)) __user *private_ptr = (ptr); \
(access_ok(VERIFY_WRITE, private_ptr, sizeof(*private_ptr)) ? \
__put_user(x, private_ptr) : -EFAULT); \
})
diff --git a/include/asm-um/vm-flags-i386.h b/include/asm-um/vm-flags-i386.h
new file mode 100644
index 000000000000..e0d24c568dbc
--- /dev/null
+++ b/include/asm-um/vm-flags-i386.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __VM_FLAGS_I386_H
+#define __VM_FLAGS_I386_H
+
+#define VM_DATA_DEFAULT_FLAGS \
+ (VM_READ | VM_WRITE | \
+ ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#endif
diff --git a/include/asm-um/vm-flags-x86_64.h b/include/asm-um/vm-flags-x86_64.h
new file mode 100644
index 000000000000..3213edfa7888
--- /dev/null
+++ b/include/asm-um/vm-flags-x86_64.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright 2003 PathScale, Inc.
+ * Licensed under the GPL
+ */
+
+#ifndef __VM_FLAGS_X86_64_H
+#define __VM_FLAGS_X86_64_H
+
+#define __VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+#define __VM_STACK_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \
+ VM_EXEC | VM_MAYREAD | VM_MAYWRITE | \
+ VM_MAYEXEC)
+
+extern unsigned long vm_stack_flags, vm_stack_flags32;
+extern unsigned long vm_data_default_flags, vm_data_default_flags32;
+extern unsigned long vm_force_exec32;
+
+#ifdef TIF_IA32
+#define VM_DATA_DEFAULT_FLAGS \
+ (test_thread_flag(TIF_IA32) ? vm_data_default_flags32 : \
+ vm_data_default_flags)
+
+#define VM_STACK_DEFAULT_FLAGS \
+ (test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags)
+#endif
+
+#define VM_DATA_DEFAULT_FLAGS vm_data_default_flags
+
+#define VM_STACK_DEFAULT_FLAGS vm_stack_flags
+
+#endif
diff --git a/include/asm-v850/cputime.h b/include/asm-v850/cputime.h
new file mode 100644
index 000000000000..7c799c33b8a9
--- /dev/null
+++ b/include/asm-v850/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __V850_CPUTIME_H
+#define __V850_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __V850_CPUTIME_H */
diff --git a/include/asm-x86_64/cputime.h b/include/asm-x86_64/cputime.h
new file mode 100644
index 000000000000..a07012dc5a3c
--- /dev/null
+++ b/include/asm-x86_64/cputime.h
@@ -0,0 +1,6 @@
+#ifndef __X86_64_CPUTIME_H
+#define __X86_64_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* __X86_64_CPUTIME_H */
diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h
index 767e11abd5c5..2b5cb2865d21 100644
--- a/include/asm-x86_64/hw_irq.h
+++ b/include/asm-x86_64/hw_irq.h
@@ -87,8 +87,6 @@ extern u8 irq_vector[NR_IRQ_VECTORS];
* Interrupt entry/exit code at both C and assembly level
*/
-extern void mask_irq(unsigned int irq);
-extern void unmask_irq(unsigned int irq);
extern void disable_8259A_irq(unsigned int irq);
extern void enable_8259A_irq(unsigned int irq);
extern int i8259A_irq_pending(unsigned int irq);
diff --git a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h
index 26e56c27fe18..f3b7111cf33d 100644
--- a/include/asm-x86_64/ia32_unistd.h
+++ b/include/asm-x86_64/ia32_unistd.h
@@ -290,7 +290,11 @@
#define __NR_ia32_mq_getsetattr (__NR_ia32_mq_open+5)
#define __NR_ia32_kexec 283
#define __NR_ia32_waitid 284
+/* #define __NR_sys_setaltroot 285 */
+#define __NR_ia32_add_key 286
+#define __NR_ia32_request_key 287
+#define __NR_ia32_keyctl 288
-#define IA32_NR_syscalls 285 /* must be > than biggest syscall! */
+#define IA32_NR_syscalls 290 /* must be > than biggest syscall! */
#endif /* _ASM_X86_64_IA32_UNISTD_H_ */
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index ce379aee7355..734db492e889 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -260,10 +260,8 @@ static inline void memcpy_toio(volatile void __iomem *to, const void *from, unsi
{
__memcpy_toio((unsigned long)to,from,len);
}
-static inline void memset_io(volatile void __iomem *a, int b, size_t c)
-{
- memset((__force void *)a,b,c);
-}
+
+void memset_io(volatile void __iomem *a, int b, size_t c);
/*
* ISA space is 'always mapped' on a typical x86 system, no need to
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h
index ed94245a5d4f..850695678419 100644
--- a/include/asm-x86_64/msr.h
+++ b/include/asm-x86_64/msr.h
@@ -67,7 +67,8 @@
: "=a" (low), "=d" (high) \
: "c" (counter))
-extern inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
+extern inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
{
__asm__("cpuid"
: "=a" (*eax),
diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h
index 21843b35ef18..3574f604542b 100644
--- a/include/asm-x86_64/numa.h
+++ b/include/asm-x86_64/numa.h
@@ -8,7 +8,7 @@ struct node {
u64 start,end;
};
-extern int compute_hash_shift(struct node *nodes);
+extern int compute_hash_shift(struct node *nodes, int numnodes);
#define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index e942ca5957e4..3bee3482389a 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -15,7 +15,7 @@ extern void pda_init(int);
extern void early_idt_handler(void);
extern void mcheck_init(struct cpuinfo_x86 *c);
-extern void init_memory_mapping(void);
+extern void init_memory_mapping(unsigned long start, unsigned long end);
extern void system_call(void);
extern int kernel_syscall(void);
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
index 406102dbf298..926e614e60d6 100644
--- a/include/asm-x86_64/uaccess.h
+++ b/include/asm-x86_64/uaccess.h
@@ -172,7 +172,7 @@ do { \
/* FIXME: this hack is definitely wrong -AK */
struct __large_struct { unsigned long buf[100]; };
-#define __m(x) (*(struct __large_struct *)(x))
+#define __m(x) (*(struct __large_struct __user *)(x))
/*
* Tell gcc we read from memory instead of writing: this is because
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index 506ec8d12e75..d9182e600b69 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -556,8 +556,14 @@ __SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr)
__SYSCALL(__NR_kexec_load, sys_ni_syscall)
#define __NR_waitid 247
__SYSCALL(__NR_waitid, sys_waitid)
-
-#define __NR_syscall_max __NR_waitid
+#define __NR_add_key 248
+__SYSCALL(__NR_add_key, sys_add_key)
+#define __NR_request_key 249
+__SYSCALL(__NR_request_key, sys_request_key)
+#define __NR_keyctl 250
+__SYSCALL(__NR_keyctl, sys_keyctl)
+
+#define __NR_syscall_max __NR_keyctl
#ifndef __NO_STUBS
/* user-visible error numbers are in the range -1 - -4095 */
@@ -724,7 +730,7 @@ static inline long dup(unsigned int fd)
}
/* implemented in asm in arch/x86_64/kernel/entry.S */
-extern long execve(char *, char **, char **);
+extern int execve(const char *, char * const *, char * const *);
static inline long open(const char * filename, int flags, int mode)
{
diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h
index bd4364daf948..7198f129e135 100644
--- a/include/linux/arcdevice.h
+++ b/include/linux/arcdevice.h
@@ -343,7 +343,6 @@ void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc,
void arcnet_unregister_proto(struct ArcProto *proto);
irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-void arcdev_setup(struct net_device *dev);
struct net_device *alloc_arcdev(char *name);
void arcnet_rx(struct net_device *dev, int bufnum);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 1b7dc44bf3c1..5615a3c9e410 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -95,6 +95,7 @@ void swap_io_context(struct io_context **ioc1, struct io_context **ioc2);
struct request_list {
int count[2];
+ int starved[2];
mempool_t *rq_pool;
wait_queue_head_t wait[2];
wait_queue_head_t drain;
diff --git a/include/linux/coda.h b/include/linux/coda.h
index 309cbbe35e67..bbc5afcd7db6 100644
--- a/include/linux/coda.h
+++ b/include/linux/coda.h
@@ -761,8 +761,8 @@ union coda_downcalls {
struct ViceIoctl {
void __user *in; /* Data to be transferred in */
void __user *out; /* Data to be transferred out */
- short in_size; /* Size of input buffer <= 2K */
- short out_size; /* Maximum size of output buffer, <= 2K */
+ u_short in_size; /* Size of input buffer <= 2K */
+ u_short out_size; /* Maximum size of output buffer, <= 2K */
};
struct PioctlData {
diff --git a/include/linux/coda_proc.h b/include/linux/coda_proc.h
index c061a22ed86d..0dc1b0458e75 100644
--- a/include/linux/coda_proc.h
+++ b/include/linux/coda_proc.h
@@ -72,26 +72,5 @@ struct coda_cache_inv_stats
/* these global variables hold the actual statistics data */
extern struct coda_vfs_stats coda_vfs_stat;
-extern struct coda_cache_inv_stats coda_cache_inv_stat;
-
-/* reset statistics to 0 */
-void reset_coda_vfs_stats( void );
-void reset_coda_cache_inv_stats( void );
-
-/* like coda_dointvec, these functions are to be registered in the ctl_table
- * data structure for /proc/sys/... files
- */
-int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
- void __user * buffer, size_t * lenp, loff_t * ppos );
-int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
- struct file * filp, void __user * buffer,
- size_t * lenp, loff_t * ppos );
-
-/* these functions are called to form the content of /proc/fs/coda/... files */
-int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
- int length);
-int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
- int length);
-
#endif /* _CODA_PROC_H */
diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h
index 0c767ffd6a0d..d539262a8f89 100644
--- a/include/linux/coda_psdev.h
+++ b/include/linux/coda_psdev.h
@@ -49,7 +49,7 @@ int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid,
const char *name, int length,
struct CodaFid *newfid, struct coda_vattr *attrs);
int venus_create(struct super_block *sb, struct CodaFid *dirfid,
- const char *name, int length, int excl, int mode, dev_t rdev,
+ const char *name, int length, int excl, int mode,
struct CodaFid *newfid, struct coda_vattr *attrs) ;
int venus_rmdir(struct super_block *sb, struct CodaFid *dirfid,
const char *name, int length);
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index a9a2a486234c..062049ca5c44 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -9,6 +9,8 @@
* to achieve effects such as fast scrolling by changing the origin.
*/
+struct vt_struct;
+
#define NPAR 16
struct vc_data {
@@ -87,6 +89,7 @@ struct vc_data {
struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */
unsigned long vc_uni_pagedir;
unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
+ struct vt_struct *vc_vt;
/* additional information is in vt_kern.h */
};
diff --git a/include/linux/device.h b/include/linux/device.h
index 2c5d57283d5a..786e1591102b 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -61,7 +61,7 @@ struct bus_type {
int (*match)(struct device * dev, struct device_driver * drv);
int (*hotplug) (struct device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
- int (*suspend)(struct device * dev, u32 state);
+ int (*suspend)(struct device * dev, pm_message_t state);
int (*resume)(struct device * dev);
};
diff --git a/include/linux/efs_vh.h b/include/linux/efs_vh.h
index b3df61ef2eb2..8a11150c61fe 100644
--- a/include/linux/efs_vh.h
+++ b/include/linux/efs_vh.h
@@ -47,23 +47,6 @@ struct volume_header {
struct pt_types {
int pt_type;
char *pt_name;
-} sgi_pt_types[] = {
- {0x00, "SGI vh"},
- {0x01, "SGI trkrepl"},
- {0x02, "SGI secrepl"},
- {0x03, "SGI raw"},
- {0x04, "SGI bsd"},
- {SGI_SYSV, "SGI sysv"},
- {0x06, "SGI vol"},
- {SGI_EFS, "SGI efs"},
- {0x08, "SGI lv"},
- {0x09, "SGI rlv"},
- {0x0A, "SGI xfs"},
- {0x0B, "SGI xfslog"},
- {0x0C, "SGI xlv"},
- {0x82, "Linux swap"},
- {0x83, "Linux native"},
- {0, NULL}
};
#endif /* __EFS_VH_H__ */
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index a45400d0a2f4..2789be67fbe9 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -793,25 +793,15 @@ extern void ext3_error (struct super_block *, const char *, const char *, ...)
extern void __ext3_std_error (struct super_block *, const char *, int);
extern void ext3_abort (struct super_block *, const char *, const char *, ...)
__attribute__ ((format (printf, 3, 4)));
-extern NORET_TYPE void ext3_panic (struct super_block *, const char *,
- const char *, ...)
- __attribute__ ((NORET_AND format (printf, 3, 4)));
extern void ext3_warning (struct super_block *, const char *, const char *, ...)
__attribute__ ((format (printf, 3, 4)));
extern void ext3_update_dynamic_rev (struct super_block *sb);
-extern void ext3_put_super (struct super_block *);
-extern void ext3_write_super (struct super_block *);
-extern void ext3_write_super_lockfs (struct super_block *);
-extern void ext3_unlockfs (struct super_block *);
-extern int ext3_remount (struct super_block *, int *, char *);
-extern int ext3_statfs (struct super_block *, struct kstatfs *);
#define ext3_std_error(sb, errno) \
do { \
if ((errno)) \
__ext3_std_error((sb), __FUNCTION__, (errno)); \
} while (0)
-extern const char *ext3_decode_error(struct super_block *sb, int errno, char nbuf[16]);
/*
* Inodes and files operations
diff --git a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h
index 0380c1fbdab0..47445f93d4f7 100644
--- a/include/linux/ext3_jbd.h
+++ b/include/linux/ext3_jbd.h
@@ -46,8 +46,6 @@
EXT3_XATTR_TRANS_BLOCKS - 2 + \
2*EXT3_QUOTA_TRANS_BLOCKS)
-extern int ext3_writepage_trans_blocks(struct inode *inode);
-
/* Delete operations potentially hit one directory's namespace plus an
* entire inode, plus arbitrary amounts of bitmap/indirection data. Be
* generous. We can grow the delete transaction later if necessary. */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 31391d59ddc2..4d26f55c1299 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -68,8 +68,6 @@ extern int dir_notify_enable;
#endif
#define NR_FILE 8192 /* this can well be larger on a larger system */
-#define NR_RESERVED_FILES 10 /* reserved for root */
-#define NR_SUPER 256
#define MAY_EXEC 1
#define MAY_WRITE 2
@@ -1346,7 +1344,7 @@ static inline void invalidate_remote_inode(struct inode *inode)
invalidate_inode_pages(inode->i_mapping);
}
extern int invalidate_inode_pages2(struct address_space *mapping);
-extern void write_inode_now(struct inode *, int);
+extern int write_inode_now(struct inode *, int);
extern int filemap_fdatawrite(struct address_space *);
extern int filemap_flush(struct address_space *);
extern int filemap_fdatawait(struct address_space *);
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index ba0fcb34c8cd..ebc712e91066 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -4,6 +4,7 @@
#include <linux/config.h>
#include <linux/smp_lock.h>
#include <asm/hardirq.h>
+#include <asm/system.h>
/*
* We put the hardirq and softirq counter into the preemption
@@ -84,7 +85,22 @@ extern void synchronize_irq(unsigned int irq);
#define nmi_enter() irq_enter()
#define nmi_exit() sub_preempt_count(HARDIRQ_OFFSET)
-#define irq_enter() add_preempt_count(HARDIRQ_OFFSET)
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+static inline void account_user_vtime(struct task_struct *tsk)
+{
+}
+
+static inline void account_system_vtime(struct task_struct *tsk)
+{
+}
+#endif
+
+#define irq_enter() \
+ do { \
+ account_system_vtime(current); \
+ add_preempt_count(HARDIRQ_OFFSET); \
+ } while (0)
+
extern void irq_exit(void);
#endif /* LINUX_HARDIRQ_H */
diff --git a/include/linux/in6.h b/include/linux/in6.h
index 5b4e89b1ac68..f8256c582845 100644
--- a/include/linux/in6.h
+++ b/include/linux/in6.h
@@ -44,8 +44,10 @@ struct in6_addr
* NOTE: Be aware the IN6ADDR_* constants and in6addr_* externals are defined
* in network byte order, not in host byte order as are the IPv4 equivalents
*/
+#if 0
extern const struct in6_addr in6addr_any;
#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }
+#endif
extern const struct in6_addr in6addr_loopback;
#define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 991831cff1da..d99e7aeb7d33 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -61,12 +61,30 @@ extern void enable_irq(unsigned int irq);
* Temporary defines for UP kernels, until all code gets fixed.
*/
#ifndef CONFIG_SMP
-# define cli() local_irq_disable()
-# define sti() local_irq_enable()
-# define save_flags(x) local_save_flags(x)
-# define restore_flags(x) local_irq_restore(x)
-# define save_and_cli(x) local_irq_save(x)
-#endif
+static inline void __deprecated cli(void)
+{
+ local_irq_disable();
+}
+static inline void __deprecated sti(void)
+{
+ local_irq_enable();
+}
+static inline void __deprecated save_flags(unsigned long *x)
+{
+ local_save_flags(*x);
+}
+#define save_flags(x) save_flags(&x);
+static inline void __deprecated restore_flags(unsigned long x)
+{
+ local_irq_restore(x);
+}
+
+static inline void __deprecated save_and_cli(unsigned long *x)
+{
+ local_irq_save(*x);
+}
+#define save_and_cli(x) save_and_cli(&x)
+#endif /* CONFIG_SMP */
/* SoftIRQ primitives. */
#define local_bh_disable() \
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index 4594ccc4a7c1..dba27749b428 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -6,6 +6,7 @@
#include <linux/smp.h>
#include <linux/threads.h>
#include <linux/percpu.h>
+#include <asm/cputime.h>
/*
* 'kernel_stat.h' contains the definitions needed for doing
@@ -14,13 +15,14 @@
*/
struct cpu_usage_stat {
- u64 user;
- u64 nice;
- u64 system;
- u64 softirq;
- u64 irq;
- u64 idle;
- u64 iowait;
+ cputime64_t user;
+ cputime64_t nice;
+ cputime64_t system;
+ cputime64_t softirq;
+ cputime64_t irq;
+ cputime64_t idle;
+ cputime64_t iowait;
+ cputime64_t steal;
};
struct kernel_stat {
@@ -50,4 +52,8 @@ static inline int kstat_irqs(int irq)
return sum;
}
+extern void account_user_time(struct task_struct *, cputime_t);
+extern void account_system_time(struct task_struct *, int, cputime_t);
+extern void account_steal_time(struct task_struct *, cputime_t);
+
#endif /* _LINUX_KERNEL_STAT_H */
diff --git a/include/linux/list.h b/include/linux/list.h
index 7cad5322077c..dd7cd54fa831 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -326,8 +326,8 @@ static inline void list_splice_init(struct list_head *list,
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
- for (pos = (head)->next, prefetch(pos->next); pos != (head); \
- pos = pos->next, prefetch(pos->next))
+ for (pos = (head)->next; prefetch(pos->next), pos != (head); \
+ pos = pos->next)
/**
* __list_for_each - iterate over a list
@@ -348,8 +348,8 @@ static inline void list_splice_init(struct list_head *list,
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
- for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
- pos = pos->prev, prefetch(pos->prev))
+ for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
+ pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
@@ -368,11 +368,9 @@ static inline void list_splice_init(struct list_head *list,
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member), \
- prefetch(pos->member.next); \
- &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member), \
- prefetch(pos->member.next))
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
@@ -381,11 +379,9 @@ static inline void list_splice_init(struct list_head *list,
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member) \
- for (pos = list_entry((head)->prev, typeof(*pos), member), \
- prefetch(pos->member.prev); \
- &pos->member != (head); \
- pos = list_entry(pos->member.prev, typeof(*pos), member), \
- prefetch(pos->member.prev))
+ for (pos = list_entry((head)->prev, typeof(*pos), member); \
+ prefetch(pos->member.prev), &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_prepare_entry - prepare a pos entry for use as a start point in
@@ -405,11 +401,9 @@ static inline void list_splice_init(struct list_head *list,
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_continue(pos, head, member) \
- for (pos = list_entry(pos->member.next, typeof(*pos), member), \
- prefetch(pos->member.next); \
- &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member), \
- prefetch(pos->member.next))
+ for (pos = list_entry(pos->member.next, typeof(*pos), member); \
+ prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
@@ -434,8 +428,8 @@ static inline void list_splice_init(struct list_head *list,
* as long as the traversal is guarded by rcu_read_lock().
*/
#define list_for_each_rcu(pos, head) \
- for (pos = (head)->next, prefetch(pos->next); pos != (head); \
- pos = rcu_dereference(pos->next), prefetch(pos->next))
+ for (pos = (head)->next; prefetch(pos->next), pos != (head); \
+ pos = rcu_dereference(pos->next))
#define __list_for_each_rcu(pos, head) \
for (pos = (head)->next; pos != (head); \
@@ -467,12 +461,10 @@ static inline void list_splice_init(struct list_head *list,
* as long as the traversal is guarded by rcu_read_lock().
*/
#define list_for_each_entry_rcu(pos, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member), \
- prefetch(pos->member.next); \
- &pos->member != (head); \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ prefetch(pos->member.next), &pos->member != (head); \
pos = rcu_dereference(list_entry(pos->member.next, \
- typeof(*pos), member)), \
- prefetch(pos->member.next))
+ typeof(*pos), member)))
/**
@@ -486,8 +478,8 @@ static inline void list_splice_init(struct list_head *list,
* as long as the traversal is guarded by rcu_read_lock().
*/
#define list_for_each_continue_rcu(pos, head) \
- for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
- (pos) = rcu_dereference((pos)->next), prefetch((pos)->next))
+ for ((pos) = (pos)->next; prefetch((pos)->next), (pos) != (head); \
+ (pos) = rcu_dereference((pos)->next))
/*
* Double linked lists with a single pointer list head.
diff --git a/include/linux/lp.h b/include/linux/lp.h
index 521bcd2fecb1..7059b6b9878a 100644
--- a/include/linux/lp.h
+++ b/include/linux/lp.h
@@ -186,12 +186,6 @@ struct lp_struct {
*/
#define LP_DELAY 50
-/*
- * function prototypes
- */
-
-extern int lp_init(void);
-
#endif
#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index ee9817135376..75f5b8ed7231 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -711,6 +711,7 @@ static inline void vma_nonlinear_insert(struct vm_area_struct *vma,
}
/* mmap.c */
+extern int __vm_enough_memory(long pages, int cap_sys_admin);
extern void vma_adjust(struct vm_area_struct *vma, unsigned long start,
unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert);
extern struct vm_area_struct *vma_merge(struct mm_struct *,
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 871bcbdf2abd..fca36de5e3fc 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -522,7 +522,6 @@ extern struct net_device loopback_dev; /* The loopback */
extern struct net_device *dev_base; /* All devices */
extern rwlock_t dev_base_lock; /* Device list lock */
-extern int netdev_boot_setup_add(char *name, struct ifmap *map);
extern int netdev_boot_setup_check(struct net_device *dev);
extern unsigned long netdev_boot_base(const char *prefix, int unit);
extern struct net_device *dev_getbyhwaddr(unsigned short type, char *hwaddr);
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index b0ee19e302de..0c267c89fa3e 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -175,10 +175,6 @@ extern void nf_reinject(struct sk_buff *skb,
extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
extern void nf_ct_attach(struct sk_buff *, struct sk_buff *);
-#ifdef CONFIG_NETFILTER_DEBUG
-extern void nf_dump_skb(int pf, struct sk_buff *skb);
-#endif
-
/* FIXME: Before cache is ever used, this must be implemented for real. */
extern void nf_invalidate_cache(int pf);
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index d6a7188b525c..b16b4799e27e 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -312,9 +312,6 @@ struct arpt_table
/* A unique name... */
char name[ARPT_TABLE_MAXNAMELEN];
- /* Seed table: copied in register_table */
- struct arpt_replace *table;
-
/* What hooks you will enter on */
unsigned int valid_hooks;
@@ -328,7 +325,8 @@ struct arpt_table
struct module *me;
};
-extern int arpt_register_table(struct arpt_table *table);
+extern int arpt_register_table(struct arpt_table *table,
+ const struct arpt_replace *repl);
extern void arpt_unregister_table(struct arpt_table *table);
extern unsigned int arpt_do_table(struct sk_buff **pskb,
unsigned int hook,
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index a50174ab3440..91f3594d3bfd 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -440,9 +440,6 @@ struct ipt_table
/* A unique name... */
char name[IPT_TABLE_MAXNAMELEN];
- /* Seed table: copied in register_table */
- struct ipt_replace *table;
-
/* What hooks you will enter on */
unsigned int valid_hooks;
@@ -456,7 +453,30 @@ struct ipt_table
struct module *me;
};
-extern int ipt_register_table(struct ipt_table *table);
+/* net/sched/ipt.c: Gimme access to your targets! Gets target->me. */
+extern struct ipt_target *ipt_find_target(const char *name, u8 revision);
+
+/* Standard entry. */
+struct ipt_standard
+{
+ struct ipt_entry entry;
+ struct ipt_standard_target target;
+};
+
+struct ipt_error_target
+{
+ struct ipt_entry_target target;
+ char errorname[IPT_FUNCTION_MAXNAMELEN];
+};
+
+struct ipt_error
+{
+ struct ipt_entry entry;
+ struct ipt_error_target target;
+};
+
+extern int ipt_register_table(struct ipt_table *table,
+ const struct ipt_replace *repl);
extern void ipt_unregister_table(struct ipt_table *table);
extern unsigned int ipt_do_table(struct sk_buff **pskb,
unsigned int hook,
diff --git a/include/linux/netfilter_ipv4/ipt_LOG.h b/include/linux/netfilter_ipv4/ipt_LOG.h
index 481e12846208..d25f782e57d1 100644
--- a/include/linux/netfilter_ipv4/ipt_LOG.h
+++ b/include/linux/netfilter_ipv4/ipt_LOG.h
@@ -4,7 +4,8 @@
#define IPT_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */
#define IPT_LOG_TCPOPT 0x02 /* Log TCP options */
#define IPT_LOG_IPOPT 0x04 /* Log IP options */
-#define IPT_LOG_MASK 0x07
+#define IPT_LOG_UID 0x08 /* Log UID owning local socket */
+#define IPT_LOG_MASK 0x0f
struct ipt_log_info {
unsigned char level;
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index d6ac08c14dc1..8fa1bf0104ee 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -429,9 +429,6 @@ struct ip6t_table
/* A unique name... */
char name[IP6T_TABLE_MAXNAMELEN];
- /* Seed table: copied in register_table */
- struct ip6t_replace *table;
-
/* What hooks you will enter on */
unsigned int valid_hooks;
@@ -445,7 +442,8 @@ struct ip6t_table
struct module *me;
};
-extern int ip6t_register_table(struct ip6t_table *table);
+extern int ip6t_register_table(struct ip6t_table *table,
+ const struct ip6t_replace *repl);
extern void ip6t_unregister_table(struct ip6t_table *table);
extern unsigned int ip6t_do_table(struct sk_buff **pskb,
unsigned int hook,
diff --git a/include/linux/netfilter_ipv6/ip6t_LOG.h b/include/linux/netfilter_ipv6/ip6t_LOG.h
index 0646a107702a..42996a43bb39 100644
--- a/include/linux/netfilter_ipv6/ip6t_LOG.h
+++ b/include/linux/netfilter_ipv6/ip6t_LOG.h
@@ -4,7 +4,8 @@
#define IP6T_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */
#define IP6T_LOG_TCPOPT 0x02 /* Log TCP options */
#define IP6T_LOG_IPOPT 0x04 /* Log IP options */
-#define IP6T_LOG_MASK 0x07
+#define IP6T_LOG_UID 0x08 /* Log UID owning local socket */
+#define IP6T_LOG_MASK 0x0f
struct ip6t_log_info {
unsigned char level;
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index ee36f08c341e..9cad6dfd86b0 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -116,7 +116,6 @@ struct netlink_skb_parms
#define NETLINK_CREDS(skb) (&NETLINK_CB((skb)).creds)
-extern int netlink_post(int unit, struct sk_buff *skb);
extern struct sock *netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len));
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index a9e4817c416e..ccf1ccb80972 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -24,7 +24,6 @@ struct netpoll {
};
void netpoll_poll(struct netpoll *np);
-void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb);
void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
int netpoll_parse_options(struct netpoll *np, char *opt);
int netpoll_setup(struct netpoll *np);
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index 4de843d94147..16475a23efa7 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -38,6 +38,8 @@
*
* int first_node(mask) Number lowest set bit, or MAX_NUMNODES
* int next_node(node, mask) Next node past 'node', or MAX_NUMNODES
+ * int first_unset_node(mask) First node not set in mask, or
+ * MAX_NUMNODES.
*
* nodemask_t nodemask_of_node(node) Return nodemask with bit 'node' set
* NODE_MASK_ALL Initializer - all bits set
@@ -235,6 +237,13 @@ static inline int __next_node(int n, const nodemask_t *srcp, int nbits)
m; \
})
+#define first_unset_node(mask) __first_unset_node(&(mask))
+static inline int __first_unset_node(const nodemask_t *maskp)
+{
+ return min_t(int,MAX_NUMNODES,
+ find_first_zero_bit(maskp->bits, MAX_NUMNODES));
+}
+
#define NODE_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(MAX_NUMNODES)
#if MAX_NUMNODES <= BITS_PER_LONG
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index f36775e68710..791a795862c2 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -693,7 +693,7 @@
#define PCI_DEVICE_ID_HP_SX1000_IOC 0x127c
#define PCI_DEVICE_ID_HP_DIVA_EVEREST 0x1282
#define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290
-#define PCI_DEVICE_ID_HP_CISS 0x3210
+#define PCI_DEVICE_ID_HP_CISSA 0x3220
#define PCI_VENDOR_ID_PCTECH 0x1042
#define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000
diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
index 45ed903d247c..3101ef5000ad 100644
--- a/include/linux/pkt_cls.h
+++ b/include/linux/pkt_cls.h
@@ -249,6 +249,7 @@ enum
TCA_RSVP_SRC,
TCA_RSVP_PINFO,
TCA_RSVP_POLICE,
+ TCA_RSVP_ACT,
__TCA_RSVP_MAX
};
@@ -280,6 +281,7 @@ enum
TCA_ROUTE4_FROM,
TCA_ROUTE4_IIF,
TCA_ROUTE4_POLICE,
+ TCA_ROUTE4_ACT,
__TCA_ROUTE4_MAX
};
@@ -311,6 +313,7 @@ enum
TCA_TCINDEX_FALL_THROUGH,
TCA_TCINDEX_CLASSID,
TCA_TCINDEX_POLICE,
+ TCA_TCINDEX_ACT,
__TCA_TCINDEX_MAX
};
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 68da2eae8547..1d106a3edad5 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -28,44 +28,28 @@
#include <asm/atomic.h>
/*
- * Power management requests
+ * Power management requests... these are passed to pm_send_all() and friends.
+ *
+ * these functions are old and deprecated, see below.
*/
-enum
-{
- PM_SUSPEND, /* enter D1-D3 */
- PM_RESUME, /* enter D0 */
+typedef int __bitwise pm_request_t;
- PM_SAVE_STATE, /* save device's state */
+#define PM_SUSPEND ((__force pm_request_t) 1) /* enter D1-D3 */
+#define PM_RESUME ((__force pm_request_t) 2) /* enter D0 */
- /* enable wake-on */
- PM_SET_WAKEUP,
-
- /* bus resource management */
- PM_GET_RESOURCES,
- PM_SET_RESOURCES,
-
- /* base station management */
- PM_EJECT,
- PM_LOCK,
-};
-
-typedef int pm_request_t;
/*
- * Device types
+ * Device types... these are passed to pm_register
*/
-enum
-{
- PM_UNKNOWN_DEV = 0, /* generic */
- PM_SYS_DEV, /* system device (fan, KB controller, ...) */
- PM_PCI_DEV, /* PCI device */
- PM_USB_DEV, /* USB device */
- PM_SCSI_DEV, /* SCSI device */
- PM_ISA_DEV, /* ISA device */
- PM_MTD_DEV, /* Memory Technology Device */
-};
+typedef int __bitwise pm_dev_t;
-typedef int pm_dev_t;
+#define PM_UNKNOWN_DEV ((__force pm_dev_t) 0) /* generic */
+#define PM_SYS_DEV ((__force pm_dev_t) 1) /* system device (fan, KB controller, ...) */
+#define PM_PCI_DEV ((__force pm_dev_t) 2) /* PCI device */
+#define PM_USB_DEV ((__force pm_dev_t) 3) /* USB device */
+#define PM_SCSI_DEV ((__force pm_dev_t) 4) /* SCSI device */
+#define PM_ISA_DEV ((__force pm_dev_t) 5) /* ISA device */
+#define PM_MTD_DEV ((__force pm_dev_t) 6) /* Memory Technology Device */
/*
* System device hardware ID (PnP) values
@@ -119,32 +103,27 @@ extern int pm_active;
/*
* Register a device with power management
*/
-struct pm_dev *pm_register(pm_dev_t type,
- unsigned long id,
- pm_callback callback);
+struct pm_dev __deprecated *pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
/*
* Unregister a device with power management
*/
-void pm_unregister(struct pm_dev *dev);
+void __deprecated pm_unregister(struct pm_dev *dev);
/*
* Unregister all devices with matching callback
*/
-void pm_unregister_all(pm_callback callback);
+void __deprecated pm_unregister_all(pm_callback callback);
/*
* Send a request to a single device
*/
-int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data);
+int __deprecated pm_send(struct pm_dev *dev, pm_request_t rqst, void *data);
/*
* Send a request to all devices
*/
-int pm_send_all(pm_request_t rqst, void *data);
-
-static inline void pm_access(struct pm_dev *dev) {}
-static inline void pm_dev_idle(struct pm_dev *dev) {}
+int __deprecated pm_send_all(pm_request_t rqst, void *data);
#else /* CONFIG_PM */
@@ -171,16 +150,10 @@ static inline int pm_send_all(pm_request_t rqst, void *data)
return 0;
}
-static inline struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from)
-{
- return 0;
-}
-
-static inline void pm_access(struct pm_dev *dev) {}
-static inline void pm_dev_idle(struct pm_dev *dev) {}
-
#endif /* CONFIG_PM */
+/* Functions above this comment are list-based old-style power
+ * managment. Please avoid using them. */
/*
* Callbacks for platform drivers to implement.
@@ -222,10 +195,34 @@ extern int pm_suspend(suspend_state_t state);
struct device;
+typedef u32 __bitwise pm_message_t;
+
+/*
+ * There are 4 important states driver can be in:
+ * ON -- driver is working
+ * FREEZE -- stop operations and apply whatever policy is applicable to a suspended driver
+ * of that class, freeze queues for block like IDE does, drop packets for
+ * ethernet, etc... stop DMA engine too etc... so a consistent image can be
+ * saved; but do not power any hardware down.
+ * SUSPEND - like FREEZE, but hardware is doing as much powersaving as possible. Roughly
+ * pci D3.
+ *
+ * Unfortunately, current drivers only recognize numeric values 0 (ON) and 3 (SUSPEND).
+ * We'll need to fix the drivers. So yes, putting 3 to all diferent defines is intentional,
+ * and will go away as soon as drivers are fixed. Also note that typedef is neccessary,
+ * we'll probably want to switch to
+ * typedef struct pm_message_t { int event; int flags; } pm_message_t
+ * or something similar soon.
+ */
+
+#define PMSG_FREEZE ((__force pm_message_t) 3)
+#define PMSG_SUSPEND ((__force pm_message_t) 3)
+#define PMSG_ON ((__force pm_message_t) 0)
+
struct dev_pm_info {
- u32 power_state;
+ pm_message_t power_state;
#ifdef CONFIG_PM
- u32 prev_state;
+ pm_message_t prev_state;
void * saved_state;
atomic_t pm_users;
struct device * pm_parent;
@@ -235,8 +232,8 @@ struct dev_pm_info {
extern void device_pm_set_parent(struct device * dev, struct device * parent);
-extern int device_suspend(u32 state);
-extern int device_power_down(u32 state);
+extern int device_suspend(pm_message_t state);
+extern int device_power_down(pm_message_t state);
extern void device_power_up(void);
extern void device_resume(void);
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index f18247125091..a373fc254df2 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -87,6 +87,7 @@ extern void ptrace_notify(int exit_code);
extern void __ptrace_link(struct task_struct *child,
struct task_struct *new_parent);
extern void __ptrace_unlink(struct task_struct *child);
+extern void ptrace_untrace(struct task_struct *child);
static inline void ptrace_link(struct task_struct *child,
struct task_struct *new_parent)
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 354e5f88e4f8..c3d5d043a5ca 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -748,6 +748,7 @@ struct tcamsg
#include <linux/config.h>
+extern size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size);
static __inline__ int rtattr_strcmp(const struct rtattr *rta, const char *str)
{
int len = strlen(str) + 1;
@@ -756,6 +757,9 @@ static __inline__ int rtattr_strcmp(const struct rtattr *rta, const char *str)
extern int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len);
+#define rtattr_parse_nested(tb, max, rta) \
+ rtattr_parse((tb), (max), RTA_DATA((rta)), RTA_PAYLOAD((rta)))
+
extern struct sock *rtnl;
struct rtnetlink_link
@@ -765,7 +769,6 @@ struct rtnetlink_link
};
extern struct rtnetlink_link * rtnetlink_links[NPROTO];
-extern int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb);
extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo);
extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics);
@@ -806,6 +809,7 @@ extern struct semaphore rtnl_sem;
} while(0)
extern void rtnl_lock(void);
+extern int rtnl_lock_interruptible(void);
extern void rtnl_unlock(void);
extern void rtnetlink_init(void);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 3c2c63f23a4a..96f69aaa0534 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -20,6 +20,7 @@
#include <asm/page.h>
#include <asm/ptrace.h>
#include <asm/mmu.h>
+#include <asm/cputime.h>
#include <linux/smp.h>
#include <linux/sem.h>
@@ -120,6 +121,9 @@ extern unsigned long nr_iowait(void);
#define set_current_state(state_value) \
set_mb(current->state, (state_value))
+/* Task command name length */
+#define TASK_COMM_LEN 16
+
/*
* Scheduling policies
*/
@@ -168,7 +172,7 @@ long io_schedule_timeout(long timeout);
extern void cpu_init (void);
extern void trap_init(void);
extern void update_process_times(int user);
-extern void scheduler_tick(int user_tick, int system);
+extern void scheduler_tick(void);
extern unsigned long cache_decay_ticks;
/* Attach to any functions which should be ignored in wchan output. */
@@ -311,7 +315,7 @@ struct signal_struct {
* Live threads maintain their own counters and add to these
* in __exit_signal, except for the group leader.
*/
- unsigned long utime, stime, cutime, cstime;
+ cputime_t utime, stime, cutime, cstime;
unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
@@ -589,10 +593,11 @@ struct task_struct {
int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */
unsigned long rt_priority;
- unsigned long it_real_value, it_prof_value, it_virt_value;
- unsigned long it_real_incr, it_prof_incr, it_virt_incr;
+ unsigned long it_real_value, it_real_incr;
+ cputime_t it_virt_value, it_virt_incr;
+ cputime_t it_prof_value, it_prof_incr;
struct timer_list real_timer;
- unsigned long utime, stime;
+ cputime_t utime, stime;
unsigned long nvcsw, nivcsw; /* context switch counts */
struct timespec start_time;
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
@@ -610,7 +615,7 @@ struct task_struct {
struct key *thread_keyring; /* keyring private to this thread */
#endif
unsigned short used_math;
- char comm[16];
+ char comm[TASK_COMM_LEN];
/* file system info */
int link_count, total_link_count;
/* ipc stuff */
diff --git a/include/linux/sctp.h b/include/linux/sctp.h
index 1ed3da0cb9d0..6ec66dec29f7 100644
--- a/include/linux/sctp.h
+++ b/include/linux/sctp.h
@@ -364,7 +364,7 @@ typedef struct sctp_heartbeat_chunk {
*/
typedef struct sctp_abort_chunk {
sctp_chunkhdr_t uh;
-} __attribute__((packed)) sctp_abort_chunkt_t;
+} __attribute__((packed)) sctp_abort_chunk_t;
/* For the graceful shutdown we must carry the tag (in common header)
diff --git a/include/linux/security.h b/include/linux/security.h
index 4e0795b5a276..2b048ec62e9c 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -109,13 +109,20 @@ struct swap_info_struct;
* and the information saved in @bprm->security by the set_security hook.
* Since this hook function (and its caller) are void, this hook can not
* return an error. However, it can leave the security attributes of the
- * process unchanged if an access failure occurs at this point. It can
- * also perform other state changes on the process (e.g. closing open
- * file descriptors to which access is no longer granted if the attributes
- * were changed).
+ * process unchanged if an access failure occurs at this point.
* bprm_apply_creds is called under task_lock. @unsafe indicates various
* reasons why it may be unsafe to change security state.
* @bprm contains the linux_binprm structure.
+ * @bprm_post_apply_creds:
+ * Runs after bprm_apply_creds with the task_lock dropped, so that
+ * functions which cannot be called safely under the task_lock can
+ * be used. This hook is a good place to perform state changes on
+ * the process such as closing open file descriptors to which access
+ * is no longer granted if the attributes were changed.
+ * Note that a security module might need to save state between
+ * bprm_apply_creds and bprm_post_apply_creds to store the decision
+ * on whether the process may proceed.
+ * @bprm contains the linux_binprm structure.
* @bprm_set_security:
* Save security information in the bprm->security field, typically based
* on information about the bprm->file, for later use by the apply_creds
@@ -1042,6 +1049,7 @@ struct security_operations {
int (*bprm_alloc_security) (struct linux_binprm * bprm);
void (*bprm_free_security) (struct linux_binprm * bprm);
void (*bprm_apply_creds) (struct linux_binprm * bprm, int unsafe);
+ void (*bprm_post_apply_creds) (struct linux_binprm * bprm);
int (*bprm_set_security) (struct linux_binprm * bprm);
int (*bprm_check_security) (struct linux_binprm * bprm);
int (*bprm_secureexec) (struct linux_binprm * bprm);
@@ -1314,6 +1322,10 @@ static inline void security_bprm_apply_creds (struct linux_binprm *bprm, int uns
{
security_ops->bprm_apply_creds (bprm, unsafe);
}
+static inline void security_bprm_post_apply_creds (struct linux_binprm *bprm)
+{
+ security_ops->bprm_post_apply_creds (bprm);
+}
static inline int security_bprm_set (struct linux_binprm *bprm)
{
return security_ops->bprm_set_security (bprm);
@@ -1992,6 +2004,11 @@ static inline void security_bprm_apply_creds (struct linux_binprm *bprm, int uns
cap_bprm_apply_creds (bprm, unsafe);
}
+static inline void security_bprm_post_apply_creds (struct linux_binprm *bprm)
+{
+ return;
+}
+
static inline int security_bprm_set (struct linux_binprm *bprm)
{
return cap_bprm_set_security (bprm);
diff --git a/include/linux/selection.h b/include/linux/selection.h
index 059c958951f3..ed3408b400f1 100644
--- a/include/linux/selection.h
+++ b/include/linux/selection.h
@@ -10,7 +10,7 @@
#include <linux/tiocl.h>
#include <linux/vt_buffer.h>
-extern int sel_cons;
+extern struct vc_data *sel_cons;
extern void clear_selection(void);
extern int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty);
@@ -19,11 +19,6 @@ extern int sel_loadlut(char __user *p);
extern int mouse_reporting(void);
extern void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry);
-#define video_num_columns (vc_cons[currcons].d->vc_cols)
-#define video_num_lines (vc_cons[currcons].d->vc_rows)
-#define video_size_row (vc_cons[currcons].d->vc_size_row)
-#define can_do_color (vc_cons[currcons].d->vc_can_do_color)
-
extern int console_blanked;
extern unsigned char color_table[];
@@ -31,15 +26,15 @@ extern int default_red[];
extern int default_grn[];
extern int default_blu[];
-extern unsigned short *screen_pos(int currcons, int w_offset, int viewed);
-extern u16 screen_glyph(int currcons, int offset);
-extern void complement_pos(int currcons, int offset);
-extern void invert_screen(int currcons, int offset, int count, int shift);
+extern unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed);
+extern u16 screen_glyph(struct vc_data *vc, int offset);
+extern void complement_pos(struct vc_data *vc, int offset);
+extern void invert_screen(struct vc_data *vc, int offset, int count, int shift);
-extern void getconsxy(int currcons, unsigned char *p);
-extern void putconsxy(int currcons, unsigned char *p);
+extern void getconsxy(struct vc_data *vc, unsigned char *p);
+extern void putconsxy(struct vc_data *vc, unsigned char *p);
-extern u16 vcs_scr_readw(int currcons, const u16 *org);
-extern void vcs_scr_writew(int currcons, u16 val, u16 *org);
+extern u16 vcs_scr_readw(struct vc_data *vc, const u16 *org);
+extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org);
#endif
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index b1d0c472d19c..a6b744bccdc8 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1086,14 +1086,9 @@ extern struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags,
int noblock, int *err);
extern unsigned int datagram_poll(struct file *file, struct socket *sock,
struct poll_table_struct *wait);
-extern int skb_copy_datagram(const struct sk_buff *from,
- int offset, char __user *to, int size);
extern int skb_copy_datagram_iovec(const struct sk_buff *from,
int offset, struct iovec *to,
int size);
-extern int skb_copy_and_csum_datagram(const struct sk_buff *skb,
- int offset, u8 __user *to,
- int len, unsigned int *csump);
extern int skb_copy_and_csum_datagram_iovec(const
struct sk_buff *skb,
int hlen,
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 93c8264fe67b..0c7ae4f678a2 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -118,7 +118,6 @@ extern kmem_cache_t *mm_cachep;
extern kmem_cache_t *names_cachep;
extern kmem_cache_t *files_cachep;
extern kmem_cache_t *filp_cachep;
-extern kmem_cache_t *dquot_cachep;
extern kmem_cache_t *fs_cachep;
extern kmem_cache_t *signal_cachep;
extern kmem_cache_t *sighand_cachep;
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 4c7d11301abf..769ff4fc01b0 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -286,7 +286,6 @@ extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
extern int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode);
extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
-extern void memcpy_tokerneliovec(struct iovec *iov, unsigned char *kdata, int len);
extern int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ulen);
extern int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr);
extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
diff --git a/include/linux/umsdos_fs.h b/include/linux/umsdos_fs.h
deleted file mode 100644
index 67c25693db66..000000000000
--- a/include/linux/umsdos_fs.h
+++ /dev/null
@@ -1,182 +0,0 @@
-#ifndef LINUX_UMSDOS_FS_H
-#define LINUX_UMSDOS_FS_H
-
-
-/*#define UMS_DEBUG 1 // define for check_* functions */
-/*#define UMSDOS_DEBUG 1*/
-#define UMSDOS_PARANOIA 1
-
-#define UMSDOS_VERSION 0
-#define UMSDOS_RELEASE 4
-
-#define UMSDOS_ROOT_INO 1
-
-/* This is the file acting as a directory extension */
-#define UMSDOS_EMD_FILE "--linux-.---"
-#define UMSDOS_EMD_NAMELEN 12
-#define UMSDOS_PSDROOT_NAME "linux"
-#define UMSDOS_PSDROOT_LEN 5
-
-#ifndef _LINUX_TYPES_H
-#include <linux/types.h>
-#endif
-#ifndef _LINUX_LIMITS_H
-#include <linux/limits.h>
-#endif
-#ifndef _LINUX_DIRENT_H
-#include <linux/dirent.h>
-#endif
-#ifndef _LINUX_IOCTL_H
-#include <linux/ioctl.h>
-#endif
-
-
-#ifdef __KERNEL__
-/* #Specification: convention / PRINTK Printk and printk
- * Here is the convention for the use of printk inside fs/umsdos
- *
- * printk carry important message (error or status).
- * Printk is for debugging (it is a macro defined at the beginning of
- * most source.
- * PRINTK is a nulled Printk macro.
- *
- * This convention makes the source easier to read, and Printk easier
- * to shut off.
- */
-# define PRINTK(x)
-# ifdef UMSDOS_DEBUG
-# define Printk(x) printk x
-# else
-# define Printk(x)
-# endif
-#endif /* __KERNEL__ */
-
-
-struct umsdos_fake_info {
- char fname[13];
- int len;
-};
-
-#define UMSDOS_MAXNAME 220
-/* This structure is 256 bytes large, depending on the name, only part */
-/* of it is written to disk */
-/* nice though it would be, I can't change this and preserve backward compatibility */
-struct umsdos_dirent {
- unsigned char name_len; /* if == 0, then this entry is not used */
- unsigned char flags; /* UMSDOS_xxxx */
- unsigned short nlink; /* How many hard links point to this entry */
- __kernel_uid_t uid; /* Owner user id */
- __kernel_gid_t gid; /* Group id */
- time_t atime; /* Access time */
- time_t mtime; /* Last modification time */
- time_t ctime; /* Creation time */
- unsigned short rdev; /* major and minor of a device special file */
- umode_t mode; /* Standard UNIX permissions bits + type of */
- char spare[12]; /* unused bytes for future extensions */
- /* file, see linux/stat.h */
- char name[UMSDOS_MAXNAME]; /* Not '\0' terminated */
- /* but '\0' padded, so it will allow */
- /* for adding news fields in this record */
- /* by reducing the size of name[] */
-};
-
-#define UMSDOS_HIDDEN 1 /* Never show this entry in directory search */
-#define UMSDOS_HLINK 2 /* It is a (pseudo) hard link */
-
-/* #Specification: EMD file / record size
- * Entry are 64 bytes wide in the EMD file. It allows for a 30 characters
- * name. If a name is longer, contiguous entries are allocated. So a
- * umsdos_dirent may span multiple records.
- */
-
-#define UMSDOS_REC_SIZE 64
-
-/* Translation between MSDOS name and UMSDOS name */
-
-struct umsdos_info {
- int msdos_reject; /* Tell if the file name is invalid for MSDOS */
- /* See umsdos_parse */
- struct umsdos_fake_info fake;
- struct umsdos_dirent entry;
- off_t f_pos; /* offset of the entry in the EMD file
- * or offset where the entry may be store
- * if it is a new entry
- */
- int recsize; /* Record size needed to store entry */
-};
-
-/* Definitions for ioctl (number randomly chosen)
- * The next ioctl commands operate only on the DOS directory
- * The file umsdos_progs/umsdosio.c contain a string table
- * based on the order of those definition. Keep it in sync
- */
-#define UMSDOS_READDIR_DOS _IO(0x04,210) /* Do a readdir of the DOS directory */
-#define UMSDOS_UNLINK_DOS _IO(0x04,211) /* Erase in the DOS directory only */
-#define UMSDOS_RMDIR_DOS _IO(0x04,212) /* rmdir in the DOS directory only */
-#define UMSDOS_STAT_DOS _IO(0x04,213) /* Get info about a file */
-
-/* The next ioctl commands operate only on the EMD file */
-#define UMSDOS_CREAT_EMD _IO(0x04,214) /* Create a file */
-#define UMSDOS_UNLINK_EMD _IO(0x04,215) /* unlink (rmdir) a file */
-#define UMSDOS_READDIR_EMD _IO(0x04,216) /* read the EMD file only. */
-#define UMSDOS_GETVERSION _IO(0x04,217) /* Get the release number of UMSDOS */
-#define UMSDOS_INIT_EMD _IO(0x04,218) /* Create the EMD file if not there */
-#define UMSDOS_DOS_SETUP _IO(0x04,219) /* Set the defaults of the MS-DOS driver. */
-
-#define UMSDOS_RENAME_DOS _IO(0x04,220) /* rename a file/directory in the DOS
- * directory only */
-struct umsdos_ioctl {
- struct dirent dos_dirent;
- struct umsdos_dirent umsdos_dirent;
- /* The following structure is used to exchange some data with
- * utilities (umsdos_progs/util/umsdosio.c). The first releases
- * were using struct stat from "sys/stat.h". This was causing
- * some problem for cross compilation of the kernel.
- * Since I am not really using the structure stat, but only
- * some fields of it, I have decided to replicate the structure
- * here for compatibility with the binaries out there.
- * FIXME PTW 1998, this has probably changed
- */
-
- struct {
- unsigned long st_dev;
- ino_t st_ino; /* used */
- umode_t st_mode; /* used */
- nlink_t st_nlink;
- __kernel_uid_t st_uid;
- __kernel_gid_t st_gid;
- unsigned long st_rdev;
- off_t st_size; /* used */
- unsigned long st_blksize;
- unsigned long st_blocks;
- time_t st_atime; /* used */
- unsigned long __unused1;
- time_t st_mtime; /* used */
- unsigned long __unused2;
- time_t st_ctime; /* used */
- unsigned long __unused3;
- uid_t st_uid32;
- gid_t st_gid32;
- } stat;
- char version, release;
-};
-
-/* Different macros to access struct umsdos_dirent */
-#define EDM_ENTRY_ISUSED(e) ((e)->name_len!=0)
-
-#ifdef __KERNEL__
-
-#ifndef LINUX_FS_H
-#include <linux/fs.h>
-#endif
-
-extern struct inode_operations umsdos_dir_inode_operations;
-extern struct inode_operations umsdos_rdir_inode_operations;
-extern struct file_operations umsdos_dir_operations;
-extern struct file_operations umsdos_rdir_operations;
-
-#include <linux/umsdos_fs.p>
-
-#endif /* __KERNEL__ */
-
-#endif
diff --git a/include/linux/umsdos_fs.p b/include/linux/umsdos_fs.p
deleted file mode 100644
index 1c284c5a7aec..000000000000
--- a/include/linux/umsdos_fs.p
+++ /dev/null
@@ -1,100 +0,0 @@
-/* check.c 23/01/95 03.38.30 */
-void check_page_tables (void);
-
-/* dir.c 22/06/95 00.22.12 */
-int dummy_dir_read ( struct file *filp,
- char *buf,
- size_t size,
- loff_t *count);
-char * umsdos_d_path(struct dentry *, char *, int);
-void umsdos_lookup_patch_new(struct dentry *, struct umsdos_info *);
-int umsdos_is_pseudodos (struct inode *dir, struct dentry *dentry);
-struct dentry *umsdos_lookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo);
-struct dentry *UMSDOS_lookup(struct inode *, struct dentry *, struct nameidata *);
-struct dentry *umsdos_lookup_dentry(struct dentry *, char *, int, int);
-struct dentry *umsdos_covered(struct dentry *, char *, int);
-
-struct dentry *umsdos_solve_hlink (struct dentry *hlink);
-
-/* emd.c 22/06/95 00.22.04 */
-struct dentry *umsdos_get_emd_dentry(struct dentry *);
-int umsdos_have_emd(struct dentry *);
-int umsdos_make_emd(struct dentry *);
-int umsdos_emd_dir_readentry (struct dentry *, loff_t *, struct umsdos_dirent *);
-int umsdos_newentry (struct dentry *, struct umsdos_info *);
-int umsdos_newhidden (struct dentry *, struct umsdos_info *);
-int umsdos_delentry (struct dentry *, struct umsdos_info *, int);
-int umsdos_findentry (struct dentry *, struct umsdos_info *, int);
-int umsdos_isempty (struct dentry *);
-int umsdos_writeentry (struct dentry *, struct umsdos_info *, int);
-
-/* file.c 25/01/95 02.25.38 */
-
-/* inode.c 12/06/95 09.49.40 */
-void fill_new_filp (struct file *filp, struct dentry *dentry);
-void UMSDOS_read_inode (struct inode *);
-void UMSDOS_write_inode (struct inode *, int);
-int UMSDOS_notify_change (struct dentry *, struct iattr *attr);
-int umsdos_notify_change_locked(struct dentry *, struct iattr *attr);
-void UMSDOS_put_inode (struct inode *);
-int UMSDOS_statfs (struct super_block *, struct statfs *);
-struct super_block *UMSDOS_read_super (struct super_block *, void *, int);
-void UMSDOS_put_super (struct super_block *);
-
-void umsdos_setup_dir(struct dentry *);
-void umsdos_set_dirinfo_new(struct dentry *, off_t);
-void umsdos_patch_dentry_inode (struct dentry *, off_t);
-int umsdos_get_dirowner (struct inode *inode, struct inode **result);
-
-/* ioctl.c 22/06/95 00.22.08 */
-int UMSDOS_ioctl_dir (struct inode *dir,
- struct file *filp,
- unsigned int cmd,
- unsigned long data);
-
-/* mangle.c 25/01/95 02.25.38 */
-void umsdos_manglename (struct umsdos_info *info);
-int umsdos_evalrecsize (int len);
-int umsdos_parse (const char *name,int len, struct umsdos_info *info);
-
-/* namei.c 25/01/95 02.25.38 */
-void umsdos_lockcreate (struct inode *dir);
-void umsdos_startlookup (struct inode *dir);
-void umsdos_unlockcreate (struct inode *dir);
-void umsdos_endlookup (struct inode *dir);
-
-int umsdos_readlink_x ( struct dentry *dentry,
- char *buffer,
- int bufsiz);
-int UMSDOS_symlink (struct inode *dir,
- struct dentry *dentry,
- const char *symname);
-int UMSDOS_link (struct dentry *olddentry,
- struct inode *dir,
- struct dentry *dentry);
-int UMSDOS_create (struct inode *dir,
- struct dentry *dentry,
- int mode);
-
-int UMSDOS_mkdir (struct inode *dir,
- struct dentry *dentry,
- int mode);
-int UMSDOS_mknod (struct inode *dir,
- struct dentry *dentry,
- int mode,
- dev_t rdev);
-int UMSDOS_rmdir (struct inode *dir,struct dentry *dentry);
-int UMSDOS_unlink (struct inode *dir, struct dentry *dentry);
-int UMSDOS_rename (struct inode *old_dir,
- struct dentry *old_dentry,
- struct inode *new_dir,
- struct dentry *new_dentry);
-
-/* rdir.c 22/03/95 03.31.42 */
-struct dentry *umsdos_rlookup_x (struct inode *dir, struct dentry *dentry, int nopseudo);
-struct dentry *UMSDOS_rlookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd);
-
-static inline struct umsdos_inode_info *UMSDOS_I(struct inode *inode)
-{
- return &inode->u.umsdos_i;
-}
diff --git a/include/linux/umsdos_fs_i.h b/include/linux/umsdos_fs_i.h
deleted file mode 100644
index f4c992b44cd2..000000000000
--- a/include/linux/umsdos_fs_i.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef UMSDOS_FS_I_H
-#define UMSDOS_FS_I_H
-
-#ifndef _LINUX_TYPES_H
-#include <linux/types.h>
-#endif
-
-#include <linux/msdos_fs_i.h>
-#include <linux/pipe_fs_i.h>
-
-/* #Specification: strategy / in memory inode
- * Here is the information specific to the inode of the UMSDOS file
- * system. This information is added to the end of the standard struct
- * inode. Each file system has its own extension to struct inode,
- * so do the umsdos file system.
- *
- * The strategy is to have the umsdos_inode_info as a superset of
- * the msdos_inode_info, since most of the time the job is done
- * by the msdos fs code.
- *
- * So we duplicate the msdos_inode_info, and add our own info at the
- * end.
- *
- * The offset in this EMD file of the entry: pos
- *
- * For directory, we have dir_locking_info to help synchronise
- * file creation and file lookup. See also msdos_fs_i.h for more
- * information about msdos_inode_info.
- *
- * Special file and fifo do have an inode which correspond to an
- * empty MSDOS file.
- *
- * symlink are processed mostly like regular file. The content is the
- * link.
- *
- * The UMSDOS specific extension is placed after the union.
- */
-
-struct dir_locking_info {
- wait_queue_head_t p;
- short int looking; /* How many process doing a lookup */
- short int creating; /* Is there any creation going on here
- * Only one at a time, although one
- * may recursively lock, so it is a counter
- */
- long pid; /* pid of the process owning the creation
- * lock */
-};
-
-struct umsdos_inode_info {
- struct msdos_inode_info msdos_info;
- struct dir_locking_info dir_info;
- int i_patched; /* Inode has been patched */
- int i_is_hlink; /* Resolved hardlink inode? */
- off_t pos; /* Entry offset in the emd_owner file */
-};
-
-#endif
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 8c68717810c3..9af7ad38c08d 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -8,6 +8,7 @@
#define VM_IOREMAP 0x00000001 /* ioremap() and friends */
#define VM_ALLOC 0x00000002 /* vmalloc() */
#define VM_MAP 0x00000004 /* vmap()ed pages */
+/* bits [20..32] reserved for arch specific ioremap internals */
struct vm_struct {
void *addr;
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 97c2a6121275..bfcc02447b6b 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -112,7 +112,6 @@ extern int inet6_ac_check(struct sock *sk, struct in6_addr *addr, int ifindex);
extern int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr);
extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr);
-extern int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr);
extern int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr);
diff --git a/include/net/ax25.h b/include/net/ax25.h
index ab43611b59ba..fb95ecb6fe03 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -238,6 +238,7 @@ extern ax25_address null_ax25_address;
extern char *ax2asc(ax25_address *);
extern ax25_address *asc2ax(char *);
extern int ax25cmp(ax25_address *, ax25_address *);
+extern int ax25digicmp(ax25_digi *, ax25_digi *);
extern unsigned char *ax25_addr_parse(unsigned char *, int, ax25_address *, ax25_address *, ax25_digi *, int *, int *);
extern int ax25_addr_build(unsigned char *, ax25_address *, ax25_address *, ax25_digi *, int, int);
extern int ax25_addr_size(ax25_digi *);
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index fe5cc98511ba..fb2fa23c83e4 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -277,7 +277,6 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
return NULL;
}
-void hci_acl_connect(struct hci_conn *conn);
void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
void hci_add_sco(struct hci_conn *conn, __u16 handle);
@@ -589,6 +588,5 @@ struct hci_sec_filter {
#define hci_req_unlock(d) up(&d->req_lock)
void hci_req_complete(struct hci_dev *hdev, int result);
-void hci_req_cancel(struct hci_dev *hdev, int err);
#endif /* __HCI_CORE_H */
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 39ca54fbd041..490a65609560 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -38,17 +38,19 @@ struct sockaddr_l2 {
bdaddr_t l2_bdaddr;
};
-/* Socket options */
+/* L2CAP socket options */
#define L2CAP_OPTIONS 0x01
struct l2cap_options {
__u16 omtu;
__u16 imtu;
__u16 flush_to;
+ __u8 mode;
};
-#define L2CAP_CONNINFO 0x02
+#define L2CAP_CONNINFO 0x02
struct l2cap_conninfo {
__u16 hci_handle;
+ __u8 dev_class[3];
};
#define L2CAP_LM 0x03
@@ -59,20 +61,6 @@ struct l2cap_conninfo {
#define L2CAP_LM_RELIABLE 0x0010
#define L2CAP_LM_SECURE 0x0020
-#define L2CAP_QOS 0x04
-struct l2cap_qos {
- __u16 service_type;
- __u32 token_rate;
- __u32 token_bucket_size;
- __u32 peak_bandwidth;
- __u32 latency;
- __u32 delay_variation;
-};
-
-#define L2CAP_SERV_NO_TRAFFIC 0x00
-#define L2CAP_SERV_BEST_EFFORT 0x01
-#define L2CAP_SERV_GUARANTEED 0x02
-
/* L2CAP command codes */
#define L2CAP_COMMAND_REJ 0x01
#define L2CAP_CONN_REQ 0x02
@@ -154,6 +142,7 @@ struct l2cap_conf_opt {
#define L2CAP_CONF_MTU 0x01
#define L2CAP_CONF_FLUSH_TO 0x02
#define L2CAP_CONF_QOS 0x03
+#define L2CAP_CONF_RFC 0x04
#define L2CAP_CONF_MAX_SIZE 22
@@ -198,11 +187,11 @@ struct l2cap_conn {
bdaddr_t *dst;
bdaddr_t *src;
-
+
unsigned int mtu;
spinlock_t lock;
-
+
struct sk_buff *rx_skb;
__u32 rx_len;
__u8 rx_ident;
@@ -222,7 +211,7 @@ struct l2cap_pinfo {
__u16 imtu;
__u16 omtu;
__u16 flush_to;
-
+
__u32 link_mode;
__u8 conf_state;
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 819b06dfb08a..04b9847ace1a 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -181,6 +181,8 @@ struct rfcomm_dlc {
u8 v24_sig;
u8 mscex;
+ u32 link_mode;
+
uint mtu;
uint cfc;
uint rx_credits;
@@ -216,22 +218,6 @@ struct rfcomm_dlc {
#define RFCOMM_CFC_DISABLED 0
#define RFCOMM_CFC_ENABLED RFCOMM_MAX_CREDITS
-extern struct task_struct *rfcomm_thread;
-extern unsigned long rfcomm_event;
-
-static inline void rfcomm_schedule(uint event)
-{
- if (!rfcomm_thread)
- return;
- //set_bit(event, &rfcomm_event);
- set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
- wake_up_process(rfcomm_thread);
-}
-
-extern struct semaphore rfcomm_sem;
-#define rfcomm_lock() down(&rfcomm_sem);
-#define rfcomm_unlock() up(&rfcomm_sem);
-
/* ---- RFCOMM DLCs (channels) ---- */
struct rfcomm_dlc *rfcomm_dlc_alloc(int prio);
void rfcomm_dlc_free(struct rfcomm_dlc *d);
@@ -271,11 +257,6 @@ static inline void rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
}
/* ---- RFCOMM sessions ---- */
-struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state);
-struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
-struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err);
-void rfcomm_session_del(struct rfcomm_session *s);
-void rfcomm_session_close(struct rfcomm_session *s, int err);
void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst);
static inline void rfcomm_session_hold(struct rfcomm_session *s)
@@ -283,27 +264,36 @@ static inline void rfcomm_session_hold(struct rfcomm_session *s)
atomic_inc(&s->refcnt);
}
-static inline void rfcomm_session_put(struct rfcomm_session *s)
-{
- if (atomic_dec_and_test(&s->refcnt))
- rfcomm_session_del(s);
-}
-
/* ---- RFCOMM chechsum ---- */
extern u8 rfcomm_crc_table[];
/* ---- RFCOMM sockets ---- */
struct sockaddr_rc {
- sa_family_t rc_family;
- bdaddr_t rc_bdaddr;
- u8 rc_channel;
+ sa_family_t rc_family;
+ bdaddr_t rc_bdaddr;
+ u8 rc_channel;
};
+#define RFCOMM_CONNINFO 0x02
+struct rfcomm_conninfo {
+ __u16 hci_handle;
+ __u8 dev_class[3];
+};
+
+#define RFCOMM_LM 0x03
+#define RFCOMM_LM_MASTER 0x0001
+#define RFCOMM_LM_AUTH 0x0002
+#define RFCOMM_LM_ENCRYPT 0x0004
+#define RFCOMM_LM_TRUSTED 0x0008
+#define RFCOMM_LM_RELIABLE 0x0010
+#define RFCOMM_LM_SECURE 0x0020
+
#define rfcomm_pi(sk) ((struct rfcomm_pinfo *)sk->sk_protinfo)
struct rfcomm_pinfo {
struct rfcomm_dlc *dlc;
u8 channel;
+ u32 link_mode;
};
int rfcomm_init_sockets(void);
diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h
index a1c469cb7f19..bcd66c3feb1c 100644
--- a/include/net/bluetooth/sco.h
+++ b/include/net/bluetooth/sco.h
@@ -39,15 +39,16 @@ struct sockaddr_sco {
bdaddr_t sco_bdaddr;
};
-/* set/get sockopt defines */
-#define SCO_OPTIONS 0x01
+/* SCO socket options */
+#define SCO_OPTIONS 0x01
struct sco_options {
__u16 mtu;
};
-#define SCO_CONNINFO 0x02
+#define SCO_CONNINFO 0x02
struct sco_conninfo {
__u16 hci_handle;
+ __u8 dev_class[3];
};
/* ---- SCO connections ---- */
diff --git a/include/net/dn.h b/include/net/dn.h
index da2239862a1f..5e36492da13c 100644
--- a/include/net/dn.h
+++ b/include/net/dn.h
@@ -220,8 +220,6 @@ extern int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn
extern void dn_start_slow_timer(struct sock *sk);
extern void dn_stop_slow_timer(struct sock *sk);
-extern void dn_start_fast_timer(struct sock *sk);
-extern void dn_stop_fast_timer(struct sock *sk);
extern dn_address decnet_address;
extern int decnet_debug_level;
diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h
index ac4ec455e81e..cd3c96d9601b 100644
--- a/include/net/dn_fib.h
+++ b/include/net/dn_fib.h
@@ -117,7 +117,6 @@ struct dn_fib_table {
extern void dn_fib_init(void);
extern void dn_fib_cleanup(void);
-extern int dn_fib_rt_message(struct sk_buff *skb);
extern int dn_fib_ioctl(struct socket *sock, unsigned int cmd,
unsigned long arg);
extern struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r,
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 7fee4c0b2353..52da5d26617a 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -701,8 +701,6 @@ struct ip_vs_app
* (from ip_vs_core.c)
*/
extern const char *ip_vs_proto_name(unsigned proto);
-extern unsigned int check_for_ip_vs_out(struct sk_buff **skb_p,
- int (*okfn)(struct sk_buff *));
extern void ip_vs_init_hash_table(struct list_head *table, int rows);
#define IP_VS_INIT_HASH_TABLE(t) ip_vs_init_hash_table(t, sizeof(t)/sizeof(t[0]))
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 445fbfd71589..dc1feea01acb 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -229,8 +229,6 @@ extern int ip6_ra_control(struct sock *sk, int sel,
void (*destructor)(struct sock *));
-extern int ip6_call_ra_chain(struct sk_buff *skb, int sel);
-
extern int ipv6_parse_hopopts(struct sk_buff *skb, int);
extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h
index ac5acfc87658..44edd48f1234 100644
--- a/include/net/iw_handler.h
+++ b/include/net/iw_handler.h
@@ -418,9 +418,6 @@ struct iw_public_data {
* Those may be called only within the kernel.
*/
-/* Data needed by fs/compat_ioctl.c for 32->64 bit conversion */
-extern const char iw_priv_type_size[];
-
/* First : function strictly used inside the kernel */
/* Handle /proc/net/wireless, called in net/code/dev.c */
diff --git a/include/net/pkt_act.h b/include/net/pkt_act.h
index bf55ad5694ee..bd08964b72c0 100644
--- a/include/net/pkt_act.h
+++ b/include/net/pkt_act.h
@@ -218,25 +218,22 @@ tcf_hash_search(struct tc_action *a, u32 index)
#ifdef CONFIG_NET_ACT_INIT
static inline struct tcf_st *
-tcf_hash_check(struct tc_st *parm, struct tc_action *a, int ovr, int bind)
+tcf_hash_check(u32 index, struct tc_action *a, int ovr, int bind)
{
struct tcf_st *p = NULL;
- if (parm->index && (p = tcf_hash_lookup(parm->index)) != NULL) {
- spin_lock(&p->lock);
+ if (index && (p = tcf_hash_lookup(index)) != NULL) {
if (bind) {
p->bindcnt++;
p->refcnt++;
}
- spin_unlock(&p->lock);
- a->priv = (void *) p;
+ a->priv = p;
}
return p;
}
static inline struct tcf_st *
-tcf_hash_create(struct tc_st *parm, struct rtattr *est, struct tc_action *a, int size, int ovr, int bind)
+tcf_hash_create(u32 index, struct rtattr *est, struct tc_action *a, int size, int ovr, int bind)
{
- unsigned h;
struct tcf_st *p = NULL;
p = kmalloc(size, GFP_KERNEL);
@@ -252,31 +249,25 @@ tcf_hash_create(struct tc_st *parm, struct rtattr *est, struct tc_action *a, int
spin_lock_init(&p->lock);
p->stats_lock = &p->lock;
- p->index = parm->index ? : tcf_hash_new_index();
+ p->index = index ? : tcf_hash_new_index();
p->tm.install = jiffies;
p->tm.lastuse = jiffies;
#ifdef CONFIG_NET_ESTIMATOR
if (est)
gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est);
#endif
- h = tcf_hash(p->index);
- write_lock_bh(&tcf_t_lock);
- p->next = tcf_ht[h];
- tcf_ht[h] = p;
- write_unlock_bh(&tcf_t_lock);
-
a->priv = (void *) p;
return p;
}
-static inline struct tcf_st *
-tcf_hash_init(struct tc_st *parm, struct rtattr *est, struct tc_action *a, int size, int ovr, int bind)
+static inline void tcf_hash_insert(struct tcf_st *p)
{
- struct tcf_st *p = tcf_hash_check (parm,a,ovr,bind);
+ unsigned h = tcf_hash(p->index);
- if (!p)
- p = tcf_hash_create(parm, est, a, size, ovr, bind);
- return p;
+ write_lock_bh(&tcf_t_lock);
+ p->next = tcf_ht[h];
+ tcf_ht[h] = p;
+ write_unlock_bh(&tcf_t_lock);
}
#endif
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 973680c7537e..d12ad3831d14 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -17,7 +17,6 @@ struct tcf_walker
extern int register_tcf_proto_ops(struct tcf_proto_ops *ops);
extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
-extern int ing_filter(struct sk_buff *skb);
static inline unsigned long
__cls_set_class(unsigned long *clp, unsigned long cl)
@@ -62,100 +61,99 @@ tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r)
tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
}
-#ifdef CONFIG_NET_CLS_ACT
-static inline int
-tcf_change_act_police(struct tcf_proto *tp, struct tc_action **action,
- struct rtattr *act_police_tlv, struct rtattr *rate_tlv)
+struct tcf_exts
{
- int ret;
- struct tc_action *act;
-
- act = tcf_action_init_1(act_police_tlv, rate_tlv, "police",
- TCA_ACT_NOREPLACE, TCA_ACT_BIND, &ret);
- if (act == NULL)
- return ret;
-
- act->type = TCA_OLD_COMPAT;
-
- if (*action) {
- tcf_tree_lock(tp);
- act = xchg(action, act);
- tcf_tree_unlock(tp);
+#ifdef CONFIG_NET_CLS_ACT
+ struct tc_action *action;
+#elif defined CONFIG_NET_CLS_POLICE
+ struct tcf_police *police;
+#endif
+};
- tcf_action_destroy(act, TCA_ACT_UNBIND);
- } else
- *action = act;
+/* Map to export classifier specific extension TLV types to the
+ * generic extensions API. Unsupported extensions must be set to 0.
+ */
+struct tcf_ext_map
+{
+ int action;
+ int police;
+};
+/**
+ * tcf_exts_is_predicative - check if a predicative extension is present
+ * @exts: tc filter extensions handle
+ *
+ * Returns 1 if a predicative extension is present, i.e. an extension which
+ * might cause further actions and thus overrule the regular tcf_result.
+ */
+static inline int
+tcf_exts_is_predicative(struct tcf_exts *exts)
+{
+#ifdef CONFIG_NET_CLS_ACT
+ return !!exts->action;
+#elif defined CONFIG_NET_CLS_POLICE
+ return !!exts->police;
+#else
return 0;
+#endif
}
+/**
+ * tcf_exts_is_available - check if at least one extension is present
+ * @exts: tc filter extensions handle
+ *
+ * Returns 1 if at least one extension is present.
+ */
static inline int
-tcf_change_act(struct tcf_proto *tp, struct tc_action **action,
- struct rtattr *act_tlv, struct rtattr *rate_tlv)
+tcf_exts_is_available(struct tcf_exts *exts)
{
- int ret;
- struct tc_action *act;
-
- act = tcf_action_init(act_tlv, rate_tlv, NULL,
- TCA_ACT_NOREPLACE, TCA_ACT_BIND, &ret);
- if (act == NULL)
- return ret;
-
- if (*action) {
- tcf_tree_lock(tp);
- act = xchg(action, act);
- tcf_tree_unlock(tp);
-
- tcf_action_destroy(act, TCA_ACT_UNBIND);
- } else
- *action = act;
-
- return 0;
+ /* All non-predicative extensions must be added here. */
+ return tcf_exts_is_predicative(exts);
}
+/**
+ * tcf_exts_exec - execute tc filter extensions
+ * @skb: socket buffer
+ * @exts: tc filter extensions handle
+ * @res: desired result
+ *
+ * Executes all configured extensions. Returns 0 on a normal execution,
+ * a negative number if the filter must be considered unmatched or
+ * a positive action code (TC_ACT_*) which must be returned to the
+ * underlying layer.
+ */
static inline int
-tcf_dump_act(struct sk_buff *skb, struct tc_action *action,
- int act_type, int compat_type)
+tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
+ struct tcf_result *res)
{
- /*
- * again for backward compatible mode - we want
- * to work with both old and new modes of entering
- * tc data even if iproute2 was newer - jhs
- */
- if (action) {
- struct rtattr * p_rta = (struct rtattr*) skb->tail;
-
- if (action->type != TCA_OLD_COMPAT) {
- RTA_PUT(skb, act_type, 0, NULL);
- if (tcf_action_dump(skb, action, 0, 0) < 0)
- goto rtattr_failure;
- } else {
- RTA_PUT(skb, compat_type, 0, NULL);
- if (tcf_action_dump_old(skb, action, 0, 0) < 0)
- goto rtattr_failure;
- }
-
- p_rta->rta_len = skb->tail - (u8*)p_rta;
- }
- return 0;
+#ifdef CONFIG_NET_CLS_ACT
+ if (exts->action)
+ return tcf_action_exec(skb, exts->action, res);
+#elif defined CONFIG_NET_CLS_POLICE
+ if (exts->police)
+ return tcf_police(skb, exts->police);
+#endif
-rtattr_failure:
- return -1;
+ return 0;
}
-#endif /* CONFIG_NET_CLS_ACT */
+
+extern int tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,
+ struct rtattr *rate_tlv, struct tcf_exts *exts,
+ struct tcf_ext_map *map);
+extern void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts);
+extern void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
+ struct tcf_exts *src);
+extern int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
+ struct tcf_ext_map *map);
+extern int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
+ struct tcf_ext_map *map);
#ifdef CONFIG_NET_CLS_IND
static inline int
tcf_change_indev(struct tcf_proto *tp, char *indev, struct rtattr *indev_tlv)
{
- if (RTA_PAYLOAD(indev_tlv) >= IFNAMSIZ) {
- printk("cls: bad indev name %s\n", (char *) RTA_DATA(indev_tlv));
+ if (rtattr_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ)
return -EINVAL;
- }
-
- memset(indev, 0, IFNAMSIZ);
- sprintf(indev, "%s", (char *) RTA_DATA(indev_tlv));
-
return 0;
}
@@ -173,44 +171,4 @@ tcf_match_indev(struct sk_buff *skb, char *indev)
}
#endif /* CONFIG_NET_CLS_IND */
-#ifdef CONFIG_NET_CLS_POLICE
-static inline int
-tcf_change_police(struct tcf_proto *tp, struct tcf_police **police,
- struct rtattr *police_tlv, struct rtattr *rate_tlv)
-{
- struct tcf_police *p = tcf_police_locate(police_tlv, rate_tlv);
-
- if (*police) {
- tcf_tree_lock(tp);
- p = xchg(police, p);
- tcf_tree_unlock(tp);
-
- tcf_police_release(p, TCA_ACT_UNBIND);
- } else
- *police = p;
-
- return 0;
-}
-
-static inline int
-tcf_dump_police(struct sk_buff *skb, struct tcf_police *police,
- int police_type)
-{
- if (police) {
- struct rtattr * p_rta = (struct rtattr*) skb->tail;
-
- RTA_PUT(skb, police_type, 0, NULL);
-
- if (tcf_police_dump(skb, police) < 0)
- goto rtattr_failure;
-
- p_rta->rta_len = skb->tail - (u8*)p_rta;
- }
- return 0;
-
-rtattr_failure:
- return -1;
-}
-#endif /* CONFIG_NET_CLS_POLICE */
-
#endif
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 4e0e2246da93..ebc5282e6d58 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -189,11 +189,6 @@ typedef struct {
} sctp_cmd_seq_t;
-/* Create a new sctp_command_sequence.
- * Return NULL if creating a new sequence fails.
- */
-sctp_cmd_seq_t *sctp_new_cmd_seq(int gfp);
-
/* Initialize a block of memory as a command sequence.
* Return 0 if the initialization fails.
*/
@@ -207,18 +202,10 @@ int sctp_init_cmd_seq(sctp_cmd_seq_t *seq);
*/
int sctp_add_cmd(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj);
-/* Rewind an sctp_cmd_seq_t to iterate from the start.
- * Return 0 if the rewind fails.
- */
-int sctp_rewind_sequence(sctp_cmd_seq_t *seq);
-
/* Return the next command structure in an sctp_cmd_seq.
* Return NULL at the end of the sequence.
*/
sctp_cmd_t *sctp_next_cmd(sctp_cmd_seq_t *seq);
-/* Dispose of a command sequence. */
-void sctp_free_cmd_seq(sctp_cmd_seq_t *seq);
-
#endif /* __net_sctp_command_h__ */
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index bc1d9a63dd02..2b76c0f4babc 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -105,9 +105,10 @@ typedef enum {
typedef enum {
SCTP_EVENT_NO_PENDING_TSN = 0,
+ SCTP_EVENT_ICMP_PROTO_UNREACH,
} sctp_event_other_t;
-#define SCTP_EVENT_OTHER_MAX SCTP_EVENT_NO_PENDING_TSN
+#define SCTP_EVENT_OTHER_MAX SCTP_EVENT_ICMP_PROTO_UNREACH
#define SCTP_NUM_OTHER_TYPES (SCTP_EVENT_OTHER_MAX + 1)
/* These are primitive requests from the ULP. */
@@ -155,10 +156,6 @@ SCTP_SUBTYPE_CONSTRUCTOR(PRIMITIVE, sctp_event_primitive_t, primitive)
- (unsigned long)(c->chunk_hdr)\
- sizeof(sctp_data_chunk_t)))
-/* This is a table of printable names of sctp_param_t's. */
-extern const char *sctp_param_tbl[];
-
-
#define SCTP_MAX_ERROR_CAUSE SCTP_ERROR_NONEXIST_IP
#define SCTP_NUM_ERROR_CAUSE 10
@@ -179,6 +176,7 @@ typedef enum {
SCTP_IERROR_IGNORE_TSN,
SCTP_IERROR_NO_DATA,
SCTP_IERROR_BAD_STREAM,
+ SCTP_IERROR_BAD_PORTS,
} sctp_ierror_t;
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index f34b3aa1aa08..cca17d427c9d 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -162,17 +162,9 @@ __u32 sctp_update_copy_cksum(__u8 *, __u8 *, __u16 count, __u32 cksum);
int sctp_rcv(struct sk_buff *skb);
void sctp_v4_err(struct sk_buff *skb, u32 info);
void sctp_hash_established(struct sctp_association *);
-void __sctp_hash_established(struct sctp_association *);
void sctp_unhash_established(struct sctp_association *);
-void __sctp_unhash_established(struct sctp_association *);
void sctp_hash_endpoint(struct sctp_endpoint *);
-void __sctp_hash_endpoint(struct sctp_endpoint *);
void sctp_unhash_endpoint(struct sctp_endpoint *);
-void __sctp_unhash_endpoint(struct sctp_endpoint *);
-struct sctp_association *__sctp_lookup_association(
- const union sctp_addr *,
- const union sctp_addr *,
- struct sctp_transport **);
struct sock *sctp_err_lookup(int family, struct sk_buff *,
struct sctphdr *, struct sctp_endpoint **,
struct sctp_association **,
@@ -181,6 +173,10 @@ void sctp_err_finish(struct sock *, struct sctp_endpoint *,
struct sctp_association *);
void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
struct sctp_transport *t, __u32 pmtu);
+void sctp_icmp_proto_unreachable(struct sock *sk,
+ struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ struct sctp_transport *t);
/*
* Section: Macros, externs, and inlines
@@ -310,8 +306,6 @@ static inline int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int
int sctp_v6_init(void);
void sctp_v6_exit(void);
-void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info);
#else /* #ifdef defined(CONFIG_IPV6) */
@@ -455,7 +449,8 @@ _sctp_walk_params((pos), (chunk), WORD_ROUND(ntohs((chunk)->chunk_hdr.length)),
#define _sctp_walk_params(pos, chunk, end, member)\
for (pos.v = chunk->member;\
pos.v <= (void *)chunk + end - sizeof(sctp_paramhdr_t) &&\
- pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)); \
+ pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)) &&\
+ ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\
pos.v += WORD_ROUND(ntohs(pos.p->length)))
#define sctp_walk_errors(err, chunk_hdr)\
@@ -465,10 +460,9 @@ _sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length))
for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \
sizeof(sctp_chunkhdr_t));\
(void *)err <= (void *)chunk_hdr + end - sizeof(sctp_errhdr_t) &&\
- (void *)err <= (void *)chunk_hdr + end - \
- WORD_ROUND(ntohs(err->length));\
- err = (sctp_errhdr_t *)((void *)err + \
- WORD_ROUND(ntohs(err->length))))
+ (void *)err <= (void *)chunk_hdr + end - WORD_ROUND(ntohs(err->length)) &&\
+ ntohs(err->length) >= sizeof(sctp_errhdr_t); \
+ err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length))))
#define sctp_walk_fwdtsn(pos, chunk)\
_sctp_walk_fwdtsn((pos), (chunk), ntohs((chunk)->chunk_hdr->length) - sizeof(struct sctp_fwdtsn_chunk))
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index fc617506482a..5576db56324d 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -128,9 +128,9 @@ sctp_state_fn_t sctp_sf_do_9_2_shutdown;
sctp_state_fn_t sctp_sf_do_ecn_cwr;
sctp_state_fn_t sctp_sf_do_ecne;
sctp_state_fn_t sctp_sf_ootb;
-sctp_state_fn_t sctp_sf_shut_8_4_5;
sctp_state_fn_t sctp_sf_pdiscard;
sctp_state_fn_t sctp_sf_violation;
+sctp_state_fn_t sctp_sf_violation_chunklen;
sctp_state_fn_t sctp_sf_discard_chunk;
sctp_state_fn_t sctp_sf_do_5_2_1_siminit;
sctp_state_fn_t sctp_sf_do_5_2_2_dupinit;
@@ -138,7 +138,6 @@ sctp_state_fn_t sctp_sf_do_5_2_4_dupcook;
sctp_state_fn_t sctp_sf_unk_chunk;
sctp_state_fn_t sctp_sf_do_8_5_1_E_sa;
sctp_state_fn_t sctp_sf_cookie_echoed_err;
-sctp_state_fn_t sctp_sf_do_5_2_6_stale;
sctp_state_fn_t sctp_sf_do_asconf;
sctp_state_fn_t sctp_sf_do_asconf_ack;
sctp_state_fn_t sctp_sf_do_9_2_reshutack;
@@ -167,6 +166,7 @@ sctp_state_fn_t sctp_sf_do_prm_asconf;
sctp_state_fn_t sctp_sf_do_9_2_start_shutdown;
sctp_state_fn_t sctp_sf_do_9_2_shutdown_ack;
sctp_state_fn_t sctp_sf_ignore_other;
+sctp_state_fn_t sctp_sf_cookie_wait_icmp_abort;
/* Prototypes for timeout event state functions. */
sctp_state_fn_t sctp_sf_do_6_3_3_rtx;
@@ -200,19 +200,10 @@ struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *,
struct sctp_chunk *sctp_make_cwr(const struct sctp_association *,
const __u32 lowest_tsn,
const struct sctp_chunk *);
-struct sctp_chunk *sctp_make_datafrag(struct sctp_association *,
- const struct sctp_sndrcvinfo *sinfo,
- int len, const __u8 *data,
- __u8 flags, __u16 ssn);
struct sctp_chunk * sctp_make_datafrag_empty(struct sctp_association *,
const struct sctp_sndrcvinfo *sinfo,
int len, const __u8 flags,
__u16 ssn);
-struct sctp_chunk *sctp_make_data(struct sctp_association *,
- const struct sctp_sndrcvinfo *sinfo,
- int len, const __u8 *data);
-struct sctp_chunk *sctp_make_data_empty(struct sctp_association *,
- const struct sctp_sndrcvinfo *, int len);
struct sctp_chunk *sctp_make_ecne(const struct sctp_association *,
const __u32);
struct sctp_chunk *sctp_make_sack(const struct sctp_association *);
@@ -232,6 +223,10 @@ struct sctp_chunk *sctp_make_abort_no_data(const struct sctp_association *,
struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *,
const struct sctp_chunk *,
const struct msghdr *);
+struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *,
+ const struct sctp_chunk *,
+ const __u8 *,
+ const size_t );
struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,
const struct sctp_transport *,
const void *payload,
@@ -246,17 +241,12 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *,
const void *payload,
size_t paylen);
-struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
- union sctp_addr *addr,
- int vparam_len);
struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
union sctp_addr *,
struct sockaddr *,
int, __u16);
struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
union sctp_addr *addr);
-struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *asoc,
- __u32 serial, int vparam_len);
struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
struct sctp_chunk *asconf);
int sctp_process_asconf_ack(struct sctp_association *asoc,
@@ -268,6 +258,8 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
void sctp_chunk_assign_tsn(struct sctp_chunk *);
void sctp_chunk_assign_ssn(struct sctp_chunk *);
+void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error);
+
/* Prototypes for statetable processing. */
int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
@@ -277,71 +269,26 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
void *event_arg,
int gfp);
-int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
- sctp_state_t state,
- struct sctp_endpoint *,
- struct sctp_association *asoc,
- void *event_arg,
- sctp_disposition_t status,
- sctp_cmd_seq_t *commands,
- int gfp);
-
/* 2nd level prototypes */
-int sctp_cmd_interpreter(sctp_event_t, sctp_subtype_t, sctp_state_t,
- struct sctp_endpoint *, struct sctp_association *,
- void *event_arg, sctp_disposition_t,
- sctp_cmd_seq_t *retval, int gfp);
-
-
-int sctp_gen_sack(struct sctp_association *, int force, sctp_cmd_seq_t *);
void sctp_generate_t3_rtx_event(unsigned long peer);
void sctp_generate_heartbeat_event(unsigned long peer);
-sctp_sackhdr_t *sctp_sm_pull_sack(struct sctp_chunk *);
-struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *,
- const struct sctp_association *,
- struct sctp_chunk *chunk,
- const void *payload,
- size_t paylen);
-struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *,
- const struct sctp_chunk *);
void sctp_ootb_pkt_free(struct sctp_packet *);
-struct sctp_cookie_param *
-sctp_pack_cookie(const struct sctp_endpoint *, const struct sctp_association *,
- const struct sctp_chunk *, int *cookie_len,
- const __u8 *, int addrs_len);
struct sctp_association *sctp_unpack_cookie(const struct sctp_endpoint *,
const struct sctp_association *,
struct sctp_chunk *, int gfp, int *err,
struct sctp_chunk **err_chk_p);
int sctp_addip_addr_config(struct sctp_association *, sctp_param_t,
struct sockaddr_storage*, int);
-void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
- const struct sctp_association *asoc,
- const struct sctp_chunk *chunk,
- sctp_cmd_seq_t *commands,
- struct sctp_chunk *err_chunk);
-int sctp_eat_data(const struct sctp_association *asoc,
- struct sctp_chunk *chunk,
- sctp_cmd_seq_t *commands);
/* 3rd level prototypes */
__u32 sctp_generate_tag(const struct sctp_endpoint *);
__u32 sctp_generate_tsn(const struct sctp_endpoint *);
/* Extern declarations for major data structures. */
-const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t);
-extern const sctp_sm_table_entry_t
-primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES];
-extern const sctp_sm_table_entry_t
-other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES];
-extern const sctp_sm_table_entry_t
-timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES];
extern sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES];
-/* These are some handy utility macros... */
-
/* Get the size of a DATA chunk payload. */
static inline __u16 sctp_data_size(struct sctp_chunk *chunk)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 3bd04bc5b002..dfa0dc43fb17 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -322,10 +322,19 @@ struct sctp_cookie {
/* This holds the originating address of the INIT packet. */
union sctp_addr peer_addr;
+ /* IG Section 2.35.3
+ * Include the source port of the INIT-ACK
+ */
+ __u16 my_port;
+
__u8 prsctp_capable;
+ /* Padding for future use */
+ __u8 padding;
+
__u32 adaption_ind;
+
/* This is a shim for my peer's INIT packet, followed by
* a copy of the raw address list of the association.
* The length of the raw address list is saved in the
@@ -406,7 +415,6 @@ struct sctp_ssnmap {
int malloced;
};
-struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *, __u16, __u16);
struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, int gfp);
void sctp_ssnmap_free(struct sctp_ssnmap *map);
void sctp_ssnmap_clear(struct sctp_ssnmap *map);
@@ -538,12 +546,9 @@ struct sctp_datamsg {
struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *,
struct sctp_sndrcvinfo *,
struct msghdr *, int len);
-struct sctp_datamsg *sctp_datamsg_new(int gfp);
void sctp_datamsg_put(struct sctp_datamsg *);
-void sctp_datamsg_hold(struct sctp_datamsg *);
void sctp_datamsg_free(struct sctp_datamsg *);
void sctp_datamsg_track(struct sctp_chunk *);
-void sctp_datamsg_assign(struct sctp_datamsg *, struct sctp_chunk *);
void sctp_chunk_fail(struct sctp_chunk *, int error);
int sctp_chunk_abandoned(struct sctp_chunk *);
@@ -651,8 +656,6 @@ void sctp_chunk_hold(struct sctp_chunk *);
void sctp_chunk_put(struct sctp_chunk *);
int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len,
struct iovec *data);
-struct sctp_chunk *sctp_make_chunk(const struct sctp_association *, __u8 type,
- __u8 flags, int size);
void sctp_chunk_free(struct sctp_chunk *);
void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data);
struct sctp_chunk *sctp_chunkify(struct sk_buff *,
@@ -853,12 +856,6 @@ struct sctp_transport {
/* Error count : The current error count for this destination. */
unsigned short error_count;
- /* Error : Current error threshold for this destination
- * Threshold : i.e. what value marks the destination down if
- * : errorCount reaches this value.
- */
- unsigned short error_threshold;
-
/* This is the max_retrans value for the transport and will
* be initialized to proto.max_retrans.path. This can be changed
* using SCTP_SET_PEER_ADDR_PARAMS socket option.
@@ -922,15 +919,12 @@ struct sctp_transport {
};
struct sctp_transport *sctp_transport_new(const union sctp_addr *, int);
-struct sctp_transport *sctp_transport_init(struct sctp_transport *,
- const union sctp_addr *, int);
void sctp_transport_set_owner(struct sctp_transport *,
struct sctp_association *);
void sctp_transport_route(struct sctp_transport *, union sctp_addr *,
struct sctp_opt *);
void sctp_transport_pmtu(struct sctp_transport *);
void sctp_transport_free(struct sctp_transport *);
-void sctp_transport_destroy(struct sctp_transport *);
void sctp_transport_reset_timers(struct sctp_transport *);
void sctp_transport_hold(struct sctp_transport *);
void sctp_transport_put(struct sctp_transport *);
@@ -961,7 +955,6 @@ struct sctp_inq {
int malloced; /* Is this structure kfree()able? */
};
-struct sctp_inq *sctp_inq_new(void);
void sctp_inq_init(struct sctp_inq *);
void sctp_inq_free(struct sctp_inq *);
void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet);
@@ -1029,7 +1022,6 @@ struct sctp_outq {
char malloced;
};
-struct sctp_outq *sctp_outq_new(struct sctp_association *);
void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
void sctp_outq_teardown(struct sctp_outq *);
void sctp_outq_free(struct sctp_outq*);
@@ -1070,7 +1062,6 @@ struct sctp_bind_addr {
int malloced; /* Are we kfree()able? */
};
-struct sctp_bind_addr *sctp_bind_addr_new(int gfp_mask);
void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port);
void sctp_bind_addr_free(struct sctp_bind_addr *);
int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
@@ -1220,8 +1211,6 @@ static inline struct sctp_endpoint *sctp_ep(struct sctp_ep_common *base)
/* These are function signatures for manipulating endpoints. */
struct sctp_endpoint *sctp_endpoint_new(struct sock *, int);
-struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *,
- struct sock *, int gfp);
void sctp_endpoint_free(struct sctp_endpoint *);
void sctp_endpoint_put(struct sctp_endpoint *);
void sctp_endpoint_hold(struct sctp_endpoint *);
@@ -1243,8 +1232,6 @@ int sctp_verify_init(const struct sctp_association *asoc, sctp_cid_t,
int sctp_process_init(struct sctp_association *, sctp_cid_t cid,
const union sctp_addr *peer,
sctp_init_chunk_t *init, int gfp);
-int sctp_process_param(struct sctp_association *, union sctp_params param,
- const union sctp_addr *from, int gfp);
__u32 sctp_generate_tag(const struct sctp_endpoint *);
__u32 sctp_generate_tsn(const struct sctp_endpoint *);
@@ -1690,10 +1677,6 @@ static inline struct sctp_association *sctp_assoc(struct sctp_ep_common *base)
struct sctp_association *
sctp_association_new(const struct sctp_endpoint *, const struct sock *,
sctp_scope_t scope, int gfp);
-struct sctp_association *
-sctp_association_init(struct sctp_association *, const struct sctp_endpoint *,
- const struct sock *, sctp_scope_t scope,
- int gfp);
void sctp_association_free(struct sctp_association *);
void sctp_association_put(struct sctp_association *);
void sctp_association_hold(struct sctp_association *);
@@ -1722,7 +1705,6 @@ void sctp_assoc_update(struct sctp_association *old,
struct sctp_association *new);
__u32 sctp_association_get_next_tsn(struct sctp_association *);
-__u32 sctp_association_get_tsn_block(struct sctp_association *, int);
void sctp_assoc_sync_pmtu(struct sctp_association *);
void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned);
@@ -1736,7 +1718,6 @@ int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *,
int sctp_cmp_addr_exact(const union sctp_addr *ss1,
const union sctp_addr *ss2);
struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc);
-struct sctp_chunk *sctp_get_no_prepend(struct sctp_association *asoc);
/* A convenience structure to parse out SCTP specific CMSGs. */
typedef struct sctp_cmsgs {
diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h
index 8d77b89ca979..021947da70ea 100644
--- a/include/net/sctp/tsnmap.h
+++ b/include/net/sctp/tsnmap.h
@@ -120,12 +120,6 @@ struct sctp_tsnmap_iter {
__u32 start;
};
-/* Create a new tsnmap. */
-struct sctp_tsnmap *sctp_tsnmap_new(__u16 len, __u32 init_tsn, int gfp);
-
-/* Dispose of a tsnmap. */
-void sctp_tsnmap_free(struct sctp_tsnmap *);
-
/* This macro assists in creation of external storage for variable length
* internal buffers. We double allocate so the overflow map works.
*/
@@ -210,14 +204,4 @@ void sctp_tsnmap_renege(struct sctp_tsnmap *, __u32 tsn);
/* Is there a gap in the TSN map? */
int sctp_tsnmap_has_gap(const struct sctp_tsnmap *);
-/* Initialize a gap ack block interator from user-provided memory. */
-void sctp_tsnmap_iter_init(const struct sctp_tsnmap *,
- struct sctp_tsnmap_iter *);
-
-/* Get the next gap ack blocks. We return 0 if there are no more
- * gap ack blocks.
- */
-int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *,
- struct sctp_tsnmap_iter *,__u16 *start, __u16 *end);
-
#endif /* __sctp_tsnmap_h__ */
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 46a974464a84..1019d83a580a 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -77,8 +77,6 @@ static inline struct sctp_ulpevent *sctp_skb2event(struct sk_buff *skb)
return (struct sctp_ulpevent *)skb->cb;
}
-struct sctp_ulpevent *sctp_ulpevent_new(int size, int flags, int gfp);
-void sctp_ulpevent_init(struct sctp_ulpevent *, int flags);
void sctp_ulpevent_free(struct sctp_ulpevent *);
int sctp_ulpevent_is_notification(const struct sctp_ulpevent *);
void sctp_queue_purge_ulpevents(struct sk_buff_head *list);
diff --git a/include/net/sctp/ulpqueue.h b/include/net/sctp/ulpqueue.h
index 5a2ce0cf4d00..961736d29d21 100644
--- a/include/net/sctp/ulpqueue.h
+++ b/include/net/sctp/ulpqueue.h
@@ -57,7 +57,6 @@ struct sctp_ulpq {
};
/* Prototypes. */
-struct sctp_ulpq *sctp_ulpq_new(struct sctp_association *asoc, int gfp);
struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *,
struct sctp_association *);
void sctp_ulpq_free(struct sctp_ulpq *);
diff --git a/include/net/sock.h b/include/net/sock.h
index 5c49711c56cf..dc9a2bdf99c7 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -733,11 +733,6 @@ extern struct sk_buff *sock_alloc_send_skb(struct sock *sk,
unsigned long size,
int noblock,
int *errcode);
-extern struct sk_buff *sock_alloc_send_pskb(struct sock *sk,
- unsigned long header_len,
- unsigned long data_len,
- int noblock,
- int *errcode);
extern void *sock_kmalloc(struct sock *sk, int size, int priority);
extern void sock_kfree_s(struct sock *sk, void *mem, int size);
extern void sk_send_sigurg(struct sock *sk);
@@ -795,8 +790,6 @@ extern void sk_common_release(struct sock *sk);
* Default socket callbacks and setup code
*/
-extern void sock_def_destruct(struct sock *);
-
/* Initialise core socket variables */
extern void sock_init_data(struct socket *sock, struct sock *sk);
diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h
index 29ddb6630219..eb21689d759d 100644
--- a/include/net/tc_act/tc_pedit.h
+++ b/include/net/tc_act/tc_pedit.h
@@ -8,7 +8,7 @@ struct tcf_pedit
tca_gen(pedit);
unsigned char nkeys;
unsigned char flags;
- struct tc_pedit_key keys[0];
+ struct tc_pedit_key *keys;
};
#endif
diff --git a/include/pcmcia/bulkmem.h b/include/pcmcia/bulkmem.h
index f6954220f419..b53b78d497ba 100644
--- a/include/pcmcia/bulkmem.h
+++ b/include/pcmcia/bulkmem.h
@@ -1,33 +1,15 @@
/*
- * Definitions for bulk memory services
+ * bulkmem.h -- Definitions for bulk memory services
*
- * bulkmem.h 1.12 2000/06/12 21:55:41
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice 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.
- * bulkmem.h 1.3 1995/05/27 04:49:49
+ * (C) 1999 David A. Hinds
*/
#ifndef _LINUX_BULKMEM_H
diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h
index 0d84b163d055..2000b43ece91 100644
--- a/include/pcmcia/ciscode.h
+++ b/include/pcmcia/ciscode.h
@@ -1,30 +1,15 @@
/*
- * ciscode.h 1.56 2002/10/25 06:37:30
+ * ciscode.h -- Definitions for bulk memory services
*
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice 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.
+ * (C) 1999 David A. Hinds
*/
#ifndef _LINUX_CISCODE_H
diff --git a/include/pcmcia/cisreg.h b/include/pcmcia/cisreg.h
index 803d2c369a4b..ddaad465502e 100644
--- a/include/pcmcia/cisreg.h
+++ b/include/pcmcia/cisreg.h
@@ -1,30 +1,15 @@
/*
- * cisreg.h 1.17 2000/06/12 21:55:41
+ * cisreg.h
*
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice 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.
+ * (C) 1999 David A. Hinds
*/
#ifndef _LINUX_CISREG_H
diff --git a/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h
index 499f748c0028..c6a069554fd7 100644
--- a/include/pcmcia/cistpl.h
+++ b/include/pcmcia/cistpl.h
@@ -1,30 +1,15 @@
/*
- * cistpl.h 1.34 2000/06/19 23:18:12
+ * cistpl.h
*
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice 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.
+ * (C) 1999 David A. Hinds
*/
#ifndef _LINUX_CISTPL_H
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index 48eddee1e554..311682a7fef0 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -1,30 +1,15 @@
/*
- * cs.h 1.71 2000/08/29 00:54:20
+ * cs.h
*
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice 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.
+ * (C) 1999 David A. Hinds
*/
#ifndef _LINUX_CS_H
@@ -139,7 +124,7 @@ typedef struct client_req_t {
/* For RegisterClient */
typedef struct client_reg_t {
dev_info_t *dev_info;
- u_int Attributes;
+ u_int Attributes; /* UNUSED */
u_int EventMask;
int (*event_handler)(event_t event, int priority,
event_callback_args_t *);
@@ -294,7 +279,7 @@ typedef struct win_req_t {
#define WIN_BAR_MASK 0xe000
#define WIN_BAR_SHIFT 13
-/* Attributes for RegisterClient */
+/* Attributes for RegisterClient -- UNUSED -- */
#define INFO_MASTER_CLIENT 0x01
#define INFO_IO_CLIENT 0x02
#define INFO_MTD_CLIENT 0x04
@@ -315,23 +300,9 @@ typedef struct error_info_t {
int retcode;
} error_info_t;
-/* Special stuff for binding drivers to sockets */
-typedef struct bind_req_t {
- struct pcmcia_socket *Socket;
- u_char Function;
- dev_info_t *dev_info;
-} bind_req_t;
-
/* Flag to bind to all functions */
#define BIND_FN_ALL 0xff
-typedef struct mtd_bind_t {
- struct pcmcia_socket *Socket;
- u_int Attributes;
- u_int CardOffset;
- dev_info_t *dev_info;
-} mtd_bind_t;
-
/* Events */
#define CS_EVENT_PRI_LOW 0
#define CS_EVENT_PRI_HIGH 1
@@ -420,6 +391,8 @@ enum service {
GetFirstWindow, GetNextWindow, GetMemPage
};
+struct pcmcia_socket;
+
int pcmcia_access_configuration_register(client_handle_t handle, conf_reg_t *reg);
int pcmcia_deregister_client(client_handle_t handle);
int pcmcia_get_configuration_info(client_handle_t handle, config_info_t *config);
@@ -446,12 +419,8 @@ int pcmcia_eject_card(struct pcmcia_socket *skt);
int pcmcia_insert_card(struct pcmcia_socket *skt);
int pcmcia_report_error(client_handle_t handle, error_info_t *err);
-#ifdef CONFIG_PCMCIA_OBSOLETE
-int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req);
-int pcmcia_get_next_client(client_handle_t *handle, client_req_t *req);
-int pcmcia_modify_window(window_handle_t win, modwin_t *req);
-int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask);
-#endif
+struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt);
+void pcmcia_put_socket(struct pcmcia_socket *skt);
#endif /* __KERNEL__ */
diff --git a/include/pcmcia/cs_types.h b/include/pcmcia/cs_types.h
index 3a4aec08549e..b57c921998f0 100644
--- a/include/pcmcia/cs_types.h
+++ b/include/pcmcia/cs_types.h
@@ -1,30 +1,15 @@
/*
- * cs_types.h 1.18 2000/06/12 21:55:40
+ * cs_types.h
*
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice 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.
+ * (C) 1999 David A. Hinds
*/
#ifndef _LINUX_CS_TYPES_H
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 8a22fecf1cbd..1a7a03d8623a 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -1,30 +1,16 @@
/*
- * ds.h 1.56 2000/06/12 21:55:40
+ * ds.h -- 16-bit PCMCIA core support
*
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice 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.
+ * (C) 1999 David A. Hinds
+ * (C) 2003 - 2004 Dominik Brodowski
*/
#ifndef _LINUX_DS_H
@@ -141,10 +127,11 @@ typedef struct dev_link_t {
((l) && ((l->state & ~DEV_BUSY) == (DEV_CONFIG|DEV_PRESENT)))
+struct pcmcia_socket;
+
extern struct bus_type pcmcia_bus_type;
struct pcmcia_driver {
- int use_count;
dev_link_t *(*attach)(void);
void (*detach)(dev_link_t *);
struct module *owner;
@@ -155,6 +142,42 @@ struct pcmcia_driver {
int pcmcia_register_driver(struct pcmcia_driver *driver);
void pcmcia_unregister_driver(struct pcmcia_driver *driver);
+struct pcmcia_device {
+ /* the socket and the device_no [for multifunction devices]
+ uniquely define a pcmcia_device */
+ struct pcmcia_socket *socket;
+
+ u8 device_no;
+
+ /* the hardware "function" device; certain subdevices can
+ * share one hardware "function" device. */
+ u8 func;
+
+ struct list_head socket_device_list;
+
+ /* deprecated, a cleaned up version will be moved into this
+ struct soon */
+ dev_link_t *instance;
+ struct client_t {
+ u_short client_magic;
+ struct pcmcia_socket *Socket;
+ u_char Function;
+ u_int state;
+ event_t EventMask;
+ int (*event_handler) (event_t event, int priority,
+ event_callback_args_t *);
+ event_callback_args_t event_callback_args;
+ } client;
+
+ struct device dev;
+};
+
+#define to_pcmcia_dev(n) container_of(n, struct pcmcia_device, dev)
+#define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv)
+
+#define handle_to_pdev(handle) container_of(handle, struct pcmcia_device, client);
+#define handle_to_dev(handle) ((container_of(handle, struct pcmcia_device, client))->dev)
+
/* error reporting */
void cs_error(client_handle_t handle, int func, int ret);
diff --git a/include/pcmcia/mem_op.h b/include/pcmcia/mem_op.h
index 261dd5bbbdf2..8d19b9401a5b 100644
--- a/include/pcmcia/mem_op.h
+++ b/include/pcmcia/mem_op.h
@@ -1,30 +1,15 @@
/*
- * mem_op.h 1.13 2000/06/12 21:55:40
+ * mem_op.h
*
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice 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.
+ * (C) 1999 David A. Hinds
*/
#ifndef _LINUX_MEM_OP_H
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 1958cda29889..70cbca2638c5 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -1,30 +1,15 @@
/*
- * ss.h 1.28 2000/06/12 21:55:40
+ * ss.h
*
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice 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.
+ * (C) 1999 David A. Hinds
*/
#ifndef _LINUX_SS_H
@@ -130,6 +115,28 @@ struct pccard_operations {
int (*set_mem_map)(struct pcmcia_socket *sock, struct pccard_mem_map *mem);
};
+struct pccard_resource_ops {
+ void (*validate_mem) (struct pcmcia_socket *s);
+ int (*adjust_io_region) (struct resource *res,
+ unsigned long r_start,
+ unsigned long r_end,
+ struct pcmcia_socket *s);
+ struct resource* (*find_io) (unsigned long base, int num,
+ unsigned long align,
+ struct pcmcia_socket *s);
+ struct resource* (*find_mem) (unsigned long base, unsigned long num,
+ unsigned long align, int low,
+ struct pcmcia_socket *s);
+ int (*adjust_resource) (struct pcmcia_socket *s,
+ adjust_t *adj);
+ int (*init) (struct pcmcia_socket *s);
+ void (*exit) (struct pcmcia_socket *s);
+};
+/* SS_CAP_STATIC_MAP */
+extern struct pccard_resource_ops pccard_static_ops;
+/* !SS_CAP_STATIC_MAP */
+extern struct pccard_resource_ops pccard_nonstatic_ops;
+
/*
* Calls to set up low-level "Socket Services" drivers
*/
@@ -159,6 +166,8 @@ typedef struct window_t {
struct config_t;
struct region_t;
+struct pcmcia_callback;
+
struct pcmcia_socket {
struct module *owner;
@@ -167,7 +176,6 @@ struct pcmcia_socket {
u_int state;
u_short functions;
u_short lock_count;
- client_handle_t clients;
pccard_mem_map cis_mem;
void __iomem *cis_virt;
struct config_t *config;
@@ -199,6 +207,8 @@ struct pcmcia_socket {
/* socket operations */
struct pccard_operations * ops;
+ struct pccard_resource_ops * resource_ops;
+ void * resource_data;
/* Zoom video behaviour is so chip specific its not worth adding
this to _ops */
@@ -215,6 +225,7 @@ struct pcmcia_socket {
/* pcmcia (16-bit) */
struct pcmcia_bus_socket *pcmcia;
+ struct pcmcia_callback *callback;
/* cardbus (32-bit) */
#ifdef CONFIG_CARDBUS
diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h
index 38fbb68c9b87..12e90934a7a8 100644
--- a/include/scsi/scsi_dbg.h
+++ b/include/scsi/scsi_dbg.h
@@ -8,6 +8,9 @@ extern void scsi_print_command(struct scsi_cmnd *);
extern void __scsi_print_command(unsigned char *);
extern void scsi_print_sense(const char *, struct scsi_cmnd *);
extern void scsi_print_req_sense(const char *, struct scsi_request *);
+extern void __scsi_print_sense(const char *name,
+ const unsigned char *sense_buffer,
+ int sense_len);
extern void scsi_print_driverbyte(int);
extern void scsi_print_hostbyte(int);
extern void scsi_print_status(unsigned char);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 6afc72fba7dc..8678132e3947 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -172,6 +172,8 @@ extern struct scsi_device *scsi_device_lookup(struct Scsi_Host *,
uint, uint, uint);
extern struct scsi_device *__scsi_device_lookup(struct Scsi_Host *,
uint, uint, uint);
+extern void starget_for_each_device(struct scsi_target *, void *,
+ void (*fn)(struct scsi_device *, void *));
/* only exposed to implement shost_for_each_device */
extern struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *,
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 3b7128327791..1d4adfd6d3e9 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -185,6 +185,8 @@ struct fc_host_statistics {
#define FC_FC4_LIST_SIZE 32
#define FC_SYMBOLIC_NAME_SIZE 256
+#define FC_VERSION_STRING_SIZE 64
+#define FC_SERIAL_NUMBER_SIZE 80
struct fc_host_attrs {
/* Fixed Attributes */
@@ -195,6 +197,11 @@ struct fc_host_attrs {
char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
u32 supported_speeds;
u32 maxframe_size;
+ char hardware_version[FC_VERSION_STRING_SIZE];
+ char firmware_version[FC_VERSION_STRING_SIZE];
+ char serial_number[FC_SERIAL_NUMBER_SIZE];
+ char opt_rom_version[FC_VERSION_STRING_SIZE];
+ char driver_version[FC_VERSION_STRING_SIZE];
/* Dynamic Attributes */
u32 port_id;
@@ -226,6 +233,16 @@ struct fc_host_attrs {
(((struct fc_host_attrs *)(x)->shost_data)->supported_speeds)
#define fc_host_maxframe_size(x) \
(((struct fc_host_attrs *)(x)->shost_data)->maxframe_size)
+#define fc_host_hardware_version(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->hardware_version)
+#define fc_host_firmware_version(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->firmware_version)
+#define fc_host_serial_number(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->serial_number)
+#define fc_host_opt_rom_version(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->opt_rom_version)
+#define fc_host_driver_version(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->driver_version)
#define fc_host_port_id(x) \
(((struct fc_host_attrs *)(x)->shost_data)->port_id)
#define fc_host_port_type(x) \
@@ -285,6 +302,11 @@ struct fc_function_template {
unsigned long show_host_symbolic_name:1;
unsigned long show_host_supported_speeds:1;
unsigned long show_host_maxframe_size:1;
+ unsigned long show_host_hardware_version:1;
+ unsigned long show_host_firmware_version:1;
+ unsigned long show_host_serial_number:1;
+ unsigned long show_host_opt_rom_version:1;
+ unsigned long show_host_driver_version:1;
/* host dynamic attributes */
unsigned long show_host_port_id:1;
unsigned long show_host_port_type:1;
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index f2eabca88f30..d421d964cf63 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -426,6 +426,7 @@ struct snd_ac97_build_ops {
int (*build_spdif) (ac97_t *ac97);
int (*build_post_spdif) (ac97_t *ac97);
#ifdef CONFIG_PM
+ void (*suspend) (ac97_t *ac97);
void (*resume) (ac97_t *ac97);
#endif
};
diff --git a/include/sound/version.h b/include/sound/version.h
index 37d587f79e6b..a4db7e75de4d 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h. Generated by configure. */
-#define CONFIG_SND_VERSION "1.0.8rc2"
-#define CONFIG_SND_DATE " (Wed Jan 05 06:44:40 2005 UTC)"
+#define CONFIG_SND_VERSION "1.0.8"
+#define CONFIG_SND_DATE " (Thu Jan 13 09:39:32 2005 UTC)"
diff --git a/kernel/acct.c b/kernel/acct.c
index 311ec9c0be53..32e39accbb86 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -541,6 +541,8 @@ void acct_update_integrals(void)
if (likely(tsk->mm)) {
long delta = tsk->stime - tsk->acct_stimexpd;
+ if (delta == 0)
+ return;
tsk->acct_stimexpd = tsk->stime;
tsk->acct_rss_mem1 += delta * tsk->mm->rss;
tsk->acct_vm_mem1 += delta * tsk->mm->total_vm;
diff --git a/kernel/audit.c b/kernel/audit.c
index 8ec8a88ad35c..e21f947bacf2 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -419,7 +419,7 @@ static int audit_receive_skb(struct sk_buff *skb)
if (rlen > skb->len)
rlen = skb->len;
if ((err = audit_receive_msg(skb, nlh))) {
- netlink_ack(skb, nlh, -err);
+ netlink_ack(skb, nlh, err);
} else if (nlh->nlmsg_flags & NLM_F_ACK)
netlink_ack(skb, nlh, 0);
skb_pull(skb, rlen);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 0962944e8357..aa617bbe49b0 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -591,7 +591,7 @@ static void audit_log_exit(struct audit_context *context)
if (context->personality != PER_LINUX)
audit_log_format(ab, " per=%lx", context->personality);
if (context->return_valid)
- audit_log_format(ab, " exit=%u", context->return_code);
+ audit_log_format(ab, " exit=%d", context->return_code);
audit_log_format(ab,
" a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
" pid=%d loginuid=%d uid=%d gid=%d"
diff --git a/kernel/compat.c b/kernel/compat.c
index 48ee147c1343..d1b1d4dd019a 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -163,15 +163,15 @@ asmlinkage long compat_sys_times(struct compat_tms __user *tbuf)
struct compat_tms tmp;
struct task_struct *tsk = current;
struct task_struct *t;
- unsigned long utime, stime, cutime, cstime;
+ cputime_t utime, stime, cutime, cstime;
read_lock(&tasklist_lock);
utime = tsk->signal->utime;
stime = tsk->signal->stime;
t = tsk;
do {
- utime += t->utime;
- stime += t->stime;
+ utime = cputime_add(utime, t->utime);
+ stime = cputime_add(stime, t->stime);
t = next_thread(t);
} while (t != tsk);
@@ -190,10 +190,10 @@ asmlinkage long compat_sys_times(struct compat_tms __user *tbuf)
spin_unlock_irq(&tsk->sighand->siglock);
read_unlock(&tasklist_lock);
- tmp.tms_utime = compat_jiffies_to_clock_t(utime);
- tmp.tms_stime = compat_jiffies_to_clock_t(stime);
- tmp.tms_cutime = compat_jiffies_to_clock_t(cutime);
- tmp.tms_cstime = compat_jiffies_to_clock_t(cstime);
+ tmp.tms_utime = compat_jiffies_to_clock_t(cputime_to_jiffies(utime));
+ tmp.tms_stime = compat_jiffies_to_clock_t(cputime_to_jiffies(stime));
+ tmp.tms_cutime = compat_jiffies_to_clock_t(cputime_to_jiffies(cutime));
+ tmp.tms_cstime = compat_jiffies_to_clock_t(cputime_to_jiffies(cstime));
if (copy_to_user(tbuf, &tmp, sizeof(tmp)))
return -EFAULT;
}
diff --git a/kernel/cpu.c b/kernel/cpu.c
index b97f7f91ec6d..628f4ccda127 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -48,7 +48,9 @@ static inline void check_for_tasks(int cpu)
write_lock_irq(&tasklist_lock);
for_each_process(p) {
- if (task_cpu(p) == cpu && (p->utime != 0 || p->stime != 0))
+ if (task_cpu(p) == cpu &&
+ (!cputime_eq(p->utime, cputime_zero) ||
+ !cputime_eq(p->stime, cputime_zero)))
printk(KERN_WARNING "Task %s (pid = %d) is on cpu %d\
(state = %ld, flags = %lx) \n",
p->comm, p->pid, cpu, p->state, p->flags);
diff --git a/kernel/exit.c b/kernel/exit.c
index 54a59c727356..e0df301a4553 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -557,7 +557,7 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced)
* a normal stop since it's no longer being
* traced.
*/
- p->state = TASK_STOPPED;
+ ptrace_untrace(p);
}
}
@@ -755,8 +755,8 @@ static void exit_notify(struct task_struct *tsk)
* Clear these here so that update_process_times() won't try to deliver
* itimer, profile or rlimit signals to this task while it is in late exit.
*/
- tsk->it_virt_value = 0;
- tsk->it_prof_value = 0;
+ tsk->it_virt_value = cputime_zero;
+ tsk->it_prof_value = cputime_zero;
write_unlock_irq(&tasklist_lock);
@@ -790,6 +790,12 @@ fastcall NORET_TYPE void do_exit(long code)
panic("Attempted to kill init!");
if (tsk->io_context)
exit_io_context();
+
+ if (unlikely(current->ptrace & PT_TRACE_EXIT)) {
+ current->ptrace_message = code;
+ ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
+ }
+
tsk->flags |= PF_EXITING;
del_timer_sync(&tsk->real_timer);
@@ -798,11 +804,6 @@ fastcall NORET_TYPE void do_exit(long code)
current->comm, current->pid,
preempt_count());
- if (unlikely(current->ptrace & PT_TRACE_EXIT)) {
- current->ptrace_message = code;
- ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
- }
-
acct_update_integrals();
update_mem_hiwater();
group_dead = atomic_dec_and_test(&tsk->signal->live);
@@ -1045,10 +1046,16 @@ static int wait_task_zombie(task_t *p, int noreap,
* here reaping other children at the same time.
*/
spin_lock_irq(&p->parent->sighand->siglock);
- p->parent->signal->cutime +=
- p->utime + p->signal->utime + p->signal->cutime;
- p->parent->signal->cstime +=
- p->stime + p->signal->stime + p->signal->cstime;
+ p->parent->signal->cutime =
+ cputime_add(p->parent->signal->cutime,
+ cputime_add(p->utime,
+ cputime_add(p->signal->utime,
+ p->signal->cutime)));
+ p->parent->signal->cstime =
+ cputime_add(p->parent->signal->cstime,
+ cputime_add(p->stime,
+ cputime_add(p->signal->stime,
+ p->signal->cstime)));
p->parent->signal->cmin_flt +=
p->min_flt + p->signal->min_flt + p->signal->cmin_flt;
p->parent->signal->cmaj_flt +=
diff --git a/kernel/fork.c b/kernel/fork.c
index 6d9412937d37..be1ff8ddbb9c 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -749,7 +749,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
sig->leader = 0; /* session leadership doesn't inherit */
sig->tty_old_pgrp = 0;
- sig->utime = sig->stime = sig->cutime = sig->cstime = 0;
+ sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero;
sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
@@ -871,15 +871,15 @@ static task_t *copy_process(unsigned long clone_flags,
p->it_real_value = 0;
p->it_real_incr = 0;
- p->it_virt_value = 0;
- p->it_virt_incr = 0;
- p->it_prof_value = 0;
- p->it_prof_incr = 0;
+ p->it_virt_value = cputime_zero;
+ p->it_virt_incr = cputime_zero;
+ p->it_prof_value = cputime_zero;
+ p->it_prof_incr = cputime_zero;
init_timer(&p->real_timer);
p->real_timer.data = (unsigned long) p;
- p->utime = 0;
- p->stime = 0;
+ p->utime = cputime_zero;
+ p->stime = cputime_zero;
p->rchar = 0; /* I/O counter: bytes read */
p->wchar = 0; /* I/O counter: bytes written */
p->syscr = 0; /* I/O counter: read syscalls */
diff --git a/kernel/itimer.c b/kernel/itimer.c
index 95fbf1c6becf..e1743c563206 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -16,11 +16,10 @@
int do_getitimer(int which, struct itimerval *value)
{
- register unsigned long val, interval;
+ register unsigned long val;
switch (which) {
case ITIMER_REAL:
- interval = current->it_real_incr;
val = 0;
/*
* FIXME! This needs to be atomic, in case the kernel timer happens!
@@ -32,20 +31,20 @@ int do_getitimer(int which, struct itimerval *value)
if ((long) val <= 0)
val = 1;
}
+ jiffies_to_timeval(val, &value->it_value);
+ jiffies_to_timeval(current->it_real_incr, &value->it_interval);
break;
case ITIMER_VIRTUAL:
- val = current->it_virt_value;
- interval = current->it_virt_incr;
+ cputime_to_timeval(current->it_virt_value, &value->it_value);
+ cputime_to_timeval(current->it_virt_incr, &value->it_interval);
break;
case ITIMER_PROF:
- val = current->it_prof_value;
- interval = current->it_prof_incr;
+ cputime_to_timeval(current->it_prof_value, &value->it_value);
+ cputime_to_timeval(current->it_prof_incr, &value->it_interval);
break;
default:
return(-EINVAL);
}
- jiffies_to_timeval(val, &value->it_value);
- jiffies_to_timeval(interval, &value->it_interval);
return 0;
}
@@ -81,37 +80,43 @@ void it_real_fn(unsigned long __data)
int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
{
- register unsigned long i, j;
+ unsigned long expire;
+ cputime_t cputime;
int k;
- i = timeval_to_jiffies(&value->it_interval);
- j = timeval_to_jiffies(&value->it_value);
if (ovalue && (k = do_getitimer(which, ovalue)) < 0)
return k;
switch (which) {
case ITIMER_REAL:
del_timer_sync(&current->real_timer);
- current->it_real_value = j;
- current->it_real_incr = i;
- if (!j)
+ expire = timeval_to_jiffies(&value->it_value);
+ current->it_real_value = expire;
+ current->it_real_incr =
+ timeval_to_jiffies(&value->it_interval);
+ if (!expire)
break;
- if (j > (unsigned long) LONG_MAX)
- j = LONG_MAX;
- i = j + jiffies;
- current->real_timer.expires = i;
+ if (expire > (unsigned long) LONG_MAX)
+ expire = LONG_MAX;
+ current->real_timer.expires = jiffies + expire;
add_timer(&current->real_timer);
break;
case ITIMER_VIRTUAL:
- if (j)
- j++;
- current->it_virt_value = j;
- current->it_virt_incr = i;
+ cputime = timeval_to_cputime(&value->it_value);
+ if (cputime_gt(cputime, cputime_zero))
+ cputime = cputime_add(cputime,
+ jiffies_to_cputime(1));
+ current->it_virt_value = cputime;
+ cputime = timeval_to_cputime(&value->it_interval);
+ current->it_virt_incr = cputime;
break;
case ITIMER_PROF:
- if (j)
- j++;
- current->it_prof_value = j;
- current->it_prof_incr = i;
+ cputime = timeval_to_cputime(&value->it_value);
+ if (cputime_gt(cputime, cputime_zero))
+ cputime = cputime_add(cputime,
+ jiffies_to_cputime(1));
+ current->it_prof_value = cputime;
+ cputime = timeval_to_cputime(&value->it_interval);
+ current->it_prof_incr = cputime;
break;
default:
return -EINVAL;
diff --git a/kernel/module.c b/kernel/module.c
index f44ebfd656c6..ce427b675b98 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1691,6 +1691,9 @@ static struct module *load_module(void __user *umod,
/ sizeof(struct kernel_param),
NULL);
}
+ if (err < 0)
+ goto arch_cleanup;
+
err = mod_sysfs_setup(mod,
(struct kernel_param *)
sechdrs[setupindex].sh_addr,
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index dfac617c4f39..8ec3dadb0b27 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -843,11 +843,22 @@ int swsusp_suspend(void)
if ((error = arch_prepare_suspend()))
return error;
local_irq_disable();
+ /* At this point, device_suspend() has been called, but *not*
+ * device_power_down(). We *must* device_power_down() now.
+ * Otherwise, drivers for some devices (e.g. interrupt controllers)
+ * become desynchronized with the actual state of the hardware
+ * at resume time, and evil weirdness ensues.
+ */
+ if ((error = device_power_down(PM_SUSPEND_DISK))) {
+ local_irq_enable();
+ return error;
+ }
save_processor_state();
error = swsusp_arch_suspend();
/* Restore control flow magically appears here */
restore_processor_state();
restore_highmem();
+ device_power_up();
local_irq_enable();
return error;
}
@@ -867,6 +878,7 @@ int swsusp_resume(void)
{
int error;
local_irq_disable();
+ device_power_down(PM_SUSPEND_DISK);
/* We'll ignore saved state, but this gets preempt count (etc) right */
save_processor_state();
error = swsusp_arch_resume();
@@ -876,6 +888,7 @@ int swsusp_resume(void)
BUG_ON(!error);
restore_processor_state();
restore_highmem();
+ device_power_up();
local_irq_enable();
return error;
}
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 60801c692810..ccd79253e13f 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -38,10 +38,24 @@ void __ptrace_link(task_t *child, task_t *new_parent)
SET_LINKS(child);
}
-static inline int pending_resume_signal(struct sigpending *pending)
+/*
+ * Turn a tracing stop into a normal stop now, since with no tracer there
+ * would be no way to wake it up with SIGCONT or SIGKILL. If there was a
+ * signal sent that would resume the child, but didn't because it was in
+ * TASK_TRACED, resume it now.
+ * Requires that irqs be disabled.
+ */
+void ptrace_untrace(task_t *child)
{
-#define M(sig) (1UL << ((sig)-1))
- return sigtestsetmask(&pending->signal, M(SIGCONT) | M(SIGKILL));
+ spin_lock(&child->sighand->siglock);
+ if (child->state == TASK_TRACED) {
+ if (child->signal->flags & SIGNAL_STOP_STOPPED) {
+ child->state = TASK_STOPPED;
+ } else {
+ signal_wake_up(child, 1);
+ }
+ }
+ spin_unlock(&child->sighand->siglock);
}
/*
@@ -55,29 +69,15 @@ void __ptrace_unlink(task_t *child)
if (!child->ptrace)
BUG();
child->ptrace = 0;
- if (list_empty(&child->ptrace_list))
- return;
- list_del_init(&child->ptrace_list);
- REMOVE_LINKS(child);
- child->parent = child->real_parent;
- SET_LINKS(child);
-
- if (child->state == TASK_TRACED) {
- /*
- * Turn a tracing stop into a normal stop now,
- * since with no tracer there would be no way
- * to wake it up with SIGCONT or SIGKILL.
- * If there was a signal sent that would resume the child,
- * but didn't because it was in TASK_TRACED, resume it now.
- */
- spin_lock(&child->sighand->siglock);
- child->state = TASK_STOPPED;
- if (pending_resume_signal(&child->pending) ||
- pending_resume_signal(&child->signal->shared_pending)) {
- signal_wake_up(child, 1);
- }
- spin_unlock(&child->sighand->siglock);
+ if (!list_empty(&child->ptrace_list)) {
+ list_del_init(&child->ptrace_list);
+ REMOVE_LINKS(child);
+ child->parent = child->real_parent;
+ SET_LINKS(child);
}
+
+ if (child->state == TASK_TRACED)
+ ptrace_untrace(child);
}
/*
diff --git a/kernel/sched.c b/kernel/sched.c
index 1c523337bc61..9e1fbc42bd01 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1182,7 +1182,7 @@ void fastcall sched_fork(task_t *p)
*/
current->time_slice = 1;
preempt_disable();
- scheduler_tick(0, 0);
+ scheduler_tick();
local_irq_enable();
preempt_enable();
} else
@@ -2251,48 +2251,168 @@ EXPORT_PER_CPU_SYMBOL(kstat);
((rq)->curr->static_prio > (rq)->best_expired_prio))
/*
+ * Do the virtual cpu time signal calculations.
+ * @p: the process that the cpu time gets accounted to
+ * @cputime: the cpu time spent in user space since the last update
+ */
+static inline void account_it_virt(struct task_struct * p, cputime_t cputime)
+{
+ cputime_t it_virt = p->it_virt_value;
+
+ if (cputime_gt(it_virt, cputime_zero) &&
+ cputime_gt(cputime, cputime_zero)) {
+ if (cputime_ge(cputime, it_virt)) {
+ it_virt = cputime_add(it_virt, p->it_virt_incr);
+ send_sig(SIGVTALRM, p, 1);
+ }
+ it_virt = cputime_sub(it_virt, cputime);
+ p->it_virt_value = it_virt;
+ }
+}
+
+/*
+ * Do the virtual profiling signal calculations.
+ * @p: the process that the cpu time gets accounted to
+ * @cputime: the cpu time spent in user and kernel space since the last update
+ */
+static void account_it_prof(struct task_struct *p, cputime_t cputime)
+{
+ cputime_t it_prof = p->it_prof_value;
+
+ if (cputime_gt(it_prof, cputime_zero) &&
+ cputime_gt(cputime, cputime_zero)) {
+ if (cputime_ge(cputime, it_prof)) {
+ it_prof = cputime_add(it_prof, p->it_prof_incr);
+ send_sig(SIGPROF, p, 1);
+ }
+ it_prof = cputime_sub(it_prof, cputime);
+ p->it_prof_value = it_prof;
+ }
+}
+
+/*
+ * Check if the process went over its cputime resource limit after
+ * some cpu time got added to utime/stime.
+ * @p: the process that the cpu time gets accounted to
+ * @cputime: the cpu time spent in user and kernel space since the last update
+ */
+static void check_rlimit(struct task_struct *p, cputime_t cputime)
+{
+ cputime_t total, tmp;
+
+ total = cputime_add(p->utime, p->stime);
+ tmp = jiffies_to_cputime(p->signal->rlim[RLIMIT_CPU].rlim_cur);
+ if (unlikely(cputime_gt(total, tmp))) {
+ /* Send SIGXCPU every second. */
+ tmp = cputime_sub(total, cputime);
+ if (cputime_to_secs(tmp) < cputime_to_secs(total))
+ send_sig(SIGXCPU, p, 1);
+ /* and SIGKILL when we go over max.. */
+ tmp = jiffies_to_cputime(p->signal->rlim[RLIMIT_CPU].rlim_max);
+ if (cputime_gt(total, tmp))
+ send_sig(SIGKILL, p, 1);
+ }
+}
+
+/*
+ * Account user cpu time to a process.
+ * @p: the process that the cpu time gets accounted to
+ * @hardirq_offset: the offset to subtract from hardirq_count()
+ * @cputime: the cpu time spent in user space since the last update
+ */
+void account_user_time(struct task_struct *p, cputime_t cputime)
+{
+ struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
+ cputime64_t tmp;
+
+ p->utime = cputime_add(p->utime, cputime);
+
+ /* Check for signals (SIGVTALRM, SIGPROF, SIGXCPU & SIGKILL). */
+ check_rlimit(p, cputime);
+ account_it_virt(p, cputime);
+ account_it_prof(p, cputime);
+
+ /* Add user time to cpustat. */
+ tmp = cputime_to_cputime64(cputime);
+ if (TASK_NICE(p) > 0)
+ cpustat->nice = cputime64_add(cpustat->nice, tmp);
+ else
+ cpustat->user = cputime64_add(cpustat->user, tmp);
+}
+
+/*
+ * Account system cpu time to a process.
+ * @p: the process that the cpu time gets accounted to
+ * @hardirq_offset: the offset to subtract from hardirq_count()
+ * @cputime: the cpu time spent in kernel space since the last update
+ */
+void account_system_time(struct task_struct *p, int hardirq_offset,
+ cputime_t cputime)
+{
+ struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
+ runqueue_t *rq = this_rq();
+ cputime64_t tmp;
+
+ p->stime = cputime_add(p->stime, cputime);
+
+ /* Check for signals (SIGPROF, SIGXCPU & SIGKILL). */
+ if (likely(p->signal && p->exit_state < EXIT_ZOMBIE)) {
+ check_rlimit(p, cputime);
+ account_it_prof(p, cputime);
+ }
+
+ /* Add system time to cpustat. */
+ tmp = cputime_to_cputime64(cputime);
+ if (hardirq_count() - hardirq_offset)
+ cpustat->irq = cputime64_add(cpustat->irq, tmp);
+ else if (softirq_count())
+ cpustat->softirq = cputime64_add(cpustat->softirq, tmp);
+ else if (p != rq->idle)
+ cpustat->system = cputime64_add(cpustat->system, tmp);
+ else if (atomic_read(&rq->nr_iowait) > 0)
+ cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
+ else
+ cpustat->idle = cputime64_add(cpustat->idle, tmp);
+}
+
+/*
+ * Account for involuntary wait time.
+ * @p: the process from which the cpu time has been stolen
+ * @steal: the cpu time spent in involuntary wait
+ */
+void account_steal_time(struct task_struct *p, cputime_t steal)
+{
+ struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
+ cputime64_t steal64 = cputime_to_cputime64(steal);
+ runqueue_t *rq = this_rq();
+
+ if (p == rq->idle)
+ cpustat->system = cputime64_add(cpustat->system, steal64);
+ else
+ cpustat->steal = cputime64_add(cpustat->steal, steal64);
+}
+
+/*
* This function gets called by the timer code, with HZ frequency.
* We call it with interrupts disabled.
*
* It also gets called by the fork code, when changing the parent's
* timeslices.
*/
-void scheduler_tick(int user_ticks, int sys_ticks)
+void scheduler_tick(void)
{
int cpu = smp_processor_id();
- struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
runqueue_t *rq = this_rq();
task_t *p = current;
rq->timestamp_last_tick = sched_clock();
- if (rcu_pending(cpu))
- rcu_check_callbacks(cpu, user_ticks);
-
- /* note: this timer irq context must be accounted for as well */
- if (hardirq_count() - HARDIRQ_OFFSET) {
- cpustat->irq += sys_ticks;
- sys_ticks = 0;
- } else if (softirq_count()) {
- cpustat->softirq += sys_ticks;
- sys_ticks = 0;
- }
-
if (p == rq->idle) {
- if (atomic_read(&rq->nr_iowait) > 0)
- cpustat->iowait += sys_ticks;
- else
- cpustat->idle += sys_ticks;
if (wake_priority_sleeper(rq))
goto out;
rebalance_tick(cpu, rq, SCHED_IDLE);
return;
}
- if (TASK_NICE(p) > 0)
- cpustat->nice += user_ticks;
- else
- cpustat->user += user_ticks;
- cpustat->system += sys_ticks;
/* Task might have expired already, but not scheduled off yet */
if (p->array != rq->active) {
diff --git a/kernel/signal.c b/kernel/signal.c
index 85ad9a0ae3f1..6d0a3bd948ab 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -375,8 +375,8 @@ void __exit_signal(struct task_struct *tsk)
* We won't ever get here for the group leader, since it
* will have been the last reference on the signal_struct.
*/
- sig->utime += tsk->utime;
- sig->stime += tsk->stime;
+ sig->utime = cputime_add(sig->utime, tsk->utime);
+ sig->stime = cputime_add(sig->stime, tsk->stime);
sig->min_flt += tsk->min_flt;
sig->maj_flt += tsk->maj_flt;
sig->nvcsw += tsk->nvcsw;
@@ -587,15 +587,15 @@ void signal_wake_up(struct task_struct *t, int resume)
set_tsk_thread_flag(t, TIF_SIGPENDING);
/*
- * If resume is set, we want to wake it up in the TASK_STOPPED case.
- * We don't check for TASK_STOPPED because there is a race with it
+ * For SIGKILL, we want to wake it up in the stopped/traced case.
+ * We don't check t->state here because there is a race with it
* executing another processor and just now entering stopped state.
- * By calling wake_up_process any time resume is set, we ensure
- * the process will wake up and handle its stop or death signal.
+ * By using wake_up_state, we ensure the process will wake up and
+ * handle its death signal.
*/
mask = TASK_INTERRUPTIBLE;
if (resume)
- mask |= TASK_STOPPED;
+ mask |= TASK_STOPPED | TASK_TRACED;
if (!wake_up_state(t, mask))
kick_process(t);
}
@@ -935,11 +935,11 @@ __group_complete_signal(int sig, struct task_struct *p)
/*
* Don't bother traced and stopped tasks (but
- * SIGKILL will punch through stopped state)
+ * SIGKILL will punch through that).
*/
- mask = TASK_TRACED;
- if (sig != SIGKILL)
- mask |= TASK_STOPPED;
+ mask = TASK_STOPPED | TASK_TRACED;
+ if (sig == SIGKILL)
+ mask = 0;
/*
* Now find a thread we can wake up to take the signal off the queue.
@@ -1456,8 +1456,7 @@ void do_notify_parent(struct task_struct *tsk, int sig)
unsigned long flags;
struct sighand_struct *psig;
- if (sig == -1)
- BUG();
+ BUG_ON(sig == -1);
/* do_notify_parent_cldstop should have been called instead. */
BUG_ON(tsk->state & (TASK_STOPPED|TASK_TRACED));
@@ -1471,8 +1470,10 @@ void do_notify_parent(struct task_struct *tsk, int sig)
info.si_uid = tsk->uid;
/* FIXME: find out whether or not this is supposed to be c*time. */
- info.si_utime = tsk->utime + tsk->signal->utime;
- info.si_stime = tsk->stime + tsk->signal->stime;
+ info.si_utime = cputime_to_jiffies(cputime_add(tsk->utime,
+ tsk->signal->utime));
+ info.si_stime = cputime_to_jiffies(cputime_add(tsk->stime,
+ tsk->signal->stime));
info.si_status = tsk->exit_code & 0x7f;
if (tsk->exit_code & 0x80)
@@ -1528,8 +1529,8 @@ do_notify_parent_cldstop(struct task_struct *tsk, struct task_struct *parent,
info.si_uid = tsk->uid;
/* FIXME: find out whether or not this is supposed to be c*time. */
- info.si_utime = tsk->utime;
- info.si_stime = tsk->stime;
+ info.si_utime = cputime_to_jiffies(tsk->utime);
+ info.si_stime = cputime_to_jiffies(tsk->stime);
info.si_code = why;
switch (why) {
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 9e2d204da364..582a1e8091bc 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -163,6 +163,7 @@ EXPORT_SYMBOL(local_bh_enable);
*/
void irq_exit(void)
{
+ account_system_vtime(current);
sub_preempt_count(IRQ_EXIT_OFFSET);
if (!in_interrupt() && local_softirq_pending())
invoke_softirq();
diff --git a/kernel/sys.c b/kernel/sys.c
index 20080da0c3de..6e354fd380e7 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -893,15 +893,15 @@ asmlinkage long sys_times(struct tms __user * tbuf)
struct tms tmp;
struct task_struct *tsk = current;
struct task_struct *t;
- unsigned long utime, stime, cutime, cstime;
+ cputime_t utime, stime, cutime, cstime;
read_lock(&tasklist_lock);
utime = tsk->signal->utime;
stime = tsk->signal->stime;
t = tsk;
do {
- utime += t->utime;
- stime += t->stime;
+ utime = cputime_add(utime, t->utime);
+ stime = cputime_add(stime, t->stime);
t = next_thread(t);
} while (t != tsk);
@@ -920,10 +920,10 @@ asmlinkage long sys_times(struct tms __user * tbuf)
spin_unlock_irq(&tsk->sighand->siglock);
read_unlock(&tasklist_lock);
- tmp.tms_utime = jiffies_to_clock_t(utime);
- tmp.tms_stime = jiffies_to_clock_t(stime);
- tmp.tms_cutime = jiffies_to_clock_t(cutime);
- tmp.tms_cstime = jiffies_to_clock_t(cstime);
+ tmp.tms_utime = cputime_to_clock_t(utime);
+ tmp.tms_stime = cputime_to_clock_t(stime);
+ tmp.tms_cutime = cputime_to_clock_t(cutime);
+ tmp.tms_cstime = cputime_to_clock_t(cstime);
if (copy_to_user(tbuf, &tmp, sizeof(struct tms)))
return -EFAULT;
}
@@ -1528,7 +1528,7 @@ void k_getrusage(struct task_struct *p, int who, struct rusage *r)
{
struct task_struct *t;
unsigned long flags;
- unsigned long utime, stime;
+ cputime_t utime, stime;
memset((char *) r, 0, sizeof *r);
@@ -1545,12 +1545,12 @@ void k_getrusage(struct task_struct *p, int who, struct rusage *r)
r->ru_minflt = p->signal->cmin_flt;
r->ru_majflt = p->signal->cmaj_flt;
spin_unlock_irqrestore(&p->sighand->siglock, flags);
- jiffies_to_timeval(utime, &r->ru_utime);
- jiffies_to_timeval(stime, &r->ru_stime);
+ cputime_to_timeval(utime, &r->ru_utime);
+ cputime_to_timeval(stime, &r->ru_stime);
break;
case RUSAGE_SELF:
spin_lock_irqsave(&p->sighand->siglock, flags);
- utime = stime = 0;
+ utime = stime = cputime_zero;
goto sum_group;
case RUSAGE_BOTH:
spin_lock_irqsave(&p->sighand->siglock, flags);
@@ -1561,16 +1561,16 @@ void k_getrusage(struct task_struct *p, int who, struct rusage *r)
r->ru_minflt = p->signal->cmin_flt;
r->ru_majflt = p->signal->cmaj_flt;
sum_group:
- utime += p->signal->utime;
- stime += p->signal->stime;
+ utime = cputime_add(utime, p->signal->utime);
+ stime = cputime_add(stime, p->signal->stime);
r->ru_nvcsw += p->signal->nvcsw;
r->ru_nivcsw += p->signal->nivcsw;
r->ru_minflt += p->signal->min_flt;
r->ru_majflt += p->signal->maj_flt;
t = p;
do {
- utime += t->utime;
- stime += t->stime;
+ utime = cputime_add(utime, t->utime);
+ stime = cputime_add(stime, t->stime);
r->ru_nvcsw += t->nvcsw;
r->ru_nivcsw += t->nivcsw;
r->ru_minflt += t->min_flt;
@@ -1578,8 +1578,8 @@ void k_getrusage(struct task_struct *p, int who, struct rusage *r)
t = next_thread(t);
} while (t != p);
spin_unlock_irqrestore(&p->sighand->siglock, flags);
- jiffies_to_timeval(utime, &r->ru_utime);
- jiffies_to_timeval(stime, &r->ru_stime);
+ cputime_to_timeval(utime, &r->ru_utime);
+ cputime_to_timeval(stime, &r->ru_stime);
break;
default:
BUG();
diff --git a/kernel/timer.c b/kernel/timer.c
index ec35a6e801a8..6bb47b0e4983 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -806,59 +806,6 @@ static void update_wall_time(unsigned long ticks)
} while (ticks);
}
-static inline void do_process_times(struct task_struct *p,
- unsigned long user, unsigned long system)
-{
- unsigned long psecs;
-
- psecs = (p->utime += user);
- psecs += (p->stime += system);
- if (p->signal && !unlikely(p->exit_state) &&
- psecs / HZ >= p->signal->rlim[RLIMIT_CPU].rlim_cur) {
- /* Send SIGXCPU every second.. */
- if (!(psecs % HZ))
- send_sig(SIGXCPU, p, 1);
- /* and SIGKILL when we go over max.. */
- if (psecs / HZ >= p->signal->rlim[RLIMIT_CPU].rlim_max)
- send_sig(SIGKILL, p, 1);
- }
-}
-
-static inline void do_it_virt(struct task_struct * p, unsigned long ticks)
-{
- unsigned long it_virt = p->it_virt_value;
-
- if (it_virt) {
- it_virt -= ticks;
- if (!it_virt) {
- it_virt = p->it_virt_incr;
- send_sig(SIGVTALRM, p, 1);
- }
- p->it_virt_value = it_virt;
- }
-}
-
-static inline void do_it_prof(struct task_struct *p)
-{
- unsigned long it_prof = p->it_prof_value;
-
- if (it_prof) {
- if (--it_prof == 0) {
- it_prof = p->it_prof_incr;
- send_sig(SIGPROF, p, 1);
- }
- p->it_prof_value = it_prof;
- }
-}
-
-static void update_one_process(struct task_struct *p, unsigned long user,
- unsigned long system, int cpu)
-{
- do_process_times(p, user, system);
- do_it_virt(p, user);
- do_it_prof(p);
-}
-
/*
* Called from the timer interrupt handler to charge one tick to the current
* process. user_tick is 1 if the tick is user time, 0 for system.
@@ -866,11 +813,17 @@ static void update_one_process(struct task_struct *p, unsigned long user,
void update_process_times(int user_tick)
{
struct task_struct *p = current;
- int cpu = smp_processor_id(), system = user_tick ^ 1;
+ int cpu = smp_processor_id();
- update_one_process(p, user_tick, system, cpu);
+ /* Note: this timer irq context must be accounted for as well. */
+ if (user_tick)
+ account_user_time(p, jiffies_to_cputime(1));
+ else
+ account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1));
run_local_timers();
- scheduler_tick(user_tick, system);
+ if (rcu_pending(cpu))
+ rcu_check_callbacks(cpu, user_tick);
+ scheduler_tick();
}
/*
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index aba7f11a25ac..d2e2d705585e 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -50,7 +50,7 @@ config DEBUG_SLAB
config DEBUG_PREEMPT
bool "Debug preemptible kernel"
- depends on PREEMPT && X86
+ depends on PREEMPT && (X86 || PPC64)
default y
help
If you say Y here then the kernel will use a debug variant of the
diff --git a/mm/memory.c b/mm/memory.c
index 31451af257dd..b1494dcfd063 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -190,10 +190,10 @@ static inline void clear_pgd_range(struct mmu_gather *tlb, pgd_t *pgd, unsigned
void clear_page_range(struct mmu_gather *tlb, unsigned long start, unsigned long end)
{
unsigned long addr = start, next;
- unsigned long i, nr = pgd_index(end + PGDIR_SIZE-1) - pgd_index(start);
pgd_t * pgd = pgd_offset(tlb->mm, start);
+ unsigned long i;
- for (i = 0; i < nr; i++) {
+ for (i = pgd_index(start); i <= pgd_index(end-1); i++) {
next = (addr + PGDIR_SIZE) & PGDIR_MASK;
if (next > end || next <= addr)
next = end;
diff --git a/mm/mmap.c b/mm/mmap.c
index 3b45058686b5..21329bf3dea3 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -61,10 +61,98 @@ int sysctl_overcommit_ratio = 50; /* default is 50% */
int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
atomic_t vm_committed_space = ATOMIC_INIT(0);
+/*
+ * Check that a process has enough memory to allocate a new virtual
+ * mapping. 0 means there is enough memory for the allocation to
+ * succeed and -ENOMEM implies there is not.
+ *
+ * We currently support three overcommit policies, which are set via the
+ * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting
+ *
+ * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
+ * Additional code 2002 Jul 20 by Robert Love.
+ *
+ * cap_sys_admin is 1 if the process has admin privileges, 0 otherwise.
+ *
+ * Note this is a helper function intended to be used by LSMs which
+ * wish to use this logic.
+ */
+int __vm_enough_memory(long pages, int cap_sys_admin)
+{
+ unsigned long free, allowed;
+
+ vm_acct_memory(pages);
+
+ /*
+ * Sometimes we want to use more memory than we have
+ */
+ if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
+ return 0;
+
+ if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
+ unsigned long n;
+
+ free = get_page_cache_size();
+ free += nr_swap_pages;
+
+ /*
+ * Any slabs which are created with the
+ * SLAB_RECLAIM_ACCOUNT flag claim to have contents
+ * which are reclaimable, under pressure. The dentry
+ * cache and most inode caches should fall into this
+ */
+ free += atomic_read(&slab_reclaim_pages);
+
+ /*
+ * Leave the last 3% for root
+ */
+ if (!cap_sys_admin)
+ free -= free / 32;
+
+ if (free > pages)
+ return 0;
+
+ /*
+ * nr_free_pages() is very expensive on large systems,
+ * only call if we're about to fail.
+ */
+ n = nr_free_pages();
+ if (!cap_sys_admin)
+ n -= n / 32;
+ free += n;
+
+ if (free > pages)
+ return 0;
+ vm_unacct_memory(pages);
+ return -ENOMEM;
+ }
+
+ allowed = (totalram_pages - hugetlb_total_pages())
+ * sysctl_overcommit_ratio / 100;
+ /*
+ * Leave the last 3% for root
+ */
+ if (!cap_sys_admin)
+ allowed -= allowed / 32;
+ allowed += total_swap_pages;
+
+ /* Don't let a single process grow too big:
+ leave 3% of the size of this process for other processes */
+ allowed -= current->mm->total_vm / 32;
+
+ if (atomic_read(&vm_committed_space) < allowed)
+ return 0;
+
+ vm_unacct_memory(pages);
+
+ return -ENOMEM;
+}
+
EXPORT_SYMBOL(sysctl_overcommit_memory);
EXPORT_SYMBOL(sysctl_overcommit_ratio);
EXPORT_SYMBOL(sysctl_max_map_count);
EXPORT_SYMBOL(vm_committed_space);
+EXPORT_SYMBOL(__vm_enough_memory);
/*
* Requires inode->i_mapping->i_mmap_lock
@@ -1346,7 +1434,6 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un
struct rlimit *rlim = current->signal->rlim;
/* address space limit tests */
- rlim = current->signal->rlim;
if (mm->total_vm + grow > rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT)
return -ENOMEM;
@@ -1360,7 +1447,7 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un
unsigned long limit;
locked = mm->locked_vm + grow;
limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
- if (locked > limit)
+ if (locked > limit && !capable(CAP_IPC_LOCK))
return -ENOMEM;
}
@@ -1388,7 +1475,6 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un
int expand_stack(struct vm_area_struct * vma, unsigned long address)
{
int error;
- unsigned long size, grow;
if (!(vma->vm_flags & VM_GROWSUP))
return -EFAULT;
@@ -1408,12 +1494,19 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address)
*/
address += 4 + PAGE_SIZE - 1;
address &= PAGE_MASK;
- size = address - vma->vm_start;
- grow = (address - vma->vm_end) >> PAGE_SHIFT;
+ error = 0;
+
+ /* Somebody else might have raced and expanded it already */
+ if (address > vma->vm_end) {
+ unsigned long size, grow;
+
+ size = address - vma->vm_start;
+ grow = (address - vma->vm_end) >> PAGE_SHIFT;
- error = acct_stack_growth(vma, size, grow);
- if (!error)
- vma->vm_end = address;
+ error = acct_stack_growth(vma, size, grow);
+ if (!error)
+ vma->vm_end = address;
+ }
anon_vma_unlock(vma);
return error;
}
@@ -1441,7 +1534,6 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr)
int expand_stack(struct vm_area_struct *vma, unsigned long address)
{
int error;
- unsigned long size, grow;
/*
* We must make sure the anon_vma is allocated
@@ -1457,13 +1549,20 @@ int expand_stack(struct vm_area_struct *vma, unsigned long address)
* anon_vma lock to serialize against concurrent expand_stacks.
*/
address &= PAGE_MASK;
- size = vma->vm_end - address;
- grow = (vma->vm_start - address) >> PAGE_SHIFT;
+ error = 0;
+
+ /* Somebody else might have raced and expanded it already */
+ if (address < vma->vm_start) {
+ unsigned long size, grow;
+
+ size = vma->vm_end - address;
+ grow = (vma->vm_start - address) >> PAGE_SHIFT;
- error = acct_stack_growth(vma, size, grow);
- if (!error) {
- vma->vm_start = address;
- vma->vm_pgoff -= grow;
+ error = acct_stack_growth(vma, size, grow);
+ if (!error) {
+ vma->vm_start = address;
+ vma->vm_pgoff -= grow;
+ }
}
anon_vma_unlock(vma);
return error;
@@ -1771,6 +1870,16 @@ asmlinkage long sys_munmap(unsigned long addr, size_t len)
return ret;
}
+static inline void verify_mm_writelocked(struct mm_struct *mm)
+{
+#ifdef CONFIG_DEBUG_KERNEL
+ if (unlikely(down_read_trylock(&mm->mmap_sem))) {
+ WARN_ON(1);
+ up_read(&mm->mmap_sem);
+ }
+#endif
+}
+
/*
* this is really a simplified "do_mmap". it only handles
* anonymous maps. eventually we may be able to do some
@@ -1804,6 +1913,12 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
}
/*
+ * mm->mmap_sem is required to protect against another thread
+ * changing the mappings in case we sleep.
+ */
+ verify_mm_writelocked(mm);
+
+ /*
* Clear old maps. this also does some error checking for us
*/
munmap_back:
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 967958c7fae1..7f2951f4ddca 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -61,7 +61,8 @@ static unsigned long badness(struct task_struct *p, unsigned long uptime)
* of seconds. There is no particular reason for this other than
* that it turned out to work very well in practice.
*/
- cpu_time = (p->utime + p->stime) >> (SHIFT_HZ + 3);
+ cpu_time = (cputime_to_jiffies(p->utime) + cputime_to_jiffies(p->stime))
+ >> (SHIFT_HZ + 3);
if (uptime >= p->start_time.tv_sec)
run_time = (uptime - p->start_time.tv_sec) >> 10;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 74b5700093b5..42fd1e9fc7d3 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1630,7 +1630,7 @@ static void __init free_area_init_core(struct pglist_data *pgdat,
zone->zone_start_pfn = zone_start_pfn;
if ((zone_start_pfn) & (zone_required_alignment-1))
- printk("BUG: wrong zone alignment, it will crash\n");
+ printk(KERN_CRIT "BUG: wrong zone alignment, it will crash\n");
memmap_init(size, nid, j, zone_start_pfn);
diff --git a/mm/readahead.c b/mm/readahead.c
index d0c5a515ea07..b7c3b746de67 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -254,7 +254,7 @@ out:
* do_page_cache_readahead() returns -1 if it encountered request queue
* congestion.
*/
-static inline int
+static int
__do_page_cache_readahead(struct address_space *mapping, struct file *filp,
unsigned long offset, unsigned long nr_to_read)
{
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 5a00ea361200..547ecd9c060d 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -442,12 +442,11 @@ unuse_pte(struct vm_area_struct *vma, unsigned long address, pte_t *dir,
}
/* vma->vm_mm->page_table_lock is held */
-static unsigned long unuse_pmd(struct vm_area_struct * vma, pmd_t *dir,
- unsigned long address, unsigned long size, unsigned long offset,
+static unsigned long unuse_pmd(struct vm_area_struct *vma, pmd_t *dir,
+ unsigned long address, unsigned long end,
swp_entry_t entry, struct page *page)
{
- pte_t * pte;
- unsigned long end;
+ pte_t *pte;
pte_t swp_pte = swp_entry_to_pte(entry);
if (pmd_none(*dir))
@@ -458,18 +457,13 @@ static unsigned long unuse_pmd(struct vm_area_struct * vma, pmd_t *dir,
return 0;
}
pte = pte_offset_map(dir, address);
- offset += address & PMD_MASK;
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
do {
/*
* swapoff spends a _lot_ of time in this loop!
* Test inline before going to call unuse_pte.
*/
if (unlikely(pte_same(*pte, swp_pte))) {
- unuse_pte(vma, offset + address, pte, entry, page);
+ unuse_pte(vma, address, pte, entry, page);
pte_unmap(pte);
/*
@@ -479,22 +473,22 @@ static unsigned long unuse_pmd(struct vm_area_struct * vma, pmd_t *dir,
activate_page(page);
/* add 1 since address may be 0 */
- return 1 + offset + address;
+ return 1 + address;
}
address += PAGE_SIZE;
pte++;
- } while (address && (address < end));
+ } while (address < end);
pte_unmap(pte - 1);
return 0;
}
/* vma->vm_mm->page_table_lock is held */
-static unsigned long unuse_pud(struct vm_area_struct * vma, pud_t *pud,
- unsigned long address, unsigned long size, unsigned long offset,
+static unsigned long unuse_pud(struct vm_area_struct *vma, pud_t *pud,
+ unsigned long address, unsigned long end,
swp_entry_t entry, struct page *page)
{
- pmd_t * pmd;
- unsigned long end;
+ pmd_t *pmd;
+ unsigned long next;
unsigned long foundaddr;
if (pud_none(*pud))
@@ -505,33 +499,27 @@ static unsigned long unuse_pud(struct vm_area_struct * vma, pud_t *pud,
return 0;
}
pmd = pmd_offset(pud, address);
- offset += address & PUD_MASK;
- address &= ~PUD_MASK;
- end = address + size;
- if (end > PUD_SIZE)
- end = PUD_SIZE;
- if (address >= end)
- BUG();
do {
- foundaddr = unuse_pmd(vma, pmd, address, end - address,
- offset, entry, page);
+ next = (address + PMD_SIZE) & PMD_MASK;
+ if (next > end || !next)
+ next = end;
+ foundaddr = unuse_pmd(vma, pmd, address, next, entry, page);
if (foundaddr)
return foundaddr;
- address = (address + PMD_SIZE) & PMD_MASK;
+ address = next;
pmd++;
- } while (address && (address < end));
+ } while (address < end);
return 0;
}
/* vma->vm_mm->page_table_lock is held */
-static unsigned long unuse_pgd(struct vm_area_struct * vma, pgd_t *pgd,
- unsigned long address, unsigned long size,
+static unsigned long unuse_pgd(struct vm_area_struct *vma, pgd_t *pgd,
+ unsigned long address, unsigned long end,
swp_entry_t entry, struct page *page)
{
- pud_t * pud;
- unsigned long offset;
+ pud_t *pud;
+ unsigned long next;
unsigned long foundaddr;
- unsigned long end;
if (pgd_none(*pgd))
return 0;
@@ -541,54 +529,48 @@ static unsigned long unuse_pgd(struct vm_area_struct * vma, pgd_t *pgd,
return 0;
}
pud = pud_offset(pgd, address);
- offset = address & PGDIR_MASK;
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- BUG_ON (address >= end);
do {
- foundaddr = unuse_pud(vma, pud, address, end - address,
- offset, entry, page);
+ next = (address + PUD_SIZE) & PUD_MASK;
+ if (next > end || !next)
+ next = end;
+ foundaddr = unuse_pud(vma, pud, address, next, entry, page);
if (foundaddr)
return foundaddr;
- address = (address + PUD_SIZE) & PUD_MASK;
+ address = next;
pud++;
- } while (address && (address < end));
+ } while (address < end);
return 0;
}
/* vma->vm_mm->page_table_lock is held */
-static unsigned long unuse_vma(struct vm_area_struct * vma,
+static unsigned long unuse_vma(struct vm_area_struct *vma,
swp_entry_t entry, struct page *page)
{
pgd_t *pgd;
- unsigned long start, end, next;
+ unsigned long address, next, end;
unsigned long foundaddr;
- int i;
if (page->mapping) {
- start = page_address_in_vma(page, vma);
- if (start == -EFAULT)
+ address = page_address_in_vma(page, vma);
+ if (address == -EFAULT)
return 0;
else
- end = start + PAGE_SIZE;
+ end = address + PAGE_SIZE;
} else {
- start = vma->vm_start;
+ address = vma->vm_start;
end = vma->vm_end;
}
- pgd = pgd_offset(vma->vm_mm, start);
- for (i = pgd_index(start); i <= pgd_index(end-1); i++) {
- next = (start + PGDIR_SIZE) & PGDIR_MASK;
- if (next > end || next <= start)
+ pgd = pgd_offset(vma->vm_mm, address);
+ do {
+ next = (address + PGDIR_SIZE) & PGDIR_MASK;
+ if (next > end || !next)
next = end;
- foundaddr = unuse_pgd(vma, pgd, start, next - start, entry, page);
+ foundaddr = unuse_pgd(vma, pgd, address, next, entry, page);
if (foundaddr)
return foundaddr;
- start = next;
- i++;
+ address = next;
pgd++;
- }
+ } while (address < end);
return 0;
}
@@ -1634,8 +1616,7 @@ bad_swap_2:
++least_priority;
swap_list_unlock();
destroy_swap_extents(p);
- if (swap_map)
- vfree(swap_map);
+ vfree(swap_map);
if (swap_file)
filp_close(swap_file, NULL);
out:
diff --git a/net/802/psnap.c b/net/802/psnap.c
index f243d37dba35..1053821ddf93 100644
--- a/net/802/psnap.c
+++ b/net/802/psnap.c
@@ -22,7 +22,7 @@
#include <linux/init.h>
static LIST_HEAD(snap_list);
-static spinlock_t snap_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(snap_lock);
static struct llc_sap *snap_sap;
/*
diff --git a/net/802/tr.c b/net/802/tr.c
index c3a659d4ee7e..94cd2668768e 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -66,7 +66,7 @@ struct rif_cache_s {
static struct rif_cache_s *rif_table[RIF_TABLE_SIZE];
-static spinlock_t rif_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rif_lock);
/*
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index cd888bcf67d7..54640c01b50c 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -77,7 +77,7 @@ static struct aarp_entry *proxies[AARP_HASH_SIZE];
static int unresolved_count;
/* One lock protects it all. */
-static rwlock_t aarp_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(aarp_lock);
/* Used to walk the list and purge/kick entries. */
static struct timer_list aarp_timer;
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index d903b5070f06..123d928183b8 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -9,6 +9,7 @@
* Wesley Craig <netatalk@umich.edu>
*
* Fixes:
+ * Neil Horman : Added missing device ioctls
* Michael Callahan : Made routing work
* Wesley Craig : Fix probing to listen to a
* passed node id.
@@ -71,7 +72,7 @@ static struct proto_ops atalk_dgram_ops;
\**************************************************************************/
HLIST_HEAD(atalk_sockets);
-rwlock_t atalk_sockets_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(atalk_sockets_lock);
static inline void __atalk_insert_socket(struct sock *sk)
{
@@ -193,10 +194,10 @@ static inline void atalk_destroy_socket(struct sock *sk)
/* Anti-deadlock ordering is atalk_routes_lock --> iface_lock -DaveM */
struct atalk_route *atalk_routes;
-rwlock_t atalk_routes_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(atalk_routes_lock);
struct atalk_iface *atalk_interfaces;
-rwlock_t atalk_interfaces_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(atalk_interfaces_lock);
/* For probing devices or in a routerless network */
struct atalk_route atrtr_default;
@@ -1806,6 +1807,8 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSIFHWADDR:
case SIOCGIFFLAGS:
case SIOCSIFFLAGS:
+ case SIOCGIFTXQLEN:
+ case SIOCSIFTXQLEN:
case SIOCGIFMTU:
case SIOCGIFCONF:
case SIOCADDMULTI:
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index f7955e643314..02b2556f194d 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -97,7 +97,7 @@ struct br2684_dev {
* do read-locking under interrupt context, so write locking must block
* the current CPU's interrupts
*/
-static rwlock_t devs_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(devs_lock);
static LIST_HEAD(br2684_devs);
diff --git a/net/atm/common.c b/net/atm/common.c
index 47f5413683c8..85556b1af5c0 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -39,7 +39,7 @@
#endif
struct hlist_head vcc_hash[VCC_HTABLE_SIZE];
-rwlock_t vcc_sklist_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(vcc_sklist_lock);
void __vcc_insert_socket(struct sock *sk)
{
diff --git a/net/atm/resources.c b/net/atm/resources.c
index fd4b35b8d4eb..f030fea2ea60 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -24,7 +24,7 @@
LIST_HEAD(atm_devs);
-spinlock_t atm_dev_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(atm_dev_lock);
static struct atm_dev *__alloc_atm_dev(const char *type)
{
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 1d7b66a457f9..974d029f46e2 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -52,7 +52,7 @@
HLIST_HEAD(ax25_list);
-spinlock_t ax25_list_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(ax25_list_lock);
static struct proto_ops ax25_proto_ops;
@@ -207,8 +207,16 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr,
continue;
if (s->ax25_dev == NULL)
continue;
- if (ax25cmp(&s->source_addr, src_addr) == 0 &&
- ax25cmp(&s->dest_addr, dest_addr) == 0) {
+ if (ax25cmp(&s->source_addr, src_addr) == 0 && ax25cmp(&s->dest_addr, dest_addr) == 0 && s->ax25_dev->dev == dev) {
+ if (digi != NULL && digi->ndigi != 0) {
+ if (s->digipeat == NULL)
+ continue;
+ if (ax25digicmp(s->digipeat, digi) != 0)
+ continue;
+ } else {
+ if (s->digipeat != NULL && s->digipeat->ndigi != 0)
+ continue;
+ }
ax25_cb_hold(s);
spin_unlock_bh(&ax25_list_lock);
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c
index 4db0a89c4b3b..f4fa6dfb846e 100644
--- a/net/ax25/ax25_addr.c
+++ b/net/ax25/ax25_addr.c
@@ -121,6 +121,26 @@ int ax25cmp(ax25_address *a, ax25_address *b)
}
/*
+ * Compare two AX.25 digipeater paths.
+ */
+int ax25digicmp(ax25_digi *digi1, ax25_digi *digi2)
+{
+ int i;
+
+ if (digi1->ndigi != digi2->ndigi)
+ return 1;
+
+ if (digi1->lastrepeat != digi2->lastrepeat)
+ return 1;
+
+ for (i = 0; i < digi1->ndigi; i++)
+ if (ax25cmp(&digi1->calls[i], &digi2->calls[i]) != 0)
+ return 1;
+
+ return 0;
+}
+
+/*
* Given an AX.25 address pull of to, from, digi list, command/response and the start of data
*
*/
diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
index 8eac13755eb3..dab77efe34a6 100644
--- a/net/ax25/ax25_dev.c
+++ b/net/ax25/ax25_dev.c
@@ -32,7 +32,7 @@
#include <linux/init.h>
ax25_dev *ax25_dev_list;
-spinlock_t ax25_dev_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(ax25_dev_lock);
ax25_dev *ax25_addr_ax25dev(ax25_address *addr)
{
diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c
index d58243d46191..d68aff100729 100644
--- a/net/ax25/ax25_iface.c
+++ b/net/ax25/ax25_iface.c
@@ -34,20 +34,20 @@ static struct protocol_struct {
unsigned int pid;
int (*func)(struct sk_buff *, ax25_cb *);
} *protocol_list = NULL;
-static rwlock_t protocol_list_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(protocol_list_lock);
static struct linkfail_struct {
struct linkfail_struct *next;
void (*func)(ax25_cb *, int);
} *linkfail_list = NULL;
-static spinlock_t linkfail_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(linkfail_lock);
static struct listen_struct {
struct listen_struct *next;
ax25_address callsign;
struct net_device *dev;
} *listen_list = NULL;
-static spinlock_t listen_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(listen_lock);
int ax25_protocol_register(unsigned int pid,
int (*func)(struct sk_buff *, ax25_cb *))
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index ae2491427116..3475a3ac9343 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -32,7 +32,7 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
-static spinlock_t ax25_frag_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ax25_frag_lock);
ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax25_address *dest, ax25_digi *digi, struct net_device *dev)
{
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index 1090ac6dc058..706e729f6859 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -37,7 +37,7 @@
#include <linux/seq_file.h>
static ax25_route *ax25_route_list;
-static rwlock_t ax25_route_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ax25_route_lock);
static ax25_route *ax25_get_route(ax25_address *, struct net_device *);
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index b82efa073e75..cea6b7d19729 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -42,7 +42,7 @@
*/
static ax25_uid_assoc *ax25_uid_list;
-static rwlock_t ax25_uid_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ax25_uid_lock);
int ax25_uid_policy = 0;
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index 18d9b7393026..7fcc531d2c82 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -139,6 +139,19 @@ static int cmtp_msgnum_get(struct cmtp_session *session)
return session->msgnum;
}
+static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
+{
+ struct cmtp_scb *scb = (void *) skb->cb;
+
+ BT_DBG("session %p skb %p len %d", session, skb, skb->len);
+
+ scb->id = -1;
+ scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
+
+ skb_queue_tail(&session->transmit, skb);
+
+ cmtp_schedule(session);
+}
static void cmtp_send_interopmsg(struct cmtp_session *session,
__u8 subcmd, __u16 appl, __u16 msgnum,
@@ -337,21 +350,6 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
capi_ctr_handle_message(ctrl, appl, skb);
}
-void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
-{
- struct cmtp_scb *scb = (void *) skb->cb;
-
- BT_DBG("session %p skb %p len %d", session, skb, skb->len);
-
- scb->id = -1;
- scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
-
- skb_queue_tail(&session->transmit, skb);
-
- cmtp_schedule(session);
-}
-
-
static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
{
BT_DBG("ctrl %p data %p", ctrl, data);
diff --git a/net/bluetooth/cmtp/cmtp.h b/net/bluetooth/cmtp/cmtp.h
index 58e4adc38b1b..40e3dfec0cc8 100644
--- a/net/bluetooth/cmtp/cmtp.h
+++ b/net/bluetooth/cmtp/cmtp.h
@@ -120,7 +120,6 @@ int cmtp_attach_device(struct cmtp_session *session);
void cmtp_detach_device(struct cmtp_session *session);
void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb);
-void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb);
static inline void cmtp_schedule(struct cmtp_session *session)
{
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index bacc386111b2..618d6e64fd17 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -53,7 +53,7 @@
#define BT_DBG(D...)
#endif
-void hci_acl_connect(struct hci_conn *conn)
+static void hci_acl_connect(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
struct inquiry_entry *ie;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 37690eacff03..13e049bed8cd 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -59,15 +59,15 @@ static void hci_rx_task(unsigned long arg);
static void hci_tx_task(unsigned long arg);
static void hci_notify(struct hci_dev *hdev, int event);
-rwlock_t hci_task_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(hci_task_lock);
/* HCI device list */
LIST_HEAD(hci_dev_list);
-rwlock_t hci_dev_list_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(hci_dev_list_lock);
/* HCI callback list */
LIST_HEAD(hci_cb_list);
-rwlock_t hci_cb_list_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(hci_cb_list_lock);
/* HCI protocols */
#define HCI_MAX_PROTO 2
@@ -106,7 +106,7 @@ void hci_req_complete(struct hci_dev *hdev, int result)
}
}
-void hci_req_cancel(struct hci_dev *hdev, int err)
+static void hci_req_cancel(struct hci_dev *hdev, int err)
{
BT_DBG("%s err 0x%2.2x", hdev->name, err);
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 7fabfa13e435..52a1af7cd5d3 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -447,7 +447,7 @@ drop:
goto done;
}
-int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int len)
+static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int len)
{
struct hci_ufilter uf = { .opcode = 0 };
struct sock *sk = sock->sk;
@@ -514,7 +514,7 @@ int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user
return err;
}
-int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
+static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
{
struct hci_ufilter uf;
struct sock *sk = sock->sk;
@@ -567,7 +567,7 @@ int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user
return 0;
}
-struct proto_ops hci_sock_ops = {
+static struct proto_ops hci_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = hci_sock_release,
@@ -647,13 +647,13 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event,
return NOTIFY_DONE;
}
-struct net_proto_family hci_sock_family_ops = {
+static struct net_proto_family hci_sock_family_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.create = hci_sock_create,
};
-struct notifier_block hci_sock_nblock = {
+static struct notifier_block hci_sock_nblock = {
.notifier_call = hci_sock_dev_event
};
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index ee652ae9c342..44540e50dab7 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -50,7 +50,7 @@
#define BT_DBG(D...)
#endif
-#define VERSION "1.0"
+#define VERSION "1.1"
static DECLARE_RWSEM(hidp_session_sem);
static LIST_HEAD(hidp_session_list);
@@ -130,7 +130,7 @@ static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned i
struct sk_buff *skb;
unsigned char newleds;
- BT_DBG("session %p hid %p data %p size %d", session, device, data, size);
+ BT_DBG("input %p type %d code %d value %d", dev, type, code, value);
if (type != EV_LED)
return -1;
@@ -151,7 +151,7 @@ static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned i
return -ENOMEM;
}
- *skb_put(skb, 1) = 0xa2;
+ *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
*skb_put(skb, 1) = 0x01;
*skb_put(skb, 1) = newleds;
@@ -232,36 +232,171 @@ static inline void hidp_del_timer(struct hidp_session *session)
del_timer(&session->timer);
}
-static inline void hidp_send_message(struct hidp_session *session, unsigned char hdr)
+static int __hidp_send_ctrl_message(struct hidp_session *session,
+ unsigned char hdr, unsigned char *data, int size)
{
struct sk_buff *skb;
- BT_DBG("session %p", session);
+ BT_DBG("session %p data %p size %d", session, data, size);
- if (!(skb = alloc_skb(1, GFP_ATOMIC))) {
- BT_ERR("Can't allocate memory for message");
- return;
+ if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
+ BT_ERR("Can't allocate memory for new frame");
+ return -ENOMEM;
}
*skb_put(skb, 1) = hdr;
+ if (data && size > 0)
+ memcpy(skb_put(skb, size), data, size);
skb_queue_tail(&session->ctrl_transmit, skb);
+ return 0;
+}
+
+static int inline hidp_send_ctrl_message(struct hidp_session *session,
+ unsigned char hdr, unsigned char *data, int size)
+{
+ int err;
+
+ err = __hidp_send_ctrl_message(session, hdr, data, size);
+
hidp_schedule(session);
+
+ return err;
+}
+
+static inline void hidp_process_handshake(struct hidp_session *session, unsigned char param)
+{
+ BT_DBG("session %p param 0x%02x", session, param);
+
+ switch (param) {
+ case HIDP_HSHK_SUCCESSFUL:
+ /* FIXME: Call into SET_ GET_ handlers here */
+ break;
+
+ case HIDP_HSHK_NOT_READY:
+ case HIDP_HSHK_ERR_INVALID_REPORT_ID:
+ case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
+ case HIDP_HSHK_ERR_INVALID_PARAMETER:
+ /* FIXME: Call into SET_ GET_ handlers here */
+ break;
+
+ case HIDP_HSHK_ERR_UNKNOWN:
+ break;
+
+ case HIDP_HSHK_ERR_FATAL:
+ /* Device requests a reboot, as this is the only way this error
+ * can be recovered. */
+ __hidp_send_ctrl_message(session,
+ HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
+ break;
+
+ default:
+ __hidp_send_ctrl_message(session,
+ HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
+ break;
+ }
+}
+
+static inline void hidp_process_hid_control(struct hidp_session *session, unsigned char param)
+{
+ BT_DBG("session %p param 0x%02x", session, param);
+
+ switch (param) {
+ case HIDP_CTRL_NOP:
+ break;
+
+ case HIDP_CTRL_VIRTUAL_CABLE_UNPLUG:
+ /* Flush the transmit queues */
+ skb_queue_purge(&session->ctrl_transmit);
+ skb_queue_purge(&session->intr_transmit);
+
+ /* Kill session thread */
+ atomic_inc(&session->terminate);
+ break;
+
+ case HIDP_CTRL_HARD_RESET:
+ case HIDP_CTRL_SOFT_RESET:
+ case HIDP_CTRL_SUSPEND:
+ case HIDP_CTRL_EXIT_SUSPEND:
+ /* FIXME: We have to parse these and return no error */
+ break;
+
+ default:
+ __hidp_send_ctrl_message(session,
+ HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
+ break;
+ }
}
-static inline int hidp_recv_frame(struct hidp_session *session, struct sk_buff *skb)
+static inline void hidp_process_data(struct hidp_session *session, struct sk_buff *skb, unsigned char param)
{
- __u8 hdr;
+ BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
+
+ switch (param) {
+ case HIDP_DATA_RTYPE_INPUT:
+ hidp_set_timer(session);
+
+ if (session->input)
+ hidp_input_report(session, skb);
+ break;
+
+ case HIDP_DATA_RTYPE_OTHER:
+ case HIDP_DATA_RTYPE_OUPUT:
+ case HIDP_DATA_RTYPE_FEATURE:
+ break;
+
+ default:
+ __hidp_send_ctrl_message(session,
+ HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
+ }
+}
+
+static inline void hidp_recv_ctrl_frame(struct hidp_session *session, struct sk_buff *skb)
+{
+ unsigned char hdr, type, param;
BT_DBG("session %p skb %p len %d", session, skb, skb->len);
hdr = skb->data[0];
skb_pull(skb, 1);
- if (hdr == 0xa1) {
- hidp_set_timer(session);
+ type = hdr & HIDP_HEADER_TRANS_MASK;
+ param = hdr & HIDP_HEADER_PARAM_MASK;
+
+ switch (type) {
+ case HIDP_TRANS_HANDSHAKE:
+ hidp_process_handshake(session, param);
+ break;
+ case HIDP_TRANS_HID_CONTROL:
+ hidp_process_hid_control(session, param);
+ break;
+
+ case HIDP_TRANS_DATA:
+ hidp_process_data(session, skb, param);
+ break;
+
+ default:
+ __hidp_send_ctrl_message(session,
+ HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
+ break;
+ }
+
+ kfree_skb(skb);
+}
+
+static inline void hidp_recv_intr_frame(struct hidp_session *session, struct sk_buff *skb)
+{
+ unsigned char hdr;
+
+ BT_DBG("session %p skb %p len %d", session, skb, skb->len);
+
+ hdr = skb->data[0];
+ skb_pull(skb, 1);
+
+ if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
+ hidp_set_timer(session);
if (session->input)
hidp_input_report(session, skb);
} else {
@@ -269,7 +404,6 @@ static inline int hidp_recv_frame(struct hidp_session *session, struct sk_buff *
}
kfree_skb(skb);
- return 0;
}
static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
@@ -350,12 +484,12 @@ static int hidp_session(void *arg)
while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
skb_orphan(skb);
- hidp_recv_frame(session, skb);
+ hidp_recv_ctrl_frame(session, skb);
}
while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
skb_orphan(skb);
- hidp_recv_frame(session, skb);
+ hidp_recv_intr_frame(session, skb);
}
hidp_process_transmit(session);
@@ -514,7 +648,8 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
goto unlink;
if (session->input) {
- hidp_send_message(session, 0x70);
+ hidp_send_ctrl_message(session,
+ HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
session->leds = 0xff;
@@ -554,7 +689,8 @@ int hidp_del_connection(struct hidp_conndel_req *req)
session = __hidp_get_session(&req->bdaddr);
if (session) {
if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
- hidp_send_message(session, 0x15);
+ hidp_send_ctrl_message(session,
+ HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
} else {
/* Flush the transmit queues */
skb_queue_purge(&session->ctrl_transmit);
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index 98a742a64d02..c2775f587d2e 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -26,6 +26,51 @@
#include <linux/types.h>
#include <net/bluetooth/bluetooth.h>
+/* HIDP header masks */
+#define HIDP_HEADER_TRANS_MASK 0xf0
+#define HIDP_HEADER_PARAM_MASK 0x0f
+
+/* HIDP transaction types */
+#define HIDP_TRANS_HANDSHAKE 0x00
+#define HIDP_TRANS_HID_CONTROL 0x10
+#define HIDP_TRANS_GET_REPORT 0x40
+#define HIDP_TRANS_SET_REPORT 0x50
+#define HIDP_TRANS_GET_PROTOCOL 0x60
+#define HIDP_TRANS_SET_PROTOCOL 0x70
+#define HIDP_TRANS_GET_IDLE 0x80
+#define HIDP_TRANS_SET_IDLE 0x90
+#define HIDP_TRANS_DATA 0xa0
+#define HIDP_TRANS_DATC 0xb0
+
+/* HIDP handshake results */
+#define HIDP_HSHK_SUCCESSFUL 0x00
+#define HIDP_HSHK_NOT_READY 0x01
+#define HIDP_HSHK_ERR_INVALID_REPORT_ID 0x02
+#define HIDP_HSHK_ERR_UNSUPPORTED_REQUEST 0x03
+#define HIDP_HSHK_ERR_INVALID_PARAMETER 0x04
+#define HIDP_HSHK_ERR_UNKNOWN 0x0e
+#define HIDP_HSHK_ERR_FATAL 0x0f
+
+/* HIDP control operation parameters */
+#define HIDP_CTRL_NOP 0x00
+#define HIDP_CTRL_HARD_RESET 0x01
+#define HIDP_CTRL_SOFT_RESET 0x02
+#define HIDP_CTRL_SUSPEND 0x03
+#define HIDP_CTRL_EXIT_SUSPEND 0x04
+#define HIDP_CTRL_VIRTUAL_CABLE_UNPLUG 0x05
+
+/* HIDP data transaction headers */
+#define HIDP_DATA_RTYPE_MASK 0x03
+#define HIDP_DATA_RSRVD_MASK 0x0c
+#define HIDP_DATA_RTYPE_OTHER 0x00
+#define HIDP_DATA_RTYPE_INPUT 0x01
+#define HIDP_DATA_RTYPE_OUPUT 0x02
+#define HIDP_DATA_RTYPE_FEATURE 0x03
+
+/* HIDP protocol header parameters */
+#define HIDP_PROTO_BOOT 0x00
+#define HIDP_PROTO_REPORT 0x01
+
/* HIDP ioctl defines */
#define HIDPCONNADD _IOW('H', 200, int)
#define HIDPCONNDEL _IOW('H', 201, int)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 612ac3c62e55..3969c7ce67aa 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -57,11 +57,11 @@
#define BT_DBG(D...)
#endif
-#define VERSION "2.6"
+#define VERSION "2.7"
static struct proto_ops l2cap_sock_ops;
-struct bt_sock_list l2cap_sk_list = {
+static struct bt_sock_list l2cap_sk_list = {
.lock = RW_LOCK_UNLOCKED
};
@@ -798,7 +798,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
switch (optname) {
case L2CAP_OPTIONS:
len = min_t(unsigned int, sizeof(opts), optlen);
- if (copy_from_user((char *)&opts, optval, len)) {
+ if (copy_from_user((char *) &opts, optval, len)) {
err = -EFAULT;
break;
}
@@ -807,7 +807,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
break;
case L2CAP_LM:
- if (get_user(opt, (u32 __user *)optval)) {
+ if (get_user(opt, (u32 __user *) optval)) {
err = -EFAULT;
break;
}
@@ -829,7 +829,9 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
struct sock *sk = sock->sk;
struct l2cap_options opts;
struct l2cap_conninfo cinfo;
- int len, err = 0;
+ int len, err = 0;
+
+ BT_DBG("sk %p", sk);
if (get_user(len, optlen))
return -EFAULT;
@@ -841,15 +843,16 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
opts.imtu = l2cap_pi(sk)->imtu;
opts.omtu = l2cap_pi(sk)->omtu;
opts.flush_to = l2cap_pi(sk)->flush_to;
+ opts.mode = 0x00;
len = min_t(unsigned int, len, sizeof(opts));
- if (copy_to_user(optval, (char *)&opts, len))
+ if (copy_to_user(optval, (char *) &opts, len))
err = -EFAULT;
break;
case L2CAP_LM:
- if (put_user(l2cap_pi(sk)->link_mode, (u32 __user *)optval))
+ if (put_user(l2cap_pi(sk)->link_mode, (u32 __user *) optval))
err = -EFAULT;
break;
@@ -860,9 +863,10 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
}
cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
+ memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
len = min_t(unsigned int, len, sizeof(cinfo));
- if (copy_to_user(optval, (char *)&cinfo, len))
+ if (copy_to_user(optval, (char *) &cinfo, len))
err = -EFAULT;
break;
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index f53a8b040ffb..99d708cb26fd 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -50,7 +50,7 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h>
-#define VERSION "1.3"
+#define VERSION "1.4"
#ifndef CONFIG_BT_RFCOMM_DEBUG
#undef BT_DBG
@@ -61,8 +61,12 @@
struct proc_dir_entry *proc_bt_rfcomm;
#endif
-struct task_struct *rfcomm_thread;
-DECLARE_MUTEX(rfcomm_sem);
+static struct task_struct *rfcomm_thread;
+
+static DECLARE_MUTEX(rfcomm_sem);
+#define rfcomm_lock() down(&rfcomm_sem);
+#define rfcomm_unlock() up(&rfcomm_sem);
+
unsigned long rfcomm_event;
static LIST_HEAD(session_list);
@@ -81,6 +85,10 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr);
static void rfcomm_process_connect(struct rfcomm_session *s);
+static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err);
+static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
+static void rfcomm_session_del(struct rfcomm_session *s);
+
/* ---- RFCOMM frame parsing macros ---- */
#define __get_dlci(b) ((b & 0xfc) >> 2)
#define __get_channel(b) ((b & 0xf8) >> 3)
@@ -111,6 +119,21 @@ static void rfcomm_process_connect(struct rfcomm_session *s);
#define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1)
#define __get_rpn_parity(line) (((line) >> 3) & 0x3)
+static inline void rfcomm_schedule(uint event)
+{
+ if (!rfcomm_thread)
+ return;
+ //set_bit(event, &rfcomm_event);
+ set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
+ wake_up_process(rfcomm_thread);
+}
+
+static inline void rfcomm_session_put(struct rfcomm_session *s)
+{
+ if (atomic_dec_and_test(&s->refcnt))
+ rfcomm_session_del(s);
+}
+
/* ---- RFCOMM FCS computation ---- */
/* CRC on 2 bytes */
@@ -458,7 +481,7 @@ int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig)
}
/* ---- RFCOMM sessions ---- */
-struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state)
+static struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state)
{
struct rfcomm_session *s = kmalloc(sizeof(*s), GFP_KERNEL);
if (!s)
@@ -487,7 +510,7 @@ struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state)
return s;
}
-void rfcomm_session_del(struct rfcomm_session *s)
+static void rfcomm_session_del(struct rfcomm_session *s)
{
int state = s->state;
@@ -505,7 +528,7 @@ void rfcomm_session_del(struct rfcomm_session *s)
module_put(THIS_MODULE);
}
-struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
+static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
{
struct rfcomm_session *s;
struct list_head *p, *n;
@@ -521,7 +544,7 @@ struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst)
return NULL;
}
-void rfcomm_session_close(struct rfcomm_session *s, int err)
+static void rfcomm_session_close(struct rfcomm_session *s, int err)
{
struct rfcomm_dlc *d;
struct list_head *p, *n;
@@ -542,7 +565,7 @@ void rfcomm_session_close(struct rfcomm_session *s, int err)
rfcomm_session_put(s);
}
-struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err)
+static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err)
{
struct rfcomm_session *s = NULL;
struct sockaddr_l2 addr;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 77aac3b66490..3d3580b2accb 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -51,6 +51,8 @@
#include <asm/uaccess.h>
#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h>
#ifndef CONFIG_BT_RFCOMM_DEBUG
@@ -261,10 +263,18 @@ static void rfcomm_sock_close(struct sock *sk)
static void rfcomm_sock_init(struct sock *sk, struct sock *parent)
{
+ struct rfcomm_pinfo *pi = rfcomm_pi(sk);
+
BT_DBG("sk %p", sk);
- if (parent)
+ if (parent) {
sk->sk_type = parent->sk_type;
+ pi->link_mode = rfcomm_pi(parent)->link_mode;
+ } else {
+ pi->link_mode = 0;
+ }
+
+ pi->dlc->link_mode = pi->link_mode;
}
static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio)
@@ -393,7 +403,7 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
return err;
}
-int rfcomm_sock_listen(struct socket *sock, int backlog)
+static int rfcomm_sock_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
int err = 0;
@@ -437,7 +447,7 @@ done:
return err;
}
-int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags)
+static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags)
{
DECLARE_WAITQUEUE(wait, current);
struct sock *sk = sock->sk, *nsk;
@@ -671,12 +681,22 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
{
struct sock *sk = sock->sk;
int err = 0;
+ u32 opt;
BT_DBG("sk %p", sk);
lock_sock(sk);
switch (optname) {
+ case RFCOMM_LM:
+ if (get_user(opt, (u32 __user *) optval)) {
+ err = -EFAULT;
+ break;
+ }
+
+ rfcomm_pi(sk)->link_mode = opt;
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -689,7 +709,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
- int len, err = 0;
+ struct sock *l2cap_sk;
+ struct rfcomm_conninfo cinfo;
+ int len, err = 0;
BT_DBG("sk %p", sk);
@@ -699,10 +721,32 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
lock_sock(sk);
switch (optname) {
+ case RFCOMM_LM:
+ if (put_user(rfcomm_pi(sk)->link_mode, (u32 __user *) optval))
+ err = -EFAULT;
+ break;
+
+ case RFCOMM_CONNINFO:
+ if (sk->sk_state != BT_CONNECTED) {
+ err = -ENOTCONN;
+ break;
+ }
+
+ l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
+
+ cinfo.hci_handle = l2cap_pi(l2cap_sk)->conn->hcon->handle;
+ memcpy(cinfo.dev_class, l2cap_pi(l2cap_sk)->conn->hcon->dev_class, 3);
+
+ len = min_t(unsigned int, len, sizeof(cinfo));
+ if (copy_to_user(optval, (char *) &cinfo, len))
+ err = -EFAULT;
+
+ break;
+
default:
err = -ENOPROTOOPT;
break;
- };
+ }
release_sock(sk);
return err;
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 08907d32425e..6d689200bcf3 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -77,7 +77,7 @@ struct rfcomm_dev {
};
static LIST_HEAD(rfcomm_dev_list);
-static rwlock_t rfcomm_dev_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(rfcomm_dev_lock);
static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb);
static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 55a266705788..ac01c408238e 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -56,7 +56,7 @@
#define BT_DBG(D...)
#endif
-#define VERSION "0.3"
+#define VERSION "0.4"
static struct proto_ops sco_sock_ops;
@@ -705,6 +705,7 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
}
cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
+ memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
len = min_t(unsigned int, len, sizeof(cinfo));
if (copy_to_user(optval, (char *)&cinfo, len))
@@ -1045,7 +1046,7 @@ static void __exit sco_exit(void)
module_init(sco_init);
module_exit(sco_exit);
-MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
+MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth SCO ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index b240ad4a6308..3c34d7d2bd2d 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -845,19 +845,6 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
{
struct sk_buff *skb = *pskb;
-#ifdef CONFIG_SYSCTL
- if (!skb->nf_bridge) {
- struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
-
- if (skb->protocol == __constant_htons(ETH_P_IP) ||
- IS_VLAN_IP) {
- if (!brnf_call_iptables)
- return NF_ACCEPT;
- } else if (!brnf_call_ip6tables)
- return NF_ACCEPT;
- }
-#endif
-
if ((out->hard_start_xmit == br_dev_xmit &&
okfn != br_nf_forward_finish &&
okfn != br_nf_local_out_finish &&
@@ -869,8 +856,24 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
) {
struct nf_bridge_info *nf_bridge;
- if (!skb->nf_bridge && !nf_bridge_alloc(skb))
- return NF_DROP;
+ if (!skb->nf_bridge) {
+#ifdef CONFIG_SYSCTL
+ /* This code is executed while in the IP(v6) stack,
+ the version should be 4 or 6. We can't use
+ skb->protocol because that isn't set on
+ PF_INET(6)/LOCAL_OUT. */
+ struct iphdr *ip = skb->nh.iph;
+
+ if (ip->version == 4 && !brnf_call_iptables)
+ return NF_ACCEPT;
+ else if (ip->version == 6 && !brnf_call_ip6tables)
+ return NF_ACCEPT;
+#endif
+ if (hook == NF_IP_POST_ROUTING)
+ return NF_ACCEPT;
+ if (!nf_bridge_alloc(skb))
+ return NF_DROP;
+ }
nf_bridge = skb->nf_bridge;
diff --git a/net/bridge/netfilter/ebt_limit.c b/net/bridge/netfilter/ebt_limit.c
index 20c57d58d5bf..637c8844cd5f 100644
--- a/net/bridge/netfilter/ebt_limit.c
+++ b/net/bridge/netfilter/ebt_limit.c
@@ -18,7 +18,7 @@
#include <linux/netdevice.h>
#include <linux/spinlock.h>
-static spinlock_t limit_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(limit_lock);
#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 5071e5327241..e4ae34b88925 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -15,7 +15,7 @@
#include <linux/if_arp.h>
#include <linux/spinlock.h>
-static spinlock_t ebt_log_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ebt_log_lock);
static int ebt_log_check(const char *tablename, unsigned int hookmask,
const struct ebt_entry *e, void *data, unsigned int datalen)
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index ea6c24f6ff26..01af4fcef26d 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -135,7 +135,7 @@ static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr,
size = NLMSG_SPACE(sizeof(*pm) + copy_len);
if (size > nlbufsiz) {
- PRINTR("ebt_ulog: Size %d needed, but nlbufsiz=%d\n",
+ PRINTR("ebt_ulog: Size %Zd needed, but nlbufsiz=%d\n",
size, nlbufsiz);
return;
}
@@ -255,7 +255,7 @@ static int __init init(void)
init_timer(&ulog_buffers[i].timer);
ulog_buffers[i].timer.function = ulog_timer;
ulog_buffers[i].timer.data = i;
- ulog_buffers[i].lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&ulog_buffers[i].lock);
}
ebtulognl = netlink_kernel_create(NETLINK_NFLOG, NULL);
diff --git a/net/compat.c b/net/compat.c
index e80e0cebf464..be5d936dc423 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -125,7 +125,7 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
(struct compat_cmsghdr __user *)NULL)
#define CMSG_COMPAT_OK(ucmlen, ucmsg, mhdr) \
- ((ucmlen) >= sizeof(struct cmsghdr) && \
+ ((ucmlen) >= sizeof(struct compat_cmsghdr) && \
(ucmlen) <= (unsigned long) \
((mhdr)->msg_controllen - \
((char *)(ucmsg) - (char *)(mhdr)->msg_control)))
@@ -507,7 +507,8 @@ static int do_get_sock_timeout(int fd, int level, int optname,
asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
char __user *optval, int __user *optlen)
{
- if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
+ if (level == SOL_SOCKET &&
+ (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO))
return do_get_sock_timeout(fd, level, optname, optval, optlen);
return sys_getsockopt(fd, level, optname, optval, optlen);
}
diff --git a/net/core/datagram.c b/net/core/datagram.c
index b422d9bda2ad..d1bfd279cc1a 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -199,19 +199,6 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb)
kfree_skb(skb);
}
-/*
- * Copy a datagram to a linear buffer.
- */
-int skb_copy_datagram(const struct sk_buff *skb, int offset, char __user *to, int size)
-{
- struct iovec iov = {
- .iov_base = to,
- .iov_len =size,
- };
-
- return skb_copy_datagram_iovec(skb, offset, &iov, size);
-}
-
/**
* skb_copy_datagram_iovec - Copy a datagram to an iovec.
* @skb - buffer to copy
@@ -296,8 +283,9 @@ fault:
return -EFAULT;
}
-int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
- u8 __user *to, int len, unsigned int *csump)
+static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
+ u8 __user *to, int len,
+ unsigned int *csump)
{
int start = skb_headlen(skb);
int pos = 0;
@@ -489,7 +477,6 @@ unsigned int datagram_poll(struct file *file, struct socket *sock,
EXPORT_SYMBOL(datagram_poll);
EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec);
-EXPORT_SYMBOL(skb_copy_datagram);
EXPORT_SYMBOL(skb_copy_datagram_iovec);
EXPORT_SYMBOL(skb_free_datagram);
EXPORT_SYMBOL(skb_recv_datagram);
diff --git a/net/core/dev.c b/net/core/dev.c
index 6ee78b6595aa..4dc01e26f158 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -154,7 +154,7 @@
* 86DD IPv6
*/
-static spinlock_t ptype_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ptype_lock);
static struct list_head ptype_base[16]; /* 16 way hashed list */
static struct list_head ptype_all; /* Taps */
@@ -183,8 +183,8 @@ static struct timer_list samp_timer = TIMER_INITIALIZER(sample_queue, 0, 0);
* semaphore held.
*/
struct net_device *dev_base;
-struct net_device **dev_tail = &dev_base;
-rwlock_t dev_base_lock = RW_LOCK_UNLOCKED;
+static struct net_device **dev_tail = &dev_base;
+DEFINE_RWLOCK(dev_base_lock);
EXPORT_SYMBOL(dev_base);
EXPORT_SYMBOL(dev_base_lock);
@@ -361,7 +361,7 @@ static struct netdev_boot_setup dev_boot_setup[NETDEV_BOOT_SETUP_MAX];
* returns 0 on error and 1 on success. This is a generic routine to
* all netdevices.
*/
-int netdev_boot_setup_add(char *name, struct ifmap *map)
+static int netdev_boot_setup_add(char *name, struct ifmap *map)
{
struct netdev_boot_setup *s;
int i;
@@ -644,7 +644,7 @@ struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mas
* Network device names need to be valid file names to
* to allow sysfs to work
*/
-int dev_valid_name(const char *name)
+static int dev_valid_name(const char *name)
{
return !(*name == '\0'
|| !strcmp(name, ".")
@@ -1590,7 +1590,7 @@ static __inline__ int handle_bridge(struct sk_buff **pskb,
* the ingress scheduler, you just cant add policies on ingress.
*
*/
-int ing_filter(struct sk_buff *skb)
+static int ing_filter(struct sk_buff *skb)
{
struct Qdisc *q;
struct net_device *dev = skb->dev;
@@ -2674,7 +2674,7 @@ static int dev_new_index(void)
static int dev_boot_phase = 1;
/* Delayed registration/unregisteration */
-static spinlock_t net_todo_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(net_todo_list_lock);
static struct list_head net_todo_list = LIST_HEAD_INIT(net_todo_list);
static inline void net_set_todo(struct net_device *dev)
@@ -3346,9 +3346,4 @@ EXPORT_SYMBOL(br_handle_frame_hook);
EXPORT_SYMBOL(dev_load);
#endif
-#ifdef CONFIG_NET_CLS_ACT
-EXPORT_SYMBOL(ing_filter);
-#endif
-
-
EXPORT_PER_CPU_SYMBOL(softnet_data);
diff --git a/net/core/dst.c b/net/core/dst.c
index 8755f0de86dc..f1c95a538e3b 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -32,7 +32,7 @@ static struct dst_entry *dst_garbage_list;
#if RT_CACHE_DEBUG >= 2
static atomic_t dst_total = ATOMIC_INIT(0);
#endif
-static spinlock_t dst_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(dst_lock);
static unsigned long dst_gc_timer_expires;
static unsigned long dst_gc_timer_inc = DST_GC_MAX;
@@ -264,7 +264,7 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void
return NOTIFY_DONE;
}
-struct notifier_block dst_dev_notifier = {
+static struct notifier_block dst_dev_notifier = {
.notifier_call = dst_dev_event,
};
diff --git a/net/core/dv.c b/net/core/dv.c
index 05c76cb9c8fd..3f25f4aa4e66 100644
--- a/net/core/dv.c
+++ b/net/core/dv.c
@@ -52,26 +52,20 @@ int alloc_divert_blk(struct net_device *dev)
{
int alloc_size = (sizeof(struct divert_blk) + 3) & ~3;
+ dev->divert = NULL;
if (dev->type == ARPHRD_ETHER) {
- printk(KERN_DEBUG "divert: allocating divert_blk for %s\n",
- dev->name);
-
dev->divert = (struct divert_blk *)
kmalloc(alloc_size, GFP_KERNEL);
if (dev->divert == NULL) {
- printk(KERN_DEBUG "divert: unable to allocate divert_blk for %s\n",
+ printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n",
dev->name);
return -ENOMEM;
- } else {
- memset(dev->divert, 0, sizeof(struct divert_blk));
}
- dev_hold(dev);
- } else {
- printk(KERN_DEBUG "divert: not allocating divert_blk for non-ethernet device %s\n",
- dev->name);
- dev->divert = NULL;
+ memset(dev->divert, 0, sizeof(struct divert_blk));
+ dev_hold(dev);
}
+
return 0;
}
@@ -85,11 +79,6 @@ void free_divert_blk(struct net_device *dev)
kfree(dev->divert);
dev->divert=NULL;
dev_put(dev);
- printk(KERN_DEBUG "divert: freeing divert_blk for %s\n",
- dev->name);
- } else {
- printk(KERN_DEBUG "divert: no divert_blk to free, %s not ethernet\n",
- dev->name);
}
}
@@ -192,8 +181,12 @@ out:
/*
* control function of the diverter
*/
+#if 0
#define DVDBG(a) \
printk(KERN_DEBUG "divert_ioctl() line %d %s\n", __LINE__, (a))
+#else
+#define DVDBG(a)
+#endif
int divert_ioctl(unsigned int cmd, struct divert_cf __user *arg)
{
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index c9c70c6d0cfb..b07c029e8219 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -100,7 +100,7 @@ struct gen_estimator_head
static struct gen_estimator_head elist[EST_MAX_INTERVAL+1];
/* Estimator array lock */
-static rwlock_t est_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(est_lock);
static void est_timer(unsigned long arg)
{
diff --git a/net/core/iovec.c b/net/core/iovec.c
index 89de9355d99e..d57ace949ab8 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -99,28 +99,6 @@ int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
}
/*
- * In kernel copy to iovec. Returns -EFAULT on error.
- *
- * Note: this modifies the original iovec.
- */
-
-void memcpy_tokerneliovec(struct iovec *iov, unsigned char *kdata, int len)
-{
- while (len > 0) {
- if (iov->iov_len) {
- int copy = min_t(unsigned int, iov->iov_len, len);
- memcpy(iov->iov_base, kdata, copy);
- kdata += copy;
- len -= copy;
- iov->iov_len -= copy;
- iov->iov_base += copy;
- }
- iov++;
- }
-}
-
-
-/*
* Copy iovec to kernel. Returns -EFAULT on error.
*
* Note: this modifies the original iovec.
@@ -259,4 +237,3 @@ EXPORT_SYMBOL(csum_partial_copy_fromiovecend);
EXPORT_SYMBOL(memcpy_fromiovec);
EXPORT_SYMBOL(memcpy_fromiovecend);
EXPORT_SYMBOL(memcpy_toiovec);
-EXPORT_SYMBOL(memcpy_tokerneliovec);
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index 0a84b0d8db74..4859b7446c6f 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -38,7 +38,7 @@ static void linkwatch_event(void *dummy);
static DECLARE_WORK(linkwatch_work, linkwatch_event, NULL);
static LIST_HEAD(lweventlist);
-static spinlock_t lweventlist_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(lweventlist_lock);
struct lw_event {
struct list_head list;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 47966b5f9444..17ed7fea5e62 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -93,7 +93,7 @@ static struct file_operations neigh_stat_seq_fops;
list of neighbour tables. This list is used only in process context,
*/
-static rwlock_t neigh_tbl_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(neigh_tbl_lock);
static int neigh_blackhole(struct sk_buff *skb)
{
diff --git a/net/core/netfilter.c b/net/core/netfilter.c
index 075f3b1aee27..0416161a2ed7 100644
--- a/net/core/netfilter.c
+++ b/net/core/netfilter.c
@@ -47,7 +47,7 @@ static DECLARE_MUTEX(nf_sockopt_mutex);
struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
static LIST_HEAD(nf_sockopts);
-static spinlock_t nf_hook_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(nf_hook_lock);
/*
* A queue handler may be registered for each protocol. Each is protected by
@@ -58,7 +58,7 @@ static struct nf_queue_handler_t {
nf_queue_outfn_t outfn;
void *data;
} queue_handler[NPROTO];
-static rwlock_t queue_handler_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(queue_handler_lock);
int nf_register_hook(struct nf_hook_ops *reg)
{
@@ -173,7 +173,7 @@ static void debug_print_hooks_ip(unsigned int nf_debug)
printk("\n");
}
-void nf_dump_skb(int pf, struct sk_buff *skb)
+static void nf_dump_skb(int pf, struct sk_buff *skb)
{
printk("skb: pf=%i %s dev=%s len=%u\n",
pf,
@@ -744,7 +744,7 @@ EXPORT_SYMBOL(skb_ip_make_writable);
static nf_logfn *nf_logging[NPROTO]; /* = NULL */
static int reported = 0;
-static spinlock_t nf_log_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(nf_log_lock);
int nf_log_register(int pf, nf_logfn *logfn)
{
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 496365ae9da5..83697277a851 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -31,15 +31,15 @@
#define MAX_SKBS 32
#define MAX_UDP_CHUNK 1460
-static spinlock_t skb_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(skb_list_lock);
static int nr_skbs;
static struct sk_buff *skbs;
-static spinlock_t rx_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rx_list_lock);
static LIST_HEAD(rx_list);
static atomic_t trapped;
-spinlock_t netpoll_poll_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(netpoll_poll_lock);
#define NETPOLL_RX_ENABLED 1
#define NETPOLL_RX_DROP 2
@@ -178,7 +178,7 @@ repeat:
return skb;
}
-void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
+static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
{
int status;
@@ -676,6 +676,5 @@ EXPORT_SYMBOL(netpoll_trap);
EXPORT_SYMBOL(netpoll_parse_options);
EXPORT_SYMBOL(netpoll_setup);
EXPORT_SYMBOL(netpoll_cleanup);
-EXPORT_SYMBOL(netpoll_send_skb);
EXPORT_SYMBOL(netpoll_send_udp);
EXPORT_SYMBOL(netpoll_poll);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index f57db05b4341..9bee84a7fbf8 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -1,13 +1,22 @@
-/* -*-linux-c-*-
- * $Id: pktgen.c,v 1.8 2002/07/15 19:30:17 robert Exp $
- * pktgen.c: Packet Generator for performance evaluation.
- *
+/*
+ * Authors:
* Copyright 2001, 2002 by Robert Olsson <robert.olsson@its.uu.se>
- * Uppsala University, Sweden
+ * Uppsala University and
+ * Swedish University of Agricultural Sciences
+ *
+ * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+ * Ben Greear <greearb@candelatech.com>
+ * Jens Låås <jens.laas@data.slu.se>
+ *
+ * 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.
+ *
*
* A tool for loading the network with preconfigurated packets.
* The tool is implemented as a linux module. Parameters are output
- * device, IPG (interpacket gap), number of packets, and whether
+ * device, delay (to hard_xmit), number of packets, and whether
* to use multiple SKBs or just the same one.
* pktgen uses the installed interface's output routine.
*
@@ -21,866 +30,702 @@
* Added multiskb option 020301 --DaveM
* Scaling of results. 020417--sigurdur@linpro.no
* Significant re-work of the module:
- * * Updated to support generation over multiple interfaces at once
- * by creating 32 /proc/net/pg* files. Each file can be manipulated
- * individually.
+ * * Convert to threaded model to more efficiently be able to transmit
+ * and receive on multiple interfaces at once.
* * Converted many counters to __u64 to allow longer runs.
* * Allow configuration of ranges, like min/max IP address, MACs,
* and UDP-ports, for both source and destination, and can
* set to use a random distribution or sequentially walk the range.
- * * Can now change some values after starting.
+ * * Can now change most values after starting.
* * Place 12-byte packet in UDP payload with magic number,
- * sequence number, and timestamp. Will write receiver next.
- * * The new changes seem to have a performance impact of around 1%,
- * as far as I can tell.
+ * sequence number, and timestamp.
+ * * Add receiver code that detects dropped pkts, re-ordered pkts, and
+ * latencies (with micro-second) precision.
+ * * Add IOCTL interface to easily get counters & configuration.
* --Ben Greear <greearb@candelatech.com>
- * Integrated to 2.5.x 021029 --Lucio Maciel (luciomaciel@zipmail.com.br)
*
* Renamed multiskb to clone_skb and cleaned up sending core for two distinct
* skb modes. A clone_skb=0 mode for Ben "ranges" work and a clone_skb != 0
* as a "fastpath" with a configurable number of clones after alloc's.
- *
* clone_skb=0 means all packets are allocated this also means ranges time
* stamps etc can be used. clone_skb=100 means 1 malloc is followed by 100
* clones.
*
* Also moved to /proc/net/pktgen/
- * --ro
+ * --ro
+ *
+ * Sept 10: Fixed threading/locking. Lots of bone-headed and more clever
+ * mistakes. Also merged in DaveM's patch in the -pre6 patch.
+ * --Ben Greear <greearb@candelatech.com>
+ *
+ * Integrated to 2.5.x 021029 --Lucio Maciel (luciomaciel@zipmail.com.br)
+ *
+ *
+ * 021124 Finished major redesign and rewrite for new functionality.
+ * See Documentation/networking/pktgen.txt for how to use this.
+ *
+ * The new operation:
+ * For each CPU one thread/process is created at start. This process checks
+ * for running devices in the if_list and sends packets until count is 0 it
+ * also the thread checks the thread->control which is used for inter-process
+ * communication. controlling process "posts" operations to the threads this
+ * way. The if_lock should be possible to remove when add/rem_device is merged
+ * into this too.
+ *
+ * By design there should only be *one* "controlling" process. In practice
+ * multiple write accesses gives unpredictable result. Understood by "write"
+ * to /proc gives result code thats should be read be the "writer".
+ * For pratical use this should be no problem.
+ *
+ * Note when adding devices to a specific CPU there good idea to also assign
+ * /proc/irq/XX/smp_affinity so TX-interrupts gets bound to the same CPU.
+ * --ro
*
* Fix refcount off by one if first packet fails, potential null deref,
* memleak 030710- KJP
*
+ * First "ranges" functionality for ipv6 030726 --ro
+ *
+ * Included flow support. 030802 ANK.
+ *
* Fixed unaligned access on IA-64 Grant Grundler <grundler@parisc-linux.org>
+ *
+ * Remove if fix from added Harald Welte <laforge@netfilter.org> 040419
+ * ia64 compilation fix from Aron Griffis <aron@hp.com> 040604
*
* New xmit() return, do_div and misc clean up by Stephen Hemminger
* <shemminger@osdl.org> 040923
*
- * See Documentation/networking/pktgen.txt for how to use this.
+ * Rany Dunlap fixed u64 printk compiler waring
+ *
+ * Remove FCS from BW calculation. Lennert Buytenhek <buytenh@wantstofly.org>
+ * New time handling. Lennert Buytenhek <buytenh@wantstofly.org> 041213
+ *
+ * Corrections from Nikolai Malykh (nmalykh@bilim.com)
+ * Removed unused flags F_SET_SRCMAC & F_SET_SRCIP 041230
+ *
*/
-
+#include <linux/sys.h>
+#include <linux/types.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
+#include <linux/smp_lock.h>
#include <linux/sched.h>
-#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>
+#include <linux/unistd.h>
#include <linux/string.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
-#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/timer.h>
#include <linux/init.h>
-#include <linux/inet.h>
-#include <linux/rcupdate.h>
-#include <linux/bitops.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/udp.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
+#include <linux/inet.h>
#include <linux/inetdevice.h>
#include <linux/rtnetlink.h>
-#include <linux/proc_fs.h>
#include <linux/if_arp.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include <linux/proc_fs.h>
#include <net/checksum.h>
+#include <net/ipv6.h>
+#include <net/addrconf.h>
+#include <asm/byteorder.h>
+#include <linux/rcupdate.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+#include <asm/div64.h> /* do_div */
#include <asm/timex.h>
-#define cycles() ((u32)get_cycles())
-
-#define VERSION "pktgen version 1.32"
-static char version[] __initdata =
- "pktgen.c: v1.4: Packet Generator for packet performance testing.\n";
+#define VERSION "pktgen v2.54: Packet Generator for packet performance testing.\n"
-/* Used to help with determining the pkts on receive */
+/* #define PG_DEBUG(a) a */
+#define PG_DEBUG(a)
-#define PKTGEN_MAGIC 0xbe9be955
-
-
-/* Keep information per interface */
-struct pktgen_info {
- /* Parameters */
-
- /* If min != max, then we will either do a linear iteration, or
- * we will do a random selection from within the range.
- */
- __u32 flags;
+/* The buckets are exponential in 'width' */
+#define LAT_BUCKETS_MAX 32
+#define IP_NAME_SZ 32
+/* Device flag bits */
#define F_IPSRC_RND (1<<0) /* IP-Src Random */
#define F_IPDST_RND (1<<1) /* IP-Dst Random */
#define F_UDPSRC_RND (1<<2) /* UDP-Src Random */
#define F_UDPDST_RND (1<<3) /* UDP-Dst Random */
#define F_MACSRC_RND (1<<4) /* MAC-Src Random */
#define F_MACDST_RND (1<<5) /* MAC-Dst Random */
-#define F_SET_SRCMAC (1<<6) /* Specify-Src-Mac
- (default is to use Interface's MAC Addr) */
-#define F_SET_SRCIP (1<<7) /* Specify-Src-IP
- (default is to use Interface's IP Addr) */
+#define F_TXSIZE_RND (1<<6) /* Transmit size is random */
+#define F_IPV6 (1<<7) /* Interface in IPV6 Mode */
-
- int pkt_size; /* = ETH_ZLEN; */
- int nfrags;
- __u32 ipg; /* Default Interpacket gap in nsec */
- __u64 count; /* Default No packets to send */
- __u64 sofar; /* How many pkts we've sent so far */
- __u64 errors; /* Errors when trying to transmit, pkts will be re-sent */
- struct timeval started_at;
- struct timeval stopped_at;
- __u64 idle_acc;
- __u32 seq_num;
-
- int clone_skb; /* Use multiple SKBs during packet gen. If this number
- * is greater than 1, then that many coppies of the same
- * packet will be sent before a new packet is allocated.
- * For instance, if you want to send 1024 identical packets
- * before creating a new packet, set clone_skb to 1024.
- */
- int busy;
- int do_run_run; /* if this changes to false, the test will stop */
-
- char outdev[32];
- char dst_min[32];
- char dst_max[32];
- char src_min[32];
- char src_max[32];
-
- /* If we're doing ranges, random or incremental, then this
- * defines the min/max for those ranges.
- */
- __u32 saddr_min; /* inclusive, source IP address */
- __u32 saddr_max; /* exclusive, source IP address */
- __u32 daddr_min; /* inclusive, dest IP address */
- __u32 daddr_max; /* exclusive, dest IP address */
-
- __u16 udp_src_min; /* inclusive, source UDP port */
- __u16 udp_src_max; /* exclusive, source UDP port */
- __u16 udp_dst_min; /* inclusive, dest UDP port */
- __u16 udp_dst_max; /* exclusive, dest UDP port */
-
- __u32 src_mac_count; /* How many MACs to iterate through */
- __u32 dst_mac_count; /* How many MACs to iterate through */
-
- unsigned char dst_mac[6];
- unsigned char src_mac[6];
-
- __u32 cur_dst_mac_offset;
- __u32 cur_src_mac_offset;
- __u32 cur_saddr;
- __u32 cur_daddr;
- __u16 cur_udp_dst;
- __u16 cur_udp_src;
-
- __u8 hh[14];
- /* = {
- 0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB,
-
- We fill in SRC address later
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00
- };
- */
- __u16 pad; /* pad out the hh struct to an even 16 bytes */
- char result[512];
-
- /* proc file names */
- char fname[80];
- char busy_fname[80];
-
- struct proc_dir_entry *proc_ent;
- struct proc_dir_entry *busy_proc_ent;
-};
-
-struct pktgen_hdr {
- __u32 pgh_magic;
- __u32 seq_num;
- __u32 tv_sec;
- __u32 tv_usec;
-};
-
-static int cpu_speed;
-static int debug;
-
-/* Module parameters, defaults. */
-static int count_d = 100000;
-static int ipg_d;
-static int clone_skb_d;
+#define L_PUSH(t, i) {i->next = t; t=i;}
+#define L_POP(t, i) {i=t; if(i) t = i->next;}
+/* Thread control flag bits */
+#define T_TERMINATE (1<<0)
+#define T_STOP (1<<1) /* Stop run */
+#define T_RUN (1<<2) /* Start run */
+#define T_REMDEV (1<<3) /* Remove all devs */
-#define MAX_PKTGEN 8
-static struct pktgen_info pginfos[MAX_PKTGEN];
+/* Locks */
+#define thread_lock() spin_lock(&_thread_lock)
+#define thread_unlock() spin_unlock(&_thread_lock)
+/* If lock -- can be removed after some work */
+#define if_lock(t) spin_lock(&(t->if_lock));
+#define if_unlock(t) spin_unlock(&(t->if_lock));
-/** Convert to miliseconds */
-static inline __u64 tv_to_ms(const struct timeval* tv) {
- __u64 ms = tv->tv_usec / 1000;
- ms += (__u64)tv->tv_sec * (__u64)1000;
- return ms;
-}
-
-static inline __u64 getCurMs(void) {
- struct timeval tv;
- do_gettimeofday(&tv);
- return tv_to_ms(&tv);
-}
-
+/* Used to help with determining the pkts on receive */
+#define PKTGEN_MAGIC 0xbe9be955
#define PG_PROC_DIR "pktgen"
-static struct proc_dir_entry *proc_dir;
-static struct net_device *setup_inject(struct pktgen_info* info)
+#define MAX_CFLOWS 65536
+
+struct flow_state
{
- struct net_device *odev;
+ __u32 cur_daddr;
+ int count;
+};
- odev = dev_get_by_name(info->outdev);
- if (!odev) {
- sprintf(info->result, "No such netdevice: \"%s\"", info->outdev);
- goto out;
- }
+struct pktgen_dev {
- if (odev->type != ARPHRD_ETHER) {
- sprintf(info->result, "Not ethernet device: \"%s\"", info->outdev);
- goto out_put;
- }
+ /*
+ * Try to keep frequent/infrequent used vars. separated.
+ */
- if (!netif_running(odev)) {
- sprintf(info->result, "Device is down: \"%s\"", info->outdev);
- goto out_put;
- }
+ char ifname[32];
+ struct proc_dir_entry *proc_ent;
+ char result[512];
+ /* proc file names */
+ char fname[80];
+
+ struct pktgen_thread* pg_thread; /* the owner */
+ struct pktgen_dev *next; /* Used for chaining in the thread's run-queue */
+
+ int running; /* if this changes to false, the test will stop */
+
+ /* If min != max, then we will either do a linear iteration, or
+ * we will do a random selection from within the range.
+ */
+ __u32 flags;
+
+ int min_pkt_size; /* = ETH_ZLEN; */
+ int max_pkt_size; /* = ETH_ZLEN; */
+ int nfrags;
+ __u32 delay_us; /* Default delay */
+ __u32 delay_ns;
+ __u64 count; /* Default No packets to send */
+ __u64 sofar; /* How many pkts we've sent so far */
+ __u64 tx_bytes; /* How many bytes we've transmitted */
+ __u64 errors; /* Errors when trying to transmit, pkts will be re-sent */
+
+ /* runtime counters relating to clone_skb */
+ __u64 next_tx_us; /* timestamp of when to tx next */
+ __u32 next_tx_ns;
+
+ __u64 allocated_skbs;
+ __u32 clone_count;
+ int last_ok; /* Was last skb sent?
+ * Or a failed transmit of some sort? This will keep
+ * sequence numbers in order, for example.
+ */
+ __u64 started_at; /* micro-seconds */
+ __u64 stopped_at; /* micro-seconds */
+ __u64 idle_acc; /* micro-seconds */
+ __u32 seq_num;
+
+ int clone_skb; /* Use multiple SKBs during packet gen. If this number
+ * is greater than 1, then that many coppies of the same
+ * packet will be sent before a new packet is allocated.
+ * For instance, if you want to send 1024 identical packets
+ * before creating a new packet, set clone_skb to 1024.
+ */
+
+ char dst_min[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
+ char dst_max[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
+ char src_min[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
+ char src_max[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
+
+ struct in6_addr in6_saddr;
+ struct in6_addr in6_daddr;
+ struct in6_addr cur_in6_daddr;
+ struct in6_addr cur_in6_saddr;
+ /* For ranges */
+ struct in6_addr min_in6_daddr;
+ struct in6_addr max_in6_daddr;
+ struct in6_addr min_in6_saddr;
+ struct in6_addr max_in6_saddr;
+
+ /* If we're doing ranges, random or incremental, then this
+ * defines the min/max for those ranges.
+ */
+ __u32 saddr_min; /* inclusive, source IP address */
+ __u32 saddr_max; /* exclusive, source IP address */
+ __u32 daddr_min; /* inclusive, dest IP address */
+ __u32 daddr_max; /* exclusive, dest IP address */
+
+ __u16 udp_src_min; /* inclusive, source UDP port */
+ __u16 udp_src_max; /* exclusive, source UDP port */
+ __u16 udp_dst_min; /* inclusive, dest UDP port */
+ __u16 udp_dst_max; /* exclusive, dest UDP port */
+
+ __u32 src_mac_count; /* How many MACs to iterate through */
+ __u32 dst_mac_count; /* How many MACs to iterate through */
+
+ unsigned char dst_mac[6];
+ unsigned char src_mac[6];
+
+ __u32 cur_dst_mac_offset;
+ __u32 cur_src_mac_offset;
+ __u32 cur_saddr;
+ __u32 cur_daddr;
+ __u16 cur_udp_dst;
+ __u16 cur_udp_src;
+ __u32 cur_pkt_size;
+
+ __u8 hh[14];
+ /* = {
+ 0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB,
+
+ We fill in SRC address later
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00
+ };
+ */
+ __u16 pad; /* pad out the hh struct to an even 16 bytes */
+
+ struct sk_buff* skb; /* skb we are to transmit next, mainly used for when we
+ * are transmitting the same one multiple times
+ */
+ struct net_device* odev; /* The out-going device. Note that the device should
+ * have it's pg_info pointer pointing back to this
+ * device. This will be set when the user specifies
+ * the out-going device name (not when the inject is
+ * started as it used to do.)
+ */
+ struct flow_state *flows;
+ unsigned cflows; /* Concurrent flows (config) */
+ unsigned lflow; /* Flow length (config) */
+ unsigned nflows; /* accumulated flows (stats) */
+};
- /* Default to the interface's mac if not explicitly set. */
- if (!(info->flags & F_SET_SRCMAC)) {
- memcpy(&(info->hh[6]), odev->dev_addr, 6);
- }
- else {
- memcpy(&(info->hh[6]), info->src_mac, 6);
- }
+struct pktgen_hdr {
+ __u32 pgh_magic;
+ __u32 seq_num;
+ __u32 tv_sec;
+ __u32 tv_usec;
+};
- /* Set up Dest MAC */
- memcpy(&(info->hh[0]), info->dst_mac, 6);
-
- info->saddr_min = 0;
- info->saddr_max = 0;
- if (strlen(info->src_min) == 0) {
- struct in_device *in_dev;
-
- rcu_read_lock();
- in_dev = __in_dev_get(odev);
- if (in_dev) {
- if (in_dev->ifa_list) {
- info->saddr_min = in_dev->ifa_list->ifa_address;
- info->saddr_max = info->saddr_min;
- }
- }
- rcu_read_unlock();
- }
- else {
- info->saddr_min = in_aton(info->src_min);
- info->saddr_max = in_aton(info->src_max);
- }
+struct pktgen_thread {
+ spinlock_t if_lock;
+ struct pktgen_dev *if_list; /* All device here */
+ struct pktgen_thread* next;
+ char name[32];
+ char fname[128]; /* name of proc file */
+ struct proc_dir_entry *proc_ent;
+ char result[512];
+ u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
+
+ /* Field for thread to receive "posted" events terminate, stop ifs etc.*/
+
+ u32 control;
+ int pid;
+ int cpu;
+
+ wait_queue_head_t queue;
+};
- info->daddr_min = in_aton(info->dst_min);
- info->daddr_max = in_aton(info->dst_max);
+#define REMOVE 1
+#define FIND 0
- /* Initialize current values. */
- info->cur_dst_mac_offset = 0;
- info->cur_src_mac_offset = 0;
- info->cur_saddr = info->saddr_min;
- info->cur_daddr = info->daddr_min;
- info->cur_udp_dst = info->udp_dst_min;
- info->cur_udp_src = info->udp_src_min;
-
- return odev;
+/* This code works around the fact that do_div cannot handle two 64-bit
+ numbers, and regular 64-bit division doesn't work on x86 kernels.
+ --Ben
+*/
-out_put:
- dev_put(odev);
-out:
- return NULL;
-}
+#define PG_DIV 0
-static void nanospin(int ipg, struct pktgen_info* info)
+/* This was emailed to LMKL by: Chris Caputo <ccaputo@alt.net>
+ * Function copied/adapted/optimized from:
+ *
+ * nemesis.sourceforge.net/browse/lib/static/intmath/ix86/intmath.c.html
+ *
+ * Copyright 1994, University of Cambridge Computer Laboratory
+ * All Rights Reserved.
+ *
+ */
+inline static s64 divremdi3(s64 x, s64 y, int type)
{
- u32 idle_start, idle;
-
- idle_start = cycles();
-
- for (;;) {
- barrier();
- idle = cycles() - idle_start;
- if (idle * 1000 >= ipg * cpu_speed)
- break;
- }
- info->idle_acc += idle;
+ u64 a = (x < 0) ? -x : x;
+ u64 b = (y < 0) ? -y : y;
+ u64 res = 0, d = 1;
+
+ if (b > 0) {
+ while (b < a) {
+ b <<= 1;
+ d <<= 1;
+ }
+ }
+
+ do {
+ if ( a >= b ) {
+ a -= b;
+ res += d;
+ }
+ b >>= 1;
+ d >>= 1;
+ }
+ while (d);
+
+ if (PG_DIV == type) {
+ return (((x ^ y) & (1ll<<63)) == 0) ? res : -(s64)res;
+ }
+ else {
+ return ((x & (1ll<<63)) == 0) ? a : -(s64)a;
+ }
}
-static int calc_mhz(void)
+/* End of hacks to deal with 64-bit math on x86 */
+
+/** Convert to miliseconds */
+static inline __u64 tv_to_ms(const struct timeval* tv)
{
- struct timeval start, stop;
- u32 start_s, elapsed;
-
- do_gettimeofday(&start);
- start_s = cycles();
- do {
- barrier();
- elapsed = cycles() - start_s;
- if (elapsed == 0)
- return 0;
- } while (elapsed < 1000 * 50000);
- do_gettimeofday(&stop);
- return elapsed/(stop.tv_usec-start.tv_usec+1000000*(stop.tv_sec-start.tv_sec));
+ __u64 ms = tv->tv_usec / 1000;
+ ms += (__u64)tv->tv_sec * (__u64)1000;
+ return ms;
}
-static void cycles_calibrate(void)
-{
- int i;
- for (i = 0; i < 3; i++) {
- int res = calc_mhz();
- if (res > cpu_speed)
- cpu_speed = res;
- }
+/** Convert to micro-seconds */
+static inline __u64 tv_to_us(const struct timeval* tv)
+{
+ __u64 us = tv->tv_usec;
+ us += (__u64)tv->tv_sec * (__u64)1000000;
+ return us;
}
+static inline __u64 pg_div(__u64 n, __u32 base) {
+ __u64 tmp = n;
+ do_div(tmp, base);
+ /* printk("pktgen: pg_div, n: %llu base: %d rv: %llu\n",
+ n, base, tmp); */
+ return tmp;
+}
-/* Increment/randomize headers according to flags and current values
- * for IP src/dest, UDP src/dst port, MAC-Addr src/dst
+static inline __u64 pg_div64(__u64 n, __u64 base)
+{
+ __u64 tmp = n;
+/*
+ * How do we know if the architectrure we are running on
+ * supports division with 64 bit base?
+ *
*/
-static void mod_cur_headers(struct pktgen_info* info) {
- __u32 imn;
- __u32 imx;
-
- /* Deal with source MAC */
- if (info->src_mac_count > 1) {
- __u32 mc;
- __u32 tmp;
- if (info->flags & F_MACSRC_RND) {
- mc = net_random() % (info->src_mac_count);
- }
- else {
- mc = info->cur_src_mac_offset++;
- if (info->cur_src_mac_offset > info->src_mac_count) {
- info->cur_src_mac_offset = 0;
- }
- }
+#if defined(__sparc_v9__) || defined(__powerpc64__) || defined(__alpha__) || defined(__x86_64__) || defined(__ia64__)
- tmp = info->src_mac[5] + (mc & 0xFF);
- info->hh[11] = tmp;
- tmp = (info->src_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
- info->hh[10] = tmp;
- tmp = (info->src_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
- info->hh[9] = tmp;
- tmp = (info->src_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
- info->hh[8] = tmp;
- tmp = (info->src_mac[1] + (tmp >> 8));
- info->hh[7] = tmp;
- }
-
- /* Deal with Destination MAC */
- if (info->dst_mac_count > 1) {
- __u32 mc;
- __u32 tmp;
- if (info->flags & F_MACDST_RND) {
- mc = net_random() % (info->dst_mac_count);
- }
- else {
- mc = info->cur_dst_mac_offset++;
- if (info->cur_dst_mac_offset > info->dst_mac_count) {
- info->cur_dst_mac_offset = 0;
- }
- }
-
- tmp = info->dst_mac[5] + (mc & 0xFF);
- info->hh[5] = tmp;
- tmp = (info->dst_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
- info->hh[4] = tmp;
- tmp = (info->dst_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
- info->hh[3] = tmp;
- tmp = (info->dst_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
- info->hh[2] = tmp;
- tmp = (info->dst_mac[1] + (tmp >> 8));
- info->hh[1] = tmp;
- }
-
- if (info->udp_src_min < info->udp_src_max) {
- if (info->flags & F_UDPSRC_RND) {
- info->cur_udp_src = ((net_random() % (info->udp_src_max - info->udp_src_min))
- + info->udp_src_min);
- }
- else {
- info->cur_udp_src++;
- if (info->cur_udp_src >= info->udp_src_max) {
- info->cur_udp_src = info->udp_src_min;
- }
- }
- }
-
- if (info->udp_dst_min < info->udp_dst_max) {
- if (info->flags & F_UDPDST_RND) {
- info->cur_udp_dst = ((net_random() % (info->udp_dst_max - info->udp_dst_min))
- + info->udp_dst_min);
- }
- else {
- info->cur_udp_dst++;
- if (info->cur_udp_dst >= info->udp_dst_max) {
- info->cur_udp_dst = info->udp_dst_min;
- }
- }
- }
+ do_div(tmp, base);
+#else
+ tmp = divremdi3(n, base, PG_DIV);
+#endif
+ return tmp;
+}
- if ((imn = ntohl(info->saddr_min)) < (imx = ntohl(info->saddr_max))) {
- __u32 t;
- if (info->flags & F_IPSRC_RND) {
- t = ((net_random() % (imx - imn)) + imn);
- }
- else {
- t = ntohl(info->cur_saddr);
- t++;
- if (t >= imx) {
- t = imn;
- }
- }
- info->cur_saddr = htonl(t);
- }
+static inline u32 pktgen_random(void)
+{
+#if 0
+ __u32 n;
+ get_random_bytes(&n, 4);
+ return n;
+#else
+ return net_random();
+#endif
+}
- if ((imn = ntohl(info->daddr_min)) < (imx = ntohl(info->daddr_max))) {
- __u32 t;
- if (info->flags & F_IPDST_RND) {
- t = ((net_random() % (imx - imn)) + imn);
- }
- else {
- t = ntohl(info->cur_daddr);
- t++;
- if (t >= imx) {
- t = imn;
- }
- }
- info->cur_daddr = htonl(t);
- }
-}/* mod_cur_headers */
+static inline __u64 getCurMs(void)
+{
+ struct timeval tv;
+ do_gettimeofday(&tv);
+ return tv_to_ms(&tv);
+}
+static inline __u64 getCurUs(void)
+{
+ struct timeval tv;
+ do_gettimeofday(&tv);
+ return tv_to_us(&tv);
+}
-static struct sk_buff *fill_packet(struct net_device *odev, struct pktgen_info* info)
+static inline __u64 tv_diff(const struct timeval* a, const struct timeval* b)
{
- struct sk_buff *skb = NULL;
- __u8 *eth;
- struct udphdr *udph;
- int datalen, iplen;
- struct iphdr *iph;
- struct pktgen_hdr *pgh = NULL;
-
- skb = alloc_skb(info->pkt_size + 64 + 16, GFP_ATOMIC);
- if (!skb) {
- sprintf(info->result, "No memory");
- return NULL;
- }
+ return tv_to_us(a) - tv_to_us(b);
+}
- skb_reserve(skb, 16);
- /* Reserve for ethernet and IP header */
- eth = (__u8 *) skb_push(skb, 14);
- iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
- udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
+/* old include end */
- /* Update any of the values, used when we're incrementing various
- * fields.
- */
- mod_cur_headers(info);
+static char version[] __initdata = VERSION;
- memcpy(eth, info->hh, 14);
-
- datalen = info->pkt_size - 14 - 20 - 8; /* Eth + IPh + UDPh */
- if (datalen < sizeof(struct pktgen_hdr)) {
- datalen = sizeof(struct pktgen_hdr);
- }
-
- udph->source = htons(info->cur_udp_src);
- udph->dest = htons(info->cur_udp_dst);
- udph->len = htons(datalen + 8); /* DATA + udphdr */
- udph->check = 0; /* No checksum */
+static ssize_t proc_pgctrl_read(struct file* file, char * buf, size_t count, loff_t *ppos);
+static ssize_t proc_pgctrl_write(struct file* file, const char * buf, size_t count, loff_t *ppos);
+static int proc_if_read(char *buf , char **start, off_t offset, int len, int *eof, void *data);
- iph->ihl = 5;
- iph->version = 4;
- iph->ttl = 3;
- iph->tos = 0;
- iph->protocol = IPPROTO_UDP; /* UDP */
- iph->saddr = info->cur_saddr;
- iph->daddr = info->cur_daddr;
- iph->frag_off = 0;
- iplen = 20 + 8 + datalen;
- iph->tot_len = htons(iplen);
- iph->check = 0;
- iph->check = ip_fast_csum((void *) iph, iph->ihl);
- skb->protocol = __constant_htons(ETH_P_IP);
- skb->mac.raw = ((u8 *)iph) - 14;
- skb->dev = odev;
- skb->pkt_type = PACKET_HOST;
+static int proc_thread_read(char *buf , char **start, off_t offset, int len, int *eof, void *data);
+static int proc_if_write(struct file *file, const char *user_buffer, unsigned long count, void *data);
+static int proc_thread_write(struct file *file, const char *user_buffer, unsigned long count, void *data);
+static int create_proc_dir(void);
+static int remove_proc_dir(void);
- if (info->nfrags <= 0) {
- pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
- } else {
- int frags = info->nfrags;
- int i;
+static int pktgen_remove_device(struct pktgen_thread* t, struct pktgen_dev *i);
+static int pktgen_add_device(struct pktgen_thread* t, const char* ifname);
+static struct pktgen_thread* pktgen_find_thread(const char* name);
+static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread* t, const char* ifname);
+static int pktgen_device_event(struct notifier_block *, unsigned long, void *);
+static void pktgen_run_all_threads(void);
+static void pktgen_stop_all_threads_ifs(void);
+static int pktgen_stop_device(struct pktgen_dev *pkt_dev);
+static void pktgen_stop(struct pktgen_thread* t);
+static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);
+static struct pktgen_dev *pktgen_NN_threads(const char* dev_name, int remove);
+static unsigned int scan_ip6(const char *s,char ip[16]);
+static unsigned int fmt_ip6(char *s,const char ip[16]);
- /* TODO: Verify this is OK...it sure is ugly. --Ben */
- pgh = (struct pktgen_hdr*)(((char*)(udph)) + 8);
-
- if (frags > MAX_SKB_FRAGS)
- frags = MAX_SKB_FRAGS;
- if (datalen > frags*PAGE_SIZE) {
- skb_put(skb, datalen-frags*PAGE_SIZE);
- datalen = frags*PAGE_SIZE;
- }
+/* Module parameters, defaults. */
+static int pg_count_d = 1000; /* 1000 pkts by default */
+static int pg_delay_d = 0;
+static int pg_clone_skb_d = 0;
+static int debug = 0;
- i = 0;
- while (datalen > 0) {
- struct page *page = alloc_pages(GFP_KERNEL, 0);
- skb_shinfo(skb)->frags[i].page = page;
- skb_shinfo(skb)->frags[i].page_offset = 0;
- skb_shinfo(skb)->frags[i].size =
- (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
- datalen -= skb_shinfo(skb)->frags[i].size;
- skb->len += skb_shinfo(skb)->frags[i].size;
- skb->data_len += skb_shinfo(skb)->frags[i].size;
- i++;
- skb_shinfo(skb)->nr_frags = i;
- }
+static spinlock_t _thread_lock = SPIN_LOCK_UNLOCKED;
+static struct pktgen_thread *pktgen_threads = NULL;
- while (i < frags) {
- int rem;
+static char module_fname[128];
+static struct proc_dir_entry *module_proc_ent = NULL;
- if (i == 0)
- break;
+static struct notifier_block pktgen_notifier_block = {
+ notifier_call: pktgen_device_event,
+};
- rem = skb_shinfo(skb)->frags[i - 1].size / 2;
- if (rem == 0)
- break;
+static struct file_operations pktgen_fops = {
+ .read = proc_pgctrl_read,
+ .write = proc_pgctrl_write,
+ /* .ioctl = pktgen_ioctl, later maybe */
+};
- skb_shinfo(skb)->frags[i - 1].size -= rem;
+/*
+ * /proc handling functions
+ *
+ */
- skb_shinfo(skb)->frags[i] = skb_shinfo(skb)->frags[i - 1];
- get_page(skb_shinfo(skb)->frags[i].page);
- skb_shinfo(skb)->frags[i].page = skb_shinfo(skb)->frags[i - 1].page;
- skb_shinfo(skb)->frags[i].page_offset += skb_shinfo(skb)->frags[i - 1].size;
- skb_shinfo(skb)->frags[i].size = rem;
- i++;
- skb_shinfo(skb)->nr_frags = i;
- }
- }
+static struct proc_dir_entry *pg_proc_dir = NULL;
+static int proc_pgctrl_read_eof=0;
- /* Stamp the time, and sequence number, convert them to network byte order */
- if (pgh) {
- struct timeval timestamp;
+static ssize_t proc_pgctrl_read(struct file* file, char * buf,
+ size_t count, loff_t *ppos)
+{
+ char data[200];
+ int len = 0;
- pgh->pgh_magic = htonl(PKTGEN_MAGIC);
- pgh->seq_num = htonl(info->seq_num);
-
- do_gettimeofday(&timestamp);
- pgh->tv_sec = htonl(timestamp.tv_sec);
- pgh->tv_usec = htonl(timestamp.tv_usec);
+ if(proc_pgctrl_read_eof) {
+ proc_pgctrl_read_eof=0;
+ len = 0;
+ goto out;
}
-
- return skb;
-}
-
-static void show_results(struct pktgen_info* info, int nr_frags)
-{
- __u64 total, bps, mbps, pps;
- unsigned long idle;
- int size = info->pkt_size + 4; /* incl 32bit ethernet CRC */
- char *p = info->result;
- total = (info->stopped_at.tv_sec - info->started_at.tv_sec) * 1000000ull
- + info->stopped_at.tv_usec - info->started_at.tv_usec;
+ sprintf(data, "%s", VERSION);
- BUG_ON(cpu_speed == 0);
+ len = strlen(data);
- idle = info->idle_acc;
- do_div(idle, cpu_speed);
+ if(len > count) {
+ len =-EFAULT;
+ goto out;
+ }
- p += sprintf(p, "OK: %llu(c%llu+d%lu) usec, %llu (%dbyte,%dfrags)\n",
- (unsigned long long) total,
- (unsigned long long) (total - idle), idle,
- (unsigned long long) info->sofar,
- size, nr_frags);
+ if (copy_to_user(buf, data, len)) {
+ len =-EFAULT;
+ goto out;
+ }
- pps = info->sofar * USEC_PER_SEC;
-
- while ((total >> 32) != 0) {
- pps >>= 1;
- total >>= 1;
- }
+ *ppos += len;
+ proc_pgctrl_read_eof=1; /* EOF next call */
- do_div(pps, total);
-
- bps = pps * 8 * size;
-
- mbps = bps;
- do_div(mbps, 1000000);
- p += sprintf(p, " %llupps %lluMb/sec (%llubps) errors: %llu",
- (unsigned long long) pps,
- (unsigned long long) mbps,
- (unsigned long long) bps,
- (unsigned long long) info->errors);
+ out:
+ return len;
}
-static void inject(struct pktgen_info* info)
+static ssize_t proc_pgctrl_write(struct file* file,const char * buf,
+ size_t count, loff_t *ppos)
{
- struct net_device *odev;
- struct sk_buff *skb = NULL;
- __u64 lcount = 0;
- int ret;
- int last_ok = 1; /* Was last skb sent?
- * Or a failed transmit of some sort? This will keep
- * sequence numbers in order, for example.
- */
- __u64 fp = 0;
- __u32 fp_tmp = 0;
-
- odev = setup_inject(info);
- if (!odev)
- return;
-
- info->do_run_run = 1; /* Cranke yeself! */
- info->idle_acc = 0;
- info->sofar = 0;
- info->errors = 0;
- lcount = info->count;
-
-
- /* Build our initial pkt and place it as a re-try pkt. */
- skb = fill_packet(odev, info);
- if (skb == NULL) goto out_reldev;
+ char *data = NULL;
+ int err = 0;
- do_gettimeofday(&(info->started_at));
-
- while(info->do_run_run) {
-
- /* Set a time-stamp, so build a new pkt each time */
-
- if (last_ok) {
- if (++fp_tmp >= info->clone_skb ) {
- kfree_skb(skb);
- skb = fill_packet(odev, info);
- if (skb == NULL) {
- goto out_reldev;
- }
- fp++;
- fp_tmp = 0; /* reset counter */
- }
- }
-
- if (!(odev->features & NETIF_F_LLTX))
- spin_lock_bh(&odev->xmit_lock);
- if (!netif_queue_stopped(odev)) {
-
- atomic_inc(&skb->users);
-
- retry:
- ret = odev->hard_start_xmit(skb, odev);
- if (likely(ret == NETDEV_TX_OK)) {
- last_ok = 1;
- info->sofar++;
- info->seq_num++;
- } else if (ret == NETDEV_TX_LOCKED
- && (odev->features & NETIF_F_LLTX)) {
- cpu_relax();
- goto retry;
- } else {
- atomic_dec(&skb->users);
- if (debug && net_ratelimit()) {
- printk(KERN_INFO "Hard xmit error\n");
- }
- info->errors++;
- last_ok = 0;
- }
- }
- else {
- /* Re-try it next time */
- last_ok = 0;
- }
-
- if (!(odev->features & NETIF_F_LLTX))
- spin_unlock_bh(&odev->xmit_lock);
-
- if (info->ipg) {
- /* Try not to busy-spin if we have larger sleep times.
- * TODO: Investigate better ways to do this.
- */
- if (info->ipg < 10000) { /* 10 usecs or less */
- nanospin(info->ipg, info);
- }
- else if (info->ipg < 10000000) { /* 10ms or less */
- udelay(info->ipg / 1000);
- }
- else {
- mdelay(info->ipg / 1000000);
- }
- }
-
- if (signal_pending(current)) {
- break;
- }
-
- /* If lcount is zero, then run forever */
- if ((lcount != 0) && (--lcount == 0)) {
- if (atomic_read(&skb->users) != 1) {
- u32 idle_start, idle;
-
- idle_start = cycles();
- while (atomic_read(&skb->users) != 1) {
- if (signal_pending(current)) {
- break;
- }
- schedule();
- }
- idle = cycles() - idle_start;
- info->idle_acc += idle;
- }
- break;
- }
-
- if (netif_queue_stopped(odev) || need_resched()) {
- u32 idle_start, idle;
-
- idle_start = cycles();
- do {
- if (signal_pending(current)) {
- info->do_run_run = 0;
- break;
- }
- if (!netif_running(odev)) {
- info->do_run_run = 0;
- break;
- }
- if (need_resched())
- schedule();
- else
- do_softirq();
- } while (netif_queue_stopped(odev));
- idle = cycles() - idle_start;
- info->idle_acc += idle;
- }
- }/* while we should be running */
-
- do_gettimeofday(&(info->stopped_at));
-
- show_results(info, skb_shinfo(skb)->nr_frags);
+ if (!capable(CAP_NET_ADMIN)){
+ err = -EPERM;
+ goto out;
+ }
- kfree_skb(skb);
+ data = (void*)vmalloc ((unsigned int)count);
-out_reldev:
- if (odev) {
- dev_put(odev);
- odev = NULL;
+ if(!data) {
+ err = -ENOMEM;
+ goto out;
}
+ if (copy_from_user(data, buf, count)) {
+ err =-EFAULT;
+ goto out_free;
+ }
+ data[count-1] = 0; /* Make string */
- return;
+ if (!strcmp(data, "stop"))
+ pktgen_stop_all_threads_ifs();
-}
+ else if (!strcmp(data, "start"))
+ pktgen_run_all_threads();
-/* proc/net/pktgen/pg */
+ else
+ printk("pktgen: Unknown command: %s\n", data);
-static int proc_busy_read(char *buf , char **start, off_t offset,
- int len, int *eof, void *data)
-{
- char *p;
- int idx = (int)(long)(data);
- struct pktgen_info* info = NULL;
-
- if ((idx < 0) || (idx >= MAX_PKTGEN)) {
- printk("ERROR: idx: %i is out of range in proc_write\n", idx);
- return -EINVAL;
- }
- info = &(pginfos[idx]);
-
- p = buf;
- p += sprintf(p, "%d\n", info->busy);
- *eof = 1;
-
- return p-buf;
+ err = count;
+
+ out_free:
+ vfree (data);
+ out:
+ return err;
}
-static int proc_read(char *buf , char **start, off_t offset,
- int len, int *eof, void *data)
+static int proc_if_read(char *buf , char **start, off_t offset,
+ int len, int *eof, void *data)
{
char *p;
int i;
- int idx = (int)(long)(data);
- struct pktgen_info* info = NULL;
- __u64 sa;
- __u64 stopped;
- __u64 now = getCurMs();
-
- if ((idx < 0) || (idx >= MAX_PKTGEN)) {
- printk("ERROR: idx: %i is out of range in proc_write\n", idx);
- return -EINVAL;
- }
- info = &(pginfos[idx]);
-
+ struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
+ __u64 sa;
+ __u64 stopped;
+ __u64 now = getCurUs();
+
p = buf;
- p += sprintf(p, "%s\n", VERSION); /* Help with parsing compatibility */
- p += sprintf(p, "Params: count %llu pkt_size: %u frags: %d ipg: %u clone_skb: %d odev \"%s\"\n",
- (unsigned long long) info->count,
- info->pkt_size, info->nfrags, info->ipg,
- info->clone_skb, info->outdev);
- p += sprintf(p, " dst_min: %s dst_max: %s src_min: %s src_max: %s\n",
- info->dst_min, info->dst_max, info->src_min, info->src_max);
- p += sprintf(p, " src_mac: ");
- for (i = 0; i < 6; i++) {
- p += sprintf(p, "%02X%s", info->src_mac[i], i == 5 ? " " : ":");
- }
- p += sprintf(p, "dst_mac: ");
- for (i = 0; i < 6; i++) {
- p += sprintf(p, "%02X%s", info->dst_mac[i], i == 5 ? "\n" : ":");
- }
- p += sprintf(p, " udp_src_min: %d udp_src_max: %d udp_dst_min: %d udp_dst_max: %d\n",
- info->udp_src_min, info->udp_src_max, info->udp_dst_min,
- info->udp_dst_max);
- p += sprintf(p, " src_mac_count: %d dst_mac_count: %d\n Flags: ",
- info->src_mac_count, info->dst_mac_count);
- if (info->flags & F_IPSRC_RND) {
- p += sprintf(p, "IPSRC_RND ");
- }
- if (info->flags & F_IPDST_RND) {
- p += sprintf(p, "IPDST_RND ");
- }
- if (info->flags & F_UDPSRC_RND) {
- p += sprintf(p, "UDPSRC_RND ");
- }
- if (info->flags & F_UDPDST_RND) {
- p += sprintf(p, "UDPDST_RND ");
- }
- if (info->flags & F_MACSRC_RND) {
- p += sprintf(p, "MACSRC_RND ");
- }
- if (info->flags & F_MACDST_RND) {
- p += sprintf(p, "MACDST_RND ");
- }
- p += sprintf(p, "\n");
-
- sa = tv_to_ms(&(info->started_at));
- stopped = tv_to_ms(&(info->stopped_at));
- if (info->do_run_run) {
- stopped = now; /* not really stopped, more like last-running-at */
- }
- p += sprintf(p, "Current:\n pkts-sofar: %llu errors: %llu\n started: %llums stopped: %llums now: %llums idle: %lluns\n",
- (unsigned long long) info->sofar,
- (unsigned long long) info->errors,
+ p += sprintf(p, "Params: count %llu min_pkt_size: %u max_pkt_size: %u\n",
+ (unsigned long long) pkt_dev->count,
+ pkt_dev->min_pkt_size, pkt_dev->max_pkt_size);
+
+ p += sprintf(p, " frags: %d delay: %u clone_skb: %d ifname: %s\n",
+ pkt_dev->nfrags, 1000*pkt_dev->delay_us+pkt_dev->delay_ns, pkt_dev->clone_skb, pkt_dev->ifname);
+
+ p += sprintf(p, " flows: %u flowlen: %u\n", pkt_dev->cflows, pkt_dev->lflow);
+
+
+ if(pkt_dev->flags & F_IPV6) {
+ char b1[128], b2[128], b3[128];
+ fmt_ip6(b1, pkt_dev->in6_saddr.s6_addr);
+ fmt_ip6(b2, pkt_dev->min_in6_saddr.s6_addr);
+ fmt_ip6(b3, pkt_dev->max_in6_saddr.s6_addr);
+ p += sprintf(p, " saddr: %s min_saddr: %s max_saddr: %s\n", b1, b2, b3);
+
+ fmt_ip6(b1, pkt_dev->in6_daddr.s6_addr);
+ fmt_ip6(b2, pkt_dev->min_in6_daddr.s6_addr);
+ fmt_ip6(b3, pkt_dev->max_in6_daddr.s6_addr);
+ p += sprintf(p, " daddr: %s min_daddr: %s max_daddr: %s\n", b1, b2, b3);
+
+ }
+ else
+ p += sprintf(p, " dst_min: %s dst_max: %s\n src_min: %s src_max: %s\n",
+ pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min, pkt_dev->src_max);
+
+ p += sprintf(p, " src_mac: ");
+
+ if ((pkt_dev->src_mac[0] == 0) &&
+ (pkt_dev->src_mac[1] == 0) &&
+ (pkt_dev->src_mac[2] == 0) &&
+ (pkt_dev->src_mac[3] == 0) &&
+ (pkt_dev->src_mac[4] == 0) &&
+ (pkt_dev->src_mac[5] == 0))
+
+ for (i = 0; i < 6; i++)
+ p += sprintf(p, "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? " " : ":");
+
+ else
+ for (i = 0; i < 6; i++)
+ p += sprintf(p, "%02X%s", pkt_dev->src_mac[i], i == 5 ? " " : ":");
+
+ p += sprintf(p, "dst_mac: ");
+ for (i = 0; i < 6; i++)
+ p += sprintf(p, "%02X%s", pkt_dev->dst_mac[i], i == 5 ? "\n" : ":");
+
+ p += sprintf(p, " udp_src_min: %d udp_src_max: %d udp_dst_min: %d udp_dst_max: %d\n",
+ pkt_dev->udp_src_min, pkt_dev->udp_src_max, pkt_dev->udp_dst_min,
+ pkt_dev->udp_dst_max);
+
+ p += sprintf(p, " src_mac_count: %d dst_mac_count: %d \n Flags: ",
+ pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
+
+
+ if (pkt_dev->flags & F_IPV6)
+ p += sprintf(p, "IPV6 ");
+
+ if (pkt_dev->flags & F_IPSRC_RND)
+ p += sprintf(p, "IPSRC_RND ");
+
+ if (pkt_dev->flags & F_IPDST_RND)
+ p += sprintf(p, "IPDST_RND ");
+
+ if (pkt_dev->flags & F_TXSIZE_RND)
+ p += sprintf(p, "TXSIZE_RND ");
+
+ if (pkt_dev->flags & F_UDPSRC_RND)
+ p += sprintf(p, "UDPSRC_RND ");
+
+ if (pkt_dev->flags & F_UDPDST_RND)
+ p += sprintf(p, "UDPDST_RND ");
+
+ if (pkt_dev->flags & F_MACSRC_RND)
+ p += sprintf(p, "MACSRC_RND ");
+
+ if (pkt_dev->flags & F_MACDST_RND)
+ p += sprintf(p, "MACDST_RND ");
+
+
+ p += sprintf(p, "\n");
+
+ sa = pkt_dev->started_at;
+ stopped = pkt_dev->stopped_at;
+ if (pkt_dev->running)
+ stopped = now; /* not really stopped, more like last-running-at */
+
+ p += sprintf(p, "Current:\n pkts-sofar: %llu errors: %llu\n started: %lluus stopped: %lluus idle: %lluus\n",
+ (unsigned long long) pkt_dev->sofar,
+ (unsigned long long) pkt_dev->errors,
(unsigned long long) sa,
- (unsigned long long) stopped,
- (unsigned long long) now,
- (unsigned long long) info->idle_acc);
- p += sprintf(p, " seq_num: %d cur_dst_mac_offset: %d cur_src_mac_offset: %d\n",
- info->seq_num, info->cur_dst_mac_offset, info->cur_src_mac_offset);
- p += sprintf(p, " cur_saddr: 0x%x cur_daddr: 0x%x cur_udp_dst: %d cur_udp_src: %d\n",
- info->cur_saddr, info->cur_daddr, info->cur_udp_dst, info->cur_udp_src);
-
- if (info->result[0])
- p += sprintf(p, "Result: %s\n", info->result);
+ (unsigned long long) stopped,
+ (unsigned long long) pkt_dev->idle_acc);
+
+ p += sprintf(p, " seq_num: %d cur_dst_mac_offset: %d cur_src_mac_offset: %d\n",
+ pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset, pkt_dev->cur_src_mac_offset);
+
+ if(pkt_dev->flags & F_IPV6) {
+ char b1[128], b2[128];
+ fmt_ip6(b1, pkt_dev->cur_in6_daddr.s6_addr);
+ fmt_ip6(b2, pkt_dev->cur_in6_saddr.s6_addr);
+ p += sprintf(p, " cur_saddr: %s cur_daddr: %s\n", b2, b1);
+ }
+ else
+ p += sprintf(p, " cur_saddr: 0x%x cur_daddr: 0x%x\n",
+ pkt_dev->cur_saddr, pkt_dev->cur_daddr);
+
+
+ p += sprintf(p, " cur_udp_dst: %d cur_udp_src: %d\n",
+ pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
+
+ p += sprintf(p, " flows: %u\n", pkt_dev->nflows);
+
+ if (pkt_dev->result[0])
+ p += sprintf(p, "Result: %s\n", pkt_dev->result);
else
p += sprintf(p, "Result: Idle\n");
*eof = 1;
@@ -888,16 +733,16 @@ static int proc_read(char *buf , char **start, off_t offset,
return p - buf;
}
-static int count_trail_chars(const char __user *user_buffer, unsigned int maxlen)
+
+static int count_trail_chars(const char *user_buffer, unsigned int maxlen)
{
int i;
for (i = 0; i < maxlen; i++) {
- char c;
-
- if (get_user(c, &user_buffer[i]))
- return -EFAULT;
- switch (c) {
+ char c;
+ if (get_user(c, &user_buffer[i]))
+ return -EFAULT;
+ switch (c) {
case '\"':
case '\n':
case '\r':
@@ -913,19 +758,17 @@ done:
return i;
}
-static unsigned long num_arg(const char __user *user_buffer, unsigned long maxlen,
+static unsigned long num_arg(const char *user_buffer, unsigned long maxlen,
unsigned long *num)
{
int i = 0;
-
*num = 0;
for(; i < maxlen; i++) {
- char c;
-
- if (get_user(c, &user_buffer[i]))
- return -EFAULT;
- if ((c >= '0') && (c <= '9')) {
+ char c;
+ if (get_user(c, &user_buffer[i]))
+ return -EFAULT;
+ if ((c >= '0') && (c <= '9')) {
*num *= 10;
*num += c -'0';
} else
@@ -934,321 +777,485 @@ static unsigned long num_arg(const char __user *user_buffer, unsigned long maxle
return i;
}
-static int strn_len(const char __user *user_buffer, unsigned int maxlen)
+static int strn_len(const char *user_buffer, unsigned int maxlen)
{
int i = 0;
for(; i < maxlen; i++) {
- char c;
-
- if (get_user(c, &user_buffer[i]))
- return -EFAULT;
- switch (c) {
+ char c;
+ if (get_user(c, &user_buffer[i]))
+ return -EFAULT;
+ switch (c) {
case '\"':
case '\n':
case '\r':
case '\t':
case ' ':
goto done_str;
+ break;
default:
break;
};
}
done_str:
+
return i;
}
-static int proc_write(struct file *file, const char __user *user_buffer,
- unsigned long count, void *data)
+static int proc_if_write(struct file *file, const char *user_buffer,
+ unsigned long count, void *data)
{
int i = 0, max, len;
char name[16], valstr[32];
unsigned long value = 0;
- int idx = (int)(long)(data);
- struct pktgen_info* info = NULL;
- char* result = NULL;
- int tmp;
-
- if ((idx < 0) || (idx >= MAX_PKTGEN)) {
- printk("ERROR: idx: %i is out of range in proc_write\n", idx);
- return -EINVAL;
- }
- info = &(pginfos[idx]);
- result = &(info->result[0]);
-
+ struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
+ char* pg_result = NULL;
+ int tmp = 0;
+
+ pg_result = &(pkt_dev->result[0]);
+
if (count < 1) {
- sprintf(result, "Wrong command format");
+ printk("pktgen: wrong command format\n");
return -EINVAL;
}
max = count - i;
tmp = count_trail_chars(&user_buffer[i], max);
- if (tmp < 0)
- return tmp;
- i += tmp;
-
+ if (tmp < 0) {
+ printk("pktgen: illegal format\n");
+ return tmp;
+ }
+ i += tmp;
+
/* Read variable name */
len = strn_len(&user_buffer[i], sizeof(name) - 1);
- if (len < 0)
- return len;
+ if (len < 0) { return len; }
memset(name, 0, sizeof(name));
- if (copy_from_user(name, &user_buffer[i], len))
+ if (copy_from_user(name, &user_buffer[i], len) )
return -EFAULT;
i += len;
max = count -i;
len = count_trail_chars(&user_buffer[i], max);
- if (len < 0)
- return len;
+ if (len < 0)
+ return len;
+
i += len;
- if (debug)
- printk("pg: %s,%lu\n", name, count);
+ if (debug) {
+ char tb[count + 1];
+ if (copy_from_user(tb, user_buffer, count))
+ return -EFAULT;
+ tb[count] = 0;
+ printk("pktgen: %s,%lu buffer -:%s:-\n", name, count, tb);
+ }
- if (!strcmp(name, "stop")) {
- if (info->do_run_run) {
- strcpy(result, "Stopping");
- }
- else {
- strcpy(result, "Already stopped...\n");
- }
- info->do_run_run = 0;
+ if (!strcmp(name, "min_pkt_size")) {
+ len = num_arg(&user_buffer[i], 10, &value);
+ if (len < 0) { return len; }
+ i += len;
+ if (value < 14+20+8)
+ value = 14+20+8;
+ if (value != pkt_dev->min_pkt_size) {
+ pkt_dev->min_pkt_size = value;
+ pkt_dev->cur_pkt_size = value;
+ }
+ sprintf(pg_result, "OK: min_pkt_size=%u", pkt_dev->min_pkt_size);
+ return count;
+ }
+
+ if (!strcmp(name, "max_pkt_size")) {
+ len = num_arg(&user_buffer[i], 10, &value);
+ if (len < 0) { return len; }
+ i += len;
+ if (value < 14+20+8)
+ value = 14+20+8;
+ if (value != pkt_dev->max_pkt_size) {
+ pkt_dev->max_pkt_size = value;
+ pkt_dev->cur_pkt_size = value;
+ }
+ sprintf(pg_result, "OK: max_pkt_size=%u", pkt_dev->max_pkt_size);
return count;
}
+ /* Shortcut for min = max */
+
if (!strcmp(name, "pkt_size")) {
len = num_arg(&user_buffer[i], 10, &value);
- if (len < 0)
- return len;
+ if (len < 0) { return len; }
i += len;
if (value < 14+20+8)
value = 14+20+8;
- info->pkt_size = value;
- sprintf(result, "OK: pkt_size=%u", info->pkt_size);
+ if (value != pkt_dev->min_pkt_size) {
+ pkt_dev->min_pkt_size = value;
+ pkt_dev->max_pkt_size = value;
+ pkt_dev->cur_pkt_size = value;
+ }
+ sprintf(pg_result, "OK: pkt_size=%u", pkt_dev->min_pkt_size);
return count;
}
- if (!strcmp(name, "frags")) {
+
+ if (!strcmp(name, "debug")) {
len = num_arg(&user_buffer[i], 10, &value);
- if (len < 0)
- return len;
+ if (len < 0) { return len; }
i += len;
- info->nfrags = value;
- sprintf(result, "OK: frags=%u", info->nfrags);
+ debug = value;
+ sprintf(pg_result, "OK: debug=%u", debug);
return count;
}
- if (!strcmp(name, "ipg")) {
+
+ if (!strcmp(name, "frags")) {
len = num_arg(&user_buffer[i], 10, &value);
- if (len < 0)
- return len;
+ if (len < 0) { return len; }
+ i += len;
+ pkt_dev->nfrags = value;
+ sprintf(pg_result, "OK: frags=%u", pkt_dev->nfrags);
+ return count;
+ }
+ if (!strcmp(name, "delay")) {
+ len = num_arg(&user_buffer[i], 10, &value);
+ if (len < 0) { return len; }
i += len;
- info->ipg = value;
- sprintf(result, "OK: ipg=%u", info->ipg);
+ if (value == 0x7FFFFFFF) {
+ pkt_dev->delay_us = 0x7FFFFFFF;
+ pkt_dev->delay_ns = 0;
+ } else {
+ pkt_dev->delay_us = value / 1000;
+ pkt_dev->delay_ns = value % 1000;
+ }
+ sprintf(pg_result, "OK: delay=%u", 1000*pkt_dev->delay_us+pkt_dev->delay_ns);
return count;
}
if (!strcmp(name, "udp_src_min")) {
len = num_arg(&user_buffer[i], 10, &value);
- if (len < 0)
- return len;
+ if (len < 0) { return len; }
i += len;
- info->udp_src_min = value;
- sprintf(result, "OK: udp_src_min=%u", info->udp_src_min);
+ if (value != pkt_dev->udp_src_min) {
+ pkt_dev->udp_src_min = value;
+ pkt_dev->cur_udp_src = value;
+ }
+ sprintf(pg_result, "OK: udp_src_min=%u", pkt_dev->udp_src_min);
return count;
}
if (!strcmp(name, "udp_dst_min")) {
len = num_arg(&user_buffer[i], 10, &value);
- if (len < 0)
- return len;
+ if (len < 0) { return len; }
i += len;
- info->udp_dst_min = value;
- sprintf(result, "OK: udp_dst_min=%u", info->udp_dst_min);
+ if (value != pkt_dev->udp_dst_min) {
+ pkt_dev->udp_dst_min = value;
+ pkt_dev->cur_udp_dst = value;
+ }
+ sprintf(pg_result, "OK: udp_dst_min=%u", pkt_dev->udp_dst_min);
return count;
}
if (!strcmp(name, "udp_src_max")) {
len = num_arg(&user_buffer[i], 10, &value);
- if (len < 0)
- return len;
+ if (len < 0) { return len; }
i += len;
- info->udp_src_max = value;
- sprintf(result, "OK: udp_src_max=%u", info->udp_src_max);
+ if (value != pkt_dev->udp_src_max) {
+ pkt_dev->udp_src_max = value;
+ pkt_dev->cur_udp_src = value;
+ }
+ sprintf(pg_result, "OK: udp_src_max=%u", pkt_dev->udp_src_max);
return count;
}
if (!strcmp(name, "udp_dst_max")) {
len = num_arg(&user_buffer[i], 10, &value);
- if (len < 0)
- return len;
+ if (len < 0) { return len; }
i += len;
- info->udp_dst_max = value;
- sprintf(result, "OK: udp_dst_max=%u", info->udp_dst_max);
+ if (value != pkt_dev->udp_dst_max) {
+ pkt_dev->udp_dst_max = value;
+ pkt_dev->cur_udp_dst = value;
+ }
+ sprintf(pg_result, "OK: udp_dst_max=%u", pkt_dev->udp_dst_max);
return count;
}
if (!strcmp(name, "clone_skb")) {
len = num_arg(&user_buffer[i], 10, &value);
- if (len < 0)
- return len;
+ if (len < 0) { return len; }
i += len;
- info->clone_skb = value;
+ pkt_dev->clone_skb = value;
- sprintf(result, "OK: clone_skb=%d", info->clone_skb);
+ sprintf(pg_result, "OK: clone_skb=%d", pkt_dev->clone_skb);
return count;
}
if (!strcmp(name, "count")) {
len = num_arg(&user_buffer[i], 10, &value);
- if (len < 0)
- return len;
+ if (len < 0) { return len; }
i += len;
- info->count = value;
- sprintf(result, "OK: count=%llu", (unsigned long long) info->count);
+ pkt_dev->count = value;
+ sprintf(pg_result, "OK: count=%llu",
+ (unsigned long long) pkt_dev->count);
return count;
}
if (!strcmp(name, "src_mac_count")) {
len = num_arg(&user_buffer[i], 10, &value);
- if (len < 0)
- return len;
+ if (len < 0) { return len; }
i += len;
- info->src_mac_count = value;
- sprintf(result, "OK: src_mac_count=%d", info->src_mac_count);
+ if (pkt_dev->src_mac_count != value) {
+ pkt_dev->src_mac_count = value;
+ pkt_dev->cur_src_mac_offset = 0;
+ }
+ sprintf(pg_result, "OK: src_mac_count=%d", pkt_dev->src_mac_count);
return count;
}
if (!strcmp(name, "dst_mac_count")) {
len = num_arg(&user_buffer[i], 10, &value);
- if (len < 0)
- return len;
- i += len;
- info->dst_mac_count = value;
- sprintf(result, "OK: dst_mac_count=%d", info->dst_mac_count);
- return count;
- }
- if (!strcmp(name, "odev")) {
- len = strn_len(&user_buffer[i], sizeof(info->outdev) - 1);
- if (len < 0)
- return len;
- memset(info->outdev, 0, sizeof(info->outdev));
- if (copy_from_user(info->outdev, &user_buffer[i], len))
- return -EFAULT;
+ if (len < 0) { return len; }
i += len;
- sprintf(result, "OK: odev=%s", info->outdev);
+ if (pkt_dev->dst_mac_count != value) {
+ pkt_dev->dst_mac_count = value;
+ pkt_dev->cur_dst_mac_offset = 0;
+ }
+ sprintf(pg_result, "OK: dst_mac_count=%d", pkt_dev->dst_mac_count);
return count;
}
if (!strcmp(name, "flag")) {
- char f[32];
+ char f[32];
+ memset(f, 0, 32);
len = strn_len(&user_buffer[i], sizeof(f) - 1);
- if (len < 0)
- return len;
- memset(f, 0, 32);
+ if (len < 0) { return len; }
if (copy_from_user(f, &user_buffer[i], len))
return -EFAULT;
i += len;
- if (strcmp(f, "IPSRC_RND") == 0) {
- info->flags |= F_IPSRC_RND;
- }
- else if (strcmp(f, "!IPSRC_RND") == 0) {
- info->flags &= ~F_IPSRC_RND;
- }
- else if (strcmp(f, "IPDST_RND") == 0) {
- info->flags |= F_IPDST_RND;
- }
- else if (strcmp(f, "!IPDST_RND") == 0) {
- info->flags &= ~F_IPDST_RND;
- }
- else if (strcmp(f, "UDPSRC_RND") == 0) {
- info->flags |= F_UDPSRC_RND;
- }
- else if (strcmp(f, "!UDPSRC_RND") == 0) {
- info->flags &= ~F_UDPSRC_RND;
- }
- else if (strcmp(f, "UDPDST_RND") == 0) {
- info->flags |= F_UDPDST_RND;
- }
- else if (strcmp(f, "!UDPDST_RND") == 0) {
- info->flags &= ~F_UDPDST_RND;
- }
- else if (strcmp(f, "MACSRC_RND") == 0) {
- info->flags |= F_MACSRC_RND;
- }
- else if (strcmp(f, "!MACSRC_RND") == 0) {
- info->flags &= ~F_MACSRC_RND;
- }
- else if (strcmp(f, "MACDST_RND") == 0) {
- info->flags |= F_MACDST_RND;
- }
- else if (strcmp(f, "!MACDST_RND") == 0) {
- info->flags &= ~F_MACDST_RND;
- }
- else {
- sprintf(result, "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
- f,
- "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, MACSRC_RND, MACDST_RND\n");
- return count;
- }
- sprintf(result, "OK: flags=0x%x", info->flags);
+ if (strcmp(f, "IPSRC_RND") == 0)
+ pkt_dev->flags |= F_IPSRC_RND;
+
+ else if (strcmp(f, "!IPSRC_RND") == 0)
+ pkt_dev->flags &= ~F_IPSRC_RND;
+
+ else if (strcmp(f, "TXSIZE_RND") == 0)
+ pkt_dev->flags |= F_TXSIZE_RND;
+
+ else if (strcmp(f, "!TXSIZE_RND") == 0)
+ pkt_dev->flags &= ~F_TXSIZE_RND;
+
+ else if (strcmp(f, "IPDST_RND") == 0)
+ pkt_dev->flags |= F_IPDST_RND;
+
+ else if (strcmp(f, "!IPDST_RND") == 0)
+ pkt_dev->flags &= ~F_IPDST_RND;
+
+ else if (strcmp(f, "UDPSRC_RND") == 0)
+ pkt_dev->flags |= F_UDPSRC_RND;
+
+ else if (strcmp(f, "!UDPSRC_RND") == 0)
+ pkt_dev->flags &= ~F_UDPSRC_RND;
+
+ else if (strcmp(f, "UDPDST_RND") == 0)
+ pkt_dev->flags |= F_UDPDST_RND;
+
+ else if (strcmp(f, "!UDPDST_RND") == 0)
+ pkt_dev->flags &= ~F_UDPDST_RND;
+
+ else if (strcmp(f, "MACSRC_RND") == 0)
+ pkt_dev->flags |= F_MACSRC_RND;
+
+ else if (strcmp(f, "!MACSRC_RND") == 0)
+ pkt_dev->flags &= ~F_MACSRC_RND;
+
+ else if (strcmp(f, "MACDST_RND") == 0)
+ pkt_dev->flags |= F_MACDST_RND;
+
+ else if (strcmp(f, "!MACDST_RND") == 0)
+ pkt_dev->flags &= ~F_MACDST_RND;
+
+ else {
+ sprintf(pg_result, "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
+ f,
+ "IPSRC_RND, IPDST_RND, TXSIZE_RND, UDPSRC_RND, UDPDST_RND, MACSRC_RND, MACDST_RND\n");
+ return count;
+ }
+ sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags);
return count;
}
if (!strcmp(name, "dst_min") || !strcmp(name, "dst")) {
- len = strn_len(&user_buffer[i], sizeof(info->dst_min) - 1);
- if (len < 0)
- return len;
- memset(info->dst_min, 0, sizeof(info->dst_min));
- if (copy_from_user(info->dst_min, &user_buffer[i], len))
+ char buf[IP_NAME_SZ];
+ len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_min) - 1);
+ if (len < 0) { return len; }
+
+ if (copy_from_user(buf, &user_buffer[i], len))
return -EFAULT;
- if(debug)
- printk("pg: dst_min set to: %s\n", info->dst_min);
- i += len;
- sprintf(result, "OK: dst_min=%s", info->dst_min);
+ buf[len] = 0;
+ if (strcmp(buf, pkt_dev->dst_min) != 0) {
+ memset(pkt_dev->dst_min, 0, sizeof(pkt_dev->dst_min));
+ strncpy(pkt_dev->dst_min, buf, len);
+ pkt_dev->daddr_min = in_aton(pkt_dev->dst_min);
+ pkt_dev->cur_daddr = pkt_dev->daddr_min;
+ }
+ if(debug)
+ printk("pktgen: dst_min set to: %s\n", pkt_dev->dst_min);
+ i += len;
+ sprintf(pg_result, "OK: dst_min=%s", pkt_dev->dst_min);
return count;
}
if (!strcmp(name, "dst_max")) {
- len = strn_len(&user_buffer[i], sizeof(info->dst_max) - 1);
- if (len < 0)
- return len;
- memset(info->dst_max, 0, sizeof(info->dst_max));
- if (copy_from_user(info->dst_max, &user_buffer[i], len))
+ char buf[IP_NAME_SZ];
+ len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_max) - 1);
+ if (len < 0) { return len; }
+
+ if (copy_from_user(buf, &user_buffer[i], len))
return -EFAULT;
+
+ buf[len] = 0;
+ if (strcmp(buf, pkt_dev->dst_max) != 0) {
+ memset(pkt_dev->dst_max, 0, sizeof(pkt_dev->dst_max));
+ strncpy(pkt_dev->dst_max, buf, len);
+ pkt_dev->daddr_max = in_aton(pkt_dev->dst_max);
+ pkt_dev->cur_daddr = pkt_dev->daddr_max;
+ }
if(debug)
- printk("pg: dst_max set to: %s\n", info->dst_max);
+ printk("pktgen: dst_max set to: %s\n", pkt_dev->dst_max);
i += len;
- sprintf(result, "OK: dst_max=%s", info->dst_max);
+ sprintf(pg_result, "OK: dst_max=%s", pkt_dev->dst_max);
+ return count;
+ }
+ if (!strcmp(name, "dst6")) {
+ char buf[128];
+
+ len = strn_len(&user_buffer[i], 128 - 1);
+ if (len < 0) return len;
+
+ pkt_dev->flags |= F_IPV6;
+
+ if (copy_from_user(buf, &user_buffer[i], len))
+ return -EFAULT;
+ buf[len] = 0;
+
+ scan_ip6(buf, pkt_dev->in6_daddr.s6_addr);
+ fmt_ip6(buf, pkt_dev->in6_daddr.s6_addr);
+
+ ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->in6_daddr);
+
+ if(debug)
+ printk("pktgen: dst6 set to: %s\n", buf);
+
+ i += len;
+ sprintf(pg_result, "OK: dst6=%s", buf);
+ return count;
+ }
+ if (!strcmp(name, "dst6_min")) {
+ char buf[128];
+
+ len = strn_len(&user_buffer[i], 128 - 1);
+ if (len < 0) return len;
+
+ pkt_dev->flags |= F_IPV6;
+
+ if (copy_from_user(buf, &user_buffer[i], len))
+ return -EFAULT;
+ buf[len] = 0;
+
+ scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr);
+ fmt_ip6(buf, pkt_dev->min_in6_daddr.s6_addr);
+
+ ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->min_in6_daddr);
+ if(debug)
+ printk("pktgen: dst6_min set to: %s\n", buf);
+
+ i += len;
+ sprintf(pg_result, "OK: dst6_min=%s", buf);
+ return count;
+ }
+ if (!strcmp(name, "dst6_max")) {
+ char buf[128];
+
+ len = strn_len(&user_buffer[i], 128 - 1);
+ if (len < 0) return len;
+
+ pkt_dev->flags |= F_IPV6;
+
+ if (copy_from_user(buf, &user_buffer[i], len))
+ return -EFAULT;
+ buf[len] = 0;
+
+ scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr);
+ fmt_ip6(buf, pkt_dev->max_in6_daddr.s6_addr);
+
+ if(debug)
+ printk("pktgen: dst6_max set to: %s\n", buf);
+
+ i += len;
+ sprintf(pg_result, "OK: dst6_max=%s", buf);
+ return count;
+ }
+ if (!strcmp(name, "src6")) {
+ char buf[128];
+
+ len = strn_len(&user_buffer[i], 128 - 1);
+ if (len < 0) return len;
+
+ pkt_dev->flags |= F_IPV6;
+
+ if (copy_from_user(buf, &user_buffer[i], len))
+ return -EFAULT;
+ buf[len] = 0;
+
+ scan_ip6(buf, pkt_dev->in6_saddr.s6_addr);
+ fmt_ip6(buf, pkt_dev->in6_saddr.s6_addr);
+
+ ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &pkt_dev->in6_saddr);
+
+ if(debug)
+ printk("pktgen: src6 set to: %s\n", buf);
+
+ i += len;
+ sprintf(pg_result, "OK: src6=%s", buf);
return count;
}
if (!strcmp(name, "src_min")) {
- len = strn_len(&user_buffer[i], sizeof(info->src_min) - 1);
- if (len < 0)
- return len;
- memset(info->src_min, 0, sizeof(info->src_min));
- if (copy_from_user(info->src_min, &user_buffer[i], len))
+ char buf[IP_NAME_SZ];
+ len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_min) - 1);
+ if (len < 0) { return len; }
+ if (copy_from_user(buf, &user_buffer[i], len))
return -EFAULT;
+ buf[len] = 0;
+ if (strcmp(buf, pkt_dev->src_min) != 0) {
+ memset(pkt_dev->src_min, 0, sizeof(pkt_dev->src_min));
+ strncpy(pkt_dev->src_min, buf, len);
+ pkt_dev->saddr_min = in_aton(pkt_dev->src_min);
+ pkt_dev->cur_saddr = pkt_dev->saddr_min;
+ }
if(debug)
- printk("pg: src_min set to: %s\n", info->src_min);
+ printk("pktgen: src_min set to: %s\n", pkt_dev->src_min);
i += len;
- sprintf(result, "OK: src_min=%s", info->src_min);
+ sprintf(pg_result, "OK: src_min=%s", pkt_dev->src_min);
return count;
}
if (!strcmp(name, "src_max")) {
- len = strn_len(&user_buffer[i], sizeof(info->src_max) - 1);
- if (len < 0)
- return len;
- memset(info->src_max, 0, sizeof(info->src_max));
- if (copy_from_user(info->src_max, &user_buffer[i], len))
+ char buf[IP_NAME_SZ];
+ len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_max) - 1);
+ if (len < 0) { return len; }
+ if (copy_from_user(buf, &user_buffer[i], len))
return -EFAULT;
+ buf[len] = 0;
+ if (strcmp(buf, pkt_dev->src_max) != 0) {
+ memset(pkt_dev->src_max, 0, sizeof(pkt_dev->src_max));
+ strncpy(pkt_dev->src_max, buf, len);
+ pkt_dev->saddr_max = in_aton(pkt_dev->src_max);
+ pkt_dev->cur_saddr = pkt_dev->saddr_max;
+ }
if(debug)
- printk("pg: src_max set to: %s\n", info->src_max);
+ printk("pktgen: src_max set to: %s\n", pkt_dev->src_max);
i += len;
- sprintf(result, "OK: src_max=%s", info->src_max);
+ sprintf(pg_result, "OK: src_max=%s", pkt_dev->src_max);
return count;
}
- if (!strcmp(name, "dstmac")) {
+ if (!strcmp(name, "dst_mac")) {
char *v = valstr;
- unsigned char *m = info->dst_mac;
-
+ unsigned char old_dmac[6];
+ unsigned char *m = pkt_dev->dst_mac;
+ memcpy(old_dmac, pkt_dev->dst_mac, 6);
+
len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
- if (len < 0)
- return len;
+ if (len < 0) { return len; }
memset(valstr, 0, sizeof(valstr));
- if (copy_from_user(valstr, &user_buffer[i], len))
+ if( copy_from_user(valstr, &user_buffer[i], len))
return -EFAULT;
i += len;
- for(*m = 0;*v && m < info->dst_mac + 6; v++) {
+ for(*m = 0;*v && m < pkt_dev->dst_mac + 6; v++) {
if (*v >= '0' && *v <= '9') {
*m *= 16;
*m += *v - '0';
@@ -1265,23 +1272,27 @@ static int proc_write(struct file *file, const char __user *user_buffer,
m++;
*m = 0;
}
- }
- sprintf(result, "OK: dstmac");
+ }
+
+ /* Set up Dest MAC */
+ if (memcmp(old_dmac, pkt_dev->dst_mac, 6) != 0)
+ memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, 6);
+
+ sprintf(pg_result, "OK: dstmac");
return count;
}
- if (!strcmp(name, "srcmac")) {
+ if (!strcmp(name, "src_mac")) {
char *v = valstr;
- unsigned char *m = info->src_mac;
+ unsigned char *m = pkt_dev->src_mac;
len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
- if (len < 0)
- return len;
+ if (len < 0) { return len; }
memset(valstr, 0, sizeof(valstr));
- if (copy_from_user(valstr, &user_buffer[i], len))
+ if( copy_from_user(valstr, &user_buffer[i], len))
return -EFAULT;
i += len;
- for(*m = 0;*v && m < info->src_mac + 6; v++) {
+ for(*m = 0;*v && m < pkt_dev->src_mac + 6; v++) {
if (*v >= '0' && *v <= '9') {
*m *= 16;
*m += *v - '0';
@@ -1299,135 +1310,1841 @@ static int proc_write(struct file *file, const char __user *user_buffer,
*m = 0;
}
}
- sprintf(result, "OK: srcmac");
+
+ sprintf(pg_result, "OK: srcmac");
return count;
}
- if (!strcmp(name, "inject") || !strcmp(name, "start")) {
- if (info->busy) {
- strcpy(info->result, "Already running...\n");
- }
- else {
- info->busy = 1;
- strcpy(info->result, "Starting");
- inject(info);
- info->busy = 0;
- }
+ if (!strcmp(name, "clear_counters")) {
+ pktgen_clear_counters(pkt_dev);
+ sprintf(pg_result, "OK: Clearing counters.\n");
+ return count;
+ }
+
+ if (!strcmp(name, "flows")) {
+ len = num_arg(&user_buffer[i], 10, &value);
+ if (len < 0) { return len; }
+ i += len;
+ if (value > MAX_CFLOWS)
+ value = MAX_CFLOWS;
+
+ pkt_dev->cflows = value;
+ sprintf(pg_result, "OK: flows=%u", pkt_dev->cflows);
return count;
}
- sprintf(info->result, "No such parameter \"%s\"", name);
+ if (!strcmp(name, "flowlen")) {
+ len = num_arg(&user_buffer[i], 10, &value);
+ if (len < 0) { return len; }
+ i += len;
+ pkt_dev->lflow = value;
+ sprintf(pg_result, "OK: flowlen=%u", pkt_dev->lflow);
+ return count;
+ }
+
+ sprintf(pkt_dev->result, "No such parameter \"%s\"", name);
return -EINVAL;
}
+static int proc_thread_read(char *buf , char **start, off_t offset,
+ int len, int *eof, void *data)
+{
+ char *p;
+ struct pktgen_thread *t = (struct pktgen_thread*)(data);
+ struct pktgen_dev *pkt_dev = NULL;
+
+
+ if (!t) {
+ printk("pktgen: ERROR: could not find thread in proc_thread_read\n");
+ return -EINVAL;
+ }
+
+ p = buf;
+ p += sprintf(p, "Name: %s max_before_softirq: %d\n",
+ t->name, t->max_before_softirq);
+
+ p += sprintf(p, "Running: ");
+
+ if_lock(t);
+ pkt_dev = t->if_list;
+ while (pkt_dev && pkt_dev->running) {
+ p += sprintf(p, "%s ", pkt_dev->ifname);
+ pkt_dev = pkt_dev->next;
+ }
+ p += sprintf(p, "\nStopped: ");
+
+ pkt_dev = t->if_list;
+ while (pkt_dev && !pkt_dev->running) {
+ p += sprintf(p, "%s ", pkt_dev->ifname);
+ pkt_dev = pkt_dev->next;
+ }
+
+
+ if (t->result[0])
+ p += sprintf(p, "\nResult: %s\n", t->result);
+ else
+ p += sprintf(p, "\nResult: NA\n");
+
+ *eof = 1;
+
+ if_unlock(t);
+
+ return p - buf;
+}
+
+static int proc_thread_write(struct file *file, const char *user_buffer,
+ unsigned long count, void *data)
+{
+ int i = 0, max, len, ret;
+ char name[40];
+ struct pktgen_thread *t;
+ char *pg_result;
+ unsigned long value = 0;
+
+ if (count < 1) {
+ // sprintf(pg_result, "Wrong command format");
+ return -EINVAL;
+ }
+
+ max = count - i;
+ len = count_trail_chars(&user_buffer[i], max);
+ if (len < 0)
+ return len;
+
+ i += len;
+
+ /* Read variable name */
+
+ len = strn_len(&user_buffer[i], sizeof(name) - 1);
+ if (len < 0)
+ return len;
+
+ memset(name, 0, sizeof(name));
+ if (copy_from_user(name, &user_buffer[i], len))
+ return -EFAULT;
+ i += len;
+
+ max = count -i;
+ len = count_trail_chars(&user_buffer[i], max);
+ if (len < 0)
+ return len;
+
+ i += len;
+
+ if (debug)
+ printk("pktgen: t=%s, count=%lu\n", name, count);
+
+ thread_lock();
+
+ t = (struct pktgen_thread*)(data);
+ if(!t) {
+ printk("pktgen: ERROR: No thread\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pg_result = &(t->result[0]);
+
+ if (!strcmp(name, "add_device")) {
+ char f[32];
+ memset(f, 0, 32);
+ len = strn_len(&user_buffer[i], sizeof(f) - 1);
+ if (len < 0) {
+ ret = len;
+ goto out;
+ }
+ if( copy_from_user(f, &user_buffer[i], len) )
+ return -EFAULT;
+ i += len;
+ pktgen_add_device(t, f);
+ ret = count;
+ sprintf(pg_result, "OK: add_device=%s", f);
+ goto out;
+ }
+
+ if (!strcmp(name, "rem_device_all")) {
+ t->control |= T_REMDEV;
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ/8); /* Propagate thread->control */
+ ret = count;
+ sprintf(pg_result, "OK: rem_device_all");
+ goto out;
+ }
+
+
+ if (!strcmp(name, "max_before_softirq")) {
+ len = num_arg(&user_buffer[i], 10, &value);
+ t->max_before_softirq = value;
+ ret = count;
+ sprintf(pg_result, "OK: max_before_softirq=%lu", value);
+ goto out;
+ }
+
+ ret = -EINVAL;
+ out:
+ thread_unlock();
+
+ return ret;
+}
static int create_proc_dir(void)
{
- int len;
- /* does proc_dir already exists */
- len = strlen(PG_PROC_DIR);
-
- for (proc_dir = proc_net->subdir; proc_dir;
- proc_dir=proc_dir->next) {
- if ((proc_dir->namelen == len) &&
- (! memcmp(proc_dir->name, PG_PROC_DIR, len)))
+ int len;
+ /* does proc_dir already exists */
+ len = strlen(PG_PROC_DIR);
+
+ for (pg_proc_dir = proc_net->subdir; pg_proc_dir; pg_proc_dir=pg_proc_dir->next) {
+ if ((pg_proc_dir->namelen == len) &&
+ (! memcmp(pg_proc_dir->name, PG_PROC_DIR, len)))
+ break;
+ }
+
+ if (!pg_proc_dir)
+ pg_proc_dir = create_proc_entry(PG_PROC_DIR, S_IFDIR, proc_net);
+
+ if (!pg_proc_dir)
+ return -ENODEV;
+
+ return 0;
+}
+
+static int remove_proc_dir(void)
+{
+ remove_proc_entry(PG_PROC_DIR, proc_net);
+ return 0;
+}
+
+/* Think find or remove for NN */
+static struct pktgen_dev *__pktgen_NN_threads(const char* ifname, int remove)
+{
+ struct pktgen_thread *t;
+ struct pktgen_dev *pkt_dev = NULL;
+
+ t = pktgen_threads;
+
+ while (t) {
+ pkt_dev = pktgen_find_dev(t, ifname);
+ if (pkt_dev) {
+ if(remove) {
+ if_lock(t);
+ pktgen_remove_device(t, pkt_dev);
+ if_unlock(t);
+ }
break;
+ }
+ t = t->next;
}
- if (!proc_dir)
- proc_dir = create_proc_entry(PG_PROC_DIR, S_IFDIR, proc_net);
- if (!proc_dir) return -ENODEV;
- return 1;
+ return pkt_dev;
}
-static int remove_proc_dir(void)
+static struct pktgen_dev *pktgen_NN_threads(const char* ifname, int remove)
{
- remove_proc_entry(PG_PROC_DIR, proc_net);
- return 1;
+ struct pktgen_dev *pkt_dev = NULL;
+ thread_lock();
+ pkt_dev = __pktgen_NN_threads(ifname, remove);
+ thread_unlock();
+ return pkt_dev;
}
-static int __init init(void)
+static int pktgen_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
{
- int i;
- printk(version);
- cycles_calibrate();
- if (cpu_speed == 0) {
- printk("pktgen: Error: your machine does not have working cycle counter.\n");
- return -EINVAL;
+ struct net_device *dev = (struct net_device *)(ptr);
+
+ /* It is OK that we do not hold the group lock right now,
+ * as we run under the RTNL lock.
+ */
+
+ switch (event) {
+ case NETDEV_CHANGEADDR:
+ case NETDEV_GOING_DOWN:
+ case NETDEV_DOWN:
+ case NETDEV_UP:
+ /* Ignore for now */
+ break;
+
+ case NETDEV_UNREGISTER:
+ pktgen_NN_threads(dev->name, REMOVE);
+ break;
+ };
+
+ return NOTIFY_DONE;
+}
+
+/* Associate pktgen_dev with a device. */
+
+static struct net_device* pktgen_setup_dev(struct pktgen_dev *pkt_dev) {
+ struct net_device *odev;
+
+ /* Clean old setups */
+
+ if (pkt_dev->odev) {
+ dev_put(pkt_dev->odev);
+ pkt_dev->odev = NULL;
+ }
+
+ odev = dev_get_by_name(pkt_dev->ifname);
+
+ if (!odev) {
+ printk("pktgen: no such netdevice: \"%s\"\n", pkt_dev->ifname);
+ goto out;
+ }
+ if (odev->type != ARPHRD_ETHER) {
+ printk("pktgen: not an ethernet device: \"%s\"\n", pkt_dev->ifname);
+ goto out_put;
}
+ if (!netif_running(odev)) {
+ printk("pktgen: device is down: \"%s\"\n", pkt_dev->ifname);
+ goto out_put;
+ }
+ pkt_dev->odev = odev;
+
+ return pkt_dev->odev;
- create_proc_dir();
+out_put:
+ dev_put(odev);
+out:
+ return NULL;
- for (i = 0; i<MAX_PKTGEN; i++) {
- memset(&(pginfos[i]), 0, sizeof(pginfos[i]));
- pginfos[i].pkt_size = ETH_ZLEN;
- pginfos[i].nfrags = 0;
- pginfos[i].clone_skb = clone_skb_d;
- pginfos[i].ipg = ipg_d;
- pginfos[i].count = count_d;
- pginfos[i].sofar = 0;
- pginfos[i].hh[12] = 0x08; /* fill in protocol. Rest is filled in later. */
- pginfos[i].hh[13] = 0x00;
- pginfos[i].udp_src_min = 9; /* sink NULL */
- pginfos[i].udp_src_max = 9;
- pginfos[i].udp_dst_min = 9;
- pginfos[i].udp_dst_max = 9;
+}
+
+/* Read pkt_dev from the interface and set up internal pktgen_dev
+ * structure to have the right information to create/send packets
+ */
+static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
+{
+ /* Try once more, just in case it works now. */
+ if (!pkt_dev->odev)
+ pktgen_setup_dev(pkt_dev);
+
+ if (!pkt_dev->odev) {
+ printk("pktgen: ERROR: pkt_dev->odev == NULL in setup_inject.\n");
+ sprintf(pkt_dev->result, "ERROR: pkt_dev->odev == NULL in setup_inject.\n");
+ return;
+ }
+
+ /* Default to the interface's mac if not explicitly set. */
+
+ if ((pkt_dev->src_mac[0] == 0) &&
+ (pkt_dev->src_mac[1] == 0) &&
+ (pkt_dev->src_mac[2] == 0) &&
+ (pkt_dev->src_mac[3] == 0) &&
+ (pkt_dev->src_mac[4] == 0) &&
+ (pkt_dev->src_mac[5] == 0)) {
+
+ memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, 6);
+ }
+ /* Set up Dest MAC */
+ memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, 6);
+
+ /* Set up pkt size */
+ pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size;
+
+ if(pkt_dev->flags & F_IPV6) {
+ /*
+ * Skip this automatic address setting until locks or functions
+ * gets exported
+ */
+
+#ifdef NOTNOW
+ int i, set = 0, err=1;
+ struct inet6_dev *idev;
+
+ for(i=0; i< IN6_ADDR_HSIZE; i++)
+ if(pkt_dev->cur_in6_saddr.s6_addr[i]) {
+ set = 1;
+ break;
+ }
+
+ if(!set) {
+
+ /*
+ * Use linklevel address if unconfigured.
+ *
+ * use ipv6_get_lladdr if/when it's get exported
+ */
+
+
+ read_lock(&addrconf_lock);
+ if ((idev = __in6_dev_get(pkt_dev->odev)) != NULL) {
+ struct inet6_ifaddr *ifp;
+
+ read_lock_bh(&idev->lock);
+ for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) {
+ if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) {
+ ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &ifp->addr);
+ err = 0;
+ break;
+ }
+ }
+ read_unlock_bh(&idev->lock);
+ }
+ read_unlock(&addrconf_lock);
+ if(err) printk("pktgen: ERROR: IPv6 link address not availble.\n");
+ }
+#endif
+ }
+ else {
+ pkt_dev->saddr_min = 0;
+ pkt_dev->saddr_max = 0;
+ if (strlen(pkt_dev->src_min) == 0) {
+
+ struct in_device *in_dev;
+
+ rcu_read_lock();
+ in_dev = __in_dev_get(pkt_dev->odev);
+ if (in_dev) {
+ if (in_dev->ifa_list) {
+ pkt_dev->saddr_min = in_dev->ifa_list->ifa_address;
+ pkt_dev->saddr_max = pkt_dev->saddr_min;
+ }
+ in_dev_put(in_dev);
+ }
+ rcu_read_unlock();
+ }
+ else {
+ pkt_dev->saddr_min = in_aton(pkt_dev->src_min);
+ pkt_dev->saddr_max = in_aton(pkt_dev->src_max);
+ }
+
+ pkt_dev->daddr_min = in_aton(pkt_dev->dst_min);
+ pkt_dev->daddr_max = in_aton(pkt_dev->dst_max);
+ }
+ /* Initialize current values. */
+ pkt_dev->cur_dst_mac_offset = 0;
+ pkt_dev->cur_src_mac_offset = 0;
+ pkt_dev->cur_saddr = pkt_dev->saddr_min;
+ pkt_dev->cur_daddr = pkt_dev->daddr_min;
+ pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min;
+ pkt_dev->cur_udp_src = pkt_dev->udp_src_min;
+ pkt_dev->nflows = 0;
+}
+
+static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us)
+{
+ __u64 start;
+ __u64 now;
+
+ start = now = getCurUs();
+ printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now));
+ while (now < spin_until_us) {
+ /* TODO: optimise sleeping behavior */
+ if (spin_until_us - now > (1000000/HZ)+1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1);
+ } else if (spin_until_us - now > 100) {
+ do_softirq();
+ if (!pkt_dev->running)
+ return;
+ if (need_resched())
+ schedule();
+ }
+
+ now = getCurUs();
+ }
+
+ pkt_dev->idle_acc += now - start;
+}
+
+
+/* Increment/randomize headers according to flags and current values
+ * for IP src/dest, UDP src/dst port, MAC-Addr src/dst
+ */
+static void mod_cur_headers(struct pktgen_dev *pkt_dev) {
+ __u32 imn;
+ __u32 imx;
+ int flow = 0;
+
+ if(pkt_dev->cflows) {
+ flow = pktgen_random() % pkt_dev->cflows;
- sprintf(pginfos[i].fname, "net/%s/pg%i", PG_PROC_DIR, i);
- pginfos[i].proc_ent = create_proc_entry(pginfos[i].fname, 0600, NULL);
- if (!pginfos[i].proc_ent) {
- printk("pktgen: Error: cannot create net/%s/pg procfs entry.\n", PG_PROC_DIR);
- goto cleanup_mem;
+ if (pkt_dev->flows[flow].count > pkt_dev->lflow)
+ pkt_dev->flows[flow].count = 0;
+ }
+
+
+ /* Deal with source MAC */
+ if (pkt_dev->src_mac_count > 1) {
+ __u32 mc;
+ __u32 tmp;
+
+ if (pkt_dev->flags & F_MACSRC_RND)
+ mc = pktgen_random() % (pkt_dev->src_mac_count);
+ else {
+ mc = pkt_dev->cur_src_mac_offset++;
+ if (pkt_dev->cur_src_mac_offset > pkt_dev->src_mac_count)
+ pkt_dev->cur_src_mac_offset = 0;
+ }
+
+ tmp = pkt_dev->src_mac[5] + (mc & 0xFF);
+ pkt_dev->hh[11] = tmp;
+ tmp = (pkt_dev->src_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
+ pkt_dev->hh[10] = tmp;
+ tmp = (pkt_dev->src_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
+ pkt_dev->hh[9] = tmp;
+ tmp = (pkt_dev->src_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
+ pkt_dev->hh[8] = tmp;
+ tmp = (pkt_dev->src_mac[1] + (tmp >> 8));
+ pkt_dev->hh[7] = tmp;
+ }
+
+ /* Deal with Destination MAC */
+ if (pkt_dev->dst_mac_count > 1) {
+ __u32 mc;
+ __u32 tmp;
+
+ if (pkt_dev->flags & F_MACDST_RND)
+ mc = pktgen_random() % (pkt_dev->dst_mac_count);
+
+ else {
+ mc = pkt_dev->cur_dst_mac_offset++;
+ if (pkt_dev->cur_dst_mac_offset > pkt_dev->dst_mac_count) {
+ pkt_dev->cur_dst_mac_offset = 0;
+ }
+ }
+
+ tmp = pkt_dev->dst_mac[5] + (mc & 0xFF);
+ pkt_dev->hh[5] = tmp;
+ tmp = (pkt_dev->dst_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
+ pkt_dev->hh[4] = tmp;
+ tmp = (pkt_dev->dst_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
+ pkt_dev->hh[3] = tmp;
+ tmp = (pkt_dev->dst_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
+ pkt_dev->hh[2] = tmp;
+ tmp = (pkt_dev->dst_mac[1] + (tmp >> 8));
+ pkt_dev->hh[1] = tmp;
+ }
+
+ if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
+ if (pkt_dev->flags & F_UDPSRC_RND)
+ pkt_dev->cur_udp_src = ((pktgen_random() % (pkt_dev->udp_src_max - pkt_dev->udp_src_min)) + pkt_dev->udp_src_min);
+
+ else {
+ pkt_dev->cur_udp_src++;
+ if (pkt_dev->cur_udp_src >= pkt_dev->udp_src_max)
+ pkt_dev->cur_udp_src = pkt_dev->udp_src_min;
+ }
+ }
+
+ if (pkt_dev->udp_dst_min < pkt_dev->udp_dst_max) {
+ if (pkt_dev->flags & F_UDPDST_RND) {
+ pkt_dev->cur_udp_dst = ((pktgen_random() % (pkt_dev->udp_dst_max - pkt_dev->udp_dst_min)) + pkt_dev->udp_dst_min);
+ }
+ else {
+ pkt_dev->cur_udp_dst++;
+ if (pkt_dev->cur_udp_dst >= pkt_dev->udp_dst_max)
+ pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min;
+ }
+ }
+
+ if (!(pkt_dev->flags & F_IPV6)) {
+
+ if ((imn = ntohl(pkt_dev->saddr_min)) < (imx = ntohl(pkt_dev->saddr_max))) {
+ __u32 t;
+ if (pkt_dev->flags & F_IPSRC_RND)
+ t = ((pktgen_random() % (imx - imn)) + imn);
+ else {
+ t = ntohl(pkt_dev->cur_saddr);
+ t++;
+ if (t > imx) {
+ t = imn;
+ }
+ }
+ pkt_dev->cur_saddr = htonl(t);
}
- pginfos[i].proc_ent->read_proc = proc_read;
- pginfos[i].proc_ent->write_proc = proc_write;
- pginfos[i].proc_ent->data = (void*)(long)(i);
- pginfos[i].proc_ent->owner = THIS_MODULE;
-
- sprintf(pginfos[i].busy_fname, "net/%s/pg_busy%i", PG_PROC_DIR, i);
- pginfos[i].busy_proc_ent = create_proc_entry(pginfos[i].busy_fname, 0, NULL);
- if (!pginfos[i].busy_proc_ent) {
- printk("pktgen: Error: cannot create net/%s/pg_busy procfs entry.\n", PG_PROC_DIR);
- goto cleanup_mem;
+
+ if (pkt_dev->cflows && pkt_dev->flows[flow].count != 0) {
+ pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr;
+ } else {
+
+ if ((imn = ntohl(pkt_dev->daddr_min)) < (imx = ntohl(pkt_dev->daddr_max))) {
+ __u32 t;
+ if (pkt_dev->flags & F_IPDST_RND) {
+
+ t = ((pktgen_random() % (imx - imn)) + imn);
+ t = htonl(t);
+
+ while( LOOPBACK(t) || MULTICAST(t) || BADCLASS(t) || ZERONET(t) || LOCAL_MCAST(t) ) {
+ t = ((pktgen_random() % (imx - imn)) + imn);
+ t = htonl(t);
+ }
+ pkt_dev->cur_daddr = t;
+ }
+
+ else {
+ t = ntohl(pkt_dev->cur_daddr);
+ t++;
+ if (t > imx) {
+ t = imn;
+ }
+ pkt_dev->cur_daddr = htonl(t);
+ }
+ }
+ if(pkt_dev->cflows) {
+ pkt_dev->flows[flow].cur_daddr = pkt_dev->cur_daddr;
+ pkt_dev->nflows++;
+ }
}
- pginfos[i].busy_proc_ent->read_proc = proc_busy_read;
- pginfos[i].busy_proc_ent->data = (void*)(long)(i);
}
- return 0;
+ else /* IPV6 * */
+ {
+ if(pkt_dev->min_in6_daddr.s6_addr32[0] == 0 &&
+ pkt_dev->min_in6_daddr.s6_addr32[1] == 0 &&
+ pkt_dev->min_in6_daddr.s6_addr32[2] == 0 &&
+ pkt_dev->min_in6_daddr.s6_addr32[3] == 0);
+ else {
+ int i;
+
+ /* Only random destinations yet */
+
+ for(i=0; i < 4; i++) {
+ pkt_dev->cur_in6_daddr.s6_addr32[i] =
+ ((pktgen_random() |
+ pkt_dev->min_in6_daddr.s6_addr32[i]) &
+ pkt_dev->max_in6_daddr.s6_addr32[i]);
+ }
+ }
+ }
+
+ if (pkt_dev->min_pkt_size < pkt_dev->max_pkt_size) {
+ __u32 t;
+ if (pkt_dev->flags & F_TXSIZE_RND) {
+ t = ((pktgen_random() % (pkt_dev->max_pkt_size - pkt_dev->min_pkt_size))
+ + pkt_dev->min_pkt_size);
+ }
+ else {
+ t = pkt_dev->cur_pkt_size + 1;
+ if (t > pkt_dev->max_pkt_size)
+ t = pkt_dev->min_pkt_size;
+ }
+ pkt_dev->cur_pkt_size = t;
+ }
+
+ pkt_dev->flows[flow].count++;
+}
+
+
+static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
+ struct pktgen_dev *pkt_dev)
+{
+ struct sk_buff *skb = NULL;
+ __u8 *eth;
+ struct udphdr *udph;
+ int datalen, iplen;
+ struct iphdr *iph;
+ struct pktgen_hdr *pgh = NULL;
+
+ skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC);
+ if (!skb) {
+ sprintf(pkt_dev->result, "No memory");
+ return NULL;
+ }
+
+ skb_reserve(skb, 16);
+
+ /* Reserve for ethernet and IP header */
+ eth = (__u8 *) skb_push(skb, 14);
+ iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
+ udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
+
+ /* Update any of the values, used when we're incrementing various
+ * fields.
+ */
+ mod_cur_headers(pkt_dev);
+
+ memcpy(eth, pkt_dev->hh, 12);
+ *(u16*)&eth[12] = __constant_htons(ETH_P_IP);
+
+ datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8; /* Eth + IPh + UDPh */
+ if (datalen < sizeof(struct pktgen_hdr))
+ datalen = sizeof(struct pktgen_hdr);
+
+ udph->source = htons(pkt_dev->cur_udp_src);
+ udph->dest = htons(pkt_dev->cur_udp_dst);
+ udph->len = htons(datalen + 8); /* DATA + udphdr */
+ udph->check = 0; /* No checksum */
+
+ iph->ihl = 5;
+ iph->version = 4;
+ iph->ttl = 32;
+ iph->tos = 0;
+ iph->protocol = IPPROTO_UDP; /* UDP */
+ iph->saddr = pkt_dev->cur_saddr;
+ iph->daddr = pkt_dev->cur_daddr;
+ iph->frag_off = 0;
+ iplen = 20 + 8 + datalen;
+ iph->tot_len = htons(iplen);
+ iph->check = 0;
+ iph->check = ip_fast_csum((void *) iph, iph->ihl);
+ skb->protocol = __constant_htons(ETH_P_IP);
+ skb->mac.raw = ((u8 *)iph) - 14;
+ skb->dev = odev;
+ skb->pkt_type = PACKET_HOST;
+
+ if (pkt_dev->nfrags <= 0)
+ pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
+ else {
+ int frags = pkt_dev->nfrags;
+ int i;
+
+ pgh = (struct pktgen_hdr*)(((char*)(udph)) + 8);
+
+ if (frags > MAX_SKB_FRAGS)
+ frags = MAX_SKB_FRAGS;
+ if (datalen > frags*PAGE_SIZE) {
+ skb_put(skb, datalen-frags*PAGE_SIZE);
+ datalen = frags*PAGE_SIZE;
+ }
+
+ i = 0;
+ while (datalen > 0) {
+ struct page *page = alloc_pages(GFP_KERNEL, 0);
+ skb_shinfo(skb)->frags[i].page = page;
+ skb_shinfo(skb)->frags[i].page_offset = 0;
+ skb_shinfo(skb)->frags[i].size =
+ (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
+ datalen -= skb_shinfo(skb)->frags[i].size;
+ skb->len += skb_shinfo(skb)->frags[i].size;
+ skb->data_len += skb_shinfo(skb)->frags[i].size;
+ i++;
+ skb_shinfo(skb)->nr_frags = i;
+ }
+
+ while (i < frags) {
+ int rem;
+
+ if (i == 0)
+ break;
+
+ rem = skb_shinfo(skb)->frags[i - 1].size / 2;
+ if (rem == 0)
+ break;
+
+ skb_shinfo(skb)->frags[i - 1].size -= rem;
+
+ skb_shinfo(skb)->frags[i] = skb_shinfo(skb)->frags[i - 1];
+ get_page(skb_shinfo(skb)->frags[i].page);
+ skb_shinfo(skb)->frags[i].page = skb_shinfo(skb)->frags[i - 1].page;
+ skb_shinfo(skb)->frags[i].page_offset += skb_shinfo(skb)->frags[i - 1].size;
+ skb_shinfo(skb)->frags[i].size = rem;
+ i++;
+ skb_shinfo(skb)->nr_frags = i;
+ }
+ }
+
+ /* Stamp the time, and sequence number, convert them to network byte order */
+
+ if (pgh) {
+ struct timeval timestamp;
+
+ pgh->pgh_magic = htonl(PKTGEN_MAGIC);
+ pgh->seq_num = htonl(pkt_dev->seq_num);
+
+ do_gettimeofday(&timestamp);
+ pgh->tv_sec = htonl(timestamp.tv_sec);
+ pgh->tv_usec = htonl(timestamp.tv_usec);
+ }
+ pkt_dev->seq_num++;
+
+ return skb;
+}
+
+/*
+ * scan_ip6, fmt_ip taken from dietlibc-0.21
+ * Author Felix von Leitner <felix-dietlibc@fefe.de>
+ *
+ * Slightly modified for kernel.
+ * Should be candidate for net/ipv4/utils.c
+ * --ro
+ */
+
+static unsigned int scan_ip6(const char *s,char ip[16])
+{
+ unsigned int i;
+ unsigned int len=0;
+ unsigned long u;
+ char suffix[16];
+ unsigned int prefixlen=0;
+ unsigned int suffixlen=0;
+ __u32 tmp;
+
+ for (i=0; i<16; i++) ip[i]=0;
+
+ for (;;) {
+ if (*s == ':') {
+ len++;
+ if (s[1] == ':') { /* Found "::", skip to part 2 */
+ s+=2;
+ len++;
+ break;
+ }
+ s++;
+ }
+ {
+ char *tmp;
+ u=simple_strtoul(s,&tmp,16);
+ i=tmp-s;
+ }
+
+ if (!i) return 0;
+ if (prefixlen==12 && s[i]=='.') {
+
+ /* the last 4 bytes may be written as IPv4 address */
+
+ tmp = in_aton(s);
+ memcpy((struct in_addr*)(ip+12), &tmp, sizeof(tmp));
+ return i+len;
+ }
+ ip[prefixlen++] = (u >> 8);
+ ip[prefixlen++] = (u & 255);
+ s += i; len += i;
+ if (prefixlen==16)
+ return len;
+ }
+
+/* part 2, after "::" */
+ for (;;) {
+ if (*s == ':') {
+ if (suffixlen==0)
+ break;
+ s++;
+ len++;
+ } else if (suffixlen!=0)
+ break;
+ {
+ char *tmp;
+ u=simple_strtol(s,&tmp,16);
+ i=tmp-s;
+ }
+ if (!i) {
+ if (*s) len--;
+ break;
+ }
+ if (suffixlen+prefixlen<=12 && s[i]=='.') {
+ tmp = in_aton(s);
+ memcpy((struct in_addr*)(suffix+suffixlen), &tmp, sizeof(tmp));
+ suffixlen+=4;
+ len+=strlen(s);
+ break;
+ }
+ suffix[suffixlen++] = (u >> 8);
+ suffix[suffixlen++] = (u & 255);
+ s += i; len += i;
+ if (prefixlen+suffixlen==16)
+ break;
+ }
+ for (i=0; i<suffixlen; i++)
+ ip[16-suffixlen+i] = suffix[i];
+ return len;
+}
+
+static char tohex(char hexdigit) {
+ return hexdigit>9?hexdigit+'a'-10:hexdigit+'0';
+}
+
+static int fmt_xlong(char* s,unsigned int i) {
+ char* bak=s;
+ *s=tohex((i>>12)&0xf); if (s!=bak || *s!='0') ++s;
+ *s=tohex((i>>8)&0xf); if (s!=bak || *s!='0') ++s;
+ *s=tohex((i>>4)&0xf); if (s!=bak || *s!='0') ++s;
+ *s=tohex(i&0xf);
+ return s-bak+1;
+}
+
+static unsigned int fmt_ip6(char *s,const char ip[16]) {
+ unsigned int len;
+ unsigned int i;
+ unsigned int temp;
+ unsigned int compressing;
+ int j;
+
+ len = 0; compressing = 0;
+ for (j=0; j<16; j+=2) {
+
+#ifdef V4MAPPEDPREFIX
+ if (j==12 && !memcmp(ip,V4mappedprefix,12)) {
+ inet_ntoa_r(*(struct in_addr*)(ip+12),s);
+ temp=strlen(s);
+ return len+temp;
+ }
+#endif
+ temp = ((unsigned long) (unsigned char) ip[j] << 8) +
+ (unsigned long) (unsigned char) ip[j+1];
+ if (temp == 0) {
+ if (!compressing) {
+ compressing=1;
+ if (j==0) {
+ *s++=':'; ++len;
+ }
+ }
+ } else {
+ if (compressing) {
+ compressing=0;
+ *s++=':'; ++len;
+ }
+ i = fmt_xlong(s,temp); len += i; s += i;
+ if (j<14) {
+ *s++ = ':';
+ ++len;
+ }
+ }
+ }
+ if (compressing) {
+ *s++=':'; ++len;
+ }
+ *s=0;
+ return len;
+}
+
+static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
+ struct pktgen_dev *pkt_dev)
+{
+ struct sk_buff *skb = NULL;
+ __u8 *eth;
+ struct udphdr *udph;
+ int datalen;
+ struct ipv6hdr *iph;
+ struct pktgen_hdr *pgh = NULL;
+
+ skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC);
+ if (!skb) {
+ sprintf(pkt_dev->result, "No memory");
+ return NULL;
+ }
+
+ skb_reserve(skb, 16);
+
+ /* Reserve for ethernet and IP header */
+ eth = (__u8 *) skb_push(skb, 14);
+ iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr));
+ udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
+
+
+ /* Update any of the values, used when we're incrementing various
+ * fields.
+ */
+ mod_cur_headers(pkt_dev);
+
+
+ memcpy(eth, pkt_dev->hh, 12);
+ *(u16*)&eth[12] = __constant_htons(ETH_P_IPV6);
+
+
+ datalen = pkt_dev->cur_pkt_size-14-
+ sizeof(struct ipv6hdr)-sizeof(struct udphdr); /* Eth + IPh + UDPh */
+
+ if (datalen < sizeof(struct pktgen_hdr)) {
+ datalen = sizeof(struct pktgen_hdr);
+ if (net_ratelimit())
+ printk(KERN_INFO "pktgen: increased datalen to %d\n", datalen);
+ }
+
+ udph->source = htons(pkt_dev->cur_udp_src);
+ udph->dest = htons(pkt_dev->cur_udp_dst);
+ udph->len = htons(datalen + sizeof(struct udphdr));
+ udph->check = 0; /* No checksum */
+
+ *(u32*)iph = __constant_htonl(0x60000000); /* Version + flow */
+
+ iph->hop_limit = 32;
+
+ iph->payload_len = htons(sizeof(struct udphdr) + datalen);
+ iph->nexthdr = IPPROTO_UDP;
+
+ ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr);
+ ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
+
+ skb->mac.raw = ((u8 *)iph) - 14;
+ skb->protocol = __constant_htons(ETH_P_IPV6);
+ skb->dev = odev;
+ skb->pkt_type = PACKET_HOST;
+
+ if (pkt_dev->nfrags <= 0)
+ pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
+ else {
+ int frags = pkt_dev->nfrags;
+ int i;
+
+ pgh = (struct pktgen_hdr*)(((char*)(udph)) + 8);
+
+ if (frags > MAX_SKB_FRAGS)
+ frags = MAX_SKB_FRAGS;
+ if (datalen > frags*PAGE_SIZE) {
+ skb_put(skb, datalen-frags*PAGE_SIZE);
+ datalen = frags*PAGE_SIZE;
+ }
+
+ i = 0;
+ while (datalen > 0) {
+ struct page *page = alloc_pages(GFP_KERNEL, 0);
+ skb_shinfo(skb)->frags[i].page = page;
+ skb_shinfo(skb)->frags[i].page_offset = 0;
+ skb_shinfo(skb)->frags[i].size =
+ (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
+ datalen -= skb_shinfo(skb)->frags[i].size;
+ skb->len += skb_shinfo(skb)->frags[i].size;
+ skb->data_len += skb_shinfo(skb)->frags[i].size;
+ i++;
+ skb_shinfo(skb)->nr_frags = i;
+ }
+
+ while (i < frags) {
+ int rem;
+
+ if (i == 0)
+ break;
+
+ rem = skb_shinfo(skb)->frags[i - 1].size / 2;
+ if (rem == 0)
+ break;
+
+ skb_shinfo(skb)->frags[i - 1].size -= rem;
+
+ skb_shinfo(skb)->frags[i] = skb_shinfo(skb)->frags[i - 1];
+ get_page(skb_shinfo(skb)->frags[i].page);
+ skb_shinfo(skb)->frags[i].page = skb_shinfo(skb)->frags[i - 1].page;
+ skb_shinfo(skb)->frags[i].page_offset += skb_shinfo(skb)->frags[i - 1].size;
+ skb_shinfo(skb)->frags[i].size = rem;
+ i++;
+ skb_shinfo(skb)->nr_frags = i;
+ }
+ }
+
+ /* Stamp the time, and sequence number, convert them to network byte order */
+ /* should we update cloned packets too ? */
+ if (pgh) {
+ struct timeval timestamp;
+
+ pgh->pgh_magic = htonl(PKTGEN_MAGIC);
+ pgh->seq_num = htonl(pkt_dev->seq_num);
+
+ do_gettimeofday(&timestamp);
+ pgh->tv_sec = htonl(timestamp.tv_sec);
+ pgh->tv_usec = htonl(timestamp.tv_usec);
+ }
+ pkt_dev->seq_num++;
+
+ return skb;
+}
+
+static inline struct sk_buff *fill_packet(struct net_device *odev,
+ struct pktgen_dev *pkt_dev)
+{
+ if(pkt_dev->flags & F_IPV6)
+ return fill_packet_ipv6(odev, pkt_dev);
+ else
+ return fill_packet_ipv4(odev, pkt_dev);
+}
+
+static void pktgen_clear_counters(struct pktgen_dev *pkt_dev)
+{
+ pkt_dev->seq_num = 1;
+ pkt_dev->idle_acc = 0;
+ pkt_dev->sofar = 0;
+ pkt_dev->tx_bytes = 0;
+ pkt_dev->errors = 0;
+}
+
+/* Set up structure for sending pkts, clear counters */
+
+static void pktgen_run(struct pktgen_thread *t)
+{
+ struct pktgen_dev *pkt_dev = NULL;
+ int started = 0;
+
+ PG_DEBUG(printk("pktgen: entering pktgen_run. %p\n", t));
+
+ if_lock(t);
+ for (pkt_dev = t->if_list; pkt_dev; pkt_dev = pkt_dev->next ) {
+
+ /*
+ * setup odev and create initial packet.
+ */
+ pktgen_setup_inject(pkt_dev);
+
+ if(pkt_dev->odev) {
+ pktgen_clear_counters(pkt_dev);
+ pkt_dev->running = 1; /* Cranke yeself! */
+ pkt_dev->skb = NULL;
+ pkt_dev->started_at = getCurUs();
+ pkt_dev->next_tx_us = getCurUs(); /* Transmit immediately */
+ pkt_dev->next_tx_ns = 0;
+
+ strcpy(pkt_dev->result, "Starting");
+ started++;
+ }
+ else
+ strcpy(pkt_dev->result, "Error starting");
+ }
+ if_unlock(t);
+ if(started) t->control &= ~(T_STOP);
+}
+
+static void pktgen_stop_all_threads_ifs(void)
+{
+ struct pktgen_thread *t = pktgen_threads;
+
+ PG_DEBUG(printk("pktgen: entering pktgen_stop_all_threads.\n"));
+
+ thread_lock();
+ while(t) {
+ pktgen_stop(t);
+ t = t->next;
+ }
+ thread_unlock();
+}
+
+static int running(struct pktgen_thread *t )
+{
+ struct pktgen_dev *next;
+ int res = 0;
+
+ for(next=t->if_list; next; next=next->next) {
+ if(next->running) {
+ res = 1;
+ break;
+ }
+ }
+ return res;
+}
+
+static int pktgen_wait_thread_run(struct pktgen_thread *t )
+{
+ wait_queue_head_t queue;
+
+ init_waitqueue_head(&queue);
+
+ if_lock(t);
+
+ while(running(t)) {
+ if_unlock(t);
+
+ interruptible_sleep_on_timeout(&queue, HZ/10);
+ if (signal_pending(current))
+ goto signal;
+ if_lock(t);
+ }
+ if_unlock(t);
+ return 1;
+ signal:
+ return 0;
+}
+
+static int pktgen_wait_all_threads_run(void)
+{
+ struct pktgen_thread *t = pktgen_threads;
+ int sig = 1;
+
+ while (t) {
+ sig = pktgen_wait_thread_run(t);
+ if( sig == 0 ) break;
+ thread_lock();
+ t=t->next;
+ thread_unlock();
+ }
+ if(sig == 0) {
+ thread_lock();
+ while (t) {
+ t->control |= (T_STOP);
+ t=t->next;
+ }
+ thread_unlock();
+ }
+ return sig;
+}
+
+static void pktgen_run_all_threads(void)
+{
+ struct pktgen_thread *t = pktgen_threads;
+
+ PG_DEBUG(printk("pktgen: entering pktgen_run_all_threads.\n"));
+
+ thread_lock();
+
+ while(t) {
+ t->control |= (T_RUN);
+ t = t->next;
+ }
+ thread_unlock();
+
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ/8); /* Propagate thread->control */
+
+ pktgen_wait_all_threads_run();
+}
+
+
+static void show_results(struct pktgen_dev *pkt_dev, int nr_frags)
+{
+ __u64 total_us, bps, mbps, pps, idle;
+ char *p = pkt_dev->result;
+
+ total_us = pkt_dev->stopped_at - pkt_dev->started_at;
+
+ idle = pkt_dev->idle_acc;
+
+ p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags)\n",
+ (unsigned long long) total_us,
+ (unsigned long long)(total_us - idle),
+ (unsigned long long) idle,
+ (unsigned long long) pkt_dev->sofar,
+ pkt_dev->cur_pkt_size, nr_frags);
+
+ pps = pkt_dev->sofar * USEC_PER_SEC;
+
+ while ((total_us >> 32) != 0) {
+ pps >>= 1;
+ total_us >>= 1;
+ }
+
+ do_div(pps, total_us);
+
+ bps = pps * 8 * pkt_dev->cur_pkt_size;
+
+ mbps = bps;
+ do_div(mbps, 1000000);
+ p += sprintf(p, " %llupps %lluMb/sec (%llubps) errors: %llu",
+ (unsigned long long) pps,
+ (unsigned long long) mbps,
+ (unsigned long long) bps,
+ (unsigned long long) pkt_dev->errors);
+}
+
+
+/* Set stopped-at timer, remove from running list, do counters & statistics */
+
+static int pktgen_stop_device(struct pktgen_dev *pkt_dev)
+{
+
+ if (!pkt_dev->running) {
+ printk("pktgen: interface: %s is already stopped\n", pkt_dev->ifname);
+ return -EINVAL;
+ }
+
+ if (pkt_dev->skb)
+ kfree_skb(pkt_dev->skb);
+
+ pkt_dev->stopped_at = getCurUs();
+ pkt_dev->running = 0;
+
+ show_results(pkt_dev, skb_shinfo(pkt_dev->skb)->nr_frags);
+
+ return 0;
+}
+
+static struct pktgen_dev *next_to_run(struct pktgen_thread *t )
+{
+ struct pktgen_dev *next, *best = NULL;
+
+ if_lock(t);
+
+ for(next=t->if_list; next ; next=next->next) {
+ if(!next->running) continue;
+ if(best == NULL) best=next;
+ else if ( next->next_tx_us < best->next_tx_us)
+ best = next;
+ }
+ if_unlock(t);
+ return best;
+}
+
+static void pktgen_stop(struct pktgen_thread *t) {
+ struct pktgen_dev *next = NULL;
+
+ PG_DEBUG(printk("pktgen: entering pktgen_stop.\n"));
+
+ if_lock(t);
+
+ for(next=t->if_list; next; next=next->next)
+ pktgen_stop_device(next);
+
+ if_unlock(t);
+}
+
+static void pktgen_rem_all_ifs(struct pktgen_thread *t)
+{
+ struct pktgen_dev *cur, *next = NULL;
+
+ /* Remove all devices, free mem */
+
+ if_lock(t);
+
+ for(cur=t->if_list; cur; cur=next) {
+ next = cur->next;
+ pktgen_remove_device(t, cur);
+ }
+
+ if_unlock(t);
+}
+
+static void pktgen_rem_thread(struct pktgen_thread *t)
+{
+ /* Remove from the thread list */
+
+ struct pktgen_thread *tmp = pktgen_threads;
+
+ if (strlen(t->fname))
+ remove_proc_entry(t->fname, NULL);
+
+ thread_lock();
+
+ if (tmp == t)
+ pktgen_threads = tmp->next;
+ else {
+ while (tmp) {
+ if (tmp->next == t) {
+ tmp->next = t->next;
+ t->next = NULL;
+ break;
+ }
+ tmp = tmp->next;
+ }
+ }
+ thread_unlock();
+}
+
+__inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
+{
+ struct net_device *odev = NULL;
+ __u64 idle_start = 0;
+ int ret;
+
+ odev = pkt_dev->odev;
-cleanup_mem:
- for (i = 0; i<MAX_PKTGEN; i++) {
- if (strlen(pginfos[i].fname)) {
- remove_proc_entry(pginfos[i].fname, NULL);
+ if (pkt_dev->delay_us || pkt_dev->delay_ns) {
+ u64 now;
+
+ now = getCurUs();
+ if (now < pkt_dev->next_tx_us)
+ spin(pkt_dev, pkt_dev->next_tx_us);
+
+ /* This is max DELAY, this has special meaning of
+ * "never transmit"
+ */
+ if (pkt_dev->delay_us == 0x7FFFFFFF) {
+ pkt_dev->next_tx_us = getCurUs() + pkt_dev->delay_us;
+ pkt_dev->next_tx_ns = pkt_dev->delay_ns;
+ goto out;
}
- if (strlen(pginfos[i].busy_fname)) {
- remove_proc_entry(pginfos[i].busy_fname, NULL);
+ }
+
+ if (netif_queue_stopped(odev) || need_resched()) {
+ idle_start = getCurUs();
+
+ if (!netif_running(odev)) {
+ pktgen_stop_device(pkt_dev);
+ goto out;
+ }
+ if (need_resched())
+ schedule();
+
+ pkt_dev->idle_acc += getCurUs() - idle_start;
+
+ if (netif_queue_stopped(odev)) {
+ pkt_dev->next_tx_us = getCurUs(); /* TODO */
+ pkt_dev->next_tx_ns = 0;
+ goto out; /* Try the next interface */
+ }
+ }
+
+ if (pkt_dev->last_ok || !pkt_dev->skb) {
+ if ((++pkt_dev->clone_count >= pkt_dev->clone_skb ) || (!pkt_dev->skb)) {
+ /* build a new pkt */
+ if (pkt_dev->skb)
+ kfree_skb(pkt_dev->skb);
+
+ pkt_dev->skb = fill_packet(odev, pkt_dev);
+ if (pkt_dev->skb == NULL) {
+ printk("pktgen: ERROR: couldn't allocate skb in fill_packet.\n");
+ schedule();
+ pkt_dev->clone_count--; /* back out increment, OOM */
+ goto out;
+ }
+ pkt_dev->allocated_skbs++;
+ pkt_dev->clone_count = 0; /* reset counter */
}
}
- return -ENOMEM;
+
+ spin_lock_bh(&odev->xmit_lock);
+ if (!netif_queue_stopped(odev)) {
+ u64 now;
+
+ atomic_inc(&(pkt_dev->skb->users));
+retry_now:
+ ret = odev->hard_start_xmit(pkt_dev->skb, odev);
+ if (likely(ret == NETDEV_TX_OK)) {
+ pkt_dev->last_ok = 1;
+ pkt_dev->sofar++;
+ pkt_dev->seq_num++;
+ pkt_dev->tx_bytes += pkt_dev->cur_pkt_size;
+
+ } else if (ret == NETDEV_TX_LOCKED
+ && (odev->features & NETIF_F_LLTX)) {
+ cpu_relax();
+ goto retry_now;
+ } else { /* Retry it next time */
+
+ atomic_dec(&(pkt_dev->skb->users));
+
+ if (debug && net_ratelimit())
+ printk(KERN_INFO "pktgen: Hard xmit error\n");
+
+ pkt_dev->errors++;
+ pkt_dev->last_ok = 0;
+ pkt_dev->next_tx_us = getCurUs(); /* TODO */
+ pkt_dev->next_tx_ns = 0;
+ }
+
+ pkt_dev->next_tx_us += pkt_dev->delay_us;
+ pkt_dev->next_tx_ns += pkt_dev->delay_ns;
+ if (pkt_dev->next_tx_ns > 1000) {
+ pkt_dev->next_tx_us++;
+ pkt_dev->next_tx_ns -= 1000;
+ }
+
+ now = getCurUs();
+ if (now > pkt_dev->next_tx_us) {
+ /* TODO: this code is slightly wonky. */
+ pkt_dev->errors++;
+ pkt_dev->next_tx_us = now - pkt_dev->delay_us;
+ pkt_dev->next_tx_ns = 0;
+ }
+ }
+
+ else { /* Retry it next time */
+ pkt_dev->last_ok = 0;
+ pkt_dev->next_tx_us = getCurUs(); /* TODO */
+ pkt_dev->next_tx_ns = 0;
+ }
+
+ spin_unlock_bh(&odev->xmit_lock);
+
+ /* If pkt_dev->count is zero, then run forever */
+ if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
+ if (atomic_read(&(pkt_dev->skb->users)) != 1) {
+ idle_start = getCurUs();
+ while (atomic_read(&(pkt_dev->skb->users)) != 1) {
+ if (signal_pending(current)) {
+ break;
+ }
+ schedule();
+ }
+ pkt_dev->idle_acc += getCurUs() - idle_start;
+ }
+
+ /* Done with this */
+ pktgen_stop_device(pkt_dev);
+ }
+ out:;
+ }
+
+/*
+ * Main loop of the thread goes here
+ */
+
+static void pktgen_thread_worker(struct pktgen_thread *t)
+{
+ struct pktgen_dev *pkt_dev = NULL;
+ int cpu = t->cpu;
+ sigset_t tmpsig;
+ u32 max_before_softirq;
+ u32 tx_since_softirq = 0;
+
+ daemonize("pktgen/%d", cpu);
+
+ /* Block all signals except SIGKILL, SIGSTOP and SIGTERM */
+
+ spin_lock_irq(&current->sighand->siglock);
+ tmpsig = current->blocked;
+ siginitsetinv(&current->blocked,
+ sigmask(SIGKILL) |
+ sigmask(SIGSTOP)|
+ sigmask(SIGTERM));
+
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ /* Migrate to the right CPU */
+ set_cpus_allowed(current, cpumask_of_cpu(cpu));
+ if (smp_processor_id() != cpu)
+ BUG();
+
+ init_waitqueue_head(&t->queue);
+
+ t->control &= ~(T_TERMINATE);
+ t->control &= ~(T_RUN);
+ t->control &= ~(T_STOP);
+ t->control &= ~(T_REMDEV);
+
+ t->pid = current->pid;
+
+ PG_DEBUG(printk("pktgen: starting pktgen/%d: pid=%d\n", cpu, current->pid));
+
+ max_before_softirq = t->max_before_softirq;
+
+ __set_current_state(TASK_INTERRUPTIBLE);
+ mb();
+
+ while (1) {
+
+ __set_current_state(TASK_RUNNING);
+
+ /*
+ * Get next dev to xmit -- if any.
+ */
+
+ pkt_dev = next_to_run(t);
+
+ if (pkt_dev) {
+
+ pktgen_xmit(pkt_dev);
+
+ /*
+ * We like to stay RUNNING but must also give
+ * others fair share.
+ */
+
+ tx_since_softirq += pkt_dev->last_ok;
+
+ if (tx_since_softirq > max_before_softirq) {
+ if(softirq_pending(smp_processor_id()))
+ do_softirq();
+ tx_since_softirq = 0;
+ }
+ }
+ else
+ interruptible_sleep_on_timeout(&(t->queue), HZ/10);
+
+ /*
+ * Back from sleep, either due to the timeout or signal.
+ * We check if we have any "posted" work for us.
+ */
+
+ if (t->control & T_TERMINATE || signal_pending(current))
+ /* we received a request to terminate ourself */
+ break;
+
+
+ if(t->control & T_STOP) {
+ pktgen_stop(t);
+ t->control &= ~(T_STOP);
+ }
+
+ if(t->control & T_RUN) {
+ pktgen_run(t);
+ t->control &= ~(T_RUN);
+ }
+
+ if(t->control & T_REMDEV) {
+ pktgen_rem_all_ifs(t);
+ t->control &= ~(T_REMDEV);
+ }
+
+ if (need_resched())
+ schedule();
+ }
+
+ PG_DEBUG(printk("pktgen: %s stopping all device\n", t->name));
+ pktgen_stop(t);
+
+ PG_DEBUG(printk("pktgen: %s removing all device\n", t->name));
+ pktgen_rem_all_ifs(t);
+
+ PG_DEBUG(printk("pktgen: %s removing thread.\n", t->name));
+ pktgen_rem_thread(t);
}
+static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t, const char* ifname)
+{
+ struct pktgen_dev *pkt_dev = NULL;
+ if_lock(t);
+
+ for(pkt_dev=t->if_list; pkt_dev; pkt_dev = pkt_dev->next ) {
+ if (strcmp(pkt_dev->ifname, ifname) == 0) {
+ goto out;
+ }
+ }
+ out:
+ if_unlock(t);
+ PG_DEBUG(printk("pktgen: find_dev(%s) returning %p\n", ifname,pkt_dev));
+ return pkt_dev;
+}
-static void __exit cleanup(void)
+/*
+ * Adds a dev at front of if_list.
+ */
+
+static int add_dev_to_thread(struct pktgen_thread *t, struct pktgen_dev *pkt_dev)
{
- int i;
- for (i = 0; i<MAX_PKTGEN; i++) {
- if (strlen(pginfos[i].fname)) {
- remove_proc_entry(pginfos[i].fname, NULL);
+ int rv = 0;
+
+ if_lock(t);
+
+ if (pkt_dev->pg_thread) {
+ printk("pktgen: ERROR: already assigned to a thread.\n");
+ rv = -EBUSY;
+ goto out;
+ }
+
+ L_PUSH(t->if_list, pkt_dev);
+ pkt_dev->pg_thread = t;
+ pkt_dev->running = 0;
+
+ out:
+ if_unlock(t);
+ return rv;
+}
+
+/* Called under thread lock */
+
+static int pktgen_add_device(struct pktgen_thread *t, const char* ifname)
+{
+ struct pktgen_dev *pkt_dev;
+
+ /* We don't allow a device to be on several threads */
+
+ if( (pkt_dev = __pktgen_NN_threads(ifname, FIND)) == NULL) {
+
+ pkt_dev = kmalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
+ if (!pkt_dev)
+ return -ENOMEM;
+
+ memset(pkt_dev, 0, sizeof(struct pktgen_dev));
+
+ pkt_dev->flows = vmalloc(MAX_CFLOWS*sizeof(struct flow_state));
+ if (pkt_dev->flows == NULL) {
+ kfree(pkt_dev);
+ return -ENOMEM;
}
- if (strlen(pginfos[i].busy_fname)) {
- remove_proc_entry(pginfos[i].busy_fname, NULL);
+ memset(pkt_dev->flows, 0, MAX_CFLOWS*sizeof(struct flow_state));
+
+ pkt_dev->min_pkt_size = ETH_ZLEN;
+ pkt_dev->max_pkt_size = ETH_ZLEN;
+ pkt_dev->nfrags = 0;
+ pkt_dev->clone_skb = pg_clone_skb_d;
+ pkt_dev->delay_us = pg_delay_d / 1000;
+ pkt_dev->delay_ns = pg_delay_d % 1000;
+ pkt_dev->count = pg_count_d;
+ pkt_dev->sofar = 0;
+ pkt_dev->udp_src_min = 9; /* sink port */
+ pkt_dev->udp_src_max = 9;
+ pkt_dev->udp_dst_min = 9;
+ pkt_dev->udp_dst_max = 9;
+
+ strncpy(pkt_dev->ifname, ifname, 31);
+ sprintf(pkt_dev->fname, "net/%s/%s", PG_PROC_DIR, ifname);
+
+ if (! pktgen_setup_dev(pkt_dev)) {
+ printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
+ if (pkt_dev->flows)
+ vfree(pkt_dev->flows);
+ kfree(pkt_dev);
+ return -ENODEV;
+ }
+
+ pkt_dev->proc_ent = create_proc_entry(pkt_dev->fname, 0600, 0);
+ if (!pkt_dev->proc_ent) {
+ printk("pktgen: cannot create %s procfs entry.\n", pkt_dev->fname);
+ if (pkt_dev->flows)
+ vfree(pkt_dev->flows);
+ kfree(pkt_dev);
+ return -EINVAL;
+ }
+ pkt_dev->proc_ent->read_proc = proc_if_read;
+ pkt_dev->proc_ent->write_proc = proc_if_write;
+ pkt_dev->proc_ent->data = (void*)(pkt_dev);
+ pkt_dev->proc_ent->owner = THIS_MODULE;
+
+ return add_dev_to_thread(t, pkt_dev);
+ }
+ else {
+ printk("pktgen: ERROR: interface already used.\n");
+ return -EBUSY;
+ }
+}
+
+static struct pktgen_thread *pktgen_find_thread(const char* name)
+{
+ struct pktgen_thread *t = NULL;
+
+ thread_lock();
+
+ t = pktgen_threads;
+ while (t) {
+ if (strcmp(t->name, name) == 0)
+ break;
+
+ t = t->next;
+ }
+ thread_unlock();
+ return t;
+}
+
+static int pktgen_create_thread(const char* name, int cpu)
+{
+ struct pktgen_thread *t = NULL;
+
+ if (strlen(name) > 31) {
+ printk("pktgen: ERROR: Thread name cannot be more than 31 characters.\n");
+ return -EINVAL;
+ }
+
+ if (pktgen_find_thread(name)) {
+ printk("pktgen: ERROR: thread: %s already exists\n", name);
+ return -EINVAL;
+ }
+
+ t = (struct pktgen_thread*)(kmalloc(sizeof(struct pktgen_thread), GFP_KERNEL));
+ if (!t) {
+ printk("pktgen: ERROR: out of memory, can't create new thread.\n");
+ return -ENOMEM;
+ }
+
+ memset(t, 0, sizeof(struct pktgen_thread));
+ strcpy(t->name, name);
+ spin_lock_init(&t->if_lock);
+ t->cpu = cpu;
+
+ sprintf(t->fname, "net/%s/%s", PG_PROC_DIR, t->name);
+ t->proc_ent = create_proc_entry(t->fname, 0600, 0);
+ if (!t->proc_ent) {
+ printk("pktgen: cannot create %s procfs entry.\n", t->fname);
+ kfree(t);
+ return -EINVAL;
+ }
+ t->proc_ent->read_proc = proc_thread_read;
+ t->proc_ent->write_proc = proc_thread_write;
+ t->proc_ent->data = (void*)(t);
+ t->proc_ent->owner = THIS_MODULE;
+
+ t->next = pktgen_threads;
+ pktgen_threads = t;
+
+ if (kernel_thread((void *) pktgen_thread_worker, (void *) t,
+ CLONE_FS | CLONE_FILES | CLONE_SIGHAND) < 0)
+ printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
+
+ return 0;
+}
+
+/*
+ * Removes a device from the thread if_list.
+ */
+static void _rem_dev_from_if_list(struct pktgen_thread *t, struct pktgen_dev *pkt_dev)
+{
+ struct pktgen_dev *i, *prev = NULL;
+
+ i = t->if_list;
+
+ while(i) {
+ if(i == pkt_dev) {
+ if(prev) prev->next = i->next;
+ else t->if_list = NULL;
+ break;
}
+ prev = i;
+ i=i->next;
}
+}
+
+static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *pkt_dev)
+{
+
+ PG_DEBUG(printk("pktgen: remove_device pkt_dev=%p\n", pkt_dev));
+
+ if (pkt_dev->running) {
+ printk("pktgen:WARNING: trying to remove a running interface, stopping it now.\n");
+ pktgen_stop_device(pkt_dev);
+ }
+
+ /* Dis-associate from the interface */
+
+ if (pkt_dev->odev) {
+ dev_put(pkt_dev->odev);
+ pkt_dev->odev = NULL;
+ }
+
+ /* And update the thread if_list */
+
+ _rem_dev_from_if_list(t, pkt_dev);
+
+ /* Clean up proc file system */
+
+ if (strlen(pkt_dev->fname))
+ remove_proc_entry(pkt_dev->fname, NULL);
+
+ if (pkt_dev->flows)
+ vfree(pkt_dev->flows);
+ kfree(pkt_dev);
+ return 0;
+}
+
+static int __init pg_init(void)
+{
+ int cpu;
+ printk(version);
+
+ module_fname[0] = 0;
+
+ create_proc_dir();
+
+ sprintf(module_fname, "net/%s/pgctrl", PG_PROC_DIR);
+ module_proc_ent = create_proc_entry(module_fname, 0600, 0);
+ if (!module_proc_ent) {
+ printk("pktgen: ERROR: cannot create %s procfs entry.\n", module_fname);
+ return -EINVAL;
+ }
+
+ module_proc_ent->proc_fops = &pktgen_fops;
+ module_proc_ent->data = NULL;
+
+ /* Register us to receive netdevice events */
+ register_netdevice_notifier(&pktgen_notifier_block);
+
+ for (cpu = 0; cpu < NR_CPUS ; cpu++) {
+ char buf[30];
+
+ if (!cpu_online(cpu))
+ continue;
+
+ sprintf(buf, "kpktgend_%i", cpu);
+ pktgen_create_thread(buf, cpu);
+ }
+ return 0;
+}
+
+static void __exit pg_cleanup(void)
+{
+ wait_queue_head_t queue;
+ init_waitqueue_head(&queue);
+
+ /* Stop all interfaces & threads */
+
+ while (pktgen_threads) {
+ struct pktgen_thread *t = pktgen_threads;
+ pktgen_threads->control |= (T_TERMINATE);
+
+ while( t == pktgen_threads)
+ interruptible_sleep_on_timeout(&queue, HZ);
+ }
+
+ /* Un-register us from receiving netdevice events */
+ unregister_netdevice_notifier(&pktgen_notifier_block);
+
+ /* Clean up proc file system */
+
+ remove_proc_entry(module_fname, NULL);
+
remove_proc_dir();
}
-module_init(init);
-module_exit(cleanup);
+
+module_init(pg_init);
+module_exit(pg_cleanup);
MODULE_AUTHOR("Robert Olsson <robert.olsson@its.uu.se");
MODULE_DESCRIPTION("Packet Generator tool");
MODULE_LICENSE("GPL");
-module_param(count_d, int, 0);
-module_param(ipg_d, int, 0);
-module_param(cpu_speed, int, 0);
-module_param(clone_skb_d, int, 0);
+module_param(pg_count_d, int, 0);
+module_param(pg_delay_d, int, 0);
+module_param(pg_clone_skb_d, int, 0);
+module_param(debug, int, 0);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index fe2dc396cd4d..d69ad90e5811 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -57,6 +57,11 @@ void rtnl_lock(void)
{
rtnl_shlock();
}
+
+int rtnl_lock_interruptible(void)
+{
+ return down_interruptible(&rtnl_sem);
+}
void rtnl_unlock(void)
{
@@ -119,6 +124,21 @@ void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data
memcpy(RTA_DATA(rta), data, attrlen);
}
+size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size)
+{
+ size_t ret = RTA_PAYLOAD(rta);
+ char *src = RTA_DATA(rta);
+
+ if (ret > 0 && src[ret - 1] == '\0')
+ ret--;
+ if (size > 0) {
+ size_t len = (ret >= size) ? size - 1 : ret;
+ memset(dest, 0, size);
+ memcpy(dest, src, len);
+ }
+ return ret;
+}
+
int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
{
int err = 0;
@@ -241,7 +261,7 @@ rtattr_failure:
return -1;
}
-int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
{
int idx;
int s_idx = cb->args[0];
@@ -272,13 +292,9 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
else if (ida[IFLA_IFNAME - 1]) {
char ifname[IFNAMSIZ];
- if (RTA_PAYLOAD(ida[IFLA_IFNAME - 1]) > RTA_ALIGN(sizeof(ifname)))
+ if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1],
+ IFNAMSIZ) >= IFNAMSIZ)
return -EINVAL;
-
- memset(ifname, 0, sizeof(ifname));
- memcpy(ifname, RTA_DATA(ida[IFLA_IFNAME - 1]),
- RTA_PAYLOAD(ida[IFLA_IFNAME - 1]));
- ifname[IFNAMSIZ - 1] = '\0';
dev = dev_get_by_name(ifname);
} else
return -EINVAL;
@@ -376,16 +392,10 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) {
char ifname[IFNAMSIZ];
- if (RTA_PAYLOAD(ida[IFLA_IFNAME - 1]) > RTA_ALIGN(sizeof(ifname)))
+ if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1],
+ IFNAMSIZ) >= IFNAMSIZ)
goto out;
-
- memset(ifname, 0, sizeof(ifname));
- memcpy(ifname, RTA_DATA(ida[IFLA_IFNAME - 1]),
- RTA_PAYLOAD(ida[IFLA_IFNAME - 1]));
- ifname[IFNAMSIZ - 1] = '\0';
-
err = dev_change_name(dev, ifname);
-
if (err)
goto out;
}
@@ -690,11 +700,12 @@ void __init rtnetlink_init(void)
}
EXPORT_SYMBOL(__rta_fill);
+EXPORT_SYMBOL(rtattr_strlcpy);
EXPORT_SYMBOL(rtattr_parse);
-EXPORT_SYMBOL(rtnetlink_dump_ifinfo);
EXPORT_SYMBOL(rtnetlink_links);
EXPORT_SYMBOL(rtnetlink_put_metrics);
EXPORT_SYMBOL(rtnl);
EXPORT_SYMBOL(rtnl_lock);
+EXPORT_SYMBOL(rtnl_lock_interruptible);
EXPORT_SYMBOL(rtnl_sem);
EXPORT_SYMBOL(rtnl_unlock);
diff --git a/net/core/sock.c b/net/core/sock.c
index 6d90ed0a870e..30870f938c04 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -825,8 +825,10 @@ static long sock_wait_for_wmem(struct sock * sk, long timeo)
* Generic send/receive buffer handlers
*/
-struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
- unsigned long data_len, int noblock, int *errcode)
+static struct sk_buff *sock_alloc_send_pskb(struct sock *sk,
+ unsigned long header_len,
+ unsigned long data_len,
+ int noblock, int *errcode)
{
struct sk_buff *skb;
unsigned int gfp_mask;
@@ -1084,7 +1086,7 @@ ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset, siz
* Default Socket Callbacks
*/
-void sock_def_wakeup(struct sock *sk)
+static void sock_def_wakeup(struct sock *sk)
{
read_lock(&sk->sk_callback_lock);
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
@@ -1092,7 +1094,7 @@ void sock_def_wakeup(struct sock *sk)
read_unlock(&sk->sk_callback_lock);
}
-void sock_def_error_report(struct sock *sk)
+static void sock_def_error_report(struct sock *sk)
{
read_lock(&sk->sk_callback_lock);
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
@@ -1101,7 +1103,7 @@ void sock_def_error_report(struct sock *sk)
read_unlock(&sk->sk_callback_lock);
}
-void sock_def_readable(struct sock *sk, int len)
+static void sock_def_readable(struct sock *sk, int len)
{
read_lock(&sk->sk_callback_lock);
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
@@ -1110,7 +1112,7 @@ void sock_def_readable(struct sock *sk, int len)
read_unlock(&sk->sk_callback_lock);
}
-void sock_def_write_space(struct sock *sk)
+static void sock_def_write_space(struct sock *sk)
{
read_lock(&sk->sk_callback_lock);
@@ -1129,7 +1131,7 @@ void sock_def_write_space(struct sock *sk)
read_unlock(&sk->sk_callback_lock);
}
-void sock_def_destruct(struct sock *sk)
+static void sock_def_destruct(struct sock *sk)
{
if (sk->sk_protinfo)
kfree(sk->sk_protinfo);
@@ -1368,7 +1370,6 @@ EXPORT_SYMBOL(sk_free_slab);
EXPORT_SYMBOL(sk_alloc);
EXPORT_SYMBOL(sk_free);
EXPORT_SYMBOL(sk_send_sigurg);
-EXPORT_SYMBOL(sock_alloc_send_pskb);
EXPORT_SYMBOL(sock_alloc_send_skb);
EXPORT_SYMBOL(sock_init_data);
EXPORT_SYMBOL(sock_kfree_s);
diff --git a/net/core/wireless.c b/net/core/wireless.c
index e6d85cf63572..750cc5daeb03 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -304,7 +304,7 @@ static const int standard_event_num = (sizeof(standard_event) /
sizeof(struct iw_ioctl_description));
/* Size (in bytes) of the various private data types */
-const char iw_priv_type_size[] = {
+static const char iw_priv_type_size[] = {
0, /* IW_PRIV_TYPE_NONE */
1, /* IW_PRIV_TYPE_BYTE */
1, /* IW_PRIV_TYPE_CHAR */
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 381df28b53e1..056bac657275 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -151,7 +151,7 @@ static void dn_keepalive(struct sock *sk);
static kmem_cache_t *dn_sk_cachep;
static struct proto_ops dn_proto_ops;
-static rwlock_t dn_hash_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(dn_hash_lock);
static struct hlist_head dn_sk_hash[DN_SK_HASH_SIZE];
static struct hlist_head dn_wild_sk;
@@ -246,7 +246,7 @@ static void dn_unhash_sock_bh(struct sock *sk)
write_unlock_bh(&dn_hash_lock);
}
-struct hlist_head *listen_hash(struct sockaddr_dn *addr)
+static struct hlist_head *listen_hash(struct sockaddr_dn *addr)
{
int i;
unsigned hash = addr->sdn_objnum;
@@ -447,7 +447,7 @@ static void dn_destruct(struct sock *sk)
dst_release(xchg(&sk->sk_dst_cache, NULL));
}
-struct sock *dn_alloc_sock(struct socket *sock, int gfp)
+static struct sock *dn_alloc_sock(struct socket *sock, int gfp)
{
struct dn_scp *scp;
struct sock *sk = sk_alloc(PF_DECnet, gfp, sizeof(struct dn_sock),
@@ -578,7 +578,6 @@ int dn_destroy_timer(struct sock *sk)
if (sk->sk_socket)
return 0;
- dn_stop_fast_timer(sk); /* unlikely, but possible that this is runninng */
if ((jiffies - scp->stamp) >= (HZ * decnet_time_wait)) {
dn_unhash_sock(sk);
sock_put(sk);
@@ -631,7 +630,6 @@ disc_reject:
default:
printk(KERN_DEBUG "DECnet: dn_destroy_sock passed socket in invalid state\n");
case DN_O:
- dn_stop_fast_timer(sk);
dn_stop_slow_timer(sk);
dn_unhash_sock_bh(sk);
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index aba84350596c..c2a0346f423b 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -65,7 +65,7 @@ extern struct neigh_table dn_neigh_table;
*/
dn_address decnet_address = 0;
-static rwlock_t dndev_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(dndev_lock);
static struct net_device *decnet_default_device;
static struct notifier_block *dnaddr_chain;
@@ -662,7 +662,7 @@ static int dn_dev_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a
for(ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next) {
void *tmp = rta[IFA_LOCAL-1];
if ((tmp && memcmp(RTA_DATA(tmp), &ifa->ifa_local, 2)) ||
- (rta[IFA_LABEL-1] && strcmp(RTA_DATA(rta[IFA_LABEL-1]), ifa->ifa_label)))
+ (rta[IFA_LABEL-1] && rtattr_strcmp(rta[IFA_LABEL-1], ifa->ifa_label)))
continue;
dn_dev_del_ifa(dn_db, ifap, 1);
@@ -705,7 +705,7 @@ static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a
ifa->ifa_scope = ifm->ifa_scope;
ifa->ifa_dev = dn_db;
if (rta[IFA_LABEL-1])
- memcpy(ifa->ifa_label, RTA_DATA(rta[IFA_LABEL-1]), IFNAMSIZ);
+ rtattr_strlcpy(ifa->ifa_label, rta[IFA_LABEL-1], IFNAMSIZ);
else
memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 3aaa8cd30c53..9934b25720e4 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -57,10 +57,9 @@
extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
-static spinlock_t dn_fib_multipath_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(dn_fib_multipath_lock);
static struct dn_fib_info *dn_fib_info_list;
-static rwlock_t dn_fib_info_lock = RW_LOCK_UNLOCKED;
-int dn_fib_info_cnt;
+static DEFINE_RWLOCK(dn_fib_info_lock);
static struct
{
@@ -93,7 +92,6 @@ void dn_fib_free_info(struct dn_fib_info *fi)
dev_put(nh->nh_dev);
nh->nh_dev = NULL;
} endfor_nexthops(fi);
- dn_fib_info_cnt--;
kfree(fi);
}
@@ -388,7 +386,6 @@ link_it:
if (dn_fib_info_list)
dn_fib_info_list->fib_prev = fi;
dn_fib_info_list = fi;
- dn_fib_info_cnt++;
write_unlock(&dn_fib_info_lock);
return fi;
@@ -486,18 +483,6 @@ void dn_fib_select_multipath(const struct flowi *fl, struct dn_fib_res *res)
}
-/*
- * Punt to user via netlink for example, but for now
- * we just drop it.
- */
-int dn_fib_rt_message(struct sk_buff *skb)
-{
- kfree_skb(skb);
-
- return 0;
-}
-
-
static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta)
{
int i;
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 6128a02610c4..f6dfe96f45b7 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -355,14 +355,6 @@ static int dn_phase3_output(struct sk_buff *skb)
* basically does a neigh_lookup(), but without comparing the device
* field. This is required for the On-Ethernet cache
*/
-/*
- * Any traffic on a pointopoint link causes the timer to be reset
- * for the entry in the neighbour table.
- */
-void dn_neigh_pointopoint_notify(struct sk_buff *skb)
-{
- return;
-}
/*
* Pointopoint link receives a hello message
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index cafbe0069e6c..309a8b317a9e 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -99,9 +99,9 @@ extern struct neigh_table dn_neigh_table;
static unsigned char dn_hiord_addr[6] = {0xAA,0x00,0x04,0x00,0x00,0x00};
-int dn_rt_min_delay = 2 * HZ;
-int dn_rt_max_delay = 10 * HZ;
-int dn_rt_mtu_expires = 10 * 60 * HZ;
+static const int dn_rt_min_delay = 2 * HZ;
+static const int dn_rt_max_delay = 10 * HZ;
+static const int dn_rt_mtu_expires = 10 * 60 * HZ;
static unsigned long dn_rt_deadline;
@@ -336,7 +336,7 @@ nothing_to_declare:
}
}
-static spinlock_t dn_rt_flush_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(dn_rt_flush_lock);
void dn_rt_cache_flush(int delay)
{
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 17cc9c356ba2..597587d170d8 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -68,7 +68,7 @@ static struct dn_fib_rule default_rule = {
};
static struct dn_fib_rule *dn_fib_rules = &default_rule;
-static rwlock_t dn_fib_rules_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(dn_fib_rules_lock);
int dn_fib_rtm_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
@@ -88,7 +88,7 @@ int dn_fib_rtm_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
#endif
(!rtm->rtm_type || rtm->rtm_type == r->r_action) &&
(!rta[RTA_PRIORITY-1] || memcmp(RTA_DATA(rta[RTA_PRIORITY-1]), &r->r_preference, 4) == 0) &&
- (!rta[RTA_IIF-1] || strcmp(RTA_DATA(rta[RTA_IIF-1]), r->r_ifname) == 0) &&
+ (!rta[RTA_IIF-1] || rtattr_strcmp(rta[RTA_IIF-1], r->r_ifname) == 0) &&
(!rtm->rtm_table || (r && rtm->rtm_table == r->r_table))) {
err = -EPERM;
@@ -170,8 +170,7 @@ int dn_fib_rtm_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
new_r->r_table = table_id;
if (rta[RTA_IIF-1]) {
struct net_device *dev;
- memcpy(new_r->r_ifname, RTA_DATA(rta[RTA_IIF-1]), IFNAMSIZ);
- new_r->r_ifname[IFNAMSIZ-1] = 0;
+ rtattr_strlcpy(new_r->r_ifname, rta[RTA_IIF-1], IFNAMSIZ);
new_r->r_ifindex = -1;
dev = dev_get_by_name(new_r->r_ifname);
if (dev) {
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index 7255fb280a43..dad5603912be 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -76,7 +76,7 @@ for( ; ((f) = *(fp)) != NULL && dn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_n
#define RT_TABLE_MIN 1
-static rwlock_t dn_fib_tables_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(dn_fib_tables_lock);
struct dn_fib_table *dn_fib_tables[RT_TABLE_MAX + 1];
static kmem_cache_t *dn_hash_kmem;
diff --git a/net/decnet/dn_timer.c b/net/decnet/dn_timer.c
index 0aae8a633907..09825711d58a 100644
--- a/net/decnet/dn_timer.c
+++ b/net/decnet/dn_timer.c
@@ -27,11 +27,9 @@
#include <net/dn.h>
/*
- * Fast timer is for delayed acks (200mS max)
* Slow timer is for everything else (n * 500mS)
*/
-#define FAST_INTERVAL (HZ/5)
#define SLOW_INTERVAL (HZ/2)
static void dn_slow_timer(unsigned long arg);
@@ -109,48 +107,3 @@ out:
bh_unlock_sock(sk);
sock_put(sk);
}
-
-static void dn_fast_timer(unsigned long arg)
-{
- struct sock *sk = (struct sock *)arg;
- struct dn_scp *scp = DN_SK(sk);
-
- bh_lock_sock(sk);
- if (sock_owned_by_user(sk)) {
- scp->delack_timer.expires = jiffies + HZ / 20;
- add_timer(&scp->delack_timer);
- goto out;
- }
-
- scp->delack_pending = 0;
-
- if (scp->delack_fxn)
- scp->delack_fxn(sk);
-out:
- bh_unlock_sock(sk);
-}
-
-void dn_start_fast_timer(struct sock *sk)
-{
- struct dn_scp *scp = DN_SK(sk);
-
- if (!scp->delack_pending) {
- scp->delack_pending = 1;
- init_timer(&scp->delack_timer);
- scp->delack_timer.expires = jiffies + FAST_INTERVAL;
- scp->delack_timer.data = (unsigned long)sk;
- scp->delack_timer.function = dn_fast_timer;
- add_timer(&scp->delack_timer);
- }
-}
-
-void dn_stop_fast_timer(struct sock *sk)
-{
- struct dn_scp *scp = DN_SK(sk);
-
- if (scp->delack_pending) {
- scp->delack_pending = 0;
- del_timer(&scp->delack_timer);
- }
-}
-
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index 03890eeb7fc4..06f5460516e0 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -47,7 +47,7 @@
static struct proto_ops econet_ops;
static struct hlist_head econet_sklist;
-static rwlock_t econet_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(econet_lock);
/* Since there are only 256 possible network numbers (or fewer, depends
how you count) it makes sense to use a simple lookup table. */
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 4ec92ccca253..859f67245932 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -125,7 +125,7 @@ extern void ip_mc_drop_socket(struct sock *sk);
* build a new socket.
*/
static struct list_head inetsw[SOCK_MAX];
-static spinlock_t inetsw_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(inetsw_lock);
/* New destruction routine */
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 7b6054d49271..d9559e8ed00a 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -399,7 +399,7 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
memcmp(RTA_DATA(rta[IFA_LOCAL - 1]),
&ifa->ifa_local, 4)) ||
(rta[IFA_LABEL - 1] &&
- strcmp(RTA_DATA(rta[IFA_LABEL - 1]), ifa->ifa_label)) ||
+ rtattr_strcmp(rta[IFA_LABEL - 1], ifa->ifa_label)) ||
(rta[IFA_ADDRESS - 1] &&
(ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
!inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]),
@@ -456,7 +456,7 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
in_dev_hold(in_dev);
ifa->ifa_dev = in_dev;
if (rta[IFA_LABEL - 1])
- memcpy(ifa->ifa_label, RTA_DATA(rta[IFA_LABEL - 1]), IFNAMSIZ);
+ rtattr_strlcpy(ifa->ifa_label, rta[IFA_LABEL - 1], IFNAMSIZ);
else
memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index f13ba990f419..688e551cc5af 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -92,7 +92,7 @@ static inline u32 fz_key(u32 dst, struct fn_zone *fz)
return dst & FZ_MASK(fz);
}
-static rwlock_t fib_hash_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(fib_hash_lock);
#define FZ_MAX_DIVISOR ((PAGE_SIZE<<MAX_ORDER) / sizeof(struct hlist_head))
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index f6675eef21cf..39d0aadb9a2a 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -99,7 +99,7 @@ static struct fib_rule local_rule = {
};
static struct fib_rule *fib_rules = &local_rule;
-static rwlock_t fib_rules_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(fib_rules_lock);
int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
@@ -119,7 +119,7 @@ int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
#endif
(!rtm->rtm_type || rtm->rtm_type == r->r_action) &&
(!rta[RTA_PRIORITY-1] || memcmp(RTA_DATA(rta[RTA_PRIORITY-1]), &r->r_preference, 4) == 0) &&
- (!rta[RTA_IIF-1] || strcmp(RTA_DATA(rta[RTA_IIF-1]), r->r_ifname) == 0) &&
+ (!rta[RTA_IIF-1] || rtattr_strcmp(rta[RTA_IIF-1], r->r_ifname) == 0) &&
(!rtm->rtm_table || (r && rtm->rtm_table == r->r_table))) {
err = -EPERM;
if (r == &local_rule)
@@ -209,8 +209,7 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
new_r->r_table = table_id;
if (rta[RTA_IIF-1]) {
struct net_device *dev;
- memcpy(new_r->r_ifname, RTA_DATA(rta[RTA_IIF-1]), IFNAMSIZ);
- new_r->r_ifname[IFNAMSIZ-1] = 0;
+ rtattr_strlcpy(new_r->r_ifname, rta[RTA_IIF-1], IFNAMSIZ);
new_r->r_ifindex = -1;
dev = __dev_get_by_name(new_r->r_ifname);
if (dev)
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 68d48c21511e..edf74c31e2cd 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -47,7 +47,7 @@
#define FSprintk(a...)
-static rwlock_t fib_info_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(fib_info_lock);
static struct hlist_head *fib_info_hash;
static struct hlist_head *fib_info_laddrhash;
static unsigned int fib_hash_size;
@@ -59,7 +59,7 @@ static struct hlist_head fib_info_devhash[DEVINDEX_HASHSIZE];
#ifdef CONFIG_IP_ROUTE_MULTIPATH
-static spinlock_t fib_multipath_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(fib_multipath_lock);
#define for_nexthops(fi) { int nhsel; const struct fib_nh * nh; \
for (nhsel=0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index d7da79d5b205..9942d1146828 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -70,7 +70,7 @@
*/
/* Exported for inet_getid inline function. */
-spinlock_t inet_peer_idlock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(inet_peer_idlock);
static kmem_cache_t *peer_cachep;
@@ -82,7 +82,7 @@ static struct inet_peer peer_fake_node = {
};
#define peer_avl_empty (&peer_fake_node)
static struct inet_peer *peer_root = peer_avl_empty;
-static rwlock_t peer_pool_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(peer_pool_lock);
#define PEER_MAXDEPTH 40 /* sufficient for about 2^27 nodes */
static volatile int peer_total;
@@ -95,7 +95,7 @@ int inet_peer_maxttl = 10 * 60 * HZ; /* usual time to live: 10 min */
/* Exported for inet_putpeer inline function. */
struct inet_peer *inet_peer_unused_head,
**inet_peer_unused_tailp = &inet_peer_unused_head;
-spinlock_t inet_peer_unused_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(inet_peer_unused_lock);
#define PEER_MAX_CLEANUP_WORK 30
static void peer_check_expire(unsigned long dummy);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 441a522ec1df..6f22b22edaae 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -99,7 +99,7 @@ struct ipq {
/* Per-bucket lock is easy to add now. */
static struct ipq *ipq_hash[IPQ_HASHSZ];
-static rwlock_t ipfrag_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ipfrag_lock);
static u32 ipfrag_hash_rnd;
static LIST_HEAD(ipq_lru_list);
int ip_frag_nqueues = 0;
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index ce1e88c4c248..1404a96ae350 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -152,7 +152,7 @@ static struct ip_tunnel *tunnels[4][HASH_SIZE];
#define tunnels_l (tunnels[1])
#define tunnels_wc (tunnels[0])
-static rwlock_t ipgre_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ipgre_lock);
/* Given src, dst and key, find appropriate for input tunnel. */
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 5b242e1f6045..48f9cfbcc6a5 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -186,7 +186,7 @@ int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
sent to multicast group to reach destination designated router.
*/
struct ip_ra_chain *ip_ra_chain;
-rwlock_t ip_ra_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(ip_ra_lock);
int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *))
{
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 86ade3d3e970..0b64c7127b11 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -152,7 +152,7 @@ static char user_dev_name[IFNAMSIZ] __initdata = { 0, };
static int ic_proto_have_if __initdata = 0;
#ifdef IPCONFIG_DYNAMIC
-static spinlock_t ic_recv_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ic_recv_lock);
static volatile int ic_got_reply __initdata = 0; /* Proto(s) that replied */
#endif
#ifdef IPCONFIG_DHCP
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 1c1c2e1d429b..f91663c399ac 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -132,7 +132,7 @@ static struct ip_tunnel *tunnels_l[HASH_SIZE];
static struct ip_tunnel *tunnels_wc[1];
static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l };
-static rwlock_t ipip_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ipip_lock);
static struct ip_tunnel * ipip_tunnel_lookup(u32 remote, u32 local)
{
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 9079766beae9..2568fe28dcd5 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -73,7 +73,7 @@ static struct sock *mroute_socket;
Note that the changes are semaphored via rtnl_lock.
*/
-static rwlock_t mrt_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(mrt_lock);
/*
* Multicast router control variables
@@ -93,7 +93,7 @@ static struct mfc_cache *mfc_unres_queue; /* Queue of unresolved entries */
static atomic_t cache_resolve_queue_len; /* Size of unresolved */
/* Special spinlock for queue of unresolved entries */
-static spinlock_t mfc_unres_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(mfc_unres_lock);
/* We return to original Alan's scheme. Hash table of resolved
entries is changed only in process context and protected
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 168e5b342110..f1230075e8a3 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -57,7 +57,6 @@ EXPORT_SYMBOL(ip_vs_conn_put);
#ifdef CONFIG_IP_VS_DEBUG
EXPORT_SYMBOL(ip_vs_get_debug_level);
#endif
-EXPORT_SYMBOL(check_for_ip_vs_out);
EXPORT_SYMBOL(ip_vs_make_skb_writable);
@@ -835,31 +834,6 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
/*
- * Check if the packet is for VS/NAT connections, then send it
- * immediately.
- * Called by ip_fw_compact to detect packets for VS/NAT before
- * they are changed by ipchains masquerading code.
- */
-unsigned int
-check_for_ip_vs_out(struct sk_buff **pskb, int (*okfn)(struct sk_buff *))
-{
- unsigned int ret;
-
- ret = ip_vs_out(NF_IP_FORWARD, pskb, NULL, NULL, NULL);
- if (ret != NF_ACCEPT) {
- return ret;
- } else {
- /* send the packet immediately if it is already mangled
- by ip_vs_out */
- if ((*pskb)->nfcache & NFC_IPVS_PROPERTY) {
- (*okfn)(*pskb);
- return NF_STOLEN;
- }
- }
- return NF_ACCEPT;
-}
-
-/*
* Handle ICMP messages in the outside-to-inside direction (incoming).
* Find any that might be relevant, check against existing connections,
* forward to the right destination host if relevant.
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index dc00cccca423..102154138dbf 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -45,19 +45,19 @@
static DECLARE_MUTEX(__ip_vs_mutex);
/* lock for service table */
-static rwlock_t __ip_vs_svc_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(__ip_vs_svc_lock);
/* lock for table with the real services */
-static rwlock_t __ip_vs_rs_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(__ip_vs_rs_lock);
/* lock for state and timeout tables */
-static rwlock_t __ip_vs_securetcp_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(__ip_vs_securetcp_lock);
/* lock for drop entry handling */
-static spinlock_t __ip_vs_dropentry_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(__ip_vs_dropentry_lock);
/* lock for drop packet handling */
-static spinlock_t __ip_vs_droppacket_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(__ip_vs_droppacket_lock);
/* 1/rate drop and drop-entry variables */
int ip_vs_drop_rate = 0;
diff --git a/net/ipv4/ipvs/ip_vs_est.c b/net/ipv4/ipvs/ip_vs_est.c
index 3af1fd1473f4..67b3e2fc1fa1 100644
--- a/net/ipv4/ipvs/ip_vs_est.c
+++ b/net/ipv4/ipvs/ip_vs_est.c
@@ -62,7 +62,7 @@ struct ip_vs_estimator
static struct ip_vs_estimator *est_list = NULL;
-static rwlock_t est_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(est_lock);
static struct timer_list est_timer;
static void estimation_timer(unsigned long arg)
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
index bd8f898bfe19..e65de675da74 100644
--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c
@@ -510,7 +510,7 @@ tcp_state_transition(struct ip_vs_conn *cp, int direction,
#define TCP_APP_TAB_MASK (TCP_APP_TAB_SIZE - 1)
static struct list_head tcp_apps[TCP_APP_TAB_SIZE];
-static spinlock_t tcp_app_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(tcp_app_lock);
static inline __u16 tcp_app_hashkey(__u16 port)
{
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
index 443ec4578d40..8ae5f2e0aefa 100644
--- a/net/ipv4/ipvs/ip_vs_proto_udp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_udp.c
@@ -277,7 +277,7 @@ udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp)
#define UDP_APP_TAB_MASK (UDP_APP_TAB_SIZE - 1)
static struct list_head udp_apps[UDP_APP_TAB_SIZE];
-static spinlock_t udp_app_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(udp_app_lock);
static inline __u16 udp_app_hashkey(__u16 port)
{
diff --git a/net/ipv4/ipvs/ip_vs_sched.c b/net/ipv4/ipvs/ip_vs_sched.c
index 34e903ca789b..0f7c56a225bd 100644
--- a/net/ipv4/ipvs/ip_vs_sched.c
+++ b/net/ipv4/ipvs/ip_vs_sched.c
@@ -33,7 +33,7 @@
static LIST_HEAD(ip_vs_schedulers);
/* lock for service table */
-static rwlock_t __ip_vs_sched_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(__ip_vs_sched_lock);
/*
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index a7389993318c..da30bebbddc8 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -119,11 +119,11 @@ struct ip_vs_sync_buff {
/* the sync_buff list head and the lock */
static LIST_HEAD(ip_vs_sync_queue);
-static spinlock_t ip_vs_sync_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ip_vs_sync_lock);
/* current sync_buff for accepting new conn entries */
static struct ip_vs_sync_buff *curr_sb = NULL;
-static spinlock_t curr_sb_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(curr_sb_lock);
/* ipvs sync daemon state */
volatile int ip_vs_sync_state = IP_VS_STATE_NONE;
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index e5109f33c9f0..bc5fc5f76937 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1150,7 +1150,8 @@ void arpt_unregister_target(struct arpt_target *target)
up(&arpt_mutex);
}
-int arpt_register_table(struct arpt_table *table)
+int arpt_register_table(struct arpt_table *table,
+ const struct arpt_replace *repl)
{
int ret;
struct arpt_table_info *newinfo;
@@ -1158,18 +1159,18 @@ int arpt_register_table(struct arpt_table *table)
= { 0, 0, 0, { 0 }, { 0 }, { } };
newinfo = vmalloc(sizeof(struct arpt_table_info)
- + SMP_ALIGN(table->table->size) * NR_CPUS);
+ + SMP_ALIGN(repl->size) * NR_CPUS);
if (!newinfo) {
ret = -ENOMEM;
return ret;
}
- memcpy(newinfo->entries, table->table->entries, table->table->size);
+ memcpy(newinfo->entries, repl->entries, repl->size);
ret = translate_table(table->name, table->valid_hooks,
- newinfo, table->table->size,
- table->table->num_entries,
- table->table->hook_entry,
- table->table->underflow);
+ newinfo, repl->size,
+ repl->num_entries,
+ repl->hook_entry,
+ repl->underflow);
duprintf("arpt_register_table: translate table gives %d\n", ret);
if (ret != 0) {
vfree(newinfo);
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 70a07a67100d..0d759f5a4ef0 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -141,7 +141,6 @@ static struct
static struct arpt_table packet_filter = {
.name = "filter",
- .table = &initial_table.repl,
.valid_hooks = FILTER_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.private = NULL,
@@ -184,7 +183,7 @@ static int __init init(void)
int ret, i;
/* Register table */
- ret = arpt_register_table(&packet_filter);
+ ret = arpt_register_table(&packet_filter, &initial_table.repl);
if (ret < 0)
return ret;
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index ddcd7fc8cc0f..80773588d8ad 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -35,32 +35,13 @@
#define NAT_VALID_HOOKS ((1<<NF_IP_PRE_ROUTING) | (1<<NF_IP_POST_ROUTING) | (1<<NF_IP_LOCAL_OUT))
-/* Standard entry. */
-struct ipt_standard
-{
- struct ipt_entry entry;
- struct ipt_standard_target target;
-};
-
-struct ipt_error_target
-{
- struct ipt_entry_target target;
- char errorname[IPT_FUNCTION_MAXNAMELEN];
-};
-
-struct ipt_error
-{
- struct ipt_entry entry;
- struct ipt_error_target target;
-};
-
static struct
{
struct ipt_replace repl;
struct ipt_standard entries[3];
struct ipt_error term;
-} nat_initial_table = {
- { "nat", NAT_VALID_HOOKS, 4,
+} nat_initial_table __initdata
+= { { "nat", NAT_VALID_HOOKS, 4,
sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
{ [NF_IP_PRE_ROUTING] = 0,
[NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
@@ -110,7 +91,6 @@ static struct
static struct ipt_table nat_table = {
.name = "nat",
- .table = &nat_initial_table.repl,
.valid_hooks = NAT_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.me = THIS_MODULE,
@@ -285,7 +265,7 @@ int __init ip_nat_rule_init(void)
{
int ret;
- ret = ipt_register_table(&nat_table);
+ ret = ipt_register_table(&nat_table, &nat_initial_table.repl);
if (ret != 0)
return ret;
ret = ipt_register_target(&ipt_snat_reg);
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index 32d6e966aa13..b18e79332169 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -65,7 +65,7 @@ MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
#define NOCT1(n) (u_int8_t )((n) & 0xff)
static int debug;
-static spinlock_t snmp_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(snmp_lock);
/*
* Application layer address mapping mimics the NAT mapping, but
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index d51e2057226f..a9aa12cc83bb 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -55,7 +55,7 @@ typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long);
static unsigned char copy_mode = IPQ_COPY_NONE;
static unsigned int queue_maxlen = IPQ_QMAX_DEFAULT;
-static rwlock_t queue_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(queue_lock);
static int peer_pid;
static unsigned int copy_range;
static unsigned int queue_total;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 7eebab02e08c..3d13400af58d 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -430,62 +430,63 @@ static inline struct ipt_table *find_table_lock(const char *name)
return NULL;
}
-/* Find match, grabs mutex & ref. Returns ERR_PTR() on error. */
-static inline struct ipt_match *find_match_lock(const char *name, u8 revision)
+/* Find match, grabs ref. Returns ERR_PTR() on error. */
+static inline struct ipt_match *find_match(const char *name, u8 revision)
{
struct ipt_match *m;
- int found = 0;
+ int err = 0;
if (down_interruptible(&ipt_mutex) != 0)
return ERR_PTR(-EINTR);
list_for_each_entry(m, &ipt_match, list) {
if (strcmp(m->name, name) == 0) {
- found = 1;
if (m->revision == revision) {
- if (!try_module_get(m->me))
- found = 0;
- else
+ if (try_module_get(m->me)) {
+ up(&ipt_mutex);
return m;
- }
+ }
+ } else
+ err = -EPROTOTYPE; /* Found something. */
}
}
up(&ipt_mutex);
-
- /* Not found at all? NULL so try_then_request_module loads module. */
- if (!found)
- return NULL;
-
- return ERR_PTR(-EPROTOTYPE);
+ return ERR_PTR(err);
}
-/* Find target, grabs mutex & ref. Returns ERR_PTR() on error. */
-static inline struct ipt_target *find_target_lock(const char *name, u8 revision)
+/* Find target, grabs ref. Returns ERR_PTR() on error. */
+static inline struct ipt_target *find_target(const char *name, u8 revision)
{
struct ipt_target *t;
- int found = 0;
+ int err = 0;
if (down_interruptible(&ipt_mutex) != 0)
return ERR_PTR(-EINTR);
list_for_each_entry(t, &ipt_target, list) {
if (strcmp(t->name, name) == 0) {
- found = 1;
if (t->revision == revision) {
- if (!try_module_get(t->me))
- found = 0;
- else
+ if (try_module_get(t->me)) {
+ up(&ipt_mutex);
return t;
- }
+ }
+ } else
+ err = -EPROTOTYPE; /* Found something. */
}
}
up(&ipt_mutex);
+ return ERR_PTR(err);
+}
- /* Not found at all? NULL so try_then_request_module loads module. */
- if (!found)
- return NULL;
+struct ipt_target *ipt_find_target(const char *name, u8 revision)
+{
+ struct ipt_target *target;
- return ERR_PTR(-EPROTOTYPE);
+ target = try_then_request_module(find_target(name, revision),
+ "ipt_%s", name);
+ if (IS_ERR(target) || !target)
+ return NULL;
+ return target;
}
static int match_revfn(const char *name, u8 revision, int *bestp)
@@ -708,15 +709,14 @@ check_match(struct ipt_entry_match *m,
{
struct ipt_match *match;
- match = try_then_request_module(find_match_lock(m->u.user.name,
- m->u.user.revision),
+ match = try_then_request_module(find_match(m->u.user.name,
+ m->u.user.revision),
"ipt_%s", m->u.user.name);
if (IS_ERR(match) || !match) {
duprintf("check_match: `%s' not found\n", m->u.user.name);
return match ? PTR_ERR(match) : -ENOENT;
}
m->u.kernel.match = match;
- up(&ipt_mutex);
if (m->u.kernel.match->checkentry
&& !m->u.kernel.match->checkentry(name, ip, m->data,
@@ -754,8 +754,8 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
goto cleanup_matches;
t = ipt_get_target(e);
- target = try_then_request_module(find_target_lock(t->u.user.name,
- t->u.user.revision),
+ target = try_then_request_module(find_target(t->u.user.name,
+ t->u.user.revision),
"ipt_%s", t->u.user.name);
if (IS_ERR(target) || !target) {
duprintf("check_entry: `%s' not found\n", t->u.user.name);
@@ -763,7 +763,6 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
goto cleanup_matches;
}
t->u.kernel.target = target;
- up(&ipt_mutex);
if (t->u.kernel.target == &ipt_standard_target) {
if (!standard_check(t, size)) {
@@ -1453,7 +1452,7 @@ ipt_unregister_match(struct ipt_match *match)
up(&ipt_mutex);
}
-int ipt_register_table(struct ipt_table *table)
+int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl)
{
int ret;
struct ipt_table_info *newinfo;
@@ -1461,17 +1460,17 @@ int ipt_register_table(struct ipt_table *table)
= { 0, 0, 0, { 0 }, { 0 }, { } };
newinfo = vmalloc(sizeof(struct ipt_table_info)
- + SMP_ALIGN(table->table->size) * NR_CPUS);
+ + SMP_ALIGN(repl->size) * NR_CPUS);
if (!newinfo)
return -ENOMEM;
- memcpy(newinfo->entries, table->table->entries, table->table->size);
+ memcpy(newinfo->entries, repl->entries, repl->size);
ret = translate_table(table->name, table->valid_hooks,
- newinfo, table->table->size,
- table->table->num_entries,
- table->table->hook_entry,
- table->table->underflow);
+ newinfo, repl->size,
+ repl->num_entries,
+ repl->hook_entry,
+ repl->underflow);
if (ret != 0) {
vfree(newinfo);
return ret;
@@ -1959,6 +1958,7 @@ EXPORT_SYMBOL(ipt_unregister_match);
EXPORT_SYMBOL(ipt_do_table);
EXPORT_SYMBOL(ipt_register_target);
EXPORT_SYMBOL(ipt_unregister_target);
+EXPORT_SYMBOL(ipt_find_target);
module_init(init);
module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 2a3e3eb424e3..3713b5b4dd99 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -38,7 +38,7 @@ MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
#endif
/* Use lock to serialize, so printks don't overlap */
-static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(log_lock);
/* One level of recursion won't kill us */
static void dump_packet(const struct ipt_log_info *info,
@@ -327,6 +327,14 @@ static void dump_packet(const struct ipt_log_info *info,
printk("PROTO=%u ", ih->protocol);
}
+ /* Max length: 15 "UID=4294967295 " */
+ if ((info->logflags & IPT_LOG_UID) && !iphoff && skb->sk) {
+ read_lock_bh(&skb->sk->sk_callback_lock);
+ if (skb->sk->sk_socket && skb->sk->sk_socket->file)
+ printk("UID=%u ", skb->sk->sk_socket->file->f_uid);
+ read_unlock_bh(&skb->sk->sk_callback_lock);
+ }
+
/* Proto Max log string length */
/* IP: 40+46+6+11+127 = 230 */
/* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */
diff --git a/net/ipv4/netfilter/ipt_limit.c b/net/ipv4/netfilter/ipt_limit.c
index 46460e4caf97..0c24dcc703a5 100644
--- a/net/ipv4/netfilter/ipt_limit.c
+++ b/net/ipv4/netfilter/ipt_limit.c
@@ -29,7 +29,7 @@ MODULE_DESCRIPTION("iptables rate limit match");
* see net/sched/sch_tbf.c in the linux source tree
*/
-static spinlock_t limit_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(limit_lock);
/* Rusty: This is my (non-mathematically-inclined) understanding of
this algorithm. The `average rate' in jiffies becomes your initial
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 7bb5b4294a24..25ab9fabdcba 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -90,7 +90,7 @@ static struct recent_ip_tables *r_tables = NULL;
/* We protect r_list with this spinlock so two processors are not modifying
* the list at the same time.
*/
-static spinlock_t recent_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(recent_lock);
#ifdef CONFIG_PROC_FS
/* Our /proc/net/ipt_recent entry */
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 9af2aa7c8086..260a4f0a2a90 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -20,32 +20,13 @@ MODULE_DESCRIPTION("iptables filter table");
#define FILTER_VALID_HOOKS ((1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))
-/* Standard entry. */
-struct ipt_standard
-{
- struct ipt_entry entry;
- struct ipt_standard_target target;
-};
-
-struct ipt_error_target
-{
- struct ipt_entry_target target;
- char errorname[IPT_FUNCTION_MAXNAMELEN];
-};
-
-struct ipt_error
-{
- struct ipt_entry entry;
- struct ipt_error_target target;
-};
-
static struct
{
struct ipt_replace repl;
struct ipt_standard entries[3];
struct ipt_error term;
-} initial_table = {
- { "filter", FILTER_VALID_HOOKS, 4,
+} initial_table __initdata
+= { { "filter", FILTER_VALID_HOOKS, 4,
sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
{ [NF_IP_LOCAL_IN] = 0,
[NF_IP_FORWARD] = sizeof(struct ipt_standard),
@@ -95,7 +76,6 @@ static struct
static struct ipt_table packet_filter = {
.name = "filter",
- .table = &initial_table.repl,
.valid_hooks = FILTER_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.me = THIS_MODULE
@@ -171,7 +151,7 @@ static int __init init(void)
initial_table.entries[1].target.verdict = -forward - 1;
/* Register table */
- ret = ipt_register_table(&packet_filter);
+ ret = ipt_register_table(&packet_filter, &initial_table.repl);
if (ret < 0)
return ret;
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index b5b43b277fe2..160eb11b6e2f 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -29,25 +29,6 @@ MODULE_DESCRIPTION("iptables mangle table");
(1 << NF_IP_LOCAL_OUT) | \
(1 << NF_IP_POST_ROUTING))
-/* Standard entry. */
-struct ipt_standard
-{
- struct ipt_entry entry;
- struct ipt_standard_target target;
-};
-
-struct ipt_error_target
-{
- struct ipt_entry_target target;
- char errorname[IPT_FUNCTION_MAXNAMELEN];
-};
-
-struct ipt_error
-{
- struct ipt_entry entry;
- struct ipt_error_target target;
-};
-
/* Ouch - five different hooks? Maybe this should be a config option..... -- BC */
static struct
{
@@ -125,7 +106,6 @@ static struct
static struct ipt_table packet_mangler = {
.name = "mangle",
- .table = &initial_table.repl,
.valid_hooks = MANGLE_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.me = THIS_MODULE,
@@ -225,7 +205,7 @@ static int __init init(void)
int ret;
/* Register table */
- ret = ipt_register_table(&packet_mangler);
+ ret = ipt_register_table(&packet_mangler, &initial_table.repl);
if (ret < 0)
return ret;
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 63c6254607b3..01b4a3c814d3 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -8,25 +8,6 @@
#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
-/* Standard entry. */
-struct ipt_standard
-{
- struct ipt_entry entry;
- struct ipt_standard_target target;
-};
-
-struct ipt_error_target
-{
- struct ipt_entry_target target;
- char errorname[IPT_FUNCTION_MAXNAMELEN];
-};
-
-struct ipt_error
-{
- struct ipt_entry entry;
- struct ipt_error_target target;
-};
-
static struct
{
struct ipt_replace repl;
@@ -100,7 +81,6 @@ static struct
static struct ipt_table packet_raw = {
.name = "raw",
- .table = &initial_table.repl,
.valid_hooks = RAW_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.me = THIS_MODULE
@@ -138,7 +118,7 @@ static int __init init(void)
int ret;
/* Register table */
- ret = ipt_register_table(&packet_raw);
+ ret = ipt_register_table(&packet_raw, &initial_table.repl);
if (ret < 0)
return ret;
diff --git a/net/ipv4/protocol.c b/net/ipv4/protocol.c
index a8b4bdc27ec4..90a587cacaa4 100644
--- a/net/ipv4/protocol.c
+++ b/net/ipv4/protocol.c
@@ -49,7 +49,7 @@
#include <linux/igmp.h>
struct net_protocol *inet_protos[MAX_INET_PROTOS];
-static spinlock_t inet_proto_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(inet_proto_lock);
/*
* Add a protocol handler to the hash tables
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index b14d5fec06df..eaf475a066c2 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -81,7 +81,7 @@
#include <linux/netfilter_ipv4.h>
struct hlist_head raw_v4_htable[RAWV4_HTABLE_SIZE];
-rwlock_t raw_v4_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(raw_v4_lock);
static void raw_v4_hash(struct sock *sk)
{
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 9c438efe1249..0c5619cdce98 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -582,7 +582,7 @@ static void rt_run_flush(unsigned long dummy)
}
}
-static spinlock_t rt_flush_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rt_flush_lock);
void rt_cache_flush(int delay)
{
@@ -901,7 +901,7 @@ restart:
void rt_bind_peer(struct rtable *rt, int create)
{
- static spinlock_t rt_peer_lock = SPIN_LOCK_UNLOCKED;
+ static DEFINE_SPINLOCK(rt_peer_lock);
struct inet_peer *peer;
peer = inet_getpeer(rt->rt_dst, create);
@@ -925,7 +925,7 @@ void rt_bind_peer(struct rtable *rt, int create)
*/
static void ip_select_fb_ident(struct iphdr *iph)
{
- static spinlock_t ip_fb_id_lock = SPIN_LOCK_UNLOCKED;
+ static DEFINE_SPINLOCK(ip_fb_id_lock);
static u32 ip_fallback_id;
u32 salt;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index dd6b9aff0280..9a48486f7305 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -664,7 +664,7 @@ new_segment:
if (!sk_stream_memory_free(sk))
goto wait_for_sndbuf;
- skb = sk_stream_alloc_pskb(sk, 0, tp->mss_cache,
+ skb = sk_stream_alloc_pskb(sk, 0, 0,
sk->sk_allocation);
if (!skb)
goto wait_for_memory;
@@ -689,6 +689,9 @@ new_segment:
skb->len += copy;
skb->data_len += copy;
+ skb->truesize += copy;
+ sk->sk_wmem_queued += copy;
+ sk->sk_forward_alloc -= copy;
skb->ip_summed = CHECKSUM_HW;
tp->write_seq += copy;
TCP_SKB_CB(skb)->end_seq += copy;
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index b2f553ed7615..748224b44399 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -419,7 +419,7 @@ static void tcp_twkill(unsigned long);
#define TCP_TWKILL_QUOTA 100
static struct hlist_head tcp_tw_death_row[TCP_TWKILL_SLOTS];
-static spinlock_t tw_death_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(tw_death_lock);
static struct timer_list tcp_tw_timer = TIMER_INITIALIZER(tcp_twkill, 0, 0);
static void twkill_work(void *);
static DECLARE_WORK(tcp_twkill_work, twkill_work, NULL);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 93e27d655511..12cd0e690cb0 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -115,7 +115,7 @@
DEFINE_SNMP_STAT(struct udp_mib, udp_statistics);
struct hlist_head udp_hash[UDP_HTABLE_SIZE];
-rwlock_t udp_hash_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(udp_hash_lock);
/* Shared by v4/v6 udp. */
int udp_port_rover;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 5fa3fdb890e4..fecf022809ae 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -99,9 +99,6 @@ static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf
static void addrconf_sysctl_unregister(struct ipv6_devconf *p);
#endif
-int inet6_dev_count;
-int inet6_ifa_count;
-
#ifdef CONFIG_IPV6_PRIVACY
static int __ipv6_regen_rndid(struct inet6_dev *idev);
static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
@@ -109,7 +106,7 @@ static void ipv6_regen_rndid(unsigned long data);
static int desync_factor = MAX_DESYNC_FACTOR * HZ;
static struct crypto_tfm *md5_tfm;
-static spinlock_t md5_tfm_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(md5_tfm_lock);
#endif
static int ipv6_count_addresses(struct inet6_dev *idev);
@@ -118,16 +115,16 @@ static int ipv6_count_addresses(struct inet6_dev *idev);
* Configured unicast address hash table
*/
static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE];
-static rwlock_t addrconf_hash_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(addrconf_hash_lock);
/* Protects inet6 devices */
-rwlock_t addrconf_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(addrconf_lock);
static void addrconf_verify(unsigned long);
static struct timer_list addr_chk_timer =
TIMER_INITIALIZER(addrconf_verify, 0, 0);
-static spinlock_t addrconf_verify_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(addrconf_verify_lock);
static void addrconf_join_anycast(struct inet6_ifaddr *ifp);
static void addrconf_leave_anycast(struct inet6_ifaddr *ifp);
@@ -191,7 +188,9 @@ static struct ipv6_devconf ipv6_devconf_dflt = {
};
/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
+#if 0
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+#endif
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
int ipv6_addr_type(const struct in6_addr *addr)
@@ -310,7 +309,6 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
return;
}
snmp6_unregister_dev(idev);
- inet6_dev_count--;
kfree(idev);
}
@@ -338,7 +336,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
kfree(ndev);
return NULL;
}
- inet6_dev_count++;
/* We refer to the device */
dev_hold(dev);
@@ -475,7 +472,6 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
}
dst_release(&ifp->rt->u.dst);
- inet6_ifa_count--;
kfree(ifp);
}
@@ -530,7 +526,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
ifa->flags = flags | IFA_F_TENTATIVE;
ifa->cstamp = ifa->tstamp = jiffies;
- inet6_ifa_count++;
ifa->idev = idev;
in6_dev_hold(idev);
/* For caller */
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 5ca3af45cfeb..d5d1d83416fe 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -94,7 +94,7 @@ atomic_t inet6_sock_nr;
* build a new socket.
*/
static struct list_head inetsw6[SOCK_MAX];
-static spinlock_t inetsw6_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(inetsw6_lock);
static void inet6_sock_destruct(struct sock *sk)
{
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 959947f56e9f..410a1ab9c698 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -43,8 +43,10 @@
#include <net/checksum.h>
+static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr);
+
/* Big ac list lock for all the sockets */
-static rwlock_t ipv6_sk_ac_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ipv6_sk_ac_lock);
/* XXX ip6_addr_match() and ip6_onlink() really belong in net/core.c */
@@ -413,7 +415,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr)
return 0;
}
-int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
+static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
{
int ret;
struct inet6_dev *idev = in6_dev_get(dev);
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 2b78c840c349..e0839eafc3a9 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -501,83 +501,6 @@ int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
* for headers.
*/
-static u8 *ipv6_build_rthdr(struct sk_buff *skb, u8 *prev_hdr,
- struct ipv6_rt_hdr *opt, struct in6_addr *addr)
-{
- struct rt0_hdr *phdr, *ihdr;
- int hops;
-
- ihdr = (struct rt0_hdr *) opt;
-
- phdr = (struct rt0_hdr *) skb_put(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
- memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
-
- hops = ihdr->rt_hdr.hdrlen >> 1;
-
- if (hops > 1)
- memcpy(phdr->addr, ihdr->addr + 1,
- (hops - 1) * sizeof(struct in6_addr));
-
- ipv6_addr_copy(phdr->addr + (hops - 1), addr);
-
- phdr->rt_hdr.nexthdr = *prev_hdr;
- *prev_hdr = NEXTHDR_ROUTING;
- return &phdr->rt_hdr.nexthdr;
-}
-
-static u8 *ipv6_build_exthdr(struct sk_buff *skb, u8 *prev_hdr, u8 type, struct ipv6_opt_hdr *opt)
-{
- struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_put(skb, ipv6_optlen(opt));
-
- memcpy(h, opt, ipv6_optlen(opt));
- h->nexthdr = *prev_hdr;
- *prev_hdr = type;
- return &h->nexthdr;
-}
-
-u8 *ipv6_build_nfrag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt,
- struct in6_addr *daddr, u32 jumbolen)
-{
- struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb->data;
-
- if (opt && opt->hopopt)
- prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_HOP, opt->hopopt);
-
- if (jumbolen) {
- u8 *jumboopt = (u8 *)skb_put(skb, 8);
-
- if (opt && opt->hopopt) {
- *jumboopt++ = IPV6_TLV_PADN;
- *jumboopt++ = 0;
- h->hdrlen++;
- } else {
- h = (struct ipv6_opt_hdr *)jumboopt;
- h->nexthdr = *prev_hdr;
- h->hdrlen = 0;
- jumboopt += 2;
- *prev_hdr = NEXTHDR_HOP;
- prev_hdr = &h->nexthdr;
- }
- jumboopt[0] = IPV6_TLV_JUMBO;
- jumboopt[1] = 4;
- *(u32*)(jumboopt+2) = htonl(jumbolen);
- }
- if (opt) {
- if (opt->dst0opt)
- prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst0opt);
- if (opt->srcrt)
- prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, daddr);
- }
- return prev_hdr;
-}
-
-u8 *ipv6_build_frag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt)
-{
- if (opt->dst1opt)
- prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst1opt);
- return prev_hdr;
-}
-
static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
struct ipv6_rt_hdr *opt,
struct in6_addr **addr_p)
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 26273c82f9fc..e9eca00e0e41 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -211,7 +211,7 @@ static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset)
return (*op & 0xC0) == 0x80;
}
-int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hdr *thdr, int len)
+static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hdr *thdr, int len)
{
struct sk_buff *skb;
struct icmp6hdr *icmp6h;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 798d78cb242f..b131090deb4c 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -69,7 +69,7 @@ struct fib6_cleaner_t
void *arg;
};
-rwlock_t fib6_walker_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(fib6_walker_lock);
#ifdef CONFIG_IPV6_SUBTREES
@@ -1205,7 +1205,7 @@ static int fib6_age(struct rt6_info *rt, void *arg)
return 0;
}
-static spinlock_t fib6_gc_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(fib6_gc_lock);
void fib6_run_gc(unsigned long dummy)
{
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 1803f46755aa..a3340f2b4714 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -54,11 +54,11 @@ static struct timer_list ip6_fl_gc_timer = TIMER_INITIALIZER(ip6_fl_gc, 0, 0);
/* FL hash table lock: it protects only of GC */
-static rwlock_t ip6_fl_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ip6_fl_lock);
/* Big socket sock */
-static rwlock_t ip6_sk_fl_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ip6_sk_fl_lock);
static __inline__ struct ip6_flowlabel * __fl_lookup(u32 label)
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index aec81a63b126..37abe7141d14 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -61,7 +61,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *fhdr)
{
static u32 ipv6_fragmentation_id = 1;
- static spinlock_t ip6_id_lock = SPIN_LOCK_UNLOCKED;
+ static DEFINE_SPINLOCK(ip6_id_lock);
spin_lock_bh(&ip6_id_lock);
fhdr->identification = htonl(ipv6_fragmentation_id);
@@ -311,7 +311,7 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev,
return 0;
}
-int ip6_call_ra_chain(struct sk_buff *skb, int sel)
+static int ip6_call_ra_chain(struct sk_buff *skb, int sel)
{
struct ip6_ra_chain *ra;
struct sock *last = NULL;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 742f0e493652..57f83a7a8411 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -85,7 +85,7 @@ static struct ip6_tnl *tnls_wc[1];
static struct ip6_tnl **tnls[2] = { tnls_wc, tnls_r_l };
/* lock for the tunnel lists */
-static rwlock_t ip6ip6_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ip6ip6_lock);
static inline struct dst_entry *ip6_tnl_dst_check(struct ip6_tnl *t)
{
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index c41d5a5b7bd4..e2d848ab01b0 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -63,7 +63,7 @@ static struct packet_type ipv6_packet_type = {
};
struct ip6_ra_chain *ip6_ra_chain;
-rwlock_t ip6_ra_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(ip6_ra_lock);
int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *))
{
diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c
index a2d9601f98d3..2f4c91ddc9a3 100644
--- a/net/ipv6/ipv6_syms.c
+++ b/net/ipv6/ipv6_syms.c
@@ -32,8 +32,6 @@ EXPORT_SYMBOL(inet6_getname);
EXPORT_SYMBOL(inet6_ioctl);
EXPORT_SYMBOL(ipv6_get_saddr);
EXPORT_SYMBOL(ipv6_chk_addr);
-EXPORT_SYMBOL(in6addr_any);
-EXPORT_SYMBOL(in6addr_loopback);
EXPORT_SYMBOL(in6_dev_finish_destroy);
#ifdef CONFIG_XFRM
EXPORT_SYMBOL(xfrm6_rcv);
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 2cd84b9f96d9..393b6e6f50a9 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -121,10 +121,10 @@ struct mld2_query {
struct in6_addr srcs[0];
};
-struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT;
+static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT;
/* Big mc list lock for all the sockets */
-static rwlock_t ipv6_sk_mc_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ipv6_sk_mc_lock);
static struct socket *igmp6_socket;
@@ -143,12 +143,14 @@ static void mld_clear_delrec(struct inet6_dev *idev);
static int sf_setstate(struct ifmcaddr6 *pmc);
static void sf_markstate(struct ifmcaddr6 *pmc);
static void ip6_mc_clear_src(struct ifmcaddr6 *pmc);
-int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca, int sfmode,
- int sfcount, struct in6_addr *psfsrc, int delta);
-int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca, int sfmode,
- int sfcount, struct in6_addr *psfsrc, int delta);
-int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
- struct inet6_dev *idev);
+static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca,
+ int sfmode, int sfcount, struct in6_addr *psfsrc,
+ int delta);
+static int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca,
+ int sfmode, int sfcount, struct in6_addr *psfsrc,
+ int delta);
+static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
+ struct inet6_dev *idev);
#define IGMP6_UNSOLICITED_IVAL (10*HZ)
@@ -272,7 +274,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
return -ENOENT;
}
-struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex)
+static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex)
{
struct net_device *dev = NULL;
struct inet6_dev *idev = NULL;
@@ -1723,8 +1725,9 @@ static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
return rv;
}
-int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca, int sfmode,
- int sfcount, struct in6_addr *psfsrc, int delta)
+static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca,
+ int sfmode, int sfcount, struct in6_addr *psfsrc,
+ int delta)
{
struct ifmcaddr6 *pmc;
int changerec = 0;
@@ -1847,8 +1850,9 @@ static int sf_setstate(struct ifmcaddr6 *pmc)
/*
* Add multicast source filter list to the interface list
*/
-int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca, int sfmode,
- int sfcount, struct in6_addr *psfsrc, int delta)
+static int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca,
+ int sfmode, int sfcount, struct in6_addr *psfsrc,
+ int delta)
{
struct ifmcaddr6 *pmc;
int isexclude;
@@ -1951,8 +1955,8 @@ static void igmp6_join_group(struct ifmcaddr6 *ma)
spin_unlock_bh(&ma->mca_lock);
}
-int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
- struct inet6_dev *idev)
+static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
+ struct inet6_dev *idev)
{
int err;
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index bcf6502dee3c..6795b4179933 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -60,7 +60,7 @@ typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long);
static unsigned char copy_mode = IPQ_COPY_NONE;
static unsigned int queue_maxlen = IPQ_QMAX_DEFAULT;
-static rwlock_t queue_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(queue_lock);
static int peer_pid;
static unsigned int copy_range;
static unsigned int queue_total;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 5b74f5cfe013..6a06de74a30f 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -234,7 +234,7 @@ ip6_packet_match(const struct sk_buff *skb,
* we will change the return 0 to 1*/
if ((currenthdr == IPPROTO_NONE) ||
(currenthdr == IPPROTO_ESP))
- return 0;
+ break;
hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
BUG_ON(hp == NULL);
@@ -366,10 +366,6 @@ ip6t_do_table(struct sk_buff **pskb,
void *table_base;
struct ip6t_entry *e, *back;
- /* FIXME: Push down to extensions --RR */
- if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0)
- return NF_DROP;
-
/* Initialization */
indev = in ? in->name : nulldevname;
outdev = out ? out->name : nulldevname;
@@ -1373,7 +1369,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
sizeof(info.underflow));
info.num_entries = t->private->number;
info.size = t->private->size;
- strcpy(info.name, name);
+ memcpy(info.name, name, sizeof(info.name));
if (copy_to_user(user, &info, *len) != 0)
ret = -EFAULT;
@@ -1464,7 +1460,8 @@ ip6t_unregister_match(struct ip6t_match *match)
up(&ip6t_mutex);
}
-int ip6t_register_table(struct ip6t_table *table)
+int ip6t_register_table(struct ip6t_table *table,
+ const struct ip6t_replace *repl)
{
int ret;
struct ip6t_table_info *newinfo;
@@ -1472,17 +1469,17 @@ int ip6t_register_table(struct ip6t_table *table)
= { 0, 0, 0, { 0 }, { 0 }, { } };
newinfo = vmalloc(sizeof(struct ip6t_table_info)
- + SMP_ALIGN(table->table->size) * NR_CPUS);
+ + SMP_ALIGN(repl->size) * NR_CPUS);
if (!newinfo)
return -ENOMEM;
- memcpy(newinfo->entries, table->table->entries, table->table->size);
+ memcpy(newinfo->entries, repl->entries, repl->size);
ret = translate_table(table->name, table->valid_hooks,
- newinfo, table->table->size,
- table->table->num_entries,
- table->table->hook_entry,
- table->table->underflow);
+ newinfo, repl->size,
+ repl->num_entries,
+ repl->hook_entry,
+ repl->underflow);
if (ret != 0) {
vfree(newinfo);
return ret;
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 9f5cfdbe26a5..bfc3d0185d19 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -41,7 +41,7 @@ struct in_device;
#endif
/* Use lock to serialize, so printks don't overlap */
-static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(log_lock);
/* One level of recursion won't kill us */
static void dump_packet(const struct ip6t_log_info *info,
@@ -347,6 +347,14 @@ static void dump_packet(const struct ip6t_log_info *info,
default:
printk("PROTO=%u ", currenthdr);
}
+
+ /* Max length: 15 "UID=4294967295 " */
+ if ((info->logflags & IP6T_LOG_UID) && recurse && skb->sk) {
+ read_lock_bh(&skb->sk->sk_callback_lock);
+ if (skb->sk->sk_socket && skb->sk->sk_socket->file)
+ printk("UID=%u ", skb->sk->sk_socket->file->f_uid);
+ read_unlock_bh(&skb->sk->sk_callback_lock);
+ }
}
static void
diff --git a/net/ipv6/netfilter/ip6t_limit.c b/net/ipv6/netfilter/ip6t_limit.c
index a462b771066a..fb782f610be2 100644
--- a/net/ipv6/netfilter/ip6t_limit.c
+++ b/net/ipv6/netfilter/ip6t_limit.c
@@ -29,7 +29,7 @@ MODULE_DESCRIPTION("rate limiting within ip6tables");
* see net/sched/sch_tbf.c in the linux source tree
*/
-static spinlock_t limit_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(limit_lock);
/* Rusty: This is my (non-mathematically-inclined) understanding of
this algorithm. The `average rate' in jiffies becomes your initial
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index aca6d21cc588..4c0028671c20 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -94,7 +94,6 @@ static struct
static struct ip6t_table packet_filter = {
.name = "filter",
- .table = &initial_table.repl,
.valid_hooks = FILTER_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.me = THIS_MODULE,
@@ -172,7 +171,7 @@ static int __init init(void)
initial_table.entries[1].target.verdict = -forward - 1;
/* Register table */
- ret = ip6t_register_table(&packet_filter);
+ ret = ip6t_register_table(&packet_filter, &initial_table.repl);
if (ret < 0)
return ret;
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 0d15d5b2fdce..85c1e6eada19 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -124,7 +124,6 @@ static struct
static struct ip6t_table packet_mangler = {
.name = "mangle",
- .table = &initial_table.repl,
.valid_hooks = MANGLE_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.me = THIS_MODULE,
@@ -165,10 +164,6 @@ ip6t_local_hook(unsigned int hook,
}
#endif
- /* FIXME: Push down to extensions --RR */
- if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0)
- return NF_DROP;
-
/* save source/dest address, nfmark, hoplimit, flowlabel, priority, */
memcpy(&saddr, &(*pskb)->nh.ipv6h->saddr, sizeof(saddr));
memcpy(&daddr, &(*pskb)->nh.ipv6h->daddr, sizeof(daddr));
@@ -237,7 +232,7 @@ static int __init init(void)
int ret;
/* Register table */
- ret = ip6t_register_table(&packet_mangler);
+ ret = ip6t_register_table(&packet_mangler, &initial_table.repl);
if (ret < 0)
return ret;
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index b7077e9bf3a6..71407beaf790 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -108,7 +108,6 @@ static struct
static struct ip6t_table packet_raw = {
.name = "raw",
- .table = &initial_table.repl,
.valid_hooks = RAW_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.me = THIS_MODULE
@@ -145,7 +144,7 @@ static int __init init(void)
int ret;
/* Register table */
- ret = ip6t_register_table(&packet_raw);
+ ret = ip6t_register_table(&packet_raw, &initial_table.repl);
if (ret < 0)
return ret;
diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c
index 9a3f5b7e90e3..52c1d58b6ca6 100644
--- a/net/ipv6/protocol.c
+++ b/net/ipv6/protocol.c
@@ -40,7 +40,7 @@
#include <net/protocol.h>
struct inet6_protocol *inet6_protos[MAX_INET_PROTOS];
-static spinlock_t inet6_proto_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(inet6_proto_lock);
int inet6_add_protocol(struct inet6_protocol *prot, unsigned char protocol)
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 0f28463ac350..9e0a2e169f7b 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -56,7 +56,7 @@
#include <linux/seq_file.h>
struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE];
-rwlock_t raw_v6_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(raw_v6_lock);
static void raw_v6_hash(struct sock *sk)
{
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index f69b3f9c5bc3..59e7c6317872 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -103,7 +103,7 @@ struct frag_queue
#define IP6Q_HASHSZ 64
static struct frag_queue *ip6_frag_hash[IP6Q_HASHSZ];
-static rwlock_t ip6_frag_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ip6_frag_lock);
static u32 ip6_frag_hash_rnd;
static LIST_HEAD(ip6_frag_lru_list);
int ip6_frag_nqueues = 0;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0f0b9a6cbcf1..316644b92cb3 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -133,7 +133,7 @@ struct fib6_node ip6_routing_table = {
/* Protects all the ip6 fib */
-rwlock_t rt6_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(rt6_lock);
/* allocate dst with ip6_dst_ops */
@@ -208,8 +208,8 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt,
/*
* pointer to the last default router chosen. BH is disabled locally.
*/
-struct rt6_info *rt6_dflt_pointer;
-spinlock_t rt6_dflt_lock = SPIN_LOCK_UNLOCKED;
+static struct rt6_info *rt6_dflt_pointer;
+static DEFINE_SPINLOCK(rt6_dflt_lock);
void rt6_reset_dflt_pointer(struct rt6_info *rt)
{
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 3ddbd6ce3f64..b517fa50f01b 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -73,7 +73,7 @@ static struct ip_tunnel *tunnels_l[HASH_SIZE];
static struct ip_tunnel *tunnels_wc[1];
static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l };
-static rwlock_t ipip6_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ipip6_lock);
static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local)
{
@@ -135,10 +135,10 @@ static void ipip6_tunnel_link(struct ip_tunnel *t)
{
struct ip_tunnel **tp = ipip6_bucket(t);
- write_lock_bh(&ipip6_lock);
t->next = *tp;
- write_unlock_bh(&ipip6_lock);
+ write_lock_bh(&ipip6_lock);
*tp = t;
+ write_unlock_bh(&ipip6_lock);
}
static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create)
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 9639eaefeb57..3a18e0e6ffed 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -19,7 +19,7 @@ extern ctl_table ipv6_icmp_table[];
#ifdef CONFIG_SYSCTL
-ctl_table ipv6_table[] = {
+static ctl_table ipv6_table[] = {
{
.ctl_name = NET_IPV6_ROUTE,
.procname = "route",
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 9616a63cc431..1df30ba70200 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -72,7 +72,7 @@ struct xfrm6_tunnel_spi {
# define XFRM6_TUNNEL_SPI_MAGIC 0xdeadbeef
#endif
-static rwlock_t xfrm6_tunnel_spi_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(xfrm6_tunnel_spi_lock);
static u32 xfrm6_tunnel_spi;
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 6da62172f674..5fbd19f82c11 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -78,7 +78,7 @@ static struct datalink_proto *pSNAP_datalink;
static struct proto_ops ipx_dgram_ops;
LIST_HEAD(ipx_interfaces);
-spinlock_t ipx_interfaces_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(ipx_interfaces_lock);
struct ipx_interface *ipx_primary_net;
struct ipx_interface *ipx_internal_net;
diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c
index 57faf8cbcd5a..c85e682f7f66 100644
--- a/net/ipx/ipx_route.c
+++ b/net/ipx/ipx_route.c
@@ -16,7 +16,7 @@
#include <net/sock.h>
LIST_HEAD(ipx_routes);
-rwlock_t ipx_routes_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(ipx_routes_lock);
extern struct ipx_interface *ipx_internal_net;
diff --git a/net/irda/ircomm/ircomm_event.c b/net/irda/ircomm/ircomm_event.c
index 606b4e2a0a0f..01f4e801a1ba 100644
--- a/net/irda/ircomm/ircomm_event.c
+++ b/net/irda/ircomm/ircomm_event.c
@@ -57,6 +57,7 @@ char *ircomm_state[] = {
"IRCOMM_CONN",
};
+#ifdef CONFIG_IRDA_DEBUG
static char *ircomm_event[] = {
"IRCOMM_CONNECT_REQUEST",
"IRCOMM_CONNECT_RESPONSE",
@@ -75,6 +76,7 @@ static char *ircomm_event[] = {
"IRCOMM_CONTROL_REQUEST",
"IRCOMM_CONTROL_INDICATION",
};
+#endif /* CONFIG_IRDA_DEBUG */
static int (*state[])(struct ircomm_cb *self, IRCOMM_EVENT event,
struct sk_buff *skb, struct ircomm_info *info) =
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
index 41a6aa415040..e01be889abed 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -91,6 +91,7 @@ char *ircomm_tty_state[] = {
"*** ERROR *** ",
};
+#ifdef CONFIG_IRDA_DEBUG
static char *ircomm_tty_event[] = {
"IRCOMM_TTY_ATTACH_CABLE",
"IRCOMM_TTY_DETACH_CABLE",
@@ -107,6 +108,7 @@ static char *ircomm_tty_event[] = {
"IRCOMM_TTY_GOT_LSAPSEL",
"*** ERROR ****",
};
+#endif /* CONFIG_IRDA_DEBUG */
static int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
struct sk_buff *skb, struct ircomm_tty_info *info) =
diff --git a/net/key/af_key.c b/net/key/af_key.c
index cc4a9c8c038c..50b9466307ef 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -37,7 +37,7 @@
/* List of all pfkey sockets. */
static HLIST_HEAD(pfkey_table);
static DECLARE_WAIT_QUEUE_HEAD(pfkey_table_wait);
-static rwlock_t pfkey_table_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(pfkey_table_lock);
static atomic_t pfkey_table_users = ATOMIC_INIT(0);
static atomic_t pfkey_socks_nr = ATOMIC_INIT(0);
@@ -2344,7 +2344,7 @@ static u32 get_acqseq(void)
{
u32 res;
static u32 acqseq;
- static spinlock_t acqseq_lock = SPIN_LOCK_UNLOCKED;
+ static DEFINE_SPINLOCK(acqseq_lock);
spin_lock_bh(&acqseq_lock);
res = (++acqseq ? : ++acqseq);
diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c
index fe50f633b2a0..aea6616cea3d 100644
--- a/net/lapb/lapb_iface.c
+++ b/net/lapb/lapb_iface.c
@@ -40,7 +40,7 @@
#include <net/lapb.h>
static struct list_head lapb_list = LIST_HEAD_INIT(lapb_list);
-static rwlock_t lapb_list_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(lapb_list_lock);
/*
* Free an allocated lapb control block.
diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c
index 0b737bd77062..5ff02c080a0b 100644
--- a/net/llc/llc_core.c
+++ b/net/llc/llc_core.c
@@ -22,7 +22,7 @@
#include <net/llc.h>
LIST_HEAD(llc_sap_list);
-rwlock_t llc_sap_list_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(llc_sap_list_lock);
unsigned char llc_station_mac_sa[ETH_ALEN];
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 755a3b10f9e1..74764e224c85 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -98,14 +98,10 @@ static struct netlink_table *nl_table;
static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait);
static unsigned int nl_nonroot[MAX_LINKS];
-#ifdef NL_EMULATE_DEV
-static struct socket *netlink_kernel[MAX_LINKS];
-#endif
-
static int netlink_dump(struct sock *sk);
static void netlink_destroy_callback(struct netlink_callback *cb);
-static rwlock_t nl_table_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(nl_table_lock);
static atomic_t nl_table_users = ATOMIC_INIT(0);
static struct notifier_block *netlink_chain;
@@ -1202,37 +1198,6 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
}
-#ifdef NL_EMULATE_DEV
-
-static rwlock_t nl_emu_lock = RW_LOCK_UNLOCKED;
-
-/*
- * Backward compatibility.
- */
-
-int netlink_post(int unit, struct sk_buff *skb)
-{
- struct socket *sock;
-
- read_lock(&nl_emu_lock);
- sock = netlink_kernel[unit];
- if (sock) {
- struct sock *sk = sock->sk;
- memset(skb->cb, 0, sizeof(skb->cb));
- sock_hold(sk);
- read_unlock(&nl_emu_lock);
-
- netlink_broadcast(sk, skb, 0, ~0, GFP_ATOMIC);
-
- sock_put(sk);
- return 0;
- }
- read_unlock(&nl_emu_lock);
- return -EUNATCH;
-}
-
-#endif
-
#ifdef CONFIG_PROC_FS
struct nl_seq_iter {
int link;
@@ -1497,6 +1462,3 @@ EXPORT_SYMBOL(netlink_set_nonroot);
EXPORT_SYMBOL(netlink_unicast);
EXPORT_SYMBOL(netlink_unregister_notifier);
-#if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)
-EXPORT_SYMBOL(netlink_post);
-#endif
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 8576b42ce7fa..39223bbf1938 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -60,7 +60,7 @@ int sysctl_netrom_link_fails_count = NR_DEFAULT_FAILS;
static unsigned short circuit = 0x101;
static HLIST_HEAD(nr_list);
-static spinlock_t nr_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(nr_list_lock);
static struct proto_ops nr_proto_ops;
void nr_init_timers(struct sock *sk);
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index d39549eb2fdd..7a86b36cba50 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -41,9 +41,9 @@
static unsigned int nr_neigh_no = 1;
static HLIST_HEAD(nr_node_list);
-static spinlock_t nr_node_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(nr_node_list_lock);
static HLIST_HEAD(nr_neigh_list);
-static spinlock_t nr_neigh_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(nr_neigh_list_lock);
static struct nr_node *nr_node_get(ax25_address *callsign)
{
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 60e6d827436b..a996d9c43f9e 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -146,7 +146,7 @@ dev->hard_header == NULL (ll header is added by device, we cannot control it)
/* List of all packet sockets. */
static HLIST_HEAD(packet_sklist);
-static rwlock_t packet_sklist_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(packet_sklist_lock);
static atomic_t packet_socks_nr;
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 3d26b72b2b3a..e02d7eb6cbd0 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -59,7 +59,7 @@ int sysctl_rose_maximum_vcs = ROSE_DEFAULT_MAXVC;
int sysctl_rose_window_size = ROSE_DEFAULT_WINDOW_SIZE;
static HLIST_HEAD(rose_list);
-static spinlock_t rose_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rose_list_lock);
static struct proto_ops rose_proto_ops;
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 35591a0486cc..92674a1cc49e 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -40,11 +40,11 @@
static unsigned int rose_neigh_no = 1;
static struct rose_node *rose_node_list;
-static spinlock_t rose_node_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rose_node_list_lock);
static struct rose_neigh *rose_neigh_list;
-static spinlock_t rose_neigh_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rose_neigh_list_lock);
static struct rose_route *rose_route_list;
-static spinlock_t rose_route_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rose_route_list_lock);
struct rose_neigh *rose_loopback_neigh;
diff --git a/net/rxrpc/krxiod.c b/net/rxrpc/krxiod.c
index f34323701713..c987395e5783 100644
--- a/net/rxrpc/krxiod.c
+++ b/net/rxrpc/krxiod.c
@@ -25,10 +25,10 @@ static DECLARE_COMPLETION(rxrpc_krxiod_dead);
static atomic_t rxrpc_krxiod_qcount = ATOMIC_INIT(0);
static LIST_HEAD(rxrpc_krxiod_transportq);
-static spinlock_t rxrpc_krxiod_transportq_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rxrpc_krxiod_transportq_lock);
static LIST_HEAD(rxrpc_krxiod_callq);
-static spinlock_t rxrpc_krxiod_callq_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rxrpc_krxiod_callq_lock);
static volatile int rxrpc_krxiod_die;
diff --git a/net/rxrpc/krxsecd.c b/net/rxrpc/krxsecd.c
index c9ee29eb2032..117aa91537a1 100644
--- a/net/rxrpc/krxsecd.c
+++ b/net/rxrpc/krxsecd.c
@@ -39,7 +39,7 @@ static atomic_t rxrpc_krxsecd_qcount;
/* queue of unprocessed inbound messages with seqno #1 and
* RXRPC_CLIENT_INITIATED flag set */
static LIST_HEAD(rxrpc_krxsecd_initmsgq);
-static spinlock_t rxrpc_krxsecd_initmsgq_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rxrpc_krxsecd_initmsgq_lock);
static void rxrpc_krxsecd_process_incoming_call(struct rxrpc_message *msg);
diff --git a/net/rxrpc/krxtimod.c b/net/rxrpc/krxtimod.c
index 31771577c5bb..0d9e9d2f8eed 100644
--- a/net/rxrpc/krxtimod.c
+++ b/net/rxrpc/krxtimod.c
@@ -24,7 +24,7 @@ static DECLARE_WAIT_QUEUE_HEAD(krxtimod_sleepq);
static int krxtimod_die;
static LIST_HEAD(krxtimod_list);
-static spinlock_t krxtimod_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(krxtimod_lock);
static int krxtimod(void *arg);
diff --git a/net/rxrpc/transport.c b/net/rxrpc/transport.c
index cd40f9c8befe..9bce7794130a 100644
--- a/net/rxrpc/transport.c
+++ b/net/rxrpc/transport.c
@@ -39,7 +39,7 @@ struct errormsg {
struct sockaddr_in icmp_src; /* ICMP packet source address */
};
-static spinlock_t rxrpc_transports_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rxrpc_transports_lock);
static struct list_head rxrpc_transports = LIST_HEAD_INIT(rxrpc_transports);
__RXACCT_DECL(atomic_t rxrpc_transport_count);
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index b04297f5ddf8..b0fb5d7f42b7 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -381,7 +381,6 @@ config NET_CLS_ACT
---help---
This option requires you have a new iproute2. It enables
tc extensions which can be used with tc classifiers.
- Only the u32 and fw classifiers are supported at the moment.
You MUST NOT turn this on if you dont have an update iproute2.
config NET_ACT_POLICE
@@ -392,13 +391,6 @@ config NET_ACT_POLICE
below to select a policer.
You MUST NOT turn this on if you dont have an update iproute2.
-config NET_CLS_POLICE
- bool "Traffic policing (needed for in/egress)"
- depends on NET_CLS && NET_QOS && NET_ACT_POLICE!=y && NET_ACT_POLICE!=m
- help
- Say Y to support traffic policing (bandwidth limits). Needed for
- ingress and egress rate limiting.
-
config NET_ACT_GACT
tristate "generic Actions"
depends on NET_CLS_ACT
@@ -432,3 +424,11 @@ config NET_ACT_PEDIT
---help---
requires new iproute2
This allows for packets to be generically edited
+
+config NET_CLS_POLICE
+ bool "Traffic policing (needed for in/egress)"
+ depends on NET_CLS && NET_QOS && NET_CLS_ACT!=y
+ help
+ Say Y to support traffic policing (bandwidth limits). Needed for
+ ingress and egress rate limiting.
+
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 5fe30ba95ed6..eebef4e16a2f 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -35,36 +35,33 @@
#include <net/act_api.h>
#if 1 /* control */
-#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#define DPRINTK(format, args...) printk(KERN_DEBUG format, ##args)
#else
-#define DPRINTK(format,args...)
+#define DPRINTK(format, args...)
#endif
#if 0 /* data */
-#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#define D2PRINTK(format, args...) printk(KERN_DEBUG format, ##args)
#else
-#define D2PRINTK(format,args...)
+#define D2PRINTK(format, args...)
#endif
static struct tc_action_ops *act_base = NULL;
-static rwlock_t act_mod_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(act_mod_lock);
int tcf_register_action(struct tc_action_ops *act)
{
struct tc_action_ops *a, **ap;
write_lock(&act_mod_lock);
- for (ap = &act_base; (a=*ap)!=NULL; ap = &a->next) {
+ for (ap = &act_base; (a = *ap) != NULL; ap = &a->next) {
if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) {
write_unlock(&act_mod_lock);
return -EEXIST;
}
}
-
- act->next = NULL;
+ act->next = NULL;
*ap = act;
-
write_unlock(&act_mod_lock);
-
return 0;
}
@@ -74,10 +71,9 @@ int tcf_unregister_action(struct tc_action_ops *act)
int err = -ENOENT;
write_lock(&act_mod_lock);
- for (ap = &act_base; (a=*ap)!=NULL; ap = &a->next)
- if(a == act)
+ for (ap = &act_base; (a = *ap) != NULL; ap = &a->next)
+ if (a == act)
break;
-
if (a) {
*ap = a->next;
a->next = NULL;
@@ -90,47 +86,42 @@ int tcf_unregister_action(struct tc_action_ops *act)
/* lookup by name */
static struct tc_action_ops *tc_lookup_action_n(char *kind)
{
-
struct tc_action_ops *a = NULL;
if (kind) {
read_lock(&act_mod_lock);
for (a = act_base; a; a = a->next) {
- if (strcmp(kind,a->kind) == 0) {
+ if (strcmp(kind, a->kind) == 0) {
if (!try_module_get(a->owner)) {
read_unlock(&act_mod_lock);
return NULL;
- }
+ }
break;
}
}
read_unlock(&act_mod_lock);
}
-
return a;
}
/* lookup by rtattr */
static struct tc_action_ops *tc_lookup_action(struct rtattr *kind)
{
-
struct tc_action_ops *a = NULL;
if (kind) {
read_lock(&act_mod_lock);
for (a = act_base; a; a = a->next) {
-
- if (strcmp((char*)RTA_DATA(kind),a->kind) == 0){
+ if (rtattr_strcmp(kind, a->kind) == 0) {
if (!try_module_get(a->owner)) {
read_unlock(&act_mod_lock);
return NULL;
- }
+ }
break;
}
}
read_unlock(&act_mod_lock);
}
-
return a;
}
@@ -147,55 +138,52 @@ static struct tc_action_ops *tc_lookup_action_id(u32 type)
if (!try_module_get(a->owner)) {
read_unlock(&act_mod_lock);
return NULL;
- }
+ }
break;
}
}
read_unlock(&act_mod_lock);
}
-
return a;
}
#endif
-int tcf_action_exec(struct sk_buff *skb,struct tc_action *act, struct tcf_result *res)
+int tcf_action_exec(struct sk_buff *skb, struct tc_action *act,
+ struct tcf_result *res)
{
-
struct tc_action *a;
- int ret = -1;
+ int ret = -1;
if (skb->tc_verd & TC_NCLS) {
skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
- D2PRINTK("(%p)tcf_action_exec: cleared TC_NCLS in %s out %s\n",skb,skb->input_dev?skb->input_dev->name:"xxx",skb->dev->name);
+ D2PRINTK("(%p)tcf_action_exec: cleared TC_NCLS in %s out %s\n",
+ skb, skb->input_dev ? skb->input_dev->name : "xxx",
+ skb->dev->name);
ret = TC_ACT_OK;
goto exec_done;
}
while ((a = act) != NULL) {
repeat:
if (a->ops && a->ops->act) {
- ret = a->ops->act(&skb,a);
- if (TC_MUNGED & skb->tc_verd) {
- /* copied already, allow trampling */
- skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
- skb->tc_verd = CLR_TC_MUNGED(skb->tc_verd);
- }
-
+ ret = a->ops->act(&skb, a);
+ if (TC_MUNGED & skb->tc_verd) {
+ /* copied already, allow trampling */
+ skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
+ skb->tc_verd = CLR_TC_MUNGED(skb->tc_verd);
+ }
if (ret != TC_ACT_PIPE)
goto exec_done;
if (ret == TC_ACT_REPEAT)
goto repeat; /* we need a ttl - JHS */
-
}
act = a->next;
}
-
exec_done:
if (skb->tc_classid > 0) {
res->classid = skb->tc_classid;
res->class = 0;
skb->tc_classid = 0;
}
-
return ret;
}
@@ -203,56 +191,44 @@ void tcf_action_destroy(struct tc_action *act, int bind)
{
struct tc_action *a;
- for (a = act; act; a = act) {
- if (a && a->ops && a->ops->cleanup) {
- DPRINTK("tcf_action_destroy destroying %p next %p\n", a,a->next?a->next:NULL);
- act = act->next;
- if (ACT_P_DELETED == a->ops->cleanup(a, bind)) {
+ for (a = act; a; a = act) {
+ if (a->ops && a->ops->cleanup) {
+ DPRINTK("tcf_action_destroy destroying %p next %p\n",
+ a, a->next);
+ if (a->ops->cleanup(a, bind) == ACT_P_DELETED)
module_put(a->ops->owner);
- }
-
- a->ops = NULL;
+ act = act->next;
kfree(a);
} else { /*FIXME: Remove later - catch insertion bugs*/
- printk("tcf_action_destroy: BUG? destroying NULL ops \n");
- if (a) {
- act = act->next;
- kfree(a);
- } else {
- printk("tcf_action_destroy: BUG? destroying NULL action! \n");
- break;
- }
+ printk("tcf_action_destroy: BUG? destroying NULL ops\n");
+ act = act->next;
+ kfree(a);
}
}
}
-int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+int
+tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
int err = -EINVAL;
-
- if ( (NULL == a) || (NULL == a->ops)
- || (NULL == a->ops->dump) )
+ if (a->ops == NULL || a->ops->dump == NULL)
return err;
return a->ops->dump(skb, a, bind, ref);
-
}
-
-int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+int
+tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
int err = -EINVAL;
- unsigned char *b = skb->tail;
+ unsigned char *b = skb->tail;
struct rtattr *r;
-
- if ( (NULL == a) || (NULL == a->ops)
- || (NULL == a->ops->dump) || (NULL == a->ops->kind))
+ if (a->ops == NULL || a->ops->dump == NULL)
return err;
-
RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind);
- if (tcf_action_copy_stats(skb,a))
+ if (tcf_action_copy_stats(skb, a))
goto rtattr_failure;
r = (struct rtattr*) skb->tail;
RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
@@ -261,18 +237,17 @@ int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int re
return err;
}
-
rtattr_failure:
skb_trim(skb, b - skb->data);
return -1;
-
}
-int tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int ref)
+int
+tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int ref)
{
struct tc_action *a;
int err = -EINVAL;
- unsigned char *b = skb->tail;
+ unsigned char *b = skb->tail;
struct rtattr *r ;
while ((a = act) != NULL) {
@@ -280,9 +255,8 @@ int tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int re
act = a->next;
RTA_PUT(skb, a->order, 0, NULL);
err = tcf_action_dump_1(skb, a, bind, ref);
- if (0 > err)
+ if (err < 0)
goto rtattr_failure;
-
r->rta_len = skb->tail - (u8*)r;
}
@@ -291,7 +265,6 @@ int tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int re
rtattr_failure:
skb_trim(skb, b - skb->data);
return -err;
-
}
struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est,
@@ -299,76 +272,70 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est,
{
struct tc_action *a;
struct tc_action_ops *a_o;
- char act_name[4 + IFNAMSIZ + 1];
+ char act_name[IFNAMSIZ];
struct rtattr *tb[TCA_ACT_MAX+1];
- struct rtattr *kind = NULL;
+ struct rtattr *kind;
*err = -EINVAL;
- if (NULL == name) {
- if (rtattr_parse(tb, TCA_ACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta))<0)
+ if (name == NULL) {
+ if (rtattr_parse_nested(tb, TCA_ACT_MAX, rta) < 0)
goto err_out;
kind = tb[TCA_ACT_KIND-1];
- if (NULL != kind) {
- sprintf(act_name, "%s", (char*)RTA_DATA(kind));
- if (RTA_PAYLOAD(kind) >= IFNAMSIZ) {
- printk(" Action %s bad\n", (char*)RTA_DATA(kind));
- goto err_out;
- }
-
- } else {
- printk("Action bad kind\n");
+ if (kind == NULL)
+ goto err_out;
+ if (rtattr_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
goto err_out;
- }
- a_o = tc_lookup_action(kind);
} else {
- sprintf(act_name, "%s", name);
- DPRINTK("tcf_action_init_1: finding %s\n",act_name);
- a_o = tc_lookup_action_n(name);
+ if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ)
+ goto err_out;
}
+
+ a_o = tc_lookup_action_n(act_name);
+ if (a_o == NULL) {
#ifdef CONFIG_KMOD
- if (NULL == a_o) {
- DPRINTK("tcf_action_init_1: trying to load module %s\n",act_name);
- request_module (act_name);
+ rtnl_unlock();
+ request_module(act_name);
+ rtnl_lock();
+
a_o = tc_lookup_action_n(act_name);
- }
+ /* We dropped the RTNL semaphore in order to
+ * perform the module load. So, even if we
+ * succeeded in loading the module we have to
+ * tell the caller to replay the request. We
+ * indicate this using -EAGAIN.
+ */
+ if (a_o != NULL) {
+ *err = -EAGAIN;
+ goto err_mod;
+ }
#endif
- if (NULL == a_o) {
- printk("failed to find %s\n",act_name);
goto err_out;
}
+ *err = -ENOMEM;
a = kmalloc(sizeof(*a), GFP_KERNEL);
- if (a == NULL) {
- *err = -ENOMEM;
+ if (a == NULL)
goto err_mod;
- }
memset(a, 0, sizeof(*a));
/* backward compatibility for policer */
- if (NULL == name) {
+ if (name == NULL)
*err = a_o->init(tb[TCA_ACT_OPTIONS-1], est, a, ovr, bind);
- if (*err < 0) {
- *err = -EINVAL;
- goto err_free;
- }
- } else {
+ else
*err = a_o->init(rta, est, a, ovr, bind);
- if (*err < 0) {
- *err = -EINVAL;
- goto err_free;
- }
- }
+ if (*err < 0)
+ goto err_free;
/* module count goes up only when brand new policy is created
if it exists and is only bound to in a_o->init() then
- ACT_P_CREATED is not returned (a zero is).
- */
+ ACT_P_CREATED is not returned (a zero is).
+ */
if (*err != ACT_P_CREATED)
module_put(a_o->owner);
a->ops = a_o;
- DPRINTK("tcf_action_init_1: successfull %s \n",act_name);
+ DPRINTK("tcf_action_init_1: successfull %s\n", act_name);
*err = 0;
return a;
@@ -385,51 +352,41 @@ struct tc_action *tcf_action_init(struct rtattr *rta, struct rtattr *est,
char *name, int ovr, int bind, int *err)
{
struct rtattr *tb[TCA_ACT_MAX_PRIO+1];
- struct tc_action *a = NULL, *act, *act_prev = NULL;
+ struct tc_action *head = NULL, *act, *act_prev = NULL;
int i;
- if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(rta),
- RTA_PAYLOAD(rta)) < 0) {
+ if (rtattr_parse_nested(tb, TCA_ACT_MAX_PRIO, rta) < 0) {
*err = -EINVAL;
- return a;
+ return head;
}
- for (i=0; i < TCA_ACT_MAX_PRIO; i++) {
- if (tb[i]) {
- act = tcf_action_init_1(tb[i], est, name, ovr, bind, err);
- if (act == NULL) {
- printk("Error processing action order %d\n", i);
- goto bad_ret;
- }
-
- act->order = i+1;
- if (a == NULL)
- a = act;
- else
- act_prev->next = act;
- act_prev = act;
- }
+ for (i=0; i < TCA_ACT_MAX_PRIO && tb[i]; i++) {
+ act = tcf_action_init_1(tb[i], est, name, ovr, bind, err);
+ if (act == NULL)
+ goto err;
+ act->order = i+1;
+ if (head == NULL)
+ head = act;
+ else
+ act_prev->next = act;
+ act_prev = act;
}
- return a;
+ return head;
-bad_ret:
- if (a != NULL)
- tcf_action_destroy(a, bind);
+err:
+ if (head != NULL)
+ tcf_action_destroy(head, bind);
return NULL;
}
-int tcf_action_copy_stats (struct sk_buff *skb,struct tc_action *a)
+int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a)
{
int err;
struct gnet_dump d;
struct tcf_act_hdr *h = a->priv;
-#ifdef CONFIG_KMOD
- /* place holder */
-#endif
-
- if (NULL == h)
+ if (h == NULL)
goto errout;
if (a->type == TCA_OLD_COMPAT)
@@ -442,7 +399,7 @@ int tcf_action_copy_stats (struct sk_buff *skb,struct tc_action *a)
if (err < 0)
goto errout;
- if (NULL != a->ops && NULL != a->ops->get_stats)
+ if (a->ops != NULL && a->ops->get_stats != NULL)
if (a->ops->get_stats(skb, a) < 0)
goto errout;
@@ -462,14 +419,13 @@ errout:
return -1;
}
-
static int
-tca_get_fill(struct sk_buff *skb, struct tc_action *a,
- u32 pid, u32 seq, unsigned flags, int event, int bind, int ref)
+tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 pid, u32 seq,
+ unsigned flags, int event, int bind, int ref)
{
struct tcamsg *t;
- struct nlmsghdr *nlh;
- unsigned char *b = skb->tail;
+ struct nlmsghdr *nlh;
+ unsigned char *b = skb->tail;
struct rtattr *x;
nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*t));
@@ -480,9 +436,8 @@ tca_get_fill(struct sk_buff *skb, struct tc_action *a,
x = (struct rtattr*) skb->tail;
RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
- if (0 > tcf_action_dump(skb, a, bind, ref)) {
+ if (tcf_action_dump(skb, a, bind, ref) < 0)
goto rtattr_failure;
- }
x->rta_len = skb->tail - (u8*)x;
@@ -495,160 +450,88 @@ nlmsg_failure:
return -1;
}
-static int act_get_notify(u32 pid, struct nlmsghdr *n,
- struct tc_action *a, int event)
+static int
+act_get_notify(u32 pid, struct nlmsghdr *n, struct tc_action *a, int event)
{
struct sk_buff *skb;
-
int err = 0;
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb)
return -ENOBUFS;
-
- if (tca_get_fill(skb, a, pid, n->nlmsg_seq, 0, event, 0, 0) <= 0) {
+ if (tca_get_fill(skb, a, pid, n->nlmsg_seq, 0, event, 0, 0) <= 0) {
kfree_skb(skb);
return -EINVAL;
}
-
- err = netlink_unicast(rtnl,skb, pid, MSG_DONTWAIT);
+ err = netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
if (err > 0)
err = 0;
return err;
}
-static int tcf_action_get_1(struct rtattr *rta, struct tc_action *a, struct nlmsghdr *n, u32 pid)
+static struct tc_action *
+tcf_action_get_1(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int *err)
{
- struct tc_action_ops *a_o;
- char act_name[4 + IFNAMSIZ + 1];
struct rtattr *tb[TCA_ACT_MAX+1];
- struct rtattr *kind = NULL;
+ struct tc_action *a;
int index;
- int err = -EINVAL;
-
- if (rtattr_parse(tb, TCA_ACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta))<0)
- goto err_out;
-
-
- kind = tb[TCA_ACT_KIND-1];
- if (NULL != kind) {
- sprintf(act_name, "%s", (char*)RTA_DATA(kind));
- if (RTA_PAYLOAD(kind) >= IFNAMSIZ) {
- printk("tcf_action_get_1: action %s bad\n", (char*)RTA_DATA(kind));
- goto err_out;
- }
-
- } else {
- printk("tcf_action_get_1: action bad kind\n");
- goto err_out;
- }
-
- if (tb[TCA_ACT_INDEX - 1]) {
- index = *(int *)RTA_DATA(tb[TCA_ACT_INDEX - 1]);
- } else {
- printk("tcf_action_get_1: index not received\n");
- goto err_out;
- }
+ *err = -EINVAL;
+ if (rtattr_parse_nested(tb, TCA_ACT_MAX, rta) < 0)
+ return NULL;
- a_o = tc_lookup_action(kind);
-#ifdef CONFIG_KMOD
- if (NULL == a_o) {
- request_module (act_name);
- a_o = tc_lookup_action_n(act_name);
- }
+ if (tb[TCA_ACT_INDEX - 1] == NULL ||
+ RTA_PAYLOAD(tb[TCA_ACT_INDEX - 1]) < sizeof(index))
+ return NULL;
+ index = *(int *)RTA_DATA(tb[TCA_ACT_INDEX - 1]);
-#endif
- if (NULL == a_o) {
- printk("failed to find %s\n",act_name);
- goto err_out;
- }
+ *err = -ENOMEM;
+ a = kmalloc(sizeof(struct tc_action), GFP_KERNEL);
+ if (a == NULL)
+ return NULL;
+ memset(a, 0, sizeof(struct tc_action));
- if (NULL == a) {
+ *err = -EINVAL;
+ a->ops = tc_lookup_action(tb[TCA_ACT_KIND - 1]);
+ if (a->ops == NULL)
+ goto err_free;
+ if (a->ops->lookup == NULL)
goto err_mod;
- }
-
- a->ops = a_o;
-
- if (NULL == a_o->lookup || 0 == a_o->lookup(a, index)) {
- a->ops = NULL;
- err = -EINVAL;
+ *err = -ENOENT;
+ if (a->ops->lookup(a, index) == 0)
goto err_mod;
- }
- module_put(a_o->owner);
- return 0;
+ module_put(a->ops->owner);
+ *err = 0;
+ return a;
err_mod:
- module_put(a_o->owner);
-err_out:
- return err;
+ module_put(a->ops->owner);
+err_free:
+ kfree(a);
+ return NULL;
}
-static void cleanup_a (struct tc_action *act)
+static void cleanup_a(struct tc_action *act)
{
struct tc_action *a;
- for (a = act; act; a = act) {
- if (a) {
- act = act->next;
- a->ops = NULL;
- a->priv = NULL;
- kfree(a);
- } else {
- printk("cleanup_a: BUG? empty action\n");
- }
- }
-}
-
-static struct tc_action_ops *get_ao(struct rtattr *kind, struct tc_action *a)
-{
- char act_name[4 + IFNAMSIZ + 1];
- struct tc_action_ops *a_o = NULL;
-
- if (NULL != kind) {
- sprintf(act_name, "%s", (char*)RTA_DATA(kind));
- if (RTA_PAYLOAD(kind) >= IFNAMSIZ) {
- printk("get_ao: action %s bad\n", (char*)RTA_DATA(kind));
- return NULL;
- }
-
- } else {
- printk("get_ao: action bad kind\n");
- return NULL;
- }
-
- a_o = tc_lookup_action(kind);
-#ifdef CONFIG_KMOD
- if (NULL == a_o) {
- DPRINTK("get_ao: trying to load module %s\n",act_name);
- request_module (act_name);
- a_o = tc_lookup_action_n(act_name);
- }
-#endif
-
- if (NULL == a_o) {
- printk("get_ao: failed to find %s\n",act_name);
- return NULL;
+ for (a = act; a; a = act) {
+ act = a->next;
+ kfree(a);
}
-
- a->ops = a_o;
- return a_o;
}
static struct tc_action *create_a(int i)
{
- struct tc_action *act = NULL;
+ struct tc_action *act;
- act = kmalloc(sizeof(*act),GFP_KERNEL);
- if (NULL == act) { /* grrr .. */
- printk("create_a: failed to alloc! \n");
+ act = kmalloc(sizeof(*act), GFP_KERNEL);
+ if (act == NULL) {
+ printk("create_a: failed to alloc!\n");
return NULL;
}
-
- memset(act, 0,sizeof(*act));
-
+ memset(act, 0, sizeof(*act));
act->order = i;
-
return act;
}
@@ -661,11 +544,11 @@ static int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
struct netlink_callback dcb;
struct rtattr *x;
struct rtattr *tb[TCA_ACT_MAX+1];
- struct rtattr *kind = NULL;
+ struct rtattr *kind;
struct tc_action *a = create_a(0);
int err = -EINVAL;
- if (NULL == a) {
+ if (a == NULL) {
printk("tca_action_flush: couldnt create tc_action\n");
return err;
}
@@ -679,16 +562,15 @@ static int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
b = (unsigned char *)skb->tail;
- if (rtattr_parse(tb, TCA_ACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta))<0) {
+ if (rtattr_parse_nested(tb, TCA_ACT_MAX, rta) < 0)
goto err_out;
- }
kind = tb[TCA_ACT_KIND-1];
- if (NULL == get_ao(kind, a)) {
+ a->ops = tc_lookup_action(kind);
+ if (a->ops == NULL)
goto err_out;
- }
- nlh = NLMSG_PUT(skb, pid, n->nlmsg_seq, RTM_DELACTION, sizeof (*t));
+ nlh = NLMSG_PUT(skb, pid, n->nlmsg_seq, RTM_DELACTION, sizeof(*t));
t = NLMSG_DATA(nlh);
t->tca_family = AF_UNSPEC;
@@ -696,9 +578,8 @@ static int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
err = a->ops->walk(skb, &dcb, RTM_DELACTION, a);
- if (0 > err ) {
+ if (err < 0)
goto rtattr_failure;
- }
x->rta_len = skb->tail - (u8 *) x;
@@ -712,7 +593,6 @@ static int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
return err;
-
rtattr_failure:
module_put(a->ops->owner);
nlmsg_failure:
@@ -722,99 +602,73 @@ err_out:
return err;
}
-static int tca_action_gd(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int event )
+static int
+tca_action_gd(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int event)
{
-
- int s = 0;
int i, ret = 0;
- struct tc_action *act = NULL;
struct rtattr *tb[TCA_ACT_MAX_PRIO+1];
- struct tc_action *a = NULL, *a_s = NULL;
-
- if (event != RTM_GETACTION && event != RTM_DELACTION)
- ret = -EINVAL;
+ struct tc_action *head = NULL, *act, *act_prev = NULL;
- if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(rta), RTA_PAYLOAD(rta))<0) {
- ret = -EINVAL;
- goto nlmsg_failure;
- }
+ if (rtattr_parse_nested(tb, TCA_ACT_MAX_PRIO, rta) < 0)
+ return -EINVAL;
if (event == RTM_DELACTION && n->nlmsg_flags&NLM_F_ROOT) {
- if (NULL != tb[0] && NULL == tb[1]) {
- return tca_action_flush(tb[0],n,pid);
- }
+ if (tb[0] != NULL && tb[1] == NULL)
+ return tca_action_flush(tb[0], n, pid);
}
- for (i=0; i < TCA_ACT_MAX_PRIO ; i++) {
-
- if (NULL == tb[i])
- break;
-
- act = create_a(i+1);
- if (NULL != a && a != act) {
- a->next = act;
- a = act;
- } else {
- a = act;
- }
-
- if (!s) {
- s = 1;
- a_s = a;
- }
-
- ret = tcf_action_get_1(tb[i],act,n,pid);
- if (ret < 0) {
- printk("tcf_action_get: failed to get! \n");
- ret = -EINVAL;
- goto rtattr_failure;
- }
+ for (i=0; i < TCA_ACT_MAX_PRIO && tb[i]; i++) {
+ act = tcf_action_get_1(tb[i], n, pid, &ret);
+ if (act == NULL)
+ goto err;
+ act->order = i+1;
+ if (head == NULL)
+ head = act;
+ else
+ act_prev->next = act;
+ act_prev = act;
}
-
- if (RTM_GETACTION == event) {
- ret = act_get_notify(pid, n, a_s, event);
- } else { /* delete */
-
+ if (event == RTM_GETACTION)
+ ret = act_get_notify(pid, n, head, event);
+ else { /* delete */
struct sk_buff *skb;
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb) {
ret = -ENOBUFS;
- goto nlmsg_failure;
+ goto err;
}
- if (tca_get_fill(skb, a_s, pid, n->nlmsg_seq, 0, event, 0 , 1) <= 0) {
+ if (tca_get_fill(skb, head, pid, n->nlmsg_seq, 0, event,
+ 0, 1) <= 0) {
kfree_skb(skb);
ret = -EINVAL;
- goto nlmsg_failure;
+ goto err;
}
/* now do the delete */
- tcf_action_destroy(a_s, 0);
-
- ret = rtnetlink_send(skb, pid, RTMGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+ tcf_action_destroy(head, 0);
+ ret = rtnetlink_send(skb, pid, RTMGRP_TC,
+ n->nlmsg_flags&NLM_F_ECHO);
if (ret > 0)
return 0;
return ret;
}
-rtattr_failure:
-nlmsg_failure:
- cleanup_a(a_s);
+err:
+ cleanup_a(head);
return ret;
}
-
-static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, unsigned flags)
+static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event,
+ unsigned flags)
{
struct tcamsg *t;
- struct nlmsghdr *nlh;
+ struct nlmsghdr *nlh;
struct sk_buff *skb;
struct rtattr *x;
unsigned char *b;
-
-
int err = 0;
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
@@ -831,9 +685,8 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, unsi
x = (struct rtattr*) skb->tail;
RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
- if (0 > tcf_action_dump(skb, a, 0, 0)) {
+ if (tcf_action_dump(skb, a, 0, 0) < 0)
goto rtattr_failure;
- }
x->rta_len = skb->tail - (u8*)x;
@@ -843,7 +696,6 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, unsi
err = rtnetlink_send(skb, pid, RTMGRP_TC, flags&NLM_F_ECHO);
if (err > 0)
err = 0;
-
return err;
rtattr_failure:
@@ -853,11 +705,12 @@ nlmsg_failure:
}
-static int tcf_action_add(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int ovr )
+static int
+tcf_action_add(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int ovr)
{
int ret = 0;
- struct tc_action *act = NULL;
- struct tc_action *a = NULL;
+ struct tc_action *act;
+ struct tc_action *a;
u32 seq = n->nlmsg_seq;
act = tcf_action_init(rta, NULL, NULL, ovr, 0, &ret);
@@ -867,16 +720,10 @@ static int tcf_action_add(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int o
/* dump then free all the actions after update; inserted policy
* stays intact
* */
- ret = tcf_add_notify(act, pid, seq, RTM_NEWACTION, n->nlmsg_flags);
- for (a = act; act; a = act) {
- if (a) {
- act = act->next;
- a->ops = NULL;
- a->priv = NULL;
- kfree(a);
- } else {
- printk("tcf_action_add: BUG? empty action\n");
- }
+ ret = tcf_add_notify(act, pid, seq, RTM_NEWACTION, n->nlmsg_flags);
+ for (a = act; a; a = act) {
+ act = a->next;
+ kfree(a);
}
done:
return ret;
@@ -886,38 +733,38 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{
struct rtattr **tca = arg;
u32 pid = skb ? NETLINK_CB(skb).pid : 0;
-
int ret = 0, ovr = 0;
- if (NULL == tca[TCA_ACT_TAB-1]) {
- printk("tc_ctl_action: received NO action attribs\n");
- return -EINVAL;
+ if (tca[TCA_ACT_TAB-1] == NULL) {
+ printk("tc_ctl_action: received NO action attribs\n");
+ return -EINVAL;
}
/* n->nlmsg_flags&NLM_F_CREATE
* */
switch (n->nlmsg_type) {
- case RTM_NEWACTION:
+ case RTM_NEWACTION:
/* we are going to assume all other flags
* imply create only if it doesnt exist
* Note that CREATE | EXCL implies that
* but since we want avoid ambiguity (eg when flags
* is zero) then just set this
*/
- if (n->nlmsg_flags&NLM_F_REPLACE) {
+ if (n->nlmsg_flags&NLM_F_REPLACE)
ovr = 1;
- }
- ret = tcf_action_add(tca[TCA_ACT_TAB-1], n, pid, ovr);
+replay:
+ ret = tcf_action_add(tca[TCA_ACT_TAB-1], n, pid, ovr);
+ if (ret == -EAGAIN)
+ goto replay;
break;
case RTM_DELACTION:
- ret = tca_action_gd(tca[TCA_ACT_TAB-1], n, pid,RTM_DELACTION);
+ ret = tca_action_gd(tca[TCA_ACT_TAB-1], n, pid, RTM_DELACTION);
break;
case RTM_GETACTION:
- ret = tca_action_gd(tca[TCA_ACT_TAB-1], n, pid,RTM_GETACTION);
+ ret = tca_action_gd(tca[TCA_ACT_TAB-1], n, pid, RTM_GETACTION);
break;
default:
- printk(" Unknown cmd was detected\n");
- break;
+ BUG();
}
return ret;
@@ -929,25 +776,25 @@ find_dump_kind(struct nlmsghdr *n)
struct rtattr *tb1, *tb2[TCA_ACT_MAX+1];
struct rtattr *tb[TCA_ACT_MAX_PRIO + 1];
struct rtattr *rta[TCAA_MAX + 1];
- struct rtattr *kind = NULL;
- int min_len = NLMSG_LENGTH(sizeof (struct tcamsg));
-
+ struct rtattr *kind;
+ int min_len = NLMSG_LENGTH(sizeof(struct tcamsg));
int attrlen = n->nlmsg_len - NLMSG_ALIGN(min_len);
struct rtattr *attr = (void *) n + NLMSG_ALIGN(min_len);
if (rtattr_parse(rta, TCAA_MAX, attr, attrlen) < 0)
return NULL;
tb1 = rta[TCA_ACT_TAB - 1];
- if (NULL == tb1) {
+ if (tb1 == NULL)
return NULL;
- }
- if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(tb1), NLMSG_ALIGN(RTA_PAYLOAD(tb1))) < 0)
+ if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(tb1),
+ NLMSG_ALIGN(RTA_PAYLOAD(tb1))) < 0)
return NULL;
- if (NULL == tb[0])
+ if (tb[0] == NULL)
return NULL;
- if (rtattr_parse(tb2, TCA_ACT_MAX, RTA_DATA(tb[0]), RTA_PAYLOAD(tb[0]))<0)
+ if (rtattr_parse(tb2, TCA_ACT_MAX, RTA_DATA(tb[0]),
+ RTA_PAYLOAD(tb[0])) < 0)
return NULL;
kind = tb2[TCA_ACT_KIND-1];
@@ -963,30 +810,30 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
struct tc_action_ops *a_o;
struct tc_action a;
int ret = 0;
-
struct tcamsg *t = (struct tcamsg *) NLMSG_DATA(cb->nlh);
char *kind = find_dump_kind(cb->nlh);
- if (NULL == kind) {
+
+ if (kind == NULL) {
printk("tc_dump_action: action bad kind\n");
return 0;
}
a_o = tc_lookup_action_n(kind);
-
- if (NULL == a_o) {
+ if (a_o == NULL) {
printk("failed to find %s\n", kind);
return 0;
}
- memset(&a,0,sizeof(struct tc_action));
+ memset(&a, 0, sizeof(struct tc_action));
a.ops = a_o;
- if (NULL == a_o->walk) {
- printk("tc_dump_action: %s !capable of dumping table\n",kind);
+ if (a_o->walk == NULL) {
+ printk("tc_dump_action: %s !capable of dumping table\n", kind);
goto rtattr_failure;
}
- nlh = NLMSG_PUT(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, cb->nlh->nlmsg_type, sizeof (*t));
+ nlh = NLMSG_PUT(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
+ cb->nlh->nlmsg_type, sizeof(*t));
t = NLMSG_DATA(nlh);
t->tca_family = AF_UNSPEC;
@@ -994,19 +841,17 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
ret = a_o->walk(skb, cb, RTM_GETACTION, &a);
- if (0 > ret ) {
+ if (ret < 0)
goto rtattr_failure;
- }
if (ret > 0) {
x->rta_len = skb->tail - (u8 *) x;
ret = skb->len;
- } else {
+ } else
skb_trim(skb, (u8*)x - skb->data);
- }
nlh->nlmsg_len = skb->tail - b;
- if (NETLINK_CB(cb->skb).pid && ret)
+ if (NETLINK_CB(cb->skb).pid && ret)
nlh->nlmsg_flags |= NLM_F_MULTI;
module_put(a_o->owner);
return skb->len;
@@ -1029,7 +874,8 @@ static int __init tc_action_init(void)
link_p[RTM_GETACTION-RTM_BASE].dumpit = tc_dump_action;
}
- printk("TC classifier action (bugs to netdev@oss.sgi.com cc hadi@cyberus.ca)\n");
+ printk("TC classifier action (bugs to netdev@oss.sgi.com cc "
+ "hadi@cyberus.ca)\n");
return 0;
}
@@ -1037,11 +883,5 @@ subsys_initcall(tc_action_init);
EXPORT_SYMBOL(tcf_register_action);
EXPORT_SYMBOL(tcf_unregister_action);
-EXPORT_SYMBOL(tcf_action_init_1);
-EXPORT_SYMBOL(tcf_action_init);
-EXPORT_SYMBOL(tcf_action_destroy);
EXPORT_SYMBOL(tcf_action_exec);
-EXPORT_SYMBOL(tcf_action_copy_stats);
-EXPORT_SYMBOL(tcf_action_dump);
EXPORT_SYMBOL(tcf_action_dump_1);
-EXPORT_SYMBOL(tcf_action_dump_old);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 520312cd4738..a780c51defea 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -49,7 +49,7 @@
static struct tcf_proto_ops *tcf_proto_base;
/* Protects list of registered TC modules. It is pure SMP lock. */
-static rwlock_t cls_mod_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(cls_mod_lock);
/* Find classifier type by string name */
@@ -130,22 +130,31 @@ static __inline__ u32 tcf_auto_prio(struct tcf_proto *tp)
static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{
- struct rtattr **tca = arg;
- struct tcmsg *t = NLMSG_DATA(n);
- u32 protocol = TC_H_MIN(t->tcm_info);
- u32 prio = TC_H_MAJ(t->tcm_info);
- u32 nprio = prio;
- u32 parent = t->tcm_parent;
+ struct rtattr **tca;
+ struct tcmsg *t;
+ u32 protocol;
+ u32 prio;
+ u32 nprio;
+ u32 parent;
struct net_device *dev;
struct Qdisc *q;
struct tcf_proto **back, **chain;
- struct tcf_proto *tp = NULL;
+ struct tcf_proto *tp;
struct tcf_proto_ops *tp_ops;
struct Qdisc_class_ops *cops;
- unsigned long cl = 0;
+ unsigned long cl;
unsigned long fh;
int err;
+replay:
+ tca = arg;
+ t = NLMSG_DATA(n);
+ protocol = TC_H_MIN(t->tcm_info);
+ prio = TC_H_MAJ(t->tcm_info);
+ nprio = prio;
+ parent = t->tcm_parent;
+ cl = 0;
+
if (prio == 0) {
/* If no priority is given, user wants we allocated it. */
if (n->nlmsg_type != RTM_NEWTFILTER || !(n->nlmsg_flags&NLM_F_CREATE))
@@ -211,19 +220,29 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
err = -ENOBUFS;
if ((tp = kmalloc(sizeof(*tp), GFP_KERNEL)) == NULL)
goto errout;
+ err = -EINVAL;
tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND-1]);
+ if (tp_ops == NULL) {
#ifdef CONFIG_KMOD
- if (tp_ops==NULL && tca[TCA_KIND-1] != NULL) {
struct rtattr *kind = tca[TCA_KIND-1];
+ char name[IFNAMSIZ];
- if (RTA_PAYLOAD(kind) <= IFNAMSIZ) {
- request_module("cls_%s", (char*)RTA_DATA(kind));
+ if (kind != NULL &&
+ rtattr_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
+ rtnl_unlock();
+ request_module("cls_%s", name);
+ rtnl_lock();
tp_ops = tcf_proto_lookup_ops(kind);
+ /* We dropped the RTNL semaphore in order to
+ * perform the module load. So, even if we
+ * succeeded in loading the module we have to
+ * replay the request. We indicate this using
+ * -EAGAIN.
+ */
+ if (tp_ops != NULL)
+ err = -EAGAIN;
}
- }
#endif
- if (tp_ops == NULL) {
- err = -EINVAL;
kfree(tp);
goto errout;
}
@@ -293,6 +312,9 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
errout:
if (cl)
cops->put(q, cl);
+ if (err == -EAGAIN)
+ /* Replay the request. */
+ goto replay;
return err;
}
@@ -439,6 +461,154 @@ out:
return skb->len;
}
+void
+tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts)
+{
+#ifdef CONFIG_NET_CLS_ACT
+ if (exts->action) {
+ tcf_action_destroy(exts->action, TCA_ACT_UNBIND);
+ exts->action = NULL;
+ }
+#elif defined CONFIG_NET_CLS_POLICE
+ if (exts->police) {
+ tcf_police_release(exts->police, TCA_ACT_UNBIND);
+ exts->police = NULL;
+ }
+#endif
+}
+
+
+int
+tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,
+ struct rtattr *rate_tlv, struct tcf_exts *exts,
+ struct tcf_ext_map *map)
+{
+ memset(exts, 0, sizeof(*exts));
+
+#ifdef CONFIG_NET_CLS_ACT
+ int err;
+ struct tc_action *act;
+
+ if (map->police && tb[map->police-1]) {
+ act = tcf_action_init_1(tb[map->police-1], rate_tlv, "police",
+ TCA_ACT_NOREPLACE, TCA_ACT_BIND, &err);
+ if (act == NULL)
+ return err;
+
+ act->type = TCA_OLD_COMPAT;
+ exts->action = act;
+ } else if (map->action && tb[map->action-1]) {
+ act = tcf_action_init(tb[map->action-1], rate_tlv, NULL,
+ TCA_ACT_NOREPLACE, TCA_ACT_BIND, &err);
+ if (act == NULL)
+ return err;
+
+ exts->action = act;
+ }
+#elif defined CONFIG_NET_CLS_POLICE
+ if (map->police && tb[map->police-1]) {
+ struct tcf_police *p;
+
+ p = tcf_police_locate(tb[map->police-1], rate_tlv);
+ if (p == NULL)
+ return -EINVAL;
+
+ exts->police = p;
+ } else if (map->action && tb[map->action-1])
+ return -EOPNOTSUPP;
+#else
+ if ((map->action && tb[map->action-1]) ||
+ (map->police && tb[map->police-1]))
+ return -EOPNOTSUPP;
+#endif
+
+ return 0;
+}
+
+void
+tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
+ struct tcf_exts *src)
+{
+#ifdef CONFIG_NET_CLS_ACT
+ if (src->action) {
+ struct tc_action *act;
+ tcf_tree_lock(tp);
+ act = xchg(&dst->action, src->action);
+ tcf_tree_unlock(tp);
+ if (act)
+ tcf_action_destroy(act, TCA_ACT_UNBIND);
+ }
+#elif defined CONFIG_NET_CLS_POLICE
+ if (src->police) {
+ struct tcf_police *p;
+ tcf_tree_lock(tp);
+ p = xchg(&dst->police, src->police);
+ tcf_tree_unlock(tp);
+ if (p)
+ tcf_police_release(p, TCA_ACT_UNBIND);
+ }
+#endif
+}
+
+int
+tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
+ struct tcf_ext_map *map)
+{
+#ifdef CONFIG_NET_CLS_ACT
+ if (map->action && exts->action) {
+ /*
+ * again for backward compatible mode - we want
+ * to work with both old and new modes of entering
+ * tc data even if iproute2 was newer - jhs
+ */
+ struct rtattr * p_rta = (struct rtattr*) skb->tail;
+
+ if (exts->action->type != TCA_OLD_COMPAT) {
+ RTA_PUT(skb, map->action, 0, NULL);
+ if (tcf_action_dump(skb, exts->action, 0, 0) < 0)
+ goto rtattr_failure;
+ p_rta->rta_len = skb->tail - (u8*)p_rta;
+ } else if (map->police) {
+ RTA_PUT(skb, map->police, 0, NULL);
+ if (tcf_action_dump_old(skb, exts->action, 0, 0) < 0)
+ goto rtattr_failure;
+ p_rta->rta_len = skb->tail - (u8*)p_rta;
+ }
+ }
+#elif defined CONFIG_NET_CLS_POLICE
+ if (map->police && exts->police) {
+ struct rtattr * p_rta = (struct rtattr*) skb->tail;
+
+ RTA_PUT(skb, map->police, 0, NULL);
+
+ if (tcf_police_dump(skb, exts->police) < 0)
+ goto rtattr_failure;
+
+ p_rta->rta_len = skb->tail - (u8*)p_rta;
+ }
+#endif
+ return 0;
+rtattr_failure: __attribute__ ((unused))
+ return -1;
+}
+
+int
+tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
+ struct tcf_ext_map *map)
+{
+#ifdef CONFIG_NET_CLS_ACT
+ if (exts->action)
+ if (tcf_action_copy_stats(skb, exts->action) < 0)
+ goto rtattr_failure;
+#elif defined CONFIG_NET_CLS_POLICE
+ if (exts->police)
+ if (tcf_police_dump_stats(skb, exts->police) < 0)
+ goto rtattr_failure;
+#endif
+ return 0;
+rtattr_failure: __attribute__ ((unused))
+ return -1;
+}
static int __init tc_filter_init(void)
{
@@ -461,3 +631,8 @@ subsys_initcall(tc_filter_init);
EXPORT_SYMBOL(register_tcf_proto_ops);
EXPORT_SYMBOL(unregister_tcf_proto_ops);
+EXPORT_SYMBOL(tcf_exts_validate);
+EXPORT_SYMBOL(tcf_exts_destroy);
+EXPORT_SYMBOL(tcf_exts_change);
+EXPORT_SYMBOL(tcf_exts_dump);
+EXPORT_SYMBOL(tcf_exts_dump_stats);
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 8c214cf8e6dd..fdfc83af3d1f 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -59,13 +59,12 @@ struct fw_filter
#ifdef CONFIG_NET_CLS_IND
char indev[IFNAMSIZ];
#endif /* CONFIG_NET_CLS_IND */
-#ifdef CONFIG_NET_CLS_ACT
- struct tc_action *action;
-#else /* CONFIG_NET_CLS_ACT */
-#ifdef CONFIG_NET_CLS_POLICE
- struct tcf_police *police;
-#endif /* CONFIG_NET_CLS_POLICE */
-#endif /* CONFIG_NET_CLS_ACT */
+ struct tcf_exts exts;
+};
+
+static struct tcf_ext_map fw_ext_map = {
+ .action = TCA_FW_ACT,
+ .police = TCA_FW_POLICE
};
static __inline__ int fw_hash(u32 handle)
@@ -78,6 +77,7 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
{
struct fw_head *head = (struct fw_head*)tp->root;
struct fw_filter *f;
+ int r;
#ifdef CONFIG_NETFILTER
u32 id = skb->nfmark;
#else
@@ -92,20 +92,11 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
if (!tcf_match_indev(skb, f->indev))
continue;
#endif /* CONFIG_NET_CLS_IND */
-#ifdef CONFIG_NET_CLS_ACT
- if (f->action) {
- int act_res = tcf_action_exec(skb, f->action, res);
- if (act_res >= 0)
- return act_res;
+ r = tcf_exts_exec(skb, &f->exts, res);
+ if (r < 0)
continue;
- }
-#else /* CONFIG_NET_CLS_ACT */
-#ifdef CONFIG_NET_CLS_POLICE
- if (f->police)
- return tcf_police(skb, f->police);
-#endif /* CONFIG_NET_CLS_POLICE */
-#endif /* CONFIG_NET_CLS_ACT */
- return 0;
+
+ return r;
}
}
} else {
@@ -144,6 +135,14 @@ static int fw_init(struct tcf_proto *tp)
return 0;
}
+static inline void
+fw_delete_filter(struct tcf_proto *tp, struct fw_filter *f)
+{
+ tcf_unbind_filter(tp, &f->res);
+ tcf_exts_destroy(tp, &f->exts);
+ kfree(f);
+}
+
static void fw_destroy(struct tcf_proto *tp)
{
struct fw_head *head = (struct fw_head*)xchg(&tp->root, NULL);
@@ -156,18 +155,7 @@ static void fw_destroy(struct tcf_proto *tp)
for (h=0; h<256; h++) {
while ((f=head->ht[h]) != NULL) {
head->ht[h] = f->next;
- tcf_unbind_filter(tp, &f->res);
-#ifdef CONFIG_NET_CLS_ACT
- if (f->action)
- tcf_action_destroy(f->action, TCA_ACT_UNBIND);
-#else /* CONFIG_NET_CLS_ACT */
-#ifdef CONFIG_NET_CLS_POLICE
- if (f->police)
- tcf_police_release(f->police, TCA_ACT_UNBIND);
-#endif /* CONFIG_NET_CLS_POLICE */
-#endif /* CONFIG_NET_CLS_ACT */
-
- kfree(f);
+ fw_delete_filter(tp, f);
}
}
kfree(head);
@@ -187,16 +175,7 @@ static int fw_delete(struct tcf_proto *tp, unsigned long arg)
tcf_tree_lock(tp);
*fp = f->next;
tcf_tree_unlock(tp);
- tcf_unbind_filter(tp, &f->res);
-#ifdef CONFIG_NET_CLS_ACT
- if (f->action)
- tcf_action_destroy(f->action,TCA_ACT_UNBIND);
-#else /* CONFIG_NET_CLS_ACT */
-#ifdef CONFIG_NET_CLS_POLICE
- tcf_police_release(f->police,TCA_ACT_UNBIND);
-#endif /* CONFIG_NET_CLS_POLICE */
-#endif /* CONFIG_NET_CLS_ACT */
- kfree(f);
+ fw_delete_filter(tp, f);
return 0;
}
}
@@ -208,8 +187,14 @@ static int
fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
struct rtattr **tb, struct rtattr **tca, unsigned long base)
{
- int err = -EINVAL;
+ struct tcf_exts e;
+ int err;
+ err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &fw_ext_map);
+ if (err < 0)
+ return err;
+
+ err = -EINVAL;
if (tb[TCA_FW_CLASSID-1]) {
if (RTA_PAYLOAD(tb[TCA_FW_CLASSID-1]) != sizeof(u32))
goto errout;
@@ -225,33 +210,11 @@ fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
}
#endif /* CONFIG_NET_CLS_IND */
-#ifdef CONFIG_NET_CLS_ACT
- if (tb[TCA_FW_POLICE-1]) {
- err = tcf_change_act_police(tp, &f->action, tb[TCA_FW_POLICE-1],
- tca[TCA_RATE-1]);
- if (err < 0)
- goto errout;
- }
+ tcf_exts_change(tp, &f->exts, &e);
- if (tb[TCA_FW_ACT-1]) {
- err = tcf_change_act(tp, &f->action, tb[TCA_FW_ACT-1],
- tca[TCA_RATE-1]);
- if (err < 0)
- goto errout;
- }
-#else /* CONFIG_NET_CLS_ACT */
-#ifdef CONFIG_NET_CLS_POLICE
- if (tb[TCA_FW_POLICE-1]) {
- err = tcf_change_police(tp, &f->police, tb[TCA_FW_POLICE-1],
- tca[TCA_RATE-1]);
- if (err < 0)
- goto errout;
- }
-#endif /* CONFIG_NET_CLS_POLICE */
-#endif /* CONFIG_NET_CLS_ACT */
-
- err = 0;
+ return 0;
errout:
+ tcf_exts_destroy(tp, &e);
return err;
}
@@ -269,7 +232,7 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,
if (!opt)
return handle ? -EINVAL : 0;
- if (rtattr_parse(tb, TCA_FW_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)) < 0)
+ if (rtattr_parse_nested(tb, TCA_FW_MAX, opt) < 0)
return -EINVAL;
if (f != NULL) {
@@ -357,15 +320,7 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
t->tcm_handle = f->id;
- if (!f->res.classid
-#ifdef CONFIG_NET_CLS_ACT
- && !f->action
-#else
-#ifdef CONFIG_NET_CLS_POLICE
- && !f->police
-#endif
-#endif
- )
+ if (!f->res.classid && !tcf_exts_is_available(&f->exts))
return skb->len;
rta = (struct rtattr*)b;
@@ -377,29 +332,15 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
if (strlen(f->indev))
RTA_PUT(skb, TCA_FW_INDEV, IFNAMSIZ, f->indev);
#endif /* CONFIG_NET_CLS_IND */
-#ifdef CONFIG_NET_CLS_ACT
- if (tcf_dump_act(skb, f->action, TCA_FW_ACT, TCA_FW_POLICE) < 0)
- goto rtattr_failure;
-#else /* CONFIG_NET_CLS_ACT */
-#ifdef CONFIG_NET_CLS_POLICE
- if (tcf_dump_police(skb, f->police, TCA_FW_POLICE) < 0)
+
+ if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0)
goto rtattr_failure;
-#endif /* CONFIG_NET_CLS_POLICE */
-#endif /* CONFIG_NET_CLS_ACT */
rta->rta_len = skb->tail - b;
-#ifdef CONFIG_NET_CLS_ACT
- if (f->action && f->action->type == TCA_OLD_COMPAT) {
- if (tcf_action_copy_stats(skb,f->action))
- goto rtattr_failure;
- }
-#else /* CONFIG_NET_CLS_ACT */
-#ifdef CONFIG_NET_CLS_POLICE
- if (f->police)
- if (tcf_police_dump_stats(skb, f->police) < 0)
- goto rtattr_failure;
-#endif /* CONFIG_NET_CLS_POLICE */
-#endif /* CONFIG_NET_CLS_ACT */
+
+ if (tcf_exts_dump_stats(skb, &f->exts, &fw_ext_map) < 0)
+ goto rtattr_failure;
+
return skb->len;
rtattr_failure:
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index 8dc252eac9e8..d057789645ce 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -59,6 +59,7 @@ struct route4_head
struct route4_bucket
{
+ /* 16 FROM buckets + 16 IIF buckets + 1 wildcard bucket */
struct route4_filter *ht[16+16+1];
};
@@ -69,22 +70,25 @@ struct route4_filter
int iif;
struct tcf_result res;
-#ifdef CONFIG_NET_CLS_POLICE
- struct tcf_police *police;
-#endif
-
+ struct tcf_exts exts;
u32 handle;
struct route4_bucket *bkt;
};
#define ROUTE4_FAILURE ((struct route4_filter*)(-1L))
+static struct tcf_ext_map route_ext_map = {
+ .police = TCA_ROUTE4_POLICE,
+ .action = TCA_ROUTE4_ACT
+};
+
static __inline__ int route4_fastmap_hash(u32 id, int iif)
{
return id&0xF;
}
-static void route4_reset_fastmap(struct net_device *dev, struct route4_head *head, u32 id)
+static inline
+void route4_reset_fastmap(struct net_device *dev, struct route4_head *head, u32 id)
{
spin_lock_bh(&dev->queue_lock);
memset(head->fastmap, 0, sizeof(head->fastmap));
@@ -121,19 +125,20 @@ static __inline__ int route4_hash_wild(void)
return 32;
}
-#ifdef CONFIG_NET_CLS_POLICE
-#define IF_ROUTE_POLICE \
-if (f->police) { \
- int pol_res = tcf_police(skb, f->police); \
- if (pol_res >= 0) return pol_res; \
- dont_cache = 1; \
- continue; \
-} \
-if (!dont_cache)
-#else
-#define IF_ROUTE_POLICE
-#endif
-
+#define ROUTE4_APPLY_RESULT() \
+ do { \
+ *res = f->res; \
+ if (tcf_exts_is_available(&f->exts)) { \
+ int r = tcf_exts_exec(skb, &f->exts, res); \
+ if (r < 0) { \
+ dont_cache = 1; \
+ continue; \
+ } \
+ return r; \
+ } else if (!dont_cache) \
+ route4_set_fastmap(head, id, iif, f); \
+ return 0; \
+ } while(0)
static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp,
struct tcf_result *res)
@@ -142,11 +147,8 @@ static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp,
struct dst_entry *dst;
struct route4_bucket *b;
struct route4_filter *f;
-#ifdef CONFIG_NET_CLS_POLICE
- int dont_cache = 0;
-#endif
u32 id, h;
- int iif;
+ int iif, dont_cache = 0;
if ((dst = skb->dst) == NULL)
goto failure;
@@ -172,29 +174,16 @@ static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp,
restart:
if ((b = head->table[h]) != NULL) {
- f = b->ht[route4_hash_from(id)];
+ for (f = b->ht[route4_hash_from(id)]; f; f = f->next)
+ if (f->id == id)
+ ROUTE4_APPLY_RESULT();
- for ( ; f; f = f->next) {
- if (f->id == id) {
- *res = f->res;
- IF_ROUTE_POLICE route4_set_fastmap(head, id, iif, f);
- return 0;
- }
- }
-
- for (f = b->ht[route4_hash_iif(iif)]; f; f = f->next) {
- if (f->iif == iif) {
- *res = f->res;
- IF_ROUTE_POLICE route4_set_fastmap(head, id, iif, f);
- return 0;
- }
- }
+ for (f = b->ht[route4_hash_iif(iif)]; f; f = f->next)
+ if (f->iif == iif)
+ ROUTE4_APPLY_RESULT();
- for (f = b->ht[route4_hash_wild()]; f; f = f->next) {
- *res = f->res;
- IF_ROUTE_POLICE route4_set_fastmap(head, id, iif, f);
- return 0;
- }
+ for (f = b->ht[route4_hash_wild()]; f; f = f->next)
+ ROUTE4_APPLY_RESULT();
}
if (h < 256) {
@@ -203,9 +192,7 @@ restart:
goto restart;
}
-#ifdef CONFIG_NET_CLS_POLICE
if (!dont_cache)
-#endif
route4_set_fastmap(head, id, iif, ROUTE4_FAILURE);
failure:
return -1;
@@ -220,7 +207,7 @@ old_method:
return -1;
}
-static u32 to_hash(u32 id)
+static inline u32 to_hash(u32 id)
{
u32 h = id&0xFF;
if (id&0x8000)
@@ -228,7 +215,7 @@ static u32 to_hash(u32 id)
return h;
}
-static u32 from_hash(u32 id)
+static inline u32 from_hash(u32 id)
{
id &= 0xFFFF;
if (id == 0xFFFF)
@@ -276,6 +263,14 @@ static int route4_init(struct tcf_proto *tp)
return 0;
}
+static inline void
+route4_delete_filter(struct tcf_proto *tp, struct route4_filter *f)
+{
+ tcf_unbind_filter(tp, &f->res);
+ tcf_exts_destroy(tp, &f->exts);
+ kfree(f);
+}
+
static void route4_destroy(struct tcf_proto *tp)
{
struct route4_head *head = xchg(&tp->root, NULL);
@@ -293,11 +288,7 @@ static void route4_destroy(struct tcf_proto *tp)
while ((f = b->ht[h2]) != NULL) {
b->ht[h2] = f->next;
- tcf_unbind_filter(tp, &f->res);
-#ifdef CONFIG_NET_CLS_POLICE
- tcf_police_release(f->police,TCA_ACT_UNBIND);
-#endif
- kfree(f);
+ route4_delete_filter(tp, f);
}
}
kfree(b);
@@ -327,11 +318,7 @@ static int route4_delete(struct tcf_proto *tp, unsigned long arg)
tcf_tree_unlock(tp);
route4_reset_fastmap(tp->q->dev, head, f->id);
- tcf_unbind_filter(tp, &f->res);
-#ifdef CONFIG_NET_CLS_POLICE
- tcf_police_release(f->police,TCA_ACT_UNBIND);
-#endif
- kfree(f);
+ route4_delete_filter(tp, f);
/* Strip tree */
@@ -351,108 +338,63 @@ static int route4_delete(struct tcf_proto *tp, unsigned long arg)
return 0;
}
-static int route4_change(struct tcf_proto *tp, unsigned long base,
- u32 handle,
- struct rtattr **tca,
- unsigned long *arg)
+static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
+ struct route4_filter *f, u32 handle, struct route4_head *head,
+ struct rtattr **tb, struct rtattr *est, int new)
{
- struct route4_head *head = tp->root;
- struct route4_filter *f, *f1, **ins_f;
- struct route4_bucket *b;
- struct rtattr *opt = tca[TCA_OPTIONS-1];
- struct rtattr *tb[TCA_ROUTE4_MAX];
- unsigned h1, h2;
int err;
+ u32 id = 0, to = 0, nhandle = 0x8000;
+ struct route4_filter *fp;
+ unsigned int h1;
+ struct route4_bucket *b;
+ struct tcf_exts e;
- if (opt == NULL)
- return handle ? -EINVAL : 0;
-
- if (rtattr_parse(tb, TCA_ROUTE4_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)) < 0)
- return -EINVAL;
-
- if ((f = (struct route4_filter*)*arg) != NULL) {
- if (f->handle != handle && handle)
- return -EINVAL;
- if (tb[TCA_ROUTE4_CLASSID-1]) {
- f->res.classid = *(u32*)RTA_DATA(tb[TCA_ROUTE4_CLASSID-1]);
- tcf_bind_filter(tp, &f->res, base);
- }
-#ifdef CONFIG_NET_CLS_POLICE
- if (tb[TCA_ROUTE4_POLICE-1]) {
- err = tcf_change_police(tp, &f->police,
- tb[TCA_ROUTE4_POLICE-1], tca[TCA_RATE-1]);
- if (err < 0)
- return err;
- }
-#endif
- return 0;
- }
-
- /* Now more serious part... */
-
- if (head == NULL) {
- head = kmalloc(sizeof(struct route4_head), GFP_KERNEL);
- if (head == NULL)
- return -ENOBUFS;
- memset(head, 0, sizeof(struct route4_head));
-
- tcf_tree_lock(tp);
- tp->root = head;
- tcf_tree_unlock(tp);
- }
-
- f = kmalloc(sizeof(struct route4_filter), GFP_KERNEL);
- if (f == NULL)
- return -ENOBUFS;
-
- memset(f, 0, sizeof(*f));
+ err = tcf_exts_validate(tp, tb, est, &e, &route_ext_map);
+ if (err < 0)
+ return err;
err = -EINVAL;
- f->handle = 0x8000;
+ if (tb[TCA_ROUTE4_CLASSID-1])
+ if (RTA_PAYLOAD(tb[TCA_ROUTE4_CLASSID-1]) < sizeof(u32))
+ goto errout;
+
if (tb[TCA_ROUTE4_TO-1]) {
- if (handle&0x8000)
+ if (new && handle & 0x8000)
goto errout;
- if (RTA_PAYLOAD(tb[TCA_ROUTE4_TO-1]) < 4)
+ if (RTA_PAYLOAD(tb[TCA_ROUTE4_TO-1]) < sizeof(u32))
goto errout;
- f->id = *(u32*)RTA_DATA(tb[TCA_ROUTE4_TO-1]);
- if (f->id > 0xFF)
+ to = *(u32*)RTA_DATA(tb[TCA_ROUTE4_TO-1]);
+ if (to > 0xFF)
goto errout;
- f->handle = f->id;
+ nhandle = to;
}
+
if (tb[TCA_ROUTE4_FROM-1]) {
- u32 sid;
if (tb[TCA_ROUTE4_IIF-1])
goto errout;
- if (RTA_PAYLOAD(tb[TCA_ROUTE4_FROM-1]) < 4)
+ if (RTA_PAYLOAD(tb[TCA_ROUTE4_FROM-1]) < sizeof(u32))
goto errout;
- sid = (*(u32*)RTA_DATA(tb[TCA_ROUTE4_FROM-1]));
- if (sid > 0xFF)
+ id = *(u32*)RTA_DATA(tb[TCA_ROUTE4_FROM-1]);
+ if (id > 0xFF)
goto errout;
- f->handle |= sid<<16;
- f->id |= sid<<16;
+ nhandle |= id << 16;
} else if (tb[TCA_ROUTE4_IIF-1]) {
- if (RTA_PAYLOAD(tb[TCA_ROUTE4_IIF-1]) < 4)
+ if (RTA_PAYLOAD(tb[TCA_ROUTE4_IIF-1]) < sizeof(u32))
goto errout;
- f->iif = *(u32*)RTA_DATA(tb[TCA_ROUTE4_IIF-1]);
- if (f->iif > 0x7FFF)
+ id = *(u32*)RTA_DATA(tb[TCA_ROUTE4_IIF-1]);
+ if (id > 0x7FFF)
goto errout;
- f->handle |= (f->iif|0x8000)<<16;
+ nhandle = (id | 0x8000) << 16;
} else
- f->handle |= 0xFFFF<<16;
+ nhandle = 0xFFFF << 16;
- if (handle) {
- f->handle |= handle&0x7F00;
- if (f->handle != handle)
+ if (handle && new) {
+ nhandle |= handle & 0x7F00;
+ if (nhandle != handle)
goto errout;
}
- if (tb[TCA_ROUTE4_CLASSID-1]) {
- if (RTA_PAYLOAD(tb[TCA_ROUTE4_CLASSID-1]) < 4)
- goto errout;
- f->res.classid = *(u32*)RTA_DATA(tb[TCA_ROUTE4_CLASSID-1]);
- }
-
- h1 = to_hash(f->handle);
+ h1 = to_hash(nhandle);
if ((b = head->table[h1]) == NULL) {
err = -ENOBUFS;
b = kmalloc(sizeof(struct route4_bucket), GFP_KERNEL);
@@ -463,27 +405,119 @@ static int route4_change(struct tcf_proto *tp, unsigned long base,
tcf_tree_lock(tp);
head->table[h1] = b;
tcf_tree_unlock(tp);
+ } else {
+ unsigned int h2 = from_hash(nhandle >> 16);
+ err = -EEXIST;
+ for (fp = b->ht[h2]; fp; fp = fp->next)
+ if (fp->handle == f->handle)
+ goto errout;
}
+
+ tcf_tree_lock(tp);
+ if (tb[TCA_ROUTE4_TO-1])
+ f->id = to;
+
+ if (tb[TCA_ROUTE4_FROM-1])
+ f->id = to | id<<16;
+ else if (tb[TCA_ROUTE4_IIF-1])
+ f->iif = id;
+
+ f->handle = nhandle;
f->bkt = b;
+ tcf_tree_unlock(tp);
- err = -EEXIST;
- h2 = from_hash(f->handle>>16);
- for (ins_f = &b->ht[h2]; (f1=*ins_f) != NULL; ins_f = &f1->next) {
- if (f->handle < f1->handle)
- break;
- if (f1->handle == f->handle)
+ if (tb[TCA_ROUTE4_CLASSID-1]) {
+ f->res.classid = *(u32*)RTA_DATA(tb[TCA_ROUTE4_CLASSID-1]);
+ tcf_bind_filter(tp, &f->res, base);
+ }
+
+ tcf_exts_change(tp, &f->exts, &e);
+
+ return 0;
+errout:
+ tcf_exts_destroy(tp, &e);
+ return err;
+}
+
+static int route4_change(struct tcf_proto *tp, unsigned long base,
+ u32 handle,
+ struct rtattr **tca,
+ unsigned long *arg)
+{
+ struct route4_head *head = tp->root;
+ struct route4_filter *f, *f1, **fp;
+ struct route4_bucket *b;
+ struct rtattr *opt = tca[TCA_OPTIONS-1];
+ struct rtattr *tb[TCA_ROUTE4_MAX];
+ unsigned int h, th;
+ u32 old_handle = 0;
+ int err;
+
+ if (opt == NULL)
+ return handle ? -EINVAL : 0;
+
+ if (rtattr_parse_nested(tb, TCA_ROUTE4_MAX, opt) < 0)
+ return -EINVAL;
+
+ if ((f = (struct route4_filter*)*arg) != NULL) {
+ if (f->handle != handle && handle)
+ return -EINVAL;
+
+ if (f->bkt)
+ old_handle = f->handle;
+
+ err = route4_set_parms(tp, base, f, handle, head, tb,
+ tca[TCA_RATE-1], 0);
+ if (err < 0)
+ return err;
+
+ goto reinsert;
+ }
+
+ err = -ENOBUFS;
+ if (head == NULL) {
+ head = kmalloc(sizeof(struct route4_head), GFP_KERNEL);
+ if (head == NULL)
goto errout;
+ memset(head, 0, sizeof(struct route4_head));
+
+ tcf_tree_lock(tp);
+ tp->root = head;
+ tcf_tree_unlock(tp);
}
- tcf_bind_filter(tp, &f->res, base);
-#ifdef CONFIG_NET_CLS_POLICE
- if (tb[TCA_ROUTE4_POLICE-1])
- tcf_change_police(tp, &f->police, tb[TCA_ROUTE4_POLICE-1], tca[TCA_RATE-1]);
-#endif
+ f = kmalloc(sizeof(struct route4_filter), GFP_KERNEL);
+ if (f == NULL)
+ goto errout;
+ memset(f, 0, sizeof(*f));
+
+ err = route4_set_parms(tp, base, f, handle, head, tb,
+ tca[TCA_RATE-1], 1);
+ if (err < 0)
+ goto errout;
+
+reinsert:
+ h = from_hash(f->handle >> 16);
+ for (fp = &f->bkt->ht[h]; (f1=*fp) != NULL; fp = &f1->next)
+ if (f->handle < f1->handle)
+ break;
f->next = f1;
tcf_tree_lock(tp);
- *ins_f = f;
+ *fp = f;
+
+ if (old_handle && f->handle != old_handle) {
+ th = to_hash(old_handle);
+ h = from_hash(old_handle >> 16);
+ if ((b = head->table[th]) != NULL) {
+ for (fp = &b->ht[h]; *fp; fp = &(*fp)->next) {
+ if (*fp == f) {
+ *fp = f->next;
+ break;
+ }
+ }
+ }
+ }
tcf_tree_unlock(tp);
route4_reset_fastmap(tp->q->dev, head, f->id);
@@ -559,17 +593,15 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh,
}
if (f->res.classid)
RTA_PUT(skb, TCA_ROUTE4_CLASSID, 4, &f->res.classid);
-#ifdef CONFIG_NET_CLS_POLICE
- if (tcf_dump_police(skb, f->police, TCA_ROUTE4_POLICE) < 0)
+
+ if (tcf_exts_dump(skb, &f->exts, &route_ext_map) < 0)
goto rtattr_failure;
-#endif
rta->rta_len = skb->tail - b;
-#ifdef CONFIG_NET_CLS_POLICE
- if (f->police)
- if (tcf_police_dump_stats(skb, f->police) < 0)
- goto rtattr_failure;
-#endif
+
+ if (tcf_exts_dump_stats(skb, &f->exts, &route_ext_map) < 0)
+ goto rtattr_failure;
+
return skb->len;
rtattr_failure:
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 95f691c5c8b5..7b74ad5ccd08 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -95,9 +95,7 @@ struct rsvp_filter
u8 tunnelhdr;
struct tcf_result res;
-#ifdef CONFIG_NET_CLS_POLICE
- struct tcf_police *police;
-#endif
+ struct tcf_exts exts;
u32 handle;
struct rsvp_session *sess;
@@ -120,18 +118,20 @@ static __inline__ unsigned hash_src(u32 *src)
return h & 0xF;
}
-#ifdef CONFIG_NET_CLS_POLICE
-#define RSVP_POLICE() \
-if (f->police) { \
- int pol_res = tcf_police(skb, f->police); \
- if (pol_res < 0) continue; \
- if (pol_res) return pol_res; \
-}
-#else
-#define RSVP_POLICE()
-#endif
-
+static struct tcf_ext_map rsvp_ext_map = {
+ .police = TCA_RSVP_POLICE,
+ .action = TCA_RSVP_ACT
+};
+#define RSVP_APPLY_RESULT() \
+ do { \
+ int r = tcf_exts_exec(skb, &f->exts, res); \
+ if (r < 0) \
+ continue; \
+ else if (r > 0) \
+ return r; \
+ } while(0)
+
static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp,
struct tcf_result *res)
{
@@ -189,8 +189,7 @@ restart:
#endif
) {
*res = f->res;
-
- RSVP_POLICE();
+ RSVP_APPLY_RESULT();
matched:
if (f->tunnelhdr == 0)
@@ -205,7 +204,7 @@ matched:
/* And wildcard bucket... */
for (f = s->ht[16]; f; f = f->next) {
*res = f->res;
- RSVP_POLICE();
+ RSVP_APPLY_RESULT();
goto matched;
}
return -1;
@@ -251,6 +250,14 @@ static int rsvp_init(struct tcf_proto *tp)
return -ENOBUFS;
}
+static inline void
+rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f)
+{
+ tcf_unbind_filter(tp, &f->res);
+ tcf_exts_destroy(tp, &f->exts);
+ kfree(f);
+}
+
static void rsvp_destroy(struct tcf_proto *tp)
{
struct rsvp_head *data = xchg(&tp->root, NULL);
@@ -273,11 +280,7 @@ static void rsvp_destroy(struct tcf_proto *tp)
while ((f = s->ht[h2]) != NULL) {
s->ht[h2] = f->next;
- tcf_unbind_filter(tp, &f->res);
-#ifdef CONFIG_NET_CLS_POLICE
- tcf_police_release(f->police,TCA_ACT_UNBIND);
-#endif
- kfree(f);
+ rsvp_delete_filter(tp, f);
}
}
kfree(s);
@@ -299,12 +302,7 @@ static int rsvp_delete(struct tcf_proto *tp, unsigned long arg)
tcf_tree_lock(tp);
*fp = f->next;
tcf_tree_unlock(tp);
- tcf_unbind_filter(tp, &f->res);
-#ifdef CONFIG_NET_CLS_POLICE
- tcf_police_release(f->police,TCA_ACT_UNBIND);
-#endif
-
- kfree(f);
+ rsvp_delete_filter(tp, f);
/* Strip tree */
@@ -412,6 +410,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
struct tc_rsvp_pinfo *pinfo = NULL;
struct rtattr *opt = tca[TCA_OPTIONS-1];
struct rtattr *tb[TCA_RSVP_MAX];
+ struct tcf_exts e;
unsigned h1, h2;
u32 *dst;
int err;
@@ -419,38 +418,38 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
if (opt == NULL)
return handle ? -EINVAL : 0;
- if (rtattr_parse(tb, TCA_RSVP_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)) < 0)
+ if (rtattr_parse_nested(tb, TCA_RSVP_MAX, opt) < 0)
return -EINVAL;
+ err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &rsvp_ext_map);
+ if (err < 0)
+ return err;
+
if ((f = (struct rsvp_filter*)*arg) != NULL) {
/* Node exists: adjust only classid */
if (f->handle != handle && handle)
- return -EINVAL;
+ goto errout2;
if (tb[TCA_RSVP_CLASSID-1]) {
f->res.classid = *(u32*)RTA_DATA(tb[TCA_RSVP_CLASSID-1]);
tcf_bind_filter(tp, &f->res, base);
}
-#ifdef CONFIG_NET_CLS_POLICE
- if (tb[TCA_RSVP_POLICE-1]) {
- err = tcf_change_police(tp, &f->police,
- tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]);
- if (err < 0)
- return err;
- }
-#endif
+
+ tcf_exts_change(tp, &f->exts, &e);
return 0;
}
/* Now more serious part... */
+ err = -EINVAL;
if (handle)
- return -EINVAL;
+ goto errout2;
if (tb[TCA_RSVP_DST-1] == NULL)
- return -EINVAL;
+ goto errout2;
+ err = -ENOBUFS;
f = kmalloc(sizeof(struct rsvp_filter), GFP_KERNEL);
if (f == NULL)
- return -ENOBUFS;
+ goto errout2;
memset(f, 0, sizeof(*f));
h2 = 16;
@@ -516,10 +515,8 @@ insert:
f->sess = s;
if (f->tunnelhdr == 0)
tcf_bind_filter(tp, &f->res, base);
-#ifdef CONFIG_NET_CLS_POLICE
- if (tb[TCA_RSVP_POLICE-1])
- tcf_change_police(tp, &f->police, tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]);
-#endif
+
+ tcf_exts_change(tp, &f->exts, &e);
for (fp = &s->ht[h2]; *fp; fp = &(*fp)->next)
if (((*fp)->spi.mask&f->spi.mask) != f->spi.mask)
@@ -560,6 +557,8 @@ insert:
errout:
if (f)
kfree(f);
+errout2:
+ tcf_exts_destroy(tp, &e);
return err;
}
@@ -624,17 +623,14 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
RTA_PUT(skb, TCA_RSVP_CLASSID, 4, &f->res.classid);
if (((f->handle>>8)&0xFF) != 16)
RTA_PUT(skb, TCA_RSVP_SRC, sizeof(f->src), f->src);
-#ifdef CONFIG_NET_CLS_POLICE
- if (tcf_dump_police(skb, f->police, TCA_RSVP_POLICE) < 0)
+
+ if (tcf_exts_dump(skb, &f->exts, &rsvp_ext_map) < 0)
goto rtattr_failure;
-#endif
rta->rta_len = skb->tail - b;
-#ifdef CONFIG_NET_CLS_POLICE
- if (f->police)
- if (tcf_police_dump_stats(skb, f->police) < 0)
- goto rtattr_failure;
-#endif
+
+ if (tcf_exts_dump_stats(skb, &f->exts, &rsvp_ext_map) < 0)
+ goto rtattr_failure;
return skb->len;
rtattr_failure:
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index c520afb5b045..404d9d83a7fa 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -49,12 +49,12 @@
struct tcindex_filter_result {
- struct tcf_police *police;
- struct tcf_result res;
+ struct tcf_exts exts;
+ struct tcf_result res;
};
struct tcindex_filter {
- __u16 key;
+ u16 key;
struct tcindex_filter_result result;
struct tcindex_filter *next;
};
@@ -64,60 +64,64 @@ struct tcindex_data {
struct tcindex_filter_result *perfect; /* perfect hash; NULL if none */
struct tcindex_filter **h; /* imperfect hash; only used if !perfect;
NULL if unused */
- __u16 mask; /* AND key with mask */
+ u16 mask; /* AND key with mask */
int shift; /* shift ANDed key to the right */
int hash; /* hash table size; 0 if undefined */
int alloc_hash; /* allocated size */
int fall_through; /* 0: only classify if explicit match */
};
+static struct tcf_ext_map tcindex_ext_map = {
+ .police = TCA_TCINDEX_POLICE,
+ .action = TCA_TCINDEX_ACT
+};
+
+static inline int
+tcindex_filter_is_set(struct tcindex_filter_result *r)
+{
+ return tcf_exts_is_predicative(&r->exts) || r->res.classid;
+}
-static struct tcindex_filter_result *lookup(struct tcindex_data *p,__u16 key)
+static struct tcindex_filter_result *
+tcindex_lookup(struct tcindex_data *p, u16 key)
{
struct tcindex_filter *f;
if (p->perfect)
- return p->perfect[key].res.class ? p->perfect+key : NULL;
- if (!p->h)
- return NULL;
- for (f = p->h[key % p->hash]; f; f = f->next) {
- if (f->key == key)
- return &f->result;
+ return tcindex_filter_is_set(p->perfect + key) ?
+ p->perfect + key : NULL;
+ else if (p->h) {
+ for (f = p->h[key % p->hash]; f; f = f->next)
+ if (f->key == key)
+ return &f->result;
}
+
return NULL;
}
static int tcindex_classify(struct sk_buff *skb, struct tcf_proto *tp,
- struct tcf_result *res)
+ struct tcf_result *res)
{
struct tcindex_data *p = PRIV(tp);
struct tcindex_filter_result *f;
+ int key = (skb->tc_index & p->mask) >> p->shift;
D2PRINTK("tcindex_classify(skb %p,tp %p,res %p),p %p\n",skb,tp,res,p);
- f = lookup(p,(skb->tc_index & p->mask) >> p->shift);
+ f = tcindex_lookup(p, key);
if (!f) {
if (!p->fall_through)
return -1;
- res->classid = TC_H_MAKE(TC_H_MAJ(tp->q->handle),
- (skb->tc_index& p->mask) >> p->shift);
+ res->classid = TC_H_MAKE(TC_H_MAJ(tp->q->handle), key);
res->class = 0;
D2PRINTK("alg 0x%x\n",res->classid);
return 0;
}
*res = f->res;
D2PRINTK("map 0x%x\n",res->classid);
-#ifdef CONFIG_NET_CLS_POLICE
- if (f->police) {
- int result;
- result = tcf_police(skb,f->police);
- D2PRINTK("police %d\n",res);
- return result;
- }
-#endif
- return 0;
+ return tcf_exts_exec(skb, &f->exts, res);
}
@@ -129,8 +133,8 @@ static unsigned long tcindex_get(struct tcf_proto *tp, u32 handle)
DPRINTK("tcindex_get(tp %p,handle 0x%08x)\n",tp,handle);
if (p->perfect && handle >= p->alloc_hash)
return 0;
- r = lookup(PRIV(tp),handle);
- return r && r->res.class ? (unsigned long) r : 0;
+ r = tcindex_lookup(p, handle);
+ return r && tcindex_filter_is_set(r) ? (unsigned long) r : 0UL;
}
@@ -149,13 +153,12 @@ static int tcindex_init(struct tcf_proto *tp)
if (!p)
return -ENOMEM;
- tp->root = p;
- p->perfect = NULL;
- p->h = NULL;
- p->hash = 0;
+ memset(p, 0, sizeof(*p));
p->mask = 0xffff;
- p->shift = 0;
+ p->hash = DEFAULT_HASH_SIZE;
p->fall_through = 1;
+
+ tp->root = p;
return 0;
}
@@ -190,9 +193,7 @@ found:
tcf_tree_unlock(tp);
}
tcf_unbind_filter(tp, &r->res);
-#ifdef CONFIG_NET_CLS_POLICE
- tcf_police_release(r->police, TCA_ACT_UNBIND);
-#endif
+ tcf_exts_destroy(tp, &r->exts);
if (f)
kfree(f);
return 0;
@@ -203,148 +204,184 @@ static int tcindex_delete(struct tcf_proto *tp, unsigned long arg)
return __tcindex_delete(tp, arg, 1);
}
-/*
- * There are no parameters for tcindex_init, so we overload tcindex_change
- */
-
-
-static int tcindex_change(struct tcf_proto *tp,unsigned long base,u32 handle,
- struct rtattr **tca,unsigned long *arg)
+static inline int
+valid_perfect_hash(struct tcindex_data *p)
{
- struct tcindex_filter_result new_filter_result = {
- NULL, /* no policing */
- { 0,0 }, /* no classification */
- };
- struct rtattr *opt = tca[TCA_OPTIONS-1];
- struct rtattr *tb[TCA_TCINDEX_MAX];
- struct tcindex_data *p = PRIV(tp);
- struct tcindex_filter *f;
- struct tcindex_filter_result *r = (struct tcindex_filter_result *) *arg;
- struct tcindex_filter **walk;
- int hash,shift;
- __u16 mask;
+ return p->hash > (p->mask >> p->shift);
+}
- DPRINTK("tcindex_change(tp %p,handle 0x%08x,tca %p,arg %p),opt %p,"
- "p %p,r %p\n",tp,handle,tca,arg,opt,p,r);
- if (arg)
- DPRINTK("*arg = 0x%lx\n",*arg);
- if (!opt)
- return 0;
- if (rtattr_parse(tb,TCA_TCINDEX_MAX,RTA_DATA(opt),RTA_PAYLOAD(opt)) < 0)
- return -EINVAL;
- if (!tb[TCA_TCINDEX_HASH-1]) {
- hash = p->hash;
- } else {
- if (RTA_PAYLOAD(tb[TCA_TCINDEX_HASH-1]) < sizeof(int))
- return -EINVAL;
- hash = *(int *) RTA_DATA(tb[TCA_TCINDEX_HASH-1]);
+static int
+tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
+ struct tcindex_data *p, struct tcindex_filter_result *r,
+ struct rtattr **tb, struct rtattr *est)
+{
+ int err, balloc = 0;
+ struct tcindex_filter_result new_filter_result, *old_r = r;
+ struct tcindex_filter_result cr;
+ struct tcindex_data cp;
+ struct tcindex_filter *f = NULL; /* make gcc behave */
+ struct tcf_exts e;
+
+ err = tcf_exts_validate(tp, tb, est, &e, &tcindex_ext_map);
+ if (err < 0)
+ return err;
+
+ memcpy(&cp, p, sizeof(cp));
+ memset(&new_filter_result, 0, sizeof(new_filter_result));
+
+ if (old_r)
+ memcpy(&cr, r, sizeof(cr));
+ else
+ memset(&cr, 0, sizeof(cr));
+
+ err = -EINVAL;
+ if (tb[TCA_TCINDEX_HASH-1]) {
+ if (RTA_PAYLOAD(tb[TCA_TCINDEX_HASH-1]) < sizeof(u32))
+ goto errout;
+ cp.hash = *(u32 *) RTA_DATA(tb[TCA_TCINDEX_HASH-1]);
}
- if (!tb[TCA_TCINDEX_MASK-1]) {
- mask = p->mask;
- } else {
- if (RTA_PAYLOAD(tb[TCA_TCINDEX_MASK-1]) < sizeof(__u16))
- return -EINVAL;
- mask = *(__u16 *) RTA_DATA(tb[TCA_TCINDEX_MASK-1]);
+
+ if (tb[TCA_TCINDEX_MASK-1]) {
+ if (RTA_PAYLOAD(tb[TCA_TCINDEX_MASK-1]) < sizeof(u16))
+ goto errout;
+ cp.mask = *(u16 *) RTA_DATA(tb[TCA_TCINDEX_MASK-1]);
}
- if (!tb[TCA_TCINDEX_SHIFT-1])
- shift = p->shift;
- else {
- if (RTA_PAYLOAD(tb[TCA_TCINDEX_SHIFT-1]) < sizeof(__u16))
- return -EINVAL;
- shift = *(int *) RTA_DATA(tb[TCA_TCINDEX_SHIFT-1]);
+
+ if (tb[TCA_TCINDEX_SHIFT-1]) {
+ if (RTA_PAYLOAD(tb[TCA_TCINDEX_SHIFT-1]) < sizeof(u16))
+ goto errout;
+ cp.shift = *(u16 *) RTA_DATA(tb[TCA_TCINDEX_SHIFT-1]);
}
- if (p->perfect && hash <= (mask >> shift))
- return -EBUSY;
- if (p->perfect && hash > p->alloc_hash)
- return -EBUSY;
- if (p->h && hash != p->alloc_hash)
- return -EBUSY;
- p->hash = hash;
- p->mask = mask;
- p->shift = shift;
+
+ err = -EBUSY;
+ /* Hash already allocated, make sure that we still meet the
+ * requirements for the allocated hash.
+ */
+ if (cp.perfect) {
+ if (!valid_perfect_hash(&cp) ||
+ cp.hash > cp.alloc_hash)
+ goto errout;
+ } else if (cp.h && cp.hash != cp.alloc_hash)
+ goto errout;
+
+ err = -EINVAL;
if (tb[TCA_TCINDEX_FALL_THROUGH-1]) {
- if (RTA_PAYLOAD(tb[TCA_TCINDEX_FALL_THROUGH-1]) < sizeof(int))
- return -EINVAL;
- p->fall_through =
- *(int *) RTA_DATA(tb[TCA_TCINDEX_FALL_THROUGH-1]);
+ if (RTA_PAYLOAD(tb[TCA_TCINDEX_FALL_THROUGH-1]) < sizeof(u32))
+ goto errout;
+ cp.fall_through =
+ *(u32 *) RTA_DATA(tb[TCA_TCINDEX_FALL_THROUGH-1]);
}
- DPRINTK("classid/police %p/%p\n",tb[TCA_TCINDEX_CLASSID-1],
- tb[TCA_TCINDEX_POLICE-1]);
- if (!tb[TCA_TCINDEX_CLASSID-1] && !tb[TCA_TCINDEX_POLICE-1])
- return 0;
- if (!hash) {
- if ((mask >> shift) < PERFECT_HASH_THRESHOLD) {
- p->hash = (mask >> shift)+1;
- } else {
- p->hash = DEFAULT_HASH_SIZE;
- }
+
+ if (!cp.hash) {
+ /* Hash not specified, use perfect hash if the upper limit
+ * of the hashing index is below the threshold.
+ */
+ if ((cp.mask >> cp.shift) < PERFECT_HASH_THRESHOLD)
+ cp.hash = (cp.mask >> cp.shift)+1;
+ else
+ cp.hash = DEFAULT_HASH_SIZE;
}
- if (!p->perfect && !p->h) {
- p->alloc_hash = p->hash;
- DPRINTK("hash %d mask %d\n",p->hash,p->mask);
- if (p->hash > (mask >> shift)) {
- p->perfect = kmalloc(p->hash*
- sizeof(struct tcindex_filter_result),GFP_KERNEL);
- if (!p->perfect)
- return -ENOMEM;
- memset(p->perfect, 0,
- p->hash * sizeof(struct tcindex_filter_result));
+
+ if (!cp.perfect && !cp.h)
+ cp.alloc_hash = cp.hash;
+
+ /* Note: this could be as restrictive as if (handle & ~(mask >> shift))
+ * but then, we'd fail handles that may become valid after some future
+ * mask change. While this is extremely unlikely to ever matter,
+ * the check below is safer (and also more backwards-compatible).
+ */
+ if (cp.perfect || valid_perfect_hash(&cp))
+ if (handle >= cp.alloc_hash)
+ goto errout;
+
+
+ err = -ENOMEM;
+ if (!cp.perfect && !cp.h) {
+ if (valid_perfect_hash(&cp)) {
+ cp.perfect = kmalloc(cp.hash * sizeof(*r), GFP_KERNEL);
+ if (!cp.perfect)
+ goto errout;
+ memset(cp.perfect, 0, cp.hash * sizeof(*r));
+ balloc = 1;
} else {
- p->h = kmalloc(p->hash*sizeof(struct tcindex_filter *),
- GFP_KERNEL);
- if (!p->h)
- return -ENOMEM;
- memset(p->h, 0, p->hash*sizeof(struct tcindex_filter *));
+ cp.h = kmalloc(cp.hash * sizeof(f), GFP_KERNEL);
+ if (!cp.h)
+ goto errout;
+ memset(cp.h, 0, cp.hash * sizeof(f));
+ balloc = 2;
}
}
- /*
- * Note: this could be as restrictive as
- * if (handle & ~(mask >> shift))
- * but then, we'd fail handles that may become valid after some
- * future mask change. While this is extremely unlikely to ever
- * matter, the check below is safer (and also more
- * backwards-compatible).
- */
- if (p->perfect && handle >= p->alloc_hash)
- return -EINVAL;
- if (p->perfect) {
- r = p->perfect+handle;
- } else {
- r = lookup(p,handle);
- DPRINTK("r=%p\n",r);
- if (!r)
- r = &new_filter_result;
- }
- DPRINTK("r=%p\n",r);
+
+ if (cp.perfect)
+ r = cp.perfect + handle;
+ else
+ r = tcindex_lookup(&cp, handle) ? : &new_filter_result;
+
+ if (r == &new_filter_result) {
+ f = kmalloc(sizeof(*f), GFP_KERNEL);
+ if (!f)
+ goto errout_alloc;
+ memset(f, 0, sizeof(*f));
+ }
+
if (tb[TCA_TCINDEX_CLASSID-1]) {
- r->res.classid = *(__u32 *) RTA_DATA(tb[TCA_TCINDEX_CLASSID-1]);
- tcf_bind_filter(tp, &r->res, base);
+ cr.res.classid = *(u32 *) RTA_DATA(tb[TCA_TCINDEX_CLASSID-1]);
+ tcf_bind_filter(tp, &cr.res, base);
+ }
+
+ tcf_exts_change(tp, &cr.exts, &e);
+
+ tcf_tree_lock(tp);
+ if (old_r && old_r != r)
+ memset(old_r, 0, sizeof(*old_r));
+
+ memcpy(p, &cp, sizeof(cp));
+ memcpy(r, &cr, sizeof(cr));
+
+ if (r == &new_filter_result) {
+ struct tcindex_filter **fp;
+
+ f->key = handle;
+ f->result = new_filter_result;
+ f->next = NULL;
+ for (fp = p->h+(handle % p->hash); *fp; fp = &(*fp)->next)
+ /* nothing */;
+ *fp = f;
+ }
+ tcf_tree_unlock(tp);
- if (!r->res.class) {
- r->res.classid = 0;
- return -ENOENT;
- }
- }
-#ifdef CONFIG_NET_CLS_POLICE
- if (tb[TCA_TCINDEX_POLICE-1]) {
- int err = tcf_change_police(tp, &r->police, tb[TCA_TCINDEX_POLICE-1], NULL);
- if (err < 0)
- return err;
- }
-#endif
- if (r != &new_filter_result)
- return 0;
- f = kmalloc(sizeof(struct tcindex_filter),GFP_KERNEL);
- if (!f)
- return -ENOMEM;
- f->key = handle;
- f->result = new_filter_result;
- f->next = NULL;
- for (walk = p->h+(handle % p->hash); *walk; walk = &(*walk)->next)
- /* nothing */;
- wmb();
- *walk = f;
return 0;
+
+errout_alloc:
+ if (balloc == 1)
+ kfree(cp.perfect);
+ else if (balloc == 2)
+ kfree(cp.h);
+errout:
+ tcf_exts_destroy(tp, &e);
+ return err;
+}
+
+static int
+tcindex_change(struct tcf_proto *tp, unsigned long base, u32 handle,
+ struct rtattr **tca, unsigned long *arg)
+{
+ struct rtattr *opt = tca[TCA_OPTIONS-1];
+ struct rtattr *tb[TCA_TCINDEX_MAX];
+ struct tcindex_data *p = PRIV(tp);
+ struct tcindex_filter_result *r = (struct tcindex_filter_result *) *arg;
+
+ DPRINTK("tcindex_change(tp %p,handle 0x%08x,tca %p,arg %p),opt %p,"
+ "p %p,r %p,*arg 0x%lx\n",
+ tp, handle, tca, arg, opt, p, r, arg ? *arg : 0L);
+
+ if (!opt)
+ return 0;
+
+ if (rtattr_parse_nested(tb, TCA_TCINDEX_MAX, opt) < 0)
+ return -EINVAL;
+
+ return tcindex_set_parms(tp, base, handle, p, r, tb, tca[TCA_RATE-1]);
}
@@ -434,6 +471,7 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
RTA_PUT(skb,TCA_TCINDEX_SHIFT,sizeof(p->shift),&p->shift);
RTA_PUT(skb,TCA_TCINDEX_FALL_THROUGH,sizeof(p->fall_through),
&p->fall_through);
+ rta->rta_len = skb->tail-b;
} else {
if (p->perfect) {
t->tcm_handle = r-p->perfect;
@@ -453,12 +491,15 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
DPRINTK("handle = %d\n",t->tcm_handle);
if (r->res.class)
RTA_PUT(skb, TCA_TCINDEX_CLASSID, 4, &r->res.classid);
-#ifdef CONFIG_NET_CLS_POLICE
- if (tcf_dump_police(skb, r->police, TCA_TCINDEX_POLICE) < 0)
+
+ if (tcf_exts_dump(skb, &r->exts, &tcindex_ext_map) < 0)
+ goto rtattr_failure;
+ rta->rta_len = skb->tail-b;
+
+ if (tcf_exts_dump_stats(skb, &r->exts, &tcindex_ext_map) < 0)
goto rtattr_failure;
-#endif
}
- rta->rta_len = skb->tail-b;
+
return skb->len;
rtattr_failure:
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 984e1f27b1a6..8b870402bc96 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -61,9 +61,9 @@
struct tc_u32_mark
{
- __u32 val;
- __u32 mask;
- __u32 success;
+ u32 val;
+ u32 mask;
+ u32 success;
};
struct tc_u_knode
@@ -71,13 +71,7 @@ struct tc_u_knode
struct tc_u_knode *next;
u32 handle;
struct tc_u_hnode *ht_up;
-#ifdef CONFIG_NET_CLS_ACT
- struct tc_action *action;
-#else
-#ifdef CONFIG_NET_CLS_POLICE
- struct tcf_police *police;
-#endif
-#endif
+ struct tcf_exts exts;
#ifdef CONFIG_NET_CLS_IND
char indev[IFNAMSIZ];
#endif
@@ -112,6 +106,11 @@ struct tc_u_common
u32 hgenerator;
};
+static struct tcf_ext_map u32_ext_map = {
+ .action = TCA_U32_ACT,
+ .police = TCA_U32_POLICE
+};
+
static struct tc_u_common *u32_list;
static __inline__ unsigned u32_hash_fold(u32 key, struct tc_u32_sel *sel, u8 fshift)
@@ -137,7 +136,7 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re
#ifdef CONFIG_CLS_U32_PERF
int j;
#endif
- int i;
+ int i, r;
next_ht:
n = ht->ht[sel];
@@ -185,22 +184,13 @@ check_terminal:
#ifdef CONFIG_CLS_U32_PERF
n->pf->rhit +=1;
#endif
-#ifdef CONFIG_NET_CLS_ACT
- if (n->action) {
- int pol_res = tcf_action_exec(skb, n->action, res);
- if (pol_res >= 0)
- return pol_res;
- } else
-#else
-#ifdef CONFIG_NET_CLS_POLICE
- if (n->police) {
- int pol_res = tcf_police(skb, n->police);
- if (pol_res >= 0)
- return pol_res;
- } else
-#endif
-#endif
- return 0;
+ r = tcf_exts_exec(skb, &n->exts, res);
+ if (r < 0) {
+ n = n->next;
+ goto next_knode;
+ }
+
+ return r;
}
n = n->next;
goto next_knode;
@@ -359,15 +349,7 @@ static int u32_init(struct tcf_proto *tp)
static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n)
{
tcf_unbind_filter(tp, &n->res);
-#ifdef CONFIG_NET_CLS_ACT
- if (n->action) {
- tcf_action_destroy(n->action, TCA_ACT_UNBIND);
- }
-#else
-#ifdef CONFIG_NET_CLS_POLICE
- tcf_police_release(n->police, TCA_ACT_UNBIND);
-#endif
-#endif
+ tcf_exts_destroy(tp, &n->exts);
if (n->ht_down)
n->ht_down->refcnt--;
#ifdef CONFIG_CLS_U32_PERF
@@ -509,18 +491,26 @@ static int u32_set_parms(struct tcf_proto *tp, unsigned long base,
struct tc_u_knode *n, struct rtattr **tb,
struct rtattr *est)
{
+ int err;
+ struct tcf_exts e;
+
+ err = tcf_exts_validate(tp, tb, est, &e, &u32_ext_map);
+ if (err < 0)
+ return err;
+
+ err = -EINVAL;
if (tb[TCA_U32_LINK-1]) {
u32 handle = *(u32*)RTA_DATA(tb[TCA_U32_LINK-1]);
struct tc_u_hnode *ht_down = NULL;
if (TC_U32_KEY(handle))
- return -EINVAL;
+ goto errout;
if (handle) {
ht_down = u32_lookup_ht(ht->tp_c, handle);
if (ht_down == NULL)
- return -EINVAL;
+ goto errout;
ht_down->refcnt++;
}
@@ -535,36 +525,20 @@ static int u32_set_parms(struct tcf_proto *tp, unsigned long base,
n->res.classid = *(u32*)RTA_DATA(tb[TCA_U32_CLASSID-1]);
tcf_bind_filter(tp, &n->res, base);
}
-#ifdef CONFIG_NET_CLS_ACT
- if (tb[TCA_U32_POLICE-1]) {
- int err = tcf_change_act_police(tp, &n->action, tb[TCA_U32_POLICE-1], est);
- if (err < 0)
- return err;
- }
- if (tb[TCA_U32_ACT-1]) {
- int err = tcf_change_act(tp, &n->action, tb[TCA_U32_ACT-1], est);
- if (err < 0)
- return err;
- }
-#else
-#ifdef CONFIG_NET_CLS_POLICE
- if (tb[TCA_U32_POLICE-1]) {
- int err = tcf_change_police(tp, &n->police, tb[TCA_U32_POLICE-1], est);
- if (err < 0)
- return err;
- }
-#endif
-#endif
#ifdef CONFIG_NET_CLS_IND
if (tb[TCA_U32_INDEV-1]) {
int err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV-1]);
if (err < 0)
- return err;
+ goto errout;
}
#endif
+ tcf_exts_change(tp, &n->exts, &e);
return 0;
+errout:
+ tcf_exts_destroy(tp, &e);
+ return err;
}
static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
@@ -575,7 +549,6 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
struct tc_u_hnode *ht;
struct tc_u_knode *n;
struct tc_u32_sel *s;
- struct tc_u32_mark *mark;
struct rtattr *opt = tca[TCA_OPTIONS-1];
struct rtattr *tb[TCA_U32_MAX];
u32 htid;
@@ -584,7 +557,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
if (opt == NULL)
return handle ? -EINVAL : 0;
- if (rtattr_parse(tb, TCA_U32_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)) < 0)
+ if (rtattr_parse_nested(tb, TCA_U32_MAX, opt) < 0)
return -EINVAL;
if ((n = (struct tc_u_knode*)*arg) != NULL) {
@@ -657,12 +630,12 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
memset(n, 0, sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key));
#ifdef CONFIG_CLS_U32_PERF
- n->pf = kmalloc(sizeof(struct tc_u32_pcnt) + s->nkeys*sizeof(__u64), GFP_KERNEL);
+ n->pf = kmalloc(sizeof(struct tc_u32_pcnt) + s->nkeys*sizeof(u64), GFP_KERNEL);
if (n->pf == NULL) {
kfree(n);
return -ENOBUFS;
}
- memset(n->pf, 0, sizeof(struct tc_u32_pcnt) + s->nkeys*sizeof(__u64));
+ memset(n->pf, 0, sizeof(struct tc_u32_pcnt) + s->nkeys*sizeof(u64));
#endif
memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key));
@@ -680,15 +653,22 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
n->fshift = i;
}
-#ifdef CONFIG_CLS_U32_MARK
+#ifdef CONFIG_CLS_U32_MARK
if (tb[TCA_U32_MARK-1]) {
- if (RTA_PAYLOAD(tb[TCA_U32_MARK-1]) < sizeof(struct tc_u32_mark))
+ struct tc_u32_mark *mark;
+
+ if (RTA_PAYLOAD(tb[TCA_U32_MARK-1]) < sizeof(struct tc_u32_mark)) {
+#ifdef CONFIG_CLS_U32_PERF
+ kfree(n->pf);
+#endif
+ kfree(n);
return -EINVAL;
+ }
mark = RTA_DATA(tb[TCA_U32_MARK-1]);
memcpy(&n->mark, mark, sizeof(struct tc_u32_mark));
n->mark.success = 0;
- }
-#endif
+ }
+#endif
err = u32_set_parms(tp, base, ht, n, tb, tca[TCA_RATE-1]);
if (err == 0) {
@@ -783,15 +763,8 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
RTA_PUT(skb, TCA_U32_MARK, sizeof(n->mark), &n->mark);
#endif
-#ifdef CONFIG_NET_CLS_ACT
- if (tcf_dump_act(skb, n->action, TCA_U32_ACT, TCA_U32_POLICE) < 0)
+ if (tcf_exts_dump(skb, &n->exts, &u32_ext_map) < 0)
goto rtattr_failure;
-#else
-#ifdef CONFIG_NET_CLS_POLICE
- if (tcf_dump_police(skb, n->police, TCA_U32_POLICE) < 0)
- goto rtattr_failure;
-#endif
-#endif
#ifdef CONFIG_NET_CLS_IND
if(strlen(n->indev))
@@ -799,26 +772,15 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
#endif
#ifdef CONFIG_CLS_U32_PERF
RTA_PUT(skb, TCA_U32_PCNT,
- sizeof(struct tc_u32_pcnt) + n->sel.nkeys*sizeof(__u64),
+ sizeof(struct tc_u32_pcnt) + n->sel.nkeys*sizeof(u64),
n->pf);
#endif
}
rta->rta_len = skb->tail - b;
-#ifdef CONFIG_NET_CLS_ACT
- if (TC_U32_KEY(n->handle) != 0) {
- if (TC_U32_KEY(n->handle) && n->action && n->action->type == TCA_OLD_COMPAT) {
- if (tcf_action_copy_stats(skb,n->action))
- goto rtattr_failure;
- }
- }
-#else
-#ifdef CONFIG_NET_CLS_POLICE
- if (TC_U32_KEY(n->handle) && n->police)
- if (tcf_police_dump_stats(skb, n->police) < 0)
+ if (TC_U32_KEY(n->handle))
+ if (tcf_exts_dump_stats(skb, &n->exts, &u32_ext_map) < 0)
goto rtattr_failure;
-#endif
-#endif
return skb->len;
rtattr_failure:
diff --git a/net/sched/estimator.c b/net/sched/estimator.c
index f39a5187a75c..5d3ae03e22a7 100644
--- a/net/sched/estimator.c
+++ b/net/sched/estimator.c
@@ -95,7 +95,7 @@ struct qdisc_estimator_head
static struct qdisc_estimator_head elist[EST_MAX_INTERVAL+1];
/* Estimator array lock */
-static rwlock_t est_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(est_lock);
static void est_timer(unsigned long arg)
{
diff --git a/net/sched/gact.c b/net/sched/gact.c
index a65d2d6689f6..a811c89fef7f 100644
--- a/net/sched/gact.c
+++ b/net/sched/gact.c
@@ -38,103 +38,98 @@
/* use generic hash table */
#define MY_TAB_SIZE 16
#define MY_TAB_MASK 15
+
static u32 idx_gen;
static struct tcf_gact *tcf_gact_ht[MY_TAB_SIZE];
-static rwlock_t gact_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(gact_lock);
/* ovewrride the defaults */
-#define tcf_st tcf_gact
-#define tc_st tc_gact
-#define tcf_t_lock gact_lock
-#define tcf_ht tcf_gact_ht
+#define tcf_st tcf_gact
+#define tc_st tc_gact
+#define tcf_t_lock gact_lock
+#define tcf_ht tcf_gact_ht
#define CONFIG_NET_ACT_INIT 1
#include <net/pkt_act.h>
#ifdef CONFIG_GACT_PROB
-typedef int (*g_rand)(struct tcf_gact *p);
-static int
-gact_net_rand(struct tcf_gact *p) {
+static int gact_net_rand(struct tcf_gact *p)
+{
if (net_random()%p->pval)
return p->action;
return p->paction;
}
-static int
-gact_determ(struct tcf_gact *p) {
+static int gact_determ(struct tcf_gact *p)
+{
if (p->bstats.packets%p->pval)
return p->action;
return p->paction;
}
-
-static g_rand gact_rand[MAX_RAND]= { NULL,gact_net_rand, gact_determ};
-
+typedef int (*g_rand)(struct tcf_gact *p);
+static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ };
#endif
-static int
-tcf_gact_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,int ovr,int bind)
+
+static int tcf_gact_init(struct rtattr *rta, struct rtattr *est,
+ struct tc_action *a, int ovr, int bind)
{
struct rtattr *tb[TCA_GACT_MAX];
- struct tc_gact *parm = NULL;
-#ifdef CONFIG_GACT_PROB
- struct tc_gact_p *p_parm = NULL;
-#endif
- struct tcf_gact *p = NULL;
+ struct tc_gact *parm;
+ struct tcf_gact *p;
int ret = 0;
- int size = sizeof (*p);
- if (rtattr_parse(tb, TCA_GACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
- return -1;
-
- if (NULL == a || NULL == tb[TCA_GACT_PARMS - 1]) {
- printk("BUG: tcf_gact_init called with NULL params\n");
- return -1;
- }
+ if (rta == NULL || rtattr_parse_nested(tb, TCA_GACT_MAX, rta) < 0)
+ return -EINVAL;
+ if (tb[TCA_GACT_PARMS - 1] == NULL ||
+ RTA_PAYLOAD(tb[TCA_GACT_PARMS - 1]) < sizeof(*parm))
+ return -EINVAL;
parm = RTA_DATA(tb[TCA_GACT_PARMS - 1]);
+
+ if (tb[TCA_GACT_PROB-1] != NULL)
#ifdef CONFIG_GACT_PROB
- if (NULL != tb[TCA_GACT_PROB - 1]) {
- p_parm = RTA_DATA(tb[TCA_GACT_PROB - 1]);
- }
+ if (RTA_PAYLOAD(tb[TCA_GACT_PROB-1]) < sizeof(struct tc_gact_p))
+ return -EINVAL;
+#else
+ return -EOPNOTSUPP;
#endif
- p = tcf_hash_check(parm, a, ovr, bind);
-
- if (NULL == p) {
- p = tcf_hash_create(parm,est,a,size,ovr, bind);
-
- if (NULL == p) {
- return -1;
- } else {
- p->refcnt = 1;
- ret = 1;
- goto override;
+ p = tcf_hash_check(parm->index, a, ovr, bind);
+ if (p == NULL) {
+ p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
+ if (p == NULL)
+ return -ENOMEM;
+ ret = ACT_P_CREATED;
+ } else {
+ if (!ovr) {
+ tcf_hash_release(p, bind);
+ return -EEXIST;
}
}
- if (ovr) {
-override:
- p->action = parm->action;
+ spin_lock_bh(&p->lock);
+ p->action = parm->action;
#ifdef CONFIG_GACT_PROB
- if (NULL != p_parm) {
- p->paction = p_parm->paction;
- p->pval = p_parm->pval;
- p->ptype = p_parm->ptype;
- } else {
- p->paction = p->pval = p->ptype = 0;
- }
-#endif
+ if (tb[TCA_GACT_PROB-1] != NULL) {
+ struct tc_gact_p *p_parm = RTA_DATA(tb[TCA_GACT_PROB-1]);
+ p->paction = p_parm->paction;
+ p->pval = p_parm->pval;
+ p->ptype = p_parm->ptype;
}
-
+#endif
+ spin_unlock_bh(&p->lock);
+ if (ret == ACT_P_CREATED)
+ tcf_hash_insert(p);
return ret;
}
static int
tcf_gact_cleanup(struct tc_action *a, int bind)
{
- struct tcf_gact *p;
- p = PRIV(a,gact);
- if (NULL != p)
+ struct tcf_gact *p = PRIV(a, gact);
+
+ if (p != NULL)
return tcf_hash_release(p, bind);
return 0;
}
@@ -142,21 +137,13 @@ tcf_gact_cleanup(struct tc_action *a, int bind)
static int
tcf_gact(struct sk_buff **pskb, struct tc_action *a)
{
- struct tcf_gact *p;
+ struct tcf_gact *p = PRIV(a, gact);
struct sk_buff *skb = *pskb;
int action = TC_ACT_SHOT;
- p = PRIV(a,gact);
-
- if (NULL == p) {
- if (net_ratelimit())
- printk("BUG: tcf_gact called with NULL params\n");
- return -1;
- }
-
spin_lock(&p->lock);
#ifdef CONFIG_GACT_PROB
- if (p->ptype && NULL != gact_rand[p->ptype])
+ if (p->ptype && gact_rand[p->ptype] != NULL)
action = gact_rand[p->ptype](p);
else
action = p->action;
@@ -165,7 +152,7 @@ tcf_gact(struct sk_buff **pskb, struct tc_action *a)
#endif
p->bstats.bytes += skb->len;
p->bstats.packets++;
- if (TC_ACT_SHOT == action)
+ if (action == TC_ACT_SHOT)
p->qstats.drops++;
p->tm.lastuse = jiffies;
spin_unlock(&p->lock);
@@ -178,35 +165,27 @@ tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
unsigned char *b = skb->tail;
struct tc_gact opt;
-#ifdef CONFIG_GACT_PROB
- struct tc_gact_p p_opt;
-#endif
- struct tcf_gact *p;
+ struct tcf_gact *p = PRIV(a, gact);
struct tcf_t t;
- p = PRIV(a,gact);
- if (NULL == p) {
- printk("BUG: tcf_gact_dump called with NULL params\n");
- goto rtattr_failure;
- }
-
opt.index = p->index;
opt.refcnt = p->refcnt - ref;
opt.bindcnt = p->bindcnt - bind;
opt.action = p->action;
- RTA_PUT(skb, TCA_GACT_PARMS, sizeof (opt), &opt);
+ RTA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt);
#ifdef CONFIG_GACT_PROB
if (p->ptype) {
+ struct tc_gact_p p_opt;
p_opt.paction = p->paction;
p_opt.pval = p->pval;
p_opt.ptype = p->ptype;
- RTA_PUT(skb, TCA_GACT_PROB, sizeof (p_opt), &p_opt);
- }
+ RTA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt);
+ }
#endif
t.install = jiffies_to_clock_t(jiffies - p->tm.install);
t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
t.expires = jiffies_to_clock_t(p->tm.expires);
- RTA_PUT(skb, TCA_GACT_TM, sizeof (t), &t);
+ RTA_PUT(skb, TCA_GACT_TM, sizeof(t), &t);
return skb->len;
rtattr_failure:
@@ -215,7 +194,6 @@ tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
}
static struct tc_action_ops act_gact_ops = {
- .next = NULL,
.kind = "gact",
.type = TCA_ACT_GACT,
.capab = TCA_CAP_NONE,
diff --git a/net/sched/ipt.c b/net/sched/ipt.c
index 386d948ab1b2..a43097231590 100644
--- a/net/sched/ipt.c
+++ b/net/sched/ipt.c
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
+#include <linux/kmod.h>
#include <net/sock.h>
#include <net/pkt_sched.h>
#include <linux/tc_act/tc_ipt.h>
@@ -45,231 +46,179 @@
static u32 idx_gen;
static struct tcf_ipt *tcf_ipt_ht[MY_TAB_SIZE];
/* ipt hash table lock */
-static rwlock_t ipt_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ipt_lock);
/* ovewrride the defaults */
-#define tcf_st tcf_ipt
-#define tcf_t_lock ipt_lock
-#define tcf_ht tcf_ipt_ht
+#define tcf_st tcf_ipt
+#define tcf_t_lock ipt_lock
+#define tcf_ht tcf_ipt_ht
+#define CONFIG_NET_ACT_INIT
#include <net/pkt_act.h>
-static inline int
-init_targ(struct tcf_ipt *p)
+static int
+ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
{
struct ipt_target *target;
int ret = 0;
- struct ipt_entry_target *t = p->t;
- target = __ipt_find_target_lock(t->u.user.name, &ret);
- if (!target) {
- printk("init_targ: Failed to find %s\n", t->u.user.name);
- return -1;
- }
+ target = ipt_find_target(t->u.user.name, t->u.user.revision);
+ if (!target)
+ return -ENOENT;
- DPRINTK("init_targ: found %s\n", target->name);
- /* we really need proper ref counting
- seems to be only needed for modules?? Talk to laforge */
-/* if (target->me)
- __MOD_INC_USE_COUNT(target->me);
-*/
+ DPRINTK("ipt_init_target: found %s\n", target->name);
t->u.kernel.target = target;
- __ipt_mutex_up();
-
if (t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(p->tname, NULL, t->data,
- t->u.target_size
- - sizeof (*t), p->hook)) {
-/* if (t->u.kernel.target->me)
- __MOD_DEC_USE_COUNT(t->u.kernel.target->me);
-*/
- DPRINTK("ip_tables: check failed for `%s'.\n",
+ && !t->u.kernel.target->checkentry(table, NULL, t->data,
+ t->u.target_size - sizeof(*t),
+ hook)) {
+ DPRINTK("ipt_init_target: check failed for `%s'.\n",
t->u.kernel.target->name);
+ module_put(t->u.kernel.target->me);
ret = -EINVAL;
}
return ret;
}
+static void
+ipt_destroy_target(struct ipt_entry_target *t)
+{
+ if (t->u.kernel.target->destroy)
+ t->u.kernel.target->destroy(t->data,
+ t->u.target_size - sizeof(*t));
+ module_put(t->u.kernel.target->me);
+}
+
static int
-tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, int ovr, int bind)
+tcf_ipt_release(struct tcf_ipt *p, int bind)
{
- struct ipt_entry_target *t;
- unsigned h;
- struct rtattr *tb[TCA_IPT_MAX];
- struct tcf_ipt *p;
int ret = 0;
- u32 index = 0;
- u32 hook = 0;
-
- if (NULL == a || NULL == rta ||
- (rtattr_parse(tb, TCA_IPT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) <
- 0)) {
- return -1;
- }
-
-
- if (tb[TCA_IPT_INDEX - 1]) {
- index = *(u32 *) RTA_DATA(tb[TCA_IPT_INDEX - 1]);
- DPRINTK("ipt index %d\n", index);
- }
-
- if (index && (p = tcf_hash_lookup(index)) != NULL) {
- a->priv = (void *) p;
- spin_lock(&p->lock);
- if (bind) {
- p->bindcnt += 1;
- p->refcnt += 1;
- }
- if (ovr) {
- goto override;
+ if (p) {
+ if (bind)
+ p->bindcnt--;
+ p->refcnt--;
+ if (p->bindcnt <= 0 && p->refcnt <= 0) {
+ ipt_destroy_target(p->t);
+ kfree(p->tname);
+ kfree(p->t);
+ tcf_hash_destroy(p);
+ ret = ACT_P_DELETED;
}
- spin_unlock(&p->lock);
- return ret;
}
+ return ret;
+}
- if (NULL == tb[TCA_IPT_TARG - 1] || NULL == tb[TCA_IPT_HOOK - 1]) {
- return -1;
- }
+static int
+tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
+ int ovr, int bind)
+{
+ struct rtattr *tb[TCA_IPT_MAX];
+ struct tcf_ipt *p;
+ struct ipt_entry_target *td, *t;
+ char *tname;
+ int ret = 0, err;
+ u32 hook = 0;
+ u32 index = 0;
- p = kmalloc(sizeof (*p), GFP_KERNEL);
- if (p == NULL)
- return -1;
-
- memset(p, 0, sizeof (*p));
- p->refcnt = 1;
- ret = 1;
- spin_lock_init(&p->lock);
- p->stats_lock = &p->lock;
- if (bind)
- p->bindcnt = 1;
-
-override:
- hook = *(u32 *) RTA_DATA(tb[TCA_IPT_HOOK - 1]);
-
- t = (struct ipt_entry_target *) RTA_DATA(tb[TCA_IPT_TARG - 1]);
-
- p->t = kmalloc(t->u.target_size, GFP_KERNEL);
- if (p->t == NULL) {
- if (ovr) {
- printk("ipt policy messed up \n");
- spin_unlock(&p->lock);
- return -1;
+ if (rta == NULL || rtattr_parse_nested(tb, TCA_IPT_MAX, rta) < 0)
+ return -EINVAL;
+
+ if (tb[TCA_IPT_HOOK-1] == NULL ||
+ RTA_PAYLOAD(tb[TCA_IPT_HOOK-1]) < sizeof(u32))
+ return -EINVAL;
+ if (tb[TCA_IPT_TARG-1] == NULL ||
+ RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < sizeof(*t))
+ return -EINVAL;
+ td = (struct ipt_entry_target *)RTA_DATA(tb[TCA_IPT_TARG-1]);
+ if (RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < td->u.target_size)
+ return -EINVAL;
+
+ if (tb[TCA_IPT_INDEX-1] != NULL &&
+ RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32))
+ index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]);
+
+ p = tcf_hash_check(index, a, ovr, bind);
+ if (p == NULL) {
+ p = tcf_hash_create(index, est, a, sizeof(*p), ovr, bind);
+ if (p == NULL)
+ return -ENOMEM;
+ ret = ACT_P_CREATED;
+ } else {
+ if (!ovr) {
+ tcf_ipt_release(p, bind);
+ return -EEXIST;
}
- kfree(p);
- return -1;
}
- memcpy(p->t, RTA_DATA(tb[TCA_IPT_TARG - 1]), t->u.target_size);
- DPRINTK(" target NAME %s size %d data[0] %x data[1] %x\n",
- t->u.user.name, t->u.target_size, t->data[0], t->data[1]);
+ hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]);
- p->tname = kmalloc(IFNAMSIZ, GFP_KERNEL);
+ err = -ENOMEM;
+ tname = kmalloc(IFNAMSIZ, GFP_KERNEL);
+ if (tname == NULL)
+ goto err1;
+ if (tb[TCA_IPT_TABLE - 1] == NULL ||
+ rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ)
+ strcpy(tname, "mangle");
- if (p->tname == NULL) {
- if (ovr) {
- printk("ipt policy messed up 2 \n");
- spin_unlock(&p->lock);
- return -1;
- }
- kfree(p->t);
- kfree(p);
- return -1;
- } else {
- int csize = IFNAMSIZ - 1;
-
- memset(p->tname, 0, IFNAMSIZ);
- if (tb[TCA_IPT_TABLE - 1]) {
- if (strlen((char *) RTA_DATA(tb[TCA_IPT_TABLE - 1])) <
- csize)
- csize = strlen(RTA_DATA(tb[TCA_IPT_TABLE - 1]));
- strncpy(p->tname, RTA_DATA(tb[TCA_IPT_TABLE - 1]),
- csize);
- DPRINTK("table name %s\n", p->tname);
- } else {
- strncpy(p->tname, "mangle", 1 + strlen("mangle"));
- }
- }
+ t = kmalloc(td->u.target_size, GFP_KERNEL);
+ if (t == NULL)
+ goto err2;
+ memcpy(t, td, td->u.target_size);
- if (0 > init_targ(p)) {
- if (ovr) {
- printk("ipt policy messed up 2 \n");
- spin_unlock(&p->lock);
- return -1;
- }
+ if ((err = ipt_init_target(t, tname, hook)) < 0)
+ goto err3;
+
+ spin_lock_bh(&p->lock);
+ if (ret != ACT_P_CREATED) {
+ ipt_destroy_target(p->t);
kfree(p->tname);
kfree(p->t);
- kfree(p);
- return -1;
- }
-
- if (ovr) {
- spin_unlock(&p->lock);
- return -1;
}
-
- p->index = index ? : tcf_hash_new_index();
-
- p->tm.lastuse = jiffies;
- /*
- p->tm.expires = jiffies;
- */
- p->tm.install = jiffies;
-#ifdef CONFIG_NET_ESTIMATOR
- if (est)
- gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est);
-#endif
- h = tcf_hash(p->index);
- write_lock_bh(&ipt_lock);
- p->next = tcf_ipt_ht[h];
- tcf_ipt_ht[h] = p;
- write_unlock_bh(&ipt_lock);
- a->priv = (void *) p;
+ p->tname = tname;
+ p->t = t;
+ p->hook = hook;
+ spin_unlock_bh(&p->lock);
+ if (ret == ACT_P_CREATED)
+ tcf_hash_insert(p);
return ret;
+err3:
+ kfree(t);
+err2:
+ kfree(tname);
+err1:
+ kfree(p);
+ return err;
}
static int
tcf_ipt_cleanup(struct tc_action *a, int bind)
{
- struct tcf_ipt *p;
- p = PRIV(a,ipt);
- if (NULL != p)
- return tcf_hash_release(p, bind);
- return 0;
+ struct tcf_ipt *p = PRIV(a, ipt);
+ return tcf_ipt_release(p, bind);
}
static int
tcf_ipt(struct sk_buff **pskb, struct tc_action *a)
{
int ret = 0, result = 0;
- struct tcf_ipt *p;
+ struct tcf_ipt *p = PRIV(a, ipt);
struct sk_buff *skb = *pskb;
- p = PRIV(a,ipt);
-
- if (NULL == p || NULL == skb) {
- return -1;
- }
-
spin_lock(&p->lock);
p->tm.lastuse = jiffies;
p->bstats.bytes += skb->len;
p->bstats.packets++;
- if (skb_cloned(skb) ) {
- if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
- return -1;
- }
- }
/* yes, we have to worry about both in and out dev
worry later - danger - this API seems to have changed
from earlier kernels */
ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL,
- p->hook, p->t->data, (void *)NULL);
+ p->hook, p->t->data, NULL);
switch (ret) {
case NF_ACCEPT:
result = TC_ACT_OK;
@@ -299,22 +248,15 @@ tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
struct tcf_t tm;
struct tc_cnt c;
unsigned char *b = skb->tail;
+ struct tcf_ipt *p = PRIV(a, ipt);
- struct tcf_ipt *p;
-
- p = PRIV(a,ipt);
- if (NULL == p) {
- printk("BUG: tcf_ipt_dump called with NULL params\n");
- goto rtattr_failure;
- }
/* for simple targets kernel size == user size
** user name = target name
** for foolproof you need to not assume this
*/
t = kmalloc(p->t->u.user.target_size, GFP_ATOMIC);
-
- if (NULL == t)
+ if (t == NULL)
goto rtattr_failure;
c.bindcnt = p->bindcnt - bind;
@@ -324,10 +266,10 @@ tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
DPRINTK("\ttcf_ipt_dump tablename %s length %d\n", p->tname,
strlen(p->tname));
- DPRINTK
- ("\tdump target name %s size %d size user %d data[0] %x data[1] %x\n",
- p->t->u.kernel.target->name, p->t->u.target_size, p->t->u.user.target_size,
- p->t->data[0], p->t->data[1]);
+ DPRINTK("\tdump target name %s size %d size user %d "
+ "data[0] %x data[1] %x\n", p->t->u.kernel.target->name,
+ p->t->u.target_size, p->t->u.user.target_size,
+ p->t->data[0], p->t->data[1]);
RTA_PUT(skb, TCA_IPT_TARG, p->t->u.user.target_size, t);
RTA_PUT(skb, TCA_IPT_INDEX, 4, &p->index);
RTA_PUT(skb, TCA_IPT_HOOK, 4, &p->hook);
@@ -345,7 +287,6 @@ tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
}
static struct tc_action_ops act_ipt_ops = {
- .next = NULL,
.kind = "ipt",
.type = TCA_ACT_IPT,
.capab = TCA_CAP_NONE,
diff --git a/net/sched/mirred.c b/net/sched/mirred.c
index 07e3ba192178..f309ce336803 100644
--- a/net/sched/mirred.c
+++ b/net/sched/mirred.c
@@ -46,13 +46,13 @@
#define MY_TAB_MASK (MY_TAB_SIZE - 1)
static u32 idx_gen;
static struct tcf_mirred *tcf_mirred_ht[MY_TAB_SIZE];
-static rwlock_t mirred_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(mirred_lock);
/* ovewrride the defaults */
-#define tcf_st tcf_mirred
-#define tc_st tc_mirred
-#define tcf_t_lock mirred_lock
-#define tcf_ht tcf_mirred_ht
+#define tcf_st tcf_mirred
+#define tc_st tc_mirred
+#define tcf_t_lock mirred_lock
+#define tcf_ht tcf_mirred_ht
#define CONFIG_NET_ACT_INIT 1
#include <net/pkt_act.h>
@@ -61,10 +61,8 @@ static inline int
tcf_mirred_release(struct tcf_mirred *p, int bind)
{
if (p) {
- if (bind) {
+ if (bind)
p->bindcnt--;
- }
-
p->refcnt--;
if(!p->bindcnt && p->refcnt <= 0) {
dev_put(p->dev);
@@ -72,46 +70,32 @@ tcf_mirred_release(struct tcf_mirred *p, int bind)
return 1;
}
}
-
return 0;
}
static int
-tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,int ovr, int bind)
+tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
+ int ovr, int bind)
{
struct rtattr *tb[TCA_MIRRED_MAX];
struct tc_mirred *parm;
struct tcf_mirred *p;
struct net_device *dev = NULL;
- int size = sizeof (*p), new = 0;
-
-
- if (rtattr_parse(tb, TCA_MIRRED_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0) {
- DPRINTK("tcf_mirred_init BUG in user space couldnt parse properly\n");
- return -1;
- }
+ int ret = 0;
+ int ok_push = 0;
- if (NULL == a || NULL == tb[TCA_MIRRED_PARMS - 1]) {
- DPRINTK("BUG: tcf_mirred_init called with NULL params\n");
- return -1;
- }
+ if (rta == NULL || rtattr_parse_nested(tb, TCA_MIRRED_MAX, rta) < 0)
+ return -EINVAL;
- parm = RTA_DATA(tb[TCA_MIRRED_PARMS - 1]);
-
- p = tcf_hash_check(parm, a, ovr, bind);
- if (NULL == p) { /* new */
- p = tcf_hash_create(parm,est,a,size,ovr,bind);
- new = 1;
- if (NULL == p)
- return -1;
- }
+ if (tb[TCA_MIRRED_PARMS-1] == NULL ||
+ RTA_PAYLOAD(tb[TCA_MIRRED_PARMS-1]) < sizeof(*parm))
+ return -EINVAL;
+ parm = RTA_DATA(tb[TCA_MIRRED_PARMS-1]);
if (parm->ifindex) {
- dev = dev_get_by_index(parm->ifindex);
- if (NULL == dev) {
- printk("BUG: tcf_mirred_init called with bad device\n");
- return -1;
- }
+ dev = __dev_get_by_index(parm->ifindex);
+ if (dev == NULL)
+ return -ENODEV;
switch (dev->type) {
case ARPHRD_TUNNEL:
case ARPHRD_TUNNEL6:
@@ -119,44 +103,56 @@ tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,int
case ARPHRD_IPGRE:
case ARPHRD_VOID:
case ARPHRD_NONE:
- p->ok_push = 0;
+ ok_push = 0;
break;
default:
- p->ok_push = 1;
+ ok_push = 1;
break;
}
- } else {
- if (new) {
- kfree(p);
- return -1;
- }
}
- if (new || ovr) {
- spin_lock(&p->lock);
- p->action = parm->action;
- p->eaction = parm->eaction;
- if (parm->ifindex) {
- p->ifindex = parm->ifindex;
- if (ovr)
- dev_put(p->dev);
- p->dev = dev;
+ p = tcf_hash_check(parm->index, a, ovr, bind);
+ if (p == NULL) {
+ if (!parm->ifindex)
+ return -EINVAL;
+ p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
+ if (p == NULL)
+ return -ENOMEM;
+ ret = ACT_P_CREATED;
+ } else {
+ if (!ovr) {
+ tcf_mirred_release(p, bind);
+ return -EEXIST;
}
- spin_unlock(&p->lock);
}
-
- DPRINTK(" tcf_mirred_init index %d action %d eaction %d device %s ifndex %d\n",parm->index,parm->action,parm->eaction,dev->name,parm->ifindex);
- return new;
-
+ spin_lock_bh(&p->lock);
+ p->action = parm->action;
+ p->eaction = parm->eaction;
+ if (parm->ifindex) {
+ p->ifindex = parm->ifindex;
+ if (ret != ACT_P_CREATED)
+ dev_put(p->dev);
+ p->dev = dev;
+ dev_hold(dev);
+ p->ok_push = ok_push;
+ }
+ spin_unlock_bh(&p->lock);
+ if (ret == ACT_P_CREATED)
+ tcf_hash_insert(p);
+
+ DPRINTK("tcf_mirred_init index %d action %d eaction %d device %s "
+ "ifindex %d\n", parm->index, parm->action, parm->eaction,
+ dev->name, parm->ifindex);
+ return ret;
}
static int
tcf_mirred_cleanup(struct tc_action *a, int bind)
{
- struct tcf_mirred *p;
- p = PRIV(a,mirred);
- if (NULL != p)
+ struct tcf_mirred *p = PRIV(a, mirred);
+
+ if (p != NULL)
return tcf_mirred_release(p, bind);
return 0;
}
@@ -164,70 +160,52 @@ tcf_mirred_cleanup(struct tc_action *a, int bind)
static int
tcf_mirred(struct sk_buff **pskb, struct tc_action *a)
{
- struct tcf_mirred *p;
+ struct tcf_mirred *p = PRIV(a, mirred);
struct net_device *dev;
struct sk_buff *skb2 = NULL;
struct sk_buff *skb = *pskb;
- __u32 at = G_TC_AT(skb->tc_verd);
-
- if (NULL == a) {
- if (net_ratelimit())
- printk("BUG: tcf_mirred called with NULL action!\n");
- return -1;
- }
-
- p = PRIV(a,mirred);
-
- if (NULL == p) {
- if (net_ratelimit())
- printk("BUG: tcf_mirred called with NULL params\n");
- return -1;
- }
+ u32 at = G_TC_AT(skb->tc_verd);
spin_lock(&p->lock);
- dev = p->dev;
+ dev = p->dev;
p->tm.lastuse = jiffies;
- if (NULL == dev || !(dev->flags&IFF_UP) ) {
+ if (!(dev->flags&IFF_UP) ) {
if (net_ratelimit())
printk("mirred to Houston: device %s is gone!\n",
- dev?dev->name:"");
+ dev->name);
bad_mirred:
- if (NULL != skb2)
+ if (skb2 != NULL)
kfree_skb(skb2);
p->qstats.overlimits++;
p->bstats.bytes += skb->len;
p->bstats.packets++;
spin_unlock(&p->lock);
/* should we be asking for packet to be dropped?
- * may make sense for redirect case only
+ * may make sense for redirect case only
*/
return TC_ACT_SHOT;
- }
+ }
skb2 = skb_clone(skb, GFP_ATOMIC);
- if (skb2 == NULL) {
+ if (skb2 == NULL)
goto bad_mirred;
- }
- if (TCA_EGRESS_MIRROR != p->eaction &&
- TCA_EGRESS_REDIR != p->eaction) {
+ if (p->eaction != TCA_EGRESS_MIRROR && p->eaction != TCA_EGRESS_REDIR) {
if (net_ratelimit())
- printk("tcf_mirred unknown action %d\n",p->eaction);
+ printk("tcf_mirred unknown action %d\n", p->eaction);
goto bad_mirred;
}
p->bstats.bytes += skb2->len;
p->bstats.packets++;
- if ( !(at & AT_EGRESS)) {
- if (p->ok_push) {
+ if (!(at & AT_EGRESS))
+ if (p->ok_push)
skb_push(skb2, skb2->dev->hard_header_len);
- }
- }
/* mirror is always swallowed */
- if (TCA_EGRESS_MIRROR != p->eaction)
- skb2->tc_verd = SET_TC_FROM(skb2->tc_verd,at);
+ if (p->eaction != TCA_EGRESS_MIRROR)
+ skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at);
skb2->dev = dev;
skb2->input_dev = skb->dev;
@@ -237,31 +215,26 @@ bad_mirred:
}
static int
-tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref)
+tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
unsigned char *b = skb->tail;
struct tc_mirred opt;
- struct tcf_mirred *p;
+ struct tcf_mirred *p = PRIV(a, mirred);
struct tcf_t t;
- p = PRIV(a,mirred);
- if (NULL == p) {
- printk("BUG: tcf_mirred_dump called with NULL params\n");
- goto rtattr_failure;
- }
-
opt.index = p->index;
opt.action = p->action;
opt.refcnt = p->refcnt - ref;
opt.bindcnt = p->bindcnt - bind;
opt.eaction = p->eaction;
opt.ifindex = p->ifindex;
- DPRINTK(" tcf_mirred_dump index %d action %d eaction %d ifndex %d\n",p->index,p->action,p->eaction,p->ifindex);
- RTA_PUT(skb, TCA_MIRRED_PARMS, sizeof (opt), &opt);
+ DPRINTK("tcf_mirred_dump index %d action %d eaction %d ifindex %d\n",
+ p->index, p->action, p->eaction, p->ifindex);
+ RTA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt);
t.install = jiffies_to_clock_t(jiffies - p->tm.install);
t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
t.expires = jiffies_to_clock_t(p->tm.expires);
- RTA_PUT(skb, TCA_MIRRED_TM, sizeof (t), &t);
+ RTA_PUT(skb, TCA_MIRRED_TM, sizeof(t), &t);
return skb->len;
rtattr_failure:
@@ -270,7 +243,6 @@ tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref)
}
static struct tc_action_ops act_mirred_ops = {
- .next = NULL,
.kind = "mirred",
.type = TCA_ACT_MIRRED,
.capab = TCA_CAP_NONE,
@@ -287,7 +259,6 @@ MODULE_AUTHOR("Jamal Hadi Salim(2002)");
MODULE_DESCRIPTION("Device Mirror/redirect actions");
MODULE_LICENSE("GPL");
-
static int __init
mirred_init_module(void)
{
@@ -303,4 +274,3 @@ mirred_cleanup_module(void)
module_init(mirred_init_module);
module_exit(mirred_cleanup_module);
-
diff --git a/net/sched/pedit.c b/net/sched/pedit.c
index 23debf3f624d..678be6a645fb 100644
--- a/net/sched/pedit.c
+++ b/net/sched/pedit.c
@@ -42,92 +42,101 @@
#define MY_TAB_MASK 15
static u32 idx_gen;
static struct tcf_pedit *tcf_pedit_ht[MY_TAB_SIZE];
-static rwlock_t pedit_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(pedit_lock);
-#define tcf_st tcf_pedit
-#define tc_st tc_pedit
-#define tcf_t_lock pedit_lock
-#define tcf_ht tcf_pedit_ht
+#define tcf_st tcf_pedit
+#define tc_st tc_pedit
+#define tcf_t_lock pedit_lock
+#define tcf_ht tcf_pedit_ht
#define CONFIG_NET_ACT_INIT 1
#include <net/pkt_act.h>
-
static int
-tcf_pedit_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,int ovr, int bind)
+tcf_pedit_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
+ int ovr, int bind)
{
struct rtattr *tb[TCA_PEDIT_MAX];
struct tc_pedit *parm;
- int size = 0;
int ret = 0;
- struct tcf_pedit *p = NULL;
-
- if (rtattr_parse(tb, TCA_PEDIT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
- return -1;
-
- if (NULL == a || NULL == tb[TCA_PEDIT_PARMS - 1]) {
- printk("BUG: tcf_pedit_init called with NULL params\n");
- return -1;
- }
-
- parm = RTA_DATA(tb[TCA_PEDIT_PARMS - 1]);
-
- p = tcf_hash_check(parm, a, ovr, bind);
-
- if (NULL == p) { /* new */
-
+ struct tcf_pedit *p;
+ struct tc_pedit_key *keys = NULL;
+ int ksize;
+
+ if (rta == NULL || rtattr_parse_nested(tb, TCA_PEDIT_MAX, rta) < 0)
+ return -EINVAL;
+
+ if (tb[TCA_PEDIT_PARMS - 1] == NULL ||
+ RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm))
+ return -EINVAL;
+ parm = RTA_DATA(tb[TCA_PEDIT_PARMS-1]);
+ ksize = parm->nkeys * sizeof(struct tc_pedit_key);
+ if (RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm) + ksize)
+ return -EINVAL;
+
+ p = tcf_hash_check(parm->index, a, ovr, bind);
+ if (p == NULL) {
if (!parm->nkeys)
- return -1;
-
- size = sizeof (*p)+ (parm->nkeys*sizeof(struct tc_pedit_key));
-
- p = tcf_hash_create(parm,est,a,size,ovr,bind);
-
- if (NULL == p)
- return -1;
- ret = 1;
- goto override;
- }
+ return -EINVAL;
+ p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
+ if (p == NULL)
+ return -ENOMEM;
+ keys = kmalloc(ksize, GFP_KERNEL);
+ if (keys == NULL) {
+ kfree(p);
+ return -ENOMEM;
+ }
+ ret = ACT_P_CREATED;
+ } else {
+ if (!ovr) {
+ tcf_hash_release(p, bind);
+ return -EEXIST;
+ }
+ if (p->nkeys && p->nkeys != parm->nkeys) {
+ keys = kmalloc(ksize, GFP_KERNEL);
+ if (keys == NULL)
+ return -ENOMEM;
+ }
+ }
- if (ovr) {
-override:
- p->flags = parm->flags;
+ spin_lock_bh(&p->lock);
+ p->flags = parm->flags;
+ p->action = parm->action;
+ if (keys) {
+ kfree(p->keys);
+ p->keys = keys;
p->nkeys = parm->nkeys;
- p->action = parm->action;
- memcpy(p->keys,parm->keys,parm->nkeys*(sizeof(struct tc_pedit_key)));
}
-
+ memcpy(p->keys, parm->keys, ksize);
+ spin_unlock_bh(&p->lock);
+ if (ret == ACT_P_CREATED)
+ tcf_hash_insert(p);
return ret;
}
static int
tcf_pedit_cleanup(struct tc_action *a, int bind)
{
- struct tcf_pedit *p;
- p = PRIV(a,pedit);
- if (NULL != p)
- return tcf_hash_release(p, bind);
+ struct tcf_pedit *p = PRIV(a, pedit);
+
+ if (p != NULL) {
+ struct tc_pedit_key *keys = p->keys;
+ if (tcf_hash_release(p, bind)) {
+ kfree(keys);
+ return 1;
+ }
+ }
return 0;
}
-/*
-**
-*/
static int
tcf_pedit(struct sk_buff **pskb, struct tc_action *a)
{
- struct tcf_pedit *p;
+ struct tcf_pedit *p = PRIV(a, pedit);
struct sk_buff *skb = *pskb;
int i, munged = 0;
u8 *pptr;
- p = PRIV(a,pedit);
-
- if (NULL == p) {
- printk("BUG: tcf_pedit called with NULL params\n");
- return -1; /* change to something symbolic */
- }
-
if (!(skb->tc_verd & TC_OK2MUNGE)) {
/* should we set skb->cloned? */
if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
@@ -141,17 +150,18 @@ tcf_pedit(struct sk_buff **pskb, struct tc_action *a)
p->tm.lastuse = jiffies;
- if (0 < p->nkeys) {
+ if (p->nkeys > 0) {
struct tc_pedit_key *tkey = p->keys;
for (i = p->nkeys; i > 0; i--, tkey++) {
- u32 *ptr ;
-
+ u32 *ptr;
int offset = tkey->off;
+
if (tkey->offmask) {
if (skb->len > tkey->at) {
- char *j = pptr+tkey->at;
- offset +=((*j&tkey->offmask)>>tkey->shift);
+ char *j = pptr + tkey->at;
+ offset += ((*j & tkey->offmask) >>
+ tkey->shift);
} else {
goto bad;
}
@@ -161,14 +171,12 @@ tcf_pedit(struct sk_buff **pskb, struct tc_action *a)
printk("offset must be on 32 bit boundaries\n");
goto bad;
}
-
if (skb->len < 0 || (offset > 0 && offset > skb->len)) {
printk("offset %d cant exceed pkt length %d\n",
- offset, skb->len);
+ offset, skb->len);
goto bad;
}
-
ptr = (u32 *)(pptr+offset);
/* just do it, baby */
*ptr = ((*ptr & tkey->mask) ^ tkey->val);
@@ -196,29 +204,19 @@ tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref)
{
unsigned char *b = skb->tail;
struct tc_pedit *opt;
- struct tcf_pedit *p;
+ struct tcf_pedit *p = PRIV(a, pedit);
struct tcf_t t;
int s;
+ s = sizeof(*opt) + p->nkeys * sizeof(struct tc_pedit_key);
- p = PRIV(a,pedit);
-
- if (NULL == p) {
- printk("BUG: tcf_pedit_dump called with NULL params\n");
- goto rtattr_failure;
- }
-
- s = sizeof (*opt)+(p->nkeys*sizeof(struct tc_pedit_key));
-
- /* netlink spinlocks held above us - must use ATOMIC
- * */
+ /* netlink spinlocks held above us - must use ATOMIC */
opt = kmalloc(s, GFP_ATOMIC);
if (opt == NULL)
return -ENOBUFS;
-
memset(opt, 0, s);
- memcpy(opt->keys,p->keys,p->nkeys*(sizeof(struct tc_pedit_key)));
+ memcpy(opt->keys, p->keys, p->nkeys * sizeof(struct tc_pedit_key));
opt->index = p->index;
opt->nkeys = p->nkeys;
opt->flags = p->flags;
@@ -239,15 +237,15 @@ tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref)
(unsigned int)key->off,
(unsigned int)key->val,
(unsigned int)key->mask);
- }
- }
+ }
+ }
#endif
RTA_PUT(skb, TCA_PEDIT_PARMS, s, opt);
t.install = jiffies_to_clock_t(jiffies - p->tm.install);
t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
t.expires = jiffies_to_clock_t(p->tm.expires);
- RTA_PUT(skb, TCA_PEDIT_TM, sizeof (t), &t);
+ RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t);
return skb->len;
rtattr_failure:
diff --git a/net/sched/police.c b/net/sched/police.c
index b8c54c5727e5..c03545faf523 100644
--- a/net/sched/police.c
+++ b/net/sched/police.c
@@ -43,7 +43,7 @@
static u32 idx_gen;
static struct tcf_police *tcf_police_ht[MY_TAB_SIZE];
/* Policer hash table lock */
-static rwlock_t police_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(police_lock);
/* Each policer is serialized by its individual spinlock */
@@ -66,11 +66,12 @@ static __inline__ struct tcf_police * tcf_police_lookup(u32 index)
}
#ifdef CONFIG_NET_CLS_ACT
-static __inline__ int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, int type, struct tc_action *a)
+static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
+ int type, struct tc_action *a)
{
struct tcf_police *p;
- int err =0, index = -1,i= 0, s_i = 0, n_i = 0;
- struct rtattr *r ;
+ int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
+ struct rtattr *r;
read_lock(&police_lock);
@@ -91,7 +92,7 @@ static __inline__ int tcf_generic_walker(struct sk_buff *skb, struct netlink_cal
err = tcf_action_dump_1(skb, a, 0, 1);
else
err = tcf_action_dump_1(skb, a, 0, 0);
- if (0 > err) {
+ if (err < 0) {
index--;
skb_trim(skb, (u8*)r - skb->data);
goto done;
@@ -123,11 +124,9 @@ tcf_hash_search(struct tc_action *a, u32 index)
return 0;
}
}
-
-
#endif
-static __inline__ u32 tcf_police_new_index(void)
+static inline u32 tcf_police_new_index(void)
{
do {
if (++idx_gen == 0)
@@ -137,7 +136,6 @@ static __inline__ u32 tcf_police_new_index(void)
return idx_gen;
}
-
void tcf_police_destroy(struct tcf_police *p)
{
unsigned h = tcf_police_hash(p->index);
@@ -163,49 +161,48 @@ void tcf_police_destroy(struct tcf_police *p)
}
#ifdef CONFIG_NET_CLS_ACT
-static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,struct tc_action *a, int ovr, int bind)
+static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
+ struct tc_action *a, int ovr, int bind)
{
unsigned h;
- int ret = 0;
+ int ret = 0, err;
struct rtattr *tb[TCA_POLICE_MAX];
struct tc_police *parm;
struct tcf_police *p;
+ struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
- if (NULL == a) {
- if (net_ratelimit())
- printk("BUG: tcf_police_locate called with NULL params\n");
- return -1;
- }
-
- if (rtattr_parse(tb, TCA_POLICE_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
- return -1;
+ if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
+ return -EINVAL;
if (tb[TCA_POLICE_TBF-1] == NULL ||
RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm))
- return -1;
-
+ return -EINVAL;
parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
+ if (tb[TCA_POLICE_RESULT-1] != NULL &&
+ RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
+ return -EINVAL;
+ if (tb[TCA_POLICE_RESULT-1] != NULL &&
+ RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
+ return -EINVAL;
+
if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) {
- a->priv = (void *)p;
- spin_lock(&p->lock);
+ a->priv = p;
if (bind) {
p->bindcnt += 1;
p->refcnt += 1;
}
- if (ovr) {
+ if (ovr)
goto override;
- }
- spin_unlock(&p->lock);
- return ret;
+ return ret;
}
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL)
- return -1;
-
+ return -ENOMEM;
memset(p, 0, sizeof(*p));
- ret = 1;
+
+ ret = ACT_P_CREATED;
p->refcnt = 1;
spin_lock_init(&p->lock);
p->stats_lock = &p->lock;
@@ -213,26 +210,32 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,struct t
p->bindcnt = 1;
override:
if (parm->rate.rate) {
- if ((p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1])) == NULL) {
- goto failure;
- }
- if (parm->peakrate.rate &&
- (p->P_tab = qdisc_get_rtab(&parm->peakrate, tb[TCA_POLICE_PEAKRATE-1])) == NULL) {
+ err = -ENOMEM;
+ R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
+ if (R_tab == NULL)
goto failure;
+ if (parm->peakrate.rate) {
+ P_tab = qdisc_get_rtab(&parm->peakrate,
+ tb[TCA_POLICE_PEAKRATE-1]);
+ if (p->P_tab == NULL) {
+ qdisc_put_rtab(R_tab);
+ goto failure;
+ }
}
}
- if (tb[TCA_POLICE_RESULT-1]) {
- if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
- goto failure;
- p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
+ /* No failure allowed after this point */
+ spin_lock_bh(&p->lock);
+ if (R_tab != NULL) {
+ qdisc_put_rtab(p->R_tab);
+ p->R_tab = R_tab;
}
-#ifdef CONFIG_NET_ESTIMATOR
- if (tb[TCA_POLICE_AVRATE-1]) {
- if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32))
- goto failure;
- p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
+ if (P_tab != NULL) {
+ qdisc_put_rtab(p->P_tab);
+ p->P_tab = P_tab;
}
-#endif
+
+ if (tb[TCA_POLICE_RESULT-1])
+ p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
p->toks = p->burst = parm->burst;
p->mtu = parm->mtu;
if (p->mtu == 0) {
@@ -244,41 +247,40 @@ override:
p->ptoks = L2T_P(p, p->mtu);
p->action = parm->action;
- if (ovr) {
- spin_unlock(&p->lock);
- return ret;
- }
- PSCHED_GET_TIME(p->t_c);
- p->index = parm->index ? : tcf_police_new_index();
#ifdef CONFIG_NET_ESTIMATOR
+ if (tb[TCA_POLICE_AVRATE-1])
+ p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
if (est)
- gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est);
+ gen_replace_estimator(&p->bstats, &p->rate_est, p->stats_lock, est);
#endif
+
+ spin_unlock_bh(&p->lock);
+ if (ret != ACT_P_CREATED)
+ return ret;
+
+ PSCHED_GET_TIME(p->t_c);
+ p->index = parm->index ? : tcf_police_new_index();
h = tcf_police_hash(p->index);
write_lock_bh(&police_lock);
p->next = tcf_police_ht[h];
tcf_police_ht[h] = p;
write_unlock_bh(&police_lock);
- a->priv = (void *)p;
- return ret;
+ a->priv = p;
+ return ret;
failure:
- if (p->R_tab)
- qdisc_put_rtab(p->R_tab);
- if (ovr)
- spin_unlock(&p->lock);
- kfree(p);
- return -1;
+ if (ret == ACT_P_CREATED)
+ kfree(p);
+ return err;
}
static int tcf_act_police_cleanup(struct tc_action *a, int bind)
{
- struct tcf_police *p;
- p = PRIV(a);
- if (NULL != p)
- return tcf_police_release(p, bind);
+ struct tcf_police *p = PRIV(a);
+ if (p != NULL)
+ return tcf_police_release(p, bind);
return 0;
}
@@ -286,17 +288,10 @@ static int tcf_act_police(struct sk_buff **pskb, struct tc_action *a)
{
psched_time_t now;
struct sk_buff *skb = *pskb;
- struct tcf_police *p;
+ struct tcf_police *p = PRIV(a);
long toks;
long ptoks = 0;
- p = PRIV(a);
-
- if (NULL == p) {
- printk("BUG: tcf_police called with NULL params\n");
- return -1;
- }
-
spin_lock(&p->lock);
p->bstats.bytes += skb->len;
@@ -345,17 +340,12 @@ static int tcf_act_police(struct sk_buff **pskb, struct tc_action *a)
return p->action;
}
-static int tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+static int
+tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
unsigned char *b = skb->tail;
struct tc_police opt;
- struct tcf_police *p;
-
- p = PRIV(a);
- if (NULL == p) {
- printk("BUG: tcf_police_dump called with NULL params\n");
- goto rtattr_failure;
- }
+ struct tcf_police *p = PRIV(a);
opt.index = p->index;
opt.action = p->action;
@@ -389,12 +379,10 @@ MODULE_AUTHOR("Alexey Kuznetsov");
MODULE_DESCRIPTION("Policing actions");
MODULE_LICENSE("GPL");
-
static struct tc_action_ops act_police_ops = {
- .next = NULL,
.kind = "police",
- .type = TCA_ID_POLICE,
- .capab = TCA_CAP_NONE,
+ .type = TCA_ID_POLICE,
+ .capab = TCA_CAP_NONE,
.owner = THIS_MODULE,
.act = tcf_act_police,
.dump = tcf_act_police_dump,
@@ -428,7 +416,7 @@ struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est)
struct rtattr *tb[TCA_POLICE_MAX];
struct tc_police *parm;
- if (rtattr_parse(tb, TCA_POLICE_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
+ if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
return NULL;
if (tb[TCA_POLICE_TBF-1] == NULL ||
@@ -451,11 +439,15 @@ struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est)
spin_lock_init(&p->lock);
p->stats_lock = &p->lock;
if (parm->rate.rate) {
- if ((p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1])) == NULL)
- goto failure;
- if (parm->peakrate.rate &&
- (p->P_tab = qdisc_get_rtab(&parm->peakrate, tb[TCA_POLICE_PEAKRATE-1])) == NULL)
+ p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
+ if (p->R_tab == NULL)
goto failure;
+ if (parm->peakrate.rate) {
+ p->P_tab = qdisc_get_rtab(&parm->peakrate,
+ tb[TCA_POLICE_PEAKRATE-1]);
+ if (p->P_tab == NULL)
+ goto failure;
+ }
}
if (tb[TCA_POLICE_RESULT-1]) {
if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index a8570f361d6d..10714716d4c7 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -131,7 +131,7 @@ static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n,
*/
/* Protects list of registered TC modules. It is pure SMP lock. */
-static rwlock_t qdisc_mod_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(qdisc_mod_lock);
/************************************************
@@ -407,8 +407,9 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
ops = qdisc_lookup_ops(kind);
#ifdef CONFIG_KMOD
if (ops==NULL && tca[TCA_KIND-1] != NULL) {
- if (RTA_PAYLOAD(kind) <= IFNAMSIZ) {
- request_module("sch_%s", (char*)RTA_DATA(kind));
+ char name[IFNAMSIZ];
+ if (rtattr_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
+ request_module("sch_%s", name);
ops = qdisc_lookup_ops(kind);
}
}
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 711143443182..427b6fe7bfac 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -255,8 +255,8 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
* later.)
*/
if (flow) return -EBUSY;
- if (opt == NULL || rtattr_parse(tb,TCA_ATM_MAX,RTA_DATA(opt),
- RTA_PAYLOAD(opt))) return -EINVAL;
+ if (opt == NULL || rtattr_parse_nested(tb, TCA_ATM_MAX, opt))
+ return -EINVAL;
if (!tb[TCA_ATM_FD-1] || RTA_PAYLOAD(tb[TCA_ATM_FD-1]) < sizeof(fd))
return -EINVAL;
fd = *(int *) RTA_DATA(tb[TCA_ATM_FD-1]);
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 74ca4ee720e4..b4c1c1f15dc2 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1439,7 +1439,7 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt)
struct rtattr *tb[TCA_CBQ_MAX];
struct tc_ratespec *r;
- if (rtattr_parse(tb, TCA_CBQ_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)) < 0 ||
+ if (rtattr_parse_nested(tb, TCA_CBQ_MAX, opt) < 0 ||
tb[TCA_CBQ_RTAB-1] == NULL || tb[TCA_CBQ_RATE-1] == NULL ||
RTA_PAYLOAD(tb[TCA_CBQ_RATE-1]) < sizeof(struct tc_ratespec))
return -EINVAL;
@@ -1824,8 +1824,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
struct cbq_class *parent;
struct qdisc_rate_table *rtab = NULL;
- if (opt==NULL ||
- rtattr_parse(tb, TCA_CBQ_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)))
+ if (opt==NULL || rtattr_parse_nested(tb, TCA_CBQ_MAX, opt))
return -EINVAL;
if (tb[TCA_CBQ_OVL_STRATEGY-1] &&
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 19f4e4fa7f48..8a3db9d95bab 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -125,8 +125,7 @@ static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
"arg 0x%lx\n",sch,p,classid,parent,*arg);
if (*arg > p->indices)
return -ENOENT;
- if (!opt || rtattr_parse(tb, TCA_DSMARK_MAX, RTA_DATA(opt),
- RTA_PAYLOAD(opt)))
+ if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt))
return -EINVAL;
if (tb[TCA_DSMARK_MASK-1]) {
if (!RTA_PAYLOAD(tb[TCA_DSMARK_MASK-1]))
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 35e87b35a33f..8c01e023f02e 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -54,7 +54,7 @@
qdisc_tree_lock must be grabbed BEFORE dev->queue_lock!
*/
-rwlock_t qdisc_tree_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(qdisc_tree_lock);
void qdisc_lock_tree(struct net_device *dev)
{
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index decd7ba297e7..25c171c32715 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -332,13 +332,11 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt)
struct rtattr *tb2[TCA_GRED_DPS];
int i;
- if (opt == NULL ||
- rtattr_parse(tb, TCA_GRED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) )
- return -EINVAL;
+ if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_STAB, opt))
+ return -EINVAL;
if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0) {
- rtattr_parse(tb2, TCA_GRED_DPS, RTA_DATA(opt),
- RTA_PAYLOAD(opt));
+ rtattr_parse_nested(tb2, TCA_GRED_DPS, opt);
if (tb2[TCA_GRED_DPS-1] == 0)
return -EINVAL;
@@ -475,12 +473,11 @@ static int gred_init(struct Qdisc *sch, struct rtattr *opt)
struct rtattr *tb[TCA_GRED_STAB];
struct rtattr *tb2[TCA_GRED_DPS];
- if (opt == NULL ||
- rtattr_parse(tb, TCA_GRED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) )
- return -EINVAL;
+ if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_STAB, opt))
+ return -EINVAL;
if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0) {
- rtattr_parse(tb2, TCA_GRED_DPS, RTA_DATA(opt),RTA_PAYLOAD(opt));
+ rtattr_parse_nested(tb2, TCA_GRED_DPS, opt);
if (tb2[TCA_GRED_DPS-1] == 0)
return -EINVAL;
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index c6288dedc660..d09e0b0cb5f9 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1046,8 +1046,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL;
u64 cur_time;
- if (opt == NULL ||
- rtattr_parse(tb, TCA_HFSC_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)))
+ if (opt == NULL || rtattr_parse_nested(tb, TCA_HFSC_MAX, opt))
return -EINVAL;
if (tb[TCA_HFSC_RSC-1]) {
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 25fa2c06f139..116028554ae4 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1267,7 +1267,7 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt)
printk(KERN_INFO "HTB init, kernel part version %d.%d\n",
HTB_VER >> 16,HTB_VER & 0xffff);
#endif
- if (!opt || rtattr_parse(tb, TCA_HTB_INIT, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
+ if (!opt || rtattr_parse_nested(tb, TCA_HTB_INIT, opt) ||
tb[TCA_HTB_INIT-1] == NULL ||
RTA_PAYLOAD(tb[TCA_HTB_INIT-1]) < sizeof(*gopt)) {
printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
@@ -1559,7 +1559,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
struct tc_htb_opt *hopt;
/* extract all subattrs from opt attr */
- if (!opt || rtattr_parse(tb, TCA_HTB_RTAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
+ if (!opt || rtattr_parse_nested(tb, TCA_HTB_RTAB, opt) ||
tb[TCA_HTB_PARMS-1] == NULL ||
RTA_PAYLOAD(tb[TCA_HTB_PARMS-1]) < sizeof(*hopt))
goto failure;
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 4ea63bc58a28..664d0e47374f 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -364,7 +364,7 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt)
struct tc_red_qopt *ctl;
if (opt == NULL ||
- rtattr_parse(tb, TCA_RED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
+ rtattr_parse_nested(tb, TCA_RED_STAB, opt) ||
tb[TCA_RED_PARMS-1] == 0 || tb[TCA_RED_STAB-1] == 0 ||
RTA_PAYLOAD(tb[TCA_RED_PARMS-1]) < sizeof(*ctl) ||
RTA_PAYLOAD(tb[TCA_RED_STAB-1]) < 256)
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 2c3f14a8492d..cb9711ea8c6c 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -310,7 +310,7 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
struct Qdisc *child = NULL;
int max_size,n;
- if (rtattr_parse(tb, TCA_TBF_PTAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
+ if (rtattr_parse_nested(tb, TCA_TBF_PTAB, opt) ||
tb[TCA_TBF_PARMS-1] == NULL ||
RTA_PAYLOAD(tb[TCA_TBF_PARMS-1]) < sizeof(*qopt))
goto done;
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 498a71367ceb..fda3bc435c7c 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -66,33 +66,8 @@ static void sctp_assoc_bh_rcv(struct sctp_association *asoc);
/* 1st Level Abstractions. */
-/* Allocate and initialize a new association */
-struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep,
- const struct sock *sk,
- sctp_scope_t scope, int gfp)
-{
- struct sctp_association *asoc;
-
- asoc = t_new(struct sctp_association, gfp);
- if (!asoc)
- goto fail;
-
- if (!sctp_association_init(asoc, ep, sk, scope, gfp))
- goto fail_init;
-
- asoc->base.malloced = 1;
- SCTP_DBG_OBJCNT_INC(assoc);
-
- return asoc;
-
-fail_init:
- kfree(asoc);
-fail:
- return NULL;
-}
-
/* Initialize a new association from provided memory. */
-struct sctp_association *sctp_association_init(struct sctp_association *asoc,
+static struct sctp_association *sctp_association_init(struct sctp_association *asoc,
const struct sctp_endpoint *ep,
const struct sock *sk,
sctp_scope_t scope,
@@ -204,6 +179,7 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc,
asoc->c.peer_vtag = 0;
asoc->c.my_ttag = 0;
asoc->c.peer_ttag = 0;
+ asoc->c.my_port = ep->base.bind_addr.port;
asoc->c.initial_tsn = sctp_generate_tsn(ep);
@@ -296,6 +272,31 @@ fail_init:
return NULL;
}
+/* Allocate and initialize a new association */
+struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep,
+ const struct sock *sk,
+ sctp_scope_t scope, int gfp)
+{
+ struct sctp_association *asoc;
+
+ asoc = t_new(struct sctp_association, gfp);
+ if (!asoc)
+ goto fail;
+
+ if (!sctp_association_init(asoc, ep, sk, scope, gfp))
+ goto fail_init;
+
+ asoc->base.malloced = 1;
+ SCTP_DBG_OBJCNT_INC(assoc);
+
+ return asoc;
+
+fail_init:
+ kfree(asoc);
+fail:
+ return NULL;
+}
+
/* Free this association if possible. There may still be users, so
* the actual deallocation may be delayed.
*/
@@ -500,7 +501,6 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
peer->partial_bytes_acked = 0;
peer->flight_size = 0;
- peer->error_threshold = peer->max_retrans;
/* By default, enable heartbeat for peer address. */
peer->hb_allowed = 1;
@@ -511,7 +511,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
peer->hb_interval = msecs_to_jiffies(sp->paddrparam.spp_hbinterval);
/* Set the path max_retrans. */
- peer->max_retrans = asoc->max_retrans;
+ peer->max_retrans = sp->paddrparam.spp_pathmaxrxt;
/* Set the transport's RTO.initial value */
peer->rto = asoc->rto_initial;
@@ -714,18 +714,6 @@ __u32 sctp_association_get_next_tsn(struct sctp_association *asoc)
return retval;
}
-/* Allocate 'num' TSNs by incrementing the association's TSN by num. */
-__u32 sctp_association_get_tsn_block(struct sctp_association *asoc, int num)
-{
- __u32 retval = asoc->next_tsn;
-
- asoc->next_tsn += num;
- asoc->unack_data += num;
-
- return retval;
-}
-
-
/* Compare two addresses to see if they match. Wildcard addresses
* only match themselves.
*/
@@ -760,14 +748,6 @@ struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc)
return chunk;
}
-/* Use this function for the packet prepend callback when no ECNE
- * packet is desired (e.g. some packets don't like to be bundled).
- */
-struct sctp_chunk *sctp_get_no_prepend(struct sctp_association *asoc)
-{
- return NULL;
-}
-
/*
* Find which transport this TSN was sent on.
*/
@@ -861,7 +841,8 @@ static void sctp_assoc_bh_rcv(struct sctp_association *asoc)
struct sctp_chunk *chunk;
struct sock *sk;
struct sctp_inq *inqueue;
- int state, subtype;
+ int state;
+ sctp_subtype_t subtype;
int error = 0;
/* The association should be held so we should be safe. */
@@ -872,7 +853,7 @@ static void sctp_assoc_bh_rcv(struct sctp_association *asoc)
sctp_association_hold(asoc);
while (NULL != (chunk = sctp_inq_pop(inqueue))) {
state = asoc->state;
- subtype = chunk->chunk_hdr->type;
+ subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
/* Remember where the last DATA chunk came from so we
* know where to send the SACK.
@@ -886,7 +867,7 @@ static void sctp_assoc_bh_rcv(struct sctp_association *asoc)
chunk->transport->last_time_heard = jiffies;
/* Run through the state machine. */
- error = sctp_do_sm(SCTP_EVENT_T_CHUNK, SCTP_ST_CHUNK(subtype),
+ error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype,
state, ep, asoc, chunk, GFP_ATOMIC);
/* Check to see if the association is freed in response to
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index b484b4afd730..ec2d7450fb18 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -104,23 +104,6 @@ out:
return error;
}
-/* Create a new SCTP_bind_addr from nothing. */
-struct sctp_bind_addr *sctp_bind_addr_new(int gfp)
-{
- struct sctp_bind_addr *retval;
-
- retval = t_new(struct sctp_bind_addr, gfp);
- if (!retval)
- goto nomem;
-
- sctp_bind_addr_init(retval, 0);
- retval->malloced = 1;
- SCTP_DBG_OBJCNT_INC(bind_addr);
-
-nomem:
- return retval;
-}
-
/* Initialize the SCTP_bind_addr structure for either an endpoint or
* an association.
*/
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index cdcd427e4bac..6e500f8ca47f 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -51,7 +51,7 @@
*/
/* Initialize datamsg from memory. */
-void sctp_datamsg_init(struct sctp_datamsg *msg)
+static void sctp_datamsg_init(struct sctp_datamsg *msg)
{
atomic_set(&msg->refcnt, 1);
msg->send_failed = 0;
@@ -62,7 +62,7 @@ void sctp_datamsg_init(struct sctp_datamsg *msg)
}
/* Allocate and initialize datamsg. */
-struct sctp_datamsg *sctp_datamsg_new(int gfp)
+SCTP_STATIC struct sctp_datamsg *sctp_datamsg_new(int gfp)
{
struct sctp_datamsg *msg;
msg = kmalloc(sizeof(struct sctp_datamsg), gfp);
@@ -124,7 +124,7 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
}
/* Hold a reference. */
-void sctp_datamsg_hold(struct sctp_datamsg *msg)
+static void sctp_datamsg_hold(struct sctp_datamsg *msg)
{
atomic_inc(&msg->refcnt);
}
@@ -151,7 +151,7 @@ void sctp_datamsg_track(struct sctp_chunk *chunk)
}
/* Assign a chunk to this datamsg. */
-void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chunk)
+static void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chunk)
{
sctp_datamsg_hold(msg);
chunk->msg = msg;
diff --git a/net/sctp/command.c b/net/sctp/command.c
index 637fadee95a8..3ff804757f4a 100644
--- a/net/sctp/command.c
+++ b/net/sctp/command.c
@@ -42,17 +42,6 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
-/* Create a new sctp_command_sequence. */
-sctp_cmd_seq_t *sctp_new_cmd_seq(int gfp)
-{
- sctp_cmd_seq_t *retval = t_new(sctp_cmd_seq_t, gfp);
-
- if (retval)
- sctp_init_cmd_seq(retval);
-
- return retval;
-}
-
/* Initialize a block of memory as a command sequence. */
int sctp_init_cmd_seq(sctp_cmd_seq_t *seq)
{
@@ -77,13 +66,6 @@ fail:
return 0;
}
-/* Rewind an sctp_cmd_seq_t to iterate from the start. */
-int sctp_rewind_sequence(sctp_cmd_seq_t *seq)
-{
- seq->next_cmd = 0;
- return 1; /* We always succeed. */
-}
-
/* Return the next command structure in a sctp_cmd_seq.
* Returns NULL at the end of the sequence.
*/
@@ -97,8 +79,3 @@ sctp_cmd_t *sctp_next_cmd(sctp_cmd_seq_t *seq)
return retval;
}
-/* Dispose of a command sequence. */
-void sctp_free_cmd_seq(sctp_cmd_seq_t *seq)
-{
- kfree(seq);
-}
diff --git a/net/sctp/debug.c b/net/sctp/debug.c
index bb1301a9defa..aa8340373af7 100644
--- a/net/sctp/debug.c
+++ b/net/sctp/debug.c
@@ -98,23 +98,6 @@ const char *sctp_cname(const sctp_subtype_t cid)
return "unknown chunk";
}
-/* These are printable form of variable-length parameters. */
-const char *sctp_param_tbl[SCTP_PARAM_ECN_CAPABLE + 1] = {
- "",
- "PARAM_HEARTBEAT_INFO",
- "",
- "",
- "",
- "PARAM_IPV4_ADDRESS",
- "PARAM_IPV6_ADDRESS",
- "PARAM_STATE_COOKIE",
- "PARAM_UNRECOGNIZED_PARAMETERS",
- "PARAM_COOKIE_PRESERVATIVE",
- "",
- "PARAM_HOST_NAME_ADDRESS",
- "PARAM_SUPPORTED_ADDRESS_TYPES",
-};
-
/* These are printable forms of the states. */
const char *sctp_state_tbl[SCTP_STATE_NUM_STATES] = {
"STATE_EMPTY",
@@ -171,6 +154,7 @@ const char *sctp_pname(const sctp_subtype_t id)
static const char *sctp_other_tbl[] = {
"NO_PENDING_TSN",
+ "ICMP_PROTO_UNREACH",
};
/* Lookup "other" debug name. */
@@ -178,7 +162,7 @@ const char *sctp_oname(const sctp_subtype_t id)
{
if (id.other < 0)
return "illegal 'other' event";
- if (id.other < SCTP_EVENT_OTHER_MAX)
+ if (id.other <= SCTP_EVENT_OTHER_MAX)
return sctp_other_tbl[id.other];
return "unknown 'other' event";
}
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index edc4291a67f4..cfeb033841dc 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -63,34 +63,11 @@
/* Forward declarations for internal helpers. */
static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep);
-/* Create a sctp_endpoint with all that boring stuff initialized.
- * Returns NULL if there isn't enough memory.
- */
-struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, int gfp)
-{
- struct sctp_endpoint *ep;
-
- /* Build a local endpoint. */
- ep = t_new(struct sctp_endpoint, gfp);
- if (!ep)
- goto fail;
- if (!sctp_endpoint_init(ep, sk, gfp))
- goto fail_init;
- ep->base.malloced = 1;
- SCTP_DBG_OBJCNT_INC(ep);
- return ep;
-
-fail_init:
- kfree(ep);
-fail:
- return NULL;
-}
-
/*
* Initialize the base fields of the endpoint structure.
*/
-struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
- struct sock *sk, int gfp)
+static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
+ struct sock *sk, int gfp)
{
struct sctp_opt *sp = sctp_sk(sk);
memset(ep, 0, sizeof(struct sctp_endpoint));
@@ -160,6 +137,29 @@ struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
return ep;
}
+/* Create a sctp_endpoint with all that boring stuff initialized.
+ * Returns NULL if there isn't enough memory.
+ */
+struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, int gfp)
+{
+ struct sctp_endpoint *ep;
+
+ /* Build a local endpoint. */
+ ep = t_new(struct sctp_endpoint, gfp);
+ if (!ep)
+ goto fail;
+ if (!sctp_endpoint_init(ep, sk, gfp))
+ goto fail_init;
+ ep->base.malloced = 1;
+ SCTP_DBG_OBJCNT_INC(ep);
+ return ep;
+
+fail_init:
+ kfree(ep);
+fail:
+ return NULL;
+}
+
/* Add an association to an endpoint. */
void sctp_endpoint_add_asoc(struct sctp_endpoint *ep,
struct sctp_association *asoc)
@@ -184,7 +184,7 @@ void sctp_endpoint_free(struct sctp_endpoint *ep)
}
/* Final destructor for endpoint. */
-void sctp_endpoint_destroy(struct sctp_endpoint *ep)
+static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
{
SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);
@@ -257,7 +257,7 @@ out:
* We do a linear search of the associations for this endpoint.
* We return the matching transport address too.
*/
-struct sctp_association *__sctp_endpoint_lookup_assoc(
+static struct sctp_association *__sctp_endpoint_lookup_assoc(
const struct sctp_endpoint *ep,
const union sctp_addr *paddr,
struct sctp_transport **transport)
@@ -345,7 +345,7 @@ static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep)
sk = ep->base.sk;
while (NULL != (chunk = sctp_inq_pop(inqueue))) {
- subtype.chunk = chunk->chunk_hdr->type;
+ subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
/* We might have grown an association since last we
* looked, so try again.
diff --git a/net/sctp/input.c b/net/sctp/input.c
index cab833371a54..688e714f909f 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -63,11 +63,15 @@
/* Forward declarations for internal helpers. */
static int sctp_rcv_ootb(struct sk_buff *);
-struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
const union sctp_addr *laddr,
const union sctp_addr *paddr,
struct sctp_transport **transportp);
-struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr);
+static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr);
+static struct sctp_association *__sctp_lookup_association(
+ const union sctp_addr *local,
+ const union sctp_addr *peer,
+ struct sctp_transport **pt);
/* Calculate the SCTP checksum of an SCTP packet. */
@@ -130,6 +134,10 @@ int sctp_rcv(struct sk_buff *skb)
skb_pull(skb, sizeof(struct sctphdr));
+ /* Make sure we at least have chunk headers worth of data left. */
+ if (skb->len < sizeof(struct sctp_chunkhdr))
+ goto discard_it;
+
family = ipver2af(skb->nh.iph->version);
af = sctp_get_af_specific(family);
if (unlikely(!af))
@@ -284,6 +292,31 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
}
}
+/*
+ * SCTP Implementer's Guide, 2.37 ICMP handling procedures
+ *
+ * ICMP8) If the ICMP code is a "Unrecognized next header type encountered"
+ * or a "Protocol Unreachable" treat this message as an abort
+ * with the T bit set.
+ *
+ * This function sends an event to the state machine, which will abort the
+ * association.
+ *
+ */
+void sctp_icmp_proto_unreachable(struct sock *sk,
+ struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ struct sctp_transport *t)
+{
+ SCTP_DEBUG_PRINTK("%s\n", __FUNCTION__);
+
+ sctp_do_sm(SCTP_EVENT_T_OTHER,
+ SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
+ asoc->state, asoc->ep, asoc, NULL,
+ GFP_ATOMIC);
+
+}
+
/* Common lookup code for icmp/icmpv6 error handler. */
struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
struct sctphdr *sctphdr,
@@ -326,11 +359,12 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
}
if (asoc) {
+ sk = asoc->base.sk;
+
if (ntohl(sctphdr->vtag) != asoc->c.peer_vtag) {
ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
goto out;
}
- sk = asoc->base.sk;
} else
sk = ep->base.sk;
@@ -432,7 +466,13 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
sctp_icmp_frag_needed(sk, asoc, transport, info);
goto out_unlock;
}
-
+ else {
+ if (ICMP_PROT_UNREACH == code) {
+ sctp_icmp_proto_unreachable(sk, ep, asoc,
+ transport);
+ goto out_unlock;
+ }
+ }
err = icmp_err_convert[code].errno;
break;
case ICMP_TIME_EXCEEDED:
@@ -479,10 +519,10 @@ int sctp_rcv_ootb(struct sk_buff *skb)
sctp_errhdr_t *err;
ch = (sctp_chunkhdr_t *) skb->data;
+ ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
/* Scan through all the chunks in the packet. */
- do {
- ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
+ while (ch_end > (__u8 *)ch && ch_end < skb->tail) {
/* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the
* receiver MUST silently discard the OOTB packet and take no
@@ -513,7 +553,8 @@ int sctp_rcv_ootb(struct sk_buff *skb)
}
ch = (sctp_chunkhdr_t *) ch_end;
- } while (ch_end < skb->tail);
+ ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
+ }
return 0;
@@ -522,7 +563,7 @@ discard:
}
/* Insert endpoint into the hash table. */
-void __sctp_hash_endpoint(struct sctp_endpoint *ep)
+static void __sctp_hash_endpoint(struct sctp_endpoint *ep)
{
struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
@@ -552,7 +593,7 @@ void sctp_hash_endpoint(struct sctp_endpoint *ep)
}
/* Remove endpoint from the hash table. */
-void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
+static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
{
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
@@ -584,7 +625,7 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep)
}
/* Look up an endpoint. */
-struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
+static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
{
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
@@ -610,16 +651,8 @@ hit:
return ep;
}
-/* Add an association to the hash. Local BH-safe. */
-void sctp_hash_established(struct sctp_association *asoc)
-{
- sctp_local_bh_disable();
- __sctp_hash_established(asoc);
- sctp_local_bh_enable();
-}
-
/* Insert association into the hash table. */
-void __sctp_hash_established(struct sctp_association *asoc)
+static void __sctp_hash_established(struct sctp_association *asoc)
{
struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
@@ -642,16 +675,16 @@ void __sctp_hash_established(struct sctp_association *asoc)
sctp_write_unlock(&head->lock);
}
-/* Remove association from the hash table. Local BH-safe. */
-void sctp_unhash_established(struct sctp_association *asoc)
+/* Add an association to the hash. Local BH-safe. */
+void sctp_hash_established(struct sctp_association *asoc)
{
sctp_local_bh_disable();
- __sctp_unhash_established(asoc);
+ __sctp_hash_established(asoc);
sctp_local_bh_enable();
}
/* Remove association from the hash table. */
-void __sctp_unhash_established(struct sctp_association *asoc)
+static void __sctp_unhash_established(struct sctp_association *asoc)
{
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
@@ -675,8 +708,16 @@ void __sctp_unhash_established(struct sctp_association *asoc)
sctp_write_unlock(&head->lock);
}
+/* Remove association from the hash table. Local BH-safe. */
+void sctp_unhash_established(struct sctp_association *asoc)
+{
+ sctp_local_bh_disable();
+ __sctp_unhash_established(asoc);
+ sctp_local_bh_enable();
+}
+
/* Look up an association. */
-struct sctp_association *__sctp_lookup_association(
+static struct sctp_association *__sctp_lookup_association(
const union sctp_addr *local,
const union sctp_addr *peer,
struct sctp_transport **pt)
@@ -713,8 +754,9 @@ hit:
}
/* Look up an association. BH-safe. */
+SCTP_STATIC
struct sctp_association *sctp_lookup_association(const union sctp_addr *laddr,
- const union sctp_addr *paddr,
+ const union sctp_addr *paddr,
struct sctp_transport **transportp)
{
struct sctp_association *asoc;
@@ -784,6 +826,14 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
return NULL;
}
+ /* The code below will attempt to walk the chunk and extract
+ * parameter information. Before we do that, we need to verify
+ * that the chunk length doesn't cause overflow. Otherwise, we'll
+ * walk off the end.
+ */
+ if (WORD_ROUND(ntohs(ch->length)) > skb->len)
+ return NULL;
+
/*
* This code will NOT touch anything inside the chunk--it is
* strictly READ-ONLY.
@@ -821,7 +871,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
}
/* Lookup an association for an inbound skb. */
-struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
const union sctp_addr *paddr,
const union sctp_addr *laddr,
struct sctp_transport **transportp)
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index 2e83405b8be7..cedf4351556c 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -59,19 +59,6 @@ void sctp_inq_init(struct sctp_inq *queue)
queue->malloced = 0;
}
-/* Create an initialized sctp_inq. */
-struct sctp_inq *sctp_inq_new(void)
-{
- struct sctp_inq *retval;
-
- retval = t_new(struct sctp_inq, GFP_ATOMIC);
- if (retval) {
- sctp_inq_init(retval);
- retval->malloced = 1;
- }
- return retval;
-}
-
/* Release the memory associated with an SCTP inqueue. */
void sctp_inq_free(struct sctp_inq *queue)
{
@@ -157,14 +144,36 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
}
chunk->chunk_hdr = ch;
- chunk->chunk_end = ((__u8 *) ch)
- + WORD_ROUND(ntohs(ch->length));
+ chunk->chunk_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
+ /* In the unlikely case of an IP reassembly, the skb could be
+ * non-linear. If so, update chunk_end so that it doesn't go past
+ * the skb->tail.
+ */
+ if (unlikely(skb_is_nonlinear(chunk->skb))) {
+ if (chunk->chunk_end > chunk->skb->tail)
+ chunk->chunk_end = chunk->skb->tail;
+ }
skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t));
chunk->subh.v = NULL; /* Subheader is no longer valid. */
if (chunk->chunk_end < chunk->skb->tail) {
/* This is not a singleton */
chunk->singleton = 0;
+ } else if (chunk->chunk_end > chunk->skb->tail) {
+ /* RFC 2960, Section 6.10 Bundling
+ *
+ * Partial chunks MUST NOT be placed in an SCTP packet.
+ * If the receiver detects a partial chunk, it MUST drop
+ * the chunk.
+ *
+ * Since the end of the chunk is past the end of our buffer
+ * (which contains the whole packet, we can freely discard
+ * the whole packet.
+ */
+ sctp_chunk_free(chunk);
+ chunk = queue->in_progress = NULL;
+
+ return NULL;
} else {
/* We are at the end of the packet, so mark the chunk
* in case we need to send a SACK.
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index e142681824ca..f23de6bd5b52 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -84,8 +84,8 @@ static struct notifier_block sctp_inet6addr_notifier = {
};
/* ICMP error handler. */
-void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info)
+SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int type, int code, int offset, __u32 info)
{
struct inet6_dev *idev;
struct ipv6hdr *iph = (struct ipv6hdr *)skb->data;
@@ -122,6 +122,12 @@ void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
case ICMPV6_PKT_TOOBIG:
sctp_icmp_frag_needed(sk, asoc, transport, ntohl(info));
goto out_unlock;
+ case ICMPV6_PARAMPROB:
+ if (ICMPV6_UNK_NEXTHDR == code) {
+ sctp_icmp_proto_unreachable(sk, ep, asoc, transport);
+ goto out_unlock;
+ }
+ break;
default:
break;
}
@@ -188,9 +194,9 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
/* Returns the dst cache entry for the given source and destination ip
* addresses.
*/
-struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
- union sctp_addr *daddr,
- union sctp_addr *saddr)
+static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
+ union sctp_addr *daddr,
+ union sctp_addr *saddr)
{
struct dst_entry *dst;
struct flowi fl;
@@ -251,8 +257,10 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1,
/* Fills in the source address(saddr) based on the destination address(daddr)
* and asoc's bind address list.
*/
-void sctp_v6_get_saddr(struct sctp_association *asoc, struct dst_entry *dst,
- union sctp_addr *daddr, union sctp_addr *saddr)
+static void sctp_v6_get_saddr(struct sctp_association *asoc,
+ struct dst_entry *dst,
+ union sctp_addr *daddr,
+ union sctp_addr *saddr)
{
struct sctp_bind_addr *bp;
rwlock_t *addr_lock;
@@ -577,8 +585,8 @@ static sctp_scope_t sctp_v6_scope(union sctp_addr *addr)
}
/* Create and initialize a new sk for the socket to be returned by accept(). */
-struct sock *sctp_v6_create_accept_sk(struct sock *sk,
- struct sctp_association *asoc)
+static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
+ struct sctp_association *asoc)
{
struct inet_sock *inet = inet_sk(sk);
struct sock *newsk;
diff --git a/net/sctp/objcnt.c b/net/sctp/objcnt.c
index 23288c8d3d6e..0781e5d509fd 100644
--- a/net/sctp/objcnt.c
+++ b/net/sctp/objcnt.c
@@ -62,7 +62,7 @@ SCTP_DBG_OBJCNT(datamsg);
/* An array to make it easy to pretty print the debug information
* to the proc fs.
*/
-sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = {
+static sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = {
SCTP_DBG_OBJCNT_ENTRY(sock),
SCTP_DBG_OBJCNT_ENTRY(ep),
SCTP_DBG_OBJCNT_ENTRY(assoc),
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 36ddfb78d41e..1b2d4adc4ddb 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -190,19 +190,6 @@ static inline int sctp_cacc_skip(struct sctp_transport *primary,
return 0;
}
-/* Generate a new outqueue. */
-struct sctp_outq *sctp_outq_new(struct sctp_association *asoc)
-{
- struct sctp_outq *q;
-
- q = t_new(struct sctp_outq, GFP_KERNEL);
- if (q) {
- sctp_outq_init(asoc, q);
- q->malloced = 1;
- }
- return q;
-}
-
/* Initialize an existing sctp_outq. This does the boring stuff.
* You still need to define handlers if you really want to DO
* something with this structure...
@@ -362,7 +349,7 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
/* Insert a chunk into the sorted list based on the TSNs. The retransmit list
* and the abandoned list are in ascending order.
*/
-void sctp_insert_list(struct list_head *head, struct list_head *new)
+static void sctp_insert_list(struct list_head *head, struct list_head *new)
{
struct list_head *pos;
struct sctp_chunk *nchunk, *lchunk;
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 9c7d2e9d8cc2..e42fd8c2916b 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -39,7 +39,7 @@
#include <linux/init.h>
#include <net/sctp/sctp.h>
-struct snmp_mib sctp_snmp_list[] = {
+static struct snmp_mib sctp_snmp_list[] = {
SNMP_MIB_ITEM("SctpCurrEstab", SCTP_MIB_CURRESTAB),
SNMP_MIB_ITEM("SctpActiveEstabs", SCTP_MIB_ACTIVEESTABS),
SNMP_MIB_ITEM("SctpPassiveEstabs", SCTP_MIB_PASSIVEESTABS),
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index a8a3f3d37efc..817f14f97a4f 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -65,7 +65,7 @@ struct proc_dir_entry *proc_net_sctp;
DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics);
struct idr sctp_assocs_id;
-spinlock_t sctp_assocs_id_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(sctp_assocs_id_lock);
/* This is the global socket data structure used for responding to
* the Out-of-the-blue (OOTB) packets. A control sock will be created
@@ -95,7 +95,7 @@ struct sock *sctp_get_ctl_sock(void)
}
/* Set up the proc fs entry for the SCTP protocol. */
-__init int sctp_proc_init(void)
+static __init int sctp_proc_init(void)
{
if (!proc_net_sctp) {
struct proc_dir_entry *ent;
@@ -124,7 +124,7 @@ out_nomem:
* Note: Do not make this __exit as it is used in the init error
* path.
*/
-void sctp_proc_exit(void)
+static void sctp_proc_exit(void)
{
sctp_snmp_proc_exit();
sctp_eps_proc_exit();
@@ -428,9 +428,9 @@ static sctp_scope_t sctp_v4_scope(union sctp_addr *addr)
* addresses. If an association is passed, trys to get a dst entry with a
* source address that matches an address in the bind address list.
*/
-struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
- union sctp_addr *daddr,
- union sctp_addr *saddr)
+static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
+ union sctp_addr *daddr,
+ union sctp_addr *saddr)
{
struct rtable *rt;
struct flowi fl;
@@ -520,10 +520,10 @@ out:
/* For v4, the source address is cached in the route entry(dst). So no need
* to cache it separately and hence this is an empty routine.
*/
-void sctp_v4_get_saddr(struct sctp_association *asoc,
- struct dst_entry *dst,
- union sctp_addr *daddr,
- union sctp_addr *saddr)
+static void sctp_v4_get_saddr(struct sctp_association *asoc,
+ struct dst_entry *dst,
+ union sctp_addr *daddr,
+ union sctp_addr *saddr)
{
struct rtable *rt = (struct rtable *)dst;
@@ -547,8 +547,8 @@ static int sctp_v4_is_ce(const struct sk_buff *skb)
}
/* Create and initialize a new sk for the socket returned by accept(). */
-struct sock *sctp_v4_create_accept_sk(struct sock *sk,
- struct sctp_association *asoc)
+static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
+ struct sctp_association *asoc)
{
struct sock *newsk;
struct inet_sock *inet = inet_sk(sk);
@@ -639,7 +639,7 @@ int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
* Initialize the control inode/socket with a control endpoint data
* structure. This endpoint is reserved exclusively for the OOTB processing.
*/
-int sctp_ctl_sock_init(void)
+static int sctp_ctl_sock_init(void)
{
int err;
sa_family_t family;
@@ -808,7 +808,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
return ip_queue_xmit(skb, ipfragok);
}
-struct sctp_af sctp_ipv4_specific;
+static struct sctp_af sctp_ipv4_specific;
static struct sctp_pf sctp_pf_inet = {
.event_msgname = sctp_inet_event_msgname,
@@ -829,7 +829,7 @@ static struct notifier_block sctp_inetaddr_notifier = {
};
/* Socket operations. */
-struct proto_ops inet_seqpacket_ops = {
+static struct proto_ops inet_seqpacket_ops = {
.family = PF_INET,
.owner = THIS_MODULE,
.release = inet_release, /* Needs to be wrapped... */
@@ -878,7 +878,7 @@ static struct net_protocol sctp_protocol = {
};
/* IPv4 address related functions. */
-struct sctp_af sctp_ipv4_specific = {
+static struct sctp_af sctp_ipv4_specific = {
.sctp_xmit = sctp_v4_xmit,
.setsockopt = ip_setsockopt,
.getsockopt = ip_getsockopt,
@@ -959,7 +959,7 @@ static void cleanup_sctp_mibs(void)
}
/* Initialize the universe into something sensible. */
-__init int sctp_init(void)
+SCTP_STATIC __init int sctp_init(void)
{
int i;
int status = -EINVAL;
@@ -1196,7 +1196,7 @@ err_bucket_cachep:
}
/* Exit handler for the SCTP protocol. */
-__exit void sctp_exit(void)
+SCTP_STATIC __exit void sctp_exit(void)
{
/* BUG. This should probably do something useful like clean
* up all the remaining associations and all that memory.
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 1f0676d1ffbc..7a0c6fa4c33c 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -67,6 +67,19 @@
extern kmem_cache_t *sctp_chunk_cachep;
+SCTP_STATIC
+struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
+ __u8 type, __u8 flags, int paylen);
+static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const struct sctp_chunk *init_chunk,
+ int *cookie_len,
+ const __u8 *raw_addrs, int addrs_len);
+static int sctp_process_param(struct sctp_association *asoc,
+ union sctp_params param,
+ const union sctp_addr *peer_addr,
+ int gfp);
+
/* What was the inbound interface for this chunk? */
int sctp_chunk_iif(const struct sctp_chunk *chunk)
{
@@ -559,52 +572,6 @@ nodata:
return retval;
}
-/* Make a DATA chunk for the given association. Populate the data
- * payload.
- */
-struct sctp_chunk *sctp_make_datafrag(struct sctp_association *asoc,
- const struct sctp_sndrcvinfo *sinfo,
- int data_len, const __u8 *data,
- __u8 flags, __u16 ssn)
-{
- struct sctp_chunk *retval;
-
- retval = sctp_make_datafrag_empty(asoc, sinfo, data_len, flags, ssn);
- if (retval)
- sctp_addto_chunk(retval, data_len, data);
-
- return retval;
-}
-
-/* Make a DATA chunk for the given association to ride on stream id
- * 'stream', with a payload id of 'payload', and a body of 'data'.
- */
-struct sctp_chunk *sctp_make_data(struct sctp_association *asoc,
- const struct sctp_sndrcvinfo *sinfo,
- int data_len, const __u8 *data)
-{
- struct sctp_chunk *retval = NULL;
-
- retval = sctp_make_data_empty(asoc, sinfo, data_len);
- if (retval)
- sctp_addto_chunk(retval, data_len, data);
- return retval;
-}
-
-/* Make a DATA chunk for the given association to ride on stream id
- * 'stream', with a payload id of 'payload', and a body big enough to
- * hold 'data_len' octets of data. We use this version when we need
- * to build the message AFTER allocating memory.
- */
-struct sctp_chunk *sctp_make_data_empty(struct sctp_association *asoc,
- const struct sctp_sndrcvinfo *sinfo,
- int data_len)
-{
- __u8 flags = SCTP_DATA_NOT_FRAG;
-
- return sctp_make_datafrag_empty(asoc, sinfo, data_len, flags, 0);
-}
-
/* Create a selective ackowledgement (SACK) for the given
* association. This reports on which TSN's we've seen to date,
* including duplicates and gaps.
@@ -881,6 +848,31 @@ err_chunk:
return retval;
}
+/* Make an ABORT chunk with a PROTOCOL VIOLATION cause code. */
+struct sctp_chunk *sctp_make_abort_violation(
+ const struct sctp_association *asoc,
+ const struct sctp_chunk *chunk,
+ const __u8 *payload,
+ const size_t paylen)
+{
+ struct sctp_chunk *retval;
+ struct sctp_paramhdr phdr;
+
+ retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen
+ + sizeof(sctp_chunkhdr_t));
+ if (!retval)
+ goto end;
+
+ sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, payload, paylen);
+
+ phdr.type = htons(chunk->chunk_hdr->type);
+ phdr.length = chunk->chunk_hdr->length;
+ sctp_addto_chunk(retval, sizeof(sctp_paramhdr_t), &phdr);
+
+end:
+ return retval;
+}
+
/* Make a HEARTBEAT chunk. */
struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc,
const struct sctp_transport *transport,
@@ -933,7 +925,7 @@ nodata:
/* Create an Operation Error chunk with the specified space reserved.
* This routine can be used for containing multiple causes in the chunk.
*/
-struct sctp_chunk *sctp_make_op_error_space(
+static struct sctp_chunk *sctp_make_op_error_space(
const struct sctp_association *asoc,
const struct sctp_chunk *chunk,
size_t size)
@@ -1034,7 +1026,6 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
SCTP_DBG_OBJCNT_INC(chunk);
atomic_set(&retval->refcnt, 1);
-
nodata:
return retval;
}
@@ -1062,6 +1053,7 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk)
/* Create a new chunk, setting the type and flags headers from the
* arguments, reserving enough space for a 'paylen' byte payload.
*/
+SCTP_STATIC
struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
__u8 type, __u8 flags, int paylen)
{
@@ -1261,7 +1253,7 @@ fail:
/* Build a cookie representing asoc.
* This INCLUDES the param header needed to put the cookie in the INIT ACK.
*/
-sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
+static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const struct sctp_chunk *init_chunk,
int *cookie_len,
@@ -1409,6 +1401,24 @@ struct sctp_association *sctp_unpack_cookie(
}
no_hmac:
+ /* IG Section 2.35.2:
+ * 3) Compare the port numbers and the verification tag contained
+ * within the COOKIE ECHO chunk to the actual port numbers and the
+ * verification tag within the SCTP common header of the received
+ * packet. If these values do not match the packet MUST be silently
+ * discarded,
+ */
+ if (ntohl(chunk->sctp_hdr->vtag) != bear_cookie->my_vtag) {
+ *error = -SCTP_IERROR_BAD_TAG;
+ goto fail;
+ }
+
+ if (ntohs(chunk->sctp_hdr->source) != bear_cookie->peer_addr.v4.sin_port ||
+ ntohs(chunk->sctp_hdr->dest) != bear_cookie->my_port) {
+ *error = -SCTP_IERROR_BAD_PORTS;
+ goto fail;
+ }
+
/* Check to see if the cookie is stale. If there is already
* an association, there is no need to check cookie's expiration
* for init collision case of lost COOKIE ACK.
@@ -1547,6 +1557,30 @@ static int sctp_process_inv_mandatory(const struct sctp_association *asoc,
return 0;
}
+static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
+ struct sctp_paramhdr *param,
+ const struct sctp_chunk *chunk,
+ struct sctp_chunk **errp)
+{
+ char error[] = "The following parameter had invalid length:";
+ size_t payload_len = WORD_ROUND(sizeof(error)) +
+ sizeof(sctp_paramhdr_t);
+
+
+ /* Create an error chunk and fill it in with our payload. */
+ if (!*errp)
+ *errp = sctp_make_op_error_space(asoc, chunk, payload_len);
+
+ if (*errp) {
+ sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, error,
+ sizeof(error));
+ sctp_addto_chunk(*errp, sizeof(sctp_paramhdr_t), param);
+ }
+
+ return 0;
+}
+
+
/* Do not attempt to handle the HOST_NAME parm. However, do
* send back an indicator to the peer.
*/
@@ -1725,6 +1759,18 @@ int sctp_verify_init(const struct sctp_association *asoc,
} /* for (loop through all parameters) */
+ /* There is a possibility that a parameter length was bad and
+ * in that case we would have stoped walking the parameters.
+ * The current param.p would point at the bad one.
+ * Current consensus on the mailing list is to generate a PROTOCOL
+ * VIOLATION error. We build the ERROR chunk here and let the normal
+ * error handling code build and send the packet.
+ */
+ if (param.v < (void*)chunk->chunk_end - sizeof(sctp_paramhdr_t)) {
+ sctp_process_inv_paramlength(asoc, param.p, chunk, errp);
+ return 0;
+ }
+
/* The only missing mandatory param possible today is
* the state cookie for an INIT-ACK chunk.
*/
@@ -1912,8 +1958,10 @@ nomem:
* work we do. In particular, we should not build transport
* structures for the addresses.
*/
-int sctp_process_param(struct sctp_association *asoc, union sctp_params param,
- const union sctp_addr *peer_addr, int gfp)
+static int sctp_process_param(struct sctp_association *asoc,
+ union sctp_params param,
+ const union sctp_addr *peer_addr,
+ int gfp)
{
union sctp_addr addr;
int i;
@@ -2078,8 +2126,9 @@ __u32 sctp_generate_tsn(const struct sctp_endpoint *ep)
*
* Address Parameter and other parameter will not be wrapped in this function
*/
-struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
- union sctp_addr *addr, int vparam_len)
+static struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
+ union sctp_addr *addr,
+ int vparam_len)
{
sctp_addiphdr_t asconf;
struct sctp_chunk *retval;
@@ -2248,8 +2297,8 @@ struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
*
* Create an ASCONF_ACK chunk with enough space for the parameter responses.
*/
-struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *asoc,
- __u32 serial, int vparam_len)
+static struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *asoc,
+ __u32 serial, int vparam_len)
{
sctp_addiphdr_t asconf;
struct sctp_chunk *retval;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index c9705de466bc..f65fa441952f 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -55,6 +55,24 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
+static int sctp_cmd_interpreter(sctp_event_t event_type,
+ sctp_subtype_t subtype,
+ sctp_state_t state,
+ struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ void *event_arg,
+ sctp_disposition_t status,
+ sctp_cmd_seq_t *commands,
+ int gfp);
+static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
+ sctp_state_t state,
+ struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ void *event_arg,
+ sctp_disposition_t status,
+ sctp_cmd_seq_t *commands,
+ int gfp);
+
/********************************************************************
* Helper functions
********************************************************************/
@@ -134,8 +152,8 @@ static void sctp_do_ecn_cwr_work(struct sctp_association *asoc,
}
/* Generate SACK if necessary. We call this at the end of a packet. */
-int sctp_gen_sack(struct sctp_association *asoc, int force,
- sctp_cmd_seq_t *commands)
+static int sctp_gen_sack(struct sctp_association *asoc, int force,
+ sctp_cmd_seq_t *commands)
{
__u32 ctsn, max_tsn_seen;
struct sctp_chunk *sack;
@@ -276,31 +294,31 @@ out_unlock:
sctp_association_put(asoc);
}
-void sctp_generate_t1_cookie_event(unsigned long data)
+static void sctp_generate_t1_cookie_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *) data;
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T1_COOKIE);
}
-void sctp_generate_t1_init_event(unsigned long data)
+static void sctp_generate_t1_init_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *) data;
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T1_INIT);
}
-void sctp_generate_t2_shutdown_event(unsigned long data)
+static void sctp_generate_t2_shutdown_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *) data;
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T2_SHUTDOWN);
}
-void sctp_generate_t4_rto_event(unsigned long data)
+static void sctp_generate_t4_rto_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *) data;
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T4_RTO);
}
-void sctp_generate_t5_shutdown_guard_event(unsigned long data)
+static void sctp_generate_t5_shutdown_guard_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *)data;
sctp_generate_timeout_event(asoc,
@@ -308,7 +326,7 @@ void sctp_generate_t5_shutdown_guard_event(unsigned long data)
} /* sctp_generate_t5_shutdown_guard_event() */
-void sctp_generate_autoclose_event(unsigned long data)
+static void sctp_generate_autoclose_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *) data;
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_AUTOCLOSE);
@@ -353,7 +371,7 @@ out_unlock:
}
/* Inject a SACK Timeout event into the state machine. */
-void sctp_generate_sack_event(unsigned long data)
+static void sctp_generate_sack_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *) data;
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_SACK);
@@ -397,7 +415,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
asoc->overall_error_count++;
if (transport->active &&
- (transport->error_count++ >= transport->error_threshold)) {
+ (transport->error_count++ >= transport->max_retrans)) {
SCTP_DEBUG_PRINTK("transport_strike: transport "
"IP:%d.%d.%d.%d failed.\n",
NIPQUAD(transport->ipaddr.v4.sin_addr));
@@ -857,14 +875,14 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
/*****************************************************************
* This the master state function side effect processing function.
*****************************************************************/
-int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
- sctp_state_t state,
- struct sctp_endpoint *ep,
- struct sctp_association *asoc,
- void *event_arg,
- sctp_disposition_t status,
- sctp_cmd_seq_t *commands,
- int gfp)
+static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
+ sctp_state_t state,
+ struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ void *event_arg,
+ sctp_disposition_t status,
+ sctp_cmd_seq_t *commands,
+ int gfp)
{
int error;
@@ -944,11 +962,15 @@ bail:
********************************************************************/
/* This is the side-effect interpreter. */
-int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
- sctp_state_t state, struct sctp_endpoint *ep,
- struct sctp_association *asoc, void *event_arg,
- sctp_disposition_t status, sctp_cmd_seq_t *commands,
- int gfp)
+static int sctp_cmd_interpreter(sctp_event_t event_type,
+ sctp_subtype_t subtype,
+ sctp_state_t state,
+ struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ void *event_arg,
+ sctp_disposition_t status,
+ sctp_cmd_seq_t *commands,
+ int gfp)
{
int error = 0;
int force;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 7871faa08378..9b1b95939b62 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -65,6 +65,53 @@
#include <net/sctp/sm.h>
#include <net/sctp/structs.h>
+static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ struct sctp_chunk *chunk,
+ const void *payload,
+ size_t paylen);
+static int sctp_eat_data(const struct sctp_association *asoc,
+ struct sctp_chunk *chunk,
+ sctp_cmd_seq_t *commands);
+static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
+ const struct sctp_chunk *chunk);
+static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const struct sctp_chunk *chunk,
+ sctp_cmd_seq_t *commands,
+ struct sctp_chunk *err_chunk);
+static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands);
+static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands);
+static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk);
+
+
+/* Small helper function that checks if the chunk length
+ * is of the appropriate length. The 'required_length' argument
+ * is set to be the size of a specific chunk we are testing.
+ * Return Values: 1 = Valid length
+ * 0 = Invalid length
+ *
+ */
+static inline int
+sctp_chunk_length_valid(struct sctp_chunk *chunk,
+ __u16 required_length)
+{
+ __u16 chunk_length = ntohs(chunk->chunk_hdr->length);
+
+ if (unlikely(chunk_length < required_length))
+ return 0;
+
+ return 1;
+}
+
/**********************************************************
* These are the state functions for handling chunk events.
**********************************************************/
@@ -199,9 +246,14 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
+ *
+ * IG Section 2.11.2
+ * Furthermore, we require that the receiver of an INIT chunk MUST
+ * enforce these rules by silently discarding an arriving packet
+ * with an INIT chunk that is bundled with other chunks.
*/
if (!chunk->singleton)
- return SCTP_DISPOSITION_VIOLATION;
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
/* If the packet is an OOTB packet which is temporarily on the
* control endpoint, respond with an ABORT.
@@ -225,6 +277,14 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
if (chunk->sctp_hdr->vtag != 0)
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+ /* Make sure that the INIT chunk has a valid length.
+ * Normally, this would cause an ABORT with a Protocol Violation
+ * error, but since we don't have an association, we'll
+ * just discard the packet.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_init_chunk_t)))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
/* Verify the INIT chunk before processing it. */
err_chunk = NULL;
if (!sctp_verify_init(asoc, chunk->chunk_hdr->type,
@@ -376,6 +436,13 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
struct sctp_packet *packet;
sctp_disposition_t ret;
+ if (!sctp_vtag_verify(chunk, asoc))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
+ /* Make sure that the INIT-ACK chunk has a valid length */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_initack_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
@@ -383,9 +450,6 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
if (!chunk->singleton)
return SCTP_DISPOSITION_VIOLATION;
- if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
-
/* Grab the INIT header. */
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
@@ -542,6 +606,14 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
return sctp_sf_ootb(ep, asoc, type, arg, commands);
+ /* Make sure that the COOKIE_ECHO chunk has a valid length.
+ * In this case, we check that we have enough for at least a
+ * chunk header. More detailed verification is done
+ * in sctp_unpack_cookie().
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
/* "Decode" the chunk. We have no optional parameters so we
* are in good shape.
*/
@@ -687,6 +759,13 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ /* Verify that the chunk length for the COOKIE-ACK is OK.
+ * If we don't do this, any bundled chunks may be junked.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
/* Reset init error count upon receipt of COOKIE-ACK,
* to avoid problems with the managemement of this
* counter in stale cookie situations when a transition back
@@ -748,11 +827,11 @@ nomem:
}
/* Generate and sendout a heartbeat packet. */
-sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep,
- const struct sctp_association *asoc,
- const sctp_subtype_t type,
- void *arg,
- sctp_cmd_seq_t *commands)
+static sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands)
{
struct sctp_transport *transport = (struct sctp_transport *) arg;
struct sctp_chunk *reply;
@@ -859,6 +938,11 @@ sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ /* Make sure that the HEARTBEAT chunk has a valid length. */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_heartbeat_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
/* 8.3 The receiver of the HEARTBEAT should immediately
* respond with a HEARTBEAT ACK that contains the Heartbeat
* Information field copied from the received HEARTBEAT chunk.
@@ -922,6 +1006,11 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ /* Make sure that the HEARTBEAT-ACK chunk has a valid length. */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_heartbeat_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
from_addr = hbinfo->daddr;
link = sctp_assoc_lookup_paddr(asoc, &from_addr);
@@ -1165,9 +1254,14 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
+ *
+ * IG Section 2.11.2
+ * Furthermore, we require that the receiver of an INIT chunk MUST
+ * enforce these rules by silently discarding an arriving packet
+ * with an INIT chunk that is bundled with other chunks.
*/
if (!chunk->singleton)
- return SCTP_DISPOSITION_VIOLATION;
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
* Tag.
@@ -1175,6 +1269,13 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
if (chunk->sctp_hdr->vtag != 0)
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+ /* Make sure that the INIT chunk has a valid length.
+ * In this case, we generate a protocol violation since we have
+ * an association established.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_init_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
/* Grab the INIT header. */
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
@@ -1718,6 +1819,15 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep,
char action;
struct sctp_chunk *err_chk_p;
+ /* Make sure that the chunk has a valid length from the protocol
+ * perspective. In this case check to make sure we have at least
+ * enough for the chunk header. Cookie length verification is
+ * done later.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
/* "Decode" the chunk. We have no optional parameters so we
* are in good shape.
*/
@@ -1815,6 +1925,19 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort(
if (!sctp_vtag_verify_either(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ /* Make sure that the ABORT chunk has a valid length.
+ * Since this is an ABORT chunk, we have to discard it
+ * because of the following text:
+ * RFC 2960, Section 3.3.7
+ * If an endpoint receives an ABORT with a format error or for an
+ * association that doesn't exist, it MUST silently discard it.
+ * Becasue the length is "invalid", we can't really discard just
+ * as we do not know its true length. So, to be safe, discard the
+ * packet.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
/* Stop the T5-shutdown guard timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
@@ -1838,6 +1961,19 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify_either(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ /* Make sure that the ABORT chunk has a valid length.
+ * Since this is an ABORT chunk, we have to discard it
+ * because of the following text:
+ * RFC 2960, Section 3.3.7
+ * If an endpoint receives an ABORT with a format error or for an
+ * association that doesn't exist, it MUST silently discard it.
+ * Becasue the length is "invalid", we can't really discard just
+ * as we do not know its true length. So, to be safe, discard the
+ * packet.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
/* Stop the T2-shutdown timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
@@ -1890,6 +2026,16 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep,
struct sctp_chunk *chunk = arg;
sctp_errhdr_t *err;
+ if (!sctp_vtag_verify(chunk, asoc))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
+ /* Make sure that the ERROR chunk has a valid length.
+ * The parameter walking depends on this as well.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_operr_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
/* Process the error here */
/* FUTURE FIXME: When PR-SCTP related and other optional
* parms are emitted, this will have to change to handle multiple
@@ -1900,6 +2046,12 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep,
return sctp_sf_do_5_2_6_stale(ep, asoc, type,
arg, commands);
}
+
+ /* It is possible to have malformed error causes, and that
+ * will cause us to end the walk early. However, since
+ * we are discarding the packet, there should be no adverse
+ * affects.
+ */
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
}
@@ -1928,11 +2080,11 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
- const struct sctp_association *asoc,
- const sctp_subtype_t type,
- void *arg,
- sctp_cmd_seq_t *commands)
+static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands)
{
struct sctp_chunk *chunk = arg;
time_t stale;
@@ -2064,12 +2216,24 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify_either(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
- /* Check that chunk header looks valid. */
+ /* Make sure that the ABORT chunk has a valid length.
+ * Since this is an ABORT chunk, we have to discard it
+ * because of the following text:
+ * RFC 2960, Section 3.3.7
+ * If an endpoint receives an ABORT with a format error or for an
+ * association that doesn't exist, it MUST silently discard it.
+ * Becasue the length is "invalid", we can't really discard just
+ * as we do not know its true length. So, to be safe, discard the
+ * packet.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
+ /* See if we have an error cause code in the chunk. */
len = ntohs(chunk->chunk_hdr->length);
if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
-
/* ASSOC_FAILED will DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -2096,27 +2260,43 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify_either(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
- sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
- SCTP_STATE(SCTP_STATE_CLOSED));
- SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
- sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
- SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+ /* Make sure that the ABORT chunk has a valid length.
+ * Since this is an ABORT chunk, we have to discard it
+ * because of the following text:
+ * RFC 2960, Section 3.3.7
+ * If an endpoint receives an ABORT with a format error or for an
+ * association that doesn't exist, it MUST silently discard it.
+ * Becasue the length is "invalid", we can't really discard just
+ * as we do not know its true length. So, to be safe, discard the
+ * packet.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
- /* Check that chunk header looks valid. */
+ /* See if we have an error cause code in the chunk. */
len = ntohs(chunk->chunk_hdr->length);
if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
- /* CMD_INIT_FAILED will DELETE_TCB. */
- sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_U32(error));
-
+ sctp_stop_t1_and_abort(commands, error);
return SCTP_DISPOSITION_ABORT;
}
/*
+ * Process an incoming ICMP as an ABORT. (COOKIE-WAIT state)
+ */
+sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands)
+{
+ sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR);
+ return SCTP_DISPOSITION_ABORT;
+}
+
+/*
* Process an ABORT. (COOKIE-ECHOED state)
- *
- * See sctp_sf_do_9_1_abort() above.
*/
sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
@@ -2131,6 +2311,23 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
}
/*
+ * Stop T1 timer and abort association with "INIT failed".
+ *
+ * This is common code called by several sctp_sf_*_abort() functions above.
+ */
+void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error)
+{
+ sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
+ SCTP_STATE(SCTP_STATE_CLOSED));
+ SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
+ sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
+ SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+ /* CMD_INIT_FAILED will DELETE_TCB. */
+ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
+ SCTP_U32(error));
+}
+
+/*
* sctp_sf_do_9_2_shut
*
* Section: 9.2
@@ -2174,14 +2371,20 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
sctp_disposition_t disposition;
struct sctp_ulpevent *ev;
+ if (!sctp_vtag_verify(chunk, asoc))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
+ /* Make sure that the SHUTDOWN chunk has a valid length. */
+ if (!sctp_chunk_length_valid(chunk,
+ sizeof(struct sctp_shutdown_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
/* Convert the elaborate header. */
sdh = (sctp_shutdownhdr_t *)chunk->skb->data;
skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t));
chunk->subh.shutdown_hdr = sdh;
- if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
-
/* Upon the reception of the SHUTDOWN, the peer endpoint shall
* - enter the SHUTDOWN-RECEIVED state,
* - stop accepting new data from its SCTP user
@@ -2238,6 +2441,10 @@ sctp_disposition_t sctp_sf_do_9_2_reshutack(const struct sctp_endpoint *ep,
struct sctp_chunk *chunk = (struct sctp_chunk *) arg;
struct sctp_chunk *reply;
+ /* Since we are not going to really process this INIT, there
+ * is no point in verifying chunk boundries. Just generate
+ * the SHUTDOWN ACK.
+ */
reply = sctp_make_shutdown_ack(asoc, chunk);
if (NULL == reply)
goto nomem;
@@ -2295,6 +2502,10 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_ecne_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
cwr = (sctp_cwrhdr_t *) chunk->skb->data;
skb_pull(chunk->skb, sizeof(sctp_cwrhdr_t));
@@ -2345,6 +2556,10 @@ sctp_disposition_t sctp_sf_do_ecne(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_ecne_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
ecne = (sctp_ecnehdr_t *) chunk->skb->data;
skb_pull(chunk->skb, sizeof(sctp_ecnehdr_t));
@@ -2400,6 +2615,10 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
}
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_data_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
error = sctp_eat_data(asoc, chunk, commands );
switch (error) {
case SCTP_IERROR_NO_ERROR:
@@ -2517,6 +2736,10 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep,
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
}
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_data_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
error = sctp_eat_data(asoc, chunk, commands );
switch (error) {
case SCTP_IERROR_NO_ERROR:
@@ -2598,6 +2821,11 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ /* Make sure that the SACK chunk has a valid length. */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_sack_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
/* Pull the SACK chunk from the data buffer */
sackh = sctp_sm_pull_sack(chunk);
/* Was this a bogus SACK? */
@@ -2700,6 +2928,14 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
struct sctp_chunk *chunk = arg;
struct sctp_ulpevent *ev;
+ if (!sctp_vtag_verify(chunk, asoc))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
+ /* Make sure that the ERROR chunk has a valid length. */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_operr_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
while (chunk->chunk_end > chunk->skb->data) {
ev = sctp_ulpevent_make_remote_error(asoc, chunk, 0,
GFP_ATOMIC);
@@ -2744,6 +2980,11 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ /* Make sure that the SHUTDOWN_ACK chunk has a valid length. */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
/* 10.2 H) SHUTDOWN COMPLETE notification
*
* When SCTP completes the shutdown procedures (section 9.2) this
@@ -2818,11 +3059,23 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
ch = (sctp_chunkhdr_t *) chunk->chunk_hdr;
do {
+ /* Break out if chunk length is less then minimal. */
+ if (ntohs(ch->length) < sizeof(sctp_chunkhdr_t))
+ break;
+
ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
if (SCTP_CID_SHUTDOWN_ACK == ch->type)
ootb_shut_ack = 1;
+ /* RFC 2960, Section 3.3.7
+ * Moreover, under any circumstances, an endpoint that
+ * receives an ABORT MUST NOT respond to that ABORT by
+ * sending an ABORT of its own.
+ */
+ if (SCTP_CID_ABORT == ch->type)
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
ch = (sctp_chunkhdr_t *) ch_end;
} while (ch_end < skb->tail);
@@ -2853,11 +3106,11 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
- const struct sctp_association *asoc,
- const sctp_subtype_t type,
- void *arg,
- sctp_cmd_seq_t *commands)
+static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands)
{
struct sctp_packet *packet = NULL;
struct sctp_chunk *chunk = arg;
@@ -2885,6 +3138,12 @@ sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+ /* If the chunk length is invalid, we don't want to process
+ * the reset of the packet.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
return SCTP_DISPOSITION_CONSUME;
}
@@ -2927,6 +3186,17 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
sctp_addiphdr_t *hdr;
__u32 serial;
+ if (!sctp_vtag_verify(chunk, asoc)) {
+ sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
+ SCTP_NULL());
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ }
+
+ /* Make sure that the ASCONF ADDIP chunk has a valid length. */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_addip_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
hdr = (sctp_addiphdr_t *)chunk->skb->data;
serial = ntohl(hdr->serial);
@@ -2947,7 +3217,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
/* ADDIP 4.2 C3) If the value found in the serial number is
* equal to the value stored in the 'Peer-Serial-Number'
* IMPLEMENTATION NOTE: As an optimization a receiver may wish
- * to save the last ASCONF-ACK for some predetermined period of * time and instead of re-processing the ASCONF (with the same
+ * to save the last ASCONF-ACK for some predetermined period of
+ * time and instead of re-processing the ASCONF (with the same
* serial number) it may just re-transmit the ASCONF-ACK.
*/
if (asoc->addip_last_asconf_ack)
@@ -2986,6 +3257,17 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
sctp_addiphdr_t *addip_hdr;
__u32 sent_serial, rcvd_serial;
+ if (!sctp_vtag_verify(asconf_ack, asoc)) {
+ sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
+ SCTP_NULL());
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ }
+
+ /* Make sure that the ADDIP chunk has a valid length. */
+ if (!sctp_chunk_length_valid(asconf_ack, sizeof(sctp_addip_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
addip_hdr = (sctp_addiphdr_t *)asconf_ack->skb->data;
rcvd_serial = ntohl(addip_hdr->serial);
@@ -3084,6 +3366,11 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep,
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
}
+ /* Make sure that the FORWARD_TSN chunk has valid length. */
+ if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_fwdtsn_chunk)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
fwdtsn_hdr = (struct sctp_fwdtsn_hdr *)chunk->skb->data;
chunk->subh.fwdtsn_hdr = fwdtsn_hdr;
len = ntohs(chunk->chunk_hdr->length);
@@ -3142,6 +3429,11 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast(
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
}
+ /* Make sure that the FORWARD_TSN chunk has a valid length. */
+ if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_fwdtsn_chunk)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
fwdtsn_hdr = (struct sctp_fwdtsn_hdr *)chunk->skb->data;
chunk->subh.fwdtsn_hdr = fwdtsn_hdr;
len = ntohs(chunk->chunk_hdr->length);
@@ -3216,6 +3508,14 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
if (!sctp_vtag_verify(unk_chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ /* Make sure that the chunk has a valid length.
+ * Since we don't know the chunk type, we use a general
+ * chunkhdr structure to make a comparison.
+ */
+ if (!sctp_chunk_length_valid(unk_chunk, sizeof(sctp_chunkhdr_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
switch (type.chunk & SCTP_CID_ACTION_MASK) {
case SCTP_CID_ACTION_DISCARD:
/* Discard the packet. */
@@ -3338,6 +3638,66 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep,
return SCTP_DISPOSITION_VIOLATION;
}
+
+/*
+ * Handle a protocol violation when the chunk length is invalid.
+ * "Invalid" length is identified as smaller then the minimal length a
+ * given chunk can be. For example, a SACK chunk has invalid length
+ * if it's length is set to be smaller then the size of sctp_sack_chunk_t.
+ *
+ * We inform the other end by sending an ABORT with a Protocol Violation
+ * error code.
+ *
+ * Section: Not specified
+ * Verification Tag: Nothing to do
+ * Inputs
+ * (endpoint, asoc, chunk)
+ *
+ * Outputs
+ * (reply_msg, msg_up, counters)
+ *
+ * Generate an ABORT chunk and terminate the association.
+ */
+sctp_disposition_t sctp_sf_violation_chunklen(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands)
+{
+ struct sctp_chunk *chunk = arg;
+ struct sctp_chunk *abort = NULL;
+ char err_str[]="The following chunk had invalid length:";
+
+ /* Make the abort chunk. */
+ abort = sctp_make_abort_violation(asoc, chunk, err_str,
+ sizeof(err_str));
+ if (!abort)
+ goto nomem;
+
+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
+ SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
+
+ if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) {
+ sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
+ SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
+ SCTP_U32(SCTP_ERROR_PROTO_VIOLATION));
+ } else {
+ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
+ SCTP_U32(SCTP_ERROR_PROTO_VIOLATION));
+ SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
+ }
+
+ sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
+
+ SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
+
+ return SCTP_DISPOSITION_ABORT;
+
+nomem:
+ return SCTP_DISPOSITION_NOMEM;
+}
+
/***************************************************************************
* These are the state functions for handling primitive (Section 10) events.
***************************************************************************/
@@ -4050,6 +4410,23 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown_ack(
struct sctp_chunk *chunk = (struct sctp_chunk *) arg;
struct sctp_chunk *reply;
+ /* There are 2 ways of getting here:
+ * 1) called in response to a SHUTDOWN chunk
+ * 2) called when SCTP_EVENT_NO_PENDING_TSN event is issued.
+ *
+ * For the case (2), the arg parameter is set to NULL. We need
+ * to check that we have a chunk before accessing it's fields.
+ */
+ if (chunk) {
+ if (!sctp_vtag_verify(chunk, asoc))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
+ /* Make sure that the SHUTDOWN chunk has a valid length. */
+ if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_shutdown_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+ }
+
/* If it has no more outstanding DATA chunks, the SHUTDOWN receiver
* shall send a SHUTDOWN ACK ...
*/
@@ -4537,7 +4914,7 @@ sctp_disposition_t sctp_sf_timer_ignore(const struct sctp_endpoint *ep,
********************************************************************/
/* Pull the SACK chunk based on the SACK header. */
-struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk)
+static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk)
{
struct sctp_sackhdr *sack;
unsigned int len;
@@ -4564,7 +4941,7 @@ struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk)
/* Create an ABORT packet to be sent as a response, with the specified
* error causes.
*/
-struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
+static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
struct sctp_chunk *chunk,
const void *payload,
@@ -4600,8 +4977,8 @@ struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
}
/* Allocate a packet for responding in the OOTB conditions. */
-struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
- const struct sctp_chunk *chunk)
+static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
+ const struct sctp_chunk *chunk)
{
struct sctp_packet *packet;
struct sctp_transport *transport;
@@ -4664,11 +5041,11 @@ void sctp_ootb_pkt_free(struct sctp_packet *packet)
}
/* Send a stale cookie error when a invalid COOKIE ECHO chunk is found */
-void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
- const struct sctp_association *asoc,
- const struct sctp_chunk *chunk,
- sctp_cmd_seq_t *commands,
- struct sctp_chunk *err_chunk)
+static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const struct sctp_chunk *chunk,
+ sctp_cmd_seq_t *commands,
+ struct sctp_chunk *err_chunk)
{
struct sctp_packet *packet;
@@ -4694,9 +5071,9 @@ void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
/* Process a data chunk */
-int sctp_eat_data(const struct sctp_association *asoc,
- struct sctp_chunk *chunk,
- sctp_cmd_seq_t *commands)
+static int sctp_eat_data(const struct sctp_association *asoc,
+ struct sctp_chunk *chunk,
+ sctp_cmd_seq_t *commands)
{
sctp_datahdr_t *data_hdr;
struct sctp_chunk *err;
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 516dc7914366..8967846f69e8 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -50,6 +50,17 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
+static const sctp_sm_table_entry_t
+primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES];
+static const sctp_sm_table_entry_t
+other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES];
+static const sctp_sm_table_entry_t
+timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES];
+
+static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
+ sctp_state_t state);
+
+
static const sctp_sm_table_entry_t bug = {
.fn = sctp_sf_bug,
.name = "sctp_sf_bug"
@@ -419,7 +430,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
*
* For base protocol (RFC 2960).
*/
-const sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
+static const sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_DATA,
TYPE_SCTP_INIT,
TYPE_SCTP_INIT_ACK,
@@ -482,7 +493,7 @@ const sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_ST
/* The primary index for this table is the chunk type.
* The secondary index for this table is the state.
*/
-const sctp_sm_table_entry_t addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
+static const sctp_sm_table_entry_t addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_ASCONF,
TYPE_SCTP_ASCONF_ACK,
}; /*state_fn_t addip_chunk_event_table[][] */
@@ -511,7 +522,7 @@ const sctp_sm_table_entry_t addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_TYPES][
/* The primary index for this table is the chunk type.
* The secondary index for this table is the state.
*/
-const sctp_sm_table_entry_t prsctp_chunk_event_table[SCTP_NUM_PRSCTP_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
+static const sctp_sm_table_entry_t prsctp_chunk_event_table[SCTP_NUM_PRSCTP_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_FWD_TSN,
}; /*state_fn_t prsctp_chunk_event_table[][] */
@@ -684,7 +695,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
/* The primary index for this table is the primitive type.
* The secondary index for this table is the state.
*/
-const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES] = {
+static const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_PRIMITIVE_ASSOCIATE,
TYPE_SCTP_PRIMITIVE_SHUTDOWN,
TYPE_SCTP_PRIMITIVE_ABORT,
@@ -716,8 +727,31 @@ const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
}
-const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES] = {
+#define TYPE_SCTP_OTHER_ICMP_PROTO_UNREACH { \
+ /* SCTP_STATE_EMPTY */ \
+ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ /* SCTP_STATE_CLOSED */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ /* SCTP_STATE_COOKIE_WAIT */ \
+ {.fn = sctp_sf_cookie_wait_icmp_abort, \
+ .name = "sctp_sf_cookie_wait_icmp_abort"}, \
+ /* SCTP_STATE_COOKIE_ECHOED */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ /* SCTP_STATE_ESTABLISHED */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ /* SCTP_STATE_SHUTDOWN_PENDING */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ /* SCTP_STATE_SHUTDOWN_SENT */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+}
+
+static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_OTHER_NO_PENDING_TSN,
+ TYPE_SCTP_OTHER_ICMP_PROTO_UNREACH,
};
#define TYPE_SCTP_EVENT_TIMEOUT_NONE { \
@@ -931,7 +965,7 @@ const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_N
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
}
-const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = {
+static const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_EVENT_TIMEOUT_NONE,
TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE,
TYPE_SCTP_EVENT_TIMEOUT_T1_INIT,
@@ -944,8 +978,8 @@ const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STA
TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE,
};
-const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
- sctp_state_t state)
+static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
+ sctp_state_t state)
{
if (state > SCTP_STATE_MAX)
return &bug;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index d9967aaefecf..30b921b90d00 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -208,7 +208,7 @@ struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id)
* id are specified, the associations matching the address and the id should be
* the same.
*/
-struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
+static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
struct sockaddr_storage *addr,
sctp_assoc_t id)
{
@@ -245,7 +245,7 @@ struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
* sockaddr_in6 [RFC 2553]),
* addr_len - the size of the address structure.
*/
-int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
int retval = 0;
@@ -343,8 +343,8 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
}
/* Refresh ephemeral port. */
- if (!snum)
- snum = inet_sk(sk)->num;
+ if (!bp->port)
+ bp->port = inet_sk(sk)->num;
/* Add the address to the bind address list. */
sctp_local_bh_disable();
@@ -354,8 +354,6 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
addr->v4.sin_port = ntohs(addr->v4.sin_port);
ret = sctp_add_bind_addr(bp, addr, GFP_ATOMIC);
addr->v4.sin_port = htons(addr->v4.sin_port);
- if (!ret && !bp->port)
- bp->port = snum;
sctp_write_unlock(&ep->base.addr_lock);
sctp_local_bh_enable();
@@ -1713,10 +1711,13 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
/* update default value for endpoint (all future associations) */
if (!params.spp_assoc_id &&
sctp_is_any(( union sctp_addr *)&params.spp_address)) {
- if (params.spp_hbinterval)
+ /* Manual heartbeat on an endpoint is invalid. */
+ if (0xffffffff == params.spp_hbinterval)
+ return -EINVAL;
+ else if (params.spp_hbinterval)
sctp_sk(sk)->paddrparam.spp_hbinterval =
params.spp_hbinterval;
- if (sctp_max_retrans_path)
+ if (params.spp_pathmaxrxt)
sctp_sk(sk)->paddrparam.spp_pathmaxrxt =
params.spp_pathmaxrxt;
return 0;
@@ -1758,7 +1759,8 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
/* spp_pathmaxrxt contains the maximum number of retransmissions
* before this address shall be considered unreachable.
*/
- trans->error_threshold = params.spp_pathmaxrxt;
+ if (params.spp_pathmaxrxt)
+ trans->max_retrans = params.spp_pathmaxrxt;
return 0;
}
@@ -2937,7 +2939,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
/* spp_pathmaxrxt contains the maximum number of retransmissions
* before this address shall be considered unreachable.
*/
- params.spp_pathmaxrxt = trans->error_threshold;
+ params.spp_pathmaxrxt = trans->max_retrans;
done:
if (copy_to_user(optval, &params, len))
@@ -3049,6 +3051,9 @@ static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len,
struct sctp_bind_addr *bp;
struct sctp_association *asoc;
struct list_head *pos;
+ struct sctp_sockaddr_entry *addr;
+ rwlock_t *addr_lock;
+ unsigned long flags;
int cnt = 0;
if (len != sizeof(sctp_assoc_t))
@@ -3065,33 +3070,104 @@ static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len,
*/
if (0 == id) {
bp = &sctp_sk(sk)->ep->base.bind_addr;
+ addr_lock = &sctp_sk(sk)->ep->base.addr_lock;
} else {
asoc = sctp_id2assoc(sk, id);
if (!asoc)
return -EINVAL;
bp = &asoc->base.bind_addr;
+ addr_lock = &asoc->base.addr_lock;
+ }
+
+ sctp_read_lock(addr_lock);
+
+ /* If the endpoint is bound to 0.0.0.0 or ::0, count the valid
+ * addresses from the global local address list.
+ */
+ if (sctp_list_single_entry(&bp->address_list)) {
+ addr = list_entry(bp->address_list.next,
+ struct sctp_sockaddr_entry, list);
+ if (sctp_is_any(&addr->a)) {
+ sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
+ list_for_each(pos, &sctp_local_addr_list) {
+ addr = list_entry(pos,
+ struct sctp_sockaddr_entry,
+ list);
+ if ((PF_INET == sk->sk_family) &&
+ (AF_INET6 == addr->a.sa.sa_family))
+ continue;
+ cnt++;
+ }
+ sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
+ flags);
+ } else {
+ cnt = 1;
+ }
+ goto done;
}
list_for_each(pos, &bp->address_list) {
cnt ++;
}
+done:
+ sctp_read_unlock(addr_lock);
+ return cnt;
+}
+
+/* Helper function that copies local addresses to user and returns the number
+ * of addresses copied.
+ */
+static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, int max_addrs,
+ void __user *to)
+{
+ struct list_head *pos;
+ struct sctp_sockaddr_entry *addr;
+ unsigned long flags;
+ union sctp_addr temp;
+ int cnt = 0;
+ int addrlen;
+
+ sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
+ list_for_each(pos, &sctp_local_addr_list) {
+ addr = list_entry(pos, struct sctp_sockaddr_entry, list);
+ if ((PF_INET == sk->sk_family) &&
+ (AF_INET6 == addr->a.sa.sa_family))
+ continue;
+ memcpy(&temp, &addr->a, sizeof(temp));
+ sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
+ &temp);
+ addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
+ temp.v4.sin_port = htons(port);
+ if (copy_to_user(to, &temp, addrlen)) {
+ sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
+ flags);
+ return -EFAULT;
+ }
+ to += addrlen;
+ cnt ++;
+ if (cnt >= max_addrs) break;
+ }
+ sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
+
return cnt;
}
static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
- char __user *optval, int __user *optlen)
+ char __user *optval, int __user *optlen)
{
struct sctp_bind_addr *bp;
struct sctp_association *asoc;
struct list_head *pos;
int cnt = 0;
struct sctp_getaddrs getaddrs;
- struct sctp_sockaddr_entry *from;
+ struct sctp_sockaddr_entry *addr;
void __user *to;
union sctp_addr temp;
struct sctp_opt *sp = sctp_sk(sk);
int addrlen;
+ rwlock_t *addr_lock;
+ int err = 0;
if (len != sizeof(struct sctp_getaddrs))
return -EINVAL;
@@ -3108,33 +3184,59 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
*/
if (0 == getaddrs.assoc_id) {
bp = &sctp_sk(sk)->ep->base.bind_addr;
+ addr_lock = &sctp_sk(sk)->ep->base.addr_lock;
} else {
asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
if (!asoc)
return -EINVAL;
bp = &asoc->base.bind_addr;
+ addr_lock = &asoc->base.addr_lock;
}
to = getaddrs.addrs;
+
+ sctp_read_lock(addr_lock);
+
+ /* If the endpoint is bound to 0.0.0.0 or ::0, get the valid
+ * addresses from the global local address list.
+ */
+ if (sctp_list_single_entry(&bp->address_list)) {
+ addr = list_entry(bp->address_list.next,
+ struct sctp_sockaddr_entry, list);
+ if (sctp_is_any(&addr->a)) {
+ cnt = sctp_copy_laddrs_to_user(sk, bp->port,
+ getaddrs.addr_num, to);
+ if (cnt < 0) {
+ err = cnt;
+ goto unlock;
+ }
+ goto copy_getaddrs;
+ }
+ }
+
list_for_each(pos, &bp->address_list) {
- from = list_entry(pos,
- struct sctp_sockaddr_entry,
- list);
- memcpy(&temp, &from->a, sizeof(temp));
+ addr = list_entry(pos, struct sctp_sockaddr_entry, list);
+ memcpy(&temp, &addr->a, sizeof(temp));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
temp.v4.sin_port = htons(temp.v4.sin_port);
- if (copy_to_user(to, &temp, addrlen))
- return -EFAULT;
+ if (copy_to_user(to, &temp, addrlen)) {
+ err = -EFAULT;
+ goto unlock;
+ }
to += addrlen;
cnt ++;
if (cnt >= getaddrs.addr_num) break;
}
+
+copy_getaddrs:
getaddrs.addr_num = cnt;
if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs)))
- return -EFAULT;
+ err = -EFAULT;
- return 0;
+unlock:
+ sctp_read_unlock(addr_lock);
+ return err;
}
/* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
diff --git a/net/sctp/ssnmap.c b/net/sctp/ssnmap.c
index 847ba4ca235f..e627d2b451b6 100644
--- a/net/sctp/ssnmap.c
+++ b/net/sctp/ssnmap.c
@@ -42,6 +42,9 @@
#define MAX_KMALLOC_SIZE 131072
+static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
+ __u16 out);
+
/* Storage size needed for map includes 2 headers and then the
* specific needs of in or out streams.
*/
@@ -87,8 +90,8 @@ fail:
/* Initialize a block of memory as a ssnmap. */
-struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
- __u16 out)
+static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
+ __u16 out)
{
memset(map, 0x00, sctp_ssnmap_size(in, out));
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index c4a2370beb12..3fcca5ec314b 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -54,34 +54,10 @@
/* 1st Level Abstractions. */
-/* Allocate and initialize a new transport. */
-struct sctp_transport *sctp_transport_new(const union sctp_addr *addr, int gfp)
-{
- struct sctp_transport *transport;
-
- transport = t_new(struct sctp_transport, gfp);
- if (!transport)
- goto fail;
-
- if (!sctp_transport_init(transport, addr, gfp))
- goto fail_init;
-
- transport->malloced = 1;
- SCTP_DBG_OBJCNT_INC(transport);
-
- return transport;
-
-fail_init:
- kfree(transport);
-
-fail:
- return NULL;
-}
-
/* Initialize a new transport from provided memory. */
-struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
- const union sctp_addr *addr,
- int gfp)
+static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
+ const union sctp_addr *addr,
+ int gfp)
{
/* Copy in the address. */
peer->ipaddr = *addr;
@@ -112,7 +88,6 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
/* Initialize the default path max_retrans. */
peer->max_retrans = sctp_max_retrans_path;
- peer->error_threshold = 0;
peer->error_count = 0;
INIT_LIST_HEAD(&peer->transmitted);
@@ -144,6 +119,30 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
return peer;
}
+/* Allocate and initialize a new transport. */
+struct sctp_transport *sctp_transport_new(const union sctp_addr *addr, int gfp)
+{
+ struct sctp_transport *transport;
+
+ transport = t_new(struct sctp_transport, gfp);
+ if (!transport)
+ goto fail;
+
+ if (!sctp_transport_init(transport, addr, gfp))
+ goto fail_init;
+
+ transport->malloced = 1;
+ SCTP_DBG_OBJCNT_INC(transport);
+
+ return transport;
+
+fail_init:
+ kfree(transport);
+
+fail:
+ return NULL;
+}
+
/* This transport is no longer needed. Free up if possible, or
* delay until it last reference count.
*/
@@ -155,13 +154,23 @@ void sctp_transport_free(struct sctp_transport *transport)
if (del_timer(&transport->hb_timer))
sctp_transport_put(transport);
+ /* Delete the T3_rtx timer if it's active.
+ * There is no point in not doing this now and letting
+ * structure hang around in memory since we know
+ * the tranport is going away.
+ */
+ if (timer_pending(&transport->T3_rtx_timer) &&
+ del_timer(&transport->T3_rtx_timer))
+ sctp_transport_put(transport);
+
+
sctp_transport_put(transport);
}
/* Destroy the transport data structure.
* Assumes there are no more users of this structure.
*/
-void sctp_transport_destroy(struct sctp_transport *transport)
+static void sctp_transport_destroy(struct sctp_transport *transport)
{
SCTP_ASSERT(transport->dead, "Transport is not dead", return);
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c
index b1e334cde61f..ac4fae161bc7 100644
--- a/net/sctp/tsnmap.c
+++ b/net/sctp/tsnmap.c
@@ -52,29 +52,6 @@ static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off,
int *started, __u16 *start,
int *ended, __u16 *end);
-/* Create a new sctp_tsnmap.
- * Allocate room to store at least 'len' contiguous TSNs.
- */
-struct sctp_tsnmap *sctp_tsnmap_new(__u16 len, __u32 initial_tsn, int gfp)
-{
- struct sctp_tsnmap *retval;
-
- retval = kmalloc(sizeof(struct sctp_tsnmap) +
- sctp_tsnmap_storage_size(len), gfp);
- if (!retval)
- goto fail;
-
- if (!sctp_tsnmap_init(retval, len, initial_tsn))
- goto fail_map;
- retval->malloced = 1;
- return retval;
-
-fail_map:
- kfree(retval);
-fail:
- return NULL;
-}
-
/* Initialize a block of memory as a tsnmap. */
struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len,
__u32 initial_tsn)
@@ -168,16 +145,9 @@ void sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)
}
-/* Dispose of a tsnmap. */
-void sctp_tsnmap_free(struct sctp_tsnmap *map)
-{
- if (map->malloced)
- kfree(map);
-}
-
/* Initialize a Gap Ack Block iterator from memory being provided. */
-void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map,
- struct sctp_tsnmap_iter *iter)
+SCTP_STATIC void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map,
+ struct sctp_tsnmap_iter *iter)
{
/* Only start looking one past the Cumulative TSN Ack Point. */
iter->start = map->cumulative_tsn_ack_point + 1;
@@ -186,8 +156,9 @@ void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map,
/* Get the next Gap Ack Blocks. Returns 0 if there was not another block
* to get.
*/
-int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map,
- struct sctp_tsnmap_iter *iter, __u16 *start, __u16 *end)
+SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map,
+ struct sctp_tsnmap_iter *iter,
+ __u16 *start, __u16 *end)
{
int started, ended;
__u16 _start, _end, offset;
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index b4f2e95ae7cb..17d0ff534735 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -65,8 +65,16 @@ static void sctp_stub_rfree(struct sk_buff *skb)
*/
}
+/* Initialize an ULP event from an given skb. */
+SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags)
+{
+ memset(event, 0, sizeof(struct sctp_ulpevent));
+ event->msg_flags = msg_flags;
+}
+
/* Create a new sctp_ulpevent. */
-struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, int gfp)
+SCTP_STATIC struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags,
+ int gfp)
{
struct sctp_ulpevent *event;
struct sk_buff *skb;
@@ -84,13 +92,6 @@ fail:
return NULL;
}
-/* Initialize an ULP event from an given skb. */
-void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags)
-{
- memset(event, 0, sizeof(struct sctp_ulpevent));
- event->msg_flags = msg_flags;
-}
-
/* Is this a MSG_NOTIFICATION? */
int sctp_ulpevent_is_notification(const struct sctp_ulpevent *event)
{
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index 350a97ec7c62..47a43580f05b 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -56,25 +56,6 @@ static struct sctp_ulpevent * sctp_ulpq_order(struct sctp_ulpq *,
/* 1st Level Abstractions */
-/* Create a new ULP queue. */
-struct sctp_ulpq *sctp_ulpq_new(struct sctp_association *asoc, int gfp)
-{
- struct sctp_ulpq *ulpq;
-
- ulpq = kmalloc(sizeof(struct sctp_ulpq), gfp);
- if (!ulpq)
- goto fail;
- if (!sctp_ulpq_init(ulpq, asoc))
- goto fail_init;
- ulpq->malloced = 1;
- return ulpq;
-
-fail_init:
- kfree(ulpq);
-fail:
- return NULL;
-}
-
/* Initialize a ULP queue from a block of memory. */
struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *ulpq,
struct sctp_association *asoc)
@@ -92,7 +73,7 @@ struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *ulpq,
/* Flush the reassembly and ordering queues. */
-void sctp_ulpq_flush(struct sctp_ulpq *ulpq)
+static void sctp_ulpq_flush(struct sctp_ulpq *ulpq)
{
struct sk_buff *skb;
struct sctp_ulpevent *event;
diff --git a/net/socket.c b/net/socket.c
index dff6156dd4f8..4223cbad8224 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -144,7 +144,7 @@ static struct net_proto_family *net_families[NPROTO];
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
static atomic_t net_family_lockct = ATOMIC_INIT(0);
-static spinlock_t net_family_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(net_family_lock);
/* The strategy is: modifications net_family vector are short, do not
sleep and veeery rare, but read access should be free of any exclusive
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 001e03df0f3c..7176c6d37190 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -89,7 +89,7 @@ rpcauth_destroy(struct rpc_auth *auth)
kfree(auth);
}
-static spinlock_t rpc_credcache_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rpc_credcache_lock);
/*
* Initialize RPC credential cache
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 00d53a9ec8e8..6ee0bb02affe 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -80,7 +80,7 @@ static struct rpc_credops gss_credops;
/* dump the buffer in `emacs-hexl' style */
#define isprint(c) ((c > 0x1f) && (c < 0x7f))
-static rwlock_t gss_ctx_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(gss_ctx_lock);
struct gss_auth {
struct rpc_auth rpc_auth;
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index f5030f3fc42a..2d02377d1c9d 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -51,7 +51,7 @@
#endif
static LIST_HEAD(registered_mechs);
-static spinlock_t registered_mechs_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(registered_mechs_lock);
static void
gss_mech_free(struct gss_api_mech *gm)
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 8845b9e3d735..bf5a2dee8800 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -161,7 +161,7 @@ void cache_fresh(struct cache_detail *detail,
*/
static LIST_HEAD(cache_list);
-static spinlock_t cache_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(cache_list_lock);
static struct cache_detail *current_detail;
static int current_index;
@@ -405,7 +405,7 @@ void cache_purge(struct cache_detail *detail)
#define DFR_MAX 300 /* ??? */
-static spinlock_t cache_defer_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(cache_defer_lock);
static LIST_HEAD(cache_defer_list);
static struct list_head cache_defer_hash[DFR_HASHSIZE];
static int cache_defer_cnt;
@@ -533,7 +533,7 @@ void cache_clean_deferred(void *owner)
*
*/
-static spinlock_t queue_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(queue_lock);
static DECLARE_MUTEX(queue_io_sem);
struct cache_queue {
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index 5e157d65bbe7..2a5d319eda09 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -32,7 +32,7 @@ static struct rpc_procinfo pmap_procedures[];
static struct rpc_clnt * pmap_create(char *, struct sockaddr_in *, int);
static void pmap_getport_done(struct rpc_task *);
static struct rpc_program pmap_program;
-static spinlock_t pmap_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pmap_lock);
/*
* Obtain the port for a given RPC service on a given host. This one can
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 90e5e7e2d01d..af22e3b43ed2 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -72,7 +72,7 @@ static struct workqueue_struct *rpciod_workqueue;
/*
* Spinlock for other critical sections of code.
*/
-static spinlock_t rpc_sched_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rpc_sched_lock);
/*
* Disable the timer for a given RPC task. Should be called with
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index 8a659ac5143a..0148c3310157 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -28,7 +28,7 @@
extern struct auth_ops svcauth_null;
extern struct auth_ops svcauth_unix;
-static spinlock_t authtab_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(authtab_lock);
static struct auth_ops *authtab[RPC_AUTH_MAXFLAVOR] = {
[0] = &svcauth_null,
[1] = &svcauth_unix,
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index eb30bc7bf946..062bcc2080a7 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -124,7 +124,7 @@ int sysctl_unix_max_dgram_qlen = 10;
static kmem_cache_t *unix_sk_cachep;
struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];
-rwlock_t unix_table_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(unix_table_lock);
static atomic_t unix_nr_socks = ATOMIC_INIT(0);
#define unix_sockets_unbound (&unix_socket_table[UNIX_HASH_SIZE])
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index 5acdc5a51650..d0d92336d5c2 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -158,7 +158,7 @@ static void dbg_kfree(void * v, int line) {
/* List of all wanpipe sockets. */
HLIST_HEAD(wanpipe_sklist);
-static rwlock_t wanpipe_sklist_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(wanpipe_sklist_lock);
atomic_t wanpipe_socks_nr;
static unsigned long wanpipe_tx_critical;
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 07171faaad2a..bbac184a9401 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -58,7 +58,7 @@ int sysctl_x25_clear_request_timeout = X25_DEFAULT_T23;
int sysctl_x25_ack_holdback_timeout = X25_DEFAULT_T2;
HLIST_HEAD(x25_list);
-rwlock_t x25_list_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(x25_list_lock);
static struct proto_ops x25_proto_ops;
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c
index 3ca204cfb26a..0a760fe66843 100644
--- a/net/x25/x25_link.c
+++ b/net/x25/x25_link.c
@@ -31,7 +31,7 @@
#include <net/x25.h>
static struct list_head x25_neigh_list = LIST_HEAD_INIT(x25_neigh_list);
-static rwlock_t x25_neigh_list_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(x25_neigh_list_lock);
static void x25_t20timer_expiry(unsigned long);
diff --git a/net/x25/x25_route.c b/net/x25/x25_route.c
index 4697d55bb253..6c5d37517035 100644
--- a/net/x25/x25_route.c
+++ b/net/x25/x25_route.c
@@ -23,7 +23,7 @@
#include <net/x25.h>
struct list_head x25_route_list = LIST_HEAD_INIT(x25_route_list);
-rwlock_t x25_route_list_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(x25_route_list_lock);
/*
* Add a new route.
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index c6ffe5413ca1..4851b46b046e 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -26,11 +26,11 @@
DECLARE_MUTEX(xfrm_cfg_sem);
-static rwlock_t xfrm_policy_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(xfrm_policy_lock);
struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
-static rwlock_t xfrm_policy_afinfo_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(xfrm_policy_afinfo_lock);
static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO];
static kmem_cache_t *xfrm_dst_cache;
@@ -38,7 +38,7 @@ static kmem_cache_t *xfrm_dst_cache;
static struct work_struct xfrm_policy_gc_work;
static struct list_head xfrm_policy_gc_list =
LIST_HEAD_INIT(xfrm_policy_gc_list);
-static spinlock_t xfrm_policy_gc_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(xfrm_policy_gc_lock);
static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index e82cb815c791..5c9a57d6c09a 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -26,7 +26,7 @@
destination/tunnel endpoint. (output)
*/
-static spinlock_t xfrm_state_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(xfrm_state_lock);
/* Hash table to find appropriate SA towards given target (endpoint
* of tunnel or destination of transport mode) allowed by selector.
@@ -39,12 +39,12 @@ static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE];
DECLARE_WAIT_QUEUE_HEAD(km_waitq);
-static rwlock_t xfrm_state_afinfo_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(xfrm_state_afinfo_lock);
static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
static struct work_struct xfrm_state_gc_work;
static struct list_head xfrm_state_gc_list = LIST_HEAD_INIT(xfrm_state_gc_list);
-static spinlock_t xfrm_state_gc_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(xfrm_state_gc_lock);
static void __xfrm_state_delete(struct xfrm_state *x);
@@ -619,7 +619,7 @@ u32 xfrm_get_acqseq(void)
{
u32 res;
static u32 acqseq;
- static spinlock_t acqseq_lock = SPIN_LOCK_UNLOCKED;
+ static DEFINE_SPINLOCK(acqseq_lock);
spin_lock_bh(&acqseq_lock);
res = (++acqseq ? : ++acqseq);
@@ -747,7 +747,7 @@ void xfrm_replay_advance(struct xfrm_state *x, u32 seq)
}
static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);
-static rwlock_t xfrm_km_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(xfrm_km_lock);
static void km_state_expired(struct xfrm_state *x, int hard)
{
diff --git a/security/Kconfig b/security/Kconfig
index 576feff33a54..a850986652b4 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -76,6 +76,7 @@ config SECURITY_ROOTPLUG
config SECURITY_SECLVL
tristate "BSD Secure Levels"
depends on SECURITY
+ select CRYPTO
select CRYPTO_SHA1
help
Implements BSD Secure Levels as an LSM. See
diff --git a/security/commoncap.c b/security/commoncap.c
index 0fdbcfd40a98..849b8c338ee8 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -316,86 +316,13 @@ int cap_syslog (int type)
return 0;
}
-/*
- * Check that a process has enough memory to allocate a new virtual
- * mapping. 0 means there is enough memory for the allocation to
- * succeed and -ENOMEM implies there is not.
- *
- * We currently support three overcommit policies, which are set via the
- * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting
- *
- * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
- * Additional code 2002 Jul 20 by Robert Love.
- */
int cap_vm_enough_memory(long pages)
{
- unsigned long free, allowed;
-
- vm_acct_memory(pages);
-
- /*
- * Sometimes we want to use more memory than we have
- */
- if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
- return 0;
-
- if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
- unsigned long n;
-
- free = get_page_cache_size();
- free += nr_swap_pages;
-
- /*
- * Any slabs which are created with the
- * SLAB_RECLAIM_ACCOUNT flag claim to have contents
- * which are reclaimable, under pressure. The dentry
- * cache and most inode caches should fall into this
- */
- free += atomic_read(&slab_reclaim_pages);
-
- /*
- * Leave the last 3% for root
- */
- if (!capable(CAP_SYS_ADMIN))
- free -= free / 32;
-
- if (free > pages)
- return 0;
-
- /*
- * nr_free_pages() is very expensive on large systems,
- * only call if we're about to fail.
- */
- n = nr_free_pages();
- if (!capable(CAP_SYS_ADMIN))
- n -= n / 32;
- free += n;
-
- if (free > pages)
- return 0;
- vm_unacct_memory(pages);
- return -ENOMEM;
- }
-
- allowed = (totalram_pages - hugetlb_total_pages())
- * sysctl_overcommit_ratio / 100;
- /*
- * Leave the last 3% for root
- */
- if (!capable(CAP_SYS_ADMIN))
- allowed -= allowed / 32;
- allowed += total_swap_pages;
-
- /* Don't let a single process grow too big:
- leave 3% of the size of this process for other processes */
- allowed -= current->mm->total_vm / 32;
-
- if (atomic_read(&vm_committed_space) < allowed)
- return 0;
-
- vm_unacct_memory(pages);
+ int cap_sys_admin = 0;
- return -ENOMEM;
+ if (cap_capable(current, CAP_SYS_ADMIN) == 0)
+ cap_sys_admin = 1;
+ return __vm_enough_memory(pages, cap_sys_admin);
}
EXPORT_SYMBOL(cap_capable);
diff --git a/security/dummy.c b/security/dummy.c
index ce3deb72a87f..72e6d71a79aa 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -108,69 +108,13 @@ static int dummy_settime(struct timespec *ts, struct timezone *tz)
return 0;
}
-/*
- * Check that a process has enough memory to allocate a new virtual
- * mapping. 0 means there is enough memory for the allocation to
- * succeed and -ENOMEM implies there is not.
- *
- * We currently support three overcommit policies, which are set via the
- * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting
- */
static int dummy_vm_enough_memory(long pages)
{
- unsigned long free, allowed;
-
- vm_acct_memory(pages);
-
- /*
- * Sometimes we want to use more memory than we have
- */
- if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
- return 0;
-
- if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
- free = get_page_cache_size();
- free += nr_free_pages();
- free += nr_swap_pages;
-
- /*
- * Any slabs which are created with the
- * SLAB_RECLAIM_ACCOUNT flag claim to have contents
- * which are reclaimable, under pressure. The dentry
- * cache and most inode caches should fall into this
- */
- free += atomic_read(&slab_reclaim_pages);
-
- /*
- * Leave the last 3% for root
- */
- if (current->euid)
- free -= free / 32;
-
- if (free > pages)
- return 0;
- vm_unacct_memory(pages);
- return -ENOMEM;
- }
-
- allowed = (totalram_pages - hugetlb_total_pages())
- * sysctl_overcommit_ratio / 100;
- allowed += total_swap_pages;
+ int cap_sys_admin = 0;
- /* Leave the last 3% for root */
- if (current->euid)
- allowed -= allowed / 32;
-
- /* Don't let a single process grow too big:
- leave 3% of the size of this process for other processes */
- allowed -= current->mm->total_vm / 32;
-
- if (atomic_read(&vm_committed_space) < allowed)
- return 0;
-
- vm_unacct_memory(pages);
-
- return -ENOMEM;
+ if (dummy_capable(current, CAP_SYS_ADMIN) == 0)
+ cap_sys_admin = 1;
+ return __vm_enough_memory(pages, cap_sys_admin);
}
static int dummy_bprm_alloc_security (struct linux_binprm *bprm)
@@ -200,6 +144,11 @@ static void dummy_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
dummy_capget(current, &current->cap_effective, &current->cap_inheritable, &current->cap_permitted);
}
+static void dummy_bprm_post_apply_creds (struct linux_binprm *bprm)
+{
+ return;
+}
+
static int dummy_bprm_set_security (struct linux_binprm *bprm)
{
return 0;
@@ -916,6 +865,7 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, bprm_alloc_security);
set_to_dummy_if_null(ops, bprm_free_security);
set_to_dummy_if_null(ops, bprm_apply_creds);
+ set_to_dummy_if_null(ops, bprm_post_apply_creds);
set_to_dummy_if_null(ops, bprm_set_security);
set_to_dummy_if_null(ops, bprm_check_security);
set_to_dummy_if_null(ops, bprm_secureexec);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index a480aa47a9d3..ea244b769d99 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1515,69 +1515,29 @@ static int selinux_syslog(int type)
* mapping. 0 means there is enough memory for the allocation to
* succeed and -ENOMEM implies there is not.
*
- * We currently support three overcommit policies, which are set via the
- * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting
+ * Note that secondary_ops->capable and task_has_perm_noaudit return 0
+ * if the capability is granted, but __vm_enough_memory requires 1 if
+ * the capability is granted.
*
- * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
- * Additional code 2002 Jul 20 by Robert Love.
+ * Do not audit the selinux permission check, as this is applied to all
+ * processes that allocate mappings.
*/
static int selinux_vm_enough_memory(long pages)
{
- unsigned long free, allowed;
- int rc;
+ int rc, cap_sys_admin = 0;
struct task_security_struct *tsec = current->security;
- vm_acct_memory(pages);
-
- /*
- * Sometimes we want to use more memory than we have
- */
- if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
- return 0;
-
- if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
- free = get_page_cache_size();
- free += nr_free_pages();
- free += nr_swap_pages;
-
- /*
- * Any slabs which are created with the
- * SLAB_RECLAIM_ACCOUNT flag claim to have contents
- * which are reclaimable, under pressure. The dentry
- * cache and most inode caches should fall into this
- */
- free += atomic_read(&slab_reclaim_pages);
+ rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
+ if (rc == 0)
+ rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
+ SECCLASS_CAPABILITY,
+ CAP_TO_MASK(CAP_SYS_ADMIN),
+ NULL);
- /*
- * Leave the last 3% for privileged processes.
- * Don't audit the check, as it is applied to all processes
- * that allocate mappings.
- */
- rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
- if (!rc) {
- rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
- SECCLASS_CAPABILITY,
- CAP_TO_MASK(CAP_SYS_ADMIN), NULL);
- }
- if (rc)
- free -= free / 32;
+ if (rc == 0)
+ cap_sys_admin = 1;
- if (free > pages)
- return 0;
- vm_unacct_memory(pages);
- return -ENOMEM;
- }
-
- allowed = (totalram_pages - hugetlb_total_pages())
- * sysctl_overcommit_ratio / 100;
- allowed += total_swap_pages;
-
- if (atomic_read(&vm_committed_space) < allowed)
- return 0;
-
- vm_unacct_memory(pages);
-
- return -ENOMEM;
+ return __vm_enough_memory(pages, cap_sys_admin);
}
/* binprm security operations */
@@ -1795,10 +1755,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
struct task_security_struct *tsec;
struct bprm_security_struct *bsec;
u32 sid;
- struct av_decision avd;
- struct itimerval itimer;
- struct rlimit *rlim, *initrlim;
- int rc, i;
+ int rc;
secondary_ops->bprm_apply_creds(bprm, unsafe);
@@ -1808,91 +1765,101 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
sid = bsec->sid;
tsec->osid = tsec->sid;
+ bsec->unsafe = 0;
if (tsec->sid != sid) {
/* Check for shared state. If not ok, leave SID
unchanged and kill. */
if (unsafe & LSM_UNSAFE_SHARE) {
- rc = avc_has_perm_noaudit(tsec->sid, sid,
- SECCLASS_PROCESS, PROCESS__SHARE, &avd);
+ rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
+ PROCESS__SHARE, NULL);
if (rc) {
- task_unlock(current);
- avc_audit(tsec->sid, sid, SECCLASS_PROCESS,
- PROCESS__SHARE, &avd, rc, NULL);
- force_sig_specific(SIGKILL, current);
- goto lock_out;
+ bsec->unsafe = 1;
+ return;
}
}
/* Check for ptracing, and update the task SID if ok.
Otherwise, leave SID unchanged and kill. */
if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
- rc = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
- SECCLASS_PROCESS, PROCESS__PTRACE, &avd);
- if (!rc)
- tsec->sid = sid;
- task_unlock(current);
- avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
- PROCESS__PTRACE, &avd, rc, NULL);
+ rc = avc_has_perm(tsec->ptrace_sid, sid,
+ SECCLASS_PROCESS, PROCESS__PTRACE,
+ NULL);
if (rc) {
- force_sig_specific(SIGKILL, current);
- goto lock_out;
+ bsec->unsafe = 1;
+ return;
}
- } else {
- tsec->sid = sid;
- task_unlock(current);
- }
-
- /* Close files for which the new task SID is not authorized. */
- flush_unauthorized_files(current->files);
-
- /* Check whether the new SID can inherit signal state
- from the old SID. If not, clear itimers to avoid
- subsequent signal generation and flush and unblock
- signals. This must occur _after_ the task SID has
- been updated so that any kill done after the flush
- will be checked against the new SID. */
- rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
- PROCESS__SIGINH, NULL);
- if (rc) {
- memset(&itimer, 0, sizeof itimer);
- for (i = 0; i < 3; i++)
- do_setitimer(i, &itimer, NULL);
- flush_signals(current);
- spin_lock_irq(&current->sighand->siglock);
- flush_signal_handlers(current, 1);
- sigemptyset(&current->blocked);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
}
+ tsec->sid = sid;
+ }
+}
- /* Check whether the new SID can inherit resource limits
- from the old SID. If not, reset all soft limits to
- the lower of the current task's hard limit and the init
- task's soft limit. Note that the setting of hard limits
- (even to lower them) can be controlled by the setrlimit
- check. The inclusion of the init task's soft limit into
- the computation is to avoid resetting soft limits higher
- than the default soft limit for cases where the default
- is lower than the hard limit, e.g. RLIMIT_CORE or
- RLIMIT_STACK.*/
- rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
- PROCESS__RLIMITINH, NULL);
- if (rc) {
- for (i = 0; i < RLIM_NLIMITS; i++) {
- rlim = current->signal->rlim + i;
- initrlim = init_task.signal->rlim+i;
- rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
- }
- }
+/*
+ * called after apply_creds without the task lock held
+ */
+static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
+{
+ struct task_security_struct *tsec;
+ struct rlimit *rlim, *initrlim;
+ struct itimerval itimer;
+ struct bprm_security_struct *bsec;
+ int rc, i;
- /* Wake up the parent if it is waiting so that it can
- recheck wait permission to the new task SID. */
- wake_up_interruptible(&current->parent->signal->wait_chldexit);
+ tsec = current->security;
+ bsec = bprm->security;
-lock_out:
- task_lock(current);
+ if (bsec->unsafe) {
+ force_sig_specific(SIGKILL, current);
return;
}
+ if (tsec->osid == tsec->sid)
+ return;
+
+ /* Close files for which the new task SID is not authorized. */
+ flush_unauthorized_files(current->files);
+
+ /* Check whether the new SID can inherit signal state
+ from the old SID. If not, clear itimers to avoid
+ subsequent signal generation and flush and unblock
+ signals. This must occur _after_ the task SID has
+ been updated so that any kill done after the flush
+ will be checked against the new SID. */
+ rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
+ PROCESS__SIGINH, NULL);
+ if (rc) {
+ memset(&itimer, 0, sizeof itimer);
+ for (i = 0; i < 3; i++)
+ do_setitimer(i, &itimer, NULL);
+ flush_signals(current);
+ spin_lock_irq(&current->sighand->siglock);
+ flush_signal_handlers(current, 1);
+ sigemptyset(&current->blocked);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ }
+
+ /* Check whether the new SID can inherit resource limits
+ from the old SID. If not, reset all soft limits to
+ the lower of the current task's hard limit and the init
+ task's soft limit. Note that the setting of hard limits
+ (even to lower them) can be controlled by the setrlimit
+ check. The inclusion of the init task's soft limit into
+ the computation is to avoid resetting soft limits higher
+ than the default soft limit for cases where the default
+ is lower than the hard limit, e.g. RLIMIT_CORE or
+ RLIMIT_STACK.*/
+ rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
+ PROCESS__RLIMITINH, NULL);
+ if (rc) {
+ for (i = 0; i < RLIM_NLIMITS; i++) {
+ rlim = current->signal->rlim + i;
+ initrlim = init_task.signal->rlim+i;
+ rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
+ }
+ }
+
+ /* Wake up the parent if it is waiting so that it can
+ recheck wait permission to the new task SID. */
+ wake_up_interruptible(&current->parent->signal->wait_chldexit);
}
/* superblock security operations */
@@ -4212,6 +4179,7 @@ struct security_operations selinux_ops = {
.bprm_alloc_security = selinux_bprm_alloc_security,
.bprm_free_security = selinux_bprm_free_security,
.bprm_apply_creds = selinux_bprm_apply_creds,
+ .bprm_post_apply_creds = selinux_bprm_post_apply_creds,
.bprm_set_security = selinux_bprm_set_security,
.bprm_check_security = selinux_bprm_check_security,
.bprm_secureexec = selinux_bprm_secureexec,
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index d1516e47e421..30a0abc9c778 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -87,6 +87,12 @@ struct bprm_security_struct {
struct linux_binprm *bprm; /* back pointer to bprm object */
u32 sid; /* SID for transformed process */
unsigned char set;
+
+ /*
+ * unsafe is used to share failure information from bprm_apply_creds()
+ * to bprm_post_apply_creds().
+ */
+ char unsafe;
};
struct netif_security_struct {
diff --git a/sound/core/ioctl32/ioctl32.c b/sound/core/ioctl32/ioctl32.c
index 46d31cb63a14..0c7639e05feb 100644
--- a/sound/core/ioctl32/ioctl32.c
+++ b/sound/core/ioctl32/ioctl32.c
@@ -219,25 +219,10 @@ struct sndrv_ctl_elem_value32 {
struct sndrv_ctl_elem_id id;
unsigned int indirect; /* bit-field causes misalignment */
union {
- union {
- s32 value[128];
- u32 value_ptr;
- } integer;
- union {
- s64 value[64];
- u32 value_ptr;
- } integer64;
- union {
- u32 item[128];
- u32 item_ptr;
- } enumerated;
- union {
- unsigned char data[512];
- u32 data_ptr;
- } bytes;
- struct sndrv_aes_iec958 iec958;
+ s32 integer[128]; /* integer and boolean need conversion */
+ unsigned char data[512]; /* others should be compatible */
} value;
- unsigned char reserved[128];
+ unsigned char reserved[128]; /* not used */
};
@@ -269,7 +254,7 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd,
struct sndrv_ctl_elem_value *data;
struct sndrv_ctl_elem_value32 __user *data32;
snd_ctl_file_t *ctl;
- int err, i;
+ int err, i, indirect;
int type;
/* sanity check */
@@ -281,7 +266,7 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd,
return -ENOTTY;
data32 = compat_ptr(arg);
- data = kmalloc(sizeof(*data), GFP_KERNEL);
+ data = kcalloc(1, sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
@@ -289,12 +274,12 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd,
err = -EFAULT;
goto __end;
}
- if (__get_user(data->indirect, &data32->indirect)) {
+ if (__get_user(indirect, &data32->indirect)) {
err = -EFAULT;
goto __end;
}
/* FIXME: indirect access is not supported */
- if (data->indirect) {
+ if (indirect) {
err = -EINVAL;
goto __end;
}
@@ -309,7 +294,7 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd,
case SNDRV_CTL_ELEM_TYPE_INTEGER:
for (i = 0; i < 128; i++) {
int val;
- if (__get_user(val, &data32->value.integer.value[i])) {
+ if (__get_user(val, &data32->value.integer[i])) {
err = -EFAULT;
goto __end;
}
@@ -317,33 +302,12 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd,
}
break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
- if (__copy_from_user(data->value.integer64.value,
- data32->value.integer64.value,
- sizeof(data->value.integer64.value))) {
- err = -EFAULT;
- goto __end;
- }
- break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
- if (__copy_from_user(data->value.enumerated.item,
- data32->value.enumerated.item,
- sizeof(data32->value.enumerated.item))) {
- err = -EFAULT;
- goto __end;
- }
- break;
case SNDRV_CTL_ELEM_TYPE_BYTES:
- if (__copy_from_user(data->value.bytes.data,
- data32->value.bytes.data,
- sizeof(data32->value.bytes.data))) {
- err = -EFAULT;
- goto __end;
- }
- break;
case SNDRV_CTL_ELEM_TYPE_IEC958:
- if (__copy_from_user(&data->value.iec958,
- &data32->value.iec958,
- sizeof(data32->value.iec958))) {
+ if (__copy_from_user(data->value.bytes.data,
+ data32->value.data,
+ sizeof(data32->value.data))) {
err = -EFAULT;
goto __end;
}
@@ -367,43 +331,20 @@ static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd,
for (i = 0; i < 128; i++) {
int val;
val = data->value.integer.value[i];
- if (__put_user(val, &data32->value.integer.value[i])) {
+ if (__put_user(val, &data32->value.integer[i])) {
err = -EFAULT;
goto __end;
}
}
break;
- case SNDRV_CTL_ELEM_TYPE_INTEGER64:
- if (__copy_to_user(data32->value.integer64.value,
- data->value.integer64.value,
- sizeof(data32->value.integer64.value))) {
- err = -EFAULT;
- goto __end;
- }
- break;
- case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
- if (__copy_to_user(data32->value.enumerated.item,
- data->value.enumerated.item,
- sizeof(data32->value.enumerated.item))) {
- err = -EFAULT;
- goto __end;
- }
- break;
- case SNDRV_CTL_ELEM_TYPE_BYTES:
- if (__copy_to_user(data32->value.bytes.data,
+ default:
+ if (__copy_to_user(data32->value.data,
data->value.bytes.data,
- sizeof(data32->value.bytes.data))) {
+ sizeof(data32->value.data))) {
err = -EFAULT;
goto __end;
}
break;
- case SNDRV_CTL_ELEM_TYPE_IEC958:
- if (__copy_to_user(&data32->value.iec958,
- &data->value.iec958,
- sizeof(data32->value.iec958))) {
- err = -EFAULT;
- goto __end;
- }
break;
}
err = 0;
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index d3675111607f..0624ff970cb8 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -747,7 +747,7 @@ static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file,
case SNDRV_RAWMIDI_IOCTL_DROP:
{
int val;
- if (get_user(val, (long __user *) argp))
+ if (get_user(val, (int __user *) argp))
return -EFAULT;
switch (val) {
case SNDRV_RAWMIDI_STREAM_OUTPUT:
@@ -761,7 +761,7 @@ static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file,
case SNDRV_RAWMIDI_IOCTL_DRAIN:
{
int val;
- if (get_user(val, (long __user *) argp))
+ if (get_user(val, (int __user *) argp))
return -EFAULT;
switch (val) {
case SNDRV_RAWMIDI_STREAM_OUTPUT:
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index fd970b1ef9e0..171bf668a3ff 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -1505,7 +1505,7 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, ~AC97_GP_DRSS_MASK, 0x0000);
/* build 3D controls */
- if (ac97->build_ops && ac97->build_ops->build_3d) {
+ if (ac97->build_ops->build_3d) {
ac97->build_ops->build_3d(ac97);
} else {
if (snd_ac97_try_volume_mix(ac97, AC97_3D_CONTROL)) {
@@ -1528,14 +1528,14 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
/* build S/PDIF controls */
if (ac97->ext_id & AC97_EI_SPDIF) {
- if (ac97->build_ops && ac97->build_ops->build_spdif) {
+ if (ac97->build_ops->build_spdif) {
if ((err = ac97->build_ops->build_spdif(ac97)) < 0)
return err;
} else {
for (idx = 0; idx < 5; idx++)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)
return err;
- if (ac97->build_ops && ac97->build_ops->build_post_spdif) {
+ if (ac97->build_ops->build_post_spdif) {
if ((err = ac97->build_ops->build_post_spdif(ac97)) < 0)
return err;
}
@@ -1548,7 +1548,7 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
/* build chip specific controls */
- if (ac97->build_ops && ac97->build_ops->build_specific)
+ if (ac97->build_ops->build_specific)
if ((err = ac97->build_ops->build_specific(ac97)) < 0)
return err;
@@ -1811,6 +1811,9 @@ int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops,
return 0;
}
+/* build_ops to do nothing */
+static struct snd_ac97_build_ops null_build_ops;
+
/**
* snd_ac97_mixer - create an Codec97 component
* @bus: the AC97 bus which codec is attached to
@@ -2050,6 +2053,9 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
bus->ops->init(ac97);
snd_ac97_get_name(ac97, ac97->id, name, !ac97_is_audio(ac97));
snd_ac97_get_name(NULL, ac97->id, name, !ac97_is_audio(ac97)); // ac97->id might be changed in the special setup code
+ if (! ac97->build_ops)
+ ac97->build_ops = &null_build_ops;
+
if (ac97_is_audio(ac97)) {
char comp[16];
if (card->mixername[0] == '\0') {
@@ -2157,6 +2163,8 @@ static void snd_ac97_powerdown(ac97_t *ac97)
*/
void snd_ac97_suspend(ac97_t *ac97)
{
+ if (ac97->build_ops->suspend)
+ ac97->build_ops->suspend(ac97);
snd_ac97_powerdown(ac97);
}
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 102977a0aeda..6031db827a4d 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -910,7 +910,7 @@ static void patch_ad1881_chained(ac97_t * ac97, int unchained_idx, int cidx1, in
static struct snd_ac97_build_ops patch_ad1881_build_ops = {
#ifdef CONFIG_PM
- .resume = &ad18xx_resume
+ .resume = ad18xx_resume
#endif
};
@@ -993,7 +993,7 @@ static int patch_ad1885_specific(ac97_t * ac97)
static struct snd_ac97_build_ops patch_ad1885_build_ops = {
.build_specific = &patch_ad1885_specific,
#ifdef CONFIG_PM
- .resume = &ad18xx_resume
+ .resume = ad18xx_resume
#endif
};
@@ -1605,7 +1605,10 @@ int patch_alc655(ac97_t * ac97)
/* adjust default values */
val = snd_ac97_read(ac97, 0x7a); /* misc control */
- val |= (1 << 1); /* spdif input pin */
+ if (ac97->id == 0x414c4780) /* ALC658 */
+ val &= ~(1 << 1); /* Pin 47 is spdif input pin */
+ else /* ALC655 */
+ val |= (1 << 1); /* Pin 47 is spdif input pin */
val &= ~(1 << 12); /* vref enable */
snd_ac97_write_cache(ac97, 0x7a, val);
/* set default: spdif-in enabled,
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index f05b51b23bdc..36145684cf03 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -43,6 +43,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000};
+static char *ac97_quirk[SNDRV_CARDS];
static int spdif_aclink[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
module_param_array(index, int, NULL, 0444);
@@ -53,6 +54,8 @@ module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable audio part of ATI IXP controller.");
module_param_array(ac97_clock, int, NULL, 0444);
MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
+module_param_array(ac97_quirk, charp, NULL, 0444);
+MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
module_param_array(spdif_aclink, bool, NULL, 0444);
MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
@@ -630,21 +633,20 @@ static snd_pcm_uframes_t snd_atiixp_pcm_pointer(snd_pcm_substream_t *substream)
snd_pcm_runtime_t *runtime = substream->runtime;
atiixp_dma_t *dma = (atiixp_dma_t *)runtime->private_data;
unsigned int curptr;
+ int timeout = 1000;
- spin_lock(&chip->reg_lock);
- curptr = readl(chip->remap_addr + dma->ops->dt_cur);
- if (curptr < dma->buf_addr) {
- snd_printdd("curptr = %x, base = %x\n", curptr, dma->buf_addr);
- curptr = 0;
- } else {
+ while (timeout--) {
+ curptr = readl(chip->remap_addr + dma->ops->dt_cur);
+ if (curptr < dma->buf_addr)
+ continue;
curptr -= dma->buf_addr;
- if (curptr >= dma->buf_bytes) {
- snd_printdd("curptr = %x, size = %x\n", curptr, dma->buf_bytes);
- curptr = 0;
- }
+ if (curptr >= dma->buf_bytes)
+ continue;
+ return bytes_to_frames(runtime, curptr);
}
- spin_unlock(&chip->reg_lock);
- return bytes_to_frames(runtime, curptr);
+ snd_printd("atiixp: invalid DMA pointer read 0x%x (buf=%x)\n",
+ readl(chip->remap_addr + dma->ops->dt_cur), dma->buf_addr);
+ return 0;
}
/*
@@ -1329,7 +1331,11 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *r
* ac97 mixer section
*/
-static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock)
+static struct ac97_quirk ac97_quirks[] __devinitdata = {
+ { } /* terminator */
+};
+
+static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock, const char *quirk_override)
{
ac97_bus_t *pbus;
ac97_template_t ac97;
@@ -1376,7 +1382,7 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock)
return -ENODEV;
}
- /* snd_ac97_tune_hardware(chip->ac97, ac97_quirks); */
+ snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks, quirk_override);
return 0;
}
@@ -1569,7 +1575,7 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
chip->spdif_over_aclink = spdif_aclink[dev];
- if ((err = snd_atiixp_mixer_new(chip, ac97_clock[dev])) < 0)
+ if ((err = snd_atiixp_mixer_new(chip, ac97_clock[dev], ac97_quirk[dev])) < 0)
goto __error;
if ((err = snd_atiixp_pcm_new(chip)) < 0)
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 98e3983f14ff..97bed1b0899d 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -1,4 +1,3 @@
-#define __NO_VERSION__
/*
* Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c
index b52d57f8a22f..afb711421e47 100644
--- a/sound/pci/ca0106/ca0106_proc.c
+++ b/sound/pci/ca0106/ca0106_proc.c
@@ -1,4 +1,3 @@
-#define __NO_VERSION__
/*
* Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 66e26eaca1b1..54b6cb8d3f36 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -1766,10 +1766,22 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
.name = "Dell", /* which model? AD1981B*/
.type = AC97_TUNE_HP_ONLY
},
+ {
+ .vendor = 0x103c,
+ .device = 0x006d,
+ .name = "HP zv5000",
+ .type = AC97_TUNE_MUTE_LED /*AD1981B*/
+ },
{ /* FIXME: which codec? */
.vendor = 0x103c,
.device = 0x00c3,
- .name = "Hewlett-Packard onboard",
+ .name = "HP xw6000",
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
+ .vendor = 0x103c,
+ .device = 0x129d,
+ .name = "HP xw8000",
.type = AC97_TUNE_HP_ONLY
},
{
@@ -1786,6 +1798,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
},
{
.vendor = 0x103c,
+ .device = 0x12f2,
+ .name = "HP xw6200",
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
+ .vendor = 0x103c,
.device = 0x3008,
.name = "HP xw4200", /* AD1981B*/
.type = AC97_TUNE_HP_ONLY
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 3acffcb9540a..dd9047c50e60 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -526,11 +526,11 @@ static int mixart_set_format(mixart_stream_t *stream, snd_pcm_format_t format)
stream_param.sample_type = ST_INTEGER_24BE;
stream_param.sample_size = 24;
break;
- case SNDRV_PCM_FMTBIT_FLOAT_LE:
+ case SNDRV_PCM_FORMAT_FLOAT_LE:
stream_param.sample_type = ST_FLOATING_POINT_32LE;
stream_param.sample_size = 32;
break;
- case SNDRV_PCM_FMTBIT_FLOAT_BE:
+ case SNDRV_PCM_FORMAT_FLOAT_BE:
stream_param.sample_type = ST_FLOATING_POINT_32BE;
stream_param.sample_size = 32;
break;
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 0434acf1f75a..299bbf228358 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -183,7 +183,6 @@ static dev_link_t *snd_pdacf_attach(void)
/* Register with Card Services */
client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL
#ifdef CONFIG_PM
@@ -274,15 +273,6 @@ static void snd_pdacf_detach(dev_link_t *link)
}
/*
- * snd_pdacf_detach_all - detach all instances linked to the hw
- */
-static void snd_pdacf_detach_all(void)
-{
- while (dev_list != NULL)
- snd_pdacf_detach(dev_list);
-}
-
-/*
* configuration callback
*/
@@ -413,7 +403,7 @@ static int __init init_pdacf(void)
static void __exit exit_pdacf(void)
{
pcmcia_unregister_driver(&pdacf_cs_driver);
- snd_pdacf_detach_all();
+ BUG_ON(dev_list != NULL);
}
module_init(init_pdacf);
diff --git a/sound/pcmcia/vx/vx_entry.c b/sound/pcmcia/vx/vx_entry.c
index 1cd4a2751124..8f59818fef8a 100644
--- a/sound/pcmcia/vx/vx_entry.c
+++ b/sound/pcmcia/vx/vx_entry.c
@@ -175,7 +175,6 @@ dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw)
/* Register with Card Services */
memset(&client_reg, 0, sizeof(client_reg));
client_reg.dev_info = hw->dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL
#ifdef CONFIG_PM
@@ -266,15 +265,6 @@ void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link)
}
/*
- * snd_vxpocket_detach_all - detach all instances linked to the hw
- */
-void snd_vxpocket_detach_all(struct snd_vxp_entry *hw)
-{
- while (hw->dev_list != NULL)
- snd_vxpocket_detach(hw, hw->dev_list);
-}
-
-/*
* configuration callback
*/
@@ -397,4 +387,3 @@ static int vxpocket_event(event_t event, int priority, event_callback_args_t *ar
EXPORT_SYMBOL(snd_vxpocket_ops);
EXPORT_SYMBOL(snd_vxpocket_attach);
EXPORT_SYMBOL(snd_vxpocket_detach);
-EXPORT_SYMBOL(snd_vxpocket_detach_all);
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 63aebb2b07f2..0818bd448e28 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -165,7 +165,7 @@ static int __init init_vxpocket(void)
static void __exit exit_vxpocket(void)
{
pcmcia_unregister_driver(&vxp_cs_driver);
- snd_vxpocket_detach_all(&hw_entry);
+ BUG_ON(hw_entry.dev_list != NULL);
}
module_init(init_vxpocket);
diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h
index 2902a3b5d5a6..c051424ccf5c 100644
--- a/sound/pcmcia/vx/vxpocket.h
+++ b/sound/pcmcia/vx/vxpocket.h
@@ -77,7 +77,6 @@ void vx_set_mic_level(vx_core_t *chip, int level);
*/
dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw);
void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link);
-void snd_vxpocket_detach_all(struct snd_vxp_entry *hw);
int vxp_add_mic_controls(vx_core_t *chip);