aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-03-29 17:18:49 -0500
committerJeff Garzik <jeff@garzik.org>2006-03-29 17:18:49 -0500
commite02a4cabfcb9a999b74a2e2e6f13ffcb7ff2d606 (patch)
tree2f3db60be4c57eca2a4c3ab3f3122dcf1ec0c624
parent600511e86babe3727264a0883a3a264f6fb6caf5 (diff)
parentf3cab8a0b1a772dc8b055b7affa567a366627c9e (diff)
Merge branch 'master'
-rw-r--r--CREDITS20
-rw-r--r--Documentation/DMA-mapping.txt2
-rw-r--r--Documentation/DocBook/Makefile8
-rw-r--r--Documentation/RCU/whatisRCU.txt6
-rw-r--r--Documentation/aoe/mkdevs.sh2
-rw-r--r--Documentation/aoe/udev.txt1
-rw-r--r--Documentation/arm/Booting2
-rw-r--r--Documentation/arm/README2
-rw-r--r--Documentation/arm/SA1100/Assabet2
-rw-r--r--Documentation/arm/SA1100/LART2
-rw-r--r--Documentation/arm/Setup2
-rw-r--r--Documentation/block/biodoc.txt14
-rw-r--r--Documentation/cachetlb.txt21
-rw-r--r--Documentation/cpu-hotplug.txt4
-rw-r--r--Documentation/cputopology.txt4
-rw-r--r--Documentation/drivers/edac/edac.txt34
-rw-r--r--Documentation/feature-removal-schedule.txt12
-rw-r--r--Documentation/filesystems/00-INDEX54
-rw-r--r--Documentation/filesystems/9p.txt (renamed from Documentation/filesystems/v9fs.txt)21
-rw-r--r--Documentation/filesystems/proc.txt6
-rw-r--r--Documentation/filesystems/udf.txt14
-rw-r--r--Documentation/filesystems/vfs.txt217
-rw-r--r--Documentation/firmware_class/firmware_sample_driver.c3
-rw-r--r--Documentation/firmware_class/firmware_sample_firmware_class.c1
-rw-r--r--Documentation/ioctl-number.txt2
-rw-r--r--Documentation/kbuild/makefiles.txt172
-rw-r--r--Documentation/kbuild/modules.txt98
-rw-r--r--Documentation/kernel-parameters.txt15
-rw-r--r--Documentation/m68k/README.buddha2
-rw-r--r--Documentation/networking/TODO18
-rw-r--r--Documentation/networking/ifenslave.c2
-rw-r--r--Documentation/networking/packet_mmap.txt10
-rw-r--r--Documentation/networking/ray_cs.txt2
-rw-r--r--Documentation/networking/vortex.txt81
-rw-r--r--Documentation/pnp.txt3
-rw-r--r--Documentation/powerpc/booting-without-of.txt5
-rw-r--r--Documentation/robust-futex-ABI.txt182
-rw-r--r--Documentation/robust-futexes.txt218
-rw-r--r--Documentation/rpc-cache.txt121
-rw-r--r--Documentation/serial-console.txt11
-rw-r--r--Documentation/smart-config.txt4
-rw-r--r--Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl2
-rw-r--r--Documentation/sound/oss/Introduction2
-rw-r--r--Documentation/sound/oss/cs46xx16
-rw-r--r--Documentation/video4linux/CQcam.txt182
-rw-r--r--Documentation/video4linux/README.cpia4
-rw-r--r--Documentation/video4linux/Zoran108
-rw-r--r--Documentation/video4linux/bttv/ICs4
-rw-r--r--Documentation/video4linux/bttv/PROBLEMS16
-rw-r--r--Documentation/video4linux/bttv/README.quirks4
-rw-r--r--Documentation/video4linux/bttv/THANKS4
-rw-r--r--Documentation/video4linux/radiotrack.txt16
-rw-r--r--Documentation/video4linux/w9966.txt2
-rw-r--r--Documentation/video4linux/zr36120.txt4
-rw-r--r--MAINTAINERS97
-rw-r--r--Makefile200
-rw-r--r--arch/alpha/Kconfig8
-rw-r--r--arch/alpha/kernel/osf_sys.c1
-rw-r--r--arch/alpha/kernel/setup.c14
-rw-r--r--arch/alpha/kernel/time.c3
-rw-r--r--arch/alpha/lib/ev6-memchr.S2
-rw-r--r--arch/alpha/lib/fpreg.c8
-rw-r--r--arch/alpha/mm/numa.c4
-rw-r--r--arch/arm/Kconfig18
-rw-r--r--arch/arm/Makefile7
-rw-r--r--arch/arm/boot/Makefile5
-rw-r--r--arch/arm/boot/bootp/Makefile5
-rw-r--r--arch/arm/boot/compressed/Makefile4
-rw-r--r--arch/arm/boot/compressed/head.S82
-rw-r--r--arch/arm/boot/compressed/ice-dcc.S17
-rw-r--r--arch/arm/boot/compressed/misc.c41
-rw-r--r--arch/arm/common/rtctime.c108
-rw-r--r--arch/arm/configs/ixp23xx_defconfig1302
-rw-r--r--arch/arm/kernel/entry-header.S18
-rw-r--r--arch/arm/kernel/head.S15
-rw-r--r--arch/arm/kernel/setup.c4
-rw-r--r--arch/arm/kernel/smp.c3
-rw-r--r--arch/arm/kernel/sys_arm.c5
-rw-r--r--arch/arm/kernel/traps.c2
-rw-r--r--arch/arm/lib/Makefile2
-rw-r--r--arch/arm/lib/backtrace.S2
-rw-r--r--arch/arm/lib/copy_template.S2
-rw-r--r--arch/arm/mach-ep93xx/core.c68
-rw-r--r--arch/arm/mach-footbridge/time.c17
-rw-r--r--arch/arm/mach-integrator/core.c46
-rw-r--r--arch/arm/mach-integrator/time.c16
-rw-r--r--arch/arm/mach-iop3xx/iop331-setup.c4
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x01.c78
-rw-r--r--arch/arm/mach-ixp23xx/Kconfig25
-rw-r--r--arch/arm/mach-ixp23xx/Makefile11
-rw-r--r--arch/arm/mach-ixp23xx/Makefile.boot2
-rw-r--r--arch/arm/mach-ixp23xx/core.c431
-rw-r--r--arch/arm/mach-ixp23xx/espresso.c69
-rw-r--r--arch/arm/mach-ixp23xx/ixdp2351.c325
-rw-r--r--arch/arm/mach-ixp23xx/pci.c275
-rw-r--r--arch/arm/mach-ixp23xx/roadrunner.c164
-rw-r--r--arch/arm/mach-omap1/board-netstar.c2
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c2
-rw-r--r--arch/arm/mach-omap2/serial.c2
-rw-r--r--arch/arm/mach-pxa/Kconfig5
-rw-r--r--arch/arm/mach-pxa/Makefile1
-rw-r--r--arch/arm/mach-pxa/generic.c6
-rw-r--r--arch/arm/mach-pxa/lpd270.c393
-rw-r--r--arch/arm/mach-pxa/spitz.c2
-rw-r--r--arch/arm/mach-sa1100/Kconfig2
-rw-r--r--arch/arm/mach-sa1100/assabet.c1
-rw-r--r--arch/arm/mach-sa1100/collie.c30
-rw-r--r--arch/arm/mach-sa1100/collie_pm.c278
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1100.c2
-rw-r--r--arch/arm/mach-sa1100/generic.c6
-rw-r--r--arch/arm/mm/Kconfig27
-rw-r--r--arch/arm/mm/Makefile2
-rw-r--r--arch/arm/mm/copypage-xsc3.S97
-rw-r--r--arch/arm/mm/mm-armv.c3
-rw-r--r--arch/arm/mm/proc-arm1020.S1
-rw-r--r--arch/arm/mm/proc-arm1020e.S1
-rw-r--r--arch/arm/mm/proc-arm1022.S1
-rw-r--r--arch/arm/mm/proc-arm1026.S1
-rw-r--r--arch/arm/mm/proc-arm6_7.S1
-rw-r--r--arch/arm/mm/proc-arm720.S1
-rw-r--r--arch/arm/mm/proc-arm920.S1
-rw-r--r--arch/arm/mm/proc-arm922.S1
-rw-r--r--arch/arm/mm/proc-arm925.S1
-rw-r--r--arch/arm/mm/proc-arm926.S1
-rw-r--r--arch/arm/mm/proc-sa110.S1
-rw-r--r--arch/arm/mm/proc-sa1100.S1
-rw-r--r--arch/arm/mm/proc-v6.S17
-rw-r--r--arch/arm/mm/proc-xsc3.S498
-rw-r--r--arch/arm/mm/proc-xscale.S1
-rw-r--r--arch/arm/vfp/entry.S1
-rw-r--r--arch/arm/vfp/vfphw.S4
-rw-r--r--arch/arm26/Kconfig4
-rw-r--r--arch/arm26/Makefile7
-rw-r--r--arch/arm26/boot/Makefile5
-rw-r--r--arch/arm26/kernel/traps.c12
-rw-r--r--arch/arm26/mm/init.c7
-rw-r--r--arch/cris/Kconfig8
-rw-r--r--arch/cris/kernel/setup.c5
-rw-r--r--arch/frv/Kconfig4
-rw-r--r--arch/frv/mm/mmu-context.c6
-rw-r--r--arch/h8300/Kconfig8
-rw-r--r--arch/i386/Kconfig15
-rw-r--r--arch/i386/Kconfig.debug4
-rw-r--r--arch/i386/Makefile14
-rw-r--r--arch/i386/Makefile.cpu4
-rw-r--r--arch/i386/boot/Makefile36
-rw-r--r--arch/i386/boot/edd.S2
-rw-r--r--arch/i386/boot/video.S2
-rw-r--r--arch/i386/kernel/acpi/boot.c8
-rw-r--r--arch/i386/kernel/cpu/common.c10
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Kconfig24
-rw-r--r--arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c64
-rw-r--r--arch/i386/kernel/cpu/cpufreq/elanfreq.c109
-rw-r--r--arch/i386/kernel/cpu/cpufreq/gx-suspmod.c183
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.h4
-rw-r--r--arch/i386/kernel/cpu/cpufreq/p4-clockmod.c26
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k6.c16
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k7.c10
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.c49
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.h8
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c4
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-lib.c42
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-lib.h20
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-smi.c53
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c77
-rw-r--r--arch/i386/kernel/cpu/mtrr/main.c13
-rw-r--r--arch/i386/kernel/cpu/proc.c2
-rw-r--r--arch/i386/kernel/dmi_scan.c123
-rw-r--r--arch/i386/kernel/efi.c23
-rw-r--r--arch/i386/kernel/io_apic.c4
-rw-r--r--arch/i386/kernel/kprobes.c253
-rw-r--r--arch/i386/kernel/microcode.c28
-rw-r--r--arch/i386/kernel/nmi.c9
-rw-r--r--arch/i386/kernel/process.c8
-rw-r--r--arch/i386/kernel/setup.c9
-rw-r--r--arch/i386/kernel/smpboot.c57
-rw-r--r--arch/i386/kernel/syscall_table.S2
-rw-r--r--arch/i386/kernel/timers/timer_pm.c104
-rw-r--r--arch/i386/kernel/traps.c34
-rw-r--r--arch/i386/kernel/vm86.c12
-rw-r--r--arch/i386/kernel/vmlinux.lds.S3
-rw-r--r--arch/i386/mach-voyager/voyager_smp.c2
-rw-r--r--arch/i386/mm/discontig.c12
-rw-r--r--arch/i386/mm/pgtable.c2
-rw-r--r--arch/i386/oprofile/nmi_int.c2
-rw-r--r--arch/ia64/Kconfig17
-rw-r--r--arch/ia64/Makefile5
-rw-r--r--arch/ia64/configs/gensparse_defconfig1
-rw-r--r--arch/ia64/configs/sn2_defconfig1
-rw-r--r--arch/ia64/defconfig1
-rw-r--r--arch/ia64/dig/setup.c5
-rw-r--r--arch/ia64/ia32/ia32priv.h4
-rw-r--r--arch/ia64/ia32/sys_ia32.c89
-rw-r--r--arch/ia64/kernel/Makefile3
-rw-r--r--arch/ia64/kernel/acpi.c41
-rw-r--r--arch/ia64/kernel/efi.c62
-rw-r--r--arch/ia64/kernel/ivt.S1
-rw-r--r--arch/ia64/kernel/kprobes.c51
-rw-r--r--arch/ia64/kernel/machvec.c19
-rw-r--r--arch/ia64/kernel/mca.c113
-rw-r--r--arch/ia64/kernel/mca_drv.c22
-rw-r--r--arch/ia64/kernel/mca_drv.h7
-rw-r--r--arch/ia64/kernel/mca_drv_asm.S13
-rw-r--r--arch/ia64/kernel/numa.c2
-rw-r--r--arch/ia64/kernel/patch.c8
-rw-r--r--arch/ia64/kernel/process.c8
-rw-r--r--arch/ia64/kernel/ptrace.c10
-rw-r--r--arch/ia64/kernel/setup.c70
-rw-r--r--arch/ia64/kernel/smpboot.c109
-rw-r--r--arch/ia64/kernel/traps.c6
-rw-r--r--arch/ia64/kernel/vmlinux.lds.S60
-rw-r--r--arch/ia64/lib/Makefile2
-rw-r--r--arch/ia64/lib/bitop.c88
-rw-r--r--arch/ia64/mm/Makefile2
-rw-r--r--arch/ia64/mm/contig.c8
-rw-r--r--arch/ia64/mm/discontig.c35
-rw-r--r--arch/ia64/mm/hugetlbpage.c7
-rw-r--r--arch/ia64/mm/init.c18
-rw-r--r--arch/ia64/mm/ioremap.c43
-rw-r--r--arch/ia64/sn/kernel/io_init.c29
-rw-r--r--arch/ia64/sn/kernel/irq.c21
-rw-r--r--arch/ia64/sn/kernel/setup.c5
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_proc_fs.c39
-rw-r--r--arch/ia64/sn/kernel/tiocx.c10
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c17
-rw-r--r--arch/m32r/Kconfig8
-rw-r--r--arch/m32r/Kconfig.debug2
-rw-r--r--arch/m32r/Makefile5
-rw-r--r--arch/m32r/kernel/setup.c1
-rw-r--r--arch/m32r/mm/discontig.c7
-rw-r--r--arch/m32r/mm/init.c3
-rw-r--r--arch/m68k/Kconfig4
-rw-r--r--arch/m68k/bvme6000/config.c2
-rw-r--r--arch/m68k/mvme16x/rtc.c4
-rw-r--r--arch/m68knommu/Kconfig8
-rw-r--r--arch/mips/Kconfig8
-rw-r--r--arch/mips/au1000/common/setup.c2
-rw-r--r--arch/mips/ddb5xxx/common/rtc_ds1386.c4
-rw-r--r--arch/mips/dec/time.c51
-rw-r--r--arch/mips/ite-boards/generic/time.c4
-rw-r--r--arch/mips/ite-boards/ivr/init.c3
-rw-r--r--arch/mips/ite-boards/qed-4n-s01b/init.c3
-rw-r--r--arch/mips/jmr3927/common/rtc_ds1742.c4
-rw-r--r--arch/mips/kernel/irixsig.c4
-rw-r--r--arch/mips/kernel/linux32.c74
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S2
-rw-r--r--arch/mips/kernel/setup.c9
-rw-r--r--arch/mips/kernel/sysirix.c22
-rw-r--r--arch/mips/kernel/time.c22
-rw-r--r--arch/mips/lasat/setup.c7
-rw-r--r--arch/mips/lasat/sysctl.c63
-rw-r--r--arch/mips/mips-boards/atlas/atlas_setup.c2
-rw-r--r--arch/mips/mips-boards/generic/memory.c7
-rw-r--r--arch/mips/mips-boards/malta/malta_setup.c2
-rw-r--r--arch/mips/mips-boards/sim/sim_mem.c7
-rw-r--r--arch/mips/mm/init.c4
-rw-r--r--arch/mips/momentum/jaguar_atx/setup.c4
-rw-r--r--arch/mips/momentum/ocelot_3/setup.c38
-rw-r--r--arch/mips/momentum/ocelot_c/setup.c4
-rw-r--r--arch/mips/pmc-sierra/yosemite/setup.c4
-rw-r--r--arch/mips/sgi-ip22/ip22-reset.c2
-rw-r--r--arch/mips/sgi-ip22/ip22-time.c4
-rw-r--r--arch/mips/sgi-ip27/ip27-memory.c3
-rw-r--r--arch/mips/sgi-ip32/ip32-reset.c2
-rw-r--r--arch/mips/sgi-ip32/ip32-setup.c4
-rw-r--r--arch/mips/sibyte/swarm/setup.c8
-rw-r--r--arch/mips/sni/setup.c4
-rw-r--r--arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c4
-rw-r--r--arch/mips/tx4938/common/rtc_rx5c348.c16
-rw-r--r--arch/parisc/Kconfig8
-rw-r--r--arch/parisc/kernel/pdc_chassis.c3
-rw-r--r--arch/parisc/kernel/sys_parisc32.c58
-rw-r--r--arch/parisc/kernel/syscall_table.S2
-rw-r--r--arch/powerpc/Kconfig8
-rw-r--r--arch/powerpc/Kconfig.debug5
-rw-r--r--arch/powerpc/Makefile9
-rw-r--r--arch/powerpc/configs/cell_defconfig133
-rw-r--r--arch/powerpc/configs/mpc8540_ads_defconfig43
-rw-r--r--arch/powerpc/kernel/Makefile11
-rw-r--r--arch/powerpc/kernel/asm-offsets.c2
-rw-r--r--arch/powerpc/kernel/cpu_setup_6xx.S (renamed from arch/ppc/kernel/cpu_setup_6xx.S)0
-rw-r--r--arch/powerpc/kernel/entry_32.S8
-rw-r--r--arch/powerpc/kernel/entry_64.S6
-rw-r--r--arch/powerpc/kernel/firmware.c4
-rw-r--r--arch/powerpc/kernel/head_64.S32
-rw-r--r--arch/powerpc/kernel/idle.c (renamed from arch/powerpc/kernel/idle_64.c)79
-rw-r--r--arch/powerpc/kernel/idle_6xx.S18
-rw-r--r--arch/powerpc/kernel/idle_power4.S38
-rw-r--r--arch/powerpc/kernel/irq.c2
-rw-r--r--arch/powerpc/kernel/kprobes.c66
-rw-r--r--arch/powerpc/kernel/l2cr_6xx.S (renamed from arch/ppc/kernel/l2cr.S)0
-rw-r--r--arch/powerpc/kernel/legacy_serial.c42
-rw-r--r--arch/powerpc/kernel/lparcfg.c4
-rw-r--r--arch/powerpc/kernel/module_32.c (renamed from arch/ppc/kernel/module.c)0
-rw-r--r--arch/powerpc/kernel/nvram_64.c7
-rw-r--r--arch/powerpc/kernel/paca.c21
-rw-r--r--arch/powerpc/kernel/pci_32.c4
-rw-r--r--arch/powerpc/kernel/pci_64.c1
-rw-r--r--arch/powerpc/kernel/perfmon_fsl_booke.c (renamed from arch/ppc/kernel/perfmon_fsl_booke.c)0
-rw-r--r--arch/powerpc/kernel/proc_ppc64.c3
-rw-r--r--arch/powerpc/kernel/process.c13
-rw-r--r--arch/powerpc/kernel/prom.c154
-rw-r--r--arch/powerpc/kernel/prom_init.c68
-rw-r--r--arch/powerpc/kernel/rtas-proc.c2
-rw-r--r--arch/powerpc/kernel/rtas.c8
-rw-r--r--arch/powerpc/kernel/setup-common.c70
-rw-r--r--arch/powerpc/kernel/setup_32.c75
-rw-r--r--arch/powerpc/kernel/setup_64.c81
-rw-r--r--arch/powerpc/kernel/signal_32.c1
-rw-r--r--arch/powerpc/kernel/signal_64.c3
-rw-r--r--arch/powerpc/kernel/smp.c2
-rw-r--r--arch/powerpc/kernel/swsusp_32.S (renamed from arch/ppc/kernel/swsusp.S)0
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c73
-rw-r--r--arch/powerpc/kernel/syscalls.c1
-rw-r--r--arch/powerpc/kernel/sysfs.c12
-rw-r--r--arch/powerpc/kernel/tau_6xx.c (renamed from arch/ppc/kernel/temp.c)0
-rw-r--r--arch/powerpc/kernel/time.c4
-rw-r--r--arch/powerpc/kernel/traps.c51
-rw-r--r--arch/powerpc/kernel/vdso.c9
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S381
-rw-r--r--arch/powerpc/lib/sstep.c2
-rw-r--r--arch/powerpc/lib/strcase.c4
-rw-r--r--arch/powerpc/math-emu/Makefile (renamed from arch/ppc/math-emu/Makefile)0
-rw-r--r--arch/powerpc/math-emu/double.h (renamed from arch/ppc/math-emu/double.h)0
-rw-r--r--arch/powerpc/math-emu/fabs.c (renamed from arch/ppc/math-emu/fabs.c)0
-rw-r--r--arch/powerpc/math-emu/fadd.c (renamed from arch/ppc/math-emu/fadd.c)0
-rw-r--r--arch/powerpc/math-emu/fadds.c (renamed from arch/ppc/math-emu/fadds.c)0
-rw-r--r--arch/powerpc/math-emu/fcmpo.c (renamed from arch/ppc/math-emu/fcmpo.c)0
-rw-r--r--arch/powerpc/math-emu/fcmpu.c (renamed from arch/ppc/math-emu/fcmpu.c)0
-rw-r--r--arch/powerpc/math-emu/fctiw.c (renamed from arch/ppc/math-emu/fctiw.c)0
-rw-r--r--arch/powerpc/math-emu/fctiwz.c (renamed from arch/ppc/math-emu/fctiwz.c)0
-rw-r--r--arch/powerpc/math-emu/fdiv.c (renamed from arch/ppc/math-emu/fdiv.c)0
-rw-r--r--arch/powerpc/math-emu/fdivs.c (renamed from arch/ppc/math-emu/fdivs.c)0
-rw-r--r--arch/powerpc/math-emu/fmadd.c (renamed from arch/ppc/math-emu/fmadd.c)0
-rw-r--r--arch/powerpc/math-emu/fmadds.c (renamed from arch/ppc/math-emu/fmadds.c)0
-rw-r--r--arch/powerpc/math-emu/fmr.c (renamed from arch/ppc/math-emu/fmr.c)0
-rw-r--r--arch/powerpc/math-emu/fmsub.c (renamed from arch/ppc/math-emu/fmsub.c)0
-rw-r--r--arch/powerpc/math-emu/fmsubs.c (renamed from arch/ppc/math-emu/fmsubs.c)0
-rw-r--r--arch/powerpc/math-emu/fmul.c (renamed from arch/ppc/math-emu/fmul.c)0
-rw-r--r--arch/powerpc/math-emu/fmuls.c (renamed from arch/ppc/math-emu/fmuls.c)0
-rw-r--r--arch/powerpc/math-emu/fnabs.c (renamed from arch/ppc/math-emu/fnabs.c)0
-rw-r--r--arch/powerpc/math-emu/fneg.c (renamed from arch/ppc/math-emu/fneg.c)0
-rw-r--r--arch/powerpc/math-emu/fnmadd.c (renamed from arch/ppc/math-emu/fnmadd.c)0
-rw-r--r--arch/powerpc/math-emu/fnmadds.c (renamed from arch/ppc/math-emu/fnmadds.c)0
-rw-r--r--arch/powerpc/math-emu/fnmsub.c (renamed from arch/ppc/math-emu/fnmsub.c)0
-rw-r--r--arch/powerpc/math-emu/fnmsubs.c (renamed from arch/ppc/math-emu/fnmsubs.c)0
-rw-r--r--arch/powerpc/math-emu/fres.c (renamed from arch/ppc/math-emu/fres.c)0
-rw-r--r--arch/powerpc/math-emu/frsp.c (renamed from arch/ppc/math-emu/frsp.c)0
-rw-r--r--arch/powerpc/math-emu/frsqrte.c (renamed from arch/ppc/math-emu/frsqrte.c)0
-rw-r--r--arch/powerpc/math-emu/fsel.c (renamed from arch/ppc/math-emu/fsel.c)0
-rw-r--r--arch/powerpc/math-emu/fsqrt.c (renamed from arch/ppc/math-emu/fsqrt.c)0
-rw-r--r--arch/powerpc/math-emu/fsqrts.c (renamed from arch/ppc/math-emu/fsqrts.c)0
-rw-r--r--arch/powerpc/math-emu/fsub.c (renamed from arch/ppc/math-emu/fsub.c)0
-rw-r--r--arch/powerpc/math-emu/fsubs.c (renamed from arch/ppc/math-emu/fsubs.c)0
-rw-r--r--arch/powerpc/math-emu/lfd.c (renamed from arch/ppc/math-emu/lfd.c)0
-rw-r--r--arch/powerpc/math-emu/lfs.c (renamed from arch/ppc/math-emu/lfs.c)0
-rw-r--r--arch/powerpc/math-emu/math.c (renamed from arch/ppc/math-emu/math.c)0
-rw-r--r--arch/powerpc/math-emu/mcrfs.c (renamed from arch/ppc/math-emu/mcrfs.c)0
-rw-r--r--arch/powerpc/math-emu/mffs.c (renamed from arch/ppc/math-emu/mffs.c)0
-rw-r--r--arch/powerpc/math-emu/mtfsb0.c (renamed from arch/ppc/math-emu/mtfsb0.c)0
-rw-r--r--arch/powerpc/math-emu/mtfsb1.c (renamed from arch/ppc/math-emu/mtfsb1.c)0
-rw-r--r--arch/powerpc/math-emu/mtfsf.c (renamed from arch/ppc/math-emu/mtfsf.c)0
-rw-r--r--arch/powerpc/math-emu/mtfsfi.c (renamed from arch/ppc/math-emu/mtfsfi.c)0
-rw-r--r--arch/powerpc/math-emu/op-1.h (renamed from arch/ppc/math-emu/op-1.h)0
-rw-r--r--arch/powerpc/math-emu/op-2.h (renamed from arch/ppc/math-emu/op-2.h)0
-rw-r--r--arch/powerpc/math-emu/op-4.h (renamed from arch/ppc/math-emu/op-4.h)0
-rw-r--r--arch/powerpc/math-emu/op-common.h (renamed from arch/ppc/math-emu/op-common.h)0
-rw-r--r--arch/powerpc/math-emu/sfp-machine.h (renamed from arch/ppc/math-emu/sfp-machine.h)0
-rw-r--r--arch/powerpc/math-emu/single.h (renamed from arch/ppc/math-emu/single.h)0
-rw-r--r--arch/powerpc/math-emu/soft-fp.h (renamed from arch/ppc/math-emu/soft-fp.h)0
-rw-r--r--arch/powerpc/math-emu/stfd.c (renamed from arch/ppc/math-emu/stfd.c)0
-rw-r--r--arch/powerpc/math-emu/stfiwx.c (renamed from arch/ppc/math-emu/stfiwx.c)0
-rw-r--r--arch/powerpc/math-emu/stfs.c (renamed from arch/ppc/math-emu/stfs.c)0
-rw-r--r--arch/powerpc/math-emu/types.c (renamed from arch/ppc/math-emu/types.c)0
-rw-r--r--arch/powerpc/math-emu/udivmodti4.c (renamed from arch/ppc/math-emu/udivmodti4.c)0
-rw-r--r--arch/powerpc/mm/fault.c30
-rw-r--r--arch/powerpc/mm/hash_utils_64.c7
-rw-r--r--arch/powerpc/mm/imalloc.c18
-rw-r--r--arch/powerpc/mm/mem.c6
-rw-r--r--arch/powerpc/mm/numa.c2
-rw-r--r--arch/powerpc/mm/pgtable_32.c6
-rw-r--r--arch/powerpc/mm/stab.c2
-rw-r--r--arch/powerpc/oprofile/Makefile2
-rw-r--r--arch/powerpc/oprofile/backtrace.c126
-rw-r--r--arch/powerpc/oprofile/common.c9
-rw-r--r--arch/powerpc/oprofile/op_model_7450.c4
-rw-r--r--arch/powerpc/oprofile/op_model_fsl_booke.c4
-rw-r--r--arch/powerpc/oprofile/op_model_power4.c45
-rw-r--r--arch/powerpc/oprofile/op_model_rs64.c5
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig1
-rw-r--r--arch/powerpc/platforms/cell/Kconfig5
-rw-r--r--arch/powerpc/platforms/cell/Makefile10
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c133
-rw-r--r--arch/powerpc/platforms/cell/interrupt.h2
-rw-r--r--arch/powerpc/platforms/cell/iommu.c16
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c4
-rw-r--r--arch/powerpc/platforms/cell/setup.c11
-rw-r--r--arch/powerpc/platforms/cell/spider-pic.c108
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c39
-rw-r--r--arch/powerpc/platforms/cell/spu_callbacks.c345
-rw-r--r--arch/powerpc/platforms/cell/spufs/backing_ops.c47
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c24
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c523
-rw-r--r--arch/powerpc/platforms/cell/spufs/hw_ops.c57
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c8
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c91
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h28
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c3
-rw-r--r--arch/powerpc/platforms/chrp/chrp.h2
-rw-r--r--arch/powerpc/platforms/chrp/setup.c77
-rw-r--r--arch/powerpc/platforms/chrp/time.c22
-rw-r--r--arch/powerpc/platforms/iseries/setup.c13
-rw-r--r--arch/powerpc/platforms/maple/setup.c10
-rw-r--r--arch/powerpc/platforms/maple/time.c24
-rw-r--r--arch/powerpc/platforms/powermac/bootx_init.c6
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_64.c7
-rw-r--r--arch/powerpc/platforms/powermac/feature.c2
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c3
-rw-r--r--arch/powerpc/platforms/powermac/nvram.c14
-rw-r--r--arch/powerpc/platforms/powermac/pci.c5
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_base.c2
-rw-r--r--arch/powerpc/platforms/powermac/setup.c74
-rw-r--r--arch/powerpc/platforms/powermac/time.c4
-rw-r--r--arch/powerpc/platforms/powermac/udbg_scc.c2
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c2
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c16
-rw-r--r--arch/powerpc/platforms/pseries/firmware.c2
-rw-r--r--arch/powerpc/platforms/pseries/hvconsole.c5
-rw-r--r--arch/powerpc/platforms/pseries/pci.c2
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c11
-rw-r--r--arch/powerpc/platforms/pseries/ras.c2
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c15
-rw-r--r--arch/powerpc/platforms/pseries/rtasd.c3
-rw-r--r--arch/powerpc/platforms/pseries/setup.c231
-rw-r--r--arch/powerpc/platforms/pseries/xics.c4
-rw-r--r--arch/ppc/8xx_io/cs4218_tdm.c10
-rw-r--r--arch/ppc/Kconfig97
-rw-r--r--arch/ppc/Kconfig.debug7
-rw-r--r--arch/ppc/Makefile8
-rw-r--r--arch/ppc/boot/Makefile15
-rw-r--r--arch/ppc/boot/openfirmware/Makefile106
-rw-r--r--arch/ppc/boot/openfirmware/chrpmain.c101
-rw-r--r--arch/ppc/boot/openfirmware/common.c146
-rw-r--r--arch/ppc/boot/openfirmware/dummy.c4
-rw-r--r--arch/ppc/boot/openfirmware/misc.S67
-rw-r--r--arch/ppc/boot/openfirmware/start.c172
-rw-r--r--arch/ppc/boot/simple/mpc10x_memory.c4
-rw-r--r--arch/ppc/boot/simple/relocate.S2
-rw-r--r--arch/ppc/boot/utils/addnote.c175
-rw-r--r--arch/ppc/boot/utils/hack-coff.c84
-rw-r--r--arch/ppc/boot/utils/mknote.c44
-rw-r--r--arch/ppc/configs/ibmchrp_defconfig875
-rw-r--r--arch/ppc/configs/pmac_defconfig1591
-rw-r--r--arch/ppc/configs/power3_defconfig1035
-rw-r--r--arch/ppc/configs/prep_defconfig (renamed from arch/ppc/configs/common_defconfig)0
-rw-r--r--arch/ppc/kernel/Makefile28
-rw-r--r--arch/ppc/kernel/entry.S60
-rw-r--r--arch/ppc/kernel/head.S183
-rw-r--r--arch/ppc/kernel/idle.c112
-rw-r--r--arch/ppc/kernel/idle_6xx.S233
-rw-r--r--arch/ppc/kernel/idle_power4.S91
-rw-r--r--arch/ppc/kernel/pci.c396
-rw-r--r--arch/ppc/kernel/ppc_htab.c10
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c26
-rw-r--r--arch/ppc/kernel/setup.c256
-rw-r--r--arch/ppc/kernel/smp.c2
-rw-r--r--arch/ppc/lib/strcase.c3
-rw-r--r--arch/ppc/mm/fault.c30
-rw-r--r--arch/ppc/mm/hashtable.S34
-rw-r--r--arch/ppc/mm/init.c13
-rw-r--r--arch/ppc/mm/mmu_context.c2
-rw-r--r--arch/ppc/mm/pgtable.c8
-rw-r--r--arch/ppc/mm/ppc_mmu.c28
-rw-r--r--arch/ppc/platforms/Makefile12
-rw-r--r--arch/ppc/platforms/chrp_nvram.c83
-rw-r--r--arch/ppc/platforms/chrp_pci.c309
-rw-r--r--arch/ppc/platforms/chrp_pegasos_eth.c211
-rw-r--r--arch/ppc/platforms/chrp_setup.c669
-rw-r--r--arch/ppc/platforms/chrp_smp.c99
-rw-r--r--arch/ppc/platforms/chrp_time.c251
-rw-r--r--arch/ppc/platforms/lite5200.c71
-rw-r--r--arch/ppc/platforms/prep_setup.c14
-rw-r--r--arch/ppc/syslib/Makefile2
-rw-r--r--arch/ppc/syslib/mpc52xx_pci.c3
-rw-r--r--arch/ppc/syslib/mpc52xx_setup.c48
-rw-r--r--arch/ppc/syslib/open_pic.c2
-rw-r--r--arch/ppc/syslib/prom.c1429
-rw-r--r--arch/ppc/syslib/prom_init.c1011
-rw-r--r--arch/ppc/xmon/start.c2
-rw-r--r--arch/s390/Kconfig4
-rw-r--r--arch/s390/crypto/crypt_s390_query.c2
-rw-r--r--arch/s390/kernel/compat_linux.c74
-rw-r--r--arch/s390/kernel/compat_wrapper.S8
-rw-r--r--arch/s390/kernel/process.c11
-rw-r--r--arch/s390/kernel/syscalls.S2
-rw-r--r--arch/sh/Kconfig8
-rw-r--r--arch/sh/Makefile2
-rw-r--r--arch/sh/boards/mpc1211/rtc.c50
-rw-r--r--arch/sh/boards/sh03/rtc.c13
-rw-r--r--arch/sh/kernel/cpu/rtc.c10
-rw-r--r--arch/sh/kernel/setup.c5
-rw-r--r--arch/sh64/Kconfig8
-rw-r--r--arch/sh64/kernel/setup.c1
-rw-r--r--arch/sh64/kernel/time.c9
-rw-r--r--arch/sparc/Kconfig9
-rw-r--r--arch/sparc/kernel/irq.c66
-rw-r--r--arch/sparc/kernel/smp.c84
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c4
-rw-r--r--arch/sparc/kernel/sun4d_irq.c2
-rw-r--r--arch/sparc/kernel/sun4d_smp.c8
-rw-r--r--arch/sparc/kernel/sun4m_smp.c181
-rw-r--r--arch/sparc/mm/srmmu.c6
-rw-r--r--arch/sparc64/Kconfig8
-rw-r--r--arch/sparc64/Kconfig.debug2
-rw-r--r--arch/sparc64/defconfig39
-rw-r--r--arch/sparc64/kernel/kprobes.c69
-rw-r--r--arch/sparc64/kernel/smp.c5
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c15
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c74
-rw-r--r--arch/sparc64/kernel/systbls.S2
-rw-r--r--arch/sparc64/kernel/time.c16
-rw-r--r--arch/sparc64/kernel/traps.c17
-rw-r--r--arch/sparc64/lib/Makefile2
-rw-r--r--arch/sparc64/lib/find_bit.c127
-rw-r--r--arch/sparc64/mm/fault.c4
-rw-r--r--arch/um/Kconfig.i3865
-rw-r--r--arch/um/Kconfig.x86_645
-rw-r--r--arch/um/Makefile7
-rw-r--r--arch/um/drivers/mconsole_kern.c3
-rw-r--r--arch/um/drivers/ubd_kern.c76
-rw-r--r--arch/um/include/irq_user.h15
-rw-r--r--arch/um/include/kern.h2
-rw-r--r--arch/um/include/misc_constants.h6
-rw-r--r--arch/um/include/os.h36
-rw-r--r--arch/um/include/sigio.h3
-rw-r--r--arch/um/include/skas/mode-skas.h1
-rw-r--r--arch/um/include/skas/skas.h1
-rw-r--r--arch/um/include/user_util.h1
-rw-r--r--arch/um/kernel/Makefile9
-rw-r--r--arch/um/kernel/exec_kern.c2
-rw-r--r--arch/um/kernel/irq.c294
-rw-r--r--arch/um/kernel/irq_user.c412
-rw-r--r--arch/um/kernel/physmem.c3
-rw-r--r--arch/um/kernel/sigio_kern.c10
-rw-r--r--arch/um/kernel/smp.c15
-rw-r--r--arch/um/kernel/um_arch.c12
-rw-r--r--arch/um/os-Linux/Makefile13
-rw-r--r--arch/um/os-Linux/irq.c162
-rw-r--r--arch/um/os-Linux/sigio.c (renamed from arch/um/kernel/sigio_user.c)233
-rw-r--r--arch/um/os-Linux/start_up.c128
-rw-r--r--arch/um/os-Linux/tt.c10
-rw-r--r--arch/um/os-Linux/tty_log.c (renamed from arch/um/kernel/tty_log.c)18
-rw-r--r--arch/um/os-Linux/umid.c33
-rw-r--r--arch/um/sys-i386/ptrace.c15
-rw-r--r--arch/um/sys-i386/signal.c59
-rw-r--r--arch/um/sys-i386/user-offsets.c10
-rw-r--r--arch/um/sys-x86_64/ptrace.c22
-rw-r--r--arch/um/sys-x86_64/signal.c56
-rw-r--r--arch/um/sys-x86_64/user-offsets.c6
-rw-r--r--arch/v850/Kconfig6
-rw-r--r--arch/x86_64/Kconfig57
-rw-r--r--arch/x86_64/Makefile21
-rw-r--r--arch/x86_64/boot/Makefile36
-rw-r--r--arch/x86_64/defconfig34
-rw-r--r--arch/x86_64/ia32/ia32_binfmt.c2
-rw-r--r--arch/x86_64/ia32/ia32entry.S4
-rw-r--r--arch/x86_64/ia32/sys_ia32.c93
-rw-r--r--arch/x86_64/kernel/aperture.c4
-rw-r--r--arch/x86_64/kernel/apic.c20
-rw-r--r--arch/x86_64/kernel/entry.S2
-rw-r--r--arch/x86_64/kernel/functionlist1286
-rw-r--r--arch/x86_64/kernel/head.S26
-rw-r--r--arch/x86_64/kernel/io_apic.c10
-rw-r--r--arch/x86_64/kernel/kprobes.c65
-rw-r--r--arch/x86_64/kernel/mpparse.c19
-rw-r--r--arch/x86_64/kernel/nmi.c1
-rw-r--r--arch/x86_64/kernel/pci-dma.c3
-rw-r--r--arch/x86_64/kernel/pci-gart.c11
-rw-r--r--arch/x86_64/kernel/pmtimer.c3
-rw-r--r--arch/x86_64/kernel/process.c35
-rw-r--r--arch/x86_64/kernel/ptrace.c6
-rw-r--r--arch/x86_64/kernel/setup.c85
-rw-r--r--arch/x86_64/kernel/setup64.c18
-rw-r--r--arch/x86_64/kernel/smp.c6
-rw-r--r--arch/x86_64/kernel/smpboot.c24
-rw-r--r--arch/x86_64/kernel/time.c164
-rw-r--r--arch/x86_64/kernel/traps.c37
-rw-r--r--arch/x86_64/kernel/vmlinux.lds.S6
-rw-r--r--arch/x86_64/kernel/x8664_ksyms.c4
-rw-r--r--arch/x86_64/lib/thunk.S1
-rw-r--r--arch/x86_64/mm/fault.c79
-rw-r--r--arch/x86_64/mm/init.c38
-rw-r--r--arch/x86_64/mm/k8topology.c2
-rw-r--r--arch/x86_64/mm/numa.c39
-rw-r--r--arch/x86_64/mm/srat.c8
-rw-r--r--arch/xtensa/Kconfig8
-rw-r--r--arch/xtensa/platform-iss/setup.c2
-rw-r--r--block/Kconfig10
-rw-r--r--block/cfq-iosched.c359
-rw-r--r--block/elevator.c3
-rw-r--r--block/genhd.c6
-rw-r--r--block/ll_rw_blk.c39
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acpi/Kconfig3
-rw-r--r--drivers/acpi/blacklist.c27
-rw-r--r--drivers/acpi/osl.c64
-rw-r--r--drivers/acpi/processor_core.c2
-rw-r--r--drivers/acpi/processor_idle.c25
-rw-r--r--drivers/acpi/tables.c3
-rw-r--r--drivers/atm/.gitignore5
-rw-r--r--drivers/atm/lanai.c2
-rw-r--r--drivers/base/cpu.c9
-rw-r--r--drivers/base/memory.c8
-rw-r--r--drivers/block/DAC960.c27
-rw-r--r--drivers/block/Kconfig19
-rw-r--r--drivers/block/acsi_slm.c2
-rw-r--r--drivers/block/aoe/aoe.h14
-rw-r--r--drivers/block/aoe/aoeblk.c26
-rw-r--r--drivers/block/aoe/aoechr.c37
-rw-r--r--drivers/block/aoe/aoecmd.c187
-rw-r--r--drivers/block/aoe/aoedev.c69
-rw-r--r--drivers/block/aoe/aoemain.c4
-rw-r--r--drivers/block/aoe/aoenet.c22
-rw-r--r--drivers/block/ataflop.c4
-rw-r--r--drivers/block/cciss.c15
-rw-r--r--drivers/block/cciss_scsi.c5
-rw-r--r--drivers/block/cpqarray.c3
-rw-r--r--drivers/block/floppy.c34
-rw-r--r--drivers/block/loop.c4
-rw-r--r--drivers/block/nbd.c5
-rw-r--r--drivers/block/paride/bpck6.c3
-rw-r--r--drivers/block/paride/pd.c3
-rw-r--r--drivers/block/paride/pg.c8
-rw-r--r--drivers/block/paride/pt.c8
-rw-r--r--drivers/block/pktcdvd.c26
-rw-r--r--drivers/block/umem.c5
-rw-r--r--drivers/cdrom/cm206.c8
-rw-r--r--drivers/cdrom/sbpcd.c10
-rw-r--r--drivers/char/Kconfig20
-rw-r--r--drivers/char/Makefile91
-rw-r--r--drivers/char/agp/Kconfig4
-rw-r--r--drivers/char/agp/agp.h11
-rw-r--r--drivers/char/agp/ali-agp.c2
-rw-r--r--drivers/char/agp/alpha-agp.c14
-rw-r--r--drivers/char/agp/amd64-agp.c4
-rw-r--r--drivers/char/agp/ati-agp.c10
-rw-r--r--drivers/char/agp/backend.c2
-rw-r--r--drivers/char/agp/efficeon-agp.c16
-rw-r--r--drivers/char/agp/frontend.c2
-rw-r--r--drivers/char/agp/generic.c2
-rw-r--r--drivers/char/agp/hp-agp.c6
-rw-r--r--drivers/char/agp/i460-agp.c16
-rw-r--r--drivers/char/agp/intel-agp.c45
-rw-r--r--drivers/char/agp/isoch.c20
-rw-r--r--drivers/char/agp/nvidia-agp.c23
-rw-r--r--drivers/char/agp/sgi-agp.c2
-rw-r--r--drivers/char/agp/sis-agp.c8
-rw-r--r--drivers/char/agp/sworks-agp.c15
-rw-r--r--drivers/char/agp/uninorth-agp.c12
-rw-r--r--drivers/char/drm/drm_fops.c2
-rw-r--r--drivers/char/drm/i810_dma.c2
-rw-r--r--drivers/char/drm/i830_dma.c2
-rw-r--r--drivers/char/epca.c3
-rw-r--r--drivers/char/ftape/lowlevel/fdc-io.c2
-rw-r--r--drivers/char/generic_nvram.c5
-rw-r--r--drivers/char/hvc_console.c101
-rw-r--r--drivers/char/hvc_console.h63
-rw-r--r--drivers/char/hvc_rtas.c138
-rw-r--r--drivers/char/hvc_vio.c11
-rw-r--r--drivers/char/hvcs.c1
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c48
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c570
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c2
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c1064
-rw-r--r--drivers/char/ipmi/ipmi_si_sm.h3
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c8
-rw-r--r--drivers/char/istallion.c8
-rw-r--r--drivers/char/mem.c48
-rw-r--r--drivers/char/misc.c2
-rw-r--r--drivers/char/mxser.c8
-rw-r--r--drivers/char/mxser.h2
-rw-r--r--drivers/char/ppdev.c3
-rw-r--r--drivers/char/riscom8.c8
-rw-r--r--drivers/char/synclink.c33
-rw-r--r--drivers/char/synclink_gt.c250
-rw-r--r--drivers/char/sysrq.c250
-rw-r--r--drivers/char/tlclk.c1
-rw-r--r--drivers/char/tpm/tpm.h1
-rw-r--r--drivers/char/tty_io.c35
-rw-r--r--drivers/char/watchdog/Kconfig10
-rw-r--r--drivers/char/watchdog/Makefile1
-rw-r--r--drivers/char/watchdog/ep93xx_wdt.c257
-rw-r--r--drivers/cpufreq/cpufreq.c166
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c155
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c97
-rw-r--r--drivers/cpufreq/cpufreq_performance.c2
-rw-r--r--drivers/cpufreq/cpufreq_powersave.c2
-rw-r--r--drivers/cpufreq/cpufreq_stats.c8
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c12
-rw-r--r--drivers/cpufreq/freq_table.c12
-rw-r--r--drivers/dio/dio-driver.c9
-rw-r--r--drivers/edac/Kconfig10
-rw-r--r--drivers/edac/amd76x_edac.c126
-rw-r--r--drivers/edac/e752x_edac.c354
-rw-r--r--drivers/edac/e7xxx_edac.c228
-rw-r--r--drivers/edac/edac_mc.c810
-rw-r--r--drivers/edac/edac_mc.h133
-rw-r--r--drivers/edac/i82860_edac.c127
-rw-r--r--drivers/edac/i82875p_edac.c208
-rw-r--r--drivers/edac/r82600_edac.c140
-rw-r--r--drivers/eisa/.gitignore1
-rw-r--r--drivers/eisa/eisa-bus.c7
-rw-r--r--drivers/firmware/dcdbas.c19
-rw-r--r--drivers/firmware/efivars.c28
-rw-r--r--drivers/firmware/pcdp.c19
-rw-r--r--drivers/i2c/chips/Kconfig18
-rw-r--r--drivers/i2c/chips/Makefile2
-rw-r--r--drivers/i2c/chips/rtc8564.c385
-rw-r--r--drivers/i2c/chips/rtc8564.h78
-rw-r--r--drivers/ide/ide-cd.c1
-rw-r--r--drivers/ide/ide-tape.c5
-rw-r--r--drivers/ide/ide.c2
-rw-r--r--drivers/ide/pci/amd74xx.c8
-rw-r--r--drivers/ide/pci/generic.c3
-rw-r--r--drivers/ide/pci/sis5513.c2
-rw-r--r--drivers/ide/pci/via82cxxx.c2
-rw-r--r--drivers/ide/ppc/pmac.c2
-rw-r--r--drivers/ieee1394/dv1394.c41
-rw-r--r--drivers/ieee1394/highlevel.c3
-rw-r--r--drivers/ieee1394/ieee1394_core.c16
-rw-r--r--drivers/ieee1394/ieee1394_core.h3
-rw-r--r--drivers/ieee1394/ohci1394.c53
-rw-r--r--drivers/ieee1394/raw1394.c102
-rw-r--r--drivers/ieee1394/sbp2.c137
-rw-r--r--drivers/ieee1394/video1394.c16
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c61
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h15
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c44
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c5
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c6
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c145
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.h7
-rw-r--r--drivers/input/input.c2
-rw-r--r--drivers/input/serio/hil_mlc.c2
-rw-r--r--drivers/input/serio/hp_sdc_mlc.c7
-rw-r--r--drivers/input/touchscreen/ads7846.c1
-rw-r--r--drivers/isdn/Makefile1
-rw-r--r--drivers/isdn/capi/capi.c8
-rw-r--r--drivers/isdn/capi/kcapi_proc.c2
-rw-r--r--drivers/isdn/gigaset/Kconfig42
-rw-r--r--drivers/isdn/gigaset/Makefile6
-rw-r--r--drivers/isdn/gigaset/asyncdata.c597
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c2365
-rw-r--r--drivers/isdn/gigaset/common.c1203
-rw-r--r--drivers/isdn/gigaset/ev-layer.c1983
-rw-r--r--drivers/isdn/gigaset/gigaset.h938
-rw-r--r--drivers/isdn/gigaset/i4l.c567
-rw-r--r--drivers/isdn/gigaset/interface.c718
-rw-r--r--drivers/isdn/gigaset/isocdata.c1009
-rw-r--r--drivers/isdn/gigaset/proc.c81
-rw-r--r--drivers/isdn/gigaset/usb-gigaset.c1008
-rw-r--r--drivers/isdn/hardware/avm/avmcard.h4
-rw-r--r--drivers/isdn/hardware/avm/b1dma.c2
-rw-r--r--drivers/isdn/hardware/avm/b1isa.c4
-rw-r--r--drivers/isdn/hardware/avm/c4.c2
-rw-r--r--drivers/isdn/hardware/avm/t1isa.c6
-rw-r--r--drivers/isdn/hisax/hisax_fcpcipnp.c7
-rw-r--r--drivers/isdn/hisax/hisax_isac.c9
-rw-r--r--drivers/isdn/hisax/st5481_b.c4
-rw-r--r--drivers/isdn/hisax/st5481_d.c4
-rw-r--r--drivers/isdn/hysdn/boardergo.c31
-rw-r--r--drivers/isdn/hysdn/boardergo.h46
-rw-r--r--drivers/isdn/hysdn/hycapi.c4
-rw-r--r--drivers/isdn/hysdn/hysdn_boot.c28
-rw-r--r--drivers/isdn/hysdn/hysdn_defs.h71
-rw-r--r--drivers/isdn/hysdn/hysdn_init.c4
-rw-r--r--drivers/isdn/hysdn/hysdn_net.c8
-rw-r--r--drivers/isdn/hysdn/hysdn_pof.h12
-rw-r--r--drivers/isdn/hysdn/hysdn_procconf.c14
-rw-r--r--drivers/isdn/hysdn/hysdn_proclog.c10
-rw-r--r--drivers/isdn/hysdn/hysdn_sched.c11
-rw-r--r--drivers/isdn/hysdn/ince1pc.h18
-rw-r--r--drivers/isdn/i4l/Kconfig1
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c9
-rw-r--r--drivers/isdn/i4l/isdn_tty.c5
-rw-r--r--drivers/isdn/i4l/isdn_x25iface.c2
-rw-r--r--drivers/isdn/isdnloop/isdnloop.c2
-rw-r--r--drivers/macintosh/adb.c14
-rw-r--r--drivers/macintosh/adbhid.c7
-rw-r--r--drivers/macintosh/mediabay.c4
-rw-r--r--drivers/macintosh/smu.c9
-rw-r--r--drivers/macintosh/via-pmu.c2
-rw-r--r--drivers/macintosh/via-pmu68k.c7
-rw-r--r--drivers/macintosh/windfarm_core.c8
-rw-r--r--drivers/md/Kconfig26
-rw-r--r--drivers/md/bitmap.c18
-rw-r--r--drivers/md/dm-crypt.c31
-rw-r--r--drivers/md/dm-hw-handler.c3
-rw-r--r--drivers/md/dm-io.c13
-rw-r--r--drivers/md/dm-ioctl.c100
-rw-r--r--drivers/md/dm-linear.c8
-rw-r--r--drivers/md/dm-mpath.c3
-rw-r--r--drivers/md/dm-path-selector.c3
-rw-r--r--drivers/md/dm-raid1.c43
-rw-r--r--drivers/md/dm-snap.c412
-rw-r--r--drivers/md/dm-stripe.c13
-rw-r--r--drivers/md/dm-table.c59
-rw-r--r--drivers/md/dm.c94
-rw-r--r--drivers/md/dm.h23
-rw-r--r--drivers/md/kcopyd.c47
-rw-r--r--drivers/md/md.c235
-rw-r--r--drivers/md/multipath.c17
-rw-r--r--drivers/md/raid1.c27
-rw-r--r--drivers/md/raid5.c719
-rw-r--r--drivers/md/raid6main.c14
-rw-r--r--drivers/media/Kconfig14
-rw-r--r--drivers/media/common/saa7146_fops.c5
-rw-r--r--drivers/media/common/saa7146_vbi.c8
-rw-r--r--drivers/media/common/saa7146_video.c8
-rw-r--r--drivers/media/dvb/b2c2/flexcop-usb.c1
-rw-r--r--drivers/media/dvb/bt8xx/Makefile2
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c2
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c24
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.h2
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c5
-rw-r--r--drivers/media/video/Kconfig258
-rw-r--r--drivers/media/video/Makefile26
-rw-r--r--drivers/media/video/adv7170.c10
-rw-r--r--drivers/media/video/adv7175.c6
-rw-r--r--drivers/media/video/arv.c54
-rw-r--r--drivers/media/video/bt819.c10
-rw-r--r--drivers/media/video/bt856.c4
-rw-r--r--drivers/media/video/bt8xx/Kconfig25
-rw-r--r--drivers/media/video/bt8xx/Makefile12
-rw-r--r--drivers/media/video/bt8xx/bt832.c (renamed from drivers/media/video/bt832.c)3
-rw-r--r--drivers/media/video/bt8xx/bt832.h (renamed from drivers/media/video/bt832.h)0
-rw-r--r--drivers/media/video/bt8xx/bt848.h (renamed from drivers/media/video/bt848.h)0
-rw-r--r--drivers/media/video/bt8xx/bttv-cards.c (renamed from drivers/media/video/bttv-cards.c)315
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c (renamed from drivers/media/video/bttv-driver.c)149
-rw-r--r--drivers/media/video/bt8xx/bttv-gpio.c (renamed from drivers/media/video/bttv-gpio.c)0
-rw-r--r--drivers/media/video/bt8xx/bttv-i2c.c (renamed from drivers/media/video/bttv-i2c.c)4
-rw-r--r--drivers/media/video/bt8xx/bttv-if.c (renamed from drivers/media/video/bttv-if.c)0
-rw-r--r--drivers/media/video/bt8xx/bttv-input.c (renamed from drivers/media/video/bttv-input.c)0
-rw-r--r--drivers/media/video/bt8xx/bttv-risc.c (renamed from drivers/media/video/bttv-risc.c)4
-rw-r--r--drivers/media/video/bt8xx/bttv-vbi.c (renamed from drivers/media/video/bttv-vbi.c)6
-rw-r--r--drivers/media/video/bt8xx/bttv.h (renamed from drivers/media/video/bttv.h)23
-rw-r--r--drivers/media/video/bt8xx/bttvp.h (renamed from drivers/media/video/bttvp.h)7
-rw-r--r--drivers/media/video/bw-qcam.c106
-rw-r--r--drivers/media/video/c-qcam.c66
-rw-r--r--drivers/media/video/cpia.c656
-rw-r--r--drivers/media/video/cpia.h52
-rw-r--r--drivers/media/video/cpia2/cpia2.h2
-rw-r--r--drivers/media/video/cpia2/cpia2_core.c40
-rw-r--r--drivers/media/video/cpia2/cpia2_v4l.c43
-rw-r--r--drivers/media/video/cpia_pp.c106
-rw-r--r--drivers/media/video/cpia_usb.c40
-rw-r--r--drivers/media/video/cs53l32a.c20
-rw-r--r--drivers/media/video/cs8420.h2
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c1
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c51
-rw-r--r--drivers/media/video/cx88/Kconfig5
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c4
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c5
-rw-r--r--drivers/media/video/cx88/cx88-core.c6
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c5
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c28
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c3
-rw-r--r--drivers/media/video/cx88/cx88-vbi.c7
-rw-r--r--drivers/media/video/cx88/cx88-video.c35
-rw-r--r--drivers/media/video/cx88/cx88.h7
-rw-r--r--drivers/media/video/dabfirmware.h (renamed from drivers/usb/media/dabfirmware.h)0
-rw-r--r--drivers/media/video/dabusb.c (renamed from drivers/usb/media/dabusb.c)18
-rw-r--r--drivers/media/video/dabusb.h (renamed from drivers/usb/media/dabusb.h)4
-rw-r--r--drivers/media/video/dsbr100.c (renamed from drivers/usb/media/dsbr100.c)44
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c9
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c8
-rw-r--r--drivers/media/video/et61x251/Makefile4
-rw-r--r--drivers/media/video/et61x251/et61x251.h (renamed from drivers/usb/media/et61x251.h)8
-rw-r--r--drivers/media/video/et61x251/et61x251_core.c (renamed from drivers/usb/media/et61x251_core.c)210
-rw-r--r--drivers/media/video/et61x251/et61x251_sensor.h (renamed from drivers/usb/media/et61x251_sensor.h)20
-rw-r--r--drivers/media/video/et61x251/et61x251_tas5130d1b.c (renamed from drivers/usb/media/et61x251_tas5130d1b.c)10
-rw-r--r--drivers/media/video/font.h407
-rw-r--r--drivers/media/video/msp3400-driver.c249
-rw-r--r--drivers/media/video/msp3400-driver.h (renamed from drivers/media/video/msp3400.h)30
-rw-r--r--drivers/media/video/msp3400-kthreads.c331
-rw-r--r--drivers/media/video/mxb.c12
-rw-r--r--drivers/media/video/ov511.c (renamed from drivers/usb/media/ov511.c)92
-rw-r--r--drivers/media/video/ov511.h (renamed from drivers/usb/media/ov511.h)8
-rw-r--r--drivers/media/video/ovcamchip/Makefile2
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_core.c6
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_priv.h2
-rw-r--r--drivers/media/video/planb.c130
-rw-r--r--drivers/media/video/planb.h6
-rw-r--r--drivers/media/video/pms.c136
-rw-r--r--drivers/media/video/pwc/Makefile (renamed from drivers/usb/media/pwc/Makefile)2
-rw-r--r--drivers/media/video/pwc/philips.txt (renamed from drivers/usb/media/pwc/philips.txt)66
-rw-r--r--drivers/media/video/pwc/pwc-ctrl.c (renamed from drivers/usb/media/pwc/pwc-ctrl.c)374
-rw-r--r--drivers/media/video/pwc/pwc-if.c (renamed from drivers/usb/media/pwc/pwc-if.c)302
-rw-r--r--drivers/media/video/pwc/pwc-ioctl.h (renamed from drivers/usb/media/pwc/pwc-ioctl.h)40
-rw-r--r--drivers/media/video/pwc/pwc-kiara.c318
-rw-r--r--drivers/media/video/pwc/pwc-kiara.h (renamed from drivers/usb/media/pwc/pwc-kiara.h)0
-rw-r--r--drivers/media/video/pwc/pwc-misc.c (renamed from drivers/usb/media/pwc/pwc-misc.c)26
-rw-r--r--drivers/media/video/pwc/pwc-nala.h (renamed from drivers/usb/media/pwc/pwc-nala.h)2
-rw-r--r--drivers/media/video/pwc/pwc-timon.c316
-rw-r--r--drivers/media/video/pwc/pwc-timon.h (renamed from drivers/usb/media/pwc/pwc-timon.h)0
-rw-r--r--drivers/media/video/pwc/pwc-uncompress.c (renamed from drivers/usb/media/pwc/pwc-uncompress.c)6
-rw-r--r--drivers/media/video/pwc/pwc-uncompress.h (renamed from drivers/usb/media/pwc/pwc-uncompress.h)2
-rw-r--r--drivers/media/video/pwc/pwc.h (renamed from drivers/usb/media/pwc/pwc.h)4
-rw-r--r--drivers/media/video/saa5249.c112
-rw-r--r--drivers/media/video/saa6588.c2
-rw-r--r--drivers/media/video/saa7110.c4
-rw-r--r--drivers/media/video/saa7111.c4
-rw-r--r--drivers/media/video/saa7114.c12
-rw-r--r--drivers/media/video/saa7115.c1
-rw-r--r--drivers/media/video/saa7121.h6
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c10
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c6
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c6
-rw-r--r--drivers/media/video/saa7134/saa7134-ts.c9
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-vbi.c10
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c9
-rw-r--r--drivers/media/video/saa7134/saa7134.h3
-rw-r--r--drivers/media/video/saa7146.h10
-rw-r--r--drivers/media/video/saa7146reg.h4
-rw-r--r--drivers/media/video/saa7185.c4
-rw-r--r--drivers/media/video/saa7196.h4
-rw-r--r--drivers/media/video/se401.c (renamed from drivers/usb/media/se401.c)216
-rw-r--r--drivers/media/video/se401.h (renamed from drivers/usb/media/se401.h)6
-rw-r--r--drivers/media/video/sn9c102/Makefile7
-rw-r--r--drivers/media/video/sn9c102/sn9c102.h (renamed from drivers/usb/media/sn9c102.h)8
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c (renamed from drivers/usb/media/sn9c102_core.c)264
-rw-r--r--drivers/media/video/sn9c102/sn9c102_hv7131d.c (renamed from drivers/usb/media/sn9c102_hv7131d.c)16
-rw-r--r--drivers/media/video/sn9c102/sn9c102_mi0343.c (renamed from drivers/usb/media/sn9c102_mi0343.c)106
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7630.c (renamed from drivers/usb/media/sn9c102_ov7630.c)14
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas106b.c (renamed from drivers/usb/media/sn9c102_pas106b.c)16
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas202bca.c (renamed from drivers/usb/media/sn9c102_pas202bca.c)6
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas202bcb.c (renamed from drivers/usb/media/sn9c102_pas202bcb.c)18
-rw-r--r--drivers/media/video/sn9c102/sn9c102_sensor.h (renamed from drivers/usb/media/sn9c102_sensor.h)70
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5110c1b.c (renamed from drivers/usb/media/sn9c102_tas5110c1b.c)12
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5130d1b.c (renamed from drivers/usb/media/sn9c102_tas5130d1b.c)12
-rw-r--r--drivers/media/video/stradis.c10
-rw-r--r--drivers/media/video/stv680.c (renamed from drivers/usb/media/stv680.c)48
-rw-r--r--drivers/media/video/stv680.h (renamed from drivers/usb/media/stv680.h)142
-rw-r--r--drivers/media/video/tda7432.c5
-rw-r--r--drivers/media/video/tda9840.c4
-rw-r--r--drivers/media/video/tda9840.h2
-rw-r--r--drivers/media/video/tda9875.c9
-rw-r--r--drivers/media/video/tea6415c.c2
-rw-r--r--drivers/media/video/tea6420.c4
-rw-r--r--drivers/media/video/tea6420.h4
-rw-r--r--drivers/media/video/tuner-3036.c50
-rw-r--r--drivers/media/video/tuner-core.c1
-rw-r--r--drivers/media/video/tvaudio.c154
-rw-r--r--drivers/media/video/tvaudio.h14
-rw-r--r--drivers/media/video/tveeprom.c30
-rw-r--r--drivers/media/video/usbvideo/Makefile4
-rw-r--r--drivers/media/video/usbvideo/ibmcam.c (renamed from drivers/usb/media/ibmcam.c)10
-rw-r--r--drivers/media/video/usbvideo/konicawc.c (renamed from drivers/usb/media/konicawc.c)48
-rw-r--r--drivers/media/video/usbvideo/ultracam.c (renamed from drivers/usb/media/ultracam.c)2
-rw-r--r--drivers/media/video/usbvideo/usbvideo.c (renamed from drivers/usb/media/usbvideo.c)42
-rw-r--r--drivers/media/video/usbvideo/usbvideo.h (renamed from drivers/usb/media/usbvideo.h)10
-rw-r--r--drivers/media/video/usbvideo/vicam.c (renamed from drivers/usb/media/vicam.c)28
-rw-r--r--drivers/media/video/v4l2-common.c38
-rw-r--r--drivers/media/video/video-buf.c250
-rw-r--r--drivers/media/video/videocodec.h52
-rw-r--r--drivers/media/video/videodev.c2
-rw-r--r--drivers/media/video/vino.c4
-rw-r--r--drivers/media/video/vivi.c1454
-rw-r--r--drivers/media/video/vpx3220.c20
-rw-r--r--drivers/media/video/w9966.c102
-rw-r--r--drivers/media/video/w9968cf.c (renamed from drivers/usb/media/w9968cf.c)930
-rw-r--r--drivers/media/video/w9968cf.h (renamed from drivers/usb/media/w9968cf.h)12
-rw-r--r--drivers/media/video/w9968cf_decoder.h (renamed from drivers/usb/media/w9968cf_decoder.h)8
-rw-r--r--drivers/media/video/w9968cf_vpp.h (renamed from drivers/usb/media/w9968cf_vpp.h)2
-rw-r--r--drivers/media/video/wm8775.c20
-rw-r--r--drivers/media/video/zc0301/Makefile3
-rw-r--r--drivers/media/video/zc0301/zc0301.h (renamed from drivers/usb/media/zc0301.h)6
-rw-r--r--drivers/media/video/zc0301/zc0301_core.c (renamed from drivers/usb/media/zc0301_core.c)148
-rw-r--r--drivers/media/video/zc0301/zc0301_pas202bcb.c (renamed from drivers/usb/media/zc0301_pas202bcb.c)12
-rw-r--r--drivers/media/video/zc0301/zc0301_sensor.h (renamed from drivers/usb/media/zc0301_sensor.h)4
-rw-r--r--drivers/media/video/zoran.h2
-rw-r--r--drivers/media/video/zoran_card.c2
-rw-r--r--drivers/media/video/zoran_card.h2
-rw-r--r--drivers/media/video/zoran_device.c16
-rw-r--r--drivers/media/video/zoran_device.h2
-rw-r--r--drivers/media/video/zoran_driver.c16
-rw-r--r--drivers/media/video/zoran_procfs.c2
-rw-r--r--drivers/media/video/zoran_procfs.h2
-rw-r--r--drivers/media/video/zr36016.c22
-rw-r--r--drivers/media/video/zr36050.c16
-rw-r--r--drivers/media/video/zr36057.h10
-rw-r--r--drivers/media/video/zr36060.c20
-rw-r--r--drivers/media/video/zr36120.c54
-rw-r--r--drivers/media/video/zr36120.h6
-rw-r--r--drivers/message/i2o/debug.c31
-rw-r--r--drivers/message/i2o/i2o_block.c7
-rw-r--r--drivers/message/i2o/i2o_proc.c2
-rw-r--r--drivers/misc/ibmasm/heartbeat.c5
-rw-r--r--drivers/misc/ibmasm/ibmasmfs.c2
-rw-r--r--drivers/mmc/au1xmmc.c2
-rw-r--r--drivers/mtd/chips/Kconfig5
-rw-r--r--drivers/mtd/maps/dilnetpc.c8
-rw-r--r--drivers/mtd/maps/pcmciamtd.c14
-rw-r--r--drivers/mtd/mtd_blkdevs.c3
-rw-r--r--drivers/mtd/mtdconcat.c6
-rw-r--r--drivers/net/3c59x.c265
-rw-r--r--drivers/net/a2065.c2
-rw-r--r--drivers/net/ariadne.c2
-rw-r--r--drivers/net/arm/Kconfig8
-rw-r--r--drivers/net/arm/Makefile1
-rw-r--r--drivers/net/arm/at91_ether.c1110
-rw-r--r--drivers/net/arm/at91_ether.h101
-rw-r--r--drivers/net/atari_bionet.c2
-rw-r--r--drivers/net/atari_pamsnet.c2
-rw-r--r--drivers/net/atarilance.c2
-rw-r--r--drivers/net/bonding/bond_main.c2
-rw-r--r--drivers/net/cassini.c11
-rw-r--r--drivers/net/chelsio/cxgb2.c2
-rw-r--r--drivers/net/dgrs.c14
-rw-r--r--drivers/net/fec_8xx/fec_main.c4
-rw-r--r--drivers/net/forcedeth.c3
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c4
-rw-r--r--drivers/net/gt96100eth.c4
-rw-r--r--drivers/net/hamradio/dmascc.c2
-rw-r--r--drivers/net/hamradio/mkiss.c2
-rw-r--r--drivers/net/hplance.c2
-rw-r--r--drivers/net/hydra.c2
-rw-r--r--drivers/net/ioc3-eth.c7
-rw-r--r--drivers/net/irda/irport.c4
-rw-r--r--drivers/net/irda/nsc-ircc.c4
-rw-r--r--drivers/net/lasi_82596.c6
-rw-r--r--drivers/net/loopback.c2
-rw-r--r--drivers/net/mac89x0.c2
-rw-r--r--drivers/net/mace.c2
-rw-r--r--drivers/net/meth.c2
-rw-r--r--drivers/net/ne-h8300.c6
-rw-r--r--drivers/net/ne2k-pci.c2
-rw-r--r--drivers/net/ni5010.c4
-rw-r--r--drivers/net/ns83820.c6
-rw-r--r--drivers/net/sis900.c6
-rw-r--r--drivers/net/sun3lance.c2
-rw-r--r--drivers/net/tg3.c118
-rw-r--r--drivers/net/tulip/de4x5.c4
-rw-r--r--drivers/net/tulip/pnic2.c2
-rw-r--r--drivers/net/typhoon.c4
-rw-r--r--drivers/net/wan/dscc4.c7
-rw-r--r--drivers/net/wan/wanxl.c4
-rw-r--r--drivers/net/wireless/Kconfig1
-rw-r--r--drivers/net/wireless/orinoco.c2
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c2
-rw-r--r--drivers/net/wireless/prism54/islpci_hotplug.c3
-rw-r--r--drivers/net/zorro8390.c2
-rw-r--r--drivers/oprofile/cpu_buffer.c13
-rw-r--r--drivers/oprofile/oprofile_stats.c4
-rw-r--r--drivers/oprofile/oprofilefs.c6
-rw-r--r--drivers/parisc/led.c14
-rw-r--r--drivers/parisc/power.c6
-rw-r--r--drivers/parisc/sba_iommu.c10
-rw-r--r--drivers/parisc/superio.c7
-rw-r--r--drivers/parport/parport_pc.c31
-rw-r--r--drivers/parport/share.c19
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c12
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c19
-rw-r--r--drivers/pnp/card.c16
-rw-r--r--drivers/pnp/driver.c19
-rw-r--r--drivers/pnp/isapnp/core.c11
-rw-r--r--drivers/rtc/Kconfig165
-rw-r--r--drivers/rtc/Makefile21
-rw-r--r--drivers/rtc/class.c145
-rw-r--r--drivers/rtc/hctosys.c69
-rw-r--r--drivers/rtc/interface.c277
-rw-r--r--drivers/rtc/rtc-dev.c382
-rw-r--r--drivers/rtc/rtc-ds1672.c233
-rw-r--r--drivers/rtc/rtc-ep93xx.c162
-rw-r--r--drivers/rtc/rtc-lib.c101
-rw-r--r--drivers/rtc/rtc-m48t86.c209
-rw-r--r--drivers/rtc/rtc-pcf8563.c353
-rw-r--r--drivers/rtc/rtc-proc.c162
-rw-r--r--drivers/rtc/rtc-rs5c372.c294
-rw-r--r--drivers/rtc/rtc-sa1100.c388
-rw-r--r--drivers/rtc/rtc-sysfs.c124
-rw-r--r--drivers/rtc/rtc-test.c204
-rw-r--r--drivers/rtc/rtc-x1205.c (renamed from drivers/i2c/chips/x1205.c)453
-rw-r--r--drivers/s390/block/dasd.c11
-rw-r--r--drivers/s390/block/dasd_devmap.c9
-rw-r--r--drivers/s390/char/raw3270.c39
-rw-r--r--drivers/s390/scsi/zfcp_aux.c60
-rw-r--r--drivers/scsi/3w-9xxx.c2
-rw-r--r--drivers/scsi/BusLogic.c10
-rw-r--r--drivers/scsi/a100u2w.c3
-rw-r--r--drivers/scsi/aacraid/aachba.c1
-rw-r--r--drivers/scsi/aacraid/linit.c5
-rw-r--r--drivers/scsi/arm/cumana_2.c2
-rw-r--r--drivers/scsi/arm/eesox.c2
-rw-r--r--drivers/scsi/arm/powertec.c2
-rw-r--r--drivers/scsi/atari_scsi.c10
-rw-r--r--drivers/scsi/atp870u.c3
-rw-r--r--drivers/scsi/dpt_i2o.c5
-rw-r--r--drivers/scsi/eata.c3
-rw-r--r--drivers/scsi/gdth.c16
-rw-r--r--drivers/scsi/initio.c3
-rw-r--r--drivers/scsi/ips.c5
-rw-r--r--drivers/scsi/iscsi_tcp.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c22
-rw-r--r--drivers/scsi/megaraid.c7
-rw-r--r--drivers/scsi/mesh.c2
-rw-r--r--drivers/scsi/nsp32.c3
-rw-r--r--drivers/scsi/osst.c5
-rw-r--r--drivers/scsi/ppa.c3
-rw-r--r--drivers/scsi/qla1280.c5
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c3
-rw-r--r--drivers/scsi/qlogicfc.c8
-rw-r--r--drivers/scsi/qlogicpti.c3
-rw-r--r--drivers/scsi/scsi_lib.c5
-rw-r--r--drivers/scsi/sd.c2
-rw-r--r--drivers/serial/8250.c2
-rw-r--r--drivers/serial/8250_acpi.c183
-rw-r--r--drivers/serial/8250_au1x00.c2
-rw-r--r--drivers/serial/8250_hp300.c10
-rw-r--r--drivers/serial/Kconfig25
-rw-r--r--drivers/serial/Makefile2
-rw-r--r--drivers/serial/amba-pl010.c270
-rw-r--r--drivers/serial/au1x00_uart.c1287
-rw-r--r--drivers/serial/ioc4_serial.c387
-rw-r--r--drivers/serial/mpc52xx_uart.c2
-rw-r--r--drivers/serial/mpsc.c260
-rw-r--r--drivers/serial/mpsc.h289
-rw-r--r--drivers/serial/serial_txx9.c2
-rw-r--r--drivers/serial/sunsu.c2
-rw-r--r--drivers/telephony/phonedev.c23
-rw-r--r--drivers/usb/Kconfig2
-rw-r--r--drivers/usb/Makefile14
-rw-r--r--drivers/usb/core/file.c6
-rw-r--r--drivers/usb/core/hcd-pci.c4
-rw-r--r--drivers/usb/core/notify.c65
-rw-r--r--drivers/usb/gadget/inode.c6
-rw-r--r--drivers/usb/host/ohci-s3c2410.c2
-rw-r--r--drivers/usb/media/Kconfig241
-rw-r--r--drivers/usb/media/Makefile24
-rw-r--r--drivers/usb/media/pwc/pwc-kiara.c318
-rw-r--r--drivers/usb/media/pwc/pwc-timon.c316
-rw-r--r--drivers/usb/net/zaurus.c2
-rw-r--r--drivers/usb/serial/option.c2
-rw-r--r--drivers/video/Kconfig27
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/acornfb.c8
-rw-r--r--drivers/video/asiliantfb.c14
-rw-r--r--drivers/video/aty/aty128fb.c11
-rw-r--r--drivers/video/aty/atyfb_base.c23
-rw-r--r--drivers/video/aty/mach64_gx.c3
-rw-r--r--drivers/video/aty/radeon_base.c6
-rw-r--r--drivers/video/aty/radeon_pm.c4
-rw-r--r--drivers/video/au1200fb.c3844
-rw-r--r--drivers/video/au1200fb.h572
-rw-r--r--drivers/video/backlight/locomolcd.c23
-rw-r--r--drivers/video/bw2.c3
-rw-r--r--drivers/video/chipsfb.c14
-rw-r--r--drivers/video/cirrusfb.c6
-rw-r--r--drivers/video/console/Kconfig24
-rw-r--r--drivers/video/console/fonts.c2
-rw-r--r--drivers/video/console/newport_con.c4
-rw-r--r--drivers/video/console/vgacon.c271
-rw-r--r--drivers/video/fbcmap.c4
-rw-r--r--drivers/video/fbmem.c31
-rw-r--r--drivers/video/fbmon.c6
-rw-r--r--drivers/video/fbsysfs.c4
-rw-r--r--drivers/video/ffb.c3
-rw-r--r--drivers/video/geode/Kconfig17
-rw-r--r--drivers/video/geode/Makefile4
-rw-r--r--drivers/video/geode/display_gx.c156
-rw-r--r--drivers/video/geode/display_gx.h96
-rw-r--r--drivers/video/geode/gxfb_core.c423
-rw-r--r--drivers/video/geode/video_gx.c262
-rw-r--r--drivers/video/geode/video_gx.h47
-rw-r--r--drivers/video/hpfb.c4
-rw-r--r--drivers/video/i810/i810-i2c.c3
-rw-r--r--drivers/video/imsttfb.c32
-rw-r--r--drivers/video/macmodes.c2
-rw-r--r--drivers/video/matrox/matroxfb_DAC1064.c1
-rw-r--r--drivers/video/matrox/matroxfb_DAC1064.h1
-rw-r--r--drivers/video/matrox/matroxfb_Ti3026.c1
-rw-r--r--drivers/video/matrox/matroxfb_Ti3026.h1
-rw-r--r--drivers/video/matrox/matroxfb_base.c4
-rw-r--r--drivers/video/matrox/matroxfb_g450.c2
-rw-r--r--drivers/video/matrox/matroxfb_maven.c78
-rw-r--r--drivers/video/matrox/matroxfb_misc.c1
-rw-r--r--drivers/video/modedb.c6
-rw-r--r--drivers/video/neofb.c8
-rw-r--r--drivers/video/nvidia/nv_accel.c12
-rw-r--r--drivers/video/nvidia/nv_i2c.c3
-rw-r--r--drivers/video/nvidia/nv_type.h1
-rw-r--r--drivers/video/nvidia/nvidia.c124
-rw-r--r--drivers/video/pm3fb.c18
-rw-r--r--drivers/video/pmagb-b-fb.c2
-rw-r--r--drivers/video/radeonfb.c4
-rw-r--r--drivers/video/riva/fbdev.c11
-rw-r--r--drivers/video/savage/savagefb-i2c.c3
-rw-r--r--drivers/video/sis/init301.c11
-rw-r--r--drivers/video/sstfb.c13
-rw-r--r--drivers/video/virgefb.c3
-rw-r--r--drivers/w1/masters/matrox_w1.c2
-rw-r--r--drivers/zorro/zorro-driver.c9
-rw-r--r--fs/9p/9p.h9
-rw-r--r--fs/9p/Makefile10
-rw-r--r--fs/9p/conv.c13
-rw-r--r--fs/9p/conv.h8
-rw-r--r--fs/9p/debug.h6
-rw-r--r--fs/9p/error.c5
-rw-r--r--fs/9p/error.h5
-rw-r--r--fs/9p/fcall.c (renamed from fs/9p/9p.c)20
-rw-r--r--fs/9p/fcprint.c346
-rw-r--r--fs/9p/fid.c5
-rw-r--r--fs/9p/fid.h5
-rw-r--r--fs/9p/mux.c32
-rw-r--r--fs/9p/mux.h5
-rw-r--r--fs/9p/trans_fd.c301
-rw-r--r--fs/9p/trans_sock.c334
-rw-r--r--fs/9p/transport.h5
-rw-r--r--fs/9p/v9fs.c15
-rw-r--r--fs/9p/v9fs.h8
-rw-r--r--fs/9p/v9fs_vfs.h9
-rw-r--r--fs/9p/vfs_addr.c5
-rw-r--r--fs/9p/vfs_dentry.c7
-rw-r--r--fs/9p/vfs_dir.c7
-rw-r--r--fs/9p/vfs_file.c39
-rw-r--r--fs/9p/vfs_inode.c56
-rw-r--r--fs/9p/vfs_super.c7
-rw-r--r--fs/Kconfig1
-rw-r--r--fs/adfs/adfs.h4
-rw-r--r--fs/adfs/dir.c2
-rw-r--r--fs/adfs/file.c2
-rw-r--r--fs/affs/affs.h6
-rw-r--r--fs/affs/dir.c2
-rw-r--r--fs/affs/file.c2
-rw-r--r--fs/afs/dir.c2
-rw-r--r--fs/afs/file.c6
-rw-r--r--fs/afs/internal.h4
-rw-r--r--fs/afs/mntpt.c2
-rw-r--r--fs/afs/proc.c10
-rw-r--r--fs/aio.c3
-rw-r--r--fs/autofs/autofs_i.h2
-rw-r--r--fs/autofs/dirhash.c2
-rw-r--r--fs/autofs/root.c2
-rw-r--r--fs/autofs4/autofs_i.h54
-rw-r--r--fs/autofs4/expire.c292
-rw-r--r--fs/autofs4/inode.c103
-rw-r--r--fs/autofs4/root.c328
-rw-r--r--fs/autofs4/waitq.c111
-rw-r--r--fs/bad_inode.c2
-rw-r--r--fs/befs/datastream.c2
-rw-r--r--fs/befs/linuxvfs.c2
-rw-r--r--fs/bfs/bfs.h4
-rw-r--r--fs/bfs/dir.c2
-rw-r--r--fs/bfs/file.c2
-rw-r--r--fs/binfmt_elf.c18
-rw-r--r--fs/binfmt_elf_fdpic.c3
-rw-r--r--fs/binfmt_flat.c73
-rw-r--r--fs/binfmt_misc.c6
-rw-r--r--fs/bio.c32
-rw-r--r--fs/block_dev.c306
-rw-r--r--fs/buffer.c77
-rw-r--r--fs/char_dev.c13
-rw-r--r--fs/cifs/cifsfs.c28
-rw-r--r--fs/cifs/cifsfs.h10
-rw-r--r--fs/cifs/file.c6
-rw-r--r--fs/cifs/inode.c6
-rw-r--r--fs/cifs/readdir.c8
-rw-r--r--fs/coda/cache.c2
-rw-r--r--fs/coda/cnode.c3
-rw-r--r--fs/coda/dir.c2
-rw-r--r--fs/coda/file.c2
-rw-r--r--fs/coda/pioctl.c2
-rw-r--r--fs/coda/psdev.c2
-rw-r--r--fs/compat.c21
-rw-r--r--fs/configfs/configfs_internal.h6
-rw-r--r--fs/configfs/dir.c2
-rw-r--r--fs/configfs/file.c2
-rw-r--r--fs/cramfs/inode.c35
-rw-r--r--fs/dcache.c45
-rw-r--r--fs/dcookies.c25
-rw-r--r--fs/debugfs/file.c4
-rw-r--r--fs/debugfs/inode.c2
-rw-r--r--fs/devfs/base.c12
-rw-r--r--fs/direct-io.c40
-rw-r--r--fs/dnotify.c4
-rw-r--r--fs/efs/dir.c2
-rw-r--r--fs/eventpoll.c12
-rw-r--r--fs/exec.c39
-rw-r--r--fs/ext2/dir.c8
-rw-r--r--fs/ext2/ext2.h6
-rw-r--r--fs/ext2/file.c4
-rw-r--r--fs/ext2/inode.c14
-rw-r--r--fs/ext2/super.c2
-rw-r--r--fs/ext3/balloc.c109
-rw-r--r--fs/ext3/bitmap.c6
-rw-r--r--fs/ext3/dir.c7
-rw-r--r--fs/ext3/file.c2
-rw-r--r--fs/ext3/inode.c582
-rw-r--r--fs/ext3/super.c6
-rw-r--r--fs/fat/dir.c2
-rw-r--r--fs/fat/file.c2
-rw-r--r--fs/fat/inode.c5
-rw-r--r--fs/fcntl.c4
-rw-r--r--fs/fifo.c2
-rw-r--r--fs/file.c2
-rw-r--r--fs/freevxfs/vxfs_extern.h2
-rw-r--r--fs/freevxfs/vxfs_lookup.c2
-rw-r--r--fs/fs-writeback.c2
-rw-r--r--fs/fuse/dev.c2
-rw-r--r--fs/fuse/dir.c2
-rw-r--r--fs/fuse/file.c6
-rw-r--r--fs/fuse/fuse_i.h2
-rw-r--r--fs/hfs/bnode.c9
-rw-r--r--fs/hfs/btree.c3
-rw-r--r--fs/hfs/dir.c2
-rw-r--r--fs/hfs/hfs_fs.h2
-rw-r--r--fs/hfs/inode.c17
-rw-r--r--fs/hfsplus/dir.c2
-rw-r--r--fs/hfsplus/inode.c15
-rw-r--r--fs/hostfs/hostfs_kern.c4
-rw-r--r--fs/hostfs/hostfs_user.c1
-rw-r--r--fs/hpfs/dir.c2
-rw-r--r--fs/hpfs/file.c2
-rw-r--r--fs/hpfs/hpfs_fn.h4
-rw-r--r--fs/hppfs/hppfs_kern.c4
-rw-r--r--fs/hugetlbfs/inode.c4
-rw-r--r--fs/inode.c12
-rw-r--r--fs/inotify.c101
-rw-r--r--fs/isofs/dir.c2
-rw-r--r--fs/isofs/isofs.h2
-rw-r--r--fs/jbd/journal.c27
-rw-r--r--fs/jbd/transaction.c17
-rw-r--r--fs/jffs/inode-v23.c8
-rw-r--r--fs/jffs2/compr_zlib.c19
-rw-r--r--fs/jffs2/dir.c2
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jffs2/os-linux.h4
-rw-r--r--fs/jfs/file.c2
-rw-r--r--fs/jfs/inode.c5
-rw-r--r--fs/jfs/jfs_inode.h4
-rw-r--r--fs/jfs/jfs_logmgr.c27
-rw-r--r--fs/jfs/jfs_metapage.c11
-rw-r--r--fs/jfs/namei.c2
-rw-r--r--fs/libfs.c2
-rw-r--r--fs/lockd/clntlock.c112
-rw-r--r--fs/lockd/clntproc.c317
-rw-r--r--fs/lockd/host.c31
-rw-r--r--fs/lockd/mon.c11
-rw-r--r--fs/lockd/svc.c17
-rw-r--r--fs/lockd/svc4proc.c157
-rw-r--r--fs/lockd/svclock.c349
-rw-r--r--fs/lockd/svcproc.c151
-rw-r--r--fs/lockd/svcshare.c4
-rw-r--r--fs/lockd/svcsubs.c24
-rw-r--r--fs/lockd/xdr.c17
-rw-r--r--fs/lockd/xdr4.c21
-rw-r--r--fs/locks.c147
-rw-r--r--fs/mbcache.c2
-rw-r--r--fs/minix/bitmap.c10
-rw-r--r--fs/minix/dir.c2
-rw-r--r--fs/minix/file.c2
-rw-r--r--fs/minix/inode.c26
-rw-r--r--fs/minix/itree_v1.c4
-rw-r--r--fs/minix/itree_v2.c4
-rw-r--r--fs/minix/minix.h4
-rw-r--r--fs/mpage.c104
-rw-r--r--fs/namei.c72
-rw-r--r--fs/namespace.c50
-rw-r--r--fs/ncpfs/dir.c2
-rw-r--r--fs/ncpfs/file.c2
-rw-r--r--fs/nfs/callback.c31
-rw-r--r--fs/nfs/callback_xdr.c28
-rw-r--r--fs/nfs/delegation.c19
-rw-r--r--fs/nfs/delegation.h1
-rw-r--r--fs/nfs/dir.c116
-rw-r--r--fs/nfs/direct.c949
-rw-r--r--fs/nfs/file.c50
-rw-r--r--fs/nfs/idmap.c47
-rw-r--r--fs/nfs/inode.c229
-rw-r--r--fs/nfs/iostat.h164
-rw-r--r--fs/nfs/mount_clnt.c17
-rw-r--r--fs/nfs/nfs2xdr.c4
-rw-r--r--fs/nfs/nfs3acl.c16
-rw-r--r--fs/nfs/nfs3proc.c246
-rw-r--r--fs/nfs/nfs3xdr.c6
-rw-r--r--fs/nfs/nfs4proc.c180
-rw-r--r--fs/nfs/nfs4state.c1
-rw-r--r--fs/nfs/nfs4xdr.c2
-rw-r--r--fs/nfs/pagelist.c16
-rw-r--r--fs/nfs/proc.c156
-rw-r--r--fs/nfs/read.c108
-rw-r--r--fs/nfs/unlink.c3
-rw-r--r--fs/nfs/write.c300
-rw-r--r--fs/nfsd/export.c368
-rw-r--r--fs/nfsd/nfs4callback.c2
-rw-r--r--fs/nfsd/nfs4idmap.c146
-rw-r--r--fs/nfsd/nfs4state.c56
-rw-r--r--fs/nfsd/nfsctl.c4
-rw-r--r--fs/nfsd/nfsfh.c2
-rw-r--r--fs/nfsd/stats.c2
-rw-r--r--fs/nfsd/vfs.c2
-rw-r--r--fs/ntfs/dir.c2
-rw-r--r--fs/ntfs/file.c4
-rw-r--r--fs/ntfs/logfile.c4
-rw-r--r--fs/ntfs/mft.c2
-rw-r--r--fs/ntfs/ntfs.h35
-rw-r--r--fs/ocfs2/alloc.c88
-rw-r--r--fs/ocfs2/aops.c20
-rw-r--r--fs/ocfs2/buffer_head_io.c11
-rw-r--r--fs/ocfs2/cluster/heartbeat.c38
-rw-r--r--fs/ocfs2/cluster/masklog.h10
-rw-r--r--fs/ocfs2/dcache.c9
-rw-r--r--fs/ocfs2/dir.c42
-rw-r--r--fs/ocfs2/dlm/dlmast.c22
-rw-r--r--fs/ocfs2/dlm/dlmcommon.h21
-rw-r--r--fs/ocfs2/dlm/dlmconvert.c11
-rw-r--r--fs/ocfs2/dlm/dlmdebug.c18
-rw-r--r--fs/ocfs2/dlm/dlmlock.c14
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c227
-rw-r--r--fs/ocfs2/dlm/dlmrecovery.c50
-rw-r--r--fs/ocfs2/dlm/dlmunlock.c11
-rw-r--r--fs/ocfs2/dlmglue.c103
-rw-r--r--fs/ocfs2/export.c24
-rw-r--r--fs/ocfs2/extent_map.c34
-rw-r--r--fs/ocfs2/file.c46
-rw-r--r--fs/ocfs2/file.h4
-rw-r--r--fs/ocfs2/inode.c116
-rw-r--r--fs/ocfs2/journal.c37
-rw-r--r--fs/ocfs2/localalloc.c17
-rw-r--r--fs/ocfs2/namei.c84
-rw-r--r--fs/ocfs2/ocfs2.h12
-rw-r--r--fs/ocfs2/suballoc.c72
-rw-r--r--fs/ocfs2/super.c14
-rw-r--r--fs/ocfs2/super.h8
-rw-r--r--fs/ocfs2/uptodate.c40
-rw-r--r--fs/ocfs2/vote.c63
-rw-r--r--fs/open.c12
-rw-r--r--fs/openpromfs/inode.c6
-rw-r--r--fs/partitions/check.c27
-rw-r--r--fs/partitions/devfs.c12
-rw-r--r--fs/partitions/mac.c3
-rw-r--r--fs/pipe.c11
-rw-r--r--fs/proc/array.c5
-rw-r--r--fs/proc/base.c39
-rw-r--r--fs/proc/generic.c34
-rw-r--r--fs/proc/internal.h2
-rw-r--r--fs/proc/kcore.c2
-rw-r--r--fs/proc/kmsg.c2
-rw-r--r--fs/proc/proc_devtree.c101
-rw-r--r--fs/proc/proc_misc.c41
-rw-r--r--fs/proc/vmcore.c2
-rw-r--r--fs/qnx4/dir.c2
-rw-r--r--fs/qnx4/file.c2
-rw-r--r--fs/ramfs/file-mmu.c2
-rw-r--r--fs/ramfs/file-nommu.c2
-rw-r--r--fs/ramfs/internal.h2
-rw-r--r--fs/read_write.c4
-rw-r--r--fs/reiserfs/dir.c2
-rw-r--r--fs/reiserfs/file.c12
-rw-r--r--fs/reiserfs/fix_node.c4
-rw-r--r--fs/reiserfs/inode.c9
-rw-r--r--fs/reiserfs/item_ops.c2
-rw-r--r--fs/reiserfs/journal.c21
-rw-r--r--fs/reiserfs/prints.c2
-rw-r--r--fs/reiserfs/procfs.c2
-rw-r--r--fs/reiserfs/stree.c210
-rw-r--r--fs/reiserfs/super.c8
-rw-r--r--fs/reiserfs/xattr_acl.c4
-rw-r--r--fs/romfs/inode.c2
-rw-r--r--fs/select.c118
-rw-r--r--fs/smbfs/dir.c2
-rw-r--r--fs/smbfs/file.c2
-rw-r--r--fs/smbfs/inode.c2
-rw-r--r--fs/smbfs/proto.h4
-rw-r--r--fs/super.c10
-rw-r--r--fs/sysfs/bin.c2
-rw-r--r--fs/sysfs/dir.c2
-rw-r--r--fs/sysfs/file.c2
-rw-r--r--fs/sysfs/sysfs.h6
-rw-r--r--fs/sysv/dir.c2
-rw-r--r--fs/sysv/file.c2
-rw-r--r--fs/sysv/sysv.h4
-rw-r--r--fs/udf/dir.c2
-rw-r--r--fs/udf/file.c2
-rw-r--r--fs/udf/inode.c6
-rw-r--r--fs/udf/udfdecl.h4
-rw-r--r--fs/ufs/dir.c2
-rw-r--r--fs/ufs/file.c2
-rw-r--r--fs/ufs/super.c2
-rw-r--r--fs/xattr.c11
-rw-r--r--fs/xfs/linux-2.6/mrlock.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c74
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_export.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c6
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c22
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.h2
-rw-r--r--fs/xfs/quota/xfs_dquot_item.c2
-rw-r--r--fs/xfs/quota/xfs_qm.c14
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c2
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c2
-rw-r--r--fs/xfs/xfs_acl.c2
-rw-r--r--fs/xfs/xfs_ag.h2
-rw-r--r--fs/xfs/xfs_alloc.c6
-rw-r--r--fs/xfs/xfs_alloc.h2
-rw-r--r--fs/xfs/xfs_attr.c6
-rw-r--r--fs/xfs/xfs_attr_leaf.c4
-rw-r--r--fs/xfs/xfs_behavior.c4
-rw-r--r--fs/xfs/xfs_behavior.h4
-rw-r--r--fs/xfs/xfs_bmap.c107
-rw-r--r--fs/xfs/xfs_bmap.h8
-rw-r--r--fs/xfs/xfs_buf_item.c4
-rw-r--r--fs/xfs/xfs_cap.h2
-rw-r--r--fs/xfs/xfs_da_btree.c2
-rw-r--r--fs/xfs/xfs_dir2_block.c2
-rw-r--r--fs/xfs/xfs_dir2_leaf.c2
-rw-r--r--fs/xfs/xfs_dir2_node.c2
-rw-r--r--fs/xfs/xfs_dir_leaf.c2
-rw-r--r--fs/xfs/xfs_fsops.c2
-rw-r--r--fs/xfs/xfs_ialloc.c110
-rw-r--r--fs/xfs/xfs_iget.c2
-rw-r--r--fs/xfs/xfs_inode.c14
-rw-r--r--fs/xfs/xfs_inode_item.c2
-rw-r--r--fs/xfs/xfs_itable.c4
-rw-r--r--fs/xfs/xfs_itable.h2
-rw-r--r--fs/xfs/xfs_log.c22
-rw-r--r--fs/xfs/xfs_log.h2
-rw-r--r--fs/xfs/xfs_log_recover.c4
-rw-r--r--fs/xfs/xfs_mount.c4
-rw-r--r--fs/xfs/xfs_mount.h2
-rw-r--r--fs/xfs/xfs_quota.h4
-rw-r--r--fs/xfs/xfs_trans.c6
-rw-r--r--fs/xfs/xfs_trans.h2
-rw-r--r--fs/xfs/xfs_trans_inode.c2
-rw-r--r--fs/xfs/xfs_vfsops.c10
-rw-r--r--fs/xfs/xfs_vnodeops.c12
-rw-r--r--include/asm-alpha/bitops.h133
-rw-r--r--include/asm-alpha/fpu.h4
-rw-r--r--include/asm-alpha/mmzone.h19
-rw-r--r--include/asm-alpha/page.h4
-rw-r--r--include/asm-alpha/poll.h4
-rw-r--r--include/asm-arm/arch-aaec2000/uncompress.h23
-rw-r--r--include/asm-arm/arch-at91rm9200/at91rm9200_emac.h138
-rw-r--r--include/asm-arm/arch-at91rm9200/at91rm9200_sys.h100
-rw-r--r--include/asm-arm/arch-at91rm9200/uncompress.h23
-rw-r--r--include/asm-arm/arch-cl7500/uncompress.h18
-rw-r--r--include/asm-arm/arch-clps711x/uncompress.h21
-rw-r--r--include/asm-arm/arch-ebsa110/uncompress.h47
-rw-r--r--include/asm-arm/arch-ebsa285/uncompress.h16
-rw-r--r--include/asm-arm/arch-ep93xx/uncompress.h50
-rw-r--r--include/asm-arm/arch-h720x/uncompress.h24
-rw-r--r--include/asm-arm/arch-imx/uncompress.h21
-rw-r--r--include/asm-arm/arch-integrator/uncompress.h21
-rw-r--r--include/asm-arm/arch-iop3xx/uncompress.h16
-rw-r--r--include/asm-arm/arch-ixp2000/uncompress.h15
-rw-r--r--include/asm-arm/arch-ixp23xx/debug-macro.S23
-rw-r--r--include/asm-arm/arch-ixp23xx/dma.h3
-rw-r--r--include/asm-arm/arch-ixp23xx/entry-macro.S31
-rw-r--r--include/asm-arm/arch-ixp23xx/hardware.h37
-rw-r--r--include/asm-arm/arch-ixp23xx/io.h54
-rw-r--r--include/asm-arm/arch-ixp23xx/irqs.h223
-rw-r--r--include/asm-arm/arch-ixp23xx/ixdp2351.h89
-rw-r--r--include/asm-arm/arch-ixp23xx/ixp23xx.h306
-rw-r--r--include/asm-arm/arch-ixp23xx/memory.h46
-rw-r--r--include/asm-arm/arch-ixp23xx/platform.h31
-rw-r--r--include/asm-arm/arch-ixp23xx/system.h33
-rw-r--r--include/asm-arm/arch-ixp23xx/time.h3
-rw-r--r--include/asm-arm/arch-ixp23xx/timex.h7
-rw-r--r--include/asm-arm/arch-ixp23xx/uncompress.h45
-rw-r--r--include/asm-arm/arch-ixp23xx/vmalloc.h10
-rw-r--r--include/asm-arm/arch-ixp4xx/uncompress.h18
-rw-r--r--include/asm-arm/arch-l7200/uncompress.h15
-rw-r--r--include/asm-arm/arch-lh7a40x/uncompress.h11
-rw-r--r--include/asm-arm/arch-omap/uncompress.h20
-rw-r--r--include/asm-arm/arch-pxa/irqs.h6
-rw-r--r--include/asm-arm/arch-pxa/lpd270.h38
-rw-r--r--include/asm-arm/arch-pxa/uncompress.h13
-rw-r--r--include/asm-arm/arch-realview/uncompress.h20
-rw-r--r--include/asm-arm/arch-rpc/uncompress.h27
-rw-r--r--include/asm-arm/arch-s3c2410/uncompress.h15
-rw-r--r--include/asm-arm/arch-sa1100/uncompress.h21
-rw-r--r--include/asm-arm/arch-shark/uncompress.h13
-rw-r--r--include/asm-arm/arch-versatile/uncompress.h20
-rw-r--r--include/asm-arm/assembler.h27
-rw-r--r--include/asm-arm/bitops.h175
-rw-r--r--include/asm-arm/cacheflush.h8
-rw-r--r--include/asm-arm/domain.h18
-rw-r--r--include/asm-arm/memory.h15
-rw-r--r--include/asm-arm/page.h9
-rw-r--r--include/asm-arm/pgalloc.h5
-rw-r--r--include/asm-arm/pgtable-hwdef.h88
-rw-r--r--include/asm-arm/pgtable.h80
-rw-r--r--include/asm-arm/poll.h1
-rw-r--r--include/asm-arm/proc-fns.h8
-rw-r--r--include/asm-arm/rtc.h3
-rw-r--r--include/asm-arm/system.h19
-rw-r--r--include/asm-arm/tlb.h9
-rw-r--r--include/asm-arm/tlbflush.h9
-rw-r--r--include/asm-arm26/bitops.h146
-rw-r--r--include/asm-arm26/memory.h4
-rw-r--r--include/asm-arm26/poll.h1
-rw-r--r--include/asm-cris/bitops.h235
-rw-r--r--include/asm-cris/page.h4
-rw-r--r--include/asm-cris/poll.h1
-rw-r--r--include/asm-frv/bitops.h174
-rw-r--r--include/asm-frv/futex.h6
-rw-r--r--include/asm-frv/page.h7
-rw-r--r--include/asm-frv/poll.h1
-rw-r--r--include/asm-generic/bitops.h76
-rw-r--r--include/asm-generic/bitops/__ffs.h43
-rw-r--r--include/asm-generic/bitops/atomic.h191
-rw-r--r--include/asm-generic/bitops/ext2-atomic.h22
-rw-r--r--include/asm-generic/bitops/ext2-non-atomic.h18
-rw-r--r--include/asm-generic/bitops/ffs.h41
-rw-r--r--include/asm-generic/bitops/ffz.h12
-rw-r--r--include/asm-generic/bitops/find.h13
-rw-r--r--include/asm-generic/bitops/fls.h41
-rw-r--r--include/asm-generic/bitops/fls64.h14
-rw-r--r--include/asm-generic/bitops/hweight.h11
-rw-r--r--include/asm-generic/bitops/le.h53
-rw-r--r--include/asm-generic/bitops/minix-le.h17
-rw-r--r--include/asm-generic/bitops/minix.h15
-rw-r--r--include/asm-generic/bitops/non-atomic.h111
-rw-r--r--include/asm-generic/bitops/sched.h36
-rw-r--r--include/asm-generic/futex.h6
-rw-r--r--include/asm-generic/local.h80
-rw-r--r--include/asm-generic/memory_model.h77
-rw-r--r--include/asm-generic/percpu.h2
-rw-r--r--include/asm-h8300/bitops.h222
-rw-r--r--include/asm-h8300/page.h4
-rw-r--r--include/asm-h8300/poll.h1
-rw-r--r--include/asm-h8300/types.h3
-rw-r--r--include/asm-i386/bitops.h55
-rw-r--r--include/asm-i386/dmi.h11
-rw-r--r--include/asm-i386/futex.h27
-rw-r--r--include/asm-i386/kdebug.h10
-rw-r--r--include/asm-i386/kprobes.h6
-rw-r--r--include/asm-i386/mach-default/mach_time.h37
-rw-r--r--include/asm-i386/mmzone.h17
-rw-r--r--include/asm-i386/page.h3
-rw-r--r--include/asm-i386/poll.h1
-rw-r--r--include/asm-i386/processor.h7
-rw-r--r--include/asm-i386/setup.h4
-rw-r--r--include/asm-i386/stat.h3
-rw-r--r--include/asm-i386/topology.h2
-rw-r--r--include/asm-i386/types.h5
-rw-r--r--include/asm-i386/unistd.h4
-rw-r--r--include/asm-ia64/acpi.h4
-rw-r--r--include/asm-ia64/asmmacro.h11
-rw-r--r--include/asm-ia64/bitops.h67
-rw-r--r--include/asm-ia64/compat.h6
-rw-r--r--include/asm-ia64/dmi.h6
-rw-r--r--include/asm-ia64/io.h22
-rw-r--r--include/asm-ia64/kdebug.h4
-rw-r--r--include/asm-ia64/machvec_dig.h2
-rw-r--r--include/asm-ia64/numa.h2
-rw-r--r--include/asm-ia64/numnodes.h13
-rw-r--r--include/asm-ia64/page.h20
-rw-r--r--include/asm-ia64/pal.h3
-rw-r--r--include/asm-ia64/poll.h1
-rw-r--r--include/asm-ia64/processor.h1
-rw-r--r--include/asm-ia64/sn/l1.h3
-rw-r--r--include/asm-ia64/sn/pcibr_provider.h1
-rw-r--r--include/asm-ia64/sn/pcidev.h1
-rw-r--r--include/asm-ia64/sn/sn_feature_sets.h3
-rw-r--r--include/asm-ia64/sn/sn_sal.h28
-rw-r--r--include/asm-m32r/bitops.h457
-rw-r--r--include/asm-m32r/mmzone.h14
-rw-r--r--include/asm-m32r/page.h5
-rw-r--r--include/asm-m32r/poll.h1
-rw-r--r--include/asm-m32r/setup.h4
-rw-r--r--include/asm-m68k/bitops.h42
-rw-r--r--include/asm-m68k/poll.h1
-rw-r--r--include/asm-m68k/stat.h3
-rw-r--r--include/asm-m68knommu/bitops.h221
-rw-r--r--include/asm-mips/bitops.h465
-rw-r--r--include/asm-mips/compat.h5
-rw-r--r--include/asm-mips/futex.h6
-rw-r--r--include/asm-mips/mc146818-time.h33
-rw-r--r--include/asm-mips/mmzone.h14
-rw-r--r--include/asm-mips/page.h3
-rw-r--r--include/asm-mips/poll.h1
-rw-r--r--include/asm-mips/serial.h85
-rw-r--r--include/asm-mips/time.h12
-rw-r--r--include/asm-mips/types.h5
-rw-r--r--include/asm-parisc/bitops.h286
-rw-r--r--include/asm-parisc/compat.h5
-rw-r--r--include/asm-parisc/mmzone.h17
-rw-r--r--include/asm-parisc/page.h3
-rw-r--r--include/asm-parisc/pdc.h2
-rw-r--r--include/asm-parisc/poll.h1
-rw-r--r--include/asm-powerpc/bitops.h105
-rw-r--r--include/asm-powerpc/bug.h36
-rw-r--r--include/asm-powerpc/cputable.h299
-rw-r--r--include/asm-powerpc/firmware.h10
-rw-r--r--include/asm-powerpc/floppy.h5
-rw-r--r--include/asm-powerpc/futex.h6
-rw-r--r--include/asm-powerpc/hvcall.h1
-rw-r--r--include/asm-powerpc/hvconsole.h26
-rw-r--r--include/asm-powerpc/kdebug.h12
-rw-r--r--include/asm-powerpc/machdep.h43
-rw-r--r--include/asm-powerpc/oprofile_impl.h17
-rw-r--r--include/asm-powerpc/paca.h2
-rw-r--r--include/asm-powerpc/page.h3
-rw-r--r--include/asm-powerpc/percpu.h2
-rw-r--r--include/asm-powerpc/pmac_feature.h2
-rw-r--r--include/asm-powerpc/poll.h1
-rw-r--r--include/asm-powerpc/processor.h43
-rw-r--r--include/asm-powerpc/prom.h14
-rw-r--r--include/asm-powerpc/reg.h4
-rw-r--r--include/asm-powerpc/smp.h2
-rw-r--r--include/asm-powerpc/spu.h11
-rw-r--r--include/asm-powerpc/string.h2
-rw-r--r--include/asm-powerpc/syscalls.h58
-rw-r--r--include/asm-powerpc/types.h5
-rw-r--r--include/asm-powerpc/unistd.h35
-rw-r--r--include/asm-powerpc/vdso_datapage.h3
-rw-r--r--include/asm-ppc/machdep.h17
-rw-r--r--include/asm-ppc/mpc52xx.h4
-rw-r--r--include/asm-ppc/page.h4
-rw-r--r--include/asm-ppc/pgtable.h3
-rw-r--r--include/asm-ppc/prom.h156
-rw-r--r--include/asm-ppc/serial.h7
-rw-r--r--include/asm-s390/bitops.h48
-rw-r--r--include/asm-s390/compat.h5
-rw-r--r--include/asm-s390/page.h3
-rw-r--r--include/asm-s390/poll.h1
-rw-r--r--include/asm-s390/types.h5
-rw-r--r--include/asm-sh/addrspace.h2
-rw-r--r--include/asm-sh/bitops.h348
-rw-r--r--include/asm-sh/page.h5
-rw-r--r--include/asm-sh/poll.h1
-rw-r--r--include/asm-sh/stat.h8
-rw-r--r--include/asm-sh/thread_info.h2
-rw-r--r--include/asm-sh/types.h5
-rw-r--r--include/asm-sh64/bitops.h390
-rw-r--r--include/asm-sh64/page.h5
-rw-r--r--include/asm-sh64/platform.h5
-rw-r--r--include/asm-sh64/poll.h1
-rw-r--r--include/asm-sparc/bitops.h388
-rw-r--r--include/asm-sparc/cpudata.h1
-rw-r--r--include/asm-sparc/page.h4
-rw-r--r--include/asm-sparc/poll.h1
-rw-r--r--include/asm-sparc/smp.h9
-rw-r--r--include/asm-sparc/spinlock.h25
-rw-r--r--include/asm-sparc64/bitops.h219
-rw-r--r--include/asm-sparc64/floppy.h2
-rw-r--r--include/asm-sparc64/futex.h24
-rw-r--r--include/asm-sparc64/kdebug.h11
-rw-r--r--include/asm-sparc64/page.h2
-rw-r--r--include/asm-sparc64/poll.h1
-rw-r--r--include/asm-um/page.h4
-rw-r--r--include/asm-um/uaccess.h31
-rw-r--r--include/asm-v850/bitops.h220
-rw-r--r--include/asm-v850/page.h4
-rw-r--r--include/asm-v850/poll.h1
-rw-r--r--include/asm-x86_64/apicdef.h1
-rw-r--r--include/asm-x86_64/bitops.h42
-rw-r--r--include/asm-x86_64/dmi.h27
-rw-r--r--include/asm-x86_64/elf.h4
-rw-r--r--include/asm-x86_64/floppy.h2
-rw-r--r--include/asm-x86_64/futex.h27
-rw-r--r--include/asm-x86_64/io.h26
-rw-r--r--include/asm-x86_64/kdebug.h23
-rw-r--r--include/asm-x86_64/local.h10
-rw-r--r--include/asm-x86_64/mmzone.h13
-rw-r--r--include/asm-x86_64/numa.h4
-rw-r--r--include/asm-x86_64/page.h3
-rw-r--r--include/asm-x86_64/pda.h2
-rw-r--r--include/asm-x86_64/pgalloc.h28
-rw-r--r--include/asm-x86_64/pgtable.h4
-rw-r--r--include/asm-x86_64/poll.h1
-rw-r--r--include/asm-x86_64/processor.h7
-rw-r--r--include/asm-x86_64/proto.h3
-rw-r--r--include/asm-x86_64/smp.h1
-rw-r--r--include/asm-x86_64/string.h17
-rw-r--r--include/asm-x86_64/suspend.h4
-rw-r--r--include/asm-x86_64/system.h6
-rw-r--r--include/asm-x86_64/topology.h2
-rw-r--r--include/asm-x86_64/unistd.h6
-rw-r--r--include/asm-xtensa/bitops.h340
-rw-r--r--include/asm-xtensa/page.h6
-rw-r--r--include/asm-xtensa/poll.h1
-rw-r--r--include/linux/adb.h2
-rw-r--r--include/linux/amba/serial.h6
-rw-r--r--include/linux/audit.h130
-rw-r--r--include/linux/auto_fs4.h51
-rw-r--r--include/linux/bitops.h131
-rw-r--r--include/linux/blkdev.h22
-rw-r--r--include/linux/bootmem.h4
-rw-r--r--include/linux/buffer_head.h26
-rw-r--r--include/linux/capability.h3
-rw-r--r--include/linux/cdev.h4
-rw-r--r--include/linux/clk.h4
-rw-r--r--include/linux/coda_linux.h6
-rw-r--r--include/linux/compat.h46
-rw-r--r--include/linux/compat_ioctl.h2
-rw-r--r--include/linux/cpu.h1
-rw-r--r--include/linux/cpumask.h51
-rw-r--r--include/linux/crash_dump.h2
-rw-r--r--include/linux/dcache.h2
-rw-r--r--include/linux/debugfs.h2
-rw-r--r--include/linux/device-mapper.h1
-rw-r--r--include/linux/dio.h32
-rw-r--r--include/linux/dm-ioctl.h17
-rw-r--r--include/linux/dma-mapping.h1
-rw-r--r--include/linux/dmi.h2
-rw-r--r--include/linux/efi.h20
-rw-r--r--include/linux/efs_fs.h2
-rw-r--r--include/linux/ext3_fs.h15
-rw-r--r--include/linux/fb.h2
-rw-r--r--include/linux/fs.h73
-rw-r--r--include/linux/fsnotify.h33
-rw-r--r--include/linux/futex.h89
-rw-r--r--include/linux/gameport.h4
-rw-r--r--include/linux/genhd.h19
-rw-r--r--include/linux/gigaset_dev.h32
-rw-r--r--include/linux/highmem.h12
-rw-r--r--include/linux/hpet.h36
-rw-r--r--include/linux/hrtimer.h41
-rw-r--r--include/linux/hugetlb.h2
-rw-r--r--include/linux/i2c-id.h5
-rw-r--r--include/linux/i2o.h4
-rw-r--r--include/linux/init.h4
-rw-r--r--include/linux/init_task.h2
-rw-r--r--include/linux/inotify.h11
-rw-r--r--include/linux/input.h2
-rw-r--r--include/linux/ipmi.h3
-rw-r--r--include/linux/ipmi_msgdefs.h1
-rw-r--r--include/linux/ipmi_smi.h47
-rw-r--r--include/linux/irq.h49
-rw-r--r--include/linux/jbd.h6
-rw-r--r--include/linux/kernel.h7
-rw-r--r--include/linux/kernel_stat.h2
-rw-r--r--include/linux/ktime.h20
-rw-r--r--include/linux/lockd/lockd.h27
-rw-r--r--include/linux/lockd/share.h2
-rw-r--r--include/linux/lockd/xdr.h1
-rw-r--r--include/linux/m48t86.h16
-rw-r--r--include/linux/major.h1
-rw-r--r--include/linux/memory.h1
-rw-r--r--include/linux/mempool.h38
-rw-r--r--include/linux/miscdevice.h2
-rw-r--r--include/linux/mmzone.h91
-rw-r--r--include/linux/module.h20
-rw-r--r--include/linux/moduleparam.h7
-rw-r--r--include/linux/msdos_fs.h7
-rw-r--r--include/linux/ncp_fs.h4
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack.h17
-rw-r--r--include/linux/nfs_fs.h106
-rw-r--r--include/linux/nfs_fs_i.h8
-rw-r--r--include/linux/nfs_fs_sb.h6
-rw-r--r--include/linux/nfs_xdr.h5
-rw-r--r--include/linux/nfsd/export.h29
-rw-r--r--include/linux/nodemask.h4
-rw-r--r--include/linux/notifier.h96
-rw-r--r--include/linux/oprofile.h14
-rw-r--r--include/linux/pci_ids.h3
-rw-r--r--include/linux/pfn.h9
-rw-r--r--include/linux/pid.h2
-rw-r--r--include/linux/poll.h17
-rw-r--r--include/linux/ppdev.h2
-rw-r--r--include/linux/proc_fs.h15
-rw-r--r--include/linux/qnx4_fs.h4
-rw-r--r--include/linux/quota.h1
-rw-r--r--include/linux/radix-tree.h13
-rw-r--r--include/linux/raid/md.h3
-rw-r--r--include/linux/raid/md_k.h21
-rw-r--r--include/linux/raid/md_p.h32
-rw-r--r--include/linux/raid/raid5.h25
-rw-r--r--include/linux/ramfs.h2
-rw-r--r--include/linux/reiserfs_fs.h9
-rw-r--r--include/linux/reiserfs_xattr.h6
-rw-r--r--include/linux/relayfs_fs.h287
-rw-r--r--include/linux/rtc.h92
-rw-r--r--include/linux/sched.h58
-rw-r--r--include/linux/security.h55
-rw-r--r--include/linux/serial_8250.h1
-rw-r--r--include/linux/serio.h6
-rw-r--r--include/linux/signal.h2
-rw-r--r--include/linux/slab.h39
-rw-r--r--include/linux/smp.h6
-rw-r--r--include/linux/sound.h12
-rw-r--r--include/linux/stat.h2
-rw-r--r--include/linux/statfs.h10
-rw-r--r--include/linux/sunrpc/cache.h145
-rw-r--r--include/linux/sunrpc/clnt.h20
-rw-r--r--include/linux/sunrpc/gss_krb5.h2
-rw-r--r--include/linux/sunrpc/metrics.h77
-rw-r--r--include/linux/sunrpc/rpc_pipe_fs.h2
-rw-r--r--include/linux/sunrpc/sched.h9
-rw-r--r--include/linux/sunrpc/stats.h4
-rw-r--r--include/linux/sunrpc/svcauth.h12
-rw-r--r--include/linux/sunrpc/xprt.h13
-rw-r--r--include/linux/synclink.h11
-rw-r--r--include/linux/threads.h3
-rw-r--r--include/linux/time.h19
-rw-r--r--include/linux/timer.h9
-rw-r--r--include/linux/timex.h43
-rw-r--r--include/linux/topology.h9
-rw-r--r--include/linux/tty_flip.h4
-rw-r--r--include/linux/types.h4
-rw-r--r--include/linux/udf_fs_i.h21
-rw-r--r--include/linux/ufs_fs.h4
-rw-r--r--include/linux/usb.h2
-rw-r--r--include/linux/videodev2.h3
-rw-r--r--include/linux/x1205.h31
-rw-r--r--include/linux/zorro.h33
-rw-r--r--include/media/audiochip.h14
-rw-r--r--include/media/cs53l32a.h34
-rw-r--r--include/media/i2c-addr.h44
-rw-r--r--include/media/msp3400.h226
-rw-r--r--include/media/rds.h (renamed from drivers/media/video/rds.h)4
-rw-r--r--include/media/saa7146_vv.h3
-rw-r--r--include/media/tvaudio.h30
-rw-r--r--include/media/v4l2-common.h19
-rw-r--r--include/media/video-buf.h56
-rw-r--r--include/media/wm8775.h35
-rw-r--r--include/net/netfilter/nf_conntrack.h17
-rw-r--r--include/net/request_sock.h2
-rw-r--r--include/net/route.h2
-rw-r--r--include/net/sock.h93
-rw-r--r--include/net/xfrm.h16
-rw-r--r--include/sound/core.h6
-rw-r--r--include/video/pm3fb.h3
-rw-r--r--init/Kconfig46
-rw-r--r--init/do_mounts.c1
-rw-r--r--init/initramfs.c12
-rw-r--r--init/main.c45
-rw-r--r--ipc/compat.c2
-rw-r--r--ipc/mqueue.c4
-rw-r--r--ipc/msg.c26
-rw-r--r--ipc/sem.c45
-rw-r--r--ipc/shm.c32
-rw-r--r--ipc/util.c29
-rw-r--r--ipc/util.h4
-rw-r--r--kernel/Makefile5
-rw-r--r--kernel/audit.c175
-rw-r--r--kernel/audit.h88
-rw-r--r--kernel/auditfilter.c630
-rw-r--r--kernel/auditsc.c834
-rw-r--r--kernel/capability.c16
-rw-r--r--kernel/compat.c82
-rw-r--r--kernel/cpu.c32
-rw-r--r--kernel/exit.c137
-rw-r--r--kernel/fork.c131
-rw-r--r--kernel/futex.c170
-rw-r--r--kernel/futex_compat.c142
-rw-r--r--kernel/hrtimer.c193
-rw-r--r--kernel/irq/Makefile3
-rw-r--r--kernel/irq/manage.c24
-rw-r--r--kernel/irq/migration.c65
-rw-r--r--kernel/itimer.c117
-rw-r--r--kernel/kmod.c2
-rw-r--r--kernel/kprobes.c10
-rw-r--r--kernel/kthread.c2
-rw-r--r--kernel/module.c205
-rw-r--r--kernel/panic.c4
-rw-r--r--kernel/params.c14
-rw-r--r--kernel/pid.c40
-rw-r--r--kernel/posix-timers.c67
-rw-r--r--kernel/power/smp.c4
-rw-r--r--kernel/power/swap.c7
-rw-r--r--kernel/profile.c53
-rw-r--r--kernel/ptrace.c8
-rw-r--r--kernel/rcutorture.c14
-rw-r--r--kernel/sched.c163
-rw-r--r--kernel/signal.c344
-rw-r--r--kernel/softlockup.c3
-rw-r--r--kernel/sys.c422
-rw-r--r--kernel/sys_ni.c4
-rw-r--r--kernel/time.c63
-rw-r--r--kernel/timer.c27
-rw-r--r--lib/Kconfig.debug9
-rw-r--r--lib/Makefile3
-rw-r--r--lib/bitmap.c19
-rw-r--r--lib/cpumask.c45
-rw-r--r--lib/find_next_bit.c177
-rw-r--r--lib/hweight.c53
-rw-r--r--lib/radix-tree.c49
-rw-r--r--lib/swiotlb.c32
-rw-r--r--mm/Kconfig4
-rw-r--r--mm/Makefile2
-rw-r--r--mm/bootmem.c41
-rw-r--r--mm/highmem.c23
-rw-r--r--mm/memory.c16
-rw-r--r--mm/mempolicy.c2
-rw-r--r--mm/mempool.c46
-rw-r--r--mm/mmap.c6
-rw-r--r--mm/mmzone.c50
-rw-r--r--mm/msync.c2
-rw-r--r--mm/page_alloc.c64
-rw-r--r--mm/slab.c318
-rw-r--r--mm/slob.c10
-rw-r--r--mm/swap.c2
-rw-r--r--mm/util.c10
-rw-r--r--mm/vmscan.c8
-rw-r--r--net/appletalk/ddp.c19
-rw-r--r--net/bluetooth/af_bluetooth.c3
-rw-r--r--net/bluetooth/hci_core.c8
-rw-r--r--net/bridge/br_stp_bpdu.c5
-rw-r--r--net/bridge/netfilter/ebt_802_3.c8
-rw-r--r--net/bridge/netfilter/ebt_among.c8
-rw-r--r--net/bridge/netfilter/ebt_arp.c8
-rw-r--r--net/bridge/netfilter/ebt_arpreply.c8
-rw-r--r--net/bridge/netfilter/ebt_dnat.c8
-rw-r--r--net/bridge/netfilter/ebt_ip.c8
-rw-r--r--net/bridge/netfilter/ebt_limit.c8
-rw-r--r--net/bridge/netfilter/ebt_log.c8
-rw-r--r--net/bridge/netfilter/ebt_mark.c8
-rw-r--r--net/bridge/netfilter/ebt_mark_m.c8
-rw-r--r--net/bridge/netfilter/ebt_pkttype.c8
-rw-r--r--net/bridge/netfilter/ebt_redirect.c8
-rw-r--r--net/bridge/netfilter/ebt_snat.c8
-rw-r--r--net/bridge/netfilter/ebt_stp.c8
-rw-r--r--net/bridge/netfilter/ebt_ulog.c8
-rw-r--r--net/bridge/netfilter/ebt_vlan.c8
-rw-r--r--net/bridge/netfilter/ebtable_broute.c8
-rw-r--r--net/bridge/netfilter/ebtable_filter.c8
-rw-r--r--net/bridge/netfilter/ebtable_nat.c8
-rw-r--r--net/bridge/netfilter/ebtables.c8
-rw-r--r--net/core/datagram.c2
-rw-r--r--net/core/dev.c54
-rw-r--r--net/core/request_sock.c2
-rw-r--r--net/core/skbuff.c2
-rw-r--r--net/core/sock.c98
-rw-r--r--net/dccp/proto.c2
-rw-r--r--net/decnet/dn_dev.c10
-rw-r--r--net/decnet/netfilter/dn_rtmsg.c8
-rw-r--r--net/econet/af_econet.c124
-rw-r--r--net/ipv4/Kconfig17
-rw-r--r--net/ipv4/Makefile3
-rw-r--r--net/ipv4/devinet.c16
-rw-r--r--net/ipv4/icmp.c2
-rw-r--r--net/ipv4/ipip.c79
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c11
-rw-r--r--net/ipv4/netfilter.c8
-rw-r--r--net/ipv4/netfilter/arp_tables.c8
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c8
-rw-r--r--net/ipv4/netfilter/arptable_filter.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_amanda.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c6
-rw-r--r--net/ipv4/netfilter/ip_conntrack_ftp.c10
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_pptp.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_irc.c12
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netbios_ns.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_sctp.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_tftp.c10
-rw-r--r--net/ipv4/netfilter/ip_nat_amanda.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_ftp.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_pptp.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_irc.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_snmp_basic.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_tftp.c8
-rw-r--r--net/ipv4/netfilter/ip_queue.c8
-rw-r--r--net/ipv4/netfilter/ip_tables.c8
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c8
-rw-r--r--net/ipv4/netfilter/ipt_DSCP.c8
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c8
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c8
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c8
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c8
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c8
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c8
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c8
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c8
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c8
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c8
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c8
-rw-r--r--net/ipv4/netfilter/ipt_addrtype.c8
-rw-r--r--net/ipv4/netfilter/ipt_ah.c8
-rw-r--r--net/ipv4/netfilter/ipt_dscp.c8
-rw-r--r--net/ipv4/netfilter/ipt_ecn.c8
-rw-r--r--net/ipv4/netfilter/ipt_esp.c8
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c17
-rw-r--r--net/ipv4/netfilter/ipt_iprange.c8
-rw-r--r--net/ipv4/netfilter/ipt_multiport.c8
-rw-r--r--net/ipv4/netfilter/ipt_owner.c8
-rw-r--r--net/ipv4/netfilter/ipt_recent.c8
-rw-r--r--net/ipv4/netfilter/ipt_tos.c8
-rw-r--r--net/ipv4/netfilter/ipt_ttl.c8
-rw-r--r--net/ipv4/netfilter/iptable_filter.c8
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c8
-rw-r--r--net/ipv4/netfilter/iptable_raw.c8
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c8
-rw-r--r--net/ipv4/route.c45
-rw-r--r--net/ipv4/tcp.c28
-rw-r--r--net/ipv4/tcp_cong.c2
-rw-r--r--net/ipv4/tunnel4.c113
-rw-r--r--net/ipv4/xfrm4_tunnel.c79
-rw-r--r--net/ipv6/Kconfig19
-rw-r--r--net/ipv6/Makefile3
-rw-r--r--net/ipv6/addrconf.c10
-rw-r--r--net/ipv6/ip6_tunnel.c45
-rw-r--r--net/ipv6/ipcomp6.c5
-rw-r--r--net/ipv6/netfilter/ip6_queue.c8
-rw-r--r--net/ipv6/netfilter/ip6_tables.c8
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c8
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c8
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c8
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c8
-rw-r--r--net/ipv6/netfilter/ip6t_dst.c8
-rw-r--r--net/ipv6/netfilter/ip6t_esp.c8
-rw-r--r--net/ipv6/netfilter/ip6t_eui64.c8
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c8
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c8
-rw-r--r--net/ipv6/netfilter/ip6t_hl.c8
-rw-r--r--net/ipv6/netfilter/ip6t_multiport.c8
-rw-r--r--net/ipv6/netfilter/ip6t_owner.c8
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c8
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c8
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c8
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c8
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c8
-rw-r--r--net/ipv6/tunnel6.c131
-rw-r--r--net/ipv6/xfrm6_input.c5
-rw-r--r--net/ipv6/xfrm6_tunnel.c81
-rw-r--r--net/ipx/af_ipx.c26
-rw-r--r--net/irda/af_irda.c31
-rw-r--r--net/netfilter/nf_conntrack_core.c6
-rw-r--r--net/netfilter/nf_conntrack_ftp.c10
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c8
-rw-r--r--net/netfilter/nf_conntrack_standalone.c8
-rw-r--r--net/netfilter/nfnetlink_log.c8
-rw-r--r--net/netfilter/nfnetlink_queue.c8
-rw-r--r--net/netfilter/x_tables.c56
-rw-r--r--net/netfilter/xt_CLASSIFY.c8
-rw-r--r--net/netfilter/xt_CONNMARK.c8
-rw-r--r--net/netfilter/xt_MARK.c8
-rw-r--r--net/netfilter/xt_NFQUEUE.c8
-rw-r--r--net/netfilter/xt_NOTRACK.c8
-rw-r--r--net/netfilter/xt_comment.c8
-rw-r--r--net/netfilter/xt_connbytes.c8
-rw-r--r--net/netfilter/xt_connmark.c8
-rw-r--r--net/netfilter/xt_conntrack.c8
-rw-r--r--net/netfilter/xt_dccp.c8
-rw-r--r--net/netfilter/xt_helper.c8
-rw-r--r--net/netfilter/xt_length.c8
-rw-r--r--net/netfilter/xt_limit.c8
-rw-r--r--net/netfilter/xt_mac.c8
-rw-r--r--net/netfilter/xt_mark.c8
-rw-r--r--net/netfilter/xt_physdev.c8
-rw-r--r--net/netfilter/xt_pkttype.c8
-rw-r--r--net/netfilter/xt_realm.c8
-rw-r--r--net/netfilter/xt_sctp.c8
-rw-r--r--net/netfilter/xt_state.c8
-rw-r--r--net/netfilter/xt_string.c8
-rw-r--r--net/netfilter/xt_tcpmss.c8
-rw-r--r--net/netfilter/xt_tcpudp.c8
-rw-r--r--net/netlink/af_netlink.c9
-rw-r--r--net/netlink/genetlink.c9
-rw-r--r--net/nonet.c2
-rw-r--r--net/rxrpc/main.c2
-rw-r--r--net/sctp/input.c12
-rw-r--r--net/sctp/socket.c2
-rw-r--r--net/socket.c2
-rw-r--r--net/sunrpc/auth.c16
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c2
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_seal.c15
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_unseal.c4
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_wrap.c17
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_mech.c6
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_seal.c5
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_unseal.c4
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c182
-rw-r--r--net/sunrpc/cache.c163
-rw-r--r--net/sunrpc/clnt.c53
-rw-r--r--net/sunrpc/pmap_clnt.c41
-rw-r--r--net/sunrpc/rpc_pipe.c33
-rw-r--r--net/sunrpc/sched.c24
-rw-r--r--net/sunrpc/stats.c119
-rw-r--r--net/sunrpc/sunrpc_syms.c6
-rw-r--r--net/sunrpc/svcauth.c122
-rw-r--r--net/sunrpc/svcauth_unix.c229
-rw-r--r--net/sunrpc/xprt.c29
-rw-r--r--net/sunrpc/xprtsock.c49
-rw-r--r--net/unix/af_unix.c2
-rw-r--r--scripts/Kbuild.include65
-rw-r--r--scripts/Makefile.build27
-rw-r--r--scripts/Makefile.clean10
-rw-r--r--scripts/Makefile.modinst10
-rw-r--r--scripts/Makefile.modpost21
-rw-r--r--scripts/basic/fixdep.c14
-rwxr-xr-xscripts/checkconfig.pl65
-rw-r--r--scripts/genksyms/genksyms.c843
-rw-r--r--scripts/genksyms/genksyms.h57
-rw-r--r--scripts/kallsyms.c12
-rw-r--r--scripts/kconfig/Makefile6
-rw-r--r--scripts/kconfig/confdata.c2
-rw-r--r--scripts/kconfig/lxdialog/Makefile6
-rw-r--r--scripts/mkmakefile8
-rw-r--r--scripts/mod/file2alias.c17
-rw-r--r--scripts/mod/mk_elfconfig.c4
-rw-r--r--scripts/mod/modpost.c698
-rw-r--r--scripts/mod/modpost.h25
-rw-r--r--scripts/mod/sumversion.c32
-rw-r--r--scripts/namespace.pl4
-rw-r--r--scripts/package/Makefile20
-rw-r--r--scripts/profile2linkerlist.pl21
-rw-r--r--scripts/reference_discarded.pl112
-rw-r--r--scripts/reference_init.pl108
-rw-r--r--security/commoncap.c4
-rw-r--r--security/dummy.c14
-rw-r--r--security/keys/key.c18
-rw-r--r--security/security.c23
-rw-r--r--security/selinux/hooks.c98
-rw-r--r--security/selinux/nlmsgtab.c9
-rw-r--r--security/selinux/selinuxfs.c11
-rw-r--r--security/selinux/ss/services.c15
-rw-r--r--sound/core/init.c3
-rw-r--r--sound/core/rawmidi.c6
-rw-r--r--sound/core/sound.c4
-rw-r--r--sound/core/sound_oss.c2
-rw-r--r--sound/drivers/mpu401/mpu401.c16
-rw-r--r--sound/isa/ad1816a/ad1816a.c12
-rw-r--r--sound/isa/als100.c14
-rw-r--r--sound/isa/azt2320.c12
-rw-r--r--sound/isa/cmi8330.c15
-rw-r--r--sound/isa/cs423x/cs4236.c25
-rw-r--r--sound/isa/dt019x.c12
-rw-r--r--sound/isa/es18xx.c13
-rw-r--r--sound/isa/gus/interwave.c12
-rw-r--r--sound/isa/opl3sa2.c17
-rw-r--r--sound/isa/sb/es968.c12
-rw-r--r--sound/isa/sb/sb16.c14
-rw-r--r--sound/isa/sscape.c4
-rw-r--r--sound/isa/wavefront/wavefront.c10
-rw-r--r--sound/oss/.gitignore4
-rw-r--r--sound/oss/au1000.c2
-rw-r--r--sound/oss/au1550_ac97.c2
-rw-r--r--sound/oss/awe_wave.c6
-rw-r--r--sound/oss/cmpci.c2
-rw-r--r--sound/oss/cs4232.c15
-rw-r--r--sound/oss/dmasound/dmasound_awacs.c4
-rw-r--r--sound/oss/dmasound/dmasound_core.c10
-rw-r--r--sound/oss/emu10k1/midi.c9
-rw-r--r--sound/oss/esssolo1.c2
-rw-r--r--sound/oss/ite8172.c4
-rw-r--r--sound/oss/maestro3.c10
-rw-r--r--sound/oss/msnd.c6
-rw-r--r--sound/oss/sb_card.c35
-rw-r--r--sound/oss/sb_mixer.c6
-rw-r--r--sound/oss/sequencer.c17
-rw-r--r--sound/oss/sh_dac_audio.c2
-rw-r--r--sound/oss/sonicvibes.c21
-rw-r--r--sound/oss/swarm_cs4297a.c4
-rw-r--r--sound/oss/vwsnd.c40
-rw-r--r--sound/oss/waveartist.c8
-rw-r--r--sound/pci/ad1889.c1
-rw-r--r--sound/pci/ali5451/ali5451.c5
-rw-r--r--sound/pci/als4000.c5
-rw-r--r--sound/pci/azt3328.c5
-rw-r--r--sound/pci/emu10k1/emu10k1x.c1
-rw-r--r--sound/pci/es1938.c5
-rw-r--r--sound/pci/es1968.c1
-rw-r--r--sound/pci/ice1712/ice1712.c2
-rw-r--r--sound/pci/maestro3.c1
-rw-r--r--sound/pci/mixart/mixart.c2
-rw-r--r--sound/pci/pcxhr/pcxhr.c1
-rw-r--r--sound/pci/rme32.c8
-rw-r--r--sound/pci/rme96.c8
-rw-r--r--sound/pci/rme9652/hdspm.c2
-rw-r--r--sound/pci/sonicvibes.c5
-rw-r--r--sound/pci/trident/trident_main.c5
-rw-r--r--sound/ppc/pmac.c2
-rw-r--r--sound/sound_core.c22
-rw-r--r--sound/sparc/cs4231.c6
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c2
2279 files changed, 68017 insertions, 44437 deletions
diff --git a/CREDITS b/CREDITS
index af70678a0af..0bf31eac6dc 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1127,8 +1127,10 @@ S: Carnegie, Pennsylvania 15106-4304
S: USA
N: Philip Gladstone
-E: philip@raptor.com
+E: philip@gladstonefamily.net
D: Kernel / timekeeping stuff
+S: Carlisle, MA 01741
+S: USA
N: Jan-Benedict Glaw
E: jbglaw@lug-owl.de
@@ -2007,13 +2009,14 @@ S: University of Stuttgart, Germany and
S: Ecole Nationale Superieure des Telecommunications, Paris
N: Jamie Lokier
-E: jamie@imbolc.ucc.ie
+E: jamie@shareable.org
+W: http://www.shareable.org/
D: Reboot-through-BIOS for broken 486 motherboards
-D: Some parport fixes
-S: 11 Goodson Walk
-S: Marston
+D: Parport fixes, futex improvements
+D: First instruction of x86 sysenter path :)
+S: 51 Sunningwell Road
S: Oxford
-S: OX3 0HX
+S: OX1 4SZ
S: United Kingdom
N: Mark Lord
@@ -3740,10 +3743,11 @@ D: Mylex DAC960 PCI RAID driver
D: Miscellaneous kernel fixes
N: Alessandro Zummo
-E: azummo@ita.flashnet.it
-W: http://freepage.logicom.it/azummo/
+E: a.zummo@towertech.it
D: CMI8330 support is sb_card.c
D: ISAPnP fixes in sb_card.c
+D: ZyXEL omni.net lcd plus driver
+D: RTC subsystem
S: Italy
N: Marc Zyngier
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
index 684557474c1..ee4bb73683c 100644
--- a/Documentation/DMA-mapping.txt
+++ b/Documentation/DMA-mapping.txt
@@ -199,6 +199,8 @@ address during PCI bus mastering you might do something like:
"mydev: 24-bit DMA addressing not available.\n");
goto ignore_this_device;
}
+[Better use DMA_24BIT_MASK instead of 0x00ffffff.
+See linux/include/dma-mapping.h for reference.]
When pci_set_dma_mask() is successful, and returns zero, the PCI layer
saves away this mask you have provided. The PCI layer will use this
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 2975291e296..7d87dd73cbe 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -28,7 +28,7 @@ PS_METHOD = $(prefer-db2x)
###
# The targets that may be used.
-.PHONY: xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs
+PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs
BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
xmldocs: $(BOOKS)
@@ -211,3 +211,9 @@ clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS))
#man put files in man subdir - traverse down
subdir- := man/
+
+
+# Declare the contents of the .PHONY variable as phony. We keep that
+# information in a variable se we can use it in if_changed and friends.
+
+.PHONY: $(PHONY)
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
index 5ed85af8878..07cb93b82ba 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.txt
@@ -360,7 +360,7 @@ uses of RCU may be found in listRCU.txt, arrayRCU.txt, and NMI-RCU.txt.
struct foo *new_fp;
struct foo *old_fp;
- new_fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+ new_fp = kmalloc(sizeof(*new_fp), GFP_KERNEL);
spin_lock(&foo_mutex);
old_fp = gbl_foo;
*new_fp = *old_fp;
@@ -461,7 +461,7 @@ The foo_update_a() function might then be written as follows:
struct foo *new_fp;
struct foo *old_fp;
- new_fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+ new_fp = kmalloc(sizeof(*new_fp), GFP_KERNEL);
spin_lock(&foo_mutex);
old_fp = gbl_foo;
*new_fp = *old_fp;
@@ -605,7 +605,7 @@ are the same as those shown in the preceding section, so they are omitted.
{
int cpu;
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
run_on(cpu);
}
diff --git a/Documentation/aoe/mkdevs.sh b/Documentation/aoe/mkdevs.sh
index ec5a6de1cd7..97374aacacb 100644
--- a/Documentation/aoe/mkdevs.sh
+++ b/Documentation/aoe/mkdevs.sh
@@ -27,6 +27,8 @@ rm -f $dir/discover
mknod -m 0200 $dir/discover c $MAJOR 3
rm -f $dir/interfaces
mknod -m 0200 $dir/interfaces c $MAJOR 4
+rm -f $dir/revalidate
+mknod -m 0200 $dir/revalidate c $MAJOR 5
export n_partitions
mkshelf=`echo $0 | sed 's!mkdevs!mkshelf!'`
diff --git a/Documentation/aoe/udev.txt b/Documentation/aoe/udev.txt
index ab39d8bb634..a7ed1dc4f33 100644
--- a/Documentation/aoe/udev.txt
+++ b/Documentation/aoe/udev.txt
@@ -18,6 +18,7 @@
SUBSYSTEM="aoe", KERNEL="discover", NAME="etherd/%k", GROUP="disk", MODE="0220"
SUBSYSTEM="aoe", KERNEL="err", NAME="etherd/%k", GROUP="disk", MODE="0440"
SUBSYSTEM="aoe", KERNEL="interfaces", NAME="etherd/%k", GROUP="disk", MODE="0220"
+SUBSYSTEM="aoe", KERNEL="revalidate", NAME="etherd/%k", GROUP="disk", MODE="0220"
# aoe block devices
KERNEL="etherd*", NAME="%k", GROUP="disk"
diff --git a/Documentation/arm/Booting b/Documentation/arm/Booting
index fad566bb02f..76850295af8 100644
--- a/Documentation/arm/Booting
+++ b/Documentation/arm/Booting
@@ -118,7 +118,7 @@ to store page tables. The recommended placement is 32KiB into RAM.
In either case, the following conditions must be met:
-- Quiesce all DMA capable devicess so that memory does not get
+- Quiesce all DMA capable devices so that memory does not get
corrupted by bogus network packets or disk data. This will save
you many hours of debug.
diff --git a/Documentation/arm/README b/Documentation/arm/README
index 5ed6f3530b8..9b9c8226fdc 100644
--- a/Documentation/arm/README
+++ b/Documentation/arm/README
@@ -89,7 +89,7 @@ Modules
Although modularisation is supported (and required for the FP emulator),
each module on an ARM2/ARM250/ARM3 machine when is loaded will take
memory up to the next 32k boundary due to the size of the pages.
- Therefore, modularisation on these machines really worth it?
+ Therefore, is modularisation on these machines really worth it?
However, ARM6 and up machines allow modules to take multiples of 4k, and
as such Acorn RiscPCs and other architectures using these processors can
diff --git a/Documentation/arm/SA1100/Assabet b/Documentation/arm/SA1100/Assabet
index cbbe5587c78..78bc1c1b04e 100644
--- a/Documentation/arm/SA1100/Assabet
+++ b/Documentation/arm/SA1100/Assabet
@@ -26,7 +26,7 @@ Installing a bootloader
A couple of bootloaders able to boot Linux on Assabet are available:
-BLOB (http://www.lart.tudelft.nl/lartware/blob/)
+BLOB (http://www.lartmaker.nl/lartware/blob/)
BLOB is a bootloader used within the LART project. Some contributed
patches were merged into BLOB to add support for Assabet.
diff --git a/Documentation/arm/SA1100/LART b/Documentation/arm/SA1100/LART
index 2f73f513e16..6d412b68559 100644
--- a/Documentation/arm/SA1100/LART
+++ b/Documentation/arm/SA1100/LART
@@ -11,4 +11,4 @@ is under development, with plenty of others in different stages of
planning.
The hardware designs for this board have been released under an open license;
-see the LART page at http://www.lart.tudelft.nl/ for more information.
+see the LART page at http://www.lartmaker.nl/ for more information.
diff --git a/Documentation/arm/Setup b/Documentation/arm/Setup
index 0abd0720d7e..0cb1e64bde8 100644
--- a/Documentation/arm/Setup
+++ b/Documentation/arm/Setup
@@ -58,7 +58,7 @@ below:
video_y
This describes the character position of cursor on VGA console, and
- is otherwise unused. (should not used for other console types, and
+ is otherwise unused. (should not be used for other console types, and
should not be used for other purposes).
memc_control_reg
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index 8e63831971d..f989a9e839b 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -132,8 +132,18 @@ Some new queue property settings:
limit. No highmem default.
blk_queue_max_sectors(q, max_sectors)
- Maximum size request you can handle in units of 512 byte
- sectors. 255 default.
+ Sets two variables that limit the size of the request.
+
+ - The request queue's max_sectors, which is a soft size in
+ in units of 512 byte sectors, and could be dynamically varied
+ by the core kernel.
+
+ - The request queue's max_hw_sectors, which is a hard limit
+ and reflects the maximum size request a driver can handle
+ in units of 512 byte sectors.
+
+ The default for both max_sectors and max_hw_sectors is
+ 255. The upper limit of max_sectors is 1024.
blk_queue_max_phys_segments(q, max_segments)
Maximum physical segments you can handle in a request. 128
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
index 4ae418889b8..53245c429f7 100644
--- a/Documentation/cachetlb.txt
+++ b/Documentation/cachetlb.txt
@@ -362,6 +362,27 @@ maps this page at its virtual address.
likely that you will need to flush the instruction cache
for copy_to_user_page().
+ void flush_anon_page(struct page *page, unsigned long vmaddr)
+ When the kernel needs to access the contents of an anonymous
+ page, it calls this function (currently only
+ get_user_pages()). Note: flush_dcache_page() deliberately
+ doesn't work for an anonymous page. The default
+ implementation is a nop (and should remain so for all coherent
+ architectures). For incoherent architectures, it should flush
+ the cache of the page at vmaddr in the current user process.
+
+ void flush_kernel_dcache_page(struct page *page)
+ When the kernel needs to modify a user page is has obtained
+ with kmap, it calls this function after all modifications are
+ complete (but before kunmapping it) to bring the underlying
+ page up to date. It is assumed here that the user has no
+ incoherent cached copies (i.e. the original page was obtained
+ from a mechanism like get_user_pages()). The default
+ implementation is a nop and should remain so on all coherent
+ architectures. On incoherent architectures, this should flush
+ the kernel cache for page (using page_address(page)).
+
+
void flush_icache_range(unsigned long start, unsigned long end)
When the kernel stores into addresses that it will execute
out of (eg when loading modules), this function is called.
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt
index 57a09f99ecb..1bcf69996c9 100644
--- a/Documentation/cpu-hotplug.txt
+++ b/Documentation/cpu-hotplug.txt
@@ -97,13 +97,13 @@ at which time hotplug is disabled.
You really dont need to manipulate any of the system cpu maps. They should
be read-only for most use. When setting up per-cpu resources almost always use
-cpu_possible_map/for_each_cpu() to iterate.
+cpu_possible_map/for_each_possible_cpu() to iterate.
Never use anything other than cpumask_t to represent bitmap of CPUs.
#include <linux/cpumask.h>
-for_each_cpu - Iterate over cpu_possible_map
+for_each_possible_cpu - Iterate over cpu_possible_map
for_each_online_cpu - Iterate over cpu_online_map
for_each_present_cpu - Iterate over cpu_present_map
for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask.
diff --git a/Documentation/cputopology.txt b/Documentation/cputopology.txt
index ff280e2e161..2b28e9ec4e3 100644
--- a/Documentation/cputopology.txt
+++ b/Documentation/cputopology.txt
@@ -1,5 +1,5 @@
-Export cpu topology info by sysfs. Items (attributes) are similar
+Export cpu topology info via sysfs. Items (attributes) are similar
to /proc/cpuinfo.
1) /sys/devices/system/cpu/cpuX/topology/physical_package_id:
@@ -12,7 +12,7 @@ represent the thread siblings to cpu X in the same core;
represent the thread siblings to cpu X in the same physical package;
To implement it in an architecture-neutral way, a new source file,
-driver/base/topology.c, is to export the 5 attributes.
+drivers/base/topology.c, is to export the 4 attributes.
If one architecture wants to support this feature, it just needs to
implement 4 defines, typically in file include/asm-XXX/topology.h.
diff --git a/Documentation/drivers/edac/edac.txt b/Documentation/drivers/edac/edac.txt
index d37191fe568..70d96a62e5e 100644
--- a/Documentation/drivers/edac/edac.txt
+++ b/Documentation/drivers/edac/edac.txt
@@ -21,7 +21,7 @@ within the computer system. In the initial release, memory Correctable Errors
Detecting CE events, then harvesting those events and reporting them,
CAN be a predictor of future UE events. With CE events, the system can
-continue to operate, but with less safety. Preventive maintainence and
+continue to operate, but with less safety. Preventive maintenance and
proactive part replacement of memory DIMMs exhibiting CEs can reduce
the likelihood of the dreaded UE events and system 'panics'.
@@ -29,13 +29,13 @@ the likelihood of the dreaded UE events and system 'panics'.
In addition, PCI Bus Parity and SERR Errors are scanned for on PCI devices
in order to determine if errors are occurring on data transfers.
The presence of PCI Parity errors must be examined with a grain of salt.
-There are several addin adapters that do NOT follow the PCI specification
+There are several add-in adapters that do NOT follow the PCI specification
with regards to Parity generation and reporting. The specification says
the vendor should tie the parity status bits to 0 if they do not intend
to generate parity. Some vendors do not do this, and thus the parity bit
can "float" giving false positives.
-The PCI Parity EDAC device has the ability to "skip" known flakey
+The PCI Parity EDAC device has the ability to "skip" known flaky
cards during the parity scan. These are set by the parity "blacklist"
interface in the sysfs for PCI Parity. (See the PCI section in the sysfs
section below.) There is also a parity "whitelist" which is used as
@@ -101,7 +101,7 @@ Memory Controller (mc) Model
First a background on the memory controller's model abstracted in EDAC.
Each mc device controls a set of DIMM memory modules. These modules are
-layed out in a Chip-Select Row (csrowX) and Channel table (chX). There can
+laid out in a Chip-Select Row (csrowX) and Channel table (chX). There can
be multiple csrows and two channels.
Memory controllers allow for several csrows, with 8 csrows being a typical value.
@@ -131,7 +131,7 @@ for memory DIMMs:
DIMM_B1
Labels for these slots are usually silk screened on the motherboard. Slots
-labeled 'A' are channel 0 in this example. Slots labled 'B'
+labeled 'A' are channel 0 in this example. Slots labeled 'B'
are channel 1. Notice that there are two csrows possible on a
physical DIMM. These csrows are allocated their csrow assignment
based on the slot into which the memory DIMM is placed. Thus, when 1 DIMM
@@ -140,7 +140,7 @@ is placed in each Channel, the csrows cross both DIMMs.
Memory DIMMs come single or dual "ranked". A rank is a populated csrow.
Thus, 2 single ranked DIMMs, placed in slots DIMM_A0 and DIMM_B0 above
will have 1 csrow, csrow0. csrow1 will be empty. On the other hand,
-when 2 dual ranked DIMMs are similiaryly placed, then both csrow0 and
+when 2 dual ranked DIMMs are similarly placed, then both csrow0 and
csrow1 will be populated. The pattern repeats itself for csrow2 and
csrow3.
@@ -246,7 +246,7 @@ Module Version read-only attribute file:
'mc_version'
- The EDAC CORE modules's version and compile date are shown here to
+ The EDAC CORE module's version and compile date are shown here to
indicate what EDAC is running.
@@ -423,7 +423,7 @@ Total memory managed by this csrow attribute file:
'size_mb'
This attribute file displays, in count of megabytes, of memory
- that this csrow contatins.
+ that this csrow contains.
Memory Type attribute file:
@@ -557,7 +557,7 @@ On Header Type 00 devices the primary status is looked at
for any parity error regardless of whether Parity is enabled on the
device. (The spec indicates parity is generated in some cases).
On Header Type 01 bridges, the secondary status register is also
-looked at to see if parity ocurred on the bus on the other side of
+looked at to see if parity occurred on the bus on the other side of
the bridge.
@@ -588,7 +588,7 @@ Panic on PCI PARITY Error:
'panic_on_pci_parity'
- This control files enables or disables panic'ing when a parity
+ This control files enables or disables panicking when a parity
error has been detected.
@@ -616,12 +616,12 @@ PCI Device Whitelist:
This control file allows for an explicit list of PCI devices to be
scanned for parity errors. Only devices found on this list will
- be examined. The list is a line of hexadecimel VENDOR and DEVICE
+ be examined. The list is a line of hexadecimal VENDOR and DEVICE
ID tuples:
1022:7450,1434:16a6
- One or more can be inserted, seperated by a comma.
+ One or more can be inserted, separated by a comma.
To write the above list doing the following as one command line:
@@ -639,11 +639,11 @@ PCI Device Blacklist:
This control file allows for a list of PCI devices to be
skipped for scanning.
- The list is a line of hexadecimel VENDOR and DEVICE ID tuples:
+ The list is a line of hexadecimal VENDOR and DEVICE ID tuples:
1022:7450,1434:16a6
- One or more can be inserted, seperated by a comma.
+ One or more can be inserted, separated by a comma.
To write the above list doing the following as one command line:
@@ -651,14 +651,14 @@ PCI Device Blacklist:
> /sys/devices/system/edac/pci/pci_parity_blacklist
- To display what the whitelist current contatins,
+ To display what the whitelist currently contains,
simply 'cat' the same file.
=======================================================================
PCI Vendor and Devices IDs can be obtained with the lspci command. Using
the -n option lspci will display the vendor and device IDs. The system
-adminstrator will have to determine which devices should be scanned or
+administrator will have to determine which devices should be scanned or
skipped.
@@ -669,5 +669,5 @@ Turn OFF a whitelist by an empty echo command:
echo > /sys/devices/system/edac/pci/pci_parity_whitelist
-and any previous blacklist will be utililzed.
+and any previous blacklist will be utilized.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 21272e4b4a5..495858b236b 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -176,6 +176,18 @@ Who: Richard Knutsson <ricknu-0@student.ltu.se> and Greg Kroah-Hartman <gregkh@s
---------------------------
+What: Usage of invalid timevals in setitimer
+When: March 2007
+Why: POSIX requires to validate timevals in the setitimer call. This
+ was never done by Linux. The invalid (e.g. negative timevals) were
+ silently converted to more or less random timeouts and intervals.
+ Until the removal a per boot limited number of warnings is printed
+ and the timevals are sanitized.
+
+Who: Thomas Gleixner <tglx@linutronix.de>
+
+---------------------------
+
What: I2C interface of the it87 driver
When: January 2007
Why: The ISA interface is faster and should be always available. The I2C
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
index 74052d22d86..66fdc0744fe 100644
--- a/Documentation/filesystems/00-INDEX
+++ b/Documentation/filesystems/00-INDEX
@@ -1,27 +1,47 @@
00-INDEX
- this file (info on some of the filesystems supported by linux).
+Exporting
+ - explanation of how to make filesystems exportable.
Locking
- info on locking rules as they pertain to Linux VFS.
adfs.txt
- info and mount options for the Acorn Advanced Disc Filing System.
+afs.txt
+ - info and examples for the distributed AFS (Andrew File System) fs.
affs.txt
- info and mount options for the Amiga Fast File System.
+automount-support.txt
+ - information about filesystem automount support.
+befs.txt
+ - information about the BeOS filesystem for Linux.
bfs.txt
- info for the SCO UnixWare Boot Filesystem (BFS).
cifs.txt
- - description of the CIFS filesystem
+ - description of the CIFS filesystem.
coda.txt
- description of the CODA filesystem.
configfs/
- directory containing configfs documentation and example code.
cramfs.txt
- - info on the cram filesystem for small storage (ROMs etc)
+ - info on the cram filesystem for small storage (ROMs etc).
+dentry-locking.txt
+ - info on the RCU-based dcache locking model.
devfs/
- directory containing devfs documentation.
+directory-locking
+ - info about the locking scheme used for directory operations.
dlmfs.txt
- info on the userspace interface to the OCFS2 DLM.
ext2.txt
- info, mount options and specifications for the Ext2 filesystem.
+ext3.txt
+ - info, mount options and specifications for the Ext3 filesystem.
+files.txt
+ - info on file management in the Linux kernel.
+fuse.txt
+ - info on the Filesystem in User SpacE including mount options.
+hfs.txt
+ - info on the Macintosh HFS Filesystem for Linux.
hpfs.txt
- info and mount options for the OS/2 HPFS.
isofs.txt
@@ -32,23 +52,43 @@ ncpfs.txt
- info on Novell Netware(tm) filesystem using NCP protocol.
ntfs.txt
- info and mount options for the NTFS filesystem (Windows NT).
-proc.txt
- - info on Linux's /proc filesystem.
ocfs2.txt
- info and mount options for the OCFS2 clustered filesystem.
+porting
+ - various information on filesystem porting.
+proc.txt
+ - info on Linux's /proc filesystem.
+ramfs-rootfs-initramfs.txt
+ - info on the 'in memory' filesystems ramfs, rootfs and initramfs.
+reiser4.txt
+ - info on the Reiser4 filesystem based on dancing tree algorithms.
+relayfs.txt
+ - info on relayfs, for efficient streaming from kernel to user space.
romfs.txt
- - Description of the ROMFS filesystem.
+ - description of the ROMFS filesystem.
smbfs.txt
- - info on using filesystems with the SMB protocol (Windows 3.11 and NT)
+ - info on using filesystems with the SMB protocol (Win 3.11 and NT).
+spufs.txt
+ - info and mount options for the SPU filesystem used on Cell.
+sysfs-pci.txt
+ - info on accessing PCI device resources through sysfs.
+sysfs.txt
+ - info on sysfs, a ram-based filesystem for exporting kernel objects.
sysv-fs.txt
- info on the SystemV/V7/Xenix/Coherent filesystem.
+tmpfs.txt
+ - info on tmpfs, a filesystem that holds all files in virtual memory.
udf.txt
- info and mount options for the UDF filesystem.
ufs.txt
- info on the ufs filesystem.
+v9fs.txt
+ - v9fs is a Unix implementation of the Plan 9 9p remote fs protocol.
vfat.txt
- info on using the VFAT filesystem used in Windows NT and Windows 95
vfs.txt
- - Overview of the Virtual File System
+ - overview of the Virtual File System
xfs.txt
- info and mount options for the XFS filesystem.
+xip.txt
+ - info on execute-in-place for file mappings.
diff --git a/Documentation/filesystems/v9fs.txt b/Documentation/filesystems/9p.txt
index 24c7a9c41f0..43b89c214d2 100644
--- a/Documentation/filesystems/v9fs.txt
+++ b/Documentation/filesystems/9p.txt
@@ -1,5 +1,5 @@
- V9FS: 9P2000 for Linux
- ======================
+ v9fs: Plan 9 Resource Sharing for Linux
+ =======================================
ABOUT
=====
@@ -9,18 +9,19 @@ v9fs is a Unix implementation of the Plan 9 9p remote filesystem protocol.
This software was originally developed by Ron Minnich <rminnich@lanl.gov>
and Maya Gokhale <maya@lanl.gov>. Additional development by Greg Watson
<gwatson@lanl.gov> and most recently Eric Van Hensbergen
-<ericvh@gmail.com> and Latchesar Ionkov <lucho@ionkov.net>.
+<ericvh@gmail.com>, Latchesar Ionkov <lucho@ionkov.net> and Russ Cox
+<rsc@swtch.com>.
USAGE
=====
For remote file server:
- mount -t 9P 10.10.1.2 /mnt/9
+ mount -t 9p 10.10.1.2 /mnt/9
For Plan 9 From User Space applications (http://swtch.com/plan9)
- mount -t 9P `namespace`/acme /mnt/9 -o proto=unix,name=$USER
+ mount -t 9p `namespace`/acme /mnt/9 -o proto=unix,uname=$USER
OPTIONS
=======
@@ -32,7 +33,7 @@ OPTIONS
fd - used passed file descriptors for connection
(see rfdno and wfdno)
- name=name user name to attempt mount as on the remote server. The
+ uname=name user name to attempt mount as on the remote server. The
server may override or ignore this value. Certain user
names may require authentication.
@@ -42,7 +43,7 @@ OPTIONS
debug=n specifies debug level. The debug level is a bitmask.
0x01 = display verbose error messages
0x02 = developer debug (DEBUG_CURRENT)
- 0x04 = display 9P trace
+ 0x04 = display 9p trace
0x08 = display VFS trace
0x10 = display Marshalling debug
0x20 = display RPC debug
@@ -53,11 +54,11 @@ OPTIONS
wfdno=n the file descriptor for writing with proto=fd
- maxdata=n the number of bytes to use for 9P packet payload (msize)
+ maxdata=n the number of bytes to use for 9p packet payload (msize)
port=n port to connect to on the remote server
- noextend force legacy mode (no 9P2000.u semantics)
+ noextend force legacy mode (no 9p2000.u semantics)
uid attempt to mount as a particular uid
@@ -72,7 +73,7 @@ OPTIONS
RESOURCES
=========
-The Linux version of the 9P server is now maintained under the npfs project
+The Linux version of the 9p server is now maintained under the npfs project
on sourceforge (http://sourceforge.net/projects/npfs).
There are user and developer mailing lists available through the v9fs project
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 944cf109a6f..99902ae6804 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -121,7 +121,7 @@ Table 1-1: Process specific entries in /proc
..............................................................................
File Content
cmdline Command line arguments
- cpu Current and last cpu in wich it was executed (2.4)(smp)
+ cpu Current and last cpu in which it was executed (2.4)(smp)
cwd Link to the current working directory
environ Values of environment variables
exe Link to the executable of this process
@@ -309,13 +309,13 @@ is the same by default:
> cat /proc/irq/0/smp_affinity
ffffffff
-It's a bitmask, in wich you can specify wich CPUs can handle the IRQ, you can
+It's a bitmask, in which you can specify which CPUs can handle the IRQ, you can
set it by doing:
> echo 1 > /proc/irq/prof_cpu_mask
This means that only the first CPU will handle the IRQ, but you can also echo 5
-wich means that only the first and fourth CPU can handle the IRQ.
+which means that only the first and fourth CPU can handle the IRQ.
The way IRQs are routed is handled by the IO-APIC, and it's Round Robin
between all the CPUs which are allowed to handle it. As usual the kernel has
diff --git a/Documentation/filesystems/udf.txt b/Documentation/filesystems/udf.txt
index e5213bc301f..511b4230c05 100644
--- a/Documentation/filesystems/udf.txt
+++ b/Documentation/filesystems/udf.txt
@@ -26,6 +26,20 @@ The following mount options are supported:
nostrict Unset strict conformance
iocharset= Set the NLS character set
+The uid= and gid= options need a bit more explaining. They will accept a
+decimal numeric value which will be used as the default ID for that mount.
+They will also accept the string "ignore" and "forget". For files on the disk
+that are owned by nobody ( -1 ), they will instead look as if they are owned
+by the default ID. The ignore option causes the default ID to override all
+IDs on the disk, not just -1. The forget option causes all IDs to be written
+to disk as -1, so when the media is later remounted, they will appear to be
+owned by whatever default ID it is mounted with at that time.
+
+For typical desktop use of removable media, you should set the ID to that
+of the interactively logged on user, and also specify both the forget and
+ignore options. This way the interactive user will always see the files
+on the disk as belonging to him.
+
The remaining are for debugging and disaster recovery:
novrs Skip volume sequence recognition
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index e56e842847d..adaa899e5c9 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -230,10 +230,15 @@ only called from a process context (i.e. not from an interrupt handler
or bottom half).
alloc_inode: this method is called by inode_alloc() to allocate memory
- for struct inode and initialize it.
+ for struct inode and initialize it. If this function is not
+ defined, a simple 'struct inode' is allocated. Normally
+ alloc_inode will be used to allocate a larger structure which
+ contains a 'struct inode' embedded within it.
destroy_inode: this method is called by destroy_inode() to release
- resources allocated for struct inode.
+ resources allocated for struct inode. It is only required if
+ ->alloc_inode was defined and simply undoes anything done by
+ ->alloc_inode.
read_inode: this method is called to read a specific inode from the
mounted filesystem. The i_ino member in the struct inode is
@@ -443,14 +448,81 @@ otherwise noted.
The Address Space Object
========================
-The address space object is used to identify pages in the page cache.
-
+The address space object is used to group and manage pages in the page
+cache. It can be used to keep track of the pages in a file (or
+anything else) and also track the mapping of sections of the file into
+process address spaces.
+
+There are a number of distinct yet related services that an
+address-space can provide. These include communicating memory
+pressure, page lookup by address, and keeping track of pages tagged as
+Dirty or Writeback.
+
+The first can be used independently to the others. The VM can try to
+either write dirty pages in order to clean them, or release clean
+pages in order to reuse them. To do this it can call the ->writepage
+method on dirty pages, and ->releasepage on clean pages with
+PagePrivate set. Clean pages without PagePrivate and with no external
+references will be released without notice being given to the
+address_space.
+
+To achieve this functionality, pages need to be placed on an LRU with
+lru_cache_add and mark_page_active needs to be called whenever the
+page is used.
+
+Pages are normally kept in a radix tree index by ->index. This tree
+maintains information about the PG_Dirty and PG_Writeback status of
+each page, so that pages with either of these flags can be found
+quickly.
+
+The Dirty tag is primarily used by mpage_writepages - the default
+->writepages method. It uses the tag to find dirty pages to call
+->writepage on. If mpage_writepages is not used (i.e. the address
+provides its own ->writepages) , the PAGECACHE_TAG_DIRTY tag is
+almost unused. write_inode_now and sync_inode do use it (through
+__sync_single_inode) to check if ->writepages has been successful in
+writing out the whole address_space.
+
+The Writeback tag is used by filemap*wait* and sync_page* functions,
+via wait_on_page_writeback_range, to wait for all writeback to
+complete. While waiting ->sync_page (if defined) will be called on
+each page that is found to require writeback.
+
+An address_space handler may attach extra information to a page,
+typically using the 'private' field in the 'struct page'. If such
+information is attached, the PG_Private flag should be set. This will
+cause various VM routines to make extra calls into the address_space
+handler to deal with that data.
+
+An address space acts as an intermediate between storage and
+application. Data is read into the address space a whole page at a
+time, and provided to the application either by copying of the page,
+or by memory-mapping the page.
+Data is written into the address space by the application, and then
+written-back to storage typically in whole pages, however the
+address_space has finer control of write sizes.
+
+The read process essentially only requires 'readpage'. The write
+process is more complicated and uses prepare_write/commit_write or
+set_page_dirty to write data into the address_space, and writepage,
+sync_page, and writepages to writeback data to storage.
+
+Adding and removing pages to/from an address_space is protected by the
+inode's i_mutex.
+
+When data is written to a page, the PG_Dirty flag should be set. It
+typically remains set until writepage asks for it to be written. This
+should clear PG_Dirty and set PG_Writeback. It can be actually
+written at any point after PG_Dirty is clear. Once it is known to be
+safe, PG_Writeback is cleared.
+
+Writeback makes use of a writeback_control structure...
struct address_space_operations
-------------------------------
This describes how the VFS can manipulate mapping of a file to page cache in
-your filesystem. As of kernel 2.6.13, the following members are defined:
+your filesystem. As of kernel 2.6.16, the following members are defined:
struct address_space_operations {
int (*writepage)(struct page *page, struct writeback_control *wbc);
@@ -469,47 +541,148 @@ struct address_space_operations {
loff_t offset, unsigned long nr_segs);
struct page* (*get_xip_page)(struct address_space *, sector_t,
int);
+ /* migrate the contents of a page to the specified target */
+ int (*migratepage) (struct page *, struct page *);
};
- writepage: called by the VM write a dirty page to backing store.
+ writepage: called by the VM to write a dirty page to backing store.
+ This may happen for data integrity reasons (i.e. 'sync'), or
+ to free up memory (flush). The difference can be seen in
+ wbc->sync_mode.
+ The PG_Dirty flag has been cleared and PageLocked is true.
+ writepage should start writeout, should set PG_Writeback,
+ and should make sure the page is unlocked, either synchronously
+ or asynchronously when the write operation completes.
+
+ If wbc->sync_mode is WB_SYNC_NONE, ->writepage doesn't have to
+ try too hard if there are problems, and may choose to write out
+ other pages from the mapping if that is easier (e.g. due to
+ internal dependencies). If it chooses not to start writeout, it
+ should return AOP_WRITEPAGE_ACTIVATE so that the VM will not keep
+ calling ->writepage on that page.
+
+ See the file "Locking" for more details.
readpage: called by the VM to read a page from backing store.
+ The page will be Locked when readpage is called, and should be
+ unlocked and marked uptodate once the read completes.
+ If ->readpage discovers that it needs to unlock the page for
+ some reason, it can do so, and then return AOP_TRUNCATED_PAGE.
+ In this case, the page will be relocated, relocked and if
+ that all succeeds, ->readpage will be called again.
sync_page: called by the VM to notify the backing store to perform all
queued I/O operations for a page. I/O operations for other pages
associated with this address_space object may also be performed.
+ This function is optional and is called only for pages with
+ PG_Writeback set while waiting for the writeback to complete.
+
writepages: called by the VM to write out pages associated with the
- address_space object.
+ address_space object. If wbc->sync_mode is WBC_SYNC_ALL, then
+ the writeback_control will specify a range of pages that must be
+ written out. If it is WBC_SYNC_NONE, then a nr_to_write is given
+ and that many pages should be written if possible.
+ If no ->writepages is given, then mpage_writepages is used
+ instead. This will choose pages from the address space that are
+ tagged as DIRTY and will pass them to ->writepage.
set_page_dirty: called by the VM to set a page dirty.
+ This is particularly needed if an address space attaches
+ private data to a page, and that data needs to be updated when
+ a page is dirtied. This is called, for example, when a memory
+ mapped page gets modified.
+ If defined, it should set the PageDirty flag, and the
+ PAGECACHE_TAG_DIRTY tag in the radix tree.
readpages: called by the VM to read pages associated with the address_space
- object.
+ object. This is essentially just a vector version of
+ readpage. Instead of just one page, several pages are
+ requested.
+ readpages is only used for read-ahead, so read errors are
+ ignored. If anything goes wrong, feel free to give up.
prepare_write: called by the generic write path in VM to set up a write
- request for a page.
-
- commit_write: called by the generic write path in VM to write page to
- its backing store.
+ request for a page. This indicates to the address space that
+ the given range of bytes is about to be written. The
+ address_space should check that the write will be able to
+ complete, by allocating space if necessary and doing any other
+ internal housekeeping. If the write will update parts of
+ any basic-blocks on storage, then those blocks should be
+ pre-read (if they haven't been read already) so that the
+ updated blocks can be written out properly.
+ The page will be locked. If prepare_write wants to unlock the
+ page it, like readpage, may do so and return
+ AOP_TRUNCATED_PAGE.
+ In this case the prepare_write will be retried one the lock is
+ regained.
+
+ commit_write: If prepare_write succeeds, new data will be copied
+ into the page and then commit_write will be called. It will
+ typically update the size of the file (if appropriate) and
+ mark the inode as dirty, and do any other related housekeeping
+ operations. It should avoid returning an error if possible -
+ errors should have been handled by prepare_write.
bmap: called by the VFS to map a logical block offset within object to
- physical block number. This method is use by for the legacy FIBMAP
- ioctl. Other uses are discouraged.
-
- invalidatepage: called by the VM on truncate to disassociate a page from its
- address_space mapping.
-
- releasepage: called by the VFS to release filesystem specific metadata from
- a page.
-
- direct_IO: called by the VM for direct I/O writes and reads.
+ physical block number. This method is used by the FIBMAP
+ ioctl and for working with swap-files. To be able to swap to
+ a file, the file must have a stable mapping to a block
+ device. The swap system does not go through the filesystem
+ but instead uses bmap to find out where the blocks in the file
+ are and uses those addresses directly.
+
+
+ invalidatepage: If a page has PagePrivate set, then invalidatepage
+ will be called when part or all of the page is to be removed
+ from the address space. This generally corresponds to either a
+ truncation or a complete invalidation of the address space
+ (in the latter case 'offset' will always be 0).
+ Any private data associated with the page should be updated
+ to reflect this truncation. If offset is 0, then
+ the private data should be released, because the page
+ must be able to be completely discarded. This may be done by
+ calling the ->releasepage function, but in this case the
+ release MUST succeed.
+
+ releasepage: releasepage is called on PagePrivate pages to indicate
+ that the page should be freed if possible. ->releasepage
+ should remove any private data from the page and clear the
+ PagePrivate flag. It may also remove the page from the
+ address_space. If this fails for some reason, it may indicate
+ failure with a 0 return value.
+ This is used in two distinct though related cases. The first
+ is when the VM finds a clean page with no active users and
+ wants to make it a free page. If ->releasepage succeeds, the
+ page will be removed from the address_space and become free.
+
+ The second case if when a request has been made to invalidate
+ some or all pages in an address_space. This can happen
+ through the fadvice(POSIX_FADV_DONTNEED) system call or by the
+ filesystem explicitly requesting it as nfs and 9fs do (when
+ they believe the cache may be out of date with storage) by
+ calling invalidate_inode_pages2().
+ If the filesystem makes such a call, and needs to be certain
+ that all pages are invalidated, then its releasepage will
+ need to ensure this. Possibly it can clear the PageUptodate
+ bit if it cannot free private data yet.
+
+ direct_IO: called by the generic read/write routines to perform
+ direct_IO - that is IO requests which bypass the page cache
+ and transfer data directly between the storage and the
+ application's address space.
get_xip_page: called by the VM to translate a block number to a page.
The page is valid until the corresponding filesystem is unmounted.
Filesystems that want to use execute-in-place (XIP) need to implement
it. An example implementation can be found in fs/ext2/xip.c.
+ migrate_page: This is used to compact the physical memory usage.
+ If the VM wants to relocate a page (maybe off a memory card
+ that is signalling imminent failure) it will pass a new page
+ and an old page to this function. migrate_page should
+ transfer any private data across and update any references
+ that it has to the page.
The File Object
===============
diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c
index d3ad2c24490..ad3edaba453 100644
--- a/Documentation/firmware_class/firmware_sample_driver.c
+++ b/Documentation/firmware_class/firmware_sample_driver.c
@@ -23,7 +23,6 @@ char __init inkernel_firmware[] = "let's say that this is firmware\n";
#endif
static struct device ghost_device = {
- .name = "Ghost Device",
.bus_id = "ghost0",
};
@@ -92,7 +91,7 @@ static void sample_probe_async(void)
{
/* Let's say that I can't sleep */
int error;
- error = request_firmware_nowait (THIS_MODULE,
+ error = request_firmware_nowait (THIS_MODULE, FW_ACTION_NOHOTPLUG,
"sample_driver_fw", &ghost_device,
"my device pointer",
sample_probe_async_cont);
diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c
index 57b956aecbc..9e1b0e4051c 100644
--- a/Documentation/firmware_class/firmware_sample_firmware_class.c
+++ b/Documentation/firmware_class/firmware_sample_firmware_class.c
@@ -172,7 +172,6 @@ static void fw_remove_class_device(struct class_device *class_dev)
static struct class_device *class_dev;
static struct device my_device = {
- .name = "Sample Device",
.bus_id = "my_dev0",
};
diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
index aa7ba00ec08..171a44ebd93 100644
--- a/Documentation/ioctl-number.txt
+++ b/Documentation/ioctl-number.txt
@@ -78,8 +78,6 @@ Code Seq# Include File Comments
'#' 00-3F IEEE 1394 Subsystem Block for the entire subsystem
'1' 00-1F <linux/timepps.h> PPS kit from Ulrich Windl
<ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/>
-'6' 00-10 <asm-i386/processor.h> Intel IA32 microcode update driver
- <mailto:tigran@veritas.com>
'8' all SNP8023 advanced NIC card
<mailto:mcr@solidum.com>
'A' 00-1F linux/apm_bios.h
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 443230b43e0..a9c00facdf4 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -17,6 +17,7 @@ This document describes the Linux kernel Makefiles.
--- 3.8 Command line dependency
--- 3.9 Dependency tracking
--- 3.10 Special Rules
+ --- 3.11 $(CC) support functions
=== 4 Host Program support
--- 4.1 Simple Host Program
@@ -38,7 +39,6 @@ This document describes the Linux kernel Makefiles.
--- 6.6 Commands useful for building a boot image
--- 6.7 Custom kbuild commands
--- 6.8 Preprocessing linker scripts
- --- 6.9 $(CC) support functions
=== 7 Kbuild Variables
=== 8 Makefile language
@@ -106,9 +106,9 @@ This document is aimed towards normal developers and arch developers.
Most Makefiles within the kernel are kbuild Makefiles that use the
kbuild infrastructure. This chapter introduce the syntax used in the
kbuild makefiles.
-The preferred name for the kbuild files is 'Kbuild' but 'Makefile' will
-continue to be supported. All new developmen is expected to use the
-Kbuild filename.
+The preferred name for the kbuild files are 'Makefile' but 'Kbuild' can
+be used and if both a 'Makefile' and a 'Kbuild' file exists then the 'Kbuild'
+file will be used.
Section 3.1 "Goal definitions" is a quick intro, further chapters provide
more details, with real examples.
@@ -385,6 +385,102 @@ more details, with real examples.
to prerequisites are referenced with $(src) (because they are not
generated files).
+--- 3.11 $(CC) support functions
+
+ The kernel may be build with several different versions of
+ $(CC), each supporting a unique set of features and options.
+ kbuild provide basic support to check for valid options for $(CC).
+ $(CC) is useally the gcc compiler, but other alternatives are
+ available.
+
+ as-option
+ as-option is used to check if $(CC) when used to compile
+ assembler (*.S) files supports the given option. An optional
+ second option may be specified if first option are not supported.
+
+ Example:
+ #arch/sh/Makefile
+ cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),)
+
+ In the above example cflags-y will be assinged the the option
+ -Wa$(comma)-isa=$(isa-y) if it is supported by $(CC).
+ The second argument is optional, and if supplied will be used
+ if first argument is not supported.
+
+ cc-option
+ cc-option is used to check if $(CC) support a given option, and not
+ supported to use an optional second option.
+
+ Example:
+ #arch/i386/Makefile
+ cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)
+
+ In the above example cflags-y will be assigned the option
+ -march=pentium-mmx if supported by $(CC), otherwise -march-i586.
+ The second argument to cc-option is optional, and if omitted
+ cflags-y will be assigned no value if first option is not supported.
+
+ cc-option-yn
+ cc-option-yn is used to check if gcc supports a given option
+ and return 'y' if supported, otherwise 'n'.
+
+ Example:
+ #arch/ppc/Makefile
+ biarch := $(call cc-option-yn, -m32)
+ aflags-$(biarch) += -a32
+ cflags-$(biarch) += -m32
+
+ In the above example $(biarch) is set to y if $(CC) supports the -m32
+ option. When $(biarch) equals to y the expanded variables $(aflags-y)
+ and $(cflags-y) will be assigned the values -a32 and -m32.
+
+ cc-option-align
+ gcc version >= 3.0 shifted type of options used to speify
+ alignment of functions, loops etc. $(cc-option-align) whrn used
+ as prefix to the align options will select the right prefix:
+ gcc < 3.00
+ cc-option-align = -malign
+ gcc >= 3.00
+ cc-option-align = -falign
+
+ Example:
+ CFLAGS += $(cc-option-align)-functions=4
+
+ In the above example the option -falign-functions=4 is used for
+ gcc >= 3.00. For gcc < 3.00 -malign-functions=4 is used.
+
+ cc-version
+ cc-version return a numerical version of the $(CC) compiler version.
+ The format is <major><minor> where both are two digits. So for example
+ gcc 3.41 would return 0341.
+ cc-version is useful when a specific $(CC) version is faulty in one
+ area, for example the -mregparm=3 were broken in some gcc version
+ even though the option was accepted by gcc.
+
+ Example:
+ #arch/i386/Makefile
+ cflags-y += $(shell \
+ if [ $(call cc-version) -ge 0300 ] ; then \
+ echo "-mregparm=3"; fi ;)
+
+ In the above example -mregparm=3 is only used for gcc version greater
+ than or equal to gcc 3.0.
+
+ cc-ifversion
+ cc-ifversion test the version of $(CC) and equals last argument if
+ version expression is true.
+
+ Example:
+ #fs/reiserfs/Makefile
+ EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0402, -O1)
+
+ In this example EXTRA_CFLAGS will be assigned the value -O1 if the
+ $(CC) version is less than 4.2.
+ cc-ifversion takes all the shell operators:
+ -eq, -ne, -lt, -le, -gt, and -ge
+ The third parameter may be a text as in this example, but it may also
+ be an expanded variable or a macro.
+
=== 4 Host Program support
@@ -973,74 +1069,6 @@ When kbuild executes the following steps are followed (roughly):
architecture specific files.
---- 6.9 $(CC) support functions
-
- The kernel may be build with several different versions of
- $(CC), each supporting a unique set of features and options.
- kbuild provide basic support to check for valid options for $(CC).
- $(CC) is useally the gcc compiler, but other alternatives are
- available.
-
- cc-option
- cc-option is used to check if $(CC) support a given option, and not
- supported to use an optional second option.
-
- Example:
- #arch/i386/Makefile
- cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)
-
- In the above example cflags-y will be assigned the option
- -march=pentium-mmx if supported by $(CC), otherwise -march-i586.
- The second argument to cc-option is optional, and if omitted
- cflags-y will be assigned no value if first option is not supported.
-
- cc-option-yn
- cc-option-yn is used to check if gcc supports a given option
- and return 'y' if supported, otherwise 'n'.
-
- Example:
- #arch/ppc/Makefile
- biarch := $(call cc-option-yn, -m32)
- aflags-$(biarch) += -a32
- cflags-$(biarch) += -m32
-
- In the above example $(biarch) is set to y if $(CC) supports the -m32
- option. When $(biarch) equals to y the expanded variables $(aflags-y)
- and $(cflags-y) will be assigned the values -a32 and -m32.
-
- cc-option-align
- gcc version >= 3.0 shifted type of options used to speify
- alignment of functions, loops etc. $(cc-option-align) whrn used
- as prefix to the align options will select the right prefix:
- gcc < 3.00
- cc-option-align = -malign
- gcc >= 3.00
- cc-option-align = -falign
-
- Example:
- CFLAGS += $(cc-option-align)-functions=4
-
- In the above example the option -falign-functions=4 is used for
- gcc >= 3.00. For gcc < 3.00 -malign-functions=4 is used.
-
- cc-version
- cc-version return a numerical version of the $(CC) compiler version.
- The format is <major><minor> where both are two digits. So for example
- gcc 3.41 would return 0341.
- cc-version is useful when a specific $(CC) version is faulty in one
- area, for example the -mregparm=3 were broken in some gcc version
- even though the option was accepted by gcc.
-
- Example:
- #arch/i386/Makefile
- cflags-y += $(shell \
- if [ $(call cc-version) -ge 0300 ] ; then \
- echo "-mregparm=3"; fi ;)
-
- In the above example -mregparm=3 is only used for gcc version greater
- than or equal to gcc 3.0.
-
-
=== 7 Kbuild Variables
The top Makefile exports the following variables:
diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt
index 7e77f93634e..fcccf2432f9 100644
--- a/Documentation/kbuild/modules.txt
+++ b/Documentation/kbuild/modules.txt
@@ -13,6 +13,7 @@ In this document you will find information about:
--- 2.2 Available targets
--- 2.3 Available options
--- 2.4 Preparing the kernel tree for module build
+ --- 2.5 Building separate files for a module
=== 3. Example commands
=== 4. Creating a kbuild file for an external module
=== 5. Include files
@@ -22,7 +23,10 @@ In this document you will find information about:
=== 6. Module installation
--- 6.1 INSTALL_MOD_PATH
--- 6.2 INSTALL_MOD_DIR
- === 7. Module versioning
+ === 7. Module versioning & Module.symvers
+ --- 7.1 Symbols fron the kernel (vmlinux + modules)
+ --- 7.2 Symbols and external modules
+ --- 7.3 Symbols from another external module
=== 8. Tips & Tricks
--- 8.1 Testing for CONFIG_FOO_BAR
@@ -88,7 +92,8 @@ when building an external module.
make -C $KDIR M=$PWD modules_install
Install the external module(s).
Installation default is in /lib/modules/<kernel-version>/extra,
- but may be prefixed with INSTALL_MOD_PATH - see separate chapter.
+ but may be prefixed with INSTALL_MOD_PATH - see separate
+ chapter.
make -C $KDIR M=$PWD clean
Remove all generated files for the module - the kernel
@@ -131,6 +136,16 @@ when building an external module.
Therefore a full kernel build needs to be executed to make
module versioning work.
+--- 2.5 Building separate files for a module
+ It is possible to build single files which is part of a module.
+ This works equal for the kernel, a module and even for external
+ modules.
+ Examples (module foo.ko, consist of bar.o, baz.o):
+ make -C $KDIR M=`pwd` bar.lst
+ make -C $KDIR M=`pwd` bar.o
+ make -C $KDIR M=`pwd` foo.ko
+ make -C $KDIR M=`pwd` /
+
=== 3. Example commands
@@ -422,7 +437,7 @@ External modules are installed in the directory:
=> Install dir: /lib/modules/$(KERNELRELEASE)/gandalf
-=== 7. Module versioning
+=== 7. Module versioning & Module.symvers
Module versioning is enabled by the CONFIG_MODVERSIONS tag.
@@ -432,11 +447,80 @@ when a module is loaded/used then the CRC values contained in the kernel are
compared with similar values in the module. If they are not equal then the
kernel refuses to load the module.
-During a kernel build a file named Module.symvers will be generated. This
-file includes the symbol version of all symbols within the kernel. If the
-Module.symvers file is saved from the last full kernel compile one does not
-have to do a full kernel compile to build a module version's compatible module.
+Module.symvers contains a list of all exported symbols from a kernel build.
+
+--- 7.1 Symbols fron the kernel (vmlinux + modules)
+
+ During a kernel build a file named Module.symvers will be generated.
+ Module.symvers contains all exported symbols from the kernel and
+ compiled modules. For each symbols the corresponding CRC value
+ is stored too.
+
+ The syntax of the Module.symvers file is:
+ <CRC> <Symbol> <module>
+ Sample:
+ 0x2d036834 scsi_remove_host drivers/scsi/scsi_mod
+ For a kernel build without CONFIG_MODVERSIONING enabled the crc
+ would read: 0x00000000
+
+ Module.symvers serve two purposes.
+ 1) It list all exported symbols both from vmlinux and all modules
+ 2) It list CRC if CONFIG_MODVERSION is enabled
+
+--- 7.2 Symbols and external modules
+
+ When building an external module the build system needs access to
+ the symbols from the kernel to check if all external symbols are
+ defined. This is done in the MODPOST step and to obtain all
+ symbols modpost reads Module.symvers from the kernel.
+ If a Module.symvers file is present in the directory where
+ the external module is being build this file will be read too.
+ During the MODPOST step a new Module.symvers file will be written
+ containing all exported symbols that was not defined in the kernel.
+
+--- 7.3 Symbols from another external module
+
+ Sometimes one external module uses exported symbols from another
+ external module. Kbuild needs to have full knowledge on all symbols
+ to avoid spitting out warnings about undefined symbols.
+ Two solutions exist to let kbuild know all symbols of more than
+ one external module.
+ The method with a top-level kbuild file is recommended but may be
+ impractical in certain situations.
+
+ Use a top-level Kbuild file
+ If you have two modules: 'foo', 'bar' and 'foo' needs symbols
+ from 'bar' then one can use a common top-level kbuild file so
+ both modules are compiled in same build.
+
+ Consider following directory layout:
+ ./foo/ <= contains the foo module
+ ./bar/ <= contains the bar module
+ The top-level Kbuild file would then look like:
+
+ #./Kbuild: (this file may also be named Makefile)
+ obj-y := foo/ bar/
+
+ Executing:
+ make -C $KDIR M=`pwd`
+
+ will then do the expected and compile both modules with full
+ knowledge on symbols from both modules.
+
+ Use an extra Module.symvers file
+ When an external module is build a Module.symvers file is
+ generated containing all exported symbols which are not
+ defined in the kernel.
+ To get access to symbols from module 'bar' one can copy the
+ Module.symvers file from the compilation of the 'bar' module
+ to the directory where the 'foo' module is build.
+ During the module build kbuild will read the Module.symvers
+ file in the directory of the external module and when the
+ build is finished a new Module.symvers file is created
+ containing the sum of all symbols defined and not part of the
+ kernel.
+
=== 8. Tips & Tricks
--- 8.1 Testing for CONFIG_FOO_BAR
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 44a25f3f51d..f8cb55c30b0 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -367,12 +367,17 @@ running once the system is up.
tty<n> Use the virtual console device <n>.
ttyS<n>[,options]
+ ttyUSB0[,options]
Use the specified serial port. The options are of
- the form "bbbbpn", where "bbbb" is the baud rate,
- "p" is parity ("n", "o", or "e"), and "n" is bits.
- Default is "9600n8".
-
- See also Documentation/serial-console.txt.
+ the form "bbbbpnf", where "bbbb" is the baud rate,
+ "p" is parity ("n", "o", or "e"), "n" is number of
+ bits, and "f" is flow control ("r" for RTS or
+ omit it). Default is "9600n8".
+
+ See Documentation/serial-console.txt for more
+ information. See
+ Documentation/networking/netconsole.txt for an
+ alternative.
uart,io,<addr>[,options]
uart,mmio,<addr>[,options]
diff --git a/Documentation/m68k/README.buddha b/Documentation/m68k/README.buddha
index bf802ffc98a..ef484a719bb 100644
--- a/Documentation/m68k/README.buddha
+++ b/Documentation/m68k/README.buddha
@@ -29,7 +29,7 @@ address is written to $4a, then the whole Byte is written to
$48, while it doesn't matter how often you're writing to $4a
as long as $48 is not touched. After $48 has been written,
the whole card disappears from $e8 and is mapped to the new
-address just written. Make shure $4a is written before $48,
+address just written. Make sure $4a is written before $48,
otherwise your chance is only 1:16 to find the board :-).
The local memory-map is even active when mapped to $e8:
diff --git a/Documentation/networking/TODO b/Documentation/networking/TODO
deleted file mode 100644
index 66d36ff14ba..00000000000
--- a/Documentation/networking/TODO
+++ /dev/null
@@ -1,18 +0,0 @@
-To-do items for network drivers
--------------------------------
-
-* Move ethernet crc routine to generic code
-
-* (for 2.5) Integrate Jamal Hadi Salim's netdev Rx polling API change
-
-* Audit all net drivers to make sure magic packet / wake-on-lan /
- similar features are disabled in the driver by default.
-
-* Audit all net drivers to make sure the module always prints out a
- version string when loaded as a module, but only prints a version
- string when built into the kernel if a device is detected.
-
-* Add ETHTOOL_GDRVINFO ioctl support to all ethernet drivers.
-
-* dmfe PCI DMA is totally wrong and only works on x86
-
diff --git a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c
index 545447ac503..a1205988675 100644
--- a/Documentation/networking/ifenslave.c
+++ b/Documentation/networking/ifenslave.c
@@ -87,7 +87,7 @@
* would fail and generate an error message in the system log.
* - For opt_c: slave should not be set to the master's setting
* while it is running. It was already set during enslave. To
- * simplify things, it is now handeled separately.
+ * simplify things, it is now handled separately.
*
* - 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
* - Code cleanup and style changes
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt
index 8d4cf78258e..4fc8e987432 100644
--- a/Documentation/networking/packet_mmap.txt
+++ b/Documentation/networking/packet_mmap.txt
@@ -40,7 +40,7 @@ network interface card supports some sort of interrupt load mitigation or
+ How to use CONFIG_PACKET_MMAP
--------------------------------------------------------------------------------
-From the user standpoint, you should use the higher level libpcap library, wich
+From the user standpoint, you should use the higher level libpcap library, which
is a de facto standard, portable across nearly all operating systems
including Win32.
@@ -217,8 +217,8 @@ called pg_vec, its size limits the number of blocks that can be allocated.
kmalloc allocates any number of bytes of phisically contiguous memory from
a pool of pre-determined sizes. This pool of memory is mantained by the slab
-allocator wich is at the end the responsible for doing the allocation and
-hence wich imposes the maximum memory that kmalloc can allocate.
+allocator which is at the end the responsible for doing the allocation and
+hence which imposes the maximum memory that kmalloc can allocate.
In a 2.4/2.6 kernel and the i386 architecture, the limit is 131072 bytes. The
predetermined sizes that kmalloc uses can be checked in the "size-<bytes>"
@@ -254,7 +254,7 @@ and, the number of frames be
<block number> * <block size> / <frame size>
-Suposse the following parameters, wich apply for 2.6 kernel and an
+Suposse the following parameters, which apply for 2.6 kernel and an
i386 architecture:
<size-max> = 131072 bytes
@@ -360,7 +360,7 @@ TP_STATUS_LOSING : indicates there were packet drops from last time
statistics where checked with getsockopt() and
the PACKET_STATISTICS option.
-TP_STATUS_CSUMNOTREADY: currently it's used for outgoing IP packets wich
+TP_STATUS_CSUMNOTREADY: currently it's used for outgoing IP packets which
it's checksum will be done in hardware. So while
reading the packet we should not try to check the
checksum.
diff --git a/Documentation/networking/ray_cs.txt b/Documentation/networking/ray_cs.txt
index 5427f8c7df9..145d27a5239 100644
--- a/Documentation/networking/ray_cs.txt
+++ b/Documentation/networking/ray_cs.txt
@@ -25,7 +25,7 @@ the essid= string parameter is available via the kernel command line.
This will change after the method of sorting out parameters for all
the PCMCIA drivers is agreed upon. If you must have a built in driver
with nondefault parameters, they can be edited in
-/usr/src/linux/drivers/net/pcmcia/ray_cs.c. Searching for MODULE_PARM
+/usr/src/linux/drivers/net/pcmcia/ray_cs.c. Searching for module_param
will find them all.
Information on card services is available at:
diff --git a/Documentation/networking/vortex.txt b/Documentation/networking/vortex.txt
index 3759acf95b2..6091e5f6794 100644
--- a/Documentation/networking/vortex.txt
+++ b/Documentation/networking/vortex.txt
@@ -24,36 +24,44 @@ Since kernel 2.3.99-pre6, this driver incorporates the support for the
This driver supports the following hardware:
- 3c590 Vortex 10Mbps
- 3c592 EISA 10mbps Demon/Vortex
- 3c597 EISA Fast Demon/Vortex
- 3c595 Vortex 100baseTx
- 3c595 Vortex 100baseT4
- 3c595 Vortex 100base-MII
- 3Com Vortex
- 3c900 Boomerang 10baseT
- 3c900 Boomerang 10Mbps Combo
- 3c900 Cyclone 10Mbps TPO
- 3c900B Cyclone 10Mbps T
- 3c900 Cyclone 10Mbps Combo
- 3c900 Cyclone 10Mbps TPC
- 3c900B-FL Cyclone 10base-FL
- 3c905 Boomerang 100baseTx
- 3c905 Boomerang 100baseT4
- 3c905B Cyclone 100baseTx
- 3c905B Cyclone 10/100/BNC
- 3c905B-FX Cyclone 100baseFx
- 3c905C Tornado
- 3c980 Cyclone
- 3cSOHO100-TX Hurricane
- 3c555 Laptop Hurricane
- 3c575 Boomerang CardBus
- 3CCFE575 Cyclone CardBus
- 3CCFE575CT Cyclone CardBus
- 3CCFE656 Cyclone CardBus
- 3CCFEM656 Cyclone CardBus
- 3c450 Cyclone/unknown
-
+ 3c590 Vortex 10Mbps
+ 3c592 EISA 10Mbps Demon/Vortex
+ 3c597 EISA Fast Demon/Vortex
+ 3c595 Vortex 100baseTx
+ 3c595 Vortex 100baseT4
+ 3c595 Vortex 100base-MII
+ 3c900 Boomerang 10baseT
+ 3c900 Boomerang 10Mbps Combo
+ 3c900 Cyclone 10Mbps TPO
+ 3c900 Cyclone 10Mbps Combo
+ 3c900 Cyclone 10Mbps TPC
+ 3c900B-FL Cyclone 10base-FL
+ 3c905 Boomerang 100baseTx
+ 3c905 Boomerang 100baseT4
+ 3c905B Cyclone 100baseTx
+ 3c905B Cyclone 10/100/BNC
+ 3c905B-FX Cyclone 100baseFx
+ 3c905C Tornado
+ 3c920B-EMB-WNM (ATI Radeon 9100 IGP)
+ 3c980 Cyclone
+ 3c980C Python-T
+ 3cSOHO100-TX Hurricane
+ 3c555 Laptop Hurricane
+ 3c556 Laptop Tornado
+ 3c556B Laptop Hurricane
+ 3c575 [Megahertz] 10/100 LAN CardBus
+ 3c575 Boomerang CardBus
+ 3CCFE575BT Cyclone CardBus
+ 3CCFE575CT Tornado CardBus
+ 3CCFE656 Cyclone CardBus
+ 3CCFEM656B Cyclone+Winmodem CardBus
+ 3CXFEM656C Tornado+Winmodem CardBus
+ 3c450 HomePNA Tornado
+ 3c920 Tornado
+ 3c982 Hydra Dual Port A
+ 3c982 Hydra Dual Port B
+ 3c905B-T4
+ 3c920B-EMB-WNM Tornado
Module parameters
=================
@@ -293,11 +301,6 @@ Donald's wake-on-LAN page:
http://www.scyld.com/wakeonlan.html
-3Com's documentation for many NICs, including the ones supported by
-this driver is available at
-
- http://support.3com.com/partners/developer/developer_form.html
-
3Com's DOS-based application for setting up the NICs EEPROMs:
ftp://ftp.3com.com/pub/nic/3c90x/3c90xx2.exe
@@ -312,10 +315,10 @@ Autonegotiation notes
---------------------
The driver uses a one-minute heartbeat for adapting to changes in
- the external LAN environment. This means that when, for example, a
- machine is unplugged from a hubbed 10baseT LAN plugged into a
- switched 100baseT LAN, the throughput will be quite dreadful for up
- to sixty seconds. Be patient.
+ the external LAN environment if link is up and 5 seconds if link is down.
+ This means that when, for example, a machine is unplugged from a hubbed
+ 10baseT LAN plugged into a switched 100baseT LAN, the throughput
+ will be quite dreadful for up to sixty seconds. Be patient.
Cisco interoperability note from Walter Wong <wcw+@CMU.EDU>:
diff --git a/Documentation/pnp.txt b/Documentation/pnp.txt
index af0f6eabfa1..9529c9c9fd5 100644
--- a/Documentation/pnp.txt
+++ b/Documentation/pnp.txt
@@ -115,6 +115,9 @@ pnp_unregister_protocol
pnp_register_driver
- adds a PnP driver to the Plug and Play Layer
- this includes driver model integration
+- returns zero for success or a negative error number for failure; count
+ calls to the .add() method if you need to know how many devices bind to
+ the driver
pnp_unregister_driver
- removes a PnP driver from the Plug and Play Layer
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index ee551c6ea23..217e51768b8 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -719,6 +719,11 @@ address which can extend beyond that limit.
- model : this is your board name/model
- #address-cells : address representation for "root" devices
- #size-cells: the size representation for "root" devices
+ - device_type : This property shouldn't be necessary. However, if
+ you decide to create a device_type for your root node, make sure it
+ is _not_ "chrp" unless your platform is a pSeries or PAPR compliant
+ one for 64-bit, or a CHRP-type machine for 32-bit as this will
+ matched by the kernel this way.
Additionally, some recommended properties are:
diff --git a/Documentation/robust-futex-ABI.txt b/Documentation/robust-futex-ABI.txt
new file mode 100644
index 00000000000..8529a17ffaa
--- /dev/null
+++ b/Documentation/robust-futex-ABI.txt
@@ -0,0 +1,182 @@
+Started by Paul Jackson <pj@sgi.com>
+
+The robust futex ABI
+--------------------
+
+Robust_futexes provide a mechanism that is used in addition to normal
+futexes, for kernel assist of cleanup of held locks on task exit.
+
+The interesting data as to what futexes a thread is holding is kept on a
+linked list in user space, where it can be updated efficiently as locks
+are taken and dropped, without kernel intervention. The only additional
+kernel intervention required for robust_futexes above and beyond what is
+required for futexes is:
+
+ 1) a one time call, per thread, to tell the kernel where its list of
+ held robust_futexes begins, and
+ 2) internal kernel code at exit, to handle any listed locks held
+ by the exiting thread.
+
+The existing normal futexes already provide a "Fast Userspace Locking"
+mechanism, which handles uncontested locking without needing a system
+call, and handles contested locking by maintaining a list of waiting
+threads in the kernel. Options on the sys_futex(2) system call support
+waiting on a particular futex, and waking up the next waiter on a
+particular futex.
+
+For robust_futexes to work, the user code (typically in a library such
+as glibc linked with the application) has to manage and place the
+necessary list elements exactly as the kernel expects them. If it fails
+to do so, then improperly listed locks will not be cleaned up on exit,
+probably causing deadlock or other such failure of the other threads
+waiting on the same locks.
+
+A thread that anticipates possibly using robust_futexes should first
+issue the system call:
+
+ asmlinkage long
+ sys_set_robust_list(struct robust_list_head __user *head, size_t len);
+
+The pointer 'head' points to a structure in the threads address space
+consisting of three words. Each word is 32 bits on 32 bit arch's, or 64
+bits on 64 bit arch's, and local byte order. Each thread should have
+its own thread private 'head'.
+
+If a thread is running in 32 bit compatibility mode on a 64 native arch
+kernel, then it can actually have two such structures - one using 32 bit
+words for 32 bit compatibility mode, and one using 64 bit words for 64
+bit native mode. The kernel, if it is a 64 bit kernel supporting 32 bit
+compatibility mode, will attempt to process both lists on each task
+exit, if the corresponding sys_set_robust_list() call has been made to
+setup that list.
+
+ The first word in the memory structure at 'head' contains a
+ pointer to a single linked list of 'lock entries', one per lock,
+ as described below. If the list is empty, the pointer will point
+ to itself, 'head'. The last 'lock entry' points back to the 'head'.
+
+ The second word, called 'offset', specifies the offset from the
+ address of the associated 'lock entry', plus or minus, of what will
+ be called the 'lock word', from that 'lock entry'. The 'lock word'
+ is always a 32 bit word, unlike the other words above. The 'lock
+ word' holds 3 flag bits in the upper 3 bits, and the thread id (TID)
+ of the thread holding the lock in the bottom 29 bits. See further
+ below for a description of the flag bits.
+
+ The third word, called 'list_op_pending', contains transient copy of
+ the address of the 'lock entry', during list insertion and removal,
+ and is needed to correctly resolve races should a thread exit while
+ in the middle of a locking or unlocking operation.
+
+Each 'lock entry' on the single linked list starting at 'head' consists
+of just a single word, pointing to the next 'lock entry', or back to
+'head' if there are no more entries. In addition, nearby to each 'lock
+entry', at an offset from the 'lock entry' specified by the 'offset'
+word, is one 'lock word'.
+
+The 'lock word' is always 32 bits, and is intended to be the same 32 bit
+lock variable used by the futex mechanism, in conjunction with
+robust_futexes. The kernel will only be able to wakeup the next thread
+waiting for a lock on a threads exit if that next thread used the futex
+mechanism to register the address of that 'lock word' with the kernel.
+
+For each futex lock currently held by a thread, if it wants this
+robust_futex support for exit cleanup of that lock, it should have one
+'lock entry' on this list, with its associated 'lock word' at the
+specified 'offset'. Should a thread die while holding any such locks,
+the kernel will walk this list, mark any such locks with a bit
+indicating their holder died, and wakeup the next thread waiting for
+that lock using the futex mechanism.
+
+When a thread has invoked the above system call to indicate it
+anticipates using robust_futexes, the kernel stores the passed in 'head'
+pointer for that task. The task may retrieve that value later on by
+using the system call:
+
+ asmlinkage long
+ sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr,
+ size_t __user *len_ptr);
+
+It is anticipated that threads will use robust_futexes embedded in
+larger, user level locking structures, one per lock. The kernel
+robust_futex mechanism doesn't care what else is in that structure, so
+long as the 'offset' to the 'lock word' is the same for all
+robust_futexes used by that thread. The thread should link those locks
+it currently holds using the 'lock entry' pointers. It may also have
+other links between the locks, such as the reverse side of a double
+linked list, but that doesn't matter to the kernel.
+
+By keeping its locks linked this way, on a list starting with a 'head'
+pointer known to the kernel, the kernel can provide to a thread the
+essential service available for robust_futexes, which is to help clean
+up locks held at the time of (a perhaps unexpectedly) exit.
+
+Actual locking and unlocking, during normal operations, is handled
+entirely by user level code in the contending threads, and by the
+existing futex mechanism to wait for, and wakeup, locks. The kernels
+only essential involvement in robust_futexes is to remember where the
+list 'head' is, and to walk the list on thread exit, handling locks
+still held by the departing thread, as described below.
+
+There may exist thousands of futex lock structures in a threads shared
+memory, on various data structures, at a given point in time. Only those
+lock structures for locks currently held by that thread should be on
+that thread's robust_futex linked lock list a given time.
+
+A given futex lock structure in a user shared memory region may be held
+at different times by any of the threads with access to that region. The
+thread currently holding such a lock, if any, is marked with the threads
+TID in the lower 29 bits of the 'lock word'.
+
+When adding or removing a lock from its list of held locks, in order for
+the kernel to correctly handle lock cleanup regardless of when the task
+exits (perhaps it gets an unexpected signal 9 in the middle of
+manipulating this list), the user code must observe the following
+protocol on 'lock entry' insertion and removal:
+
+On insertion:
+ 1) set the 'list_op_pending' word to the address of the 'lock word'
+ to be inserted,
+ 2) acquire the futex lock,
+ 3) add the lock entry, with its thread id (TID) in the bottom 29 bits
+ of the 'lock word', to the linked list starting at 'head', and
+ 4) clear the 'list_op_pending' word.
+
+On removal:
+ 1) set the 'list_op_pending' word to the address of the 'lock word'
+ to be removed,
+ 2) remove the lock entry for this lock from the 'head' list,
+ 2) release the futex lock, and
+ 2) clear the 'lock_op_pending' word.
+
+On exit, the kernel will consider the address stored in
+'list_op_pending' and the address of each 'lock word' found by walking
+the list starting at 'head'. For each such address, if the bottom 29
+bits of the 'lock word' at offset 'offset' from that address equals the
+exiting threads TID, then the kernel will do two things:
+
+ 1) if bit 31 (0x80000000) is set in that word, then attempt a futex
+ wakeup on that address, which will waken the next thread that has
+ used to the futex mechanism to wait on that address, and
+ 2) atomically set bit 30 (0x40000000) in the 'lock word'.
+
+In the above, bit 31 was set by futex waiters on that lock to indicate
+they were waiting, and bit 30 is set by the kernel to indicate that the
+lock owner died holding the lock.
+
+The kernel exit code will silently stop scanning the list further if at
+any point:
+
+ 1) the 'head' pointer or an subsequent linked list pointer
+ is not a valid address of a user space word
+ 2) the calculated location of the 'lock word' (address plus
+ 'offset') is not the valud address of a 32 bit user space
+ word
+ 3) if the list contains more than 1 million (subject to
+ future kernel configuration changes) elements.
+
+When the kernel sees a list entry whose 'lock word' doesn't have the
+current threads TID in the lower 29 bits, it does nothing with that
+entry, and goes on to the next entry.
+
+Bit 29 (0x20000000) of the 'lock word' is reserved for future use.
diff --git a/Documentation/robust-futexes.txt b/Documentation/robust-futexes.txt
new file mode 100644
index 00000000000..df82d75245a
--- /dev/null
+++ b/Documentation/robust-futexes.txt
@@ -0,0 +1,218 @@
+Started by: Ingo Molnar <mingo@redhat.com>
+
+Background
+----------
+
+what are robust futexes? To answer that, we first need to understand
+what futexes are: normal futexes are special types of locks that in the
+noncontended case can be acquired/released from userspace without having
+to enter the kernel.
+
+A futex is in essence a user-space address, e.g. a 32-bit lock variable
+field. If userspace notices contention (the lock is already owned and
+someone else wants to grab it too) then the lock is marked with a value
+that says "there's a waiter pending", and the sys_futex(FUTEX_WAIT)
+syscall is used to wait for the other guy to release it. The kernel
+creates a 'futex queue' internally, so that it can later on match up the
+waiter with the waker - without them having to know about each other.
+When the owner thread releases the futex, it notices (via the variable
+value) that there were waiter(s) pending, and does the
+sys_futex(FUTEX_WAKE) syscall to wake them up. Once all waiters have
+taken and released the lock, the futex is again back to 'uncontended'
+state, and there's no in-kernel state associated with it. The kernel
+completely forgets that there ever was a futex at that address. This
+method makes futexes very lightweight and scalable.
+
+"Robustness" is about dealing with crashes while holding a lock: if a
+process exits prematurely while holding a pthread_mutex_t lock that is
+also shared with some other process (e.g. yum segfaults while holding a
+pthread_mutex_t, or yum is kill -9-ed), then waiters for that lock need
+to be notified that the last owner of the lock exited in some irregular
+way.
+
+To solve such types of problems, "robust mutex" userspace APIs were
+created: pthread_mutex_lock() returns an error value if the owner exits
+prematurely - and the new owner can decide whether the data protected by
+the lock can be recovered safely.
+
+There is a big conceptual problem with futex based mutexes though: it is
+the kernel that destroys the owner task (e.g. due to a SEGFAULT), but
+the kernel cannot help with the cleanup: if there is no 'futex queue'
+(and in most cases there is none, futexes being fast lightweight locks)
+then the kernel has no information to clean up after the held lock!
+Userspace has no chance to clean up after the lock either - userspace is
+the one that crashes, so it has no opportunity to clean up. Catch-22.
+
+In practice, when e.g. yum is kill -9-ed (or segfaults), a system reboot
+is needed to release that futex based lock. This is one of the leading
+bugreports against yum.
+
+To solve this problem, the traditional approach was to extend the vma
+(virtual memory area descriptor) concept to have a notion of 'pending
+robust futexes attached to this area'. This approach requires 3 new
+syscall variants to sys_futex(): FUTEX_REGISTER, FUTEX_DEREGISTER and
+FUTEX_RECOVER. At do_exit() time, all vmas are searched to see whether
+they have a robust_head set. This approach has two fundamental problems
+left:
+
+ - it has quite complex locking and race scenarios. The vma-based
+ approach had been pending for years, but they are still not completely
+ reliable.
+
+ - they have to scan _every_ vma at sys_exit() time, per thread!
+
+The second disadvantage is a real killer: pthread_exit() takes around 1
+microsecond on Linux, but with thousands (or tens of thousands) of vmas
+every pthread_exit() takes a millisecond or more, also totally
+destroying the CPU's L1 and L2 caches!
+
+This is very much noticeable even for normal process sys_exit_group()
+calls: the kernel has to do the vma scanning unconditionally! (this is
+because the kernel has no knowledge about how many robust futexes there
+are to be cleaned up, because a robust futex might have been registered
+in another task, and the futex variable might have been simply mmap()-ed
+into this process's address space).
+
+This huge overhead forced the creation of CONFIG_FUTEX_ROBUST so that
+normal kernels can turn it off, but worse than that: the overhead makes
+robust futexes impractical for any type of generic Linux distribution.
+
+So something had to be done.
+
+New approach to robust futexes
+------------------------------
+
+At the heart of this new approach there is a per-thread private list of
+robust locks that userspace is holding (maintained by glibc) - which
+userspace list is registered with the kernel via a new syscall [this
+registration happens at most once per thread lifetime]. At do_exit()
+time, the kernel checks this user-space list: are there any robust futex
+locks to be cleaned up?
+
+In the common case, at do_exit() time, there is no list registered, so
+the cost of robust futexes is just a simple current->robust_list != NULL
+comparison. If the thread has registered a list, then normally the list
+is empty. If the thread/process crashed or terminated in some incorrect
+way then the list might be non-empty: in this case the kernel carefully
+walks the list [not trusting it], and marks all locks that are owned by
+this thread with the FUTEX_OWNER_DEAD bit, and wakes up one waiter (if
+any).
+
+The list is guaranteed to be private and per-thread at do_exit() time,
+so it can be accessed by the kernel in a lockless way.
+
+There is one race possible though: since adding to and removing from the
+list is done after the futex is acquired by glibc, there is a few
+instructions window for the thread (or process) to die there, leaving
+the futex hung. To protect against this possibility, userspace (glibc)
+also maintains a simple per-thread 'list_op_pending' field, to allow the
+kernel to clean up if the thread dies after acquiring the lock, but just
+before it could have added itself to the list. Glibc sets this
+list_op_pending field before it tries to acquire the futex, and clears
+it after the list-add (or list-remove) has finished.
+
+That's all that is needed - all the rest of robust-futex cleanup is done
+in userspace [just like with the previous patches].
+
+Ulrich Drepper has implemented the necessary glibc support for this new
+mechanism, which fully enables robust mutexes.
+
+Key differences of this userspace-list based approach, compared to the
+vma based method:
+
+ - it's much, much faster: at thread exit time, there's no need to loop
+ over every vma (!), which the VM-based method has to do. Only a very
+ simple 'is the list empty' op is done.
+
+ - no VM changes are needed - 'struct address_space' is left alone.
+
+ - no registration of individual locks is needed: robust mutexes dont
+ need any extra per-lock syscalls. Robust mutexes thus become a very
+ lightweight primitive - so they dont force the application designer
+ to do a hard choice between performance and robustness - robust
+ mutexes are just as fast.
+
+ - no per-lock kernel allocation happens.
+
+ - no resource limits are needed.
+
+ - no kernel-space recovery call (FUTEX_RECOVER) is needed.
+
+ - the implementation and the locking is "obvious", and there are no
+ interactions with the VM.
+
+Performance
+-----------
+
+I have benchmarked the time needed for the kernel to process a list of 1
+million (!) held locks, using the new method [on a 2GHz CPU]:
+
+ - with FUTEX_WAIT set [contended mutex]: 130 msecs
+ - without FUTEX_WAIT set [uncontended mutex]: 30 msecs
+
+I have also measured an approach where glibc does the lock notification
+[which it currently does for !pshared robust mutexes], and that took 256
+msecs - clearly slower, due to the 1 million FUTEX_WAKE syscalls
+userspace had to do.
+
+(1 million held locks are unheard of - we expect at most a handful of
+locks to be held at a time. Nevertheless it's nice to know that this
+approach scales nicely.)
+
+Implementation details
+----------------------
+
+The patch adds two new syscalls: one to register the userspace list, and
+one to query the registered list pointer:
+
+ asmlinkage long
+ sys_set_robust_list(struct robust_list_head __user *head,
+ size_t len);
+
+ asmlinkage long
+ sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr,
+ size_t __user *len_ptr);
+
+List registration is very fast: the pointer is simply stored in
+current->robust_list. [Note that in the future, if robust futexes become
+widespread, we could extend sys_clone() to register a robust-list head
+for new threads, without the need of another syscall.]
+
+So there is virtually zero overhead for tasks not using robust futexes,
+and even for robust futex users, there is only one extra syscall per
+thread lifetime, and the cleanup operation, if it happens, is fast and
+straightforward. The kernel doesnt have any internal distinction between
+robust and normal futexes.
+
+If a futex is found to be held at exit time, the kernel sets the
+following bit of the futex word:
+
+ #define FUTEX_OWNER_DIED 0x40000000
+
+and wakes up the next futex waiter (if any). User-space does the rest of
+the cleanup.
+
+Otherwise, robust futexes are acquired by glibc by putting the TID into
+the futex field atomically. Waiters set the FUTEX_WAITERS bit:
+
+ #define FUTEX_WAITERS 0x80000000
+
+and the remaining bits are for the TID.
+
+Testing, architecture support
+-----------------------------
+
+i've tested the new syscalls on x86 and x86_64, and have made sure the
+parsing of the userspace list is robust [ ;-) ] even if the list is
+deliberately corrupted.
+
+i386 and x86_64 syscalls are wired up at the moment, and Ulrich has
+tested the new glibc code (on x86_64 and i386), and it works for his
+robust-mutex testcases.
+
+All other architectures should build just fine too - but they wont have
+the new syscalls yet.
+
+Architectures need to implement the new futex_atomic_cmpxchg_inatomic()
+inline function before writing up the syscalls (that function returns
+-ENOSYS right now).
diff --git a/Documentation/rpc-cache.txt b/Documentation/rpc-cache.txt
index 2b5d4434fa5..5f757c8cf97 100644
--- a/Documentation/rpc-cache.txt
+++ b/Documentation/rpc-cache.txt
@@ -1,4 +1,4 @@
-This document gives a brief introduction to the caching
+ This document gives a brief introduction to the caching
mechanisms in the sunrpc layer that is used, in particular,
for NFS authentication.
@@ -25,25 +25,17 @@ The common code handles such things as:
- supporting 'NEGATIVE' as well as positive entries
- allowing an EXPIRED time on cache items, and removing
items after they expire, and are no longe in-use.
-
- Future code extensions are expect to handle
- making requests to user-space to fill in cache entries
- allowing user-space to directly set entries in the cache
- delaying RPC requests that depend on as-yet incomplete
cache entries, and replaying those requests when the cache entry
is complete.
- - maintaining last-access times on cache entries
- - clean out old entries when the caches become full
-
-The code for performing a cache lookup is also common, but in the form
-of a template. i.e. a #define.
-Each cache defines a lookup function by using the DefineCacheLookup
-macro, or the simpler DefineSimpleCacheLookup macro
+ - clean out old entries as they expire.
Creating a Cache
----------------
-1/ A cache needs a datum to cache. This is in the form of a
+1/ A cache needs a datum to store. This is in the form of a
structure definition that must contain a
struct cache_head
as an element, usually the first.
@@ -51,35 +43,69 @@ Creating a Cache
Each cache element is reference counted and contains
expiry and update times for use in cache management.
2/ A cache needs a "cache_detail" structure that
- describes the cache. This stores the hash table, and some
- parameters for cache management.
-3/ A cache needs a lookup function. This is created using
- the DefineCacheLookup macro. This lookup function is used both
- to find entries and to update entries. The normal mode for
- updating an entry is to replace the old entry with a new
- entry. However it is possible to allow update-in-place
- for those caches where it makes sense (no atomicity issues
- or indirect reference counting issue)
-4/ A cache needs to be registered using cache_register(). This
- includes in on a list of caches that will be regularly
- cleaned to discard old data. For this to work, some
- thread must periodically call cache_clean
-
+ describes the cache. This stores the hash table, some
+ parameters for cache management, and some operations detailing how
+ to work with particular cache items.
+ The operations requires are:
+ struct cache_head *alloc(void)
+ This simply allocates appropriate memory and returns
+ a pointer to the cache_detail embedded within the
+ structure
+ void cache_put(struct kref *)
+ This is called when the last reference to an item is
+ is dropped. The pointer passed is to the 'ref' field
+ in the cache_head. cache_put should release any
+ references create by 'cache_init' and, if CACHE_VALID
+ is set, any references created by cache_update.
+ It should then release the memory allocated by
+ 'alloc'.
+ int match(struct cache_head *orig, struct cache_head *new)
+ test if the keys in the two structures match. Return
+ 1 if they do, 0 if they don't.
+ void init(struct cache_head *orig, struct cache_head *new)
+ Set the 'key' fields in 'new' from 'orig'. This may
+ include taking references to shared objects.
+ void update(struct cache_head *orig, struct cache_head *new)
+ Set the 'content' fileds in 'new' from 'orig'.
+ int cache_show(struct seq_file *m, struct cache_detail *cd,
+ struct cache_head *h)
+ Optional. Used to provide a /proc file that lists the
+ contents of a cache. This should show one item,
+ usually on just one line.
+ int cache_request(struct cache_detail *cd, struct cache_head *h,
+ char **bpp, int *blen)
+ Format a request to be send to user-space for an item
+ to be instantiated. *bpp is a buffer of size *blen.
+ bpp should be moved forward over the encoded message,
+ and *blen should be reduced to show how much free
+ space remains. Return 0 on success or <0 if not
+ enough room or other problem.
+ int cache_parse(struct cache_detail *cd, char *buf, int len)
+ A message from user space has arrived to fill out a
+ cache entry. It is in 'buf' of length 'len'.
+ cache_parse should parse this, find the item in the
+ cache with sunrpc_cache_lookup, and update the item
+ with sunrpc_cache_update.
+
+
+3/ A cache needs to be registered using cache_register(). This
+ includes it on a list of caches that will be regularly
+ cleaned to discard old data.
+
Using a cache
-------------
-To find a value in a cache, call the lookup function passing it a the
-datum which contains key, and possibly content, and a flag saying
-whether to update the cache with new data from the datum. Depending
-on how the cache lookup function was defined, it may take an extra
-argument to identify the particular cache in question.
+To find a value in a cache, call sunrpc_cache_lookup passing a pointer
+to the cache_head in a sample item with the 'key' fields filled in.
+This will be passed to ->match to identify the target entry. If no
+entry is found, a new entry will be create, added to the cache, and
+marked as not containing valid data.
-Except in cases of kmalloc failure, the lookup function
-will return a new datum which will store the key and
-may contain valid content, or may not.
-This datum is typically passed to cache_check which determines the
-validity of the datum and may later initiate an upcall to fill
-in the data.
+The item returned is typically passed to cache_check which will check
+if the data is valid, and may initiate an up-call to get fresh data.
+cache_check will return -ENOENT in the entry is negative or if an up
+call is needed but not possible, -EAGAIN if an upcall is pending,
+or 0 if the data is valid;
cache_check can be passed a "struct cache_req *". This structure is
typically embedded in the actual request and can be used to create a
@@ -90,6 +116,13 @@ item does become valid, the deferred copy of the request will be
revisited (->revisit). It is expected that this method will
reschedule the request for processing.
+The value returned by sunrpc_cache_lookup can also be passed to
+sunrpc_cache_update to set the content for the item. A second item is
+passed which should hold the content. If the item found by _lookup
+has valid data, then it is discarded and a new item is created. This
+saves any user of an item from worrying about content changing while
+it is being inspected. If the item found by _lookup does not contain
+valid data, then the content is copied across and CACHE_VALID is set.
Populating a cache
------------------
@@ -114,8 +147,8 @@ should be create or updated to have the given content, and the
expiry time should be set on that item.
Reading from a channel is a bit more interesting. When a cache
-lookup fail, or when it suceeds but finds an entry that may soon
-expiry, a request is lodged for that cache item to be updated by
+lookup fails, or when it succeeds but finds an entry that may soon
+expire, a request is lodged for that cache item to be updated by
user-space. These requests appear in the channel file.
Successive reads will return successive requests.
@@ -130,7 +163,7 @@ Thus a user-space helper is likely to:
write a response
loop.
-If it dies and needs to be restarted, any requests that have not be
+If it dies and needs to be restarted, any requests that have not been
answered will still appear in the file and will be read by the new
instance of the helper.
@@ -142,10 +175,9 @@ Each cache should also define a "cache_request" method which
takes a cache item and encodes a request into the buffer
provided.
-
Note: If a cache has no active readers on the channel, and has had not
active readers for more than 60 seconds, further requests will not be
-added to the channel but instead all looks that do not find a valid
+added to the channel but instead all lookups that do not find a valid
entry will fail. This is partly for backward compatibility: The
previous nfs exports table was deemed to be authoritative and a
failed lookup meant a definite 'no'.
@@ -154,18 +186,17 @@ request/response format
-----------------------
While each cache is free to use it's own format for requests
-and responses over channel, the following is recommended are
+and responses over channel, the following is recommended as
appropriate and support routines are available to help:
Each request or response record should be printable ASCII
with precisely one newline character which should be at the end.
Fields within the record should be separated by spaces, normally one.
If spaces, newlines, or nul characters are needed in a field they
-much be quotes. two mechanisms are available:
+much be quoted. two mechanisms are available:
1/ If a field begins '\x' then it must contain an even number of
hex digits, and pairs of these digits provide the bytes in the
field.
2/ otherwise a \ in the field must be followed by 3 octal digits
which give the code for a byte. Other characters are treated
- as them selves. At the very least, space, newlines nul, and
+ as them selves. At the very least, space, newline, nul, and
'\' must be quoted in this way.
-
diff --git a/Documentation/serial-console.txt b/Documentation/serial-console.txt
index 6c689b0df2b..9a7bc8b3f47 100644
--- a/Documentation/serial-console.txt
+++ b/Documentation/serial-console.txt
@@ -17,11 +17,13 @@ The format of this option is:
ttyX for any other virtual console
ttySx for a serial port
lp0 for the first parallel port
+ ttyUSB0 for the first USB serial device
options: depend on the driver. For the serial port this
- defines the baudrate/parity/bits of the port,
- in the format BBBBPN, where BBBB is the speed,
- P is parity (n/o/e), and N is bits. Default is
+ defines the baudrate/parity/bits/flow control of
+ the port, in the format BBBBPNF, where BBBB is the
+ speed, P is parity (n/o/e), N is number of bits,
+ and F is flow control ('r' for RTS). Default is
9600n8. The maximum baudrate is 115200.
You can specify multiple console= options on the kernel command line.
@@ -45,6 +47,9 @@ become the console.
You will need to create a new device to use /dev/console. The official
/dev/console is now character device 5,1.
+(You can also use a network device as a console. See
+Documentation/networking/netconsole.txt for information on that.)
+
Here's an example that will use /dev/ttyS1 (COM2) as the console.
Replace the sample values as needed.
diff --git a/Documentation/smart-config.txt b/Documentation/smart-config.txt
index c9bed4cf877..8467447b5a8 100644
--- a/Documentation/smart-config.txt
+++ b/Documentation/smart-config.txt
@@ -56,10 +56,6 @@ Here is the solution:
writing one file per option. It updates only the files for options
that have changed.
- mkdep.c no longer generates warning messages for missing or unneeded
- <linux/config.h> lines. The new top-level target 'make checkconfig'
- checks for these problems.
-
Flag Dependencies
Martin Von Loewis contributed another feature to this patch:
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 6dc9d9f622c..6feef9e82b6 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -2836,7 +2836,7 @@ struct _snd_pcm_runtime {
<para>
Note that this callback became non-atomic since the recent version.
- You can use schedule-related fucntions safely in this callback now.
+ You can use schedule-related functions safely in this callback now.
</para>
<para>
diff --git a/Documentation/sound/oss/Introduction b/Documentation/sound/oss/Introduction
index 15d4fb975ac..f04ba6bb739 100644
--- a/Documentation/sound/oss/Introduction
+++ b/Documentation/sound/oss/Introduction
@@ -69,7 +69,7 @@ are available, for example IRQ, address, DMA.
Warning, the options for different cards sometime use different names
for the same or a similar feature (dma1= versus dma16=). As a last
-resort, inspect the code (search for MODULE_PARM).
+resort, inspect the code (search for module_param).
Notes:
diff --git a/Documentation/sound/oss/cs46xx b/Documentation/sound/oss/cs46xx
index 88d6cf8b39f..b5443270986 100644
--- a/Documentation/sound/oss/cs46xx
+++ b/Documentation/sound/oss/cs46xx
@@ -88,7 +88,7 @@ parameters. for a copy email: twoller@crystal.cirrus.com
MODULE_PARMS definitions
------------------------
-MODULE_PARM(defaultorder, "i");
+module_param(defaultorder, ulong, 0);
defaultorder=N
where N is a value from 1 to 12
The buffer order determines the size of the dma buffer for the driver.
@@ -98,18 +98,18 @@ to not underrun the dma buffer as easily. As default, use 32k (order=3)
rather than 64k as some of the games work more responsively.
(2^N) * PAGE_SIZE = allocated buffer size
-MODULE_PARM(cs_debuglevel, "i");
-MODULE_PARM(cs_debugmask, "i");
+module_param(cs_debuglevel, ulong, 0644);
+module_param(cs_debugmask, ulong, 0644);
cs_debuglevel=N
cs_debugmask=0xMMMMMMMM
where N is a value from 0 (no debug printfs), to 9 (maximum)
0xMMMMMMMM is a debug mask corresponding to the CS_xxx bits (see driver source).
-MODULE_PARM(hercules_egpio_disable, "i");
+module_param(hercules_egpio_disable, ulong, 0);
hercules_egpio_disable=N
where N is a 0 (enable egpio), or a 1 (disable egpio support)
-MODULE_PARM(initdelay, "i");
+module_param(initdelay, ulong, 0);
initdelay=N
This value is used to determine the millescond delay during the initialization
code prior to powering up the PLL. On laptops this value can be used to
@@ -118,19 +118,19 @@ system is booted under battery power then the mdelay()/udelay() functions fail t
properly delay the required time. Also, if the system is booted under AC power
and then the power removed, the mdelay()/udelay() functions will not delay properly.
-MODULE_PARM(powerdown, "i");
+module_param(powerdown, ulong, 0);
powerdown=N
where N is 0 (disable any powerdown of the internal blocks) or 1 (enable powerdown)
-MODULE_PARM(external_amp, "i");
+module_param(external_amp, bool, 0);
external_amp=1
if N is set to 1, then force enabling the EAPD support in the primary AC97 codec.
override the detection logic and force the external amp bit in the AC97 0x26 register
to be reset (0). EAPD should be 0 for powerup, and 1 for powerdown. The VTB Santa Cruz
card has inverted logic, so there is a special function for these cards.
-MODULE_PARM(thinkpad, "i");
+module_param(thinkpad, bool, 0);
thinkpad=1
if N is set to 1, then force enabling the clkrun functionality.
Currently, when the part is being used, then clkrun is disabled for the entire system,
diff --git a/Documentation/video4linux/CQcam.txt b/Documentation/video4linux/CQcam.txt
index e415e360453..464e4cec94c 100644
--- a/Documentation/video4linux/CQcam.txt
+++ b/Documentation/video4linux/CQcam.txt
@@ -1,7 +1,7 @@
c-qcam - Connectix Color QuickCam video4linux kernel driver
Copyright (C) 1999 Dave Forrest <drf5n@virginia.edu>
- released under GNU GPL.
+ released under GNU GPL.
1999-12-08 Dave Forrest, written with kernel version 2.2.12 in mind
@@ -45,21 +45,21 @@ configuration. The appropriate flags are:
CONFIG_PNP_PARPORT M for autoprobe.o IEEE1284 readback module
CONFIG_PRINTER_READBACK M for parport_probe.o IEEE1284 readback module
CONFIG_VIDEO_DEV M for videodev.o video4linux module
- CONFIG_VIDEO_CQCAM M for c-qcam.o Color Quickcam module
+ CONFIG_VIDEO_CQCAM M for c-qcam.o Color Quickcam module
With these flags, the kernel should compile and install the modules.
To record and monitor the compilation, I use:
(make zlilo ; \
make modules; \
- make modules_install ;
+ make modules_install ;
depmod -a ) &>log &
less log # then a capital 'F' to watch the progress
-
+
But that is my personal preference.
2.2 Configuration
-
+
The configuration requires module configuration and device
configuration. I like kmod or kerneld process with the
/etc/modprobe.conf file so the modules can automatically load/unload as
@@ -68,7 +68,7 @@ using MAKEDEV, or need to be created. The following sections detail
these procedures.
-2.1 Module Configuration
+2.1 Module Configuration
Using modules requires a bit of work to install and pass the
parameters. Understand that entries in /etc/modprobe.conf of:
@@ -128,9 +128,9 @@ system (CONFIG_PROC_FS), the parallel printer support
(CONFIG_PRINTER), the IEEE 1284 system,(CONFIG_PRINTER_READBACK), you
should be able to read some identification from your quickcam with
- modprobe -v parport
- modprobe -v parport_probe
- cat /proc/parport/PORTNUMBER/autoprobe
+ modprobe -v parport
+ modprobe -v parport_probe
+ cat /proc/parport/PORTNUMBER/autoprobe
Returns:
CLASS:MEDIA;
MODEL:Color QuickCam 2.0;
@@ -140,7 +140,7 @@ Returns:
and well. A common problem is that the current driver does not
reliably detect a c-qcam, even though one is attached. In this case,
- modprobe -v c-qcam
+ modprobe -v c-qcam
or
insmod -v c-qcam
@@ -152,16 +152,16 @@ video4linux mailing list and archive for more current information.
3.1 Checklist:
Can you get an image?
- v4lgrab >qcam.ppm ; wc qcam.ppm ; xv qcam.ppm
+ v4lgrab >qcam.ppm ; wc qcam.ppm ; xv qcam.ppm
- Is a working c-qcam connected to the port?
- grep ^ /proc/parport/?/autoprobe
+ Is a working c-qcam connected to the port?
+ grep ^ /proc/parport/?/autoprobe
- Do the /dev/video* files exist?
- ls -lad /dev/video
+ Do the /dev/video* files exist?
+ ls -lad /dev/video
- Is the c-qcam module loaded?
- modprobe -v c-qcam ; lsmod
+ Is the c-qcam module loaded?
+ modprobe -v c-qcam ; lsmod
Does the camera work with alternate programs? cqcam, etc?
@@ -174,7 +174,7 @@ video4linux mailing list and archive for more current information.
isn't, you might try patching the c-qcam module to add a parport=xxx
option as in the bw-qcam module so you can specify the parallel port:
- insmod -v c-qcam parport=0
+ insmod -v c-qcam parport=0
And bypass the detection code, see ../../drivers/char/c-qcam.c and
look for the 'qc_detect' code and call.
@@ -183,12 +183,12 @@ look for the 'qc_detect' code and call.
this work is documented at the video4linux2 site listed below.
-9.0 --- A sample program using v4lgrabber,
+9.0 --- A sample program using v4lgrabber,
This program is a simple image grabber that will copy a frame from the
first video device, /dev/video0 to standard output in portable pixmap
format (.ppm) Using this like: 'v4lgrab | convert - c-qcam.jpg'
-produced this picture of me at
+produced this picture of me at
http://mug.sys.virginia.edu/~drf5n/extras/c-qcam.jpg
-------------------- 8< ---------------- 8< -----------------------------
@@ -202,8 +202,8 @@ produced this picture of me at
* Use as:
* v4lgrab >image.ppm
*
- * Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
- * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
+ * Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
+ * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
* with minor modifications (Dave Forrest, drf5n@virginia.edu).
*
*/
@@ -225,55 +225,55 @@ produced this picture of me at
#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \
{ \
- switch (format) \
- { \
- case VIDEO_PALETTE_GREY: \
- switch (depth) \
- { \
- case 4: \
- case 6: \
- case 8: \
- (r) = (g) = (b) = (*buf++ << 8);\
- break; \
- \
- case 16: \
- (r) = (g) = (b) = \
- *((unsigned short *) buf); \
- buf += 2; \
- break; \
- } \
- break; \
- \
- \
- case VIDEO_PALETTE_RGB565: \
- { \
- unsigned short tmp = *(unsigned short *)buf; \
- (r) = tmp&0xF800; \
- (g) = (tmp<<5)&0xFC00; \
- (b) = (tmp<<11)&0xF800; \
- buf += 2; \
- } \
- break; \
- \
- case VIDEO_PALETTE_RGB555: \
- (r) = (buf[0]&0xF8)<<8; \
- (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \
- (b) = ((buf[1] << 2 ) & 0xF8)<<8; \
- buf += 2; \
- break; \
- \
- case VIDEO_PALETTE_RGB24: \
- (r) = buf[0] << 8; (g) = buf[1] << 8; \
- (b) = buf[2] << 8; \
- buf += 3; \
- break; \
- \
- default: \
- fprintf(stderr, \
- "Format %d not yet supported\n", \
- format); \
- } \
-}
+ switch (format) \
+ { \
+ case VIDEO_PALETTE_GREY: \
+ switch (depth) \
+ { \
+ case 4: \
+ case 6: \
+ case 8: \
+ (r) = (g) = (b) = (*buf++ << 8);\
+ break; \
+ \
+ case 16: \
+ (r) = (g) = (b) = \
+ *((unsigned short *) buf); \
+ buf += 2; \
+ break; \
+ } \
+ break; \
+ \
+ \
+ case VIDEO_PALETTE_RGB565: \
+ { \
+ unsigned short tmp = *(unsigned short *)buf; \
+ (r) = tmp&0xF800; \
+ (g) = (tmp<<5)&0xFC00; \
+ (b) = (tmp<<11)&0xF800; \
+ buf += 2; \
+ } \
+ break; \
+ \
+ case VIDEO_PALETTE_RGB555: \
+ (r) = (buf[0]&0xF8)<<8; \
+ (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \
+ (b) = ((buf[1] << 2 ) & 0xF8)<<8; \
+ buf += 2; \
+ break; \
+ \
+ case VIDEO_PALETTE_RGB24: \
+ (r) = buf[0] << 8; (g) = buf[1] << 8; \
+ (b) = buf[2] << 8; \
+ buf += 3; \
+ break; \
+ \
+ default: \
+ fprintf(stderr, \
+ "Format %d not yet supported\n", \
+ format); \
+ } \
+}
int get_brightness_adj(unsigned char *image, long size, int *brightness) {
long i, tot = 0;
@@ -324,40 +324,40 @@ int main(int argc, char ** argv)
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
vpic.depth=6;
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
- vpic.depth=4;
- if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
- fprintf(stderr, "Unable to find a supported capture format.\n");
- close(fd);
- exit(1);
- }
+ vpic.depth=4;
+ if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+ fprintf(stderr, "Unable to find a supported capture format.\n");
+ close(fd);
+ exit(1);
+ }
}
}
} else {
vpic.depth=24;
vpic.palette=VIDEO_PALETTE_RGB24;
-
+
if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
vpic.palette=VIDEO_PALETTE_RGB565;
vpic.depth=16;
-
+
if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
- vpic.palette=VIDEO_PALETTE_RGB555;
- vpic.depth=15;
-
- if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
- fprintf(stderr, "Unable to find a supported capture format.\n");
- return -1;
- }
+ vpic.palette=VIDEO_PALETTE_RGB555;
+ vpic.depth=15;
+
+ if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+ fprintf(stderr, "Unable to find a supported capture format.\n");
+ return -1;
+ }
}
}
}
-
+
buffer = malloc(win.width * win.height * bpp);
if (!buffer) {
fprintf(stderr, "Out of memory.\n");
exit(1);
}
-
+
do {
int newbright;
read(fd, buffer, win.width * win.height * bpp);
@@ -365,8 +365,8 @@ int main(int argc, char ** argv)
if (f) {
vpic.brightness += (newbright << 8);
if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
- perror("VIDIOSPICT");
- break;
+ perror("VIDIOSPICT");
+ break;
}
}
} while (f);
@@ -381,7 +381,7 @@ int main(int argc, char ** argv)
fputc(g>>8, stdout);
fputc(b>>8, stdout);
}
-
+
close(fd);
return 0;
}
diff --git a/Documentation/video4linux/README.cpia b/Documentation/video4linux/README.cpia
index c95e7bbc0fd..19cd3bf2498 100644
--- a/Documentation/video4linux/README.cpia
+++ b/Documentation/video4linux/README.cpia
@@ -87,7 +87,7 @@ hardware configuration of the parport. You can give the boot-parameter
at the LILO-prompt or specify it in lilo.conf. I use the following
append-line in lilo.conf:
- append="parport=0x378,7,3"
+ append="parport=0x378,7,3"
See Documentation/parport.txt for more information about the
configuration of the parport and the values given above. Do not simply
@@ -175,7 +175,7 @@ THANKS (in no particular order):
- Manuel J. Petit de Gabriel <mpetit@dit.upm.es> for providing help
with Isabel (http://isabel.dit.upm.es/)
- Bas Huisman <bhuism@cs.utwente.nl> for writing the initial parport code
-- Jarl Totland <Jarl.Totland@bdc.no> for setting up the mailing list
+- Jarl Totland <Jarl.Totland@bdc.no> for setting up the mailing list
and maintaining the web-server[3]
- Chris Whiteford <Chris@informinteractive.com> for fixes related to the
1.02 firmware
diff --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran
index 52c94bd7dca..be9f21b8455 100644
--- a/Documentation/video4linux/Zoran
+++ b/Documentation/video4linux/Zoran
@@ -28,7 +28,7 @@ Iomega Buz:
* Philips saa7111 TV decoder
* Philips saa7185 TV encoder
Drivers to use: videodev, i2c-core, i2c-algo-bit,
- videocodec, saa7111, saa7185, zr36060, zr36067
+ videocodec, saa7111, saa7185, zr36060, zr36067
Inputs/outputs: Composite and S-video
Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
Card number: 7
@@ -39,7 +39,7 @@ Linux Media Labs LML33:
* Brooktree bt819 TV decoder
* Brooktree bt856 TV encoder
Drivers to use: videodev, i2c-core, i2c-algo-bit,
- videocodec, bt819, bt856, zr36060, zr36067
+ videocodec, bt819, bt856, zr36060, zr36067
Inputs/outputs: Composite and S-video
Norms: PAL (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
Card number: 5
@@ -50,7 +50,7 @@ Linux Media Labs LML33R10:
* Philips saa7114 TV decoder
* Analog Devices adv7170 TV encoder
Drivers to use: videodev, i2c-core, i2c-algo-bit,
- videocodec, saa7114, adv7170, zr36060, zr36067
+ videocodec, saa7114, adv7170, zr36060, zr36067
Inputs/outputs: Composite and S-video
Norms: PAL (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
Card number: 6
@@ -61,7 +61,7 @@ Pinnacle/Miro DC10(new):
* Philips saa7110a TV decoder
* Analog Devices adv7176 TV encoder
Drivers to use: videodev, i2c-core, i2c-algo-bit,
- videocodec, saa7110, adv7175, zr36060, zr36067
+ videocodec, saa7110, adv7175, zr36060, zr36067
Inputs/outputs: Composite, S-video and Internal
Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps)
Card number: 1
@@ -84,7 +84,7 @@ Pinnacle/Miro DC10(old): *
* Micronas vpx3220a TV decoder
* mse3000 TV encoder or Analog Devices adv7176 TV encoder *
Drivers to use: videodev, i2c-core, i2c-algo-bit,
- videocodec, vpx3220, mse3000/adv7175, zr36050, zr36016, zr36067
+ videocodec, vpx3220, mse3000/adv7175, zr36050, zr36016, zr36067
Inputs/outputs: Composite, S-video and Internal
Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps)
Card number: 0
@@ -96,7 +96,7 @@ Pinnacle/Miro DC30: *
* Micronas vpx3225d/vpx3220a/vpx3216b TV decoder
* Analog Devices adv7176 TV encoder
Drivers to use: videodev, i2c-core, i2c-algo-bit,
- videocodec, vpx3220/vpx3224, adv7175, zr36050, zr36016, zr36067
+ videocodec, vpx3220/vpx3224, adv7175, zr36050, zr36016, zr36067
Inputs/outputs: Composite, S-video and Internal
Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps)
Card number: 3
@@ -123,11 +123,11 @@ Note: use encoder=X or decoder=X for non-default i2c chips (see i2c-id.h)
The best know TV standards are NTSC/PAL/SECAM. but for decoding a frame that
information is not enough. There are several formats of the TV standards.
-And not every TV decoder is able to handle every format. Also the every
-combination is supported by the driver. There are currently 11 different
-tv broadcast formats all aver the world.
+And not every TV decoder is able to handle every format. Also the every
+combination is supported by the driver. There are currently 11 different
+tv broadcast formats all aver the world.
-The CCIR defines parameters needed for broadcasting the signal.
+The CCIR defines parameters needed for broadcasting the signal.
The CCIR has defined different standards: A,B,D,E,F,G,D,H,I,K,K1,L,M,N,...
The CCIR says not much about about the colorsystem used !!!
And talking about a colorsystem says not to much about how it is broadcast.
@@ -136,18 +136,18 @@ The CCIR standards A,E,F are not used any more.
When you speak about NTSC, you usually mean the standard: CCIR - M using
the NTSC colorsystem which is used in the USA, Japan, Mexico, Canada
-and a few others.
+and a few others.
When you talk about PAL, you usually mean: CCIR - B/G using the PAL
-colorsystem which is used in many Countries.
+colorsystem which is used in many Countries.
-When you talk about SECAM, you mean: CCIR - L using the SECAM Colorsystem
+When you talk about SECAM, you mean: CCIR - L using the SECAM Colorsystem
which is used in France, and a few others.
There the other version of SECAM, CCIR - D/K is used in Bulgaria, China,
-Slovakai, Hungary, Korea (Rep.), Poland, Rumania and a others.
+Slovakai, Hungary, Korea (Rep.), Poland, Rumania and a others.
-The CCIR - H uses the PAL colorsystem (sometimes SECAM) and is used in
+The CCIR - H uses the PAL colorsystem (sometimes SECAM) and is used in
Egypt, Libya, Sri Lanka, Syrain Arab. Rep.
The CCIR - I uses the PAL colorsystem, and is used in Great Britain, Hong Kong,
@@ -158,30 +158,30 @@ and is used in Argentinia, Uruguay, an a few others
We do not talk about how the audio is broadcast !
-A rather good sites about the TV standards are:
+A rather good sites about the TV standards are:
http://www.sony.jp/ServiceArea/Voltage_map/
http://info.electronicwerkstatt.de/bereiche/fernsehtechnik/frequenzen_und_normen/Fernsehnormen/
and http://www.cabl.com/restaurant/channel.html
Other weird things around: NTSC 4.43 is a modificated NTSC, which is mainly
used in PAL VCR's that are able to play back NTSC. PAL 60 seems to be the same
-as NTSC 4.43 . The Datasheets also talk about NTSC 44, It seems as if it would
-be the same as NTSC 4.43.
+as NTSC 4.43 . The Datasheets also talk about NTSC 44, It seems as if it would
+be the same as NTSC 4.43.
NTSC Combs seems to be a decoder mode where the decoder uses a comb filter
to split coma and luma instead of a Delay line.
But I did not defiantly find out what NTSC Comb is.
Philips saa7111 TV decoder
-was introduced in 1997, is used in the BUZ and
-can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC N, NTSC 4.43 and SECAM
+was introduced in 1997, is used in the BUZ and
+can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC N, NTSC 4.43 and SECAM
Philips saa7110a TV decoder
was introduced in 1995, is used in the Pinnacle/Miro DC10(new), DC10+ and
-can handle: PAL B/G, NTSC M and SECAM
+can handle: PAL B/G, NTSC M and SECAM
Philips saa7114 TV decoder
-was introduced in 2000, is used in the LML33R10 and
+was introduced in 2000, is used in the LML33R10 and
can handle: PAL B/G/D/H/I/N, PAL N, PAL M, NTSC M, NTSC 4.43 and SECAM
Brooktree bt819 TV decoder
@@ -206,7 +206,7 @@ was introduced in 1996, is used in the BUZ
can generate: PAL B/G, NTSC M
Brooktree bt856 TV Encoder
-was introduced in 1994, is used in the LML33
+was introduced in 1994, is used in the LML33
can generate: PAL B/D/G/H/I/N, PAL M, NTSC M, PAL-N (Argentina)
Analog Devices adv7170 TV Encoder
@@ -221,9 +221,9 @@ ITT mse3000 TV encoder
was introduced in 1991, is used in the DC10 old
can generate: PAL , NTSC , SECAM
-The adv717x, should be able to produce PAL N. But you find nothing PAL N
+The adv717x, should be able to produce PAL N. But you find nothing PAL N
specific in the registers. Seem that you have to reuse a other standard
-to generate PAL N, maybe it would work if you use the PAL M settings.
+to generate PAL N, maybe it would work if you use the PAL M settings.
==========================
@@ -261,7 +261,7 @@ Here's my experience of using LML33 and Buz on various motherboards:
VIA MVP3
Forget it. Pointless. Doesn't work.
-Intel 430FX (Pentium 200)
+Intel 430FX (Pentium 200)
LML33 perfect, Buz tolerable (3 or 4 frames dropped per movie)
Intel 440BX (early stepping)
LML33 tolerable. Buz starting to get annoying (6-10 frames/hour)
@@ -438,52 +438,52 @@ importance of buffer sizes:
> -q 25 -b 128 : 24.655.992
> -q 25 -b 256 : 25.859.820
-I woke up, and can't go to sleep again. I'll kill some time explaining why
+I woke up, and can't go to sleep again. I'll kill some time explaining why
this doesn't look strange to me.
-Let's do some math using a width of 704 pixels. I'm not sure whether the Buz
+Let's do some math using a width of 704 pixels. I'm not sure whether the Buz
actually use that number or not, but that's not too important right now.
-704x288 pixels, one field, is 202752 pixels. Divided by 64 pixels per block;
-3168 blocks per field. Each pixel consist of two bytes; 128 bytes per block;
-1024 bits per block. 100% in the new driver mean 1:2 compression; the maximum
-output becomes 512 bits per block. Actually 510, but 512 is simpler to use
+704x288 pixels, one field, is 202752 pixels. Divided by 64 pixels per block;
+3168 blocks per field. Each pixel consist of two bytes; 128 bytes per block;
+1024 bits per block. 100% in the new driver mean 1:2 compression; the maximum
+output becomes 512 bits per block. Actually 510, but 512 is simpler to use
for calculations.
-Let's say that we specify d1q50. We thus want 256 bits per block; times 3168
-becomes 811008 bits; 101376 bytes per field. We're talking raw bits and bytes
-here, so we don't need to do any fancy corrections for bits-per-pixel or such
+Let's say that we specify d1q50. We thus want 256 bits per block; times 3168
+becomes 811008 bits; 101376 bytes per field. We're talking raw bits and bytes
+here, so we don't need to do any fancy corrections for bits-per-pixel or such
things. 101376 bytes per field.
-d1 video contains two fields per frame. Those sum up to 202752 bytes per
+d1 video contains two fields per frame. Those sum up to 202752 bytes per
frame, and one of those frames goes into each buffer.
-But wait a second! -b128 gives 128kB buffers! It's not possible to cram
+But wait a second! -b128 gives 128kB buffers! It's not possible to cram
202752 bytes of JPEG data into 128kB!
-This is what the driver notice and automatically compensate for in your
+This is what the driver notice and automatically compensate for in your
examples. Let's do some math using this information:
-128kB is 131072 bytes. In this buffer, we want to store two fields, which
-leaves 65536 bytes for each field. Using 3168 blocks per field, we get
-20.68686868... available bytes per block; 165 bits. We can't allow the
-request for 256 bits per block when there's only 165 bits available! The -q50
-option is silently overridden, and the -b128 option takes precedence, leaving
+128kB is 131072 bytes. In this buffer, we want to store two fields, which
+leaves 65536 bytes for each field. Using 3168 blocks per field, we get
+20.68686868... available bytes per block; 165 bits. We can't allow the
+request for 256 bits per block when there's only 165 bits available! The -q50
+option is silently overridden, and the -b128 option takes precedence, leaving
us with the equivalence of -q32.
-This gives us a data rate of 165 bits per block, which, times 3168, sums up
-to 65340 bytes per field, out of the allowed 65536. The current driver has
-another level of rate limiting; it won't accept -q values that fill more than
-6/8 of the specified buffers. (I'm not sure why. "Playing it safe" seem to be
-a safe bet. Personally, I think I would have lowered requested-bits-per-block
-by one, or something like that.) We can't use 165 bits per block, but have to
-lower it again, to 6/8 of the available buffer space: We end up with 124 bits
-per block, the equivalence of -q24. With 128kB buffers, you can't use greater
+This gives us a data rate of 165 bits per block, which, times 3168, sums up
+to 65340 bytes per field, out of the allowed 65536. The current driver has
+another level of rate limiting; it won't accept -q values that fill more than
+6/8 of the specified buffers. (I'm not sure why. "Playing it safe" seem to be
+a safe bet. Personally, I think I would have lowered requested-bits-per-block
+by one, or something like that.) We can't use 165 bits per block, but have to
+lower it again, to 6/8 of the available buffer space: We end up with 124 bits
+per block, the equivalence of -q24. With 128kB buffers, you can't use greater
than -q24 at -d1. (And PAL, and 704 pixels width...)
-The third example is limited to -q24 through the same process. The second
-example, using very similar calculations, is limited to -q48. The only
-example that actually grab at the specified -q value is the last one, which
+The third example is limited to -q24 through the same process. The second
+example, using very similar calculations, is limited to -q48. The only
+example that actually grab at the specified -q value is the last one, which
is clearly visible, looking at the file size.
--
diff --git a/Documentation/video4linux/bttv/ICs b/Documentation/video4linux/bttv/ICs
index 6b749133696..611315f87c3 100644
--- a/Documentation/video4linux/bttv/ICs
+++ b/Documentation/video4linux/bttv/ICs
@@ -14,13 +14,13 @@ Hauppauge Win/TV pci (version 405):
Microchip 24LC02B or
Philips 8582E2Y: 256 Byte EEPROM with configuration information
- I2C 0xa0-0xa1, (24LC02B also responds to 0xa2-0xaf)
+ I2C 0xa0-0xa1, (24LC02B also responds to 0xa2-0xaf)
Philips SAA5246AGP/E: Videotext decoder chip, I2C 0x22-0x23
TDA9800: sound decoder
Winbond W24257AS-35: 32Kx8 CMOS static RAM (Videotext buffer mem)
14052B: analog switch for selection of sound source
-PAL:
+PAL:
TDA5737: VHF, hyperband and UHF mixer/oscillator for TV and VCR 3-band tuners
TSA5522: 1.4 GHz I2C-bus controlled synthesizer, I2C 0xc2-0xc3
diff --git a/Documentation/video4linux/bttv/PROBLEMS b/Documentation/video4linux/bttv/PROBLEMS
index 8e31e9e36bf..2b8b0079f7c 100644
--- a/Documentation/video4linux/bttv/PROBLEMS
+++ b/Documentation/video4linux/bttv/PROBLEMS
@@ -3,7 +3,7 @@
- Start capturing by pressing "c" or by selecting it via a menu!!!
- The memory of some S3 cards is not recognized right:
-
+
First of all, if you are not using XFree-3.2 or newer, upgrade AT LEAST to
XFree-3.2A! This solved the problem for most people.
@@ -31,23 +31,23 @@
(mostly with Trio 64 but also with some others)
Get the free demo version of Accelerated X from www.xinside.com and try
bttv with it. bttv seems to work with most S3 cards with Accelerated X.
-
+
Since I do not know much (better make that almost nothing) about VGA card
programming I do not know the reason for this.
Looks like XFree does something different when setting up the video memory?
- Maybe somebody can enlighten me?
- Would be nice if somebody could get this to work with XFree since
- Accelerated X costs more than some of the grabber cards ...
-
+ Maybe somebody can enlighten me?
+ Would be nice if somebody could get this to work with XFree since
+ Accelerated X costs more than some of the grabber cards ...
+
Better linear frame buffer support for S3 cards will probably be in
XFree 4.0.
-
+
- Grabbing is not switched off when changing consoles with XFree.
That's because XFree and some AcceleratedX versions do not send unmap
events.
- Some popup windows (e.g. of the window manager) are not refreshed.
-
+
Disable backing store by starting X with the option "-bs"
- When using 32 bpp in XFree or 24+8bpp mode in AccelX 3.1 the system
diff --git a/Documentation/video4linux/bttv/README.quirks b/Documentation/video4linux/bttv/README.quirks
index e8edb87df71..92e03929a6b 100644
--- a/Documentation/video4linux/bttv/README.quirks
+++ b/Documentation/video4linux/bttv/README.quirks
@@ -38,9 +38,9 @@ tolerate.
------------------------
When using the 430FX PCI, the following rules will ensure
-compatibility:
+compatibility:
- (1) Deassert REQ at the same time as asserting FRAME.
+ (1) Deassert REQ at the same time as asserting FRAME.
(2) Do not reassert REQ to request another bus transaction until after
finish-ing the previous transaction.
diff --git a/Documentation/video4linux/bttv/THANKS b/Documentation/video4linux/bttv/THANKS
index 2085399da7d..950aa781c2e 100644
--- a/Documentation/video4linux/bttv/THANKS
+++ b/Documentation/video4linux/bttv/THANKS
@@ -1,6 +1,6 @@
Many thanks to:
-- Markus Schroeder <schroedm@uni-duesseldorf.de> for information on the Bt848
+- Markus Schroeder <schroedm@uni-duesseldorf.de> for information on the Bt848
and tuner programming and his control program xtvc.
- Martin Buck <martin-2.buck@student.uni-ulm.de> for his great Videotext
@@ -16,7 +16,7 @@ Many thanks to:
- MIRO for providing a free PCTV card and detailed information about the
components on their cards. (E.g. how the tuner type is detected)
Without their card I could not have debugged the NTSC mode.
-
+
- Hauppauge for telling how the sound input is selected and what components
they do and will use on their radio cards.
Also many thanks for faxing me the FM1216 data sheet.
diff --git a/Documentation/video4linux/radiotrack.txt b/Documentation/video4linux/radiotrack.txt
index 2b75345f13e..d1f3ed19918 100644
--- a/Documentation/video4linux/radiotrack.txt
+++ b/Documentation/video4linux/radiotrack.txt
@@ -131,17 +131,17 @@ Check Stereo: BASE <-- 0xd8 (current volume, stereo detect,
x=0xff ==> "not stereo", x=0xfd ==> "stereo detected"
Set Frequency: code = (freq*40) + 10486188
- foreach of the 24 bits in code,
- (from Least to Most Significant):
- to write a "zero" bit,
- BASE <-- 0x01 (audio mute, no stereo detect, radio
+ foreach of the 24 bits in code,
+ (from Least to Most Significant):
+ to write a "zero" bit,
+ BASE <-- 0x01 (audio mute, no stereo detect, radio
disable, "zero" bit phase 1, tuner adjust)
- BASE <-- 0x03 (audio mute, no stereo detect, radio
+ BASE <-- 0x03 (audio mute, no stereo detect, radio
disable, "zero" bit phase 2, tuner adjust)
- to write a "one" bit,
- BASE <-- 0x05 (audio mute, no stereo detect, radio
+ to write a "one" bit,
+ BASE <-- 0x05 (audio mute, no stereo detect, radio
disable, "one" bit phase 1, tuner adjust)
- BASE <-- 0x07 (audio mute, no stereo detect, radio
+ BASE <-- 0x07 (audio mute, no stereo detect, radio
disable, "one" bit phase 2, tuner adjust)
----------------------------------------------------------------------------
diff --git a/Documentation/video4linux/w9966.txt b/Documentation/video4linux/w9966.txt
index e7ac33a7eb0..78a651254b8 100644
--- a/Documentation/video4linux/w9966.txt
+++ b/Documentation/video4linux/w9966.txt
@@ -26,7 +26,7 @@ is called VIDEO_PALETTE_YUV422 (16 bpp).
A minimal test application (with source) is available from:
http://hem.fyristorg.com/mogul/w9966.html
-The slow framerate is due to missing DMA ECP read support in the
+The slow framerate is due to missing DMA ECP read support in the
parport drivers. I might add working EPP support later.
Good luck!
diff --git a/Documentation/video4linux/zr36120.txt b/Documentation/video4linux/zr36120.txt
index 5d6357eefde..ac6d92d0194 100644
--- a/Documentation/video4linux/zr36120.txt
+++ b/Documentation/video4linux/zr36120.txt
@@ -2,7 +2,7 @@ Driver for Trust Computer Products Framegrabber, version 0.6.1
------ --- ----- -------- -------- ------------ ------- - - -
- ZORAN ------------------------------------------------------
- Author: Pauline Middelink <middelin@polyware.nl>
+ Author: Pauline Middelink <middelin@polyware.nl>
Date: 18 September 1999
Version: 0.6.1
@@ -115,7 +115,7 @@ After making/checking the devices do:
<n> is the cardtype of the card you have. The cardnumber can
be found in the source of zr36120. Look for tvcards. If your
card is not there, please try if any other card gives some
-response, and mail me if you got a working tvcard addition.
+response, and mail me if you got a working tvcard addition.
PS. <TVCard editors behold!)
Dont forget to set video_input to the number of inputs
diff --git a/MAINTAINERS b/MAINTAINERS
index 5b6a0145505..c9465811add 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -147,6 +147,18 @@ M: p_gortmaker@yahoo.com
L: netdev@vger.kernel.org
S: Maintained
+9P FILE SYSTEM
+P: Eric Van Hensbergen
+M: ericvh@gmail.com
+P: Ron Minnich
+M: rminnich@lanl.gov
+P: Latchesar Ionkov
+M: lucho@ionkov.net
+L: v9fs-developer@lists.sourceforge.net
+W: http://v9fs.sf.net
+T: git kernel.org:/pub/scm/linux/kernel/ericvh/v9fs.git
+S: Maintained
+
A2232 SERIAL BOARD DRIVER
P: Enver Haase
M: ehaase@inf.fu-berlin.de
@@ -870,13 +882,34 @@ W: http://ebtables.sourceforge.net/
S: Maintained
EDAC-CORE
-P: Doug Thompson
-M: norsk5@xmission.com, dthompson@linuxnetworx.com
-P: Dave Peterson
-M: dsp@llnl.gov, dave_peterson@pobox.com
-L: bluesmoke-devel@lists.sourceforge.net
-W: bluesmoke.sourceforge.net
-S: Maintained
+P: Doug Thompson
+M: norsk5@xmission.com, dthompson@linuxnetworx.com
+P: Dave Peterson
+M: dsp@llnl.gov, dave_peterson@pobox.com
+L: bluesmoke-devel@lists.sourceforge.net
+W: bluesmoke.sourceforge.net
+S: Maintained
+
+EDAC-E752X
+P: Dave Peterson
+M: dsp@llnl.gov, dave_peterson@pobox.com
+L: bluesmoke-devel@lists.sourceforge.net
+W: bluesmoke.sourceforge.net
+S: Maintained
+
+EDAC-E7XXX
+P: Dave Peterson
+M: dsp@llnl.gov, dave_peterson@pobox.com
+L: bluesmoke-devel@lists.sourceforge.net
+W: bluesmoke.sourceforge.net
+S: Maintained
+
+EDAC-R82600
+P: Tim Small
+M: tim@buttersideup.com
+L: bluesmoke-devel@lists.sourceforge.net
+W: bluesmoke.sourceforge.net
+S: Maintained
EEPRO100 NETWORK DRIVER
P: Andrey V. Savochkin
@@ -1027,6 +1060,15 @@ M: khc@pm.waw.pl
W: http://www.kernel.org/pub/linux/utils/net/hdlc/
S: Maintained
+GIGASET ISDN DRIVERS
+P: Hansjoerg Lipp
+M: hjlipp@web.de
+P: Tilman Schmidt
+M: tilman@imap.cc
+L: gigaset307x-common@lists.sourceforge.net
+W: http://gigaset307x.sourceforge.net/
+S: Maintained
+
HARDWARE MONITORING
P: Jean Delvare
M: khali@linux-fr.org
@@ -1843,6 +1885,7 @@ NETWORKING [GENERAL]
P: Networking Team
M: netdev@vger.kernel.org
L: netdev@vger.kernel.org
+W: http://linux-net.osdl.org/
S: Maintained
NETWORKING [IPv4/IPv6]
@@ -2013,12 +2056,6 @@ L: parisc-linux@parisc-linux.org
W: http://www.parisc-linux.org/
S: Maintained
-PERSONALITY HANDLING
-P: Christoph Hellwig
-M: hch@infradead.org
-L: linux-abi-devel@lists.sourceforge.net
-S: Maintained
-
PCI ERROR RECOVERY
P: Linas Vepstas
M: linas@austin.ibm.com
@@ -2069,6 +2106,12 @@ M: tsbogend@alpha.franken.de
L: netdev@vger.kernel.org
S: Maintained
+PERSONALITY HANDLING
+P: Christoph Hellwig
+M: hch@infradead.org
+L: linux-abi-devel@lists.sourceforge.net
+S: Maintained
+
PHRAM MTD DRIVER
P: Jörn Engel
M: joern@wh.fh-wedel.de
@@ -2191,6 +2234,12 @@ M: p_gortmaker@yahoo.com
L: linux-kernel@vger.kernel.org
S: Maintained
+REAL TIME CLOCK (RTC) SUBSYSTEM
+P: Alessandro Zummo
+M: a.zummo@towertech.it
+L: linux-kernel@vger.kernel.org
+S: Maintained
+
REISERFS FILE SYSTEM
P: Hans Reiser
M: reiserfs-dev@namesys.com
@@ -2212,13 +2261,6 @@ S: Maintained
RISCOM8 DRIVER
S: Orphan
-RTLINUX REALTIME LINUX
-P: Victor Yodaiken
-M: yodaiken@fsmlabs.com
-L: rtl@rtlinux.org
-W: www.rtlinux.org
-S: Maintained
-
S3 SAVAGE FRAMEBUFFER DRIVER
P: Antonino Daplas
M: adaplas@pol.net
@@ -2531,7 +2573,6 @@ S: Unsupported ?
STRADIS MPEG-2 DECODER DRIVER
P: Nathan Laredo
M: laredo@gnu.org
-W: http://mpeg.openprojects.net/
W: http://www.stradis.com/
S: Maintained
@@ -2650,7 +2691,7 @@ S: Maintained
TUN/TAP driver
P: Maxim Krasnyansky
-M: maxk@qualcomm.com, max_mk@yahoo.com
+M: maxk@qualcomm.com
L: vtun@office.satix.net
W: http://vtun.sourceforge.net/tun
S: Maintained
@@ -2979,18 +3020,6 @@ L: rio500-users@lists.sourceforge.net
W: http://rio500.sourceforge.net
S: Maintained
-V9FS FILE SYSTEM
-P: Eric Van Hensbergen
-M: ericvh@gmail.com
-P: Ron Minnich
-M: rminnich@lanl.gov
-P: Latchesar Ionkov
-M: lucho@ionkov.net
-L: v9fs-developer@lists.sourceforge.net
-W: http://v9fs.sf.net
-T: git kernel.org:/pub/scm/linux/kernel/ericvh/v9fs-devel.git
-S: Maintained
-
VIDEO FOR LINUX
P: Mauro Carvalho Chehab
M: mchehab@infradead.org
diff --git a/Makefile b/Makefile
index 14781f36e32..af6210d4883 100644
--- a/Makefile
+++ b/Makefile
@@ -95,7 +95,7 @@ ifdef O
endif
# That's our default target when none is given on the command line
-.PHONY: _all
+PHONY := _all
_all:
ifneq ($(KBUILD_OUTPUT),)
@@ -106,7 +106,7 @@ KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
$(if $(KBUILD_OUTPUT),, \
$(error output directory "$(saved-output)" does not exist))
-.PHONY: $(MAKECMDGOALS)
+PHONY += $(MAKECMDGOALS)
$(filter-out _all,$(MAKECMDGOALS)) _all:
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
@@ -123,7 +123,7 @@ ifeq ($(skip-makefile),)
# If building an external module we do not care about the all: rule
# but instead _all depend on modules
-.PHONY: all
+PHONY += all
ifeq ($(KBUILD_EXTMOD),)
_all: all
else
@@ -137,7 +137,7 @@ objtree := $(CURDIR)
src := $(srctree)
obj := $(objtree)
-VPATH := $(srctree)
+VPATH := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
export srctree objtree VPATH TOPDIR
@@ -151,7 +151,7 @@ export srctree objtree VPATH TOPDIR
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/ \
-e s/s390x/s390/ -e s/parisc64/parisc/ \
- -e s/ppc.*/powerpc/ )
+ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ )
# Cross compiling and selecting different set of gcc/bin-utils
# ---------------------------------------------------------------------------
@@ -258,38 +258,6 @@ endif
export quiet Q KBUILD_VERBOSE
-######
-# cc support functions to be used (only) in arch/$(ARCH)/Makefile
-# See documentation in Documentation/kbuild/makefiles.txt
-
-# as-option
-# Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,)
-
-as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
- -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \
- else echo "$(2)"; fi ;)
-
-# cc-option
-# Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
-
-cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
- > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
-
-# cc-option-yn
-# Usage: flag := $(call cc-option-yn, -march=winchip-c6)
-cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
- > /dev/null 2>&1; then echo "y"; else echo "n"; fi;)
-
-# cc-option-align
-# Prefix align with either -falign or -malign
-cc-option-align = $(subst -functions=0,,\
- $(call cc-option,-falign-functions=0,-malign-functions=0))
-
-# cc-version
-# Usage gcc-ver := $(call cc-version $(CC))
-cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
- $(if $(1), $(1), $(CC)))
-
# Look for make include files relative to root of kernel src
MAKEFLAGS += --include-dir=$(srctree)
@@ -338,8 +306,7 @@ LINUXINCLUDE := -Iinclude \
CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
- -fno-strict-aliasing -fno-common \
- -ffreestanding
+ -fno-strict-aliasing -fno-common
AFLAGS := -D__ASSEMBLY__
# Read KERNELRELEASE from .kernelrelease (if it exists)
@@ -369,14 +336,14 @@ export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exc
# Rules shared between *config targets and build targets
# Basic helpers built in scripts/
-.PHONY: scripts_basic
+PHONY += scripts_basic
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
# To avoid any implicit rule to kick in, define an empty command.
scripts/basic/%: scripts_basic ;
-.PHONY: outputmakefile
+PHONY += outputmakefile
# outputmakefile generate a Makefile to be placed in output directory, if
# using a seperate output directory. This allows convinient use
# of make in output directory
@@ -452,7 +419,7 @@ ifeq ($(KBUILD_EXTMOD),)
# Additional helpers built in scripts/
# Carefully list dependencies so we do not try to build scripts twice
# in parrallel
-.PHONY: scripts
+PHONY += scripts
scripts: scripts_basic include/config/MARKER
$(Q)$(MAKE) $(build)=$(@)
@@ -504,13 +471,6 @@ else
CFLAGS += -O2
endif
-#Add align options if CONFIG_CC_* is not equal to 0
-add-align = $(if $(filter-out 0,$($(1))),$(cc-option-align)$(2)=$($(1)))
-CFLAGS += $(call add-align,CONFIG_CC_ALIGN_FUNCTIONS,-functions)
-CFLAGS += $(call add-align,CONFIG_CC_ALIGN_LABELS,-labels)
-CFLAGS += $(call add-align,CONFIG_CC_ALIGN_LOOPS,-loops)
-CFLAGS += $(call add-align,CONFIG_CC_ALIGN_JUMPS,-jumps)
-
ifdef CONFIG_FRAME_POINTER
CFLAGS += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)
else
@@ -756,7 +716,7 @@ $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
# make menuconfig etc.
# Error messages still appears in the original language
-.PHONY: $(vmlinux-dirs)
+PHONY += $(vmlinux-dirs)
$(vmlinux-dirs): prepare scripts
$(Q)$(MAKE) $(build)=$@
@@ -809,10 +769,10 @@ kernelrelease = $(KERNELVERSION)$(localver-full)
# version.h and scripts_basic is processed / created.
# Listed in dependency order
-.PHONY: prepare archprepare prepare0 prepare1 prepare2 prepare3
+PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
# prepare-all is deprecated, use prepare as valid replacement
-.PHONY: prepare-all
+PHONY += prepare-all
# prepare3 is used to check if we are building in a separate output directory,
# and if so do:
@@ -853,27 +813,6 @@ prepare prepare-all: prepare0
export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
-# Single targets
-# ---------------------------------------------------------------------------
-
-%.s: %.c scripts FORCE
- $(Q)$(MAKE) $(build)=$(@D) $@
-%.i: %.c scripts FORCE
- $(Q)$(MAKE) $(build)=$(@D) $@
-%.o: %.c scripts FORCE
- $(Q)$(MAKE) $(build)=$(@D) $@
-%.ko: scripts FORCE
- $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) $(build)=$(@D) $(@:.ko=.o)
- $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
-%/: scripts prepare FORCE
- $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) $(build)=$(@D)
-%.lst: %.c scripts FORCE
- $(Q)$(MAKE) $(build)=$(@D) $@
-%.s: %.S scripts FORCE
- $(Q)$(MAKE) $(build)=$(@D) $@
-%.o: %.S scripts FORCE
- $(Q)$(MAKE) $(build)=$(@D) $@
-
# FIXME: The asm symlink changes when $(ARCH) changes. That's
# hard to detect, but I suppose "make mrproper" is a good idea
# before switching between archs anyway.
@@ -914,7 +853,7 @@ include/linux/version.h: $(srctree)/Makefile .config .kernelrelease FORCE
# ---------------------------------------------------------------------------
-.PHONY: depend dep
+PHONY += depend dep
depend dep:
@echo '*** Warning: make $@ is unnecessary now.'
@@ -929,21 +868,21 @@ all: modules
# Build modules
-.PHONY: modules
+PHONY += modules
modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
@echo ' Building modules, stage 2.';
$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
# Target to prepare building external modules
-.PHONY: modules_prepare
+PHONY += modules_prepare
modules_prepare: prepare scripts
# Target to install modules
-.PHONY: modules_install
+PHONY += modules_install
modules_install: _modinst_ _modinst_post
-.PHONY: _modinst_
+PHONY += _modinst_
_modinst_:
@if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \
echo "Warning: you may need to install module-init-tools"; \
@@ -970,7 +909,7 @@ depmod_opts :=
else
depmod_opts := -b $(INSTALL_MOD_PATH) -r
endif
-.PHONY: _modinst_post
+PHONY += _modinst_post
_modinst_post: _modinst_
if [ -r System.map -a -x $(DEPMOD) ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
@@ -1013,7 +952,7 @@ clean: rm-dirs := $(CLEAN_DIRS)
clean: rm-files := $(CLEAN_FILES)
clean-dirs := $(addprefix _clean_,$(srctree) $(vmlinux-alldirs))
-.PHONY: $(clean-dirs) clean archclean
+PHONY += $(clean-dirs) clean archclean
$(clean-dirs):
$(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
@@ -1031,7 +970,7 @@ mrproper: rm-dirs := $(wildcard $(MRPROPER_DIRS))
mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
mrproper-dirs := $(addprefix _mrproper_,Documentation/DocBook scripts)
-.PHONY: $(mrproper-dirs) mrproper archmrproper
+PHONY += $(mrproper-dirs) mrproper archmrproper
$(mrproper-dirs):
$(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)
@@ -1041,7 +980,7 @@ mrproper: clean archmrproper $(mrproper-dirs)
# distclean
#
-.PHONY: distclean
+PHONY += distclean
distclean: mrproper
@find $(srctree) $(RCS_FIND_IGNORE) \
@@ -1057,12 +996,10 @@ distclean: mrproper
# rpm target kept for backward compatibility
package-dir := $(srctree)/scripts/package
-.PHONY: %-pkg rpm
-
%pkg: FORCE
- $(Q)$(MAKE) -f $(package-dir)/Makefile $@
+ $(Q)$(MAKE) $(build)=$(package-dir) $@
rpm: FORCE
- $(Q)$(MAKE) -f $(package-dir)/Makefile $@
+ $(Q)$(MAKE) $(build)=$(package-dir) $@
# Brief documentation of the typical targets used
@@ -1094,13 +1031,11 @@ help:
@echo ' kernelversion - Output the version stored in Makefile'
@echo ''
@echo 'Static analysers'
- @echo ' buildcheck - List dangling references to vmlinux discarded sections'
- @echo ' and init sections from non-init sections'
@echo ' checkstack - Generate a list of stack hogs'
@echo ' namespacecheck - Name space analysis on compiled kernel'
@echo ''
@echo 'Kernel packaging:'
- @$(MAKE) -f $(package-dir)/Makefile help
+ @$(MAKE) $(build)=$(package-dir) help
@echo ''
@echo 'Documentation targets:'
@$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp
@@ -1149,11 +1084,12 @@ else # KBUILD_EXTMOD
# We are always building modules
KBUILD_MODULES := 1
-.PHONY: crmodverdir
+PHONY += crmodverdir
crmodverdir:
+ $(Q)rm -rf $(MODVERDIR)
$(Q)mkdir -p $(MODVERDIR)
-.PHONY: $(objtree)/Module.symvers
+PHONY += $(objtree)/Module.symvers
$(objtree)/Module.symvers:
@test -e $(objtree)/Module.symvers || ( \
echo; \
@@ -1162,7 +1098,7 @@ $(objtree)/Module.symvers:
echo )
module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
-.PHONY: $(module-dirs) modules
+PHONY += $(module-dirs) modules
$(module-dirs): crmodverdir $(objtree)/Module.symvers
$(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@)
@@ -1170,13 +1106,32 @@ modules: $(module-dirs)
@echo ' Building modules, stage 2.';
$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
-.PHONY: modules_install
-modules_install:
+PHONY += modules_install
+modules_install: _emodinst_ _emodinst_post
+
+install-dir := $(if $(INSTALL_MOD_DIR),$(INSTALL_MOD_DIR),extra)
+PHONY += _emodinst_
+_emodinst_:
+ $(Q)rm -rf $(MODLIB)/$(install-dir)
+ $(Q)mkdir -p $(MODLIB)/$(install-dir)
$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst
+# Run depmod only is we have System.map and depmod is executable
+quiet_cmd_depmod = DEPMOD $(KERNELRELEASE)
+ cmd_depmod = if [ -r System.map -a -x $(DEPMOD) ]; then \
+ $(DEPMOD) -ae -F System.map \
+ $(if $(strip $(INSTALL_MOD_PATH)), \
+ -b $(INSTALL_MOD_PATH) -r) \
+ $(KERNELRELEASE); \
+ fi
+
+PHONY += _emodinst_post
+_emodinst_post: _emodinst_
+ $(call cmd,depmod)
+
clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD))
-.PHONY: $(clean-dirs) clean
+PHONY += $(clean-dirs) clean
$(clean-dirs):
$(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
@@ -1196,6 +1151,11 @@ help:
@echo ' modules_install - install the module'
@echo ' clean - remove generated files in module directory only'
@echo ''
+
+# Dummies...
+PHONY += prepare scripts
+prepare: ;
+scripts: ;
endif # KBUILD_EXTMOD
# Generate tags for editors
@@ -1296,17 +1256,13 @@ versioncheck:
-name '*.[hcS]' -type f -print | sort \
| xargs $(PERL) -w scripts/checkversion.pl
-buildcheck:
- $(PERL) $(srctree)/scripts/reference_discarded.pl
- $(PERL) $(srctree)/scripts/reference_init.pl
-
namespacecheck:
$(PERL) $(srctree)/scripts/namespace.pl
endif #ifeq ($(config-targets),1)
endif #ifeq ($(mixed-targets),1)
-.PHONY: checkstack
+PHONY += checkstack
checkstack:
$(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
$(PERL) $(src)/scripts/checkstack.pl $(ARCH)
@@ -1317,6 +1273,44 @@ kernelrelease:
kernelversion:
@echo $(KERNELVERSION)
+# Single targets
+# ---------------------------------------------------------------------------
+# The directory part is taken from first prerequisite, so this
+# works even with external modules
+%.s: %.c prepare scripts FORCE
+ $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+%.i: %.c prepare scripts FORCE
+ $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+%.o: %.c prepare scripts FORCE
+ $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+%.lst: %.c prepare scripts FORCE
+ $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+%.s: %.S prepare scripts FORCE
+ $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+%.o: %.S prepare scripts FORCE
+ $(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+
+# For external modules we shall include any directory of the target,
+# but usual case there is no directory part.
+# make M=`pwd` module.o => $(dir $@)=./
+# make M=`pwd` foo/module.o => $(dir $@)=foo/
+# make M=`pwd` / => $(dir $@)=/
+
+ifeq ($(KBUILD_EXTMOD),)
+ target-dir = $(@D)
+else
+ zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@)))
+ target-dir = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
+endif
+
+/ %/: scripts prepare FORCE
+ $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
+ $(build)=$(target-dir)
+%.ko: scripts FORCE
+ $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
+ $(build)=$(target-dir) $(@:.ko=.o)
+ $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
+
# FIXME Should go into a make.lib or something
# ===========================================================================
@@ -1351,4 +1345,10 @@ clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
endif # skip-makefile
+PHONY += FORCE
FORCE:
+
+
+# Declare the contents of the .PHONY variable as phony. We keep that
+# information in a variable se we can use it in if_changed and friends.
+.PHONY: $(PHONY)
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index eedf41bf705..9bef61b3036 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -25,6 +25,10 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default y
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
@@ -447,6 +451,10 @@ config ALPHA_IRONGATE
depends on ALPHA_NAUTILUS
default y
+config GENERIC_HWEIGHT
+ bool
+ default y if !ALPHA_EV6 && !ALPHA_EV67
+
config ALPHA_AVANTI
bool
depends on ALPHA_XL || ALPHA_AVANTI_CH
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 7fb14f42a12..31afe3d91ac 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -821,7 +821,6 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
affects all sorts of things, like timeval and itimerval. */
extern struct timezone sys_tz;
-extern int do_adjtimex(struct timex *);
struct timeval32
{
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index b4e5f8ff2b2..dd876967059 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -34,6 +34,7 @@
#include <linux/root_dev.h>
#include <linux/initrd.h>
#include <linux/eisa.h>
+#include <linux/pfn.h>
#ifdef CONFIG_MAGIC_SYSRQ
#include <linux/sysrq.h>
#include <linux/reboot.h>
@@ -42,7 +43,7 @@
#include <asm/setup.h>
#include <asm/io.h>
-extern struct notifier_block *panic_notifier_list;
+extern struct atomic_notifier_head panic_notifier_list;
static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
static struct notifier_block alpha_panic_block = {
alpha_panic_event,
@@ -241,9 +242,6 @@ reserve_std_resources(void)
request_resource(io, standard_io_resources+i);
}
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
#define PFN_MAX PFN_DOWN(0x80000000)
#define for_each_mem_cluster(memdesc, cluster, i) \
for ((cluster) = (memdesc)->cluster, (i) = 0; \
@@ -472,11 +470,6 @@ page_is_ram(unsigned long pfn)
return 0;
}
-#undef PFN_UP
-#undef PFN_DOWN
-#undef PFN_PHYS
-#undef PFN_MAX
-
void __init
setup_arch(char **cmdline_p)
{
@@ -507,7 +500,8 @@ setup_arch(char **cmdline_p)
}
/* Register a call for panic conditions. */
- notifier_chain_register(&panic_notifier_list, &alpha_panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &alpha_panic_block);
#ifdef CONFIG_ALPHA_GENERIC
/* Assume that we've booted from SRM if we haven't booted from MILO.
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 6b2921be190..3859749810b 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -314,10 +314,11 @@ time_init(void)
if (!est_cycle_freq)
est_cycle_freq = validate_cc_value(calibrate_cc_with_pit());
- cc1 = rpcc_after_update_in_progress();
+ cc1 = rpcc();
/* Calibrate CPU clock -- attempt #2. */
if (!est_cycle_freq) {
+ cc1 = rpcc_after_update_in_progress();
cc2 = rpcc_after_update_in_progress();
est_cycle_freq = validate_cc_value(cc2 - cc1);
cc1 = cc2;
diff --git a/arch/alpha/lib/ev6-memchr.S b/arch/alpha/lib/ev6-memchr.S
index a8e843dbcc2..1a5f71b9d8b 100644
--- a/arch/alpha/lib/ev6-memchr.S
+++ b/arch/alpha/lib/ev6-memchr.S
@@ -84,7 +84,7 @@ $last_quad:
beq $2, $not_found # U : U L U L
$found_it:
-#if defined(__alpha_fix__) && defined(__alpha_cix__)
+#ifdef CONFIG_ALPHA_EV67
/*
* Since we are guaranteed to have set one of the bits, we don't
* have to worry about coming back with a 0x40 out of cttz...
diff --git a/arch/alpha/lib/fpreg.c b/arch/alpha/lib/fpreg.c
index 97c4d9d7a4d..05017ba34c3 100644
--- a/arch/alpha/lib/fpreg.c
+++ b/arch/alpha/lib/fpreg.c
@@ -4,7 +4,7 @@
* (C) Copyright 1998 Linus Torvalds
*/
-#if defined(__alpha_cix__) || defined(__alpha_fix__)
+#if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67)
#define STT(reg,val) asm volatile ("ftoit $f"#reg",%0" : "=r"(val));
#else
#define STT(reg,val) asm volatile ("stt $f"#reg",%0" : "=m"(val));
@@ -53,7 +53,7 @@ alpha_read_fp_reg (unsigned long reg)
return val;
}
-#if defined(__alpha_cix__) || defined(__alpha_fix__)
+#if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67)
#define LDT(reg,val) asm volatile ("itoft %0,$f"#reg : : "r"(val));
#else
#define LDT(reg,val) asm volatile ("ldt $f"#reg",%0" : : "m"(val));
@@ -98,7 +98,7 @@ alpha_write_fp_reg (unsigned long reg, unsigned long val)
}
}
-#if defined(__alpha_cix__) || defined(__alpha_fix__)
+#if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67)
#define STS(reg,val) asm volatile ("ftois $f"#reg",%0" : "=r"(val));
#else
#define STS(reg,val) asm volatile ("sts $f"#reg",%0" : "=m"(val));
@@ -147,7 +147,7 @@ alpha_read_fp_reg_s (unsigned long reg)
return val;
}
-#if defined(__alpha_cix__) || defined(__alpha_fix__)
+#if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67)
#define LDS(reg,val) asm volatile ("itofs %0,$f"#reg : : "r"(val));
#else
#define LDS(reg,val) asm volatile ("lds $f"#reg",%0" : : "m"(val));
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
index 6d5251254f6..bf6b65c81be 100644
--- a/arch/alpha/mm/numa.c
+++ b/arch/alpha/mm/numa.c
@@ -13,6 +13,7 @@
#include <linux/bootmem.h>
#include <linux/swap.h>
#include <linux/initrd.h>
+#include <linux/pfn.h>
#include <asm/hwrpb.h>
#include <asm/pgalloc.h>
@@ -27,9 +28,6 @@ bootmem_data_t node_bdata[MAX_NUMNODES];
#define DBGDCONT(args...)
#endif
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
#define for_each_mem_cluster(memdesc, cluster, i) \
for ((cluster) = (memdesc)->cluster, (i) = 0; \
(i) < (memdesc)->numclusters; (i)++, (cluster)++)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0dd24ebdf6a..ba46d779ede 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -8,6 +8,7 @@ mainmenu "Linux Kernel Configuration"
config ARM
bool
default y
+ select RTC_LIB
help
The ARM series is a line of low-power-consumption RISC chip designs
licensed by ARM Ltd and targeted at embedded applications and
@@ -53,6 +54,10 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
@@ -148,6 +153,12 @@ config ARCH_IXP2000
help
Support for Intel's IXP2400/2800 (XScale) family of processors.
+config ARCH_IXP23XX
+ bool "IXP23XX-based"
+ select PCI
+ help
+ Support for Intel's IXP23xx (XScale) family of processors.
+
config ARCH_L7200
bool "LinkUp-L7200"
select FIQ
@@ -269,6 +280,8 @@ source "arch/arm/mach-ixp4xx/Kconfig"
source "arch/arm/mach-ixp2000/Kconfig"
+source "arch/arm/mach-ixp23xx/Kconfig"
+
source "arch/arm/mach-pxa/Kconfig"
source "arch/arm/mach-sa1100/Kconfig"
@@ -787,7 +800,8 @@ source "drivers/acorn/block/Kconfig"
if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \
|| ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
- || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
+ || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
+ || ARCH_IXP23XX
source "drivers/ide/Kconfig"
endif
@@ -835,6 +849,8 @@ source "drivers/usb/Kconfig"
source "drivers/mmc/Kconfig"
+source "drivers/rtc/Kconfig"
+
endmenu
source "fs/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index b5b1e408751..ce3e804ea0f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -1,6 +1,9 @@
#
# arch/arm/Makefile
#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
@@ -54,6 +57,7 @@ tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi
tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
+tune-$(CONFIG_CPU_XSC3) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
ifeq ($(CONFIG_AEABI),y)
@@ -94,6 +98,7 @@ endif
machine-$(CONFIG_ARCH_IOP3XX) := iop3xx
machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx
machine-$(CONFIG_ARCH_IXP2000) := ixp2000
+ machine-$(CONFIG_ARCH_IXP23XX) := ixp23xx
machine-$(CONFIG_ARCH_OMAP1) := omap1
machine-$(CONFIG_ARCH_OMAP2) := omap2
incdir-$(CONFIG_ARCH_OMAP) := omap
@@ -177,7 +182,7 @@ endif
archprepare: maketools
-.PHONY: maketools FORCE
+PHONY += maketools FORCE
maketools: include/linux/version.h include/asm-arm/.arch FORCE
$(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index a174d63395e..ec9c400c7f8 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -1,6 +1,9 @@
#
# arch/arm/boot/Makefile
#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
@@ -73,7 +76,7 @@ $(obj)/bootpImage: $(obj)/bootp/bootp FORCE
$(call if_changed,objcopy)
@echo ' Kernel: $@ is ready'
-.PHONY: initrd FORCE
+PHONY += initrd FORCE
initrd:
@test "$(INITRD_PHYS)" != "" || \
(echo This machine does not support INITRD; exit -1)
diff --git a/arch/arm/boot/bootp/Makefile b/arch/arm/boot/bootp/Makefile
index 8e8879b6b3d..c394e305447 100644
--- a/arch/arm/boot/bootp/Makefile
+++ b/arch/arm/boot/bootp/Makefile
@@ -1,6 +1,9 @@
#
# linux/arch/arm/boot/bootp/Makefile
#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
LDFLAGS_bootp :=-p --no-undefined -X \
--defsym initrd_phys=$(INITRD_PHYS) \
@@ -21,4 +24,4 @@ $(obj)/kernel.o: arch/arm/boot/zImage FORCE
$(obj)/initrd.o: $(INITRD) FORCE
-.PHONY: $(INITRD) FORCE
+PHONY += $(INITRD) FORCE
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 35ffe0f4ece..2adc1527e0e 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -50,10 +50,6 @@ ifeq ($(CONFIG_ARCH_AT91RM9200),y)
OBJS += head-at91rm9200.o
endif
-ifeq ($(CONFIG_DEBUG_ICEDCC),y)
-OBJS += ice-dcc.o
-endif
-
ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
OBJS += big-endian.o
endif
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index db3389d8e02..491c7e4c9ac 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -358,7 +358,7 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size
str r1, [r0]
mov pc, lr
-__armv4_cache_on:
+__armv4_mmu_cache_on:
mov r12, lr
bl __setup_mmu
mov r0, #0
@@ -367,24 +367,24 @@ __armv4_cache_on:
mrc p15, 0, r0, c1, c0, 0 @ read control reg
orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
orr r0, r0, #0x0030
- bl __common_cache_on
+ bl __common_mmu_cache_on
mov r0, #0
mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
mov pc, r12
-__arm6_cache_on:
+__arm6_mmu_cache_on:
mov r12, lr
bl __setup_mmu
mov r0, #0
mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
mov r0, #0x30
- bl __common_cache_on
+ bl __common_mmu_cache_on
mov r0, #0
mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
mov pc, r12
-__common_cache_on:
+__common_mmu_cache_on:
#ifndef DEBUG
orr r0, r0, #0x000d @ Write buffer, mmu
#endif
@@ -471,12 +471,12 @@ call_cache_fn: adr r12, proc_types
proc_types:
.word 0x41560600 @ ARM6/610
.word 0xffffffe0
- b __arm6_cache_off @ works, but slow
- b __arm6_cache_off
+ b __arm6_mmu_cache_off @ works, but slow
+ b __arm6_mmu_cache_off
mov pc, lr
-@ b __arm6_cache_on @ untested
-@ b __arm6_cache_off
-@ b __armv3_cache_flush
+@ b __arm6_mmu_cache_on @ untested
+@ b __arm6_mmu_cache_off
+@ b __armv3_mmu_cache_flush
.word 0x00000000 @ old ARM ID
.word 0x0000f000
@@ -486,14 +486,14 @@ proc_types:
.word 0x41007000 @ ARM7/710
.word 0xfff8fe00
- b __arm7_cache_off
- b __arm7_cache_off
+ b __arm7_mmu_cache_off
+ b __arm7_mmu_cache_off
mov pc, lr
.word 0x41807200 @ ARM720T (writethrough)
.word 0xffffff00
- b __armv4_cache_on
- b __armv4_cache_off
+ b __armv4_mmu_cache_on
+ b __armv4_mmu_cache_off
mov pc, lr
.word 0x00007000 @ ARM7 IDs
@@ -506,41 +506,41 @@ proc_types:
.word 0x4401a100 @ sa110 / sa1100
.word 0xffffffe0
- b __armv4_cache_on
- b __armv4_cache_off
- b __armv4_cache_flush
+ b __armv4_mmu_cache_on
+ b __armv4_mmu_cache_off
+ b __armv4_mmu_cache_flush
.word 0x6901b110 @ sa1110
.word 0xfffffff0
- b __armv4_cache_on
- b __armv4_cache_off
- b __armv4_cache_flush
+ b __armv4_mmu_cache_on
+ b __armv4_mmu_cache_off
+ b __armv4_mmu_cache_flush
@ These match on the architecture ID
.word 0x00020000 @ ARMv4T
.word 0x000f0000
- b __armv4_cache_on
- b __armv4_cache_off
- b __armv4_cache_flush
+ b __armv4_mmu_cache_on
+ b __armv4_mmu_cache_off
+ b __armv4_mmu_cache_flush
.word 0x00050000 @ ARMv5TE
.word 0x000f0000
- b __armv4_cache_on
- b __armv4_cache_off
- b __armv4_cache_flush
+ b __armv4_mmu_cache_on
+ b __armv4_mmu_cache_off
+ b __armv4_mmu_cache_flush
.word 0x00060000 @ ARMv5TEJ
.word 0x000f0000
- b __armv4_cache_on
- b __armv4_cache_off
- b __armv4_cache_flush
+ b __armv4_mmu_cache_on
+ b __armv4_mmu_cache_off
+ b __armv4_mmu_cache_flush
.word 0x00070000 @ ARMv6
.word 0x000f0000
- b __armv4_cache_on
- b __armv4_cache_off
- b __armv6_cache_flush
+ b __armv4_mmu_cache_on
+ b __armv4_mmu_cache_off
+ b __armv6_mmu_cache_flush
.word 0 @ unrecognised type
.word 0
@@ -562,7 +562,7 @@ proc_types:
cache_off: mov r3, #12 @ cache_off function
b call_cache_fn
-__armv4_cache_off:
+__armv4_mmu_cache_off:
mrc p15, 0, r0, c1, c0
bic r0, r0, #0x000d
mcr p15, 0, r0, c1, c0 @ turn MMU and cache off
@@ -571,15 +571,15 @@ __armv4_cache_off:
mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4
mov pc, lr
-__arm6_cache_off:
+__arm6_mmu_cache_off:
mov r0, #0x00000030 @ ARM6 control reg.
- b __armv3_cache_off
+ b __armv3_mmu_cache_off
-__arm7_cache_off:
+__arm7_mmu_cache_off:
mov r0, #0x00000070 @ ARM7 control reg.
- b __armv3_cache_off
+ b __armv3_mmu_cache_off
-__armv3_cache_off:
+__armv3_mmu_cache_off:
mcr p15, 0, r0, c1, c0, 0 @ turn MMU and cache off
mov r0, #0
mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
@@ -601,7 +601,7 @@ cache_clean_flush:
mov r3, #16
b call_cache_fn
-__armv6_cache_flush:
+__armv6_mmu_cache_flush:
mov r1, #0
mcr p15, 0, r1, c7, c14, 0 @ clean+invalidate D
mcr p15, 0, r1, c7, c5, 0 @ invalidate I+BTB
@@ -609,7 +609,7 @@ __armv6_cache_flush:
mcr p15, 0, r1, c7, c10, 4 @ drain WB
mov pc, lr
-__armv4_cache_flush:
+__armv4_mmu_cache_flush:
mov r2, #64*1024 @ default: 32K dcache size (*2)
mov r11, #32 @ default: 32 byte line size
mrc p15, 0, r3, c0, c0, 1 @ read cache type
@@ -637,7 +637,7 @@ no_cache_id:
mcr p15, 0, r1, c7, c10, 4 @ drain WB
mov pc, lr
-__armv3_cache_flush:
+__armv3_mmu_cache_flush:
mov r1, #0
mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
mov pc, lr
diff --git a/arch/arm/boot/compressed/ice-dcc.S b/arch/arm/boot/compressed/ice-dcc.S
deleted file mode 100644
index 104377a199b..00000000000
--- a/arch/arm/boot/compressed/ice-dcc.S
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- .text
-
- .global icedcc_putc
-
-icedcc_putc:
- mov r2, #0x4000000
-1:
- subs r2, r2, #1
- movlt pc, r14
- mrc p14, 0, r1, c0, c0, 0
- tst r1, #2
- bne 1b
-
- mcr p14, 0, r0, c1, c0, 0
- mov pc, r14
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 5ab94584bae..0af3772efcb 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -20,24 +20,45 @@ unsigned int __machine_arch_type;
#include <linux/string.h>
-#include <asm/arch/uncompress.h>
-
#ifdef STANDALONE_DEBUG
#define putstr printf
-#endif
+#else
+
+static void putstr(const char *ptr);
+
+#include <linux/compiler.h>
+#include <asm/arch/uncompress.h>
#ifdef CONFIG_DEBUG_ICEDCC
-#define putstr icedcc_putstr
-#define putc icedcc_putc
+static void icedcc_putc(int ch)
+{
+ int status, i = 0x4000000;
-extern void icedcc_putc(int ch);
+ do {
+ if (--i < 0)
+ return;
-static void
-icedcc_putstr(const char *ptr)
+ asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
+ } while (status & 2);
+
+ asm("mcr p15, 0, %0, c1, c0, 0" : : "r" (ch));
+}
+
+#define putc(ch) icedcc_putc(ch)
+#define flush() do { } while (0)
+#endif
+
+static void putstr(const char *ptr)
{
- for (; *ptr != '\0'; ptr++) {
- icedcc_putc(*ptr);
+ char c;
+
+ while ((c = *ptr++) != '\0') {
+ if (c == '\n')
+ putc('\r');
+ putc(c);
}
+
+ flush();
}
#endif
diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c
index e851d86c212..35c9a64ac14 100644
--- a/arch/arm/common/rtctime.c
+++ b/arch/arm/common/rtctime.c
@@ -20,6 +20,7 @@
#include <linux/capability.h>
#include <linux/device.h>
#include <linux/mutex.h>
+#include <linux/rtc.h>
#include <asm/rtc.h>
#include <asm/semaphore.h>
@@ -42,89 +43,6 @@ static struct rtc_ops *rtc_ops;
#define rtc_epoch 1900UL
-static const unsigned char days_in_month[] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
-#define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400))
-
-static int month_days(unsigned int month, unsigned int year)
-{
- return days_in_month[month] + (LEAP_YEAR(year) && month == 1);
-}
-
-/*
- * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
- */
-void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
-{
- int days, month, year;
-
- days = time / 86400;
- time -= days * 86400;
-
- tm->tm_wday = (days + 4) % 7;
-
- year = 1970 + days / 365;
- days -= (year - 1970) * 365
- + LEAPS_THRU_END_OF(year - 1)
- - LEAPS_THRU_END_OF(1970 - 1);
- if (days < 0) {
- year -= 1;
- days += 365 + LEAP_YEAR(year);
- }
- tm->tm_year = year - 1900;
- tm->tm_yday = days + 1;
-
- for (month = 0; month < 11; month++) {
- int newdays;
-
- newdays = days - month_days(month, year);
- if (newdays < 0)
- break;
- days = newdays;
- }
- tm->tm_mon = month;
- tm->tm_mday = days + 1;
-
- tm->tm_hour = time / 3600;
- time -= tm->tm_hour * 3600;
- tm->tm_min = time / 60;
- tm->tm_sec = time - tm->tm_min * 60;
-}
-EXPORT_SYMBOL(rtc_time_to_tm);
-
-/*
- * Does the rtc_time represent a valid date/time?
- */
-int rtc_valid_tm(struct rtc_time *tm)
-{
- if (tm->tm_year < 70 ||
- tm->tm_mon >= 12 ||
- tm->tm_mday < 1 ||
- tm->tm_mday > month_days(tm->tm_mon, tm->tm_year + 1900) ||
- tm->tm_hour >= 24 ||
- tm->tm_min >= 60 ||
- tm->tm_sec >= 60)
- return -EINVAL;
-
- return 0;
-}
-EXPORT_SYMBOL(rtc_valid_tm);
-
-/*
- * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
- */
-int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
-{
- *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
-
- return 0;
-}
-EXPORT_SYMBOL(rtc_tm_to_time);
-
/*
* Calculate the next alarm time given the requested alarm time mask
* and the current time.
@@ -151,13 +69,13 @@ void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc
}
}
-static inline int rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm)
+static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm)
{
memset(tm, 0, sizeof(struct rtc_time));
return ops->read_time(tm);
}
-static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm)
+static inline int rtc_arm_set_time(struct rtc_ops *ops, struct rtc_time *tm)
{
int ret;
@@ -168,7 +86,7 @@ static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm)
return ret;
}
-static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
+static inline int rtc_arm_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
{
int ret = -EINVAL;
if (ops->read_alarm) {
@@ -178,7 +96,7 @@ static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
return ret;
}
-static inline int rtc_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
+static inline int rtc_arm_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
{
int ret = -EINVAL;
if (ops->set_alarm)
@@ -266,7 +184,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
switch (cmd) {
case RTC_ALM_READ:
- ret = rtc_read_alarm(ops, &alrm);
+ ret = rtc_arm_read_alarm(ops, &alrm);
if (ret)
break;
ret = copy_to_user(uarg, &alrm.time, sizeof(tm));
@@ -288,11 +206,11 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
alrm.time.tm_wday = -1;
alrm.time.tm_yday = -1;
alrm.time.tm_isdst = -1;
- ret = rtc_set_alarm(ops, &alrm);
+ ret = rtc_arm_set_alarm(ops, &alrm);
break;
case RTC_RD_TIME:
- ret = rtc_read_time(ops, &tm);
+ ret = rtc_arm_read_time(ops, &tm);
if (ret)
break;
ret = copy_to_user(uarg, &tm, sizeof(tm));
@@ -310,7 +228,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
ret = -EFAULT;
break;
}
- ret = rtc_set_time(ops, &tm);
+ ret = rtc_arm_set_time(ops, &tm);
break;
case RTC_EPOCH_SET:
@@ -341,11 +259,11 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
ret = -EFAULT;
break;
}
- ret = rtc_set_alarm(ops, &alrm);
+ ret = rtc_arm_set_alarm(ops, &alrm);
break;
case RTC_WKALM_RD:
- ret = rtc_read_alarm(ops, &alrm);
+ ret = rtc_arm_read_alarm(ops, &alrm);
if (ret)
break;
ret = copy_to_user(uarg, &alrm, sizeof(alrm));
@@ -435,7 +353,7 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo
struct rtc_time tm;
char *p = page;
- if (rtc_read_time(ops, &tm) == 0) {
+ if (rtc_arm_read_time(ops, &tm) == 0) {
p += sprintf(p,
"rtc_time\t: %02d:%02d:%02d\n"
"rtc_date\t: %04d-%02d-%02d\n"
@@ -445,7 +363,7 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo
rtc_epoch);
}
- if (rtc_read_alarm(ops, &alrm) == 0) {
+ if (rtc_arm_read_alarm(ops, &alrm) == 0) {
p += sprintf(p, "alrm_time\t: ");
if ((unsigned int)alrm.time.tm_hour <= 24)
p += sprintf(p, "%02d:", alrm.time.tm_hour);
diff --git a/arch/arm/configs/ixp23xx_defconfig b/arch/arm/configs/ixp23xx_defconfig
new file mode 100644
index 00000000000..1a2751e9ab0
--- /dev/null
+++ b/arch/arm/configs/ixp23xx_defconfig
@@ -0,0 +1,1302 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16
+# Tue Mar 21 03:27:20 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+CONFIG_ARCH_IXP23XX=y
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+
+#
+# Intel IXP23xx Implementation Options
+#
+
+#
+# IXP23xx Platforms
+#
+CONFIG_MACH_ESPRESSO=y
+CONFIG_MACH_IXDP2351=y
+CONFIG_MACH_ROADRUNNER=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSC3=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_IO_36=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BIG_ENDIAN=y
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+CONFIG_WAN=y
+# CONFIG_DSCC4 is not set
+# CONFIG_LANMEDIA is not set
+# CONFIG_SYNCLINK_SYNCPPP is not set
+CONFIG_HDLC=y
+CONFIG_HDLC_RAW=y
+# CONFIG_HDLC_RAW_ETH is not set
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300 is not set
+# CONFIG_FARSYNC is not set
+CONFIG_DLCI=y
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_VFAT_FS is not set
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 55c99cdab7d..f1c2fd5b63e 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -37,24 +37,6 @@
#endif
.endm
-#if __LINUX_ARM_ARCH__ >= 6
- .macro disable_irq
- cpsid i
- .endm
-
- .macro enable_irq
- cpsie i
- .endm
-#else
- .macro disable_irq
- msr cpsr_c, #PSR_I_BIT | SVC_MODE
- .endm
-
- .macro enable_irq
- msr cpsr_c, #SVC_MODE
- .endm
-#endif
-
.macro get_thread_info, rd
mov \rd, sp, lsr #13
mov \rd, \rd, lsl #13
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 84277fe818a..53b6901f70a 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -81,6 +81,7 @@
ENTRY(stext)
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ ensure svc mode
@ and irqs disabled
+ mrc p15, 0, r9, c0, c0 @ get processor id
bl __lookup_processor_type @ r5=procinfo r9=cpuid
movs r10, r5 @ invalid processor (r5=0)?
beq __error_p @ yes, error 'p'
@@ -155,6 +156,7 @@ ENTRY(secondary_startup)
* as it has already been validated by the primary processor.
*/
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC
+ mrc p15, 0, r9, c0, c0 @ get processor id
bl __lookup_processor_type
movs r10, r5 @ invalid processor?
moveq r0, #'p' @ yes, error 'p'
@@ -449,19 +451,19 @@ __error:
* (and therefore, we are not in the correct address space). We have to
* calculate the offset.
*
+ * r9 = cpuid
* Returns:
* r3, r4, r6 corrupted
* r5 = proc_info pointer in physical address space
- * r9 = cpuid
+ * r9 = cpuid (preserved)
*/
.type __lookup_processor_type, %function
__lookup_processor_type:
adr r3, 3f
- ldmda r3, {r5, r6, r9}
- sub r3, r3, r9 @ get offset between virt&phys
+ ldmda r3, {r5 - r7}
+ sub r3, r3, r7 @ get offset between virt&phys
add r5, r5, r3 @ convert virt addresses to
add r6, r6, r3 @ physical address space
- mrc p15, 0, r9, c0, c0 @ get processor id
1: ldmia r5, {r3, r4} @ value, mask
and r4, r4, r9 @ mask wanted bits
teq r3, r4
@@ -476,10 +478,11 @@ __lookup_processor_type:
* This provides a C-API version of the above function.
*/
ENTRY(lookup_processor_type)
- stmfd sp!, {r4 - r6, r9, lr}
+ stmfd sp!, {r4 - r7, r9, lr}
+ mov r9, r0
bl __lookup_processor_type
mov r0, r5
- ldmfd sp!, {r4 - r6, r9, pc}
+ ldmfd sp!, {r4 - r7, r9, pc}
/*
* Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 08974cbe982..b7cd280bfd6 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -278,7 +278,7 @@ int cpu_architecture(void)
* These functions re-use the assembly code in head.S, which
* already provide the required functionality.
*/
-extern struct proc_info_list *lookup_processor_type(void);
+extern struct proc_info_list *lookup_processor_type(unsigned int);
extern struct machine_desc *lookup_machine_type(unsigned int);
static void __init setup_processor(void)
@@ -290,7 +290,7 @@ static void __init setup_processor(void)
* types. The linker builds this table for us from the
* entries in arch/arm/mm/proc-*.S
*/
- list = lookup_processor_type();
+ list = lookup_processor_type(processor_id);
if (!list) {
printk("CPU configuration botched (ID %08x), unable "
"to continue.\n", processor_id);
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 02aa300c463..1370d726dc1 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -337,9 +337,6 @@ void __init smp_prepare_boot_cpu(void)
unsigned int cpu = smp_processor_id();
per_cpu(cpu_data, cpu).idle = current;
-
- cpu_set(cpu, cpu_present_map);
- cpu_set(cpu, cpu_online_map);
}
static void send_ipi_message(cpumask_t callmap, enum ipi_msg_type msg)
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index a491de2d902..8170af47143 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -234,7 +234,12 @@ asmlinkage int sys_ipc(uint call, int first, int second, int third,
*/
asmlinkage int sys_fork(struct pt_regs *regs)
{
+#ifdef CONFIG_MMU
return do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
+#else
+ /* can not support in nommu mode */
+ return(-EINVAL);
+#endif
}
/* Clone a task - this clones the calling program thread.
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 03924bcc612..d566d5f4574 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -506,7 +506,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
if (!pmd_present(*pmd))
goto bad_access;
pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
- if (!pte_present(*pte) || !pte_write(*pte)) {
+ if (!pte_present(*pte) || !pte_dirty(*pte)) {
pte_unmap_unlock(pte, ptl);
goto bad_access;
}
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 391f3ab3ff3..7b726b627ea 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -18,7 +18,7 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
# the code in uaccess.S is not preemption safe and
# probably faster on ARMv3 only
-ifeq ($CONFIG_PREEMPT,y)
+ifeq ($(CONFIG_PREEMPT),y)
lib-y += copy_from_user.o copy_to_user.o
else
ifneq ($(CONFIG_CPU_32v3),y)
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index 68a21c0f3f5..3bdc8c6949c 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -29,7 +29,7 @@ ENTRY(__backtrace)
ENTRY(c_backtrace)
-#ifndef CONFIG_FRAME_POINTER
+#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
mov pc, lr
#else
diff --git a/arch/arm/lib/copy_template.S b/arch/arm/lib/copy_template.S
index 838e435e492..cab355c0c1f 100644
--- a/arch/arm/lib/copy_template.S
+++ b/arch/arm/lib/copy_template.S
@@ -236,7 +236,7 @@
/*
- * Abort preanble and completion macros.
+ * Abort preamble and completion macros.
* If a fixup handler is required then those macros must surround it.
* It is assumed that the fixup code will handle the private part of
* the exit macro.
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 865427bfad7..2d892e4daa0 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -30,7 +30,9 @@
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/delay.h>
+#include <linux/termios.h>
#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
#include <asm/types.h>
#include <asm/setup.h>
@@ -360,6 +362,68 @@ void __init ep93xx_init_irq(void)
/*************************************************************************
* EP93xx peripheral handling
*************************************************************************/
+#define EP93XX_UART_MCR_OFFSET (0x0100)
+
+static void ep93xx_uart_set_mctrl(struct amba_device *dev,
+ void __iomem *base, unsigned int mctrl)
+{
+ unsigned int mcr;
+
+ mcr = 0;
+ if (!(mctrl & TIOCM_RTS))
+ mcr |= 2;
+ if (!(mctrl & TIOCM_DTR))
+ mcr |= 1;
+
+ __raw_writel(mcr, base + EP93XX_UART_MCR_OFFSET);
+}
+
+static struct amba_pl010_data ep93xx_uart_data = {
+ .set_mctrl = ep93xx_uart_set_mctrl,
+};
+
+static struct amba_device uart1_device = {
+ .dev = {
+ .bus_id = "apb:uart1",
+ .platform_data = &ep93xx_uart_data,
+ },
+ .res = {
+ .start = EP93XX_UART1_PHYS_BASE,
+ .end = EP93XX_UART1_PHYS_BASE + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_EP93XX_UART1, NO_IRQ },
+ .periphid = 0x00041010,
+};
+
+static struct amba_device uart2_device = {
+ .dev = {
+ .bus_id = "apb:uart2",
+ .platform_data = &ep93xx_uart_data,
+ },
+ .res = {
+ .start = EP93XX_UART2_PHYS_BASE,
+ .end = EP93XX_UART2_PHYS_BASE + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_EP93XX_UART2, NO_IRQ },
+ .periphid = 0x00041010,
+};
+
+static struct amba_device uart3_device = {
+ .dev = {
+ .bus_id = "apb:uart3",
+ .platform_data = &ep93xx_uart_data,
+ },
+ .res = {
+ .start = EP93XX_UART3_PHYS_BASE,
+ .end = EP93XX_UART3_PHYS_BASE + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = { IRQ_EP93XX_UART3, NO_IRQ },
+ .periphid = 0x00041010,
+};
+
void __init ep93xx_init_devices(void)
{
unsigned int v;
@@ -371,4 +435,8 @@ void __init ep93xx_init_devices(void)
v &= ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE;
__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
__raw_writel(v, EP93XX_SYSCON_DEVICE_CONFIG);
+
+ amba_device_register(&uart1_device, &iomem_resource);
+ amba_device_register(&uart2_device, &iomem_resource);
+ amba_device_register(&uart3_device, &iomem_resource);
}
diff --git a/arch/arm/mach-footbridge/time.c b/arch/arm/mach-footbridge/time.c
index 2c64a0b0502..5d02e95dede 100644
--- a/arch/arm/mach-footbridge/time.c
+++ b/arch/arm/mach-footbridge/time.c
@@ -34,27 +34,12 @@ static int rtc_base;
static unsigned long __init get_isa_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- int i;
// check to see if the RTC makes sense.....
if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)
return mktime(1970, 1, 1, 0, 0, 0);
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
-
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
-
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
+ do {
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
hour = CMOS_READ(RTC_HOURS);
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index 20071a2767c..576a5e979c0 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -15,7 +15,9 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/smp.h>
+#include <linux/termios.h>
#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
#include <asm/hardware.h>
#include <asm/irq.h>
@@ -28,6 +30,8 @@
#include "common.h"
+static struct amba_pl010_data integrator_uart_data;
+
static struct amba_device rtc_device = {
.dev = {
.bus_id = "mb:15",
@@ -44,6 +48,7 @@ static struct amba_device rtc_device = {
static struct amba_device uart0_device = {
.dev = {
.bus_id = "mb:16",
+ .platform_data = &integrator_uart_data,
},
.res = {
.start = INTEGRATOR_UART0_BASE,
@@ -57,6 +62,7 @@ static struct amba_device uart0_device = {
static struct amba_device uart1_device = {
.dev = {
.bus_id = "mb:17",
+ .platform_data = &integrator_uart_data,
},
.res = {
.start = INTEGRATOR_UART1_BASE,
@@ -115,6 +121,46 @@ static int __init integrator_init(void)
arch_initcall(integrator_init);
+/*
+ * On the Integrator platform, the port RTS and DTR are provided by
+ * bits in the following SC_CTRLS register bits:
+ * RTS DTR
+ * UART0 7 6
+ * UART1 5 4
+ */
+#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
+#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
+
+static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl)
+{
+ unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
+
+ if (dev == &uart0_device) {
+ rts_mask = 1 << 4;
+ dtr_mask = 1 << 5;
+ } else {
+ rts_mask = 1 << 6;
+ dtr_mask = 1 << 7;
+ }
+
+ if (mctrl & TIOCM_RTS)
+ ctrlc |= rts_mask;
+ else
+ ctrls |= rts_mask;
+
+ if (mctrl & TIOCM_DTR)
+ ctrlc |= dtr_mask;
+ else
+ ctrls |= dtr_mask;
+
+ __raw_writel(ctrls, SC_CTRLS);
+ __raw_writel(ctrlc, SC_CTRLC);
+}
+
+static struct amba_pl010_data integrator_uart_data = {
+ .set_mctrl = integrator_uart_set_mctrl,
+};
+
#define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_BASE) + INTEGRATOR_HDR_CTRL_OFFSET
static DEFINE_SPINLOCK(cm_lock);
diff --git a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c
index 3c22c16b38b..bc07f52a6fd 100644
--- a/arch/arm/mach-integrator/time.c
+++ b/arch/arm/mach-integrator/time.c
@@ -40,13 +40,13 @@ static int integrator_set_rtc(void)
return 1;
}
-static int rtc_read_alarm(struct rtc_wkalrm *alrm)
+static int integrator_rtc_read_alarm(struct rtc_wkalrm *alrm)
{
rtc_time_to_tm(readl(rtc_base + RTC_MR), &alrm->time);
return 0;
}
-static inline int rtc_set_alarm(struct rtc_wkalrm *alrm)
+static inline int integrator_rtc_set_alarm(struct rtc_wkalrm *alrm)
{
unsigned long time;
int ret;
@@ -62,7 +62,7 @@ static inline int rtc_set_alarm(struct rtc_wkalrm *alrm)
return ret;
}
-static int rtc_read_time(struct rtc_time *tm)
+static int integrator_rtc_read_time(struct rtc_time *tm)
{
rtc_time_to_tm(readl(rtc_base + RTC_DR), tm);
return 0;
@@ -76,7 +76,7 @@ static int rtc_read_time(struct rtc_time *tm)
* edge of the 1Hz clock, we must write the time one second
* in advance.
*/
-static inline int rtc_set_time(struct rtc_time *tm)
+static inline int integrator_rtc_set_time(struct rtc_time *tm)
{
unsigned long time;
int ret;
@@ -90,10 +90,10 @@ static inline int rtc_set_time(struct rtc_time *tm)
static struct rtc_ops rtc_ops = {
.owner = THIS_MODULE,
- .read_time = rtc_read_time,
- .set_time = rtc_set_time,
- .read_alarm = rtc_read_alarm,
- .set_alarm = rtc_set_alarm,
+ .read_time = integrator_rtc_read_time,
+ .set_time = integrator_rtc_set_time,
+ .read_alarm = integrator_rtc_read_alarm,
+ .set_alarm = integrator_rtc_set_alarm,
};
static irqreturn_t arm_rtc_interrupt(int irq, void *dev_id,
diff --git a/arch/arm/mach-iop3xx/iop331-setup.c b/arch/arm/mach-iop3xx/iop331-setup.c
index 2d6abe5be14..7b7b6eea384 100644
--- a/arch/arm/mach-iop3xx/iop331-setup.c
+++ b/arch/arm/mach-iop3xx/iop331-setup.c
@@ -103,7 +103,7 @@ static struct plat_serial8250_port iop33x_uart1_data[] = {
static struct platform_device iop33x_uart0 = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev.platform_data = iop33x_uart0_data,
.num_resources = 2,
.resource = iop33x_uart0_resources,
@@ -111,7 +111,7 @@ static struct platform_device iop33x_uart0 = {
static struct platform_device iop33x_uart1 = {
.name = "serial8250",
- .id = 1,
+ .id = PLAT8250_DEV_PLATFORM1,
.dev.platform_data = iop33x_uart1_data,
.num_resources = 2,
.resource = iop33x_uart1_resources,
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
index f9d4968c1d6..66915282a46 100644
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -30,6 +30,7 @@
#include <linux/tty.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -132,7 +133,7 @@ void __init ixdp2x01_init_irq(void)
/*************************************************************************
- * IXDP2x01 memory map and serial ports
+ * IXDP2x01 memory map
*************************************************************************/
static struct map_desc ixdp2x01_io_desc __initdata = {
.virtual = IXDP2X01_VIRT_CPLD_BASE,
@@ -141,40 +142,78 @@ static struct map_desc ixdp2x01_io_desc __initdata = {
.type = MT_DEVICE
};
-static struct uart_port ixdp2x01_serial_ports[2] = {
+static void __init ixdp2x01_map_io(void)
+{
+ ixp2000_map_io();
+ iotable_init(&ixdp2x01_io_desc, 1);
+}
+
+
+/*************************************************************************
+ * IXDP2x01 serial ports
+ *************************************************************************/
+static struct plat_serial8250_port ixdp2x01_serial_port1[] = {
{
- .membase = (char *)(IXDP2X01_UART1_VIRT_BASE),
.mapbase = (unsigned long)IXDP2X01_UART1_PHYS_BASE,
+ .membase = (char *)IXDP2X01_UART1_VIRT_BASE,
.irq = IRQ_IXDP2X01_UART1,
- .flags = UPF_SKIP_TEST,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
.iotype = UPIO_MEM32,
.regshift = 2,
.uartclk = IXDP2X01_UART_CLK,
- .line = 1,
- .type = PORT_16550A,
- .fifosize = 16
- }, {
- .membase = (char *)(IXDP2X01_UART2_VIRT_BASE),
+ },
+ { }
+};
+
+static struct resource ixdp2x01_uart_resource1 = {
+ .start = IXDP2X01_UART1_PHYS_BASE,
+ .end = IXDP2X01_UART1_PHYS_BASE + 0xffff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp2x01_serial_device1 = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM1,
+ .dev = {
+ .platform_data = ixdp2x01_serial_port1,
+ },
+ .num_resources = 1,
+ .resource = &ixdp2x01_uart_resource1,
+};
+
+static struct plat_serial8250_port ixdp2x01_serial_port2[] = {
+ {
.mapbase = (unsigned long)IXDP2X01_UART2_PHYS_BASE,
+ .membase = (char *)IXDP2X01_UART2_VIRT_BASE,
.irq = IRQ_IXDP2X01_UART2,
- .flags = UPF_SKIP_TEST,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
.iotype = UPIO_MEM32,
.regshift = 2,
.uartclk = IXDP2X01_UART_CLK,
- .line = 2,
- .type = PORT_16550A,
- .fifosize = 16
},
+ { }
};
-static void __init ixdp2x01_map_io(void)
-{
- ixp2000_map_io();
+static struct resource ixdp2x01_uart_resource2 = {
+ .start = IXDP2X01_UART2_PHYS_BASE,
+ .end = IXDP2X01_UART2_PHYS_BASE + 0xffff,
+ .flags = IORESOURCE_MEM,
+};
- iotable_init(&ixdp2x01_io_desc, 1);
+static struct platform_device ixdp2x01_serial_device2 = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM2,
+ .dev = {
+ .platform_data = ixdp2x01_serial_port2,
+ },
+ .num_resources = 1,
+ .resource = &ixdp2x01_uart_resource2,
+};
- early_serial_setup(&ixdp2x01_serial_ports[0]);
- early_serial_setup(&ixdp2x01_serial_ports[1]);
+static void ixdp2x01_uart_init(void)
+{
+ platform_device_register(&ixdp2x01_serial_device1);
+ platform_device_register(&ixdp2x01_serial_device2);
}
@@ -374,6 +413,7 @@ static void __init ixdp2x01_init_machine(void)
platform_add_devices(ixdp2x01_devices, ARRAY_SIZE(ixdp2x01_devices));
ixp2000_uart_init();
+ ixdp2x01_uart_init();
}
diff --git a/arch/arm/mach-ixp23xx/Kconfig b/arch/arm/mach-ixp23xx/Kconfig
new file mode 100644
index 00000000000..982670ec386
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/Kconfig
@@ -0,0 +1,25 @@
+if ARCH_IXP23XX
+
+config ARCH_SUPPORTS_BIG_ENDIAN
+ bool
+ default y
+
+menu "Intel IXP23xx Implementation Options"
+
+comment "IXP23xx Platforms"
+
+config MACH_ESPRESSO
+ bool "Support IP Fabrics Double Espresso platform"
+ help
+
+config MACH_IXDP2351
+ bool "Support Intel IXDP2351 platform"
+ help
+
+config MACH_ROADRUNNER
+ bool "Support ADI RoadRunner platform"
+ help
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-ixp23xx/Makefile b/arch/arm/mach-ixp23xx/Makefile
new file mode 100644
index 00000000000..288b371b6d0
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the linux kernel.
+#
+obj-y := core.o pci.o
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-$(CONFIG_MACH_ESPRESSO) += espresso.o
+obj-$(CONFIG_MACH_IXDP2351) += ixdp2351.o
+obj-$(CONFIG_MACH_ROADRUNNER) += roadrunner.o
diff --git a/arch/arm/mach-ixp23xx/Makefile.boot b/arch/arm/mach-ixp23xx/Makefile.boot
new file mode 100644
index 00000000000..d5561ad15ba
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/Makefile.boot
@@ -0,0 +1,2 @@
+ zreladdr-y := 0x00008000
+params_phys-y := 0x00000100
diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c
new file mode 100644
index 00000000000..092ee12ced4
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/core.c
@@ -0,0 +1,431 @@
+/*
+ * arch/arm/mach-ixp23xx/core.c
+ *
+ * Core routines for IXP23xx chips
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * Based on 2.4 code Copyright 2004 (c) Intel Corporation
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/bitops.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/arch.h>
+
+
+/*************************************************************************
+ * Chip specific mappings shared by all IXP23xx systems
+ *************************************************************************/
+static struct map_desc ixp23xx_io_desc[] __initdata = {
+ { /* XSI-CPP CSRs */
+ .virtual = IXP23XX_XSI2CPP_CSR_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_XSI2CPP_CSR_PHYS),
+ .length = IXP23XX_XSI2CPP_CSR_SIZE,
+ .type = MT_DEVICE,
+ }, { /* Expansion Bus Config */
+ .virtual = IXP23XX_EXP_CFG_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_EXP_CFG_PHYS),
+ .length = IXP23XX_EXP_CFG_SIZE,
+ .type = MT_DEVICE,
+ }, { /* UART, Interrupt ctrl, GPIO, timers, NPEs, MACS,.... */
+ .virtual = IXP23XX_PERIPHERAL_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_PERIPHERAL_PHYS),
+ .length = IXP23XX_PERIPHERAL_SIZE,
+ .type = MT_DEVICE,
+ }, { /* CAP CSRs */
+ .virtual = IXP23XX_CAP_CSR_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_CAP_CSR_PHYS),
+ .length = IXP23XX_CAP_CSR_SIZE,
+ .type = MT_DEVICE,
+ }, { /* MSF CSRs */
+ .virtual = IXP23XX_MSF_CSR_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_MSF_CSR_PHYS),
+ .length = IXP23XX_MSF_CSR_SIZE,
+ .type = MT_DEVICE,
+ }, { /* PCI I/O Space */
+ .virtual = IXP23XX_PCI_IO_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_PCI_IO_PHYS),
+ .length = IXP23XX_PCI_IO_SIZE,
+ .type = MT_DEVICE,
+ }, { /* PCI Config Space */
+ .virtual = IXP23XX_PCI_CFG_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_PCI_CFG_PHYS),
+ .length = IXP23XX_PCI_CFG_SIZE,
+ .type = MT_DEVICE,
+ }, { /* PCI local CFG CSRs */
+ .virtual = IXP23XX_PCI_CREG_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_PCI_CREG_PHYS),
+ .length = IXP23XX_PCI_CREG_SIZE,
+ .type = MT_DEVICE,
+ }, { /* PCI MEM Space */
+ .virtual = IXP23XX_PCI_MEM_VIRT,
+ .pfn = __phys_to_pfn(IXP23XX_PCI_MEM_PHYS),
+ .length = IXP23XX_PCI_MEM_SIZE,
+ .type = MT_DEVICE,
+ }
+};
+
+void __init ixp23xx_map_io(void)
+{
+ iotable_init(ixp23xx_io_desc, ARRAY_SIZE(ixp23xx_io_desc));
+}
+
+
+/***************************************************************************
+ * IXP23xx Interrupt Handling
+ ***************************************************************************/
+enum ixp23xx_irq_type {
+ IXP23XX_IRQ_LEVEL, IXP23XX_IRQ_EDGE
+};
+
+static void ixp23xx_config_irq(unsigned int, enum ixp23xx_irq_type);
+
+static int ixp23xx_irq_set_type(unsigned int irq, unsigned int type)
+{
+ int line = irq - IRQ_IXP23XX_GPIO6 + 6;
+ u32 int_style;
+ enum ixp23xx_irq_type irq_type;
+ volatile u32 *int_reg;
+
+ /*
+ * Only GPIOs 6-15 are wired to interrupts on IXP23xx
+ */
+ if (line < 6 || line > 15)
+ return -EINVAL;
+
+ switch (type) {
+ case IRQT_BOTHEDGE:
+ int_style = IXP23XX_GPIO_STYLE_TRANSITIONAL;
+ irq_type = IXP23XX_IRQ_EDGE;
+ break;
+ case IRQT_RISING:
+ int_style = IXP23XX_GPIO_STYLE_RISING_EDGE;
+ irq_type = IXP23XX_IRQ_EDGE;
+ break;
+ case IRQT_FALLING:
+ int_style = IXP23XX_GPIO_STYLE_FALLING_EDGE;
+ irq_type = IXP23XX_IRQ_EDGE;
+ break;
+ case IRQT_HIGH:
+ int_style = IXP23XX_GPIO_STYLE_ACTIVE_HIGH;
+ irq_type = IXP23XX_IRQ_LEVEL;
+ break;
+ case IRQT_LOW:
+ int_style = IXP23XX_GPIO_STYLE_ACTIVE_LOW;
+ irq_type = IXP23XX_IRQ_LEVEL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ixp23xx_config_irq(irq, irq_type);
+
+ if (line >= 8) { /* pins 8-15 */
+ line -= 8;
+ int_reg = (volatile u32 *)IXP23XX_GPIO_GPIT2R;
+ } else { /* pins 0-7 */
+ int_reg = (volatile u32 *)IXP23XX_GPIO_GPIT1R;
+ }
+
+ /*
+ * Clear pending interrupts
+ */
+ *IXP23XX_GPIO_GPISR = (1 << line);
+
+ /* Clear the style for the appropriate pin */
+ *int_reg &= ~(IXP23XX_GPIO_STYLE_MASK <<
+ (line * IXP23XX_GPIO_STYLE_SIZE));
+
+ /* Set the new style */
+ *int_reg |= (int_style << (line * IXP23XX_GPIO_STYLE_SIZE));
+
+ return 0;
+}
+
+static void ixp23xx_irq_mask(unsigned int irq)
+{
+ volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
+
+ *intr_reg &= ~(1 << (irq % 32));
+}
+
+static void ixp23xx_irq_ack(unsigned int irq)
+{
+ int line = irq - IRQ_IXP23XX_GPIO6 + 6;
+
+ if ((line < 6) || (line > 15))
+ return;
+
+ *IXP23XX_GPIO_GPISR = (1 << line);
+}
+
+/*
+ * Level triggered interrupts on GPIO lines can only be cleared when the
+ * interrupt condition disappears.
+ */
+static void ixp23xx_irq_level_unmask(unsigned int irq)
+{
+ volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
+
+ ixp23xx_irq_ack(irq);
+
+ *intr_reg |= (1 << (irq % 32));
+}
+
+static void ixp23xx_irq_edge_unmask(unsigned int irq)
+{
+ volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
+
+ *intr_reg |= (1 << (irq % 32));
+}
+
+static struct irqchip ixp23xx_irq_level_chip = {
+ .ack = ixp23xx_irq_mask,
+ .mask = ixp23xx_irq_mask,
+ .unmask = ixp23xx_irq_level_unmask,
+ .set_type = ixp23xx_irq_set_type
+};
+
+static struct irqchip ixp23xx_irq_edge_chip = {
+ .ack = ixp23xx_irq_ack,
+ .mask = ixp23xx_irq_mask,
+ .unmask = ixp23xx_irq_edge_unmask,
+ .set_type = ixp23xx_irq_set_type
+};
+
+static void ixp23xx_pci_irq_mask(unsigned int irq)
+{
+ *IXP23XX_PCI_XSCALE_INT_ENABLE &= ~(1 << (IRQ_IXP23XX_INTA + 27 - irq));
+}
+
+static void ixp23xx_pci_irq_unmask(unsigned int irq)
+{
+ *IXP23XX_PCI_XSCALE_INT_ENABLE |= (1 << (IRQ_IXP23XX_INTA + 27 - irq));
+}
+
+/*
+ * TODO: Should this just be done at ASM level?
+ */
+static void pci_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+ u32 pci_interrupt;
+ unsigned int irqno;
+ struct irqdesc *int_desc;
+
+ pci_interrupt = *IXP23XX_PCI_XSCALE_INT_STATUS;
+
+ desc->chip->ack(irq);
+
+ /* See which PCI_INTA, or PCI_INTB interrupted */
+ if (pci_interrupt & (1 << 26)) {
+ irqno = IRQ_IXP23XX_INTB;
+ } else if (pci_interrupt & (1 << 27)) {
+ irqno = IRQ_IXP23XX_INTA;
+ } else {
+ BUG();
+ }
+
+ int_desc = irq_desc + irqno;
+ int_desc->handle(irqno, int_desc, regs);
+
+ desc->chip->unmask(irq);
+}
+
+static struct irqchip ixp23xx_pci_irq_chip = {
+ .ack = ixp23xx_pci_irq_mask,
+ .mask = ixp23xx_pci_irq_mask,
+ .unmask = ixp23xx_pci_irq_unmask
+};
+
+static void ixp23xx_config_irq(unsigned int irq, enum ixp23xx_irq_type type)
+{
+ switch (type) {
+ case IXP23XX_IRQ_LEVEL:
+ set_irq_chip(irq, &ixp23xx_irq_level_chip);
+ set_irq_handler(irq, do_level_IRQ);
+ break;
+ case IXP23XX_IRQ_EDGE:
+ set_irq_chip(irq, &ixp23xx_irq_edge_chip);
+ set_irq_handler(irq, do_edge_IRQ);
+ break;
+ }
+ set_irq_flags(irq, IRQF_VALID);
+}
+
+void __init ixp23xx_init_irq(void)
+{
+ int irq;
+
+ /* Route everything to IRQ */
+ *IXP23XX_INTR_SEL1 = 0x0;
+ *IXP23XX_INTR_SEL2 = 0x0;
+ *IXP23XX_INTR_SEL3 = 0x0;
+ *IXP23XX_INTR_SEL4 = 0x0;
+
+ /* Mask all sources */
+ *IXP23XX_INTR_EN1 = 0x0;
+ *IXP23XX_INTR_EN2 = 0x0;
+ *IXP23XX_INTR_EN3 = 0x0;
+ *IXP23XX_INTR_EN4 = 0x0;
+
+ /*
+ * Configure all IRQs for level-sensitive operation
+ */
+ for (irq = 0; irq <= NUM_IXP23XX_RAW_IRQS; irq++) {
+ ixp23xx_config_irq(irq, IXP23XX_IRQ_LEVEL);
+ }
+
+ for (irq = IRQ_IXP23XX_INTA; irq <= IRQ_IXP23XX_INTB; irq++) {
+ set_irq_chip(irq, &ixp23xx_pci_irq_chip);
+ set_irq_handler(irq, do_level_IRQ);
+ set_irq_flags(irq, IRQF_VALID);
+ }
+
+ set_irq_chained_handler(IRQ_IXP23XX_PCI_INT_RPH, pci_handler);
+}
+
+
+/*************************************************************************
+ * Timer-tick functions for IXP23xx
+ *************************************************************************/
+#define CLOCK_TICKS_PER_USEC CLOCK_TICK_RATE / (USEC_PER_SEC)
+
+static unsigned long next_jiffy_time;
+
+static unsigned long
+ixp23xx_gettimeoffset(void)
+{
+ unsigned long elapsed;
+
+ elapsed = *IXP23XX_TIMER_CONT - (next_jiffy_time - LATCH);
+
+ return elapsed / CLOCK_TICKS_PER_USEC;
+}
+
+static irqreturn_t
+ixp23xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ /* Clear Pending Interrupt by writing '1' to it */
+ *IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND;
+ while ((*IXP23XX_TIMER_CONT - next_jiffy_time) > LATCH) {
+ timer_tick(regs);
+ next_jiffy_time += LATCH;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction ixp23xx_timer_irq = {
+ .name = "IXP23xx Timer Tick",
+ .handler = ixp23xx_timer_interrupt,
+ .flags = SA_INTERRUPT | SA_TIMER,
+};
+
+void __init ixp23xx_init_timer(void)
+{
+ /* Clear Pending Interrupt by writing '1' to it */
+ *IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND;
+
+ /* Setup the Timer counter value */
+ *IXP23XX_TIMER1_RELOAD =
+ (LATCH & ~IXP23XX_TIMER_RELOAD_MASK) | IXP23XX_TIMER_ENABLE;
+
+ *IXP23XX_TIMER_CONT = 0;
+ next_jiffy_time = LATCH;
+
+ /* Connect the interrupt handler and enable the interrupt */
+ setup_irq(IRQ_IXP23XX_TIMER1, &ixp23xx_timer_irq);
+}
+
+struct sys_timer ixp23xx_timer = {
+ .init = ixp23xx_init_timer,
+ .offset = ixp23xx_gettimeoffset,
+};
+
+
+/*************************************************************************
+ * IXP23xx Platform Initializaion
+ *************************************************************************/
+static struct resource ixp23xx_uart_resources[] = {
+ {
+ .start = IXP23XX_UART1_PHYS,
+ .end = IXP23XX_UART1_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM
+ }, {
+ .start = IXP23XX_UART2_PHYS,
+ .end = IXP23XX_UART2_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM
+ }
+};
+
+static struct plat_serial8250_port ixp23xx_uart_data[] = {
+ {
+ .mapbase = IXP23XX_UART1_PHYS,
+ .membase = (char *)(IXP23XX_UART1_VIRT + 3),
+ .irq = IRQ_IXP23XX_UART1,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP23XX_UART_XTAL,
+ }, {
+ .mapbase = IXP23XX_UART2_PHYS,
+ .membase = (char *)(IXP23XX_UART2_VIRT + 3),
+ .irq = IRQ_IXP23XX_UART2,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP23XX_UART_XTAL,
+ },
+ { },
+};
+
+static struct platform_device ixp23xx_uart = {
+ .name = "serial8250",
+ .id = 0,
+ .dev.platform_data = ixp23xx_uart_data,
+ .num_resources = 2,
+ .resource = ixp23xx_uart_resources,
+};
+
+static struct platform_device *ixp23xx_devices[] __initdata = {
+ &ixp23xx_uart,
+};
+
+void __init ixp23xx_sys_init(void)
+{
+ platform_add_devices(ixp23xx_devices, ARRAY_SIZE(ixp23xx_devices));
+}
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c
new file mode 100644
index 00000000000..2327c979041
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/espresso.c
@@ -0,0 +1,69 @@
+/*
+ * arch/arm/mach-ixp23xx/espresso.c
+ *
+ * Double Espresso-specific routines
+ *
+ * Author: Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/bitops.h>
+#include <linux/ioport.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/pci.h>
+
+static void __init espresso_init(void)
+{
+ physmap_configure(0x90000000, 0x02000000, 2, NULL);
+
+ /*
+ * Mark flash as writeable.
+ */
+ IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE;
+
+ ixp23xx_sys_init();
+}
+
+MACHINE_START(ESPRESSO, "IP Fabrics Double Espresso")
+ /* Maintainer: Lennert Buytenhek */
+ .phys_io = IXP23XX_PERIPHERAL_PHYS,
+ .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
+ .map_io = ixp23xx_map_io,
+ .init_irq = ixp23xx_init_irq,
+ .timer = &ixp23xx_timer,
+ .boot_params = 0x00000100,
+ .init_machine = espresso_init,
+MACHINE_END
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c
new file mode 100644
index 00000000000..00146c35daa
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/ixdp2351.c
@@ -0,0 +1,325 @@
+/*
+ * arch/arm/mach-ixp23xx/ixdp2351.c
+ *
+ * IXDP2351 board-specific routines
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * Based on 2.4 code Copyright 2004 (c) Intel Corporation
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/bitops.h>
+#include <linux/ioport.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/pci.h>
+
+/*
+ * IXDP2351 Interrupt Handling
+ */
+static void ixdp2351_inta_mask(unsigned int irq)
+{
+ *IXDP2351_CPLD_INTA_MASK_SET_REG = IXDP2351_INTA_IRQ_MASK(irq);
+}
+
+static void ixdp2351_inta_unmask(unsigned int irq)
+{
+ *IXDP2351_CPLD_INTA_MASK_CLR_REG = IXDP2351_INTA_IRQ_MASK(irq);
+}
+
+static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+ u16 ex_interrupt =
+ *IXDP2351_CPLD_INTA_STAT_REG & IXDP2351_INTA_IRQ_VALID;
+ int i;
+
+ desc->chip->mask(irq);
+
+ for (i = 0; i < IXDP2351_INTA_IRQ_NUM; i++) {
+ if (ex_interrupt & (1 << i)) {
+ struct irqdesc *cpld_desc;
+ int cpld_irq =
+ IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i);
+ cpld_desc = irq_desc + cpld_irq;
+ cpld_desc->handle(cpld_irq, cpld_desc, regs);
+ }
+ }
+
+ desc->chip->unmask(irq);
+}
+
+static struct irqchip ixdp2351_inta_chip = {
+ .ack = ixdp2351_inta_mask,
+ .mask = ixdp2351_inta_mask,
+ .unmask = ixdp2351_inta_unmask
+};
+
+static void ixdp2351_intb_mask(unsigned int irq)
+{
+ *IXDP2351_CPLD_INTB_MASK_SET_REG = IXDP2351_INTB_IRQ_MASK(irq);
+}
+
+static void ixdp2351_intb_unmask(unsigned int irq)
+{
+ *IXDP2351_CPLD_INTB_MASK_CLR_REG = IXDP2351_INTB_IRQ_MASK(irq);
+}
+
+static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+ u16 ex_interrupt =
+ *IXDP2351_CPLD_INTB_STAT_REG & IXDP2351_INTB_IRQ_VALID;
+ int i;
+
+ desc->chip->ack(irq);
+
+ for (i = 0; i < IXDP2351_INTB_IRQ_NUM; i++) {
+ if (ex_interrupt & (1 << i)) {
+ struct irqdesc *cpld_desc;
+ int cpld_irq =
+ IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i);
+ cpld_desc = irq_desc + cpld_irq;
+ cpld_desc->handle(cpld_irq, cpld_desc, regs);
+ }
+ }
+
+ desc->chip->unmask(irq);
+}
+
+static struct irqchip ixdp2351_intb_chip = {
+ .ack = ixdp2351_intb_mask,
+ .mask = ixdp2351_intb_mask,
+ .unmask = ixdp2351_intb_unmask
+};
+
+void ixdp2351_init_irq(void)
+{
+ int irq;
+
+ /* Mask all interrupts from CPLD, disable simulation */
+ *IXDP2351_CPLD_INTA_MASK_SET_REG = (u16) -1;
+ *IXDP2351_CPLD_INTB_MASK_SET_REG = (u16) -1;
+ *IXDP2351_CPLD_INTA_SIM_REG = 0;
+ *IXDP2351_CPLD_INTB_SIM_REG = 0;
+
+ ixp23xx_init_irq();
+
+ for (irq = IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE);
+ irq <
+ IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + IXDP2351_INTA_IRQ_NUM);
+ irq++) {
+ if (IXDP2351_INTA_IRQ_MASK(irq) & IXDP2351_INTA_IRQ_VALID) {
+ set_irq_flags(irq, IRQF_VALID);
+ set_irq_handler(irq, do_level_IRQ);
+ set_irq_chip(irq, &ixdp2351_inta_chip);
+ }
+ }
+
+ for (irq = IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE);
+ irq <
+ IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + IXDP2351_INTB_IRQ_NUM);
+ irq++) {
+ if (IXDP2351_INTB_IRQ_MASK(irq) & IXDP2351_INTB_IRQ_VALID) {
+ set_irq_flags(irq, IRQF_VALID);
+ set_irq_handler(irq, do_level_IRQ);
+ set_irq_chip(irq, &ixdp2351_intb_chip);
+ }
+ }
+
+ set_irq_chained_handler(IRQ_IXP23XX_INTA, &ixdp2351_inta_handler);
+ set_irq_chained_handler(IRQ_IXP23XX_INTB, &ixdp2351_intb_handler);
+}
+
+/*
+ * IXDP2351 PCI
+ */
+
+/*
+ * This board does not do normal PCI IRQ routing, or any
+ * sort of swizzling, so we just need to check where on the
+ * bus the device is and figure out what CPLD pin it is
+ * being routed to.
+ */
+#define DEVPIN(dev, pin) ((pin) | ((dev) << 3))
+
+static int __init ixdp2351_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ u8 bus = dev->bus->number;
+ u32 devpin = DEVPIN(PCI_SLOT(dev->devfn), pin);
+ struct pci_bus *tmp_bus = dev->bus;
+
+ /* Primary bus, no interrupts here */
+ if (!bus)
+ return -1;
+
+ /* Lookup first leaf in bus tree */
+ while ((tmp_bus->parent != NULL) && (tmp_bus->parent->parent != NULL))
+ tmp_bus = tmp_bus->parent;
+
+ /* Select between known bridges */
+ switch (tmp_bus->self->devfn | (tmp_bus->self->bus->number << 8)) {
+ /* Device is located after first bridge */
+ case 0x0008:
+ if (tmp_bus == dev->bus) {
+ /* Device is located directy after first bridge */
+ switch (devpin) {
+ /* Onboard 82546 */
+ case DEVPIN(1, 1): /* Onboard 82546 ch 0 */
+ return IRQ_IXDP2351_INTA_82546;
+ case DEVPIN(1, 2): /* Onboard 82546 ch 1 */
+ return IRQ_IXDP2351_INTB_82546;
+ /* PMC SLOT */
+ case DEVPIN(0, 1): /* PMCP INTA# */
+ case DEVPIN(2, 4): /* PMCS INTD# */
+ return IRQ_IXDP2351_SPCI_PMC_INTA;
+ case DEVPIN(0, 2): /* PMCP INTB# */
+ case DEVPIN(2, 1): /* PMCS INTA# */
+ return IRQ_IXDP2351_SPCI_PMC_INTB;
+ case DEVPIN(0, 3): /* PMCP INTC# */
+ case DEVPIN(2, 2): /* PMCS INTB# */
+ return IRQ_IXDP2351_SPCI_PMC_INTC;
+ case DEVPIN(0, 4): /* PMCP INTD# */
+ case DEVPIN(2, 3): /* PMCS INTC# */
+ return IRQ_IXDP2351_SPCI_PMC_INTD;
+ }
+ } else {
+ /* Device is located indirectly after first bridge */
+ /* Not supported now */
+ return -1;
+ }
+ break;
+ case 0x0010:
+ if (tmp_bus == dev->bus) {
+ /* Device is located directy after second bridge */
+ /* Secondary bus of second bridge */
+ switch (devpin) {
+ case DEVPIN(0, 1): /* DB#0 */
+ case DEVPIN(0, 2):
+ case DEVPIN(0, 3):
+ case DEVPIN(0, 4):
+ return IRQ_IXDP2351_SPCI_DB_0;
+ case DEVPIN(1, 1): /* DB#1 */
+ case DEVPIN(1, 2):
+ case DEVPIN(1, 3):
+ case DEVPIN(1, 4):
+ return IRQ_IXDP2351_SPCI_DB_1;
+ case DEVPIN(2, 1): /* FIC1 */
+ case DEVPIN(2, 2):
+ case DEVPIN(2, 3):
+ case DEVPIN(2, 4):
+ case DEVPIN(3, 1): /* FIC2 */
+ case DEVPIN(3, 2):
+ case DEVPIN(3, 3):
+ case DEVPIN(3, 4):
+ return IRQ_IXDP2351_SPCI_FIC;
+ }
+ } else {
+ /* Device is located indirectly after second bridge */
+ /* Not supported now */
+ return -1;
+ }
+ break;
+ }
+
+ return -1;
+}
+
+struct hw_pci ixdp2351_pci __initdata = {
+ .nr_controllers = 1,
+ .preinit = ixp23xx_pci_preinit,
+ .setup = ixp23xx_pci_setup,
+ .scan = ixp23xx_pci_scan_bus,
+ .map_irq = ixdp2351_map_irq,
+};
+
+int __init ixdp2351_pci_init(void)
+{
+ if (machine_is_ixdp2351())
+ pci_common_init(&ixdp2351_pci);
+
+ return 0;
+}
+
+subsys_initcall(ixdp2351_pci_init);
+
+/*
+ * IXDP2351 Static Mapped I/O
+ */
+static struct map_desc ixdp2351_io_desc[] __initdata = {
+ {
+ .virtual = IXDP2351_NP_VIRT_BASE,
+ .pfn = __phys_to_pfn((u64)IXDP2351_NP_PHYS_BASE),
+ .length = IXDP2351_NP_PHYS_SIZE,
+ .type = MT_DEVICE
+ }, {
+ .virtual = IXDP2351_BB_BASE_VIRT,
+ .pfn = __phys_to_pfn((u64)IXDP2351_BB_BASE_PHYS),
+ .length = IXDP2351_BB_SIZE,
+ .type = MT_DEVICE
+ }
+};
+
+static void __init ixdp2351_map_io(void)
+{
+ ixp23xx_map_io();
+ iotable_init(ixdp2351_io_desc, ARRAY_SIZE(ixdp2351_io_desc));
+}
+
+static void __init ixdp2351_init(void)
+{
+ physmap_configure(0x90000000, 0x04000000, 1, NULL);
+
+ /*
+ * Mark flash as writeable
+ */
+ IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[2] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[3] |= IXP23XX_FLASH_WRITABLE;
+
+ ixp23xx_sys_init();
+}
+
+MACHINE_START(IXDP2351, "Intel IXDP2351 Development Platform")
+ /* Maintainer: MontaVista Software, Inc. */
+ .phys_io = IXP23XX_PERIPHERAL_PHYS,
+ .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
+ .map_io = ixdp2351_map_io,
+ .init_irq = ixdp2351_init_irq,
+ .timer = &ixp23xx_timer,
+ .boot_params = 0x00000100,
+ .init_machine = ixdp2351_init,
+MACHINE_END
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c
new file mode 100644
index 00000000000..5330ad78c1b
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/pci.c
@@ -0,0 +1,275 @@
+/*
+ * arch/arm/mach-ixp23xx/pci.c
+ *
+ * PCI routines for IXP23XX based systems
+ *
+ * Copyright (c) 2005 MontaVista Software, Inc.
+ *
+ * based on original code:
+ *
+ * Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Copyright 2002-2005 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+extern int (*external_fault) (unsigned long, struct pt_regs *);
+
+static int pci_master_aborts = 0;
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+int clear_master_aborts(void);
+
+static u32
+*ixp23xx_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where)
+{
+ u32 *paddress;
+
+ /*
+ * Must be dword aligned
+ */
+ where &= ~3;
+
+ /*
+ * For top bus, generate type 0, else type 1
+ */
+ if (!bus_nr) {
+ if (PCI_SLOT(devfn) >= 8)
+ return 0;
+
+ paddress = (u32 *) (IXP23XX_PCI_CFG0_VIRT
+ | (1 << (PCI_SLOT(devfn) + 16))
+ | (PCI_FUNC(devfn) << 8) | where);
+ } else {
+ paddress = (u32 *) (IXP23XX_PCI_CFG1_VIRT
+ | (bus_nr << 16)
+ | (PCI_SLOT(devfn) << 11)
+ | (PCI_FUNC(devfn) << 8) | where);
+ }
+
+ return paddress;
+}
+
+/*
+ * Mask table, bits to mask for quantity of size 1, 2 or 4 bytes.
+ * 0 and 3 are not valid indexes...
+ */
+static u32 bytemask[] = {
+ /*0*/ 0,
+ /*1*/ 0xff,
+ /*2*/ 0xffff,
+ /*3*/ 0,
+ /*4*/ 0xffffffff,
+};
+
+static int ixp23xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *value)
+{
+ u32 n;
+ u32 *addr;
+
+ n = where % 4;
+
+ DBG("In config_read(%d) %d from dev %d:%d:%d\n", size, where,
+ bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+ addr = ixp23xx_pci_config_addr(bus->number, devfn, where);
+ if (!addr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ pci_master_aborts = 0;
+ *value = (*addr >> (8*n)) & bytemask[size];
+ if (pci_master_aborts) {
+ pci_master_aborts = 0;
+ *value = 0xffffffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * We don't do error checking on the address for writes.
+ * It's assumed that the user checked for the device existing first
+ * by doing a read first.
+ */
+static int ixp23xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 value)
+{
+ u32 mask;
+ u32 *addr;
+ u32 temp;
+
+ mask = ~(bytemask[size] << ((where % 0x4) * 8));
+ addr = ixp23xx_pci_config_addr(bus->number, devfn, where);
+ if (!addr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ temp = (u32) (value) << ((where % 0x4) * 8);
+ *addr = (*addr & mask) | temp;
+
+ clear_master_aborts();
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops ixp23xx_pci_ops = {
+ .read = ixp23xx_pci_read_config,
+ .write = ixp23xx_pci_write_config,
+};
+
+struct pci_bus *ixp23xx_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
+{
+ return pci_scan_bus(sysdata->busnr, &ixp23xx_pci_ops, sysdata);
+}
+
+int ixp23xx_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+ volatile unsigned long temp;
+ unsigned long flags;
+
+ pci_master_aborts = 1;
+
+ local_irq_save(flags);
+ temp = *IXP23XX_PCI_CONTROL;
+
+ /*
+ * master abort and cmd tgt err
+ */
+ if (temp & ((1 << 8) | (1 << 5)))
+ *IXP23XX_PCI_CONTROL = temp;
+
+ temp = *IXP23XX_PCI_CMDSTAT;
+
+ if (temp & (1 << 29))
+ *IXP23XX_PCI_CMDSTAT = temp;
+ local_irq_restore(flags);
+
+ /*
+ * If it was an imprecise abort, then we need to correct the
+ * return address to be _after_ the instruction.
+ */
+ if (fsr & (1 << 10))
+ regs->ARM_pc += 4;
+
+ return 0;
+}
+
+int clear_master_aborts(void)
+{
+ volatile u32 temp;
+
+ temp = *IXP23XX_PCI_CONTROL;
+
+ /*
+ * master abort and cmd tgt err
+ */
+ if (temp & ((1 << 8) | (1 << 5)))
+ *IXP23XX_PCI_CONTROL = temp;
+
+ temp = *IXP23XX_PCI_CMDSTAT;
+
+ if (temp & (1 << 29))
+ *IXP23XX_PCI_CMDSTAT = temp;
+
+ return 0;
+}
+
+void __init ixp23xx_pci_preinit(void)
+{
+#ifdef __ARMEB__
+ *IXP23XX_PCI_CONTROL |= 0x20000; /* set I/O swapping */
+#endif
+ /*
+ * ADDR_31 needs to be clear for PCI memory access to CPP memory
+ */
+ *IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_ADDR_31;
+ *IXP23XX_CPP2XSI_CURR_XFER_REG3 |= IXP23XX_CPP2XSI_PSH_OFF;
+
+ /*
+ * Select correct memory for PCI inbound transactions
+ */
+ if (ixp23xx_cpp_boot()) {
+ *IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1);
+ } else {
+ *IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1);
+ }
+
+ hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS,
+ "PCI config cycle to non-existent device");
+
+ *IXP23XX_PCI_ADDR_EXT = 0x0000e000;
+}
+
+/*
+ * Prevent PCI layer from seeing the inbound host-bridge resources
+ */
+static void __devinit pci_fixup_ixp23xx(struct pci_dev *dev)
+{
+ int i;
+
+ dev->class &= 0xff;
+ dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ dev->resource[i].start = 0;
+ dev->resource[i].end = 0;
+ dev->resource[i].flags = 0;
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9002, pci_fixup_ixp23xx);
+
+/*
+ * IXP2300 systems often have large resource requirements, so we just
+ * use our own resource space.
+ */
+static struct resource ixp23xx_pci_mem_space = {
+ .start = IXP23XX_PCI_MEM_START,
+ .end = IXP23XX_PCI_MEM_START + IXP23XX_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "PCI Mem Space"
+};
+
+static struct resource ixp23xx_pci_io_space = {
+ .start = 0x00000100,
+ .end = 0x01ffffff,
+ .flags = IORESOURCE_IO,
+ .name = "PCI I/O Space"
+};
+
+int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys)
+{
+ if (nr >= 1)
+ return 0;
+
+ sys->resource[0] = &ixp23xx_pci_io_space;
+ sys->resource[1] = &ixp23xx_pci_mem_space;
+ sys->resource[2] = NULL;
+
+ return 1;
+}
diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c
new file mode 100644
index 00000000000..43c14e74079
--- /dev/null
+++ b/arch/arm/mach-ixp23xx/roadrunner.c
@@ -0,0 +1,164 @@
+/*
+ * arch/arm/mach-ixp23xx/roadrunner.c
+ *
+ * RoadRunner board-specific routines
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * Based on 2.4 code Copyright 2005 (c) ADI Engineering Corporation
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/bitops.h>
+#include <linux/ioport.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/pci.h>
+
+/*
+ * Interrupt mapping
+ */
+#define INTA IRQ_ROADRUNNER_PCI_INTA
+#define INTB IRQ_ROADRUNNER_PCI_INTB
+#define INTC IRQ_ROADRUNNER_PCI_INTC
+#define INTD IRQ_ROADRUNNER_PCI_INTD
+
+#define INTC_PIN IXP23XX_GPIO_PIN_11
+#define INTD_PIN IXP23XX_GPIO_PIN_12
+
+static int __init roadrunner_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+{
+ static int pci_card_slot_irq[] = {INTB, INTC, INTD, INTA};
+ static int pmc_card_slot_irq[] = {INTA, INTB, INTC, INTD};
+ static int usb_irq[] = {INTB, INTC, INTD, -1};
+ static int mini_pci_1_irq[] = {INTB, INTC, -1, -1};
+ static int mini_pci_2_irq[] = {INTC, INTD, -1, -1};
+
+ switch(dev->bus->number) {
+ case 0:
+ switch(dev->devfn) {
+ case 0x0: // PCI-PCI bridge
+ break;
+ case 0x8: // PCI Card Slot
+ return pci_card_slot_irq[pin - 1];
+ case 0x10: // PMC Slot
+ return pmc_card_slot_irq[pin - 1];
+ case 0x18: // PMC Slot Secondary Agent
+ break;
+ case 0x20: // IXP Processor
+ break;
+ default:
+ return NO_IRQ;
+ }
+ break;
+
+ case 1:
+ switch(dev->devfn) {
+ case 0x0: // IDE Controller
+ return (pin == 1) ? INTC : -1;
+ case 0x8: // USB fun 0
+ case 0x9: // USB fun 1
+ case 0xa: // USB fun 2
+ return usb_irq[pin - 1];
+ case 0x10: // Mini PCI 1
+ return mini_pci_1_irq[pin-1];
+ case 0x18: // Mini PCI 2
+ return mini_pci_2_irq[pin-1];
+ case 0x20: // MEM slot
+ return (pin == 1) ? INTA : -1;
+ default:
+ return NO_IRQ;
+ }
+ break;
+
+ default:
+ return NO_IRQ;
+ }
+
+ return NO_IRQ;
+}
+
+static void roadrunner_pci_preinit(void)
+{
+ set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQT_LOW);
+ set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQT_LOW);
+
+ ixp23xx_pci_preinit();
+}
+
+static struct hw_pci roadrunner_pci __initdata = {
+ .nr_controllers = 1,
+ .preinit = roadrunner_pci_preinit,
+ .setup = ixp23xx_pci_setup,
+ .scan = ixp23xx_pci_scan_bus,
+ .map_irq = roadrunner_map_irq,
+};
+
+static int __init roadrunner_pci_init(void)
+{
+ if (machine_is_roadrunner())
+ pci_common_init(&roadrunner_pci);
+
+ return 0;
+};
+
+subsys_initcall(roadrunner_pci_init);
+
+static void __init roadrunner_init(void)
+{
+ physmap_configure(0x90000000, 0x04000000, 2, NULL);
+
+ /*
+ * Mark flash as writeable
+ */
+ IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[2] |= IXP23XX_FLASH_WRITABLE;
+ IXP23XX_EXP_CS0[3] |= IXP23XX_FLASH_WRITABLE;
+
+ ixp23xx_sys_init();
+}
+
+MACHINE_START(ROADRUNNER, "ADI Engineering RoadRunner Development Platform")
+ /* Maintainer: Deepak Saxena */
+ .phys_io = IXP23XX_PERIPHERAL_PHYS,
+ .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc,
+ .map_io = ixp23xx_map_io,
+ .init_irq = ixp23xx_init_irq,
+ .timer = &ixp23xx_timer,
+ .boot_params = 0x00000100,
+ .init_machine = roadrunner_init,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c
index 60d5f8a3339..7520e602d7a 100644
--- a/arch/arm/mach-omap1/board-netstar.c
+++ b/arch/arm/mach-omap1/board-netstar.c
@@ -141,7 +141,7 @@ static int __init netstar_late_init(void)
/* TODO: Setup front panel switch here */
/* Setup panic notifier */
- notifier_chain_register(&panic_notifier_list, &panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
return 0;
}
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index bfd5fdd1a87..52e4a9d6964 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -235,7 +235,7 @@ static struct notifier_block panic_block = {
static int __init voiceblue_setup(void)
{
/* Setup panic notifier */
- notifier_chain_register(&panic_notifier_list, &panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
return 0;
}
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 24dd374224a..0884bc7c23b 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -167,7 +167,7 @@ void __init omap_serial_init()
static struct platform_device serial_device = {
.name = "serial8250",
- .id = 0,
+ .id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = serial_platform_data,
},
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index c1d77f5b382..0104fd142e7 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -10,6 +10,11 @@ config ARCH_LUBBOCK
select PXA25x
select SA1111
+config MACH_LOGICPD_PXA270
+ bool "LogicPD PXA270 Card Engine Development Platform"
+ select PXA27x
+ select IWMMXT
+
config MACH_MAINSTONE
bool "Intel HCDDBBVA0 Development Platform"
select PXA27x
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 382644401a4..4e8a983e2b8 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_PXA27x) += pxa27x.o
# Specific board support
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
+obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 9b48a90aefc..5efa84749f3 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -319,6 +319,11 @@ void __init pxa_set_ficp_info(struct pxaficp_platform_data *info)
pxaficp_device.dev.platform_data = info;
}
+static struct platform_device pxartc_device = {
+ .name = "sa1100-rtc",
+ .id = -1,
+};
+
static struct platform_device *devices[] __initdata = {
&pxamci_device,
&udc_device,
@@ -329,6 +334,7 @@ static struct platform_device *devices[] __initdata = {
&pxaficp_device,
&i2c_device,
&i2s_device,
+ &pxartc_device,
};
static int __init pxa_init(void)
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
new file mode 100644
index 00000000000..ec0f43a102c
--- /dev/null
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -0,0 +1,393 @@
+/*
+ * linux/arch/arm/mach-pxa/lpd270.c
+ *
+ * Support for the LogicPD PXA270 Card Engine.
+ * Derived from the mainstone code, which carries these notices:
+ *
+ * Author: Nicolas Pitre
+ * Created: Nov 05, 2002
+ * Copyright: MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/bitops.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/lpd270.h>
+#include <asm/arch/audio.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/ohci.h>
+
+#include "generic.h"
+
+
+static unsigned int lpd270_irq_enabled;
+
+static void lpd270_mask_irq(unsigned int irq)
+{
+ int lpd270_irq = irq - LPD270_IRQ(0);
+
+ __raw_writew(~(1 << lpd270_irq), LPD270_INT_STATUS);
+
+ lpd270_irq_enabled &= ~(1 << lpd270_irq);
+ __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
+}
+
+static void lpd270_unmask_irq(unsigned int irq)
+{
+ int lpd270_irq = irq - LPD270_IRQ(0);
+
+ lpd270_irq_enabled |= 1 << lpd270_irq;
+ __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
+}
+
+static struct irqchip lpd270_irq_chip = {
+ .ack = lpd270_mask_irq,
+ .mask = lpd270_mask_irq,
+ .unmask = lpd270_unmask_irq,
+};
+
+static void lpd270_irq_handler(unsigned int irq, struct irqdesc *desc,
+ struct pt_regs *regs)
+{
+ unsigned long pending;
+
+ pending = __raw_readw(LPD270_INT_STATUS) & lpd270_irq_enabled;
+ do {
+ GEDR(0) = GPIO_bit(0); /* clear useless edge notification */
+ if (likely(pending)) {
+ irq = LPD270_IRQ(0) + __ffs(pending);
+ desc = irq_desc + irq;
+ desc_handle_irq(irq, desc, regs);
+
+ pending = __raw_readw(LPD270_INT_STATUS) &
+ lpd270_irq_enabled;
+ }
+ } while (pending);
+}
+
+static void __init lpd270_init_irq(void)
+{
+ int irq;
+
+ pxa_init_irq();
+
+ __raw_writew(0, LPD270_INT_MASK);
+ __raw_writew(0, LPD270_INT_STATUS);
+
+ /* setup extra LogicPD PXA270 irqs */
+ for (irq = LPD270_IRQ(2); irq <= LPD270_IRQ(4); irq++) {
+ set_irq_chip(irq, &lpd270_irq_chip);
+ set_irq_handler(irq, do_level_IRQ);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
+ set_irq_chained_handler(IRQ_GPIO(0), lpd270_irq_handler);
+ set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
+}
+
+
+#ifdef CONFIG_PM
+static int lpd270_irq_resume(struct sys_device *dev)
+{
+ __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
+ return 0;
+}
+
+static struct sysdev_class lpd270_irq_sysclass = {
+ set_kset_name("cpld_irq"),
+ .resume = lpd270_irq_resume,
+};
+
+static struct sys_device lpd270_irq_device = {
+ .cls = &lpd270_irq_sysclass,
+};
+
+static int __init lpd270_irq_device_init(void)
+{
+ int ret = sysdev_class_register(&lpd270_irq_sysclass);
+ if (ret == 0)
+ ret = sysdev_register(&lpd270_irq_device);
+ return ret;
+}
+
+device_initcall(lpd270_irq_device_init);
+#endif
+
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = LPD270_ETH_PHYS,
+ .end = (LPD270_ETH_PHYS + 0xfffff),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = LPD270_ETHERNET_IRQ,
+ .end = LPD270_ETHERNET_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+static struct platform_device lpd270_audio_device = {
+ .name = "pxa2xx-ac97",
+ .id = -1,
+};
+
+static struct resource lpd270_flash_resources[] = {
+ [0] = {
+ .start = PXA_CS0_PHYS,
+ .end = PXA_CS0_PHYS + SZ_64M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = PXA_CS1_PHYS,
+ .end = PXA_CS1_PHYS + SZ_64M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct mtd_partition lpd270_flash0_partitions[] = {
+ {
+ .name = "Bootloader",
+ .size = 0x00040000,
+ .offset = 0,
+ .mask_flags = MTD_WRITEABLE /* force read-only */
+ }, {
+ .name = "Kernel",
+ .size = 0x00400000,
+ .offset = 0x00040000,
+ }, {
+ .name = "Filesystem",
+ .size = MTDPART_SIZ_FULL,
+ .offset = 0x00440000
+ },
+};
+
+static struct flash_platform_data lpd270_flash_data[2] = {
+ {
+ .name = "processor-flash",
+ .map_name = "cfi_probe",
+ .parts = lpd270_flash0_partitions,
+ .nr_parts = ARRAY_SIZE(lpd270_flash0_partitions),
+ }, {
+ .name = "mainboard-flash",
+ .map_name = "cfi_probe",
+ .parts = NULL,
+ .nr_parts = 0,
+ }
+};
+
+static struct platform_device lpd270_flash_device[2] = {
+ {
+ .name = "pxa2xx-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &lpd270_flash_data[0],
+ },
+ .resource = &lpd270_flash_resources[0],
+ .num_resources = 1,
+ }, {
+ .name = "pxa2xx-flash",
+ .id = 1,
+ .dev = {
+ .platform_data = &lpd270_flash_data[1],
+ },
+ .resource = &lpd270_flash_resources[1],
+ .num_resources = 1,
+ },
+};
+
+static void lpd270_backlight_power(int on)
+{
+ if (on) {
+ pxa_gpio_mode(GPIO16_PWM0_MD);
+ pxa_set_cken(CKEN0_PWM0, 1);
+ PWM_CTRL0 = 0;
+ PWM_PWDUTY0 = 0x3ff;
+ PWM_PERVAL0 = 0x3ff;
+ } else {
+ PWM_CTRL0 = 0;
+ PWM_PWDUTY0 = 0x0;
+ PWM_PERVAL0 = 0x3FF;
+ pxa_set_cken(CKEN0_PWM0, 0);
+ }
+}
+
+/* 5.7" TFT QVGA (LoLo display number 1) */
+static struct pxafb_mach_info sharp_lq057q3dc02 __initdata = {
+ .pixclock = 100000,
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+ .hsync_len = 64,
+ .left_margin = 0x27,
+ .right_margin = 0x09,
+ .vsync_len = 0x04,
+ .upper_margin = 0x08,
+ .lower_margin = 0x14,
+ .sync = 0,
+ .lccr0 = 0x07800080,
+ .lccr3 = 0x04400007,
+ .pxafb_backlight_power = lpd270_backlight_power,
+};
+
+/* 6.4" TFT VGA (LoLo display number 5) */
+static struct pxafb_mach_info sharp_lq64d343 __initdata = {
+ .pixclock = 20000,
+ .xres = 640,
+ .yres = 480,
+ .bpp = 16,
+ .hsync_len = 49,
+ .left_margin = 0x89,
+ .right_margin = 0x19,
+ .vsync_len = 18,
+ .upper_margin = 0x22,
+ .lower_margin = 0,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .lccr0 = 0x07800080,
+ .lccr3 = 0x04400001,
+ .pxafb_backlight_power = lpd270_backlight_power,
+};
+
+/* 3.5" TFT QVGA (LoLo display number 8) */
+static struct pxafb_mach_info sharp_lq035q7db02_20 __initdata = {
+ .pixclock = 100000,
+ .xres = 240,
+ .yres = 320,
+ .bpp = 16,
+ .hsync_len = 0x34,
+ .left_margin = 0x09,
+ .right_margin = 0x09,
+ .vsync_len = 0x08,
+ .upper_margin = 0x05,
+ .lower_margin = 0x14,
+ .sync = 0,
+ .lccr0 = 0x07800080,
+ .lccr3 = 0x04400007,
+ .pxafb_backlight_power = lpd270_backlight_power,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+ &smc91x_device,
+ &lpd270_audio_device,
+ &lpd270_flash_device[0],
+ &lpd270_flash_device[1],
+};
+
+static int lpd270_ohci_init(struct device *dev)
+{
+ /* setup Port1 GPIO pin. */
+ pxa_gpio_mode(88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */
+ pxa_gpio_mode(89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
+
+ /* Set the Power Control Polarity Low and Power Sense
+ Polarity Low to active low. */
+ UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
+ ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+
+ return 0;
+}
+
+static struct pxaohci_platform_data lpd270_ohci_platform_data = {
+ .port_mode = PMM_PERPORT_MODE,
+ .init = lpd270_ohci_init,
+};
+
+static void __init lpd270_init(void)
+{
+ lpd270_flash_data[0].width = (BOOT_DEF & 1) ? 2 : 4;
+ lpd270_flash_data[1].width = 4;
+
+ /*
+ * System bus arbiter setting:
+ * - Core_Park
+ * - LCD_wt:DMA_wt:CORE_Wt = 2:3:4
+ */
+ ARB_CNTRL = ARB_CORE_PARK | 0x234;
+
+ /*
+ * On LogicPD PXA270, we route AC97_SYSCLK via GPIO45.
+ */
+ pxa_gpio_mode(GPIO45_SYSCLK_AC97_MD);
+
+ platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+ // set_pxa_fb_info(&sharp_lq057q3dc02);
+ set_pxa_fb_info(&sharp_lq64d343);
+ // set_pxa_fb_info(&sharp_lq035q7db02_20);
+
+ pxa_set_ohci_info(&lpd270_ohci_platform_data);
+}
+
+
+static struct map_desc lpd270_io_desc[] __initdata = {
+ {
+ .virtual = LPD270_CPLD_VIRT,
+ .pfn = __phys_to_pfn(LPD270_CPLD_PHYS),
+ .length = LPD270_CPLD_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+static void __init lpd270_map_io(void)
+{
+ pxa_map_io();
+ iotable_init(lpd270_io_desc, ARRAY_SIZE(lpd270_io_desc));
+
+ /* initialize sleep mode regs (wake-up sources, etc) */
+ PGSR0 = 0x00008800;
+ PGSR1 = 0x00000002;
+ PGSR2 = 0x0001FC00;
+ PGSR3 = 0x00001F81;
+ PWER = 0xC0000002;
+ PRER = 0x00000002;
+ PFER = 0x00000002;
+
+ /* for use I SRAM as framebuffer. */
+ PSLR |= 0x00000F04;
+ PCFR = 0x00000066;
+}
+
+MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
+ /* Maintainer: Peter Barada */
+ .phys_io = 0x40000000,
+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+ .boot_params = 0xa0000100,
+ .map_io = lpd270_map_io,
+ .init_irq = lpd270_init_irq,
+ .timer = &pxa_timer,
+ .init_machine = lpd270_init,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 30ec317bbb9..0dbb079ecd2 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -467,6 +467,8 @@ struct platform_device akitaioexp_device = {
.id = -1,
};
+EXPORT_SYMBOL_GPL(akitaioexp_device);
+
static void __init akita_init(void)
{
spitz_ficp_platform_data.transceiver_mode = akita_irda_transceiver_mode;
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
index 6923316b3d0..cd67ab1b217 100644
--- a/arch/arm/mach-sa1100/Kconfig
+++ b/arch/arm/mach-sa1100/Kconfig
@@ -111,7 +111,7 @@ config SA1100_LART
bool "LART"
help
Say Y here if you are using the Linux Advanced Radio Terminal
- (also known as the LART). See <http://www.lart.tudelft.nl/> for
+ (also known as the LART). See <http://www.lartmaker.nl/> for
information on the LART.
config SA1100_PLEB
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index a599bb0d4ab..c58f12ba7a9 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -26,6 +26,7 @@
#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/page.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 6888816a193..10245408247 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -40,6 +40,7 @@
#include <asm/hardware/scoop.h>
#include <asm/mach/sharpsl_param.h>
#include <asm/hardware/locomo.h>
+#include <asm/arch/mcp.h>
#include "generic.h"
@@ -66,6 +67,32 @@ struct platform_device colliescoop_device = {
.resource = collie_scoop_resources,
};
+static struct scoop_pcmcia_dev collie_pcmcia_scoop[] = {
+{
+ .dev = &colliescoop_device.dev,
+ .irq = COLLIE_IRQ_GPIO_CF_IRQ,
+ .cd_irq = COLLIE_IRQ_GPIO_CF_CD,
+ .cd_irq_str = "PCMCIA0 CD",
+},
+};
+
+static struct scoop_pcmcia_config collie_pcmcia_config = {
+ .devs = &collie_pcmcia_scoop[0],
+ .num_devs = 1,
+};
+
+
+static struct mcp_plat_data collie_mcp_data = {
+ .mccr0 = MCCR0_ADM,
+ .sclk_rate = 11981000,
+};
+
+
+static struct sa1100_port_fns collie_port_fns __initdata = {
+ .set_mctrl = collie_uart_set_mctrl,
+ .get_mctrl = collie_uart_get_mctrl,
+};
+
static struct resource locomo_resources[] = {
[0] = {
@@ -159,6 +186,8 @@ static void __init collie_init(void)
GPDR |= GPIO_32_768kHz;
TUCR = TUCR_32_768kHz;
+ platform_scoop_config = &collie_pcmcia_config;
+
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
if (ret) {
printk(KERN_WARNING "collie: Unable to register LoCoMo device\n");
@@ -166,6 +195,7 @@ static void __init collie_init(void)
sa11x0_set_flash_data(&collie_flash_data, collie_flash_resources,
ARRAY_SIZE(collie_flash_resources));
+ sa11x0_set_mcp_data(&collie_mcp_data);
sharpsl_save_param();
}
diff --git a/arch/arm/mach-sa1100/collie_pm.c b/arch/arm/mach-sa1100/collie_pm.c
new file mode 100644
index 00000000000..696d7d29c8a
--- /dev/null
+++ b/arch/arm/mach-sa1100/collie_pm.c
@@ -0,0 +1,278 @@
+/*
+ * Based on spitz_pm.c and sharp code.
+ *
+ * Copyright (C) 2001 SHARP
+ * Copyright 2005 Pavel Machek <pavel@suse.cz>
+ *
+ * Distribute under GPLv2.
+ *
+ * Li-ion batteries are angry beasts, and they like to explode. This driver is not finished,
+ * and sometimes charges them when it should not. If it makes angry lithium to come your way...
+ * ...well, you have been warned.
+ */
+
+#include <linux/module.h>
+#include <linux/stat.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/hardware/scoop.h>
+#include <asm/dma.h>
+#include <asm/arch/collie.h>
+#include <asm/mach/sharpsl_param.h>
+#include <asm/hardware/sharpsl_pm.h>
+
+#include "../drivers/mfd/ucb1x00.h"
+
+static struct ucb1x00 *ucb;
+static int ad_revise;
+
+#define ADCtoPower(x) ((330 * x * 2) / 1024)
+
+static void collie_charger_init(void)
+{
+ int err;
+
+ if (sharpsl_param.adadj != -1) {
+ ad_revise = sharpsl_param.adadj;
+ }
+
+ /* Register interrupt handler. */
+ if ((err = request_irq(COLLIE_IRQ_GPIO_AC_IN, sharpsl_ac_isr, SA_INTERRUPT,
+ "ACIN", sharpsl_ac_isr))) {
+ printk("Could not get irq %d.\n", COLLIE_IRQ_GPIO_AC_IN);
+ return;
+ }
+ if ((err = request_irq(COLLIE_IRQ_GPIO_CO, sharpsl_chrg_full_isr, SA_INTERRUPT,
+ "CO", sharpsl_chrg_full_isr))) {
+ free_irq(COLLIE_IRQ_GPIO_AC_IN, sharpsl_ac_isr);
+ printk("Could not get irq %d.\n", COLLIE_IRQ_GPIO_CO);
+ return;
+ }
+
+ ucb1x00_io_set_dir(ucb, 0, COLLIE_TC35143_GPIO_MBAT_ON | COLLIE_TC35143_GPIO_TMP_ON |
+ COLLIE_TC35143_GPIO_BBAT_ON);
+ return;
+}
+
+static void collie_measure_temp(int on)
+{
+ if (on)
+ ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_TMP_ON, 0);
+ else
+ ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_TMP_ON);
+}
+
+static void collie_charge(int on)
+{
+ if (on) {
+ printk("Should start charger\n");
+ } else {
+ printk("Should stop charger\n");
+ }
+#ifdef I_AM_SURE
+
+ /* Zaurus seems to contain LTC1731 ; it should know when to
+ * stop charging itself, so setting charge on should be
+ * relatively harmless (as long as it is not done too often).
+ */
+#define CF_BUF_CTRL_BASE 0xF0800000
+#define SCOOP_REG(adr) (*(volatile unsigned short*)(CF_BUF_CTRL_BASE+(adr)))
+#define SCOOP_REG_GPWR SCOOP_REG(SCOOP_GPWR)
+
+ if (on) {
+ set_scoop_gpio(&colliescoop_device.dev, COLLIE_SCP_CHARGE_ON);
+ } else {
+ reset_scoop_gpio(&colliescoop_device.dev, COLLIE_SCP_CHARGE_ON);
+ }
+#endif
+}
+
+static void collie_discharge(int on)
+{
+}
+
+static void collie_discharge1(int on)
+{
+}
+
+static void collie_presuspend(void)
+{
+}
+
+static void collie_postsuspend(void)
+{
+}
+
+static int collie_should_wakeup(unsigned int resume_on_alarm)
+{
+ return 0;
+}
+
+static unsigned long collie_charger_wakeup(void)
+{
+ return 0;
+}
+
+int collie_read_backup_battery(void)
+{
+ int voltage;
+
+ ucb1x00_adc_enable(ucb);
+
+ /* Gives 75..130 */
+ ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_BBAT_ON, 0);
+ voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD1, UCB_SYNC);
+
+ ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_BBAT_ON);
+ ucb1x00_adc_disable(ucb);
+
+ printk("Backup battery = %d(%d)\n", ADCtoPower(voltage), voltage);
+
+ return ADCtoPower(voltage);
+}
+
+int collie_read_main_battery(void)
+{
+ int voltage, voltage_rev, voltage_volts;
+
+ ucb1x00_adc_enable(ucb);
+ ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_BBAT_ON);
+ ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_MBAT_ON, 0);
+ /* gives values 160..255 with battery removed... and
+ 145..255 with battery inserted. (on AC), goes as low as
+ 80 on DC. */
+ voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD1, UCB_SYNC);
+
+ ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_MBAT_ON);
+ ucb1x00_adc_disable(ucb);
+
+ voltage_rev = voltage + ((ad_revise * voltage) / 652);
+ voltage_volts = ADCtoPower(voltage_rev);
+
+ printk("Main battery = %d(%d)\n", voltage_volts, voltage);
+
+ if (voltage != -1)
+ return voltage_volts;
+ else
+ return voltage;
+}
+
+int collie_read_temp(void)
+{
+ int voltage;
+
+ /* According to Sharp, temp must be > 973, main battery must be < 465,
+ FIXME: sharpsl_pm.c has both conditions negated? FIXME: values
+ are way out of range? */
+
+ ucb1x00_adc_enable(ucb);
+ ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_TMP_ON, 0);
+ /* >1010 = battery removed, 460 = 22C ?, higer = lower temp ? */
+ voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD0, UCB_SYNC);
+ ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_TMP_ON);
+ ucb1x00_adc_disable(ucb);
+
+ printk("Battery temp = %d\n", voltage);
+ return voltage;
+}
+
+static unsigned long read_devdata(int which)
+{
+ switch (which) {
+ case SHARPSL_BATT_VOLT:
+ return collie_read_main_battery();
+ case SHARPSL_BATT_TEMP:
+ return collie_read_temp();
+ case SHARPSL_ACIN_VOLT:
+ return 0x1;
+ case SHARPSL_STATUS_ACIN: {
+ int ret = GPLR & COLLIE_GPIO_AC_IN;
+ printk("AC status = %d\n", ret);
+ return ret;
+ }
+ case SHARPSL_STATUS_FATAL: {
+ int ret = GPLR & COLLIE_GPIO_MAIN_BAT_LOW;
+ printk("Fatal bat = %d\n", ret);
+ return ret;
+ }
+ default:
+ return ~0;
+ }
+}
+
+struct battery_thresh collie_battery_levels[] = {
+ { 368, 100},
+ { 358, 25},
+ { 356, 5},
+ { 0, 0},
+};
+
+struct sharpsl_charger_machinfo collie_pm_machinfo = {
+ .init = collie_charger_init,
+ .read_devdata = read_devdata,
+ .discharge = collie_discharge,
+ .discharge1 = collie_discharge1,
+ .charge = collie_charge,
+ .measure_temp = collie_measure_temp,
+ .presuspend = collie_presuspend,
+ .postsuspend = collie_postsuspend,
+ .charger_wakeup = collie_charger_wakeup,
+ .should_wakeup = collie_should_wakeup,
+ .bat_levels = 3,
+ .bat_levels_noac = collie_battery_levels,
+ .bat_levels_acin = collie_battery_levels,
+ .status_high_acin = 368,
+ .status_low_acin = 358,
+ .status_high_noac = 368,
+ .status_low_noac = 358,
+};
+
+static int __init collie_pm_ucb_add(struct ucb1x00_dev *pdev)
+{
+ sharpsl_pm.machinfo = &collie_pm_machinfo;
+ ucb = pdev->ucb;
+ return 0;
+}
+
+static struct ucb1x00_driver collie_pm_ucb_driver = {
+ .add = collie_pm_ucb_add,
+};
+
+static struct platform_device *collie_pm_device;
+
+static int __init collie_pm_init(void)
+{
+ int ret;
+
+ collie_pm_device = platform_device_alloc("sharpsl-pm", -1);
+ if (!collie_pm_device)
+ return -ENOMEM;
+
+ collie_pm_device->dev.platform_data = &collie_pm_machinfo;
+ ret = platform_device_add(collie_pm_device);
+
+ if (ret)
+ platform_device_put(collie_pm_device);
+
+ if (!ret)
+ ret = ucb1x00_register_driver(&collie_pm_ucb_driver);
+
+ return ret;
+}
+
+static void __exit collie_pm_exit(void)
+{
+ ucb1x00_unregister_driver(&collie_pm_ucb_driver);
+ platform_device_unregister(collie_pm_device);
+}
+
+module_init(collie_pm_init);
+module_exit(collie_pm_exit);
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
index 6435b2e48ff..d68630b74d7 100644
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c
@@ -11,7 +11,7 @@
* linux-2.4.5-rmk1
*
* This software has been developed while working on the LART
- * computing board (http://www.lart.tudelft.nl/), which is
+ * computing board (http://www.lartmaker.nl/), which is
* sponsored by the Mobile Multi-media Communications
* (http://www.mmc.tudelft.nl/) and Ubiquitous Communications
* (http://www.ubicom.tudelft.nl/) projects.
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 2abdc419e98..9ea71551fc0 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -324,6 +324,11 @@ void sa11x0_set_irda_data(struct irda_platform_data *irda)
sa11x0ir_device.dev.platform_data = irda;
}
+static struct platform_device sa11x0rtc_device = {
+ .name = "sa1100-rtc",
+ .id = -1,
+};
+
static struct platform_device *sa11x0_devices[] __initdata = {
&sa11x0udc_device,
&sa11x0uart1_device,
@@ -333,6 +338,7 @@ static struct platform_device *sa11x0_devices[] __initdata = {
&sa11x0pcmcia_device,
&sa11x0fb_device,
&sa11x0mtd_device,
+ &sa11x0rtc_device,
};
static int __init sa1100_init(void)
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index eaaec90db97..c55b739e10b 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -239,6 +239,17 @@ config CPU_XSCALE
select CPU_CACHE_VIVT
select CPU_TLB_V4WBI
+# XScale Core Version 3
+config CPU_XSC3
+ bool
+ depends on ARCH_IXP23XX
+ default y
+ select CPU_32v5
+ select CPU_ABRT_EV5T
+ select CPU_CACHE_VIVT
+ select CPU_TLB_V4WBI
+ select IO_36
+
# ARMv6
config CPU_V6
bool "Support ARM V6 processor"
@@ -266,12 +277,18 @@ config CPU_32v6K
# This defines the compiler instruction set which depends on the machine type.
config CPU_32v3
bool
+ select TLS_REG_EMUL if SMP
+ select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
config CPU_32v4
bool
+ select TLS_REG_EMUL if SMP
+ select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
config CPU_32v5
bool
+ select TLS_REG_EMUL if SMP
+ select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
config CPU_32v6
bool
@@ -355,11 +372,17 @@ config CPU_TLB_V4WBI
config CPU_TLB_V6
bool
+#
+# CPU supports 36-bit I/O
+#
+config IO_36
+ bool
+
comment "Processor Features"
config ARM_THUMB
bool "Support Thumb user binaries"
- depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_V6
+ depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6
default y
help
Say Y if you want to include kernel support for running user space
@@ -417,7 +440,6 @@ config CPU_BPREDICT_DISABLE
config TLS_REG_EMUL
bool
- default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3)
help
An SMP system using a pre-ARMv6 processor (there are apparently
a few prototypes like that in existence) and therefore access to
@@ -436,7 +458,6 @@ config HAS_TLS_REG
config NEEDS_SYSCALL_FOR_CMPXCHG
bool
- default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3)
help
SMP on a pre-ARMv6 processor? Well OK then.
Forget about fast user space cmpxchg support.
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index ffe73ba2bf1..07a53850578 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_CPU_COPY_V4WB) += copypage-v4wb.o
obj-$(CONFIG_CPU_COPY_V6) += copypage-v6.o mmu.o
obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o
obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o
+obj-$(CONFIG_CPU_XSC3) += copypage-xsc3.o
obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o
obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o
@@ -51,4 +52,5 @@ obj-$(CONFIG_CPU_ARM1026) += proc-arm1026.o
obj-$(CONFIG_CPU_SA110) += proc-sa110.o
obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o
obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o
+obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o
obj-$(CONFIG_CPU_V6) += proc-v6.o
diff --git a/arch/arm/mm/copypage-xsc3.S b/arch/arm/mm/copypage-xsc3.S
new file mode 100644
index 00000000000..9a2cb4332b4
--- /dev/null
+++ b/arch/arm/mm/copypage-xsc3.S
@@ -0,0 +1,97 @@
+/*
+ * linux/arch/arm/lib/copypage-xsc3.S
+ *
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * 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.
+ *
+ * Adapted for 3rd gen XScale core, no more mini-dcache
+ * Author: Matt Gilbert (matthew.m.gilbert@intel.com)
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+
+/*
+ * General note:
+ * We don't really want write-allocate cache behaviour for these functions
+ * since that will just eat through 8K of the cache.
+ */
+
+ .text
+ .align 5
+/*
+ * XSC3 optimised copy_user_page
+ * r0 = destination
+ * r1 = source
+ * r2 = virtual user address of ultimate destination page
+ *
+ * The source page may have some clean entries in the cache already, but we
+ * can safely ignore them - break_cow() will flush them out of the cache
+ * if we eventually end up using our copied page.
+ *
+ */
+ENTRY(xsc3_mc_copy_user_page)
+ stmfd sp!, {r4, r5, lr}
+ mov lr, #PAGE_SZ/64-1
+
+ pld [r1, #0]
+ pld [r1, #32]
+1: pld [r1, #64]
+ pld [r1, #96]
+
+2: ldrd r2, [r1], #8
+ mov ip, r0
+ ldrd r4, [r1], #8
+ mcr p15, 0, ip, c7, c6, 1 @ invalidate
+ strd r2, [r0], #8
+ ldrd r2, [r1], #8
+ strd r4, [r0], #8
+ ldrd r4, [r1], #8
+ strd r2, [r0], #8
+ strd r4, [r0], #8
+ ldrd r2, [r1], #8
+ mov ip, r0
+ ldrd r4, [r1], #8
+ mcr p15, 0, ip, c7, c6, 1 @ invalidate
+ strd r2, [r0], #8
+ ldrd r2, [r1], #8
+ subs lr, lr, #1
+ strd r4, [r0], #8
+ ldrd r4, [r1], #8
+ strd r2, [r0], #8
+ strd r4, [r0], #8
+ bgt 1b
+ beq 2b
+
+ ldmfd sp!, {r4, r5, pc}
+
+ .align 5
+/*
+ * XScale optimised clear_user_page
+ * r0 = destination
+ * r1 = virtual user address of ultimate destination page
+ */
+ENTRY(xsc3_mc_clear_user_page)
+ mov r1, #PAGE_SZ/32
+ mov r2, #0
+ mov r3, #0
+1: mcr p15, 0, r0, c7, c6, 1 @ invalidate line
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ strd r2, [r0], #8
+ subs r1, r1, #1
+ bne 1b
+ mov pc, lr
+
+ __INITDATA
+
+ .type xsc3_mc_user_fns, #object
+ENTRY(xsc3_mc_user_fns)
+ .long xsc3_mc_clear_user_page
+ .long xsc3_mc_copy_user_page
+ .size xsc3_mc_user_fns, . - xsc3_mc_user_fns
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index ef8d30a185a..5e5d05bcad5 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -557,7 +557,8 @@ void __init create_mapping(struct map_desc *md)
* supersections are only allocated for domain 0 regardless
* of the actual domain assignments in use.
*/
- if (cpu_architecture() >= CPU_ARCH_ARMv6 && domain == 0) {
+ if ((cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())
+ && domain == 0) {
/*
* Align to supersection boundary if !high pages.
* High pages have already been checked for proper
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index 3aa80094012..959588884fa 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -29,6 +29,7 @@
#include <linux/init.h>
#include <asm/assembler.h>
#include <asm/asm-offsets.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index 767d158f211..be6d081ff2b 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -29,6 +29,7 @@
#include <linux/init.h>
#include <asm/assembler.h>
#include <asm/asm-offsets.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 6ca639094d6..f778545d57a 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <asm/assembler.h>
#include <asm/asm-offsets.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index 10317e4f55d..148c111fde7 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <asm/assembler.h>
#include <asm/asm-offsets.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
index 8e7e1e70ab0..540359b475d 100644
--- a/arch/arm/mm/proc-arm6_7.S
+++ b/arch/arm/mm/proc-arm6_7.S
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <asm/assembler.h>
#include <asm/asm-offsets.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index 471286fdf78..26f00ee2ad9 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -34,6 +34,7 @@
#include <linux/init.h>
#include <asm/assembler.h>
#include <asm/asm-offsets.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 950d3b664c1..a17f79e0199 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -28,6 +28,7 @@
#include <linux/config.h>
#include <linux/init.h>
#include <asm/assembler.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/page.h>
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index 410b032faa3..bbde4a024a4 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -29,6 +29,7 @@
#include <linux/config.h>
#include <linux/init.h>
#include <asm/assembler.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/page.h>
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index 6dd2be7cd05..224ce226a01 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -51,6 +51,7 @@
#include <linux/config.h>
#include <linux/init.h>
#include <asm/assembler.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/page.h>
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 022e8684204..4e2a087cf38 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -28,6 +28,7 @@
#include <linux/config.h>
#include <linux/init.h>
#include <asm/assembler.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include <asm/procinfo.h>
#include <asm/page.h>
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index bd330c4075a..c916a6cae40 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -18,6 +18,7 @@
#include <asm/asm-offsets.h>
#include <asm/procinfo.h>
#include <asm/hardware.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include <asm/ptrace.h>
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 91b89124c0d..41f21f2dd8f 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -23,6 +23,7 @@
#include <asm/asm-offsets.h>
#include <asm/procinfo.h>
#include <asm/hardware.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
/*
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 92f3ca31b7b..ee6f1529873 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -14,12 +14,21 @@
#include <asm/asm-offsets.h>
#include <asm/hardware/arm_scu.h>
#include <asm/procinfo.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include "proc-macros.S"
#define D_CACHE_LINE_SIZE 32
+#define TTB_C (1 << 0)
+#define TTB_S (1 << 1)
+#define TTB_IMP (1 << 2)
+#define TTB_RGN_NC (0 << 3)
+#define TTB_RGN_WBWA (1 << 3)
+#define TTB_RGN_WT (2 << 3)
+#define TTB_RGN_WB (3 << 3)
+
.macro cpsie, flags
.ifc \flags, f
.long 0xf1080040
@@ -114,7 +123,7 @@ ENTRY(cpu_v6_switch_mm)
mov r2, #0
ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
#ifdef CONFIG_SMP
- orr r0, r0, #2 @ set shared pgtable
+ orr r0, r0, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable
#endif
mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
mcr p15, 0, r2, c7, c10, 4 @ drain write buffer
@@ -160,8 +169,8 @@ ENTRY(cpu_v6_set_pte)
tst r1, #L_PTE_YOUNG
biceq r2, r2, #PTE_EXT_APX | PTE_EXT_AP_MASK
-@ tst r1, #L_PTE_EXEC
-@ orreq r2, r2, #PTE_EXT_XN
+ tst r1, #L_PTE_EXEC
+ orreq r2, r2, #PTE_EXT_XN
tst r1, #L_PTE_PRESENT
moveq r2, #0
@@ -220,7 +229,7 @@ __v6_setup:
mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
mcr p15, 0, r0, c2, c0, 2 @ TTB control register
#ifdef CONFIG_SMP
- orr r4, r4, #2 @ set shared pgtable
+ orr r4, r4, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable
#endif
mcr p15, 0, r4, c2, c0, 1 @ load TTB1
#ifdef CONFIG_VFP
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
new file mode 100644
index 00000000000..f90513e9af0
--- /dev/null
+++ b/arch/arm/mm/proc-xsc3.S
@@ -0,0 +1,498 @@
+/*
+ * linux/arch/arm/mm/proc-xsc3.S
+ *
+ * Original Author: Matthew Gilbert
+ * Current Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (C) Intel Corp.
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * MMU functions for the Intel XScale3 Core (XSC3). The XSC3 core is an
+ * extension to Intel's original XScale core that adds the following
+ * features:
+ *
+ * - ARMv6 Supersections
+ * - Low Locality Reference pages (replaces mini-cache)
+ * - 36-bit addressing
+ * - L2 cache
+ * - Cache-coherency if chipset supports it
+ *
+ * Based on orignal XScale code by Nicolas Pitre
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/procinfo.h>
+#include <asm/hardware.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include "proc-macros.S"
+
+/*
+ * This is the maximum size of an area which will be flushed. If the
+ * area is larger than this, then we flush the whole cache.
+ */
+#define MAX_AREA_SIZE 32768
+
+/*
+ * The cache line size of the I and D cache.
+ */
+#define CACHELINESIZE 32
+
+/*
+ * The size of the data cache.
+ */
+#define CACHESIZE 32768
+
+/*
+ * Run with L2 enabled.
+ */
+#define L2_CACHE_ENABLE 1
+
+/*
+ * Enable the Branch Target Buffer (can cause crashes, see erratum #42.)
+ */
+#define BTB_ENABLE 0
+
+/*
+ * This macro is used to wait for a CP15 write and is needed
+ * when we have to ensure that the last operation to the co-pro
+ * was completed before continuing with operation.
+ */
+ .macro cpwait_ret, lr, rd
+ mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15
+ sub pc, \lr, \rd, LSR #32 @ wait for completion and
+ @ flush instruction pipeline
+ .endm
+
+/*
+ * This macro cleans & invalidates the entire xsc3 dcache by set & way.
+ */
+
+ .macro clean_d_cache rd, rs
+ mov \rd, #0x1f00
+ orr \rd, \rd, #0x00e0
+1: mcr p15, 0, \rd, c7, c14, 2 @ clean/inv set/way
+ adds \rd, \rd, #0x40000000
+ bcc 1b
+ subs \rd, \rd, #0x20
+ bpl 1b
+ .endm
+
+ .text
+
+/*
+ * cpu_xsc3_proc_init()
+ *
+ * Nothing too exciting at the moment
+ */
+ENTRY(cpu_xsc3_proc_init)
+ mov pc, lr
+
+/*
+ * cpu_xsc3_proc_fin()
+ */
+ENTRY(cpu_xsc3_proc_fin)
+ str lr, [sp, #-4]!
+ mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
+ msr cpsr_c, r0
+ bl xsc3_flush_kern_cache_all @ clean caches
+ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
+ bic r0, r0, #0x1800 @ ...IZ...........
+ bic r0, r0, #0x0006 @ .............CA.
+ mcr p15, 0, r0, c1, c0, 0 @ disable caches
+ ldr pc, [sp], #4
+
+/*
+ * cpu_xsc3_reset(loc)
+ *
+ * Perform a soft reset of the system. Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * loc: location to jump to for soft reset
+ */
+ .align 5
+ENTRY(cpu_xsc3_reset)
+ mov r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
+ msr cpsr_c, r1 @ reset CPSR
+ mrc p15, 0, r1, c1, c0, 0 @ ctrl register
+ bic r1, r1, #0x0086 @ ........B....CA.
+ bic r1, r1, #0x3900 @ ..VIZ..S........
+ mcr p15, 0, r1, c1, c0, 0 @ ctrl register
+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches & BTB
+ bic r1, r1, #0x0001 @ ...............M
+ mcr p15, 0, r1, c1, c0, 0 @ ctrl register
+ @ CAUTION: MMU turned off from this point. We count on the pipeline
+ @ already containing those two last instructions to survive.
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ mov pc, r0
+
+/*
+ * cpu_xsc3_do_idle()
+ *
+ * Cause the processor to idle
+ *
+ * For now we do nothing but go to idle mode for every case
+ *
+ * XScale supports clock switching, but using idle mode support
+ * allows external hardware to react to system state changes.
+
+ MMG: Come back to this one.
+ */
+ .align 5
+
+ENTRY(cpu_xsc3_do_idle)
+ mov r0, #1
+ mcr p14, 0, r0, c7, c0, 0 @ Go to IDLE
+ mov pc, lr
+
+/* ================================= CACHE ================================ */
+
+/*
+ * flush_user_cache_all()
+ *
+ * Invalidate all cache entries in a particular address
+ * space.
+ */
+ENTRY(xsc3_flush_user_cache_all)
+ /* FALLTHROUGH */
+
+/*
+ * flush_kern_cache_all()
+ *
+ * Clean and invalidate the entire cache.
+ */
+ENTRY(xsc3_flush_kern_cache_all)
+ mov r2, #VM_EXEC
+ mov ip, #0
+__flush_whole_cache:
+ clean_d_cache r0, r1
+ tst r2, #VM_EXEC
+ mcrne p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
+ mcrne p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
+ mcrne p15, 0, ip, c7, c5, 4 @ Prefetch Flush
+ mov pc, lr
+
+/*
+ * flush_user_cache_range(start, end, vm_flags)
+ *
+ * Invalidate a range of cache entries in the specified
+ * address space.
+ *
+ * - start - start address (may not be aligned)
+ * - end - end address (exclusive, may not be aligned)
+ * - vma - vma_area_struct describing address space
+ */
+ .align 5
+ENTRY(xsc3_flush_user_cache_range)
+ mov ip, #0
+ sub r3, r1, r0 @ calculate total size
+ cmp r3, #MAX_AREA_SIZE
+ bhs __flush_whole_cache
+
+1: tst r2, #VM_EXEC
+ mcrne p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
+ mcr p15, 0, r0, c7, c14, 1 @ Clean/invalidate D cache line
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ tst r2, #VM_EXEC
+ mcrne p15, 0, ip, c7, c5, 6 @ Invalidate BTB
+ mcrne p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
+ mcrne p15, 0, ip, c7, c5, 4 @ Prefetch Flush
+ mov pc, lr
+
+/*
+ * coherent_kern_range(start, end)
+ *
+ * Ensure coherency between the Icache and the Dcache in the
+ * region described by start. If you have non-snooping
+ * Harvard caches, you need to implement this function.
+ *
+ * - start - virtual start address
+ * - end - virtual end address
+ *
+ * Note: single I-cache line invalidation isn't used here since
+ * it also trashes the mini I-cache used by JTAG debuggers.
+ */
+ENTRY(xsc3_coherent_kern_range)
+/* FALLTHROUGH */
+ENTRY(xsc3_coherent_user_range)
+ bic r0, r0, #CACHELINESIZE - 1
+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB
+ mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
+ mcr p15, 0, r0, c7, c5, 4 @ Prefetch Flush
+ mov pc, lr
+
+/*
+ * flush_kern_dcache_page(void *page)
+ *
+ * Ensure no D cache aliasing occurs, either with itself or
+ * the I cache
+ *
+ * - addr - page aligned address
+ */
+ENTRY(xsc3_flush_kern_dcache_page)
+ add r1, r0, #PAGE_SZ
+1: mcr p15, 0, r0, c7, c14, 1 @ Clean/Invalidate D Cache line
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB
+ mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
+ mcr p15, 0, r0, c7, c5, 4 @ Prefetch Flush
+ mov pc, lr
+
+/*
+ * dma_inv_range(start, end)
+ *
+ * Invalidate (discard) the specified virtual address range.
+ * May not write back any entries. If 'start' or 'end'
+ * are not cache line aligned, those lines must be written
+ * back.
+ *
+ * - start - virtual start address
+ * - end - virtual end address
+ */
+ENTRY(xsc3_dma_inv_range)
+ tst r0, #CACHELINESIZE - 1
+ bic r0, r0, #CACHELINESIZE - 1
+ mcrne p15, 0, r0, c7, c10, 1 @ clean L1 D entry
+ mcrne p15, 1, r0, c7, c11, 1 @ clean L2 D entry
+ tst r1, #CACHELINESIZE - 1
+ mcrne p15, 0, r1, c7, c10, 1 @ clean L1 D entry
+ mcrne p15, 1, r1, c7, c11, 1 @ clean L2 D entry
+1: mcr p15, 0, r0, c7, c6, 1 @ invalidate L1 D entry
+ mcr p15, 1, r0, c7, c7, 1 @ Invalidate L2 D cache line
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
+ mov pc, lr
+
+/*
+ * dma_clean_range(start, end)
+ *
+ * Clean the specified virtual address range.
+ *
+ * - start - virtual start address
+ * - end - virtual end address
+ */
+ENTRY(xsc3_dma_clean_range)
+ bic r0, r0, #CACHELINESIZE - 1
+1: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D entry
+ mcr p15, 1, r0, c7, c11, 1 @ clean L2 D entry
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
+ mov pc, lr
+
+/*
+ * dma_flush_range(start, end)
+ *
+ * Clean and invalidate the specified virtual address range.
+ *
+ * - start - virtual start address
+ * - end - virtual end address
+ */
+ENTRY(xsc3_dma_flush_range)
+ bic r0, r0, #CACHELINESIZE - 1
+1: mcr p15, 0, r0, c7, c14, 1 @ Clean/invalidate L1 D cache line
+ mcr p15, 1, r0, c7, c11, 1 @ Clean L2 D cache line
+ mcr p15, 1, r0, c7, c7, 1 @ Invalidate L2 D cache line
+ add r0, r0, #CACHELINESIZE
+ cmp r0, r1
+ blo 1b
+ mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
+ mov pc, lr
+
+ENTRY(xsc3_cache_fns)
+ .long xsc3_flush_kern_cache_all
+ .long xsc3_flush_user_cache_all
+ .long xsc3_flush_user_cache_range
+ .long xsc3_coherent_kern_range
+ .long xsc3_coherent_user_range
+ .long xsc3_flush_kern_dcache_page
+ .long xsc3_dma_inv_range
+ .long xsc3_dma_clean_range
+ .long xsc3_dma_flush_range
+
+ENTRY(cpu_xsc3_dcache_clean_area)
+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #CACHELINESIZE
+ subs r1, r1, #CACHELINESIZE
+ bhi 1b
+ mov pc, lr
+
+/* =============================== PageTable ============================== */
+
+/*
+ * cpu_xsc3_switch_mm(pgd)
+ *
+ * Set the translation base pointer to be as described by pgd.
+ *
+ * pgd: new page tables
+ */
+ .align 5
+ENTRY(cpu_xsc3_switch_mm)
+ clean_d_cache r1, r2
+ mcr p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
+ mcr p15, 0, ip, c7, c5, 4 @ Prefetch Flush
+#ifdef L2_CACHE_ENABLE
+ orr r0, r0, #0x18 @ cache the page table in L2
+#endif
+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ cpwait_ret lr, ip
+
+/*
+ * cpu_xsc3_set_pte(ptep, pte)
+ *
+ * Set a PTE and flush it out
+ *
+ */
+ .align 5
+ENTRY(cpu_xsc3_set_pte)
+ str r1, [r0], #-2048 @ linux version
+
+ bic r2, r1, #0xff0
+ orr r2, r2, #PTE_TYPE_EXT @ extended page
+
+ eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
+
+ tst r3, #L_PTE_USER @ User?
+ orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w
+
+ tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty?
+ orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w
+ @ combined with user -> user r/w
+
+#if L2_CACHE_ENABLE
+ @ If its cacheable it needs to be in L2 also.
+ eor ip, r1, #L_PTE_CACHEABLE
+ tst ip, #L_PTE_CACHEABLE
+ orreq r2, r2, #PTE_EXT_TEX(0x5)
+#endif
+
+ tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young?
+ movne r2, #0 @ no -> fault
+
+ str r2, [r0] @ hardware version
+ mov ip, #0
+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line mcr
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
+ mov pc, lr
+
+ .ltorg
+
+ .align
+
+ __INIT
+
+ .type __xsc3_setup, #function
+__xsc3_setup:
+ mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
+ msr cpsr_c, r0
+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB
+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
+ mcr p15, 0, ip, c7, c5, 4 @ Prefetch Flush
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs
+#if L2_CACHE_ENABLE
+ orr r4, r4, #0x18 @ cache the page table in L2
+#endif
+ mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
+ mov r0, #1 @ Allow access to CP0 and CP13
+ orr r0, r0, #1 << 13 @ Its undefined whether this
+ mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes
+ mrc p15, 0, r0, c1, c0, 1 @ get auxiliary control reg
+ and r0, r0, #2 @ preserve bit P bit setting
+#if L2_CACHE_ENABLE
+ orr r0, r0, #(1 << 10) @ enable L2 for LLR cache
+#endif
+ mcr p15, 0, r0, c1, c0, 1 @ set auxiliary control reg
+ mrc p15, 0, r0, c1, c0, 0 @ get control register
+ bic r0, r0, #0x0200 @ .... ..R. .... ....
+ bic r0, r0, #0x0002 @ .... .... .... ..A.
+ orr r0, r0, #0x0005 @ .... .... .... .C.M
+#if BTB_ENABLE
+ orr r0, r0, #0x3900 @ ..VI Z..S .... ....
+#else
+ orr r0, r0, #0x3100 @ ..VI ...S .... ....
+#endif
+#if L2_CACHE_ENABLE
+ orr r0, r0, #0x4000000 @ L2 enable
+#endif
+ mov pc, lr
+
+ .size __xsc3_setup, . - __xsc3_setup
+
+ __INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ * come through these
+ */
+
+ .type xsc3_processor_functions, #object
+ENTRY(xsc3_processor_functions)
+ .word v5t_early_abort
+ .word cpu_xsc3_proc_init
+ .word cpu_xsc3_proc_fin
+ .word cpu_xsc3_reset
+ .word cpu_xsc3_do_idle
+ .word cpu_xsc3_dcache_clean_area
+ .word cpu_xsc3_switch_mm
+ .word cpu_xsc3_set_pte
+ .size xsc3_processor_functions, . - xsc3_processor_functions
+
+ .section ".rodata"
+
+ .type cpu_arch_name, #object
+cpu_arch_name:
+ .asciz "armv5te"
+ .size cpu_arch_name, . - cpu_arch_name
+
+ .type cpu_elf_name, #object
+cpu_elf_name:
+ .asciz "v5"
+ .size cpu_elf_name, . - cpu_elf_name
+
+ .type cpu_xsc3_name, #object
+cpu_xsc3_name:
+ .asciz "XScale-Core3"
+ .size cpu_xsc3_name, . - cpu_xsc3_name
+
+ .align
+
+ .section ".proc.info.init", #alloc, #execinstr
+
+ .type __xsc3_proc_info,#object
+__xsc3_proc_info:
+ .long 0x69056000
+ .long 0xffffe000
+ .long 0x00000c0e
+ b __xsc3_setup
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+ .long cpu_xsc3_name
+ .long xsc3_processor_functions
+ .long v4wbi_tlb_fns
+ .long xsc3_mc_user_fns
+ .long xsc3_cache_fns
+ .size __xsc3_proc_info, . - __xsc3_proc_info
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index b50f87a0ee7..29bcc4dd651 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -25,6 +25,7 @@
#include <asm/assembler.h>
#include <asm/procinfo.h>
#include <asm/pgtable.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/page.h>
#include <asm/ptrace.h>
#include "proc-macros.S"
diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
index 9ab1abfbe7a..7b595547c1c 100644
--- a/arch/arm/vfp/entry.S
+++ b/arch/arm/vfp/entry.S
@@ -18,6 +18,7 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
#include <asm/vfpmacros.h>
.globl do_vfp
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index de4ca1223c5..b7ed57e00cd 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -102,7 +102,6 @@ vfp_support_entry:
VFPFMRX r8, FPINST2, NE @ FPINST2 if needed - avoids reading
@ nonexistant reg on rev0
VFPFSTMIA r4 @ save the working registers
- add r4, r4, #8*16+4
stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2
@ and point r4 at the word at the
@ start of the register dump
@@ -111,10 +110,9 @@ no_old_VFP_process:
DBGSTR1 "load state %p", r10
str r10, [r3] @ update the last_VFP_context pointer
@ Load the saved state back into the VFP
- add r4, r10, #8*16+4
- ldmia r4, {r1, r5, r6, r8} @ load FPEXC, FPSCR, FPINST, FPINST2
VFPFLDMIA r10 @ reload the working registers while
@ FPEXC is in a safe state
+ ldmia r10, {r1, r5, r6, r8} @ load FPEXC, FPSCR, FPINST, FPINST2
tst r1, #FPEXC_FPV2 @ is there an FPINST2 to write?
VFPFMXR FPINST2, r8, NE @ FPINST2 if needed - avoids writing
@ nonexistant reg on rev0
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index dee23d87fc5..cf4ebf4c274 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -41,6 +41,10 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/arm26/Makefile b/arch/arm26/Makefile
index 844a9e46886..fe91eda98a9 100644
--- a/arch/arm26/Makefile
+++ b/arch/arm26/Makefile
@@ -1,6 +1,9 @@
#
# arch/arm26/Makefile
#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
@@ -49,9 +52,9 @@ all: zImage
boot := arch/arm26/boot
-.PHONY: maketools FORCE
+PHONY += maketools FORCE
maketools: FORCE
-
+
# Convert bzImage to zImage
bzImage: vmlinux
diff --git a/arch/arm26/boot/Makefile b/arch/arm26/boot/Makefile
index b5c2277654d..68acb7b0d47 100644
--- a/arch/arm26/boot/Makefile
+++ b/arch/arm26/boot/Makefile
@@ -1,6 +1,9 @@
#
# arch/arm26/boot/Makefile
#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
@@ -60,7 +63,7 @@ $(obj)/xipImage: vmlinux FORCE
@echo ' Kernel: $@ is ready'
endif
-.PHONY: initrd
+PHONY += initrd
initrd:
@test "$(INITRD_PHYS)" != "" || \
(echo This machine does not support INITRD; exit -1)
diff --git a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c
index 5847ea5d774..a79de041b50 100644
--- a/arch/arm26/kernel/traps.c
+++ b/arch/arm26/kernel/traps.c
@@ -34,7 +34,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include "ptrace.h"
@@ -207,19 +207,19 @@ void die_if_kernel(const char *str, struct pt_regs *regs, int err)
die(str, regs, err);
}
-static DECLARE_MUTEX(undef_sem);
+static DEFINE_MUTEX(undef_mutex);
static int (*undef_hook)(struct pt_regs *);
int request_undef_hook(int (*fn)(struct pt_regs *))
{
int ret = -EBUSY;
- down(&undef_sem);
+ mutex_lock(&undef_mutex);
if (undef_hook == NULL) {
undef_hook = fn;
ret = 0;
}
- up(&undef_sem);
+ mutex_unlock(&undef_mutex);
return ret;
}
@@ -228,12 +228,12 @@ int release_undef_hook(int (*fn)(struct pt_regs *))
{
int ret = -EINVAL;
- down(&undef_sem);
+ mutex_lock(&undef_mutex);
if (undef_hook == fn) {
undef_hook = NULL;
ret = 0;
}
- up(&undef_sem);
+ mutex_unlock(&undef_mutex);
return ret;
}
diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c
index e3ecaa45374..7da8a520567 100644
--- a/arch/arm26/mm/init.c
+++ b/arch/arm26/mm/init.c
@@ -23,6 +23,7 @@
#include <linux/initrd.h>
#include <linux/bootmem.h>
#include <linux/blkdev.h>
+#include <linux/pfn.h>
#include <asm/segment.h>
#include <asm/mach-types.h>
@@ -101,12 +102,6 @@ struct node_info {
int bootmap_pages;
};
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT)
-#define PFN_SIZE(x) ((x) >> PAGE_SHIFT)
-#define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \
- (((unsigned long)(s)) & PAGE_MASK))
-
/*
* FIXME: We really want to avoid allocating the bootmap bitmap
* over the top of the initrd. Hopefully, this is located towards
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index b8326194973..856b665020e 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -16,6 +16,14 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
index 1ba57efff60..619a6eefd89 100644
--- a/arch/cris/kernel/setup.c
+++ b/arch/cris/kernel/setup.c
@@ -18,6 +18,7 @@
#include <linux/seq_file.h>
#include <linux/tty.h>
#include <linux/utsname.h>
+#include <linux/pfn.h>
#include <asm/setup.h>
@@ -88,10 +89,6 @@ setup_arch(char **cmdline_p)
init_mm.end_data = (unsigned long) &_edata;
init_mm.brk = (unsigned long) &_end;
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
-
/* min_low_pfn points to the start of DRAM, start_pfn points
* to the first DRAM pages after the kernel, and max_low_pfn
* to the end of DRAM.
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index e0838371237..95a3892b8d1 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -17,6 +17,10 @@ config GENERIC_FIND_NEXT_BIT
bool
default y
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default n
diff --git a/arch/frv/mm/mmu-context.c b/arch/frv/mm/mmu-context.c
index f2c6866fc88..1530a4111e6 100644
--- a/arch/frv/mm/mmu-context.c
+++ b/arch/frv/mm/mmu-context.c
@@ -54,9 +54,9 @@ static unsigned get_cxn(mm_context_t *ctx)
/* find the first unallocated context number
* - 0 is reserved for the kernel
*/
- cxn = find_next_zero_bit(&cxn_bitmap, NR_CXN, 1);
+ cxn = find_next_zero_bit(cxn_bitmap, NR_CXN, 1);
if (cxn < NR_CXN) {
- set_bit(cxn, &cxn_bitmap);
+ set_bit(cxn, cxn_bitmap);
}
else {
/* none remaining - need to steal someone else's cxn */
@@ -138,7 +138,7 @@ void destroy_context(struct mm_struct *mm)
cxn_pinned = -1;
list_del_init(&ctx->id_link);
- clear_bit(ctx->id, &cxn_bitmap);
+ clear_bit(ctx->id, cxn_bitmap);
__flush_tlb_mm(ctx->id);
ctx->id = 0;
}
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 98308b018a3..cabf0bfffc5 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -29,6 +29,14 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default n
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index bfea1bedcbf..f17bd1d2707 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -37,6 +37,10 @@ config GENERIC_IOMAP
bool
default y
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config ARCH_MAY_HAVE_PC_FDC
bool
default y
@@ -227,6 +231,15 @@ config SCHED_SMT
cost of slightly increased overhead in some places. If unsure say
N here.
+config SCHED_MC
+ bool "Multi-core scheduler support"
+ depends on SMP
+ default y
+ help
+ Multi-core scheduler support improves the CPU scheduler's decision
+ making when dealing with multi-core CPU chips at a cost of slightly
+ increased overhead in some places. If unsure say N here.
+
source "kernel/Kconfig.preempt"
config X86_UP_APIC
@@ -737,7 +750,7 @@ config PHYSICAL_START
config HOTPLUG_CPU
bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
- depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER
+ depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER && !X86_PC
---help---
Say Y here to experiment with turning CPUs off and on. CPUs
can be controlled through /sys/devices/system/cpu.
diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
index 00108ba9a78..6e97df6979e 100644
--- a/arch/i386/Kconfig.debug
+++ b/arch/i386/Kconfig.debug
@@ -44,8 +44,8 @@ comment "Page alloc debug is incompatible with Software Suspend on i386"
depends on DEBUG_KERNEL && SOFTWARE_SUSPEND
config DEBUG_PAGEALLOC
- bool "Page alloc debugging"
- depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND
+ bool "Debug page memory allocations"
+ depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND && !HUGETLBFS
help
Unmap pages from the kernel linear mapping after free_pages().
This results in a large slowdown, but helps to find certain types
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 36bef6543ac..3e4adb1e224 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -39,6 +39,9 @@ include $(srctree)/arch/i386/Makefile.cpu
cflags-$(CONFIG_REGPARM) += -mregparm=3
+# temporary until string.h is fixed
+cflags-y += -ffreestanding
+
# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
# a lot more stack due to the lack of sharing of stacklots:
CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;)
@@ -99,8 +102,8 @@ AFLAGS += $(mflags-y)
boot := arch/i386/boot
-.PHONY: zImage bzImage compressed zlilo bzlilo \
- zdisk bzdisk fdimage fdimage144 fdimage288 install
+PHONY += zImage bzImage compressed zlilo bzlilo \
+ zdisk bzdisk fdimage fdimage144 fdimage288 isoimage install
all: bzImage
@@ -119,7 +122,7 @@ zlilo bzlilo: vmlinux
zdisk bzdisk: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zdisk
-fdimage fdimage144 fdimage288: vmlinux
+fdimage fdimage144 fdimage288 isoimage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
install:
@@ -136,6 +139,9 @@ define archhelp
echo ' install to $$(INSTALL_PATH) and run lilo'
echo ' bzdisk - Create a boot floppy in /dev/fd0'
echo ' fdimage - Create a boot floppy image'
+ echo ' isoimage - Create a boot CD-ROM image'
endef
-CLEAN_FILES += arch/$(ARCH)/boot/fdimage arch/$(ARCH)/boot/mtools.conf
+CLEAN_FILES += arch/$(ARCH)/boot/fdimage \
+ arch/$(ARCH)/boot/image.iso \
+ arch/$(ARCH)/boot/mtools.conf
diff --git a/arch/i386/Makefile.cpu b/arch/i386/Makefile.cpu
index dcd936ef45d..a11befba26d 100644
--- a/arch/i386/Makefile.cpu
+++ b/arch/i386/Makefile.cpu
@@ -39,3 +39,7 @@ cflags-$(CONFIG_X86_ELAN) += -march=i486
# Geode GX1 support
cflags-$(CONFIG_MGEODEGX1) += -march=pentium-mmx
+# add at the end to overwrite eventual tuning options from earlier
+# cpu entries
+cflags-$(CONFIG_X86_GENERIC) += $(call tune,generic)
+
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
index f136752563b..33e55476381 100644
--- a/arch/i386/boot/Makefile
+++ b/arch/i386/boot/Makefile
@@ -62,8 +62,12 @@ $(obj)/setup $(obj)/bootsect: %: %.o FORCE
$(obj)/compressed/vmlinux: FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@
-# Set this if you want to pass append arguments to the zdisk/fdimage kernel
+# Set this if you want to pass append arguments to the zdisk/fdimage/isoimage kernel
FDARGS =
+# Set this if you want an initrd included with the zdisk/fdimage/isoimage kernel
+FDINITRD =
+
+image_cmdline = default linux $(FDARGS) $(if $(FDINITRD),initrd=initrd.img,)
$(obj)/mtools.conf: $(src)/mtools.conf.in
sed -e 's|@OBJ@|$(obj)|g' < $< > $@
@@ -72,8 +76,11 @@ $(obj)/mtools.conf: $(src)/mtools.conf.in
zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync
syslinux /dev/fd0 ; sync
- echo 'default linux $(FDARGS)' | \
+ echo '$(image_cmdline)' | \
MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg
+ if [ -f '$(FDINITRD)' ] ; then \
+ MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' a:initrd.img ; \
+ fi
MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync
# These require being root or having syslinux 2.02 or higher installed
@@ -81,18 +88,39 @@ fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync
syslinux $(obj)/fdimage ; sync
- echo 'default linux $(FDARGS)' | \
+ echo '$(image_cmdline)' | \
MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg
+ if [ -f '$(FDINITRD)' ] ; then \
+ MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' v:initrd.img ; \
+ fi
MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync
fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync
syslinux $(obj)/fdimage ; sync
- echo 'default linux $(FDARGS)' | \
+ echo '$(image_cmdline)' | \
MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg
+ if [ -f '$(FDINITRD)' ] ; then \
+ MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' w:initrd.img ; \
+ fi
MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync
+isoimage: $(BOOTIMAGE)
+ -rm -rf $(obj)/isoimage
+ mkdir $(obj)/isoimage
+ cp `echo /usr/lib*/syslinux/isolinux.bin | awk '{ print $1; }'` \
+ $(obj)/isoimage
+ cp $(BOOTIMAGE) $(obj)/isoimage/linux
+ echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg
+ if [ -f '$(FDINITRD)' ] ; then \
+ cp '$(FDINITRD)' $(obj)/isoimage/initrd.img ; \
+ fi
+ mkisofs -J -r -o $(obj)/image.iso -b isolinux.bin -c boot.cat \
+ -no-emul-boot -boot-load-size 4 -boot-info-table \
+ $(obj)/isoimage
+ rm -rf $(obj)/isoimage
+
zlilo: $(BOOTIMAGE)
if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
diff --git a/arch/i386/boot/edd.S b/arch/i386/boot/edd.S
index d8d69f2b911..4b84ea216f2 100644
--- a/arch/i386/boot/edd.S
+++ b/arch/i386/boot/edd.S
@@ -76,6 +76,8 @@ edd_mbr_sig_read:
popw %es
popw %bx
jc edd_mbr_sig_done # on failure, we're done.
+ cmpb $0, %ah # some BIOSes do not set CF
+ jne edd_mbr_sig_done # on failure, we're done.
movl (EDDBUF+EDD_MBR_SIG_OFFSET), %eax # read sig out of the MBR
movl %eax, (%bx) # store success
incb (EDD_MBR_SIG_NR_BUF) # note that we stored something
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
index 2ac40c8244c..0000a267453 100644
--- a/arch/i386/boot/video.S
+++ b/arch/i386/boot/video.S
@@ -1924,6 +1924,7 @@ skip10: movb %ah, %al
ret
store_edid:
+#ifdef CONFIG_FB_FIRMWARE_EDID
pushw %es # just save all registers
pushw %ax
pushw %bx
@@ -1954,6 +1955,7 @@ store_edid:
popw %bx
popw %ax
popw %es
+#endif
ret
# VIDEO_SELECT-only variables
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index f1a21945963..033066176b3 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -668,10 +668,10 @@ unsigned long __init acpi_find_rsdp(void)
unsigned long rsdp_phys = 0;
if (efi_enabled) {
- if (efi.acpi20)
- return __pa(efi.acpi20);
- else if (efi.acpi)
- return __pa(efi.acpi);
+ if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
+ return efi.acpi20;
+ else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
+ return efi.acpi;
}
/*
* Scan memory looking for the RSDP signature. First search EBDA (low
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 7e3d6b6a4e9..a06a49075f1 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -266,7 +266,7 @@ static void __init early_cpu_detect(void)
void __cpuinit generic_identify(struct cpuinfo_x86 * c)
{
u32 tfms, xlvl;
- int junk;
+ int ebx;
if (have_cpuid_p()) {
/* Get vendor name */
@@ -282,7 +282,7 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c)
/* Intel-defined flags: level 0x00000001 */
if ( c->cpuid_level >= 0x00000001 ) {
u32 capability, excap;
- cpuid(0x00000001, &tfms, &junk, &excap, &capability);
+ cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
c->x86_capability[0] = capability;
c->x86_capability[4] = excap;
c->x86 = (tfms >> 8) & 15;
@@ -292,6 +292,11 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c)
if (c->x86 >= 0x6)
c->x86_model += ((tfms >> 16) & 0xF) << 4;
c->x86_mask = tfms & 15;
+#ifdef CONFIG_SMP
+ c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
+#else
+ c->apicid = (ebx >> 24) & 0xFF;
+#endif
} else {
/* Have CPUID level 0 only - unheard of */
c->x86 = 4;
@@ -474,7 +479,6 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
cpuid(1, &eax, &ebx, &ecx, &edx);
- c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
return;
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index 26892d2099b..e44a4c6a4fe 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -96,7 +96,6 @@ config X86_POWERNOW_K8_ACPI
config X86_GX_SUSPMOD
tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
- depends on PCI
help
This add the CPUFreq driver for NatSemi Geode processors which
support suspend modulation.
@@ -115,9 +114,9 @@ config X86_SPEEDSTEP_CENTRINO
you also need to say Y to "Use ACPI tables to decode..." below
[which might imply enabling ACPI] if you want to use this driver
on non-Banias CPUs.
-
+
For details, take a look at <file:Documentation/cpu-freq/>.
-
+
If in doubt, say N.
config X86_SPEEDSTEP_CENTRINO_ACPI
@@ -148,7 +147,7 @@ config X86_SPEEDSTEP_ICH
help
This adds the CPUFreq driver for certain mobile Intel Pentium III
(Coppermine), all mobile Intel Pentium III-M (Tualatin) and all
- mobile Intel Pentium 4 P4-M on systems which have an Intel ICH2,
+ mobile Intel Pentium 4 P4-M on systems which have an Intel ICH2,
ICH3 or ICH4 southbridge.
For details, take a look at <file:Documentation/cpu-freq/>.
@@ -161,7 +160,7 @@ config X86_SPEEDSTEP_SMI
depends on EXPERIMENTAL
help
This adds the CPUFreq driver for certain mobile Intel Pentium III
- (Coppermine), all mobile Intel Pentium III-M (Tualatin)
+ (Coppermine), all mobile Intel Pentium III-M (Tualatin)
on systems which have an Intel 440BX/ZX/MX southbridge.
For details, take a look at <file:Documentation/cpu-freq/>.
@@ -203,9 +202,10 @@ config X86_LONGRUN
config X86_LONGHAUL
tristate "VIA Cyrix III Longhaul"
select CPU_FREQ_TABLE
+ depends on BROKEN
help
- This adds the CPUFreq driver for VIA Samuel/CyrixIII,
- VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T
+ This adds the CPUFreq driver for VIA Samuel/CyrixIII,
+ VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T
processors.
For details, take a look at <file:Documentation/cpu-freq/>.
@@ -215,11 +215,11 @@ config X86_LONGHAUL
comment "shared options"
config X86_ACPI_CPUFREQ_PROC_INTF
- bool "/proc/acpi/processor/../performance interface (deprecated)"
+ bool "/proc/acpi/processor/../performance interface (deprecated)"
depends on PROC_FS
depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
help
- This enables the deprecated /proc/acpi/processor/../performance
+ This enables the deprecated /proc/acpi/processor/../performance
interface. While it is helpful for debugging, the generic,
cross-architecture cpufreq interfaces should be used.
@@ -233,9 +233,9 @@ config X86_SPEEDSTEP_RELAXED_CAP_CHECK
bool "Relaxed speedstep capability checks"
depends on (X86_SPEEDSTEP_SMI || X86_SPEEDSTEP_ICH)
help
- Don't perform all checks for a speedstep capable system which would
- normally be done. Some ancient or strange systems, though speedstep
- capable, don't always indicate that they are speedstep capable. This
+ Don't perform all checks for a speedstep capable system which would
+ normally be done. Some ancient or strange systems, though speedstep
+ capable, don't always indicate that they are speedstep capable. This
option lets the probing code bypass some of those checks if the
parameter "relaxed_check=1" is passed to the module.
diff --git a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
index 2b62dee35c6..f275e0d4aee 100644
--- a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
+++ b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
@@ -39,7 +39,7 @@ static struct pci_dev *nforce2_chipset_dev;
static int fid = 0;
/* min_fsb, max_fsb:
- * minimum and maximum FSB (= FSB at boot time)
+ * minimum and maximum FSB (= FSB at boot time)
*/
static int min_fsb = 0;
static int max_fsb = 0;
@@ -57,10 +57,10 @@ MODULE_PARM_DESC(min_fsb,
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "cpufreq-nforce2", msg)
-/*
+/**
* nforce2_calc_fsb - calculate FSB
* @pll: PLL value
- *
+ *
* Calculates FSB from PLL value
*/
static int nforce2_calc_fsb(int pll)
@@ -76,10 +76,10 @@ static int nforce2_calc_fsb(int pll)
return 0;
}
-/*
+/**
* nforce2_calc_pll - calculate PLL value
* @fsb: FSB
- *
+ *
* Calculate PLL value for given FSB
*/
static int nforce2_calc_pll(unsigned int fsb)
@@ -106,10 +106,10 @@ static int nforce2_calc_pll(unsigned int fsb)
return NFORCE2_PLL(mul, div);
}
-/*
+/**
* nforce2_write_pll - write PLL value to chipset
* @pll: PLL value
- *
+ *
* Writes new FSB PLL value to chipset
*/
static void nforce2_write_pll(int pll)
@@ -121,15 +121,13 @@ static void nforce2_write_pll(int pll)
pci_write_config_dword(nforce2_chipset_dev, NFORCE2_PLLADR, temp);
/* Now write the value in all 64 registers */
- for (temp = 0; temp <= 0x3f; temp++) {
- pci_write_config_dword(nforce2_chipset_dev,
- NFORCE2_PLLREG, pll);
- }
+ for (temp = 0; temp <= 0x3f; temp++)
+ pci_write_config_dword(nforce2_chipset_dev, NFORCE2_PLLREG, pll);
return;
}
-/*
+/**
* nforce2_fsb_read - Read FSB
*
* Read FSB from chipset
@@ -140,39 +138,32 @@ static unsigned int nforce2_fsb_read(int bootfsb)
struct pci_dev *nforce2_sub5;
u32 fsb, temp = 0;
-
/* Get chipset boot FSB from subdevice 5 (FSB at boot-time) */
nforce2_sub5 = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
- 0x01EF,
- PCI_ANY_ID,
- PCI_ANY_ID,
- NULL);
-
+ 0x01EF,PCI_ANY_ID,PCI_ANY_ID,NULL);
if (!nforce2_sub5)
return 0;
pci_read_config_dword(nforce2_sub5, NFORCE2_BOOTFSB, &fsb);
fsb /= 1000000;
-
+
/* Check if PLL register is already set */
- pci_read_config_byte(nforce2_chipset_dev,
- NFORCE2_PLLENABLE, (u8 *)&temp);
-
+ pci_read_config_byte(nforce2_chipset_dev,NFORCE2_PLLENABLE, (u8 *)&temp);
+
if(bootfsb || !temp)
return fsb;
/* Use PLL register FSB value */
- pci_read_config_dword(nforce2_chipset_dev,
- NFORCE2_PLLREG, &temp);
+ pci_read_config_dword(nforce2_chipset_dev,NFORCE2_PLLREG, &temp);
fsb = nforce2_calc_fsb(temp);
return fsb;
}
-/*
+/**
* nforce2_set_fsb - set new FSB
* @fsb: New FSB
- *
+ *
* Sets new FSB
*/
static int nforce2_set_fsb(unsigned int fsb)
@@ -186,7 +177,7 @@ static int nforce2_set_fsb(unsigned int fsb)
printk(KERN_ERR "cpufreq: FSB %d is out of range!\n", fsb);
return -EINVAL;
}
-
+
tfsb = nforce2_fsb_read(0);
if (!tfsb) {
printk(KERN_ERR "cpufreq: Error while reading the FSB\n");
@@ -194,8 +185,7 @@ static int nforce2_set_fsb(unsigned int fsb)
}
/* First write? Then set actual value */
- pci_read_config_byte(nforce2_chipset_dev,
- NFORCE2_PLLENABLE, (u8 *)&temp);
+ pci_read_config_byte(nforce2_chipset_dev,NFORCE2_PLLENABLE, (u8 *)&temp);
if (!temp) {
pll = nforce2_calc_pll(tfsb);
@@ -223,7 +213,7 @@ static int nforce2_set_fsb(unsigned int fsb)
/* Calculate the PLL reg. value */
if ((pll = nforce2_calc_pll(tfsb)) == -1)
return -EINVAL;
-
+
nforce2_write_pll(pll);
#ifdef NFORCE2_DELAY
mdelay(NFORCE2_DELAY);
@@ -239,7 +229,7 @@ static int nforce2_set_fsb(unsigned int fsb)
/**
* nforce2_get - get the CPU frequency
* @cpu: CPU number
- *
+ *
* Returns the CPU frequency
*/
static unsigned int nforce2_get(unsigned int cpu)
@@ -354,10 +344,10 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy)
printk(KERN_INFO "cpufreq: FSB currently at %i MHz, FID %d.%d\n", fsb,
fid / 10, fid % 10);
-
+
/* Set maximum FSB to FSB at boot time */
max_fsb = nforce2_fsb_read(1);
-
+
if(!max_fsb)
return -EIO;
@@ -398,17 +388,15 @@ static struct cpufreq_driver nforce2_driver = {
* nforce2_detect_chipset - detect the Southbridge which contains FSB PLL logic
*
* Detects nForce2 A2 and C1 stepping
- *
+ *
*/
static unsigned int nforce2_detect_chipset(void)
{
u8 revision;
nforce2_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
- PCI_DEVICE_ID_NVIDIA_NFORCE2,
- PCI_ANY_ID,
- PCI_ANY_ID,
- NULL);
+ PCI_DEVICE_ID_NVIDIA_NFORCE2,
+ PCI_ANY_ID, PCI_ANY_ID, NULL);
if (nforce2_chipset_dev == NULL)
return -ENODEV;
diff --git a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c
index 3f7caa4ae6d..f317276afa7 100644
--- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c
@@ -1,16 +1,16 @@
/*
- * elanfreq: cpufreq driver for the AMD ELAN family
+ * elanfreq: cpufreq driver for the AMD ELAN family
*
* (c) Copyright 2002 Robert Schwebel <r.schwebel@pengutronix.de>
*
- * Parts of this code are (c) Sven Geggus <sven@geggus.net>
+ * Parts of this code are (c) Sven Geggus <sven@geggus.net>
*
- * All Rights Reserved.
+ * All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
+ * 2 of the License, or (at your option) any later version.
*
* 2002-02-13: - initial revision for 2.4.18-pre9 by Robert Schwebel
*
@@ -28,7 +28,7 @@
#include <asm/timex.h>
#include <asm/io.h>
-#define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */
+#define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */
#define REG_CSCDR 0x23 /* Chip Setup and Control Data Register */
/* Module parameter */
@@ -41,7 +41,7 @@ struct s_elan_multiplier {
};
/*
- * It is important that the frequencies
+ * It is important that the frequencies
* are listed in ascending order here!
*/
struct s_elan_multiplier elan_multiplier[] = {
@@ -72,78 +72,79 @@ static struct cpufreq_frequency_table elanfreq_table[] = {
* elanfreq_get_cpu_frequency: determine current cpu speed
*
* Finds out at which frequency the CPU of the Elan SOC runs
- * at the moment. Frequencies from 1 to 33 MHz are generated
+ * at the moment. Frequencies from 1 to 33 MHz are generated
* the normal way, 66 and 99 MHz are called "Hyperspeed Mode"
- * and have the rest of the chip running with 33 MHz.
+ * and have the rest of the chip running with 33 MHz.
*/
static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu)
{
- u8 clockspeed_reg; /* Clock Speed Register */
-
+ u8 clockspeed_reg; /* Clock Speed Register */
+
local_irq_disable();
- outb_p(0x80,REG_CSCIR);
- clockspeed_reg = inb_p(REG_CSCDR);
+ outb_p(0x80,REG_CSCIR);
+ clockspeed_reg = inb_p(REG_CSCDR);
local_irq_enable();
- if ((clockspeed_reg & 0xE0) == 0xE0) { return 0; }
+ if ((clockspeed_reg & 0xE0) == 0xE0)
+ return 0;
- /* Are we in CPU clock multiplied mode (66/99 MHz)? */
- if ((clockspeed_reg & 0xE0) == 0xC0) {
- if ((clockspeed_reg & 0x01) == 0) {
+ /* Are we in CPU clock multiplied mode (66/99 MHz)? */
+ if ((clockspeed_reg & 0xE0) == 0xC0) {
+ if ((clockspeed_reg & 0x01) == 0)
return 66000;
- } else {
- return 99000;
- }
- }
+ else
+ return 99000;
+ }
/* 33 MHz is not 32 MHz... */
if ((clockspeed_reg & 0xE0)==0xA0)
return 33000;
- return ((1<<((clockspeed_reg & 0xE0) >> 5)) * 1000);
+ return ((1<<((clockspeed_reg & 0xE0) >> 5)) * 1000);
}
/**
- * elanfreq_set_cpu_frequency: Change the CPU core frequency
- * @cpu: cpu number
+ * elanfreq_set_cpu_frequency: Change the CPU core frequency
+ * @cpu: cpu number
* @freq: frequency in kHz
*
- * This function takes a frequency value and changes the CPU frequency
+ * This function takes a frequency value and changes the CPU frequency
* according to this. Note that the frequency has to be checked by
* elanfreq_validatespeed() for correctness!
- *
- * There is no return value.
+ *
+ * There is no return value.
*/
-static void elanfreq_set_cpu_state (unsigned int state) {
-
+static void elanfreq_set_cpu_state (unsigned int state)
+{
struct cpufreq_freqs freqs;
freqs.old = elanfreq_get_cpu_frequency(0);
freqs.new = elan_multiplier[state].clock;
freqs.cpu = 0; /* elanfreq.c is UP only driver */
-
+
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- printk(KERN_INFO "elanfreq: attempting to set frequency to %i kHz\n",elan_multiplier[state].clock);
+ printk(KERN_INFO "elanfreq: attempting to set frequency to %i kHz\n",
+ elan_multiplier[state].clock);
- /*
- * Access to the Elan's internal registers is indexed via
- * 0x22: Chip Setup & Control Register Index Register (CSCI)
- * 0x23: Chip Setup & Control Register Data Register (CSCD)
+ /*
+ * Access to the Elan's internal registers is indexed via
+ * 0x22: Chip Setup & Control Register Index Register (CSCI)
+ * 0x23: Chip Setup & Control Register Data Register (CSCD)
*
*/
- /*
- * 0x40 is the Power Management Unit's Force Mode Register.
+ /*
+ * 0x40 is the Power Management Unit's Force Mode Register.
* Bit 6 enables Hyperspeed Mode (66/100 MHz core frequency)
*/
local_irq_disable();
- outb_p(0x40,REG_CSCIR); /* Disable hyperspeed mode */
+ outb_p(0x40,REG_CSCIR); /* Disable hyperspeed mode */
outb_p(0x00,REG_CSCDR);
local_irq_enable(); /* wait till internal pipelines and */
udelay(1000); /* buffers have cleaned up */
@@ -166,10 +167,10 @@ static void elanfreq_set_cpu_state (unsigned int state) {
/**
* elanfreq_validatespeed: test if frequency range is valid
- * @policy: the policy to validate
+ * @policy: the policy to validate
*
- * This function checks if a given frequency range in kHz is valid
- * for the hardware supported by the driver.
+ * This function checks if a given frequency range in kHz is valid
+ * for the hardware supported by the driver.
*/
static int elanfreq_verify (struct cpufreq_policy *policy)
@@ -177,11 +178,11 @@ static int elanfreq_verify (struct cpufreq_policy *policy)
return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]);
}
-static int elanfreq_target (struct cpufreq_policy *policy,
- unsigned int target_freq,
+static int elanfreq_target (struct cpufreq_policy *policy,
+ unsigned int target_freq,
unsigned int relation)
{
- unsigned int newstate = 0;
+ unsigned int newstate = 0;
if (cpufreq_frequency_table_target(policy, &elanfreq_table[0], target_freq, relation, &newstate))
return -EINVAL;
@@ -212,7 +213,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
max_freq = elanfreq_get_cpu_frequency(0);
/* table init */
- for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) {
+ for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) {
if (elanfreq_table[i].frequency > max_freq)
elanfreq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
}
@@ -226,8 +227,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
if (result)
return (result);
- cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu);
-
+ cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu);
return 0;
}
@@ -268,9 +268,9 @@ static struct freq_attr* elanfreq_attr[] = {
static struct cpufreq_driver elanfreq_driver = {
- .get = elanfreq_get_cpu_frequency,
- .verify = elanfreq_verify,
- .target = elanfreq_target,
+ .get = elanfreq_get_cpu_frequency,
+ .verify = elanfreq_verify,
+ .target = elanfreq_target,
.init = elanfreq_cpu_init,
.exit = elanfreq_cpu_exit,
.name = "elanfreq",
@@ -279,23 +279,21 @@ static struct cpufreq_driver elanfreq_driver = {
};
-static int __init elanfreq_init(void)
-{
+static int __init elanfreq_init(void)
+{
struct cpuinfo_x86 *c = cpu_data;
/* Test if we have the right hardware */
if ((c->x86_vendor != X86_VENDOR_AMD) ||
- (c->x86 != 4) || (c->x86_model!=10))
- {
+ (c->x86 != 4) || (c->x86_model!=10)) {
printk(KERN_INFO "elanfreq: error: no Elan processor found!\n");
return -ENODEV;
}
-
return cpufreq_register_driver(&elanfreq_driver);
}
-static void __exit elanfreq_exit(void)
+static void __exit elanfreq_exit(void)
{
cpufreq_unregister_driver(&elanfreq_driver);
}
@@ -309,4 +307,3 @@ MODULE_DESCRIPTION("cpufreq driver for AMD's Elan CPUs");
module_init(elanfreq_init);
module_exit(elanfreq_exit);
-
diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
index e86ea486c31..92afa3bc84f 100644
--- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
@@ -6,12 +6,12 @@
*
* 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
+ * version 2 as published by the Free Software Foundation
*
* The author(s) of this software shall not be held liable for damages
* of any nature resulting due to the use of this software. This
* software is provided AS-IS with no warranties.
- *
+ *
* Theoritical note:
*
* (see Geode(tm) CS5530 manual (rev.4.1) page.56)
@@ -21,18 +21,18 @@
*
* Suspend Modulation works by asserting and de-asserting the SUSP# pin
* to CPU(GX1/GXLV) for configurable durations. When asserting SUSP#
- * the CPU enters an idle state. GX1 stops its core clock when SUSP# is
+ * the CPU enters an idle state. GX1 stops its core clock when SUSP# is
* asserted then power consumption is reduced.
*
- * Suspend Modulation's OFF/ON duration are configurable
+ * Suspend Modulation's OFF/ON duration are configurable
* with 'Suspend Modulation OFF Count Register'
* and 'Suspend Modulation ON Count Register'.
- * These registers are 8bit counters that represent the number of
+ * These registers are 8bit counters that represent the number of
* 32us intervals which the SUSP# pin is asserted(ON)/de-asserted(OFF)
* to the processor.
*
- * These counters define a ratio which is the effective frequency
- * of operation of the system.
+ * These counters define a ratio which is the effective frequency
+ * of operation of the system.
*
* OFF Count
* F_eff = Fgx * ----------------------
@@ -40,24 +40,24 @@
*
* 0 <= On Count, Off Count <= 255
*
- * From these limits, we can get register values
+ * From these limits, we can get register values
*
* off_duration + on_duration <= MAX_DURATION
* on_duration = off_duration * (stock_freq - freq) / freq
*
- * off_duration = (freq * DURATION) / stock_freq
- * on_duration = DURATION - off_duration
+ * off_duration = (freq * DURATION) / stock_freq
+ * on_duration = DURATION - off_duration
*
*
*---------------------------------------------------------------------------
*
* ChangeLog:
- * Dec. 12, 2003 Hiroshi Miura <miura@da-cha.org>
- * - fix on/off register mistake
- * - fix cpu_khz calc when it stops cpu modulation.
+ * Dec. 12, 2003 Hiroshi Miura <miura@da-cha.org>
+ * - fix on/off register mistake
+ * - fix cpu_khz calc when it stops cpu modulation.
*
- * Dec. 11, 2002 Hiroshi Miura <miura@da-cha.org>
- * - rewrite for Cyrix MediaGX Cx5510/5520 and
+ * Dec. 11, 2002 Hiroshi Miura <miura@da-cha.org>
+ * - rewrite for Cyrix MediaGX Cx5510/5520 and
* NatSemi Geode Cs5530(A).
*
* Jul. ??, 2002 Zwane Mwaikambo <zwane@commfireservices.com>
@@ -74,40 +74,40 @@
************************************************************************/
#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/cpufreq.h>
#include <linux/pci.h>
-#include <asm/processor.h>
+#include <asm/processor.h>
#include <asm/errno.h>
/* PCI config registers, all at F0 */
-#define PCI_PMER1 0x80 /* power management enable register 1 */
-#define PCI_PMER2 0x81 /* power management enable register 2 */
-#define PCI_PMER3 0x82 /* power management enable register 3 */
-#define PCI_IRQTC 0x8c /* irq speedup timer counter register:typical 2 to 4ms */
-#define PCI_VIDTC 0x8d /* video speedup timer counter register: typical 50 to 100ms */
-#define PCI_MODOFF 0x94 /* suspend modulation OFF counter register, 1 = 32us */
-#define PCI_MODON 0x95 /* suspend modulation ON counter register */
-#define PCI_SUSCFG 0x96 /* suspend configuration register */
+#define PCI_PMER1 0x80 /* power management enable register 1 */
+#define PCI_PMER2 0x81 /* power management enable register 2 */
+#define PCI_PMER3 0x82 /* power management enable register 3 */
+#define PCI_IRQTC 0x8c /* irq speedup timer counter register:typical 2 to 4ms */
+#define PCI_VIDTC 0x8d /* video speedup timer counter register: typical 50 to 100ms */
+#define PCI_MODOFF 0x94 /* suspend modulation OFF counter register, 1 = 32us */
+#define PCI_MODON 0x95 /* suspend modulation ON counter register */
+#define PCI_SUSCFG 0x96 /* suspend configuration register */
/* PMER1 bits */
-#define GPM (1<<0) /* global power management */
-#define GIT (1<<1) /* globally enable PM device idle timers */
-#define GTR (1<<2) /* globally enable IO traps */
-#define IRQ_SPDUP (1<<3) /* disable clock throttle during interrupt handling */
-#define VID_SPDUP (1<<4) /* disable clock throttle during vga video handling */
+#define GPM (1<<0) /* global power management */
+#define GIT (1<<1) /* globally enable PM device idle timers */
+#define GTR (1<<2) /* globally enable IO traps */
+#define IRQ_SPDUP (1<<3) /* disable clock throttle during interrupt handling */
+#define VID_SPDUP (1<<4) /* disable clock throttle during vga video handling */
/* SUSCFG bits */
-#define SUSMOD (1<<0) /* enable/disable suspend modulation */
-/* the belows support only with cs5530 (after rev.1.2)/cs5530A */
-#define SMISPDUP (1<<1) /* select how SMI re-enable suspend modulation: */
- /* IRQTC timer or read SMI speedup disable reg.(F1BAR[08-09h]) */
-#define SUSCFG (1<<2) /* enable powering down a GXLV processor. "Special 3Volt Suspend" mode */
-/* the belows support only with cs5530A */
-#define PWRSVE_ISA (1<<3) /* stop ISA clock */
-#define PWRSVE (1<<4) /* active idle */
+#define SUSMOD (1<<0) /* enable/disable suspend modulation */
+/* the belows support only with cs5530 (after rev.1.2)/cs5530A */
+#define SMISPDUP (1<<1) /* select how SMI re-enable suspend modulation: */
+ /* IRQTC timer or read SMI speedup disable reg.(F1BAR[08-09h]) */
+#define SUSCFG (1<<2) /* enable powering down a GXLV processor. "Special 3Volt Suspend" mode */
+/* the belows support only with cs5530A */
+#define PWRSVE_ISA (1<<3) /* stop ISA clock */
+#define PWRSVE (1<<4) /* active idle */
struct gxfreq_params {
u8 on_duration;
@@ -128,7 +128,7 @@ module_param (pci_busclk, int, 0444);
/* maximum duration for which the cpu may be suspended
* (32us * MAX_DURATION). If no parameter is given, this defaults
- * to 255.
+ * to 255.
* Note that this leads to a maximum of 8 ms(!) where the CPU clock
* is suspended -- processing power is just 0.39% of what it used to be,
* though. 781.25 kHz(!) for a 200 MHz processor -- wow. */
@@ -144,17 +144,17 @@ module_param (max_duration, int, 0444);
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "gx-suspmod", msg)
/**
- * we can detect a core multipiler from dir0_lsb
- * from GX1 datasheet p.56,
- * MULT[3:0]:
- * 0000 = SYSCLK multiplied by 4 (test only)
- * 0001 = SYSCLK multiplied by 10
- * 0010 = SYSCLK multiplied by 4
- * 0011 = SYSCLK multiplied by 6
- * 0100 = SYSCLK multiplied by 9
- * 0101 = SYSCLK multiplied by 5
- * 0110 = SYSCLK multiplied by 7
- * 0111 = SYSCLK multiplied by 8
+ * we can detect a core multipiler from dir0_lsb
+ * from GX1 datasheet p.56,
+ * MULT[3:0]:
+ * 0000 = SYSCLK multiplied by 4 (test only)
+ * 0001 = SYSCLK multiplied by 10
+ * 0010 = SYSCLK multiplied by 4
+ * 0011 = SYSCLK multiplied by 6
+ * 0100 = SYSCLK multiplied by 9
+ * 0101 = SYSCLK multiplied by 5
+ * 0110 = SYSCLK multiplied by 7
+ * 0111 = SYSCLK multiplied by 8
* of 33.3MHz
**/
static int gx_freq_mult[16] = {
@@ -164,17 +164,17 @@ static int gx_freq_mult[16] = {
/****************************************************************
- * Low Level chipset interface *
+ * Low Level chipset interface *
****************************************************************/
static struct pci_device_id gx_chipset_tbl[] __initdata = {
- { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, PCI_ANY_ID, PCI_ANY_ID },
- { 0, },
+ { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, PCI_ANY_ID, PCI_ANY_ID },
+ { 0, },
};
/**
- * gx_detect_chipset:
+ * gx_detect_chipset:
*
**/
static __init struct pci_dev *gx_detect_chipset(void)
@@ -182,17 +182,16 @@ static __init struct pci_dev *gx_detect_chipset(void)
struct pci_dev *gx_pci = NULL;
/* check if CPU is a MediaGX or a Geode. */
- if ((current_cpu_data.x86_vendor != X86_VENDOR_NSC) &&
+ if ((current_cpu_data.x86_vendor != X86_VENDOR_NSC) &&
(current_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) {
dprintk("error: no MediaGX/Geode processor found!\n");
- return NULL;
+ return NULL;
}
/* detect which companion chip is used */
while ((gx_pci = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, gx_pci)) != NULL) {
- if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL) {
+ if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL)
return gx_pci;
- }
}
dprintk("error: no supported chipset found!\n");
@@ -200,24 +199,24 @@ static __init struct pci_dev *gx_detect_chipset(void)
}
/**
- * gx_get_cpuspeed:
+ * gx_get_cpuspeed:
*
* Finds out at which efficient frequency the Cyrix MediaGX/NatSemi Geode CPU runs.
*/
static unsigned int gx_get_cpuspeed(unsigned int cpu)
{
- if ((gx_params->pci_suscfg & SUSMOD) == 0)
+ if ((gx_params->pci_suscfg & SUSMOD) == 0)
return stock_freq;
- return (stock_freq * gx_params->off_duration)
+ return (stock_freq * gx_params->off_duration)
/ (gx_params->on_duration + gx_params->off_duration);
}
/**
* gx_validate_speed:
* determine current cpu speed
- *
-**/
+ *
+ **/
static unsigned int gx_validate_speed(unsigned int khz, u8 *on_duration, u8 *off_duration)
{
@@ -230,7 +229,7 @@ static unsigned int gx_validate_speed(unsigned int khz, u8 *on_duration, u8 *off
*on_duration=0;
for (i=max_duration; i>0; i--) {
- tmp_off = ((khz * i) / stock_freq) & 0xff;
+ tmp_off = ((khz * i) / stock_freq) & 0xff;
tmp_on = i - tmp_off;
tmp_freq = (stock_freq * tmp_off) / i;
/* if this relation is closer to khz, use this. If it's equal,
@@ -247,18 +246,17 @@ static unsigned int gx_validate_speed(unsigned int khz, u8 *on_duration, u8 *off
/**
- * gx_set_cpuspeed:
- * set cpu speed in khz.
+ * gx_set_cpuspeed:
+ * set cpu speed in khz.
**/
static void gx_set_cpuspeed(unsigned int khz)
{
- u8 suscfg, pmer1;
+ u8 suscfg, pmer1;
unsigned int new_khz;
unsigned long flags;
struct cpufreq_freqs freqs;
-
freqs.cpu = 0;
freqs.old = gx_get_cpuspeed(0);
@@ -303,18 +301,18 @@ static void gx_set_cpuspeed(unsigned int khz)
pci_write_config_byte(gx_params->cs55x0, PCI_MODOFF, gx_params->off_duration);
pci_write_config_byte(gx_params->cs55x0, PCI_MODON, gx_params->on_duration);
- pci_write_config_byte(gx_params->cs55x0, PCI_SUSCFG, suscfg);
- pci_read_config_byte(gx_params->cs55x0, PCI_SUSCFG, &suscfg);
+ pci_write_config_byte(gx_params->cs55x0, PCI_SUSCFG, suscfg);
+ pci_read_config_byte(gx_params->cs55x0, PCI_SUSCFG, &suscfg);
- local_irq_restore(flags);
+ local_irq_restore(flags);
gx_params->pci_suscfg = suscfg;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
- dprintk("suspend modulation w/ duration of ON:%d us, OFF:%d us\n",
- gx_params->on_duration * 32, gx_params->off_duration * 32);
- dprintk("suspend modulation w/ clock speed: %d kHz.\n", freqs.new);
+ dprintk("suspend modulation w/ duration of ON:%d us, OFF:%d us\n",
+ gx_params->on_duration * 32, gx_params->off_duration * 32);
+ dprintk("suspend modulation w/ clock speed: %d kHz.\n", freqs.new);
}
/****************************************************************
@@ -322,10 +320,10 @@ static void gx_set_cpuspeed(unsigned int khz)
****************************************************************/
/*
- * cpufreq_gx_verify: test if frequency range is valid
+ * cpufreq_gx_verify: test if frequency range is valid
*
- * This function checks if a given frequency range in kHz is valid
- * for the hardware supported by the driver.
+ * This function checks if a given frequency range in kHz is valid
+ * for the hardware supported by the driver.
*/
static int cpufreq_gx_verify(struct cpufreq_policy *policy)
@@ -333,8 +331,8 @@ static int cpufreq_gx_verify(struct cpufreq_policy *policy)
unsigned int tmp_freq = 0;
u8 tmp1, tmp2;
- if (!stock_freq || !policy)
- return -EINVAL;
+ if (!stock_freq || !policy)
+ return -EINVAL;
policy->cpu = 0;
cpufreq_verify_within_limits(policy, (stock_freq / max_duration), stock_freq);
@@ -342,14 +340,14 @@ static int cpufreq_gx_verify(struct cpufreq_policy *policy)
/* it needs to be assured that at least one supported frequency is
* within policy->min and policy->max. If it is not, policy->max
* needs to be increased until one freuqency is supported.
- * policy->min may not be decreased, though. This way we guarantee a
+ * policy->min may not be decreased, though. This way we guarantee a
* specific processing capacity.
*/
tmp_freq = gx_validate_speed(policy->min, &tmp1, &tmp2);
- if (tmp_freq < policy->min)
+ if (tmp_freq < policy->min)
tmp_freq += stock_freq / max_duration;
policy->min = tmp_freq;
- if (policy->min > policy->max)
+ if (policy->min > policy->max)
policy->max = tmp_freq;
tmp_freq = gx_validate_speed(policy->max, &tmp1, &tmp2);
if (tmp_freq > policy->max)
@@ -358,12 +356,12 @@ static int cpufreq_gx_verify(struct cpufreq_policy *policy)
if (policy->max < policy->min)
policy->max = policy->min;
cpufreq_verify_within_limits(policy, (stock_freq / max_duration), stock_freq);
-
+
return 0;
}
/*
- * cpufreq_gx_target:
+ * cpufreq_gx_target:
*
*/
static int cpufreq_gx_target(struct cpufreq_policy *policy,
@@ -373,8 +371,8 @@ static int cpufreq_gx_target(struct cpufreq_policy *policy,
u8 tmp1, tmp2;
unsigned int tmp_freq;
- if (!stock_freq || !policy)
- return -EINVAL;
+ if (!stock_freq || !policy)
+ return -EINVAL;
policy->cpu = 0;
@@ -431,7 +429,7 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
return 0;
}
-/*
+/*
* cpufreq_gx_init:
* MediaGX/Geode GX initialize cpufreq driver
*/
@@ -452,7 +450,7 @@ static int __init cpufreq_gx_init(void)
u32 class_rev;
/* Test if we have the right hardware */
- if ((gx_pci = gx_detect_chipset()) == NULL)
+ if ((gx_pci = gx_detect_chipset()) == NULL)
return -ENODEV;
/* check whether module parameters are sane */
@@ -461,10 +459,9 @@ static int __init cpufreq_gx_init(void)
dprintk("geode suspend modulation available.\n");
- params = kmalloc(sizeof(struct gxfreq_params), GFP_KERNEL);
+ params = kzalloc(sizeof(struct gxfreq_params), GFP_KERNEL);
if (params == NULL)
return -ENOMEM;
- memset(params, 0, sizeof(struct gxfreq_params));
params->cs55x0 = gx_pci;
gx_params = params;
@@ -478,7 +475,7 @@ static int __init cpufreq_gx_init(void)
pci_read_config_dword(params->cs55x0, PCI_CLASS_REVISION, &class_rev);
params->pci_rev = class_rev && 0xff;
- if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) {
+ if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) {
kfree(params);
return ret; /* register error! */
}
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.h b/arch/i386/kernel/cpu/cpufreq/longhaul.h
index 2a495c162ec..d3a95d77ee8 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.h
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.h
@@ -234,7 +234,7 @@ static int __initdata ezrat_eblcr[32] = {
/*
* VIA C3 Nehemiah */
-
+
static int __initdata nehemiah_a_clock_ratio[32] = {
100, /* 0000 -> 10.0x */
160, /* 0001 -> 16.0x */
@@ -446,7 +446,7 @@ static int __initdata nehemiah_c_eblcr[32] = {
/* end of table */
};
-/*
+/*
* Voltage scales. Div/Mod by 1000 to get actual voltage.
* Which scale to use depends on the VRM type in use.
*/
diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
index cc73a7ae34b..ab6504efd80 100644
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
@@ -14,7 +14,7 @@
* The author(s) of this software shall not be held liable for damages
* of any nature resulting due to the use of this software. This
* software is provided AS-IS with no warranties.
- *
+ *
* Date Errata Description
* 20020525 N44, O17 12.5% or 25% DC causes lockup
*
@@ -22,7 +22,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/cpufreq.h>
@@ -30,7 +30,7 @@
#include <linux/cpumask.h>
#include <linux/sched.h> /* current / set_cpus_allowed() */
-#include <asm/processor.h>
+#include <asm/processor.h>
#include <asm/msr.h>
#include <asm/timex.h>
@@ -79,7 +79,7 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
} else {
dprintk("CPU#%d setting duty cycle to %d%%\n",
cpu, ((125 * newstate) / 10));
- /* bits 63 - 5 : reserved
+ /* bits 63 - 5 : reserved
* bit 4 : enable/disable
* bits 3-1 : duty cycle
* bit 0 : reserved
@@ -132,7 +132,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
}
/* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software
- * Developer's Manual, Volume 3
+ * Developer's Manual, Volume 3
*/
cpus_allowed = current->cpus_allowed;
@@ -206,7 +206,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_P4D);
}
-
+
static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
{
@@ -234,7 +234,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
dprintk("has errata -- disabling frequencies lower than 2ghz\n");
break;
}
-
+
/* get max frequency */
stock_freq = cpufreq_p4_get_frequency(c);
if (!stock_freq)
@@ -244,13 +244,13 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) {
if ((i<2) && (has_N44_O17_errata[policy->cpu]))
p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
- else if (has_N60_errata[policy->cpu] && p4clockmod_table[i].frequency < 2000000)
+ else if (has_N60_errata[policy->cpu] && ((stock_freq * i)/8) < 2000000)
p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
else
p4clockmod_table[i].frequency = (stock_freq * i)/8;
}
cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu);
-
+
/* cpuinfo and default policy values */
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = 1000000; /* assumed */
@@ -262,7 +262,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
{
- cpufreq_frequency_table_put_attr(policy->cpu);
+ cpufreq_frequency_table_put_attr(policy->cpu);
return 0;
}
@@ -298,7 +298,7 @@ static struct freq_attr* p4clockmod_attr[] = {
};
static struct cpufreq_driver p4clockmod_driver = {
- .verify = cpufreq_p4_verify,
+ .verify = cpufreq_p4_verify,
.target = cpufreq_p4_target,
.init = cpufreq_p4_cpu_init,
.exit = cpufreq_p4_cpu_exit,
@@ -310,12 +310,12 @@ static struct cpufreq_driver p4clockmod_driver = {
static int __init cpufreq_p4_init(void)
-{
+{
struct cpuinfo_x86 *c = cpu_data;
int ret;
/*
- * THERM_CONTROL is architectural for IA32 now, so
+ * THERM_CONTROL is architectural for IA32 now, so
* we can rely on the capability checks
*/
if (c->x86_vendor != X86_VENDOR_INTEL)
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
index 222f8cfe3c5..f89524051e4 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
@@ -8,7 +8,7 @@
*/
#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/cpufreq.h>
#include <linux/ioport.h>
@@ -50,7 +50,7 @@ static int powernow_k6_get_cpu_multiplier(void)
{
u64 invalue = 0;
u32 msrval;
-
+
msrval = POWERNOW_IOPORT + 0x1;
wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
invalue=inl(POWERNOW_IOPORT + 0x8);
@@ -81,7 +81,7 @@ static void powernow_k6_set_state (unsigned int best_i)
freqs.old = busfreq * powernow_k6_get_cpu_multiplier();
freqs.new = busfreq * clock_ratio[best_i].index;
freqs.cpu = 0; /* powernow-k6.c is UP only driver */
-
+
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
/* we now need to transform best_i to the BVC format, see AMD#23446 */
@@ -152,7 +152,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
busfreq = cpu_khz / max_multiplier;
/* table init */
- for (i=0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
+ for (i=0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
if (clock_ratio[i].index > max_multiplier)
clock_ratio[i].frequency = CPUFREQ_ENTRY_INVALID;
else
@@ -182,7 +182,7 @@ static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
powernow_k6_set_state(i);
}
cpufreq_frequency_table_put_attr(policy->cpu);
- return 0;
+ return 0;
}
static unsigned int powernow_k6_get(unsigned int cpu)
@@ -196,8 +196,8 @@ static struct freq_attr* powernow_k6_attr[] = {
};
static struct cpufreq_driver powernow_k6_driver = {
- .verify = powernow_k6_verify,
- .target = powernow_k6_target,
+ .verify = powernow_k6_verify,
+ .target = powernow_k6_target,
.init = powernow_k6_cpu_init,
.exit = powernow_k6_cpu_exit,
.get = powernow_k6_get,
@@ -215,7 +215,7 @@ static struct cpufreq_driver powernow_k6_driver = {
* on success.
*/
static int __init powernow_k6_init(void)
-{
+{
struct cpuinfo_x86 *c = cpu_data;
if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
index edcd626001d..2bf4237cb94 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
@@ -199,8 +199,8 @@ static int get_ranges (unsigned char *pst)
powernow_table[j].index |= (vid << 8); /* upper 8 bits */
dprintk (" FID: 0x%x (%d.%dx [%dMHz]) "
- "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
- fid_codes[fid] % 10, speed/1000, vid,
+ "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
+ fid_codes[fid] % 10, speed/1000, vid,
mobile_vid_table[vid]/1000,
mobile_vid_table[vid]%1000);
}
@@ -368,8 +368,8 @@ static int powernow_acpi_init(void)
}
dprintk (" FID: 0x%x (%d.%dx [%dMHz]) "
- "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
- fid_codes[fid] % 10, speed/1000, vid,
+ "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
+ fid_codes[fid] % 10, speed/1000, vid,
mobile_vid_table[vid]/1000,
mobile_vid_table[vid]%1000);
@@ -460,7 +460,7 @@ static int powernow_decode_bios (int maxfid, int startvid)
(maxfid==pst->maxfid) && (startvid==pst->startvid))
{
dprintk ("PST:%d (@%p)\n", i, pst);
- dprintk (" cpuid: 0x%x fsb: %d maxFID: 0x%x startvid: 0x%x\n",
+ dprintk (" cpuid: 0x%x fsb: %d maxFID: 0x%x startvid: 0x%x\n",
pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid);
ret = get_ranges ((char *) pst + sizeof (struct pst_s));
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 798da7c2b5d..712a26bd445 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -40,21 +40,22 @@
#ifdef CONFIG_X86_POWERNOW_K8_ACPI
#include <linux/acpi.h>
+#include <linux/mutex.h>
#include <acpi/processor.h>
#endif
#define PFX "powernow-k8: "
#define BFX PFX "BIOS error: "
-#define VERSION "version 1.60.0"
+#define VERSION "version 1.60.1"
#include "powernow-k8.h"
/* serialize freq changes */
-static DECLARE_MUTEX(fidvid_sem);
+static DEFINE_MUTEX(fidvid_mutex);
static struct powernow_k8_data *powernow_data[NR_CPUS];
#ifndef CONFIG_SMP
-static cpumask_t cpu_core_map[1];
+static cpumask_t cpu_core_map[1] = { CPU_MASK_ALL };
#endif
/* Return a frequency in MHz, given an input fid */
@@ -83,11 +84,10 @@ static u32 find_millivolts_from_vid(struct powernow_k8_data *data, u32 vid)
*/
static u32 convert_fid_to_vco_fid(u32 fid)
{
- if (fid < HI_FID_TABLE_BOTTOM) {
+ if (fid < HI_FID_TABLE_BOTTOM)
return 8 + (2 * fid);
- } else {
+ else
return fid;
- }
}
/*
@@ -177,7 +177,7 @@ static int write_new_fid(struct powernow_k8_data *data, u32 fid)
if (i++ > 100) {
printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n");
return 1;
- }
+ }
} while (query_current_values_with_pending_wait(data));
count_off_irt(data);
@@ -474,8 +474,10 @@ static int check_supported_cpu(unsigned int cpu)
goto out;
eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
+ if ((eax & CPUID_XFAM) != CPUID_XFAM_K8)
+ goto out;
+
if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
- ((eax & CPUID_XFAM) != CPUID_XFAM_K8) ||
((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) {
printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
goto out;
@@ -780,9 +782,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
/* verify only 1 entry from the lo frequency table */
if (fid < HI_FID_TABLE_BOTTOM) {
if (cntlofreq) {
- /* if both entries are the same, ignore this
- * one...
- */
+ /* if both entries are the same, ignore this one ... */
if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
(powernow_table[i].index != powernow_table[cntlofreq].index)) {
printk(KERN_ERR PFX "Too many lo freq table entries\n");
@@ -854,7 +854,7 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
/* fid are the lower 8 bits of the index we stored into
- * the cpufreq frequency table in find_psb_table, vid are
+ * the cpufreq frequency table in find_psb_table, vid are
* the upper 8 bits.
*/
@@ -909,7 +909,6 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
u32 checkvid = data->currvid;
unsigned int newstate;
int ret = -EIO;
- int i;
/* only run on specific CPU from here on */
oldmask = current->cpus_allowed;
@@ -945,23 +944,17 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
goto err_out;
- down(&fidvid_sem);
+ mutex_lock(&fidvid_mutex);
powernow_k8_acpi_pst_values(data, newstate);
if (transition_frequency(data, newstate)) {
printk(KERN_ERR PFX "transition frequency failed\n");
ret = 1;
- up(&fidvid_sem);
+ mutex_unlock(&fidvid_mutex);
goto err_out;
}
-
- /* Update all the fid/vids of our siblings */
- for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
- powernow_data[i]->currvid = data->currvid;
- powernow_data[i]->currfid = data->currfid;
- }
- up(&fidvid_sem);
+ mutex_unlock(&fidvid_mutex);
pol->cur = find_khz_freq_from_fid(data->currfid);
ret = 0;
@@ -1048,7 +1041,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
pol->cpus = cpu_core_map[pol->cpu];
- /* Take a crude guess here.
+ /* Take a crude guess here.
* That guess was in microseconds, so multiply with 1000 */
pol->cpuinfo.transition_latency = (((data->rvo + 8) * data->vstable * VST_UNITS_20US)
+ (3 * (1 << data->irt) * 10)) * 1000;
@@ -1070,9 +1063,8 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
printk("cpu_init done, current fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid);
- for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
+ for_each_cpu_mask(i, cpu_core_map[pol->cpu])
powernow_data[i] = data;
- }
return 0;
@@ -1103,10 +1095,15 @@ static int __devexit powernowk8_cpu_exit (struct cpufreq_policy *pol)
static unsigned int powernowk8_get (unsigned int cpu)
{
- struct powernow_k8_data *data = powernow_data[cpu];
+ struct powernow_k8_data *data;
cpumask_t oldmask = current->cpus_allowed;
unsigned int khz = 0;
+ data = powernow_data[first_cpu(cpu_core_map[cpu])];
+
+ if (!data)
+ return -EINVAL;
+
set_cpus_allowed(current, cpumask_of_cpu(cpu));
if (smp_processor_id() != cpu) {
printk(KERN_ERR PFX "limiting to CPU %d failed in powernowk8_get\n", cpu);
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
index d0de37d58e9..79a7c5c87ed 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
@@ -63,7 +63,7 @@ struct powernow_k8_data {
#define MSR_C_LO_VID_SHIFT 8
/* Field definitions within the FID VID High Control MSR : */
-#define MSR_C_HI_STP_GNT_TO 0x000fffff
+#define MSR_C_HI_STP_GNT_TO 0x000fffff
/* Field definitions within the FID VID Low Status MSR : */
#define MSR_S_LO_CHANGE_PENDING 0x80000000 /* cleared when completed */
@@ -123,7 +123,7 @@ struct powernow_k8_data {
* Most values of interest are enocoded in a single field of the _PSS
* entries: the "control" value.
*/
-
+
#define IRT_SHIFT 30
#define RVO_SHIFT 28
#define EXT_TYPE_SHIFT 27
@@ -182,10 +182,6 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid);
static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index);
-#ifndef for_each_cpu_mask
-#define for_each_cpu_mask(i,mask) for (i=0;i<1;i++)
-#endif
-
#ifdef CONFIG_SMP
static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
{
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index c173c0fa117..b0ff9075708 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -479,15 +479,13 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
unsigned l, h;
int ret;
int i;
- struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
/* Only Intel makes Enhanced Speedstep-capable CPUs */
if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST))
return -ENODEV;
- if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
+ if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC))
centrino_driver.flags |= CPUFREQ_CONST_LOOPS;
- }
if (centrino_cpu_init_acpi(policy)) {
if (policy->cpu != 0)
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
index 7c47005a180..4f46cac155c 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
@@ -9,7 +9,7 @@
*/
#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/cpufreq.h>
@@ -36,8 +36,8 @@ static unsigned int pentium3_get_frequency (unsigned int processor)
/* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */
struct {
unsigned int ratio; /* Frequency Multiplier (x10) */
- u8 bitmap; /* power on configuration bits
- [27, 25:22] (in MSR 0x2a) */
+ u8 bitmap; /* power on configuration bits
+ [27, 25:22] (in MSR 0x2a) */
} msr_decode_mult [] = {
{ 30, 0x01 },
{ 35, 0x05 },
@@ -58,9 +58,9 @@ static unsigned int pentium3_get_frequency (unsigned int processor)
/* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */
struct {
- unsigned int value; /* Front Side Bus speed in MHz */
- u8 bitmap; /* power on configuration bits [18: 19]
- (in MSR 0x2a) */
+ unsigned int value; /* Front Side Bus speed in MHz */
+ u8 bitmap; /* power on configuration bits [18: 19]
+ (in MSR 0x2a) */
} msr_decode_fsb [] = {
{ 66, 0x0 },
{ 100, 0x2 },
@@ -68,8 +68,8 @@ static unsigned int pentium3_get_frequency (unsigned int processor)
{ 0, 0xff}
};
- u32 msr_lo, msr_tmp;
- int i = 0, j = 0;
+ u32 msr_lo, msr_tmp;
+ int i = 0, j = 0;
/* read MSR 0x2a - we only need the low 32 bits */
rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp);
@@ -106,7 +106,7 @@ static unsigned int pentium3_get_frequency (unsigned int processor)
static unsigned int pentiumM_get_frequency(void)
{
- u32 msr_lo, msr_tmp;
+ u32 msr_lo, msr_tmp;
rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp);
dprintk("PM - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp);
@@ -134,7 +134,7 @@ static unsigned int pentium4_get_frequency(void)
dprintk("P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi);
- /* decode the FSB: see IA-32 Intel (C) Architecture Software
+ /* decode the FSB: see IA-32 Intel (C) Architecture Software
* Developer's Manual, Volume 3: System Prgramming Guide,
* revision #12 in Table B-1: MSRs in the Pentium 4 and
* Intel Xeon Processors, on page B-4 and B-5.
@@ -170,7 +170,7 @@ static unsigned int pentium4_get_frequency(void)
return (fsb * mult);
}
-
+
unsigned int speedstep_get_processor_frequency(unsigned int processor)
{
switch (processor) {
@@ -198,11 +198,11 @@ EXPORT_SYMBOL_GPL(speedstep_get_processor_frequency);
unsigned int speedstep_detect_processor (void)
{
struct cpuinfo_x86 *c = cpu_data;
- u32 ebx, msr_lo, msr_hi;
+ u32 ebx, msr_lo, msr_hi;
dprintk("x86: %x, model: %x\n", c->x86, c->x86_model);
- if ((c->x86_vendor != X86_VENDOR_INTEL) ||
+ if ((c->x86_vendor != X86_VENDOR_INTEL) ||
((c->x86 != 6) && (c->x86 != 0xF)))
return 0;
@@ -218,15 +218,15 @@ unsigned int speedstep_detect_processor (void)
dprintk("ebx value is %x, x86_mask is %x\n", ebx, c->x86_mask);
switch (c->x86_mask) {
- case 4:
+ case 4:
/*
- * B-stepping [M-P4-M]
+ * B-stepping [M-P4-M]
* sample has ebx = 0x0f, production has 0x0e.
*/
if ((ebx == 0x0e) || (ebx == 0x0f))
return SPEEDSTEP_PROCESSOR_P4M;
break;
- case 7:
+ case 7:
/*
* C-stepping [M-P4-M]
* needs to have ebx=0x0e, else it's a celeron:
@@ -253,7 +253,7 @@ unsigned int speedstep_detect_processor (void)
* also, M-P4M HTs have ebx=0x8, too
* For now, they are distinguished by the model_id string
*/
- if ((ebx == 0x0e) || (strstr(c->x86_model_id,"Mobile Intel(R) Pentium(R) 4") != NULL))
+ if ((ebx == 0x0e) || (strstr(c->x86_model_id,"Mobile Intel(R) Pentium(R) 4") != NULL))
return SPEEDSTEP_PROCESSOR_P4M;
break;
default:
@@ -264,8 +264,7 @@ unsigned int speedstep_detect_processor (void)
switch (c->x86_model) {
case 0x0B: /* Intel PIII [Tualatin] */
- /* cpuid_ebx(1) is 0x04 for desktop PIII,
- 0x06 for mobile PIII-M */
+ /* cpuid_ebx(1) is 0x04 for desktop PIII, 0x06 for mobile PIII-M */
ebx = cpuid_ebx(0x00000001);
dprintk("ebx is %x\n", ebx);
@@ -275,9 +274,8 @@ unsigned int speedstep_detect_processor (void)
return 0;
/* So far all PIII-M processors support SpeedStep. See
- * Intel's 24540640.pdf of June 2003
+ * Intel's 24540640.pdf of June 2003
*/
-
return SPEEDSTEP_PROCESSOR_PIII_T;
case 0x08: /* Intel PIII [Coppermine] */
@@ -399,7 +397,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
}
}
- out:
+out:
local_irq_restore(flags);
return (ret);
}
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
index 6a727fd3a77..b735429c50b 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
@@ -14,7 +14,7 @@
#define SPEEDSTEP_PROCESSOR_PIII_C_EARLY 0x00000001 /* Coppermine core */
#define SPEEDSTEP_PROCESSOR_PIII_C 0x00000002 /* Coppermine core */
-#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000003 /* Tualatin core */
+#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000003 /* Tualatin core */
#define SPEEDSTEP_PROCESSOR_P4M 0x00000004 /* P4-M */
/* the following processors are not speedstep-capable and are not auto-detected
@@ -25,8 +25,8 @@
/* speedstep states -- only two of them */
-#define SPEEDSTEP_HIGH 0x00000000
-#define SPEEDSTEP_LOW 0x00000001
+#define SPEEDSTEP_HIGH 0x00000000
+#define SPEEDSTEP_LOW 0x00000001
/* detect a speedstep-capable processor */
@@ -36,13 +36,13 @@ extern unsigned int speedstep_detect_processor (void);
extern unsigned int speedstep_get_processor_frequency(unsigned int processor);
-/* detect the low and high speeds of the processor. The callback
- * set_state"'s first argument is either SPEEDSTEP_HIGH or
- * SPEEDSTEP_LOW; the second argument is zero so that no
+/* detect the low and high speeds of the processor. The callback
+ * set_state"'s first argument is either SPEEDSTEP_HIGH or
+ * SPEEDSTEP_LOW; the second argument is zero so that no
* cpufreq_notify_transition calls are initiated.
*/
extern unsigned int speedstep_get_freqs(unsigned int processor,
- unsigned int *low_speed,
- unsigned int *high_speed,
- unsigned int *transition_latency,
- void (*set_state) (unsigned int state));
+ unsigned int *low_speed,
+ unsigned int *high_speed,
+ unsigned int *transition_latency,
+ void (*set_state) (unsigned int state));
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
index 28cc5d524af..c28333d5364 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
@@ -13,8 +13,8 @@
*********************************************************************/
#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/cpufreq.h>
#include <linux/pci.h>
@@ -28,21 +28,21 @@
*
* These parameters are got from IST-SMI BIOS call.
* If user gives it, these are used.
- *
+ *
*/
-static int smi_port = 0;
-static int smi_cmd = 0;
-static unsigned int smi_sig = 0;
+static int smi_port = 0;
+static int smi_cmd = 0;
+static unsigned int smi_sig = 0;
/* info about the processor */
-static unsigned int speedstep_processor = 0;
+static unsigned int speedstep_processor = 0;
-/*
- * There are only two frequency states for each processor. Values
+/*
+ * There are only two frequency states for each processor. Values
* are in kHz for the time being.
*/
static struct cpufreq_frequency_table speedstep_freqs[] = {
- {SPEEDSTEP_HIGH, 0},
+ {SPEEDSTEP_HIGH, 0},
{SPEEDSTEP_LOW, 0},
{0, CPUFREQ_TABLE_END},
};
@@ -75,7 +75,9 @@ static int speedstep_smi_ownership (void)
__asm__ __volatile__(
"out %%al, (%%dx)\n"
: "=D" (result)
- : "a" (command), "b" (function), "c" (0), "d" (smi_port), "D" (0), "S" (magic)
+ : "a" (command), "b" (function), "c" (0), "d" (smi_port),
+ "D" (0), "S" (magic)
+ : "memory"
);
dprintk("result is %x\n", result);
@@ -123,7 +125,7 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high)
*low = low_mhz * 1000;
return result;
-}
+}
/**
* speedstep_get_state - set the SpeedStep state
@@ -204,7 +206,7 @@ static void speedstep_set_state (unsigned int state)
* speedstep_target - set a new CPUFreq policy
* @policy: new policy
* @target_freq: new freq
- * @relation:
+ * @relation:
*
* Sets a new CPUFreq policy/freq.
*/
@@ -283,7 +285,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
state = speedstep_get_state();
speed = speedstep_freqs[state].frequency;
- dprintk("currently at %s speed setting - %i MHz\n",
+ dprintk("currently at %s speed setting - %i MHz\n",
(speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high",
(speed / 1000));
@@ -296,7 +298,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
if (result)
return (result);
- cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu);
+ cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu);
return 0;
}
@@ -332,8 +334,8 @@ static struct freq_attr* speedstep_attr[] = {
static struct cpufreq_driver speedstep_driver = {
.name = "speedstep-smi",
- .verify = speedstep_verify,
- .target = speedstep_target,
+ .verify = speedstep_verify,
+ .target = speedstep_target,
.init = speedstep_cpu_init,
.exit = speedstep_cpu_exit,
.get = speedstep_get,
@@ -370,13 +372,12 @@ static int __init speedstep_init(void)
return -ENODEV;
}
- dprintk("signature:0x%.8lx, command:0x%.8lx, event:0x%.8lx, perf_level:0x%.8lx.\n",
+ dprintk("signature:0x%.8lx, command:0x%.8lx, event:0x%.8lx, perf_level:0x%.8lx.\n",
ist_info.signature, ist_info.command, ist_info.event, ist_info.perf_level);
-
- /* Error if no IST-SMI BIOS or no PARM
+ /* Error if no IST-SMI BIOS or no PARM
sig= 'ISGE' aka 'Intel Speedstep Gate E' */
- if ((ist_info.signature != 0x47534943) && (
+ if ((ist_info.signature != 0x47534943) && (
(smi_port == 0) || (smi_cmd == 0)))
return -ENODEV;
@@ -386,17 +387,15 @@ static int __init speedstep_init(void)
smi_sig = ist_info.signature;
/* setup smi_port from MODLULE_PARM or BIOS */
- if ((smi_port > 0xff) || (smi_port < 0)) {
+ if ((smi_port > 0xff) || (smi_port < 0))
return -EINVAL;
- } else if (smi_port == 0) {
+ else if (smi_port == 0)
smi_port = ist_info.command & 0xff;
- }
- if ((smi_cmd > 0xff) || (smi_cmd < 0)) {
+ if ((smi_cmd > 0xff) || (smi_cmd < 0))
return -EINVAL;
- } else if (smi_cmd == 0) {
+ else if (smi_cmd == 0)
smi_cmd = (ist_info.command >> 16) & 0xff;
- }
return cpufreq_register_driver(&speedstep_driver);
}
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index ce61921369e..9df87b03612 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -173,6 +173,10 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
+ unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
+#ifdef CONFIG_SMP
+ unsigned int cpu = (c == &boot_cpu_data) ? 0 : (c - cpu_data);
+#endif
if (c->cpuid_level > 3) {
static int is_initialized;
@@ -205,9 +209,15 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
break;
case 2:
new_l2 = this_leaf.size/1024;
+ num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
+ index_msb = get_count_order(num_threads_sharing);
+ l2_id = c->apicid >> index_msb;
break;
case 3:
new_l3 = this_leaf.size/1024;
+ num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing;
+ index_msb = get_count_order(num_threads_sharing);
+ l3_id = c->apicid >> index_msb;
break;
default:
break;
@@ -215,11 +225,19 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
}
}
}
- if (c->cpuid_level > 1) {
+ /*
+ * Don't use cpuid2 if cpuid4 is supported. For P4, we use cpuid2 for
+ * trace cache
+ */
+ if ((num_cache_leaves == 0 || c->x86 == 15) && c->cpuid_level > 1) {
/* supports eax=2 call */
int i, j, n;
int regs[4];
unsigned char *dp = (unsigned char *)regs;
+ int only_trace = 0;
+
+ if (num_cache_leaves != 0 && c->x86 == 15)
+ only_trace = 1;
/* Number of times to iterate */
n = cpuid_eax(2) & 0xFF;
@@ -241,6 +259,8 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
while (cache_table[k].descriptor != 0)
{
if (cache_table[k].descriptor == des) {
+ if (only_trace && cache_table[k].cache_type != LVL_TRACE)
+ break;
switch (cache_table[k].cache_type) {
case LVL_1_INST:
l1i += cache_table[k].size;
@@ -266,34 +286,45 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
}
}
}
+ }
- if (new_l1d)
- l1d = new_l1d;
+ if (new_l1d)
+ l1d = new_l1d;
- if (new_l1i)
- l1i = new_l1i;
+ if (new_l1i)
+ l1i = new_l1i;
- if (new_l2)
- l2 = new_l2;
+ if (new_l2) {
+ l2 = new_l2;
+#ifdef CONFIG_SMP
+ cpu_llc_id[cpu] = l2_id;
+#endif
+ }
- if (new_l3)
- l3 = new_l3;
+ if (new_l3) {
+ l3 = new_l3;
+#ifdef CONFIG_SMP
+ cpu_llc_id[cpu] = l3_id;
+#endif
+ }
- if ( trace )
- printk (KERN_INFO "CPU: Trace cache: %dK uops", trace);
- else if ( l1i )
- printk (KERN_INFO "CPU: L1 I cache: %dK", l1i);
- if ( l1d )
- printk(", L1 D cache: %dK\n", l1d);
- else
- printk("\n");
- if ( l2 )
- printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
- if ( l3 )
- printk(KERN_INFO "CPU: L3 cache: %dK\n", l3);
+ if (trace)
+ printk (KERN_INFO "CPU: Trace cache: %dK uops", trace);
+ else if ( l1i )
+ printk (KERN_INFO "CPU: L1 I cache: %dK", l1i);
- c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d));
- }
+ if (l1d)
+ printk(", L1 D cache: %dK\n", l1d);
+ else
+ printk("\n");
+
+ if (l2)
+ printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
+
+ if (l3)
+ printk(KERN_INFO "CPU: L3 cache: %dK\n", l3);
+
+ c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d));
return l2;
}
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
index 3b4618bed70..fff90bda473 100644
--- a/arch/i386/kernel/cpu/mtrr/main.c
+++ b/arch/i386/kernel/cpu/mtrr/main.c
@@ -36,6 +36,7 @@
#include <linux/pci.h>
#include <linux/smp.h>
#include <linux/cpu.h>
+#include <linux/mutex.h>
#include <asm/mtrr.h>
@@ -47,7 +48,7 @@
u32 num_var_ranges = 0;
unsigned int *usage_table;
-static DECLARE_MUTEX(mtrr_sem);
+static DEFINE_MUTEX(mtrr_mutex);
u32 size_or_mask, size_and_mask;
@@ -333,7 +334,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
/* No CPU hotplug when we change MTRR entries */
lock_cpu_hotplug();
/* Search for existing MTRR */
- down(&mtrr_sem);
+ mutex_lock(&mtrr_mutex);
for (i = 0; i < num_var_ranges; ++i) {
mtrr_if->get(i, &lbase, &lsize, &ltype);
if (base >= lbase + lsize)
@@ -371,7 +372,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
printk(KERN_INFO "mtrr: no more MTRRs available\n");
error = i;
out:
- up(&mtrr_sem);
+ mutex_unlock(&mtrr_mutex);
unlock_cpu_hotplug();
return error;
}
@@ -464,7 +465,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
max = num_var_ranges;
/* No CPU hotplug when we change MTRR entries */
lock_cpu_hotplug();
- down(&mtrr_sem);
+ mutex_lock(&mtrr_mutex);
if (reg < 0) {
/* Search for existing MTRR */
for (i = 0; i < max; ++i) {
@@ -503,7 +504,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
set_mtrr(reg, 0, 0, 0);
error = reg;
out:
- up(&mtrr_sem);
+ mutex_unlock(&mtrr_mutex);
unlock_cpu_hotplug();
return error;
}
@@ -685,7 +686,7 @@ void mtrr_ap_init(void)
if (!mtrr_if || !use_intel())
return;
/*
- * Ideally we should hold mtrr_sem here to avoid mtrr entries changed,
+ * Ideally we should hold mtrr_mutex here to avoid mtrr entries changed,
* but this routine will be called in cpu boot time, holding the lock
* breaks it. This routine is called in two cases: 1.very earily time
* of software resume, when there absolutely isn't mtrr entry changes;
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index 5cfbd801169..f94cdb7aca5 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -45,7 +45,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* Intel-defined (#2) */
- "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", NULL, "est",
+ "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
"tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
index 6a93d75db43..5efceebc48d 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/arch/i386/kernel/dmi_scan.c
@@ -3,8 +3,10 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/dmi.h>
+#include <linux/efi.h>
#include <linux/bootmem.h>
#include <linux/slab.h>
+#include <asm/dmi.h>
static char * __init dmi_string(struct dmi_header *dm, u8 s)
{
@@ -106,7 +108,7 @@ static void __init dmi_save_devices(struct dmi_header *dm)
struct dmi_device *dev;
for (i = 0; i < count; i++) {
- char *d = ((char *) dm) + (i * 2);
+ char *d = (char *)(dm + 1) + (i * 2);
/* Skip disabled device */
if ((*d & 0x80) == 0)
@@ -184,47 +186,72 @@ static void __init dmi_decode(struct dmi_header *dm)
}
}
-void __init dmi_scan_machine(void)
+static int __init dmi_present(char __iomem *p)
{
u8 buf[15];
- char __iomem *p, *q;
+ memcpy_fromio(buf, p, 15);
+ if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
+ u16 num = (buf[13] << 8) | buf[12];
+ u16 len = (buf[7] << 8) | buf[6];
+ u32 base = (buf[11] << 24) | (buf[10] << 16) |
+ (buf[9] << 8) | buf[8];
- /*
- * 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.
- */
- p = ioremap(0xF0000, 0x10000);
- if (p == NULL)
- goto out;
-
- for (q = p; q < p + 0x10000; q += 16) {
- memcpy_fromio(buf, q, 15);
- if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
- u16 num = (buf[13] << 8) | buf[12];
- u16 len = (buf[7] << 8) | buf[6];
- u32 base = (buf[11] << 24) | (buf[10] << 16) |
- (buf[9] << 8) | buf[8];
-
- /*
- * DMI version 0.0 means that the real version is taken from
- * the SMBIOS version, which we don't know at this point.
- */
- if (buf[14] != 0)
- printk(KERN_INFO "DMI %d.%d present.\n",
- buf[14] >> 4, buf[14] & 0xF);
- else
- printk(KERN_INFO "DMI present.\n");
+ /*
+ * DMI version 0.0 means that the real version is taken from
+ * the SMBIOS version, which we don't know at this point.
+ */
+ if (buf[14] != 0)
+ printk(KERN_INFO "DMI %d.%d present.\n",
+ buf[14] >> 4, buf[14] & 0xF);
+ else
+ printk(KERN_INFO "DMI present.\n");
+ if (dmi_table(base,len, num, dmi_decode) == 0)
+ return 0;
+ }
+ return 1;
+}
+
+void __init dmi_scan_machine(void)
+{
+ char __iomem *p, *q;
+ int rc;
+
+ if (efi_enabled) {
+ if (efi.smbios == EFI_INVALID_TABLE_ADDR)
+ goto out;
+
+ /* This is called as a core_initcall() because it isn't
+ * needed during early boot. This also means we can
+ * iounmap the space when we're done with it.
+ */
+ p = dmi_ioremap(efi.smbios, 32);
+ if (p == NULL)
+ goto out;
+
+ rc = dmi_present(p + 0x10); /* offset of _DMI_ string */
+ dmi_iounmap(p, 32);
+ if (!rc)
+ return;
+ }
+ else {
+ /*
+ * 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.
+ */
+ p = dmi_ioremap(0xF0000, 0x10000);
+ if (p == NULL)
+ goto out;
- if (dmi_table(base,len, num, dmi_decode) == 0)
+ for (q = p; q < p + 0x10000; q += 16) {
+ rc = dmi_present(q);
+ if (!rc)
return;
}
}
-
-out: printk(KERN_INFO "DMI not present or invalid.\n");
+ out: printk(KERN_INFO "DMI not present or invalid.\n");
}
-
/**
* dmi_check_system - check system DMI data
* @list: array of dmi_system_id structures to match against
@@ -299,3 +326,33 @@ struct dmi_device * dmi_find_device(int type, const char *name,
return NULL;
}
EXPORT_SYMBOL(dmi_find_device);
+
+/**
+ * dmi_get_year - Return year of a DMI date
+ * @field: data index (like dmi_get_system_info)
+ *
+ * Returns -1 when the field doesn't exist. 0 when it is broken.
+ */
+int dmi_get_year(int field)
+{
+ int year;
+ char *s = dmi_get_system_info(field);
+
+ if (!s)
+ return -1;
+ if (*s == '\0')
+ return 0;
+ s = strrchr(s, '/');
+ if (!s)
+ return 0;
+
+ s += 1;
+ year = simple_strtoul(s, NULL, 0);
+ if (year && year < 100) { /* 2-digit year */
+ year += 1900;
+ if (year < 1996) /* no dates < spec 1.0 */
+ year += 100;
+ }
+
+ return year;
+}
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c
index 7ec6cfa01fb..9202b67c4b2 100644
--- a/arch/i386/kernel/efi.c
+++ b/arch/i386/kernel/efi.c
@@ -361,7 +361,7 @@ void __init efi_init(void)
*/
c16 = (efi_char16_t *) boot_ioremap(efi.systab->fw_vendor, 2);
if (c16) {
- for (i = 0; i < sizeof(vendor) && *c16; ++i)
+ for (i = 0; i < (sizeof(vendor) - 1) && *c16; ++i)
vendor[i] = *c16++;
vendor[i] = '\0';
} else
@@ -381,29 +381,38 @@ void __init efi_init(void)
if (config_tables == NULL)
printk(KERN_ERR PFX "Could not map EFI Configuration Table!\n");
+ efi.mps = EFI_INVALID_TABLE_ADDR;
+ efi.acpi = EFI_INVALID_TABLE_ADDR;
+ efi.acpi20 = EFI_INVALID_TABLE_ADDR;
+ efi.smbios = EFI_INVALID_TABLE_ADDR;
+ efi.sal_systab = EFI_INVALID_TABLE_ADDR;
+ efi.boot_info = EFI_INVALID_TABLE_ADDR;
+ efi.hcdp = EFI_INVALID_TABLE_ADDR;
+ efi.uga = EFI_INVALID_TABLE_ADDR;
+
for (i = 0; i < num_config_tables; i++) {
if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
- efi.mps = (void *)config_tables[i].table;
+ efi.mps = config_tables[i].table;
printk(KERN_INFO " MPS=0x%lx ", config_tables[i].table);
} else
if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) {
- efi.acpi20 = __va(config_tables[i].table);
+ efi.acpi20 = config_tables[i].table;
printk(KERN_INFO " ACPI 2.0=0x%lx ", config_tables[i].table);
} else
if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) {
- efi.acpi = __va(config_tables[i].table);
+ efi.acpi = config_tables[i].table;
printk(KERN_INFO " ACPI=0x%lx ", config_tables[i].table);
} else
if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
- efi.smbios = (void *) config_tables[i].table;
+ efi.smbios = config_tables[i].table;
printk(KERN_INFO " SMBIOS=0x%lx ", config_tables[i].table);
} else
if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
- efi.hcdp = (void *)config_tables[i].table;
+ efi.hcdp = config_tables[i].table;
printk(KERN_INFO " HCDP=0x%lx ", config_tables[i].table);
} else
if (efi_guidcmp(config_tables[i].guid, UGA_IO_PROTOCOL_GUID) == 0) {
- efi.uga = (void *)config_tables[i].table;
+ efi.uga = config_tables[i].table;
printk(KERN_INFO " UGA=0x%lx ", config_tables[i].table);
}
}
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 311b4e7266f..3b329af4afc 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -381,7 +381,7 @@ static void do_irq_balance(void)
unsigned long imbalance = 0;
cpumask_t allowed_mask, target_cpu_mask, tmp;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
int package_index;
CPU_IRQ(i) = 0;
if (!cpu_online(i))
@@ -632,7 +632,7 @@ static int __init balanced_irq_init(void)
else
printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
failed:
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
kfree(irq_cpu_data[i].irq_delta);
irq_cpu_data[i].irq_delta = NULL;
kfree(irq_cpu_data[i].last_irq);
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 7a59050242a..f19768789e8 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -35,12 +35,56 @@
#include <asm/cacheflush.h>
#include <asm/kdebug.h>
#include <asm/desc.h>
+#include <asm/uaccess.h>
void jprobe_return_end(void);
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+/* insert a jmp code */
+static inline void set_jmp_op(void *from, void *to)
+{
+ struct __arch_jmp_op {
+ char op;
+ long raddr;
+ } __attribute__((packed)) *jop;
+ jop = (struct __arch_jmp_op *)from;
+ jop->raddr = (long)(to) - ((long)(from) + 5);
+ jop->op = RELATIVEJUMP_INSTRUCTION;
+}
+
+/*
+ * returns non-zero if opcodes can be boosted.
+ */
+static inline int can_boost(kprobe_opcode_t opcode)
+{
+ switch (opcode & 0xf0 ) {
+ case 0x70:
+ return 0; /* can't boost conditional jump */
+ case 0x90:
+ /* can't boost call and pushf */
+ return opcode != 0x9a && opcode != 0x9c;
+ case 0xc0:
+ /* can't boost undefined opcodes and soft-interruptions */
+ return (0xc1 < opcode && opcode < 0xc6) ||
+ (0xc7 < opcode && opcode < 0xcc) || opcode == 0xcf;
+ case 0xd0:
+ /* can boost AA* and XLAT */
+ return (opcode == 0xd4 || opcode == 0xd5 || opcode == 0xd7);
+ case 0xe0:
+ /* can boost in/out and (may be) jmps */
+ return (0xe3 < opcode && opcode != 0xe8);
+ case 0xf0:
+ /* clear and set flags can be boost */
+ return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe));
+ default:
+ /* currently, can't boost 2 bytes opcodes */
+ return opcode != 0x0f;
+ }
+}
+
+
/*
* returns non-zero if opcode modifies the interrupt flag.
*/
@@ -65,6 +109,11 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
p->opcode = *p->addr;
+ if (can_boost(p->opcode)) {
+ p->ainsn.boostable = 0;
+ } else {
+ p->ainsn.boostable = -1;
+ }
return 0;
}
@@ -155,9 +204,13 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
int ret = 0;
- kprobe_opcode_t *addr = NULL;
- unsigned long *lp;
+ kprobe_opcode_t *addr;
struct kprobe_ctlblk *kcb;
+#ifdef CONFIG_PREEMPT
+ unsigned pre_preempt_count = preempt_count();
+#endif /* CONFIG_PREEMPT */
+
+ addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t));
/*
* We don't want to be preempted for the entire
@@ -166,17 +219,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
preempt_disable();
kcb = get_kprobe_ctlblk();
- /* 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 *) (get_desc_base(lp) + 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()) {
p = get_kprobe(addr);
@@ -252,6 +294,21 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
/* handler has already set things up, so skip ss setup */
return 1;
+ if (p->ainsn.boostable == 1 &&
+#ifdef CONFIG_PREEMPT
+ !(pre_preempt_count) && /*
+ * This enables booster when the direct
+ * execution path aren't preempted.
+ */
+#endif /* CONFIG_PREEMPT */
+ !p->post_handler && !p->break_handler ) {
+ /* Boost up -- we can execute copied instructions directly */
+ reset_current_kprobe();
+ regs->eip = (unsigned long)p->ainsn.insn;
+ preempt_enable_no_resched();
+ return 1;
+ }
+
ss_probe:
prepare_singlestep(p, regs);
kcb->kprobe_status = KPROBE_HIT_SS;
@@ -267,17 +324,44 @@ no_kprobe:
* here. When a retprobed function returns, this probe is hit and
* trampoline_probe_handler() runs, calling the kretprobe's handler.
*/
- void kretprobe_trampoline_holder(void)
+ void __kprobes kretprobe_trampoline_holder(void)
{
- asm volatile ( ".global kretprobe_trampoline\n"
+ asm volatile ( ".global kretprobe_trampoline\n"
"kretprobe_trampoline: \n"
- "nop\n");
- }
+ " pushf\n"
+ /* skip cs, eip, orig_eax, es, ds */
+ " subl $20, %esp\n"
+ " pushl %eax\n"
+ " pushl %ebp\n"
+ " pushl %edi\n"
+ " pushl %esi\n"
+ " pushl %edx\n"
+ " pushl %ecx\n"
+ " pushl %ebx\n"
+ " movl %esp, %eax\n"
+ " call trampoline_handler\n"
+ /* move eflags to cs */
+ " movl 48(%esp), %edx\n"
+ " movl %edx, 44(%esp)\n"
+ /* save true return address on eflags */
+ " movl %eax, 48(%esp)\n"
+ " popl %ebx\n"
+ " popl %ecx\n"
+ " popl %edx\n"
+ " popl %esi\n"
+ " popl %edi\n"
+ " popl %ebp\n"
+ " popl %eax\n"
+ /* skip eip, orig_eax, es, ds */
+ " addl $16, %esp\n"
+ " popf\n"
+ " ret\n");
+}
/*
- * Called when we hit the probe point at kretprobe_trampoline
+ * Called from kretprobe_trampoline
*/
-int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+fastcall void *__kprobes trampoline_handler(struct pt_regs *regs)
{
struct kretprobe_instance *ri = NULL;
struct hlist_head *head;
@@ -306,8 +390,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
/* another task is sharing our hash bucket */
continue;
- if (ri->rp && ri->rp->handler)
+ if (ri->rp && ri->rp->handler){
+ __get_cpu_var(current_kprobe) = &ri->rp->kp;
ri->rp->handler(ri, regs);
+ __get_cpu_var(current_kprobe) = NULL;
+ }
orig_ret_address = (unsigned long)ri->ret_addr;
recycle_rp_inst(ri);
@@ -322,18 +409,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
}
BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
- regs->eip = orig_ret_address;
- reset_current_kprobe();
spin_unlock_irqrestore(&kretprobe_lock, flags);
- preempt_enable_no_resched();
- /*
- * By returning a non-zero value, we are telling
- * kprobe_handler() that we don't want the post_handler
- * to run (and have re-enabled preemption)
- */
- return 1;
+ return (void*)orig_ret_address;
}
/*
@@ -357,15 +436,17 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
* 2) If the single-stepped instruction was a call, the return address
* that is atop the stack is the address following the copied instruction.
* We need to make it the address following the original instruction.
+ *
+ * This function also checks instruction size for preparing direct execution.
*/
static void __kprobes resume_execution(struct kprobe *p,
struct pt_regs *regs, struct kprobe_ctlblk *kcb)
{
unsigned long *tos = (unsigned long *)&regs->esp;
- unsigned long next_eip = 0;
unsigned long copy_eip = (unsigned long)p->ainsn.insn;
unsigned long orig_eip = (unsigned long)p->addr;
+ regs->eflags &= ~TF_MASK;
switch (p->ainsn.insn[0]) {
case 0x9c: /* pushfl */
*tos &= ~(TF_MASK | IF_MASK);
@@ -375,37 +456,51 @@ static void __kprobes resume_execution(struct kprobe *p,
case 0xcb:
case 0xc2:
case 0xca:
- regs->eflags &= ~TF_MASK;
- /* eip is already adjusted, no more changes required*/
- return;
+ case 0xea: /* jmp absolute -- eip is correct */
+ /* eip is already adjusted, no more changes required */
+ p->ainsn.boostable = 1;
+ goto no_change;
case 0xe8: /* call relative - Fix return addr */
*tos = orig_eip + (*tos - copy_eip);
break;
case 0xff:
if ((p->ainsn.insn[1] & 0x30) == 0x10) {
/* call absolute, indirect */
- /* Fix return addr; eip is correct. */
- next_eip = regs->eip;
+ /*
+ * Fix return addr; eip is correct.
+ * But this is not boostable
+ */
*tos = orig_eip + (*tos - copy_eip);
+ goto no_change;
} else if (((p->ainsn.insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */
((p->ainsn.insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */
- /* eip is correct. */
- next_eip = regs->eip;
+ /* eip is correct. And this is boostable */
+ p->ainsn.boostable = 1;
+ goto no_change;
}
- break;
- case 0xea: /* jmp absolute -- eip is correct */
- next_eip = regs->eip;
- break;
default:
break;
}
- regs->eflags &= ~TF_MASK;
- if (next_eip) {
- regs->eip = next_eip;
- } else {
- regs->eip = orig_eip + (regs->eip - copy_eip);
+ if (p->ainsn.boostable == 0) {
+ if ((regs->eip > copy_eip) &&
+ (regs->eip - copy_eip) + 5 < MAX_INSN_SIZE) {
+ /*
+ * These instructions can be executed directly if it
+ * jumps back to correct address.
+ */
+ set_jmp_op((void *)regs->eip,
+ (void *)orig_eip + (regs->eip - copy_eip));
+ p->ainsn.boostable = 1;
+ } else {
+ p->ainsn.boostable = -1;
+ }
}
+
+ regs->eip = orig_eip + (regs->eip - copy_eip);
+
+no_change:
+ return;
}
/*
@@ -453,15 +548,57 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
- return 1;
-
- if (kcb->kprobe_status & KPROBE_HIT_SS) {
- resume_execution(cur, regs, kcb);
+ switch(kcb->kprobe_status) {
+ case KPROBE_HIT_SS:
+ case KPROBE_REENTER:
+ /*
+ * We are here because the instruction being single
+ * stepped caused a page fault. We reset the current
+ * kprobe and the eip points back to the probe address
+ * and allow the page fault handler to continue as a
+ * normal page fault.
+ */
+ regs->eip = (unsigned long)cur->addr;
regs->eflags |= kcb->kprobe_old_eflags;
-
- reset_current_kprobe();
+ if (kcb->kprobe_status == KPROBE_REENTER)
+ restore_previous_kprobe(kcb);
+ else
+ reset_current_kprobe();
preempt_enable_no_resched();
+ break;
+ case KPROBE_HIT_ACTIVE:
+ case KPROBE_HIT_SSDONE:
+ /*
+ * We increment the nmissed count for accounting,
+ * we can also use npre/npostfault count for accouting
+ * these specific fault cases.
+ */
+ kprobes_inc_nmissed_count(cur);
+
+ /*
+ * We come here because instructions in the pre/post
+ * handler caused the page_fault, this could happen
+ * if handler tries to access user space by
+ * copy_from_user(), get_user() etc. Let the
+ * user-specified handler try to fix it first.
+ */
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+ return 1;
+
+ /*
+ * In case the user-specified fault handler returned
+ * zero, try to fix up.
+ */
+ if (fixup_exception(regs))
+ return 1;
+
+ /*
+ * fixup_exception() could not handle it,
+ * Let do_page_fault() fix it.
+ */
+ break;
+ default:
+ break;
}
return 0;
}
@@ -475,6 +612,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
struct die_args *args = (struct die_args *)data;
int ret = NOTIFY_DONE;
+ if (args->regs && user_mode(args->regs))
+ return ret;
+
switch (val) {
case DIE_INT3:
if (kprobe_handler(args->regs))
@@ -564,12 +704,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
return 0;
}
-static struct kprobe trampoline_p = {
- .addr = (kprobe_opcode_t *) &kretprobe_trampoline,
- .pre_handler = trampoline_probe_handler
-};
-
int __init arch_init_kprobes(void)
{
- return register_kprobe(&trampoline_p);
+ return 0;
}
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 5390b521aca..e7c138f66c5 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -81,6 +81,7 @@
#include <linux/miscdevice.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
+#include <linux/mutex.h>
#include <asm/msr.h>
#include <asm/uaccess.h>
@@ -114,7 +115,7 @@ MODULE_LICENSE("GPL");
static DEFINE_SPINLOCK(microcode_update_lock);
/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
-static DECLARE_MUTEX(microcode_sem);
+static DEFINE_MUTEX(microcode_mutex);
static void __user *user_buffer; /* user area microcode data buffer */
static unsigned int user_buffer_size; /* it's size */
@@ -202,8 +203,6 @@ static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_he
} else if (mc_header->rev == uci->rev) {
/* notify the caller of success on this cpu */
uci->err = MC_SUCCESS;
- printk(KERN_ERR "microcode: CPU%d already at revision"
- " 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
goto out;
}
@@ -369,7 +368,6 @@ static void do_update_one (void * unused)
struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
if (uci->mc == NULL) {
- printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num);
return;
}
@@ -447,7 +445,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
return -EINVAL;
}
- down(&microcode_sem);
+ mutex_lock(&microcode_mutex);
user_buffer = (void __user *) buf;
user_buffer_size = (int) len;
@@ -456,31 +454,14 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
if (!ret)
ret = (ssize_t)len;
- up(&microcode_sem);
+ mutex_unlock(&microcode_mutex);
return ret;
}
-static int microcode_ioctl (struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- switch (cmd) {
- /*
- * XXX: will be removed after microcode_ctl
- * is updated to ignore failure of this ioctl()
- */
- case MICROCODE_IOCFREE:
- return 0;
- default:
- return -EINVAL;
- }
- return -EINVAL;
-}
-
static struct file_operations microcode_fops = {
.owner = THIS_MODULE,
.write = microcode_write,
- .ioctl = microcode_ioctl,
.open = microcode_open,
};
@@ -511,7 +492,6 @@ static int __init microcode_init (void)
static void __exit microcode_exit (void)
{
misc_deregister(&microcode_dev);
- printk(KERN_INFO "IA-32 Microcode Update Driver v" MICROCODE_VERSION " unregistered\n");
}
module_init(microcode_init)
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 9074818b947..d43b498ec74 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -138,12 +138,12 @@ static int __init check_nmi_watchdog(void)
if (nmi_watchdog == NMI_LOCAL_APIC)
smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0);
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count;
local_irq_enable();
mdelay((10*1000)/nmi_hz); // wait 10 ticks
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
#ifdef CONFIG_SMP
/* Check cpu_callin_map here because that is set
after the timer is started. */
@@ -510,7 +510,7 @@ void touch_nmi_watchdog (void)
* Just reset the alert counters, (other CPUs might be
* spinning on locks we hold):
*/
- for_each_cpu(i)
+ for_each_possible_cpu(i)
alert_counter[i] = 0;
/*
@@ -529,7 +529,8 @@ void nmi_watchdog_tick (struct pt_regs * regs)
* always switch the stack NMI-atomically, it's safe to use
* smp_processor_id().
*/
- int sum, cpu = smp_processor_id();
+ unsigned int sum;
+ int cpu = smp_processor_id();
sum = per_cpu(irq_stat, cpu).apic_timer_irqs;
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 299e6167408..24b3e745478 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -38,7 +38,6 @@
#include <linux/kallsyms.h>
#include <linux/ptrace.h>
#include <linux/random.h>
-#include <linux/kprobes.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -364,13 +363,6 @@ void exit_thread(void)
struct task_struct *tsk = current;
struct thread_struct *t = &tsk->thread;
- /*
- * Remove function-return probe instances associated with this task
- * and put them back on the free list. Do not insert an exit probe for
- * this function, it will be disabled by kprobe_flush_task if you do.
- */
- kprobe_flush_task(tsk);
-
/* The process may have allocated an io port bitmap... nuke it. */
if (unlikely(NULL != t->io_bitmap_ptr)) {
int cpu = get_cpu();
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index d313a11acaf..8c08660b4e5 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -46,6 +46,7 @@
#include <linux/kexec.h>
#include <linux/crash_dump.h>
#include <linux/dmi.h>
+#include <linux/pfn.h>
#include <video/edid.h>
@@ -1058,10 +1059,10 @@ static int __init
free_available_memory(unsigned long start, unsigned long end, void *arg)
{
/* check max_low_pfn */
- if (start >= ((max_low_pfn + 1) << PAGE_SHIFT))
+ if (start >= (max_low_pfn << PAGE_SHIFT))
return 0;
- if (end >= ((max_low_pfn + 1) << PAGE_SHIFT))
- end = (max_low_pfn + 1) << PAGE_SHIFT;
+ if (end >= (max_low_pfn << PAGE_SHIFT))
+ end = max_low_pfn << PAGE_SHIFT;
if (start < end)
free_bootmem(start, end - start);
@@ -1286,8 +1287,6 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
probe_roms();
for (i = 0; i < e820.nr_map; i++) {
struct resource *res;
- if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
- continue;
res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
switch (e820.map[i].type) {
case E820_RAM: res->name = "System RAM"; break;
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 4c470e99a74..a6969903f2d 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -72,6 +72,9 @@ int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
/* Core ID of each logical CPU */
int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
+/* Last level cache ID of each logical CPU */
+int cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID};
+
/* representing HT siblings of each logical CPU */
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_sibling_map);
@@ -440,6 +443,18 @@ static void __devinit smp_callin(void)
static int cpucount;
+/* maps the cpu to the sched domain representing multi-core */
+cpumask_t cpu_coregroup_map(int cpu)
+{
+ struct cpuinfo_x86 *c = cpu_data + cpu;
+ /*
+ * For perf, we return last level cache shared map.
+ * TBD: when power saving sched policy is added, we will return
+ * cpu_core_map when power saving policy is enabled
+ */
+ return c->llc_shared_map;
+}
+
/* representing cpus for which sibling maps can be computed */
static cpumask_t cpu_sibling_setup_map;
@@ -459,12 +474,16 @@ set_cpu_sibling_map(int cpu)
cpu_set(cpu, cpu_sibling_map[i]);
cpu_set(i, cpu_core_map[cpu]);
cpu_set(cpu, cpu_core_map[i]);
+ cpu_set(i, c[cpu].llc_shared_map);
+ cpu_set(cpu, c[i].llc_shared_map);
}
}
} else {
cpu_set(cpu, cpu_sibling_map[cpu]);
}
+ cpu_set(cpu, c[cpu].llc_shared_map);
+
if (current_cpu_data.x86_max_cores == 1) {
cpu_core_map[cpu] = cpu_sibling_map[cpu];
c[cpu].booted_cores = 1;
@@ -472,6 +491,11 @@ set_cpu_sibling_map(int cpu)
}
for_each_cpu_mask(i, cpu_sibling_setup_map) {
+ if (cpu_llc_id[cpu] != BAD_APICID &&
+ cpu_llc_id[cpu] == cpu_llc_id[i]) {
+ cpu_set(i, c[cpu].llc_shared_map);
+ cpu_set(cpu, c[i].llc_shared_map);
+ }
if (phys_proc_id[cpu] == phys_proc_id[i]) {
cpu_set(i, cpu_core_map[cpu]);
cpu_set(cpu, cpu_core_map[i]);
@@ -1003,7 +1027,6 @@ void cpu_exit_clear(void)
cpu_clear(cpu, cpu_callout_map);
cpu_clear(cpu, cpu_callin_map);
- cpu_clear(cpu, cpu_present_map);
cpu_clear(cpu, smp_commenced_mask);
unmap_cpu_to_logical_apicid(cpu);
@@ -1015,31 +1038,20 @@ struct warm_boot_cpu_info {
int cpu;
};
-static void __devinit do_warm_boot_cpu(void *p)
+static void __cpuinit do_warm_boot_cpu(void *p)
{
struct warm_boot_cpu_info *info = p;
do_boot_cpu(info->apicid, info->cpu);
complete(info->complete);
}
-int __devinit smp_prepare_cpu(int cpu)
+static int __cpuinit __smp_prepare_cpu(int cpu)
{
DECLARE_COMPLETION(done);
struct warm_boot_cpu_info info;
struct work_struct task;
int apicid, ret;
- lock_cpu_hotplug();
-
- /*
- * On x86, CPU0 is never offlined. Trying to bring up an
- * already-booted CPU will hang. So check for that case.
- */
- if (cpu_online(cpu)) {
- ret = -EINVAL;
- goto exit;
- }
-
apicid = x86_cpu_to_apicid[cpu];
if (apicid == BAD_APICID) {
ret = -ENODEV;
@@ -1064,7 +1076,6 @@ int __devinit smp_prepare_cpu(int cpu)
zap_low_mappings();
ret = 0;
exit:
- unlock_cpu_hotplug();
return ret;
}
#endif
@@ -1392,6 +1403,22 @@ void __cpu_die(unsigned int cpu)
int __devinit __cpu_up(unsigned int cpu)
{
+#ifdef CONFIG_HOTPLUG_CPU
+ int ret=0;
+
+ /*
+ * We do warm boot only on cpus that had booted earlier
+ * Otherwise cold boot is all handled from smp_boot_cpus().
+ * cpu_callin_map is set during AP kickstart process. Its reset
+ * when a cpu is taken offline from cpu_exit_clear().
+ */
+ if (!cpu_isset(cpu, cpu_callin_map))
+ ret = __smp_prepare_cpu(cpu);
+
+ if (ret)
+ return -EIO;
+#endif
+
/* In case one didn't come up */
if (!cpu_isset(cpu, cpu_callin_map)) {
printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu);
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index ac687d00a1c..326595f3fa4 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -310,3 +310,5 @@ ENTRY(sys_call_table)
.long sys_pselect6
.long sys_ppoll
.long sys_unshare /* 310 */
+ .long sys_set_robust_list
+ .long sys_get_robust_list
diff --git a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c
index 264edaaac31..144e94a0493 100644
--- a/arch/i386/kernel/timers/timer_pm.c
+++ b/arch/i386/kernel/timers/timer_pm.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/device.h>
#include <linux/init.h>
+#include <linux/pci.h>
#include <asm/types.h>
#include <asm/timer.h>
#include <asm/smp.h>
@@ -45,24 +46,31 @@ static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */
+static int pmtmr_need_workaround __read_mostly = 1;
+
/*helper function to safely read acpi pm timesource*/
static inline u32 read_pmtmr(void)
{
- u32 v1=0,v2=0,v3=0;
- /* It has been reported that because of various broken
- * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time
- * source is not latched, so you must read it multiple
- * times to insure a safe value is read.
- */
- do {
- v1 = inl(pmtmr_ioport);
- v2 = inl(pmtmr_ioport);
- v3 = inl(pmtmr_ioport);
- } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
- || (v3 > v1 && v3 < v2));
-
- /* mask the output to 24 bits */
- return v2 & ACPI_PM_MASK;
+ if (pmtmr_need_workaround) {
+ u32 v1, v2, v3;
+
+ /* It has been reported that because of various broken
+ * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time
+ * source is not latched, so you must read it multiple
+ * times to insure a safe value is read.
+ */
+ do {
+ v1 = inl(pmtmr_ioport);
+ v2 = inl(pmtmr_ioport);
+ v3 = inl(pmtmr_ioport);
+ } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
+ || (v3 > v1 && v3 < v2));
+
+ /* mask the output to 24 bits */
+ return v2 & ACPI_PM_MASK;
+ }
+
+ return inl(pmtmr_ioport) & ACPI_PM_MASK;
}
@@ -263,6 +271,72 @@ struct init_timer_opts __initdata timer_pmtmr_init = {
.opts = &timer_pmtmr,
};
+#ifdef CONFIG_PCI
+/*
+ * PIIX4 Errata:
+ *
+ * The power management timer may return improper results when read.
+ * Although the timer value settles properly after incrementing,
+ * while incrementing there is a 3 ns window every 69.8 ns where the
+ * timer value is indeterminate (a 4.2% chance that the data will be
+ * incorrect when read). As a result, the ACPI free running count up
+ * timer specification is violated due to erroneous reads.
+ */
+static int __init pmtmr_bug_check(void)
+{
+ static struct pci_device_id gray_list[] __initdata = {
+ /* these chipsets may have bug. */
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82801DB_0) },
+ { },
+ };
+ struct pci_dev *dev;
+ int pmtmr_has_bug = 0;
+ u8 rev;
+
+ if (cur_timer != &timer_pmtmr || !pmtmr_need_workaround)
+ return 0;
+
+ dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
+ if (dev) {
+ pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+ /* the bug has been fixed in PIIX4M */
+ if (rev < 3) {
+ printk(KERN_WARNING "* Found PM-Timer Bug on this "
+ "chipset. Due to workarounds for a bug,\n"
+ "* this time source is slow. Consider trying "
+ "other time sources (clock=)\n");
+ pmtmr_has_bug = 1;
+ }
+ pci_dev_put(dev);
+ }
+
+ if (pci_dev_present(gray_list)) {
+ printk(KERN_WARNING "* This chipset may have PM-Timer Bug. Due"
+ " to workarounds for a bug,\n"
+ "* this time source is slow. If you are sure your timer"
+ " does not have\n"
+ "* this bug, please use \"pmtmr_good\" to disable the "
+ "workaround\n");
+ pmtmr_has_bug = 1;
+ }
+
+ if (!pmtmr_has_bug)
+ pmtmr_need_workaround = 0;
+
+ return 0;
+}
+device_initcall(pmtmr_bug_check);
+#endif
+
+static int __init pmtr_good_setup(char *__str)
+{
+ pmtmr_need_workaround = 0;
+ return 1;
+}
+__setup("pmtmr_good", pmtr_good_setup);
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
MODULE_DESCRIPTION("Power Management Timer (PMTMR) as primary timing source for x86");
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index de5386b01d3..6b63a5aa1e4 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -92,22 +92,21 @@ asmlinkage void spurious_interrupt_bug(void);
asmlinkage void machine_check(void);
static int kstack_depth_to_print = 24;
-struct notifier_block *i386die_chain;
-static DEFINE_SPINLOCK(die_notifier_lock);
+ATOMIC_NOTIFIER_HEAD(i386die_chain);
int register_die_notifier(struct notifier_block *nb)
{
- int err = 0;
- unsigned long flags;
-
vmalloc_sync_all();
- spin_lock_irqsave(&die_notifier_lock, flags);
- err = notifier_chain_register(&i386die_chain, nb);
- spin_unlock_irqrestore(&die_notifier_lock, flags);
- return err;
+ return atomic_notifier_chain_register(&i386die_chain, nb);
}
EXPORT_SYMBOL(register_die_notifier);
+int unregister_die_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&i386die_chain, nb);
+}
+EXPORT_SYMBOL(unregister_die_notifier);
+
static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
{
return p > (void *)tinfo &&
@@ -386,8 +385,12 @@ void die(const char * str, struct pt_regs * regs, long err)
#endif
if (nl)
printk("\n");
- notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
- show_registers(regs);
+ if (notify_die(DIE_OOPS, str, regs, err,
+ current->thread.trap_no, SIGSEGV) !=
+ NOTIFY_STOP)
+ show_registers(regs);
+ else
+ regs = NULL;
} else
printk(KERN_EMERG "Recursive die() failure, output suppressed\n");
@@ -395,6 +398,9 @@ void die(const char * str, struct pt_regs * regs, long err)
die.lock_owner = -1;
spin_unlock_irqrestore(&die.lock, flags);
+ if (!regs)
+ return;
+
if (kexec_should_crash(current))
crash_kexec(regs);
@@ -623,7 +629,7 @@ static DEFINE_SPINLOCK(nmi_print_lock);
void die_nmi (struct pt_regs *regs, const char *msg)
{
- if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 0, SIGINT) ==
+ if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) ==
NOTIFY_STOP)
return;
@@ -662,7 +668,7 @@ static void default_do_nmi(struct pt_regs * regs)
reason = get_nmi_reason();
if (!(reason & 0xc0)) {
- if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
+ if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
== NOTIFY_STOP)
return;
#ifdef CONFIG_X86_LOCAL_APIC
@@ -678,7 +684,7 @@ static void default_do_nmi(struct pt_regs * regs)
unknown_nmi_error(reason, regs);
return;
}
- if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP)
+ if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
return;
if (reason & 0x80)
mem_parity_error(reason, regs);
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index f51c894a7da..aee14fafd13 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -43,6 +43,7 @@
#include <linux/smp_lock.h>
#include <linux/highmem.h>
#include <linux/ptrace.h>
+#include <linux/audit.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -252,6 +253,7 @@ out:
static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk)
{
struct tss_struct *tss;
+ long eax;
/*
* make sure the vm86() system call doesn't try to do anything silly
*/
@@ -305,13 +307,19 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
tsk->thread.screen_bitmap = info->screen_bitmap;
if (info->flags & VM86_SCREEN_BITMAP)
mark_screen_rdonly(tsk->mm);
+ __asm__ __volatile__("xorl %eax,%eax; movl %eax,%fs; movl %eax,%gs\n\t");
+ __asm__ __volatile__("movl %%eax, %0\n" :"=r"(eax));
+
+ /*call audit_syscall_exit since we do not exit via the normal paths */
+ if (unlikely(current->audit_context))
+ audit_syscall_exit(current, AUDITSC_RESULT(eax), eax);
+
__asm__ __volatile__(
- "xorl %%eax,%%eax; movl %%eax,%%fs; movl %%eax,%%gs\n\t"
"movl %0,%%esp\n\t"
"movl %1,%%ebp\n\t"
"jmp resume_userspace"
: /* no outputs */
- :"r" (&info->regs), "r" (task_thread_info(tsk)) : "ax");
+ :"r" (&info->regs), "r" (task_thread_info(tsk)));
/* we never return here */
}
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index 3f21c6f6466..8831303a473 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -7,6 +7,7 @@
#include <asm-generic/vmlinux.lds.h>
#include <asm/thread_info.h>
#include <asm/page.h>
+#include <asm/cache.h>
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
@@ -135,7 +136,7 @@ SECTIONS
__initramfs_start = .;
.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) }
__initramfs_end = .;
- . = ALIGN(32);
+ . = ALIGN(L1_CACHE_BYTES);
__per_cpu_start = .;
.data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
__per_cpu_end = .;
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index 8165626a5c3..70e560a1b79 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -1700,7 +1700,7 @@ after_handle_vic_irq(unsigned int irq)
printk("VOYAGER SMP: CPU%d lost interrupt %d\n",
cpu, irq);
- for_each_cpu(real_cpu, mask) {
+ for_each_possible_cpu(real_cpu, mask) {
outb(VIC_CPU_MASQUERADE_ENABLE | real_cpu,
VIC_PROCESSOR_ID);
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index c4af9638dbf..fe6eb901326 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -31,6 +31,7 @@
#include <linux/nodemask.h>
#include <linux/module.h>
#include <linux/kexec.h>
+#include <linux/pfn.h>
#include <asm/e820.h>
#include <asm/setup.h>
@@ -352,17 +353,6 @@ void __init zone_sizes_init(void)
{
int nid;
- /*
- * Insert nodes into pgdat_list backward so they appear in order.
- * Clobber node 0's links and NULL out pgdat_list before starting.
- */
- pgdat_list = NULL;
- for (nid = MAX_NUMNODES - 1; nid >= 0; nid--) {
- if (!node_online(nid))
- continue;
- NODE_DATA(nid)->pgdat_next = pgdat_list;
- pgdat_list = NODE_DATA(nid);
- }
for_each_online_node(nid) {
unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
index 9db3242103b..2889567e21a 100644
--- a/arch/i386/mm/pgtable.c
+++ b/arch/i386/mm/pgtable.c
@@ -36,7 +36,7 @@ void show_mem(void)
printk(KERN_INFO "Mem-info:\n");
show_free_areas();
printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
pgdat_resize_lock(pgdat, &flags);
for (i = 0; i < pgdat->node_spanned_pages; ++i) {
page = pgdat_page_nr(pgdat, i);
diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
index 1accce50c2c..1a2076ce6f6 100644
--- a/arch/i386/oprofile/nmi_int.c
+++ b/arch/i386/oprofile/nmi_int.c
@@ -122,7 +122,7 @@ static void nmi_save_registers(void * dummy)
static void free_msrs(void)
{
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
kfree(cpu_msrs[i].counters);
cpu_msrs[i].counters = NULL;
kfree(cpu_msrs[i].controls);
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index ff7ae6b664e..edffe25a477 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -34,6 +34,10 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default y
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
@@ -42,6 +46,10 @@ config TIME_INTERPOLATION
bool
default y
+config DMI
+ bool
+ default y
+
config EFI
bool
default y
@@ -252,6 +260,15 @@ config NR_CPUS
than 64 will cause the use of a CPU mask array, causing a small
performance hit.
+config IA64_NR_NODES
+ int "Maximum number of NODEs (256-1024)" if (IA64_SGI_SN2 || IA64_GENERIC)
+ range 256 1024
+ depends on IA64_SGI_SN2 || IA64_GENERIC
+ default "256"
+ help
+ This option specifies the maximum number of nodes in your SSI system.
+ If in doubt, use the default.
+
config HOTPLUG_CPU
bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
depends on SMP && EXPERIMENTAL
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index f722e1a2594..80ea7506fa1 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -1,6 +1,9 @@
#
# ia64/Makefile
#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
@@ -62,7 +65,7 @@ drivers-$(CONFIG_OPROFILE) += arch/ia64/oprofile/
boot := arch/ia64/hp/sim/boot
-.PHONY: boot compressed check
+PHONY += boot compressed check
all: compressed unwcheck
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
index 744fd2f79f6..0d29aa2066b 100644
--- a/arch/ia64/configs/gensparse_defconfig
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -116,6 +116,7 @@ CONFIG_IOSAPIC=y
CONFIG_FORCE_MAX_ZONEORDER=17
CONFIG_SMP=y
CONFIG_NR_CPUS=512
+CONFIG_IA64_NR_NODES=256
CONFIG_HOTPLUG_CPU=y
# CONFIG_SCHED_SMT is not set
# CONFIG_PREEMPT is not set
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index 8206752161b..a718034d68d 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -116,6 +116,7 @@ CONFIG_IA64_SGI_SN_XP=m
CONFIG_FORCE_MAX_ZONEORDER=17
CONFIG_SMP=y
CONFIG_NR_CPUS=1024
+CONFIG_IA64_NR_NODES=256
# CONFIG_HOTPLUG_CPU is not set
CONFIG_SCHED_SMT=y
CONFIG_PREEMPT=y
diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig
index 3e767288a74..6cba55da572 100644
--- a/arch/ia64/defconfig
+++ b/arch/ia64/defconfig
@@ -116,6 +116,7 @@ CONFIG_IOSAPIC=y
CONFIG_FORCE_MAX_ZONEORDER=17
CONFIG_SMP=y
CONFIG_NR_CPUS=512
+CONFIG_IA64_NR_NODES=256
CONFIG_HOTPLUG_CPU=y
# CONFIG_SCHED_SMT is not set
# CONFIG_PREEMPT is not set
diff --git a/arch/ia64/dig/setup.c b/arch/ia64/dig/setup.c
index c9104bfff66..38aa9c10885 100644
--- a/arch/ia64/dig/setup.c
+++ b/arch/ia64/dig/setup.c
@@ -69,8 +69,3 @@ dig_setup (char **cmdline_p)
screen_info.orig_video_isVGA = 1; /* XXX fake */
screen_info.orig_video_ega_bx = 3; /* XXX fake */
}
-
-void __init
-dig_irq_init (void)
-{
-}
diff --git a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h
index 68ceb4e690c..ccb98ed48e5 100644
--- a/arch/ia64/ia32/ia32priv.h
+++ b/arch/ia64/ia32/ia32priv.h
@@ -29,9 +29,9 @@
struct partial_page {
struct partial_page *next; /* linked list, sorted by address */
struct rb_node pp_rb;
- /* 64K is the largest "normal" page supported by ia64 ABI. So 4K*32
+ /* 64K is the largest "normal" page supported by ia64 ABI. So 4K*64
* should suffice.*/
- unsigned int bitmap;
+ unsigned long bitmap;
unsigned int base;
};
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 70dba1f0e2e..5366b3b23d0 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -25,7 +25,6 @@
#include <linux/resource.h>
#include <linux/times.h>
#include <linux/utsname.h>
-#include <linux/timex.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
@@ -1166,19 +1165,7 @@ put_tv32 (struct compat_timeval __user *o, struct timeval *i)
asmlinkage unsigned long
sys32_alarm (unsigned int seconds)
{
- struct itimerval it_new, it_old;
- unsigned int oldalarm;
-
- it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
- it_new.it_value.tv_sec = seconds;
- it_new.it_value.tv_usec = 0;
- do_setitimer(ITIMER_REAL, &it_new, &it_old);
- oldalarm = it_old.it_value.tv_sec;
- /* ehhh.. We can't return 0 if we have an alarm pending.. */
- /* And we'd better return too much than too little anyway */
- if (it_old.it_value.tv_usec)
- oldalarm++;
- return oldalarm;
+ return alarm_setitimer(seconds);
}
/* Translations due to time_t size differences. Which affects all
@@ -2603,78 +2590,4 @@ sys32_setresgid(compat_gid_t rgid, compat_gid_t egid,
ssgid = (sgid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)sgid);
return sys_setresgid(srgid, segid, ssgid);
}
-
-/* Handle adjtimex compatibility. */
-
-struct timex32 {
- u32 modes;
- s32 offset, freq, maxerror, esterror;
- s32 status, constant, precision, tolerance;
- struct compat_timeval time;
- s32 tick;
- s32 ppsfreq, jitter, shift, stabil;
- s32 jitcnt, calcnt, errcnt, stbcnt;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
-};
-
-extern int do_adjtimex(struct timex *);
-
-asmlinkage long
-sys32_adjtimex(struct timex32 *utp)
-{
- struct timex txc;
- int ret;
-
- memset(&txc, 0, sizeof(struct timex));
-
- if(get_user(txc.modes, &utp->modes) ||
- __get_user(txc.offset, &utp->offset) ||
- __get_user(txc.freq, &utp->freq) ||
- __get_user(txc.maxerror, &utp->maxerror) ||
- __get_user(txc.esterror, &utp->esterror) ||
- __get_user(txc.status, &utp->status) ||
- __get_user(txc.constant, &utp->constant) ||
- __get_user(txc.precision, &utp->precision) ||
- __get_user(txc.tolerance, &utp->tolerance) ||
- __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __get_user(txc.tick, &utp->tick) ||
- __get_user(txc.ppsfreq, &utp->ppsfreq) ||
- __get_user(txc.jitter, &utp->jitter) ||
- __get_user(txc.shift, &utp->shift) ||
- __get_user(txc.stabil, &utp->stabil) ||
- __get_user(txc.jitcnt, &utp->jitcnt) ||
- __get_user(txc.calcnt, &utp->calcnt) ||
- __get_user(txc.errcnt, &utp->errcnt) ||
- __get_user(txc.stbcnt, &utp->stbcnt))
- return -EFAULT;
-
- ret = do_adjtimex(&txc);
-
- if(put_user(txc.modes, &utp->modes) ||
- __put_user(txc.offset, &utp->offset) ||
- __put_user(txc.freq, &utp->freq) ||
- __put_user(txc.maxerror, &utp->maxerror) ||
- __put_user(txc.esterror, &utp->esterror) ||
- __put_user(txc.status, &utp->status) ||
- __put_user(txc.constant, &utp->constant) ||
- __put_user(txc.precision, &utp->precision) ||
- __put_user(txc.tolerance, &utp->tolerance) ||
- __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __put_user(txc.tick, &utp->tick) ||
- __put_user(txc.ppsfreq, &utp->ppsfreq) ||
- __put_user(txc.jitter, &utp->jitter) ||
- __put_user(txc.shift, &utp->shift) ||
- __put_user(txc.stabil, &utp->stabil) ||
- __put_user(txc.jitcnt, &utp->jitcnt) ||
- __put_user(txc.calcnt, &utp->calcnt) ||
- __put_user(txc.errcnt, &utp->errcnt) ||
- __put_user(txc.stbcnt, &utp->stbcnt))
- ret = -EFAULT;
-
- return ret;
-}
#endif /* NOTYET */
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 09a0dbc17fb..59e871dae74 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := head.o init_task.o vmlinux.lds
obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \
irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \
salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
- unwind.o mca.o mca_asm.o topology.o
+ unwind.o mca.o mca_asm.o topology.o dmi_scan.o
obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o
@@ -30,6 +30,7 @@ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
mca_recovery-y += mca_drv.o mca_drv_asm.o
+dmi_scan-y += ../../i386/kernel/dmi_scan.o
# The gate DSO image is built using a special linker script.
targets += gate.so gate-syms.o
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 4722ec51c70..58c93a30348 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -420,6 +420,26 @@ int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS];
int __initdata nid_to_pxm_map[MAX_NUMNODES];
static struct acpi_table_slit __initdata *slit_table;
+static int get_processor_proximity_domain(struct acpi_table_processor_affinity *pa)
+{
+ int pxm;
+
+ pxm = pa->proximity_domain;
+ if (ia64_platform_is("sn2"))
+ pxm += pa->reserved[0] << 8;
+ return pxm;
+}
+
+static int get_memory_proximity_domain(struct acpi_table_memory_affinity *ma)
+{
+ int pxm;
+
+ pxm = ma->proximity_domain;
+ if (ia64_platform_is("sn2"))
+ pxm += ma->reserved1[0] << 8;
+ return pxm;
+}
+
/*
* ACPI 2.0 SLIT (System Locality Information Table)
* http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf
@@ -443,13 +463,20 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
void __init
acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
{
+ int pxm;
+
+ if (!pa->flags.enabled)
+ return;
+
+ pxm = get_processor_proximity_domain(pa);
+
/* record this node in proximity bitmap */
- pxm_bit_set(pa->proximity_domain);
+ pxm_bit_set(pxm);
node_cpuid[srat_num_cpus].phys_id =
(pa->apic_id << 8) | (pa->lsapic_eid);
/* nid should be overridden as logical node id later */
- node_cpuid[srat_num_cpus].nid = pa->proximity_domain;
+ node_cpuid[srat_num_cpus].nid = pxm;
srat_num_cpus++;
}
@@ -457,10 +484,10 @@ void __init
acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
{
unsigned long paddr, size;
- u8 pxm;
+ int pxm;
struct node_memblk_s *p, *q, *pend;
- pxm = ma->proximity_domain;
+ pxm = get_memory_proximity_domain(ma);
/* fill node memory chunk structure */
paddr = ma->base_addr_hi;
@@ -624,9 +651,9 @@ unsigned long __init acpi_find_rsdp(void)
{
unsigned long rsdp_phys = 0;
- if (efi.acpi20)
- rsdp_phys = __pa(efi.acpi20);
- else if (efi.acpi)
+ if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
+ rsdp_phys = efi.acpi20;
+ else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
printk(KERN_WARNING PREFIX
"v1.0/r0.71 tables no longer supported\n");
return rsdp_phys;
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 9990320b6f9..12cfedce73b 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -458,24 +458,33 @@ efi_init (void)
printk(KERN_INFO "EFI v%u.%.02u by %s:",
efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
+ efi.mps = EFI_INVALID_TABLE_ADDR;
+ efi.acpi = EFI_INVALID_TABLE_ADDR;
+ efi.acpi20 = EFI_INVALID_TABLE_ADDR;
+ efi.smbios = EFI_INVALID_TABLE_ADDR;
+ efi.sal_systab = EFI_INVALID_TABLE_ADDR;
+ efi.boot_info = EFI_INVALID_TABLE_ADDR;
+ efi.hcdp = EFI_INVALID_TABLE_ADDR;
+ efi.uga = EFI_INVALID_TABLE_ADDR;
+
for (i = 0; i < (int) efi.systab->nr_tables; i++) {
if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
- efi.mps = __va(config_tables[i].table);
+ efi.mps = config_tables[i].table;
printk(" MPS=0x%lx", config_tables[i].table);
} else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) {
- efi.acpi20 = __va(config_tables[i].table);
+ efi.acpi20 = config_tables[i].table;
printk(" ACPI 2.0=0x%lx", config_tables[i].table);
} else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) {
- efi.acpi = __va(config_tables[i].table);
+ efi.acpi = config_tables[i].table;
printk(" ACPI=0x%lx", config_tables[i].table);
} else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
- efi.smbios = __va(config_tables[i].table);
+ efi.smbios = config_tables[i].table;
printk(" SMBIOS=0x%lx", config_tables[i].table);
} else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) {
- efi.sal_systab = __va(config_tables[i].table);
+ efi.sal_systab = config_tables[i].table;
printk(" SALsystab=0x%lx", config_tables[i].table);
} else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
- efi.hcdp = __va(config_tables[i].table);
+ efi.hcdp = config_tables[i].table;
printk(" HCDP=0x%lx", config_tables[i].table);
}
}
@@ -677,27 +686,34 @@ EXPORT_SYMBOL(efi_mem_attributes);
/*
* Determines whether the memory at phys_addr supports the desired
* attribute (WB, UC, etc). If this returns 1, the caller can safely
- * access *size bytes at phys_addr with the specified attribute.
+ * access size bytes at phys_addr with the specified attribute.
*/
-static int
-efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr)
+int
+efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, u64 attr)
{
+ unsigned long end = phys_addr + size;
efi_memory_desc_t *md = efi_memory_descriptor(phys_addr);
- unsigned long md_end;
- if (!md || (md->attribute & attr) != attr)
+ /*
+ * Some firmware doesn't report MMIO regions in the EFI memory
+ * map. The Intel BigSur (a.k.a. HP i2000) has this problem.
+ * On those platforms, we have to assume UC is valid everywhere.
+ */
+ if (!md || (md->attribute & attr) != attr) {
+ if (attr == EFI_MEMORY_UC && !efi_memmap_has_mmio())
+ return 1;
return 0;
+ }
do {
- md_end = efi_md_end(md);
- if (phys_addr + *size <= md_end)
+ unsigned long md_end = efi_md_end(md);
+
+ if (end <= md_end)
return 1;
md = efi_memory_descriptor(md_end);
- if (!md || (md->attribute & attr) != attr) {
- *size = md_end - phys_addr;
- return 1;
- }
+ if (!md || (md->attribute & attr) != attr)
+ return 0;
} while (md);
return 0;
}
@@ -708,7 +724,7 @@ efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr)
* control access size.
*/
int
-valid_phys_addr_range (unsigned long phys_addr, unsigned long *size)
+valid_phys_addr_range (unsigned long phys_addr, unsigned long size)
{
return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB);
}
@@ -723,7 +739,7 @@ valid_phys_addr_range (unsigned long phys_addr, unsigned long *size)
* because that doesn't appear in the boot-time EFI memory map.
*/
int
-valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size)
+valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long size)
{
if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB))
return 1;
@@ -731,14 +747,6 @@ valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size)
if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC))
return 1;
- /*
- * Some firmware doesn't report MMIO regions in the EFI memory map.
- * The Intel BigSur (a.k.a. HP i2000) has this problem. In this
- * case, we can't use the EFI memory map to validate mmap requests.
- */
- if (!efi_memmap_has_mmio())
- return 1;
-
return 0;
}
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index dcd906fe574..829a43cab79 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -865,6 +865,7 @@ ENTRY(interrupt)
;;
SAVE_REST
;;
+ MCA_RECOVER_RANGE(interrupt)
alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
mov out0=cr.ivr // pass cr.ivr as first arg
add out1=16,sp // pass pointer to pt_regs as second arg
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 50ae8c7d453..789881ca83d 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -34,6 +34,7 @@
#include <asm/pgtable.h>
#include <asm/kdebug.h>
#include <asm/sections.h>
+#include <asm/uaccess.h>
extern void jprobe_inst_return(void);
@@ -722,13 +723,50 @@ static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
- return 1;
- if (kcb->kprobe_status & KPROBE_HIT_SS) {
- resume_execution(cur, regs);
- reset_current_kprobe();
+ switch(kcb->kprobe_status) {
+ case KPROBE_HIT_SS:
+ case KPROBE_REENTER:
+ /*
+ * We are here because the instruction being single
+ * stepped caused a page fault. We reset the current
+ * kprobe and the instruction pointer points back to
+ * the probe address and allow the page fault handler
+ * to continue as a normal page fault.
+ */
+ regs->cr_iip = ((unsigned long)cur->addr) & ~0xFULL;
+ ia64_psr(regs)->ri = ((unsigned long)cur->addr) & 0xf;
+ if (kcb->kprobe_status == KPROBE_REENTER)
+ restore_previous_kprobe(kcb);
+ else
+ reset_current_kprobe();
preempt_enable_no_resched();
+ break;
+ case KPROBE_HIT_ACTIVE:
+ case KPROBE_HIT_SSDONE:
+ /*
+ * We increment the nmissed count for accounting,
+ * we can also use npre/npostfault count for accouting
+ * these specific fault cases.
+ */
+ kprobes_inc_nmissed_count(cur);
+
+ /*
+ * We come here because instructions in the pre/post
+ * handler caused the page_fault, this could happen
+ * if handler tries to access user space by
+ * copy_from_user(), get_user() etc. Let the
+ * user-specified handler try to fix it first.
+ */
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+ return 1;
+
+ /*
+ * Let ia64_do_page_fault() fix it.
+ */
+ break;
+ default:
+ break;
}
return 0;
@@ -740,6 +778,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
struct die_args *args = (struct die_args *)data;
int ret = NOTIFY_DONE;
+ if (args->regs && user_mode(args->regs))
+ return ret;
+
switch(val) {
case DIE_BREAK:
/* err is break number from ia64_bad_break() */
diff --git a/arch/ia64/kernel/machvec.c b/arch/ia64/kernel/machvec.c
index c3a04ee7f4f..4b0b71d5aef 100644
--- a/arch/ia64/kernel/machvec.c
+++ b/arch/ia64/kernel/machvec.c
@@ -14,7 +14,15 @@
struct ia64_machine_vector ia64_mv;
EXPORT_SYMBOL(ia64_mv);
-static struct ia64_machine_vector *
+static __initdata const char *mvec_name;
+static __init int setup_mvec(char *s)
+{
+ mvec_name = s;
+ return 0;
+}
+early_param("machvec", setup_mvec);
+
+static struct ia64_machine_vector * __init
lookup_machvec (const char *name)
{
extern struct ia64_machine_vector machvec_start[];
@@ -33,10 +41,13 @@ machvec_init (const char *name)
{
struct ia64_machine_vector *mv;
+ if (!name)
+ name = mvec_name ? mvec_name : acpi_get_sysname();
mv = lookup_machvec(name);
- if (!mv) {
- panic("generic kernel failed to find machine vector for platform %s!", name);
- }
+ if (!mv)
+ panic("generic kernel failed to find machine vector for"
+ " platform %s!", name);
+
ia64_mv = *mv;
printk(KERN_INFO "booting generic kernel on platform %s\n", name);
}
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index b57e723f194..8963171788d 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -69,6 +69,7 @@
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/workqueue.h>
+#include <linux/cpumask.h>
#include <asm/delay.h>
#include <asm/kdebug.h>
@@ -83,6 +84,7 @@
#include <asm/irq.h>
#include <asm/hw_irq.h>
+#include "mca_drv.h"
#include "entry.h"
#if defined(IA64_MCA_DEBUG_INFO)
@@ -133,7 +135,7 @@ static int cpe_poll_enabled = 1;
extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe);
-static int mca_init;
+static int mca_init __initdata;
static void inline
@@ -184,7 +186,7 @@ static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES];
* Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
* Outputs : None
*/
-static void
+static void __init
ia64_log_init(int sal_info_type)
{
u64 max_size = 0;
@@ -281,6 +283,50 @@ ia64_mca_log_sal_error_record(int sal_info_type)
ia64_sal_clear_state_info(sal_info_type);
}
+/*
+ * search_mca_table
+ * See if the MCA surfaced in an instruction range
+ * that has been tagged as recoverable.
+ *
+ * Inputs
+ * first First address range to check
+ * last Last address range to check
+ * ip Instruction pointer, address we are looking for
+ *
+ * Return value:
+ * 1 on Success (in the table)/ 0 on Failure (not in the table)
+ */
+int
+search_mca_table (const struct mca_table_entry *first,
+ const struct mca_table_entry *last,
+ unsigned long ip)
+{
+ const struct mca_table_entry *curr;
+ u64 curr_start, curr_end;
+
+ curr = first;
+ while (curr <= last) {
+ curr_start = (u64) &curr->start_addr + curr->start_addr;
+ curr_end = (u64) &curr->end_addr + curr->end_addr;
+
+ if ((ip >= curr_start) && (ip <= curr_end)) {
+ return 1;
+ }
+ curr++;
+ }
+ return 0;
+}
+
+/* Given an address, look for it in the mca tables. */
+int mca_recover_range(unsigned long addr)
+{
+ extern struct mca_table_entry __start___mca_table[];
+ extern struct mca_table_entry __stop___mca_table[];
+
+ return search_mca_table(__start___mca_table, __stop___mca_table-1, addr);
+}
+EXPORT_SYMBOL_GPL(mca_recover_range);
+
#ifdef CONFIG_ACPI
int cpe_vector = -1;
@@ -355,7 +401,7 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
* Outputs
* None
*/
-static void
+static void __init
ia64_mca_register_cpev (int cpev)
{
/* Register the CPE interrupt vector with SAL */
@@ -386,7 +432,7 @@ ia64_mca_register_cpev (int cpev)
* Outputs
* None
*/
-void
+void __cpuinit
ia64_mca_cmc_vector_setup (void)
{
cmcv_reg_t cmcv;
@@ -747,31 +793,34 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
ia64_mca_modify_comm(previous_current);
goto no_mod;
}
- if (r13 != sos->prev_IA64_KR_CURRENT) {
- msg = "inconsistent previous current and r13";
- goto no_mod;
- }
- if ((r12 - r13) >= KERNEL_STACK_SIZE) {
- msg = "inconsistent r12 and r13";
- goto no_mod;
- }
- if ((ar_bspstore - r13) >= KERNEL_STACK_SIZE) {
- msg = "inconsistent ar.bspstore and r13";
- goto no_mod;
- }
- va.p = old_bspstore;
- if (va.f.reg < 5) {
- msg = "old_bspstore is in the wrong region";
- goto no_mod;
- }
- if ((ar_bsp - r13) >= KERNEL_STACK_SIZE) {
- msg = "inconsistent ar.bsp and r13";
- goto no_mod;
- }
- size += (ia64_rse_skip_regs(old_bspstore, slots) - old_bspstore) * 8;
- if (ar_bspstore + size > r12) {
- msg = "no room for blocked state";
- goto no_mod;
+
+ if (!mca_recover_range(ms->pmsa_iip)) {
+ if (r13 != sos->prev_IA64_KR_CURRENT) {
+ msg = "inconsistent previous current and r13";
+ goto no_mod;
+ }
+ if ((r12 - r13) >= KERNEL_STACK_SIZE) {
+ msg = "inconsistent r12 and r13";
+ goto no_mod;
+ }
+ if ((ar_bspstore - r13) >= KERNEL_STACK_SIZE) {
+ msg = "inconsistent ar.bspstore and r13";
+ goto no_mod;
+ }
+ va.p = old_bspstore;
+ if (va.f.reg < 5) {
+ msg = "old_bspstore is in the wrong region";
+ goto no_mod;
+ }
+ if ((ar_bsp - r13) >= KERNEL_STACK_SIZE) {
+ msg = "inconsistent ar.bsp and r13";
+ goto no_mod;
+ }
+ size += (ia64_rse_skip_regs(old_bspstore, slots) - old_bspstore) * 8;
+ if (ar_bspstore + size > r12) {
+ msg = "no room for blocked state";
+ goto no_mod;
+ }
}
ia64_mca_modify_comm(previous_current);
@@ -1443,7 +1492,7 @@ static struct irqaction mca_cpep_irqaction = {
* format most of the fields.
*/
-static void
+static void __cpuinit
format_mca_init_stack(void *mca_data, unsigned long offset,
const char *type, int cpu)
{
@@ -1457,7 +1506,7 @@ format_mca_init_stack(void *mca_data, unsigned long offset,
ti->cpu = cpu;
p->thread_info = ti;
p->state = TASK_UNINTERRUPTIBLE;
- __set_bit(cpu, &p->cpus_allowed);
+ cpu_set(cpu, p->cpus_allowed);
INIT_LIST_HEAD(&p->tasks);
p->parent = p->real_parent = p->group_leader = p;
INIT_LIST_HEAD(&p->children);
@@ -1467,7 +1516,7 @@ format_mca_init_stack(void *mca_data, unsigned long offset,
/* Do per-CPU MCA-related initialization. */
-void __devinit
+void __cpuinit
ia64_mca_cpu_init(void *cpu_data)
{
void *pal_vaddr;
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index e883d85906d..37c88eb5587 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -6,6 +6,7 @@
* Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
* Copyright (C) 2005 Silicon Graphics, Inc
* Copyright (C) 2005 Keith Owens <kaos@sgi.com>
+ * Copyright (C) 2006 Russ Anderson <rja@sgi.com>
*/
#include <linux/config.h>
#include <linux/types.h>
@@ -121,11 +122,12 @@ mca_page_isolate(unsigned long paddr)
*/
void
-mca_handler_bh(unsigned long paddr)
+mca_handler_bh(unsigned long paddr, void *iip, unsigned long ipsr)
{
- printk(KERN_ERR
- "OS_MCA: process [pid: %d](%s) encounters MCA (paddr=%lx)\n",
- current->pid, current->comm, paddr);
+ printk(KERN_ERR "OS_MCA: process [cpu %d, pid: %d, uid: %d, "
+ "iip: %p, psr: 0x%lx,paddr: 0x%lx](%s) encounters MCA.\n",
+ raw_smp_processor_id(), current->pid, current->uid,
+ iip, ipsr, paddr, current->comm);
spin_lock(&mca_bh_lock);
switch (mca_page_isolate(paddr)) {
@@ -442,21 +444,26 @@ recover_from_read_error(slidx_table_t *slidx,
if (!peidx_bottom(peidx) || !(peidx_bottom(peidx)->valid.minstate))
return 0;
psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr);
+ psr2 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_xpsr);
/*
* Check the privilege level of interrupted context.
* If it is user-mode, then terminate affected process.
*/
- if (psr1->cpl != 0) {
+
+ pmsa = sos->pal_min_state;
+ if (psr1->cpl != 0 ||
+ ((psr2->cpl != 0) && mca_recover_range(pmsa->pmsa_iip))) {
smei = peidx_bus_check(peidx, 0);
if (smei->valid.target_identifier) {
/*
* setup for resume to bottom half of MCA,
* "mca_handler_bhhook"
*/
- pmsa = sos->pal_min_state;
- /* pass to bhhook as 1st argument (gr8) */
+ /* pass to bhhook as argument (gr8, ...) */
pmsa->pmsa_gr[8-1] = smei->target_identifier;
+ pmsa->pmsa_gr[9-1] = pmsa->pmsa_iip;
+ pmsa->pmsa_gr[10-1] = pmsa->pmsa_ipsr;
/* set interrupted return address (but no use) */
pmsa->pmsa_br0 = pmsa->pmsa_iip;
/* change resume address to bottom half */
@@ -466,6 +473,7 @@ recover_from_read_error(slidx_table_t *slidx,
psr2 = (struct ia64_psr *)&pmsa->pmsa_ipsr;
psr2->cpl = 0;
psr2->ri = 0;
+ psr2->bn = 1;
psr2->i = 0;
return 1;
diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h
index e2f6fa1e0ef..31a2e52bb16 100644
--- a/arch/ia64/kernel/mca_drv.h
+++ b/arch/ia64/kernel/mca_drv.h
@@ -111,3 +111,10 @@ typedef struct slidx_table {
slidx_foreach_entry(__pos, &((slidx)->sec)) { __count++; }\
__count; })
+struct mca_table_entry {
+ int start_addr; /* location-relative starting address of MCA recoverable range */
+ int end_addr; /* location-relative ending address of MCA recoverable range */
+};
+
+extern const struct mca_table_entry *search_mca_tables (unsigned long addr);
+extern int mca_recover_range(unsigned long);
diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S
index 3f298ee4d00..e6a580d354b 100644
--- a/arch/ia64/kernel/mca_drv_asm.S
+++ b/arch/ia64/kernel/mca_drv_asm.S
@@ -14,15 +14,12 @@
GLOBAL_ENTRY(mca_handler_bhhook)
invala // clear RSE ?
- ;;
cover
;;
clrrrb
;;
- alloc r16=ar.pfs,0,2,1,0 // make a new frame
- ;;
+ alloc r16=ar.pfs,0,2,3,0 // make a new frame
mov ar.rsc=0
- ;;
mov r13=IA64_KR(CURRENT) // current task pointer
;;
mov r2=r13
@@ -30,7 +27,6 @@ GLOBAL_ENTRY(mca_handler_bhhook)
addl r22=IA64_RBS_OFFSET,r2
;;
mov ar.bspstore=r22
- ;;
addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2
;;
adds r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
@@ -40,12 +36,12 @@ GLOBAL_ENTRY(mca_handler_bhhook)
movl loc1=mca_handler_bh // recovery C function
;;
mov out0=r8 // poisoned address
+ mov out1=r9 // iip
+ mov out2=r10 // psr
mov b6=loc1
;;
mov loc1=rp
- ;;
- ssm psr.i
- ;;
+ ssm psr.i | psr.ic
br.call.sptk.many rp=b6 // does not return ...
;;
mov ar.pfs=loc0
@@ -53,5 +49,4 @@ GLOBAL_ENTRY(mca_handler_bhhook)
;;
mov r8=r0
br.ret.sptk.many rp
- ;;
END(mca_handler_bhhook)
diff --git a/arch/ia64/kernel/numa.c b/arch/ia64/kernel/numa.c
index a68ce667809..0766493d4d0 100644
--- a/arch/ia64/kernel/numa.c
+++ b/arch/ia64/kernel/numa.c
@@ -25,7 +25,7 @@
#include <asm/processor.h>
#include <asm/smp.h>
-u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
+u16 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
EXPORT_SYMBOL(cpu_to_node_map);
cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c
index 6a4ac7d70b3..bc11bb096f5 100644
--- a/arch/ia64/kernel/patch.c
+++ b/arch/ia64/kernel/patch.c
@@ -115,7 +115,7 @@ ia64_patch_vtop (unsigned long start, unsigned long end)
ia64_srlz_i();
}
-void
+void __init
ia64_patch_mckinley_e9 (unsigned long start, unsigned long end)
{
static int first_time = 1;
@@ -149,7 +149,7 @@ ia64_patch_mckinley_e9 (unsigned long start, unsigned long end)
ia64_srlz_i();
}
-static void
+static void __init
patch_fsyscall_table (unsigned long start, unsigned long end)
{
extern unsigned long fsyscall_table[NR_syscalls];
@@ -166,7 +166,7 @@ patch_fsyscall_table (unsigned long start, unsigned long end)
ia64_srlz_i();
}
-static void
+static void __init
patch_brl_fsys_bubble_down (unsigned long start, unsigned long end)
{
extern char fsys_bubble_down[];
@@ -184,7 +184,7 @@ patch_brl_fsys_bubble_down (unsigned long start, unsigned long end)
ia64_srlz_i();
}
-void
+void __init
ia64_patch_gate (void)
{
# define START(name) ((unsigned long) __start_gate_##name##_patchlist)
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 309d59658e5..355d57970ba 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -30,7 +30,6 @@
#include <linux/efi.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
-#include <linux/kprobes.h>
#include <asm/cpu.h>
#include <asm/delay.h>
@@ -738,13 +737,6 @@ void
exit_thread (void)
{
- /*
- * Remove function-return probe instances associated with this task
- * and put them back on the free list. Do not insert an exit probe for
- * this function, it will be disabled by kprobe_flush_task if you do.
- */
- kprobe_flush_task(current);
-
ia64_drop_fpu(current);
#ifdef CONFIG_PERFMON
/* if needed, stop monitoring and flush state to perfmon context */
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index eaed14aac6a..9887c8787e7 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -1656,8 +1656,14 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
long arg4, long arg5, long arg6, long arg7,
struct pt_regs regs)
{
- if (unlikely(current->audit_context))
- audit_syscall_exit(current, AUDITSC_RESULT(regs.r10), regs.r8);
+ if (unlikely(current->audit_context)) {
+ int success = AUDITSC_RESULT(regs.r10);
+ long result = regs.r8;
+
+ if (success != AUDITSC_SUCCESS)
+ result = -result;
+ audit_syscall_exit(current, success, result);
+ }
if (test_thread_flag(TIF_SYSCALL_TRACE)
&& (current->ptrace & PT_PTRACED))
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 958c1508036..e4dfda1eb7d 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -37,6 +37,7 @@
#include <linux/string.h>
#include <linux/threads.h>
#include <linux/tty.h>
+#include <linux/dmi.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/efi.h>
@@ -130,8 +131,8 @@ EXPORT_SYMBOL(ia64_max_iommu_merge_mask);
/*
* We use a special marker for the end of memory and it uses the extra (+1) slot
*/
-struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1];
-int num_rsvd_regions;
+struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1] __initdata;
+int num_rsvd_regions __initdata;
/*
@@ -140,7 +141,7 @@ int num_rsvd_regions;
* caller-specified function is called with the memory ranges that remain after filtering.
* This routine does not assume the incoming segments are sorted.
*/
-int
+int __init
filter_rsvd_memory (unsigned long start, unsigned long end, void *arg)
{
unsigned long range_start, range_end, prev_start;
@@ -176,7 +177,7 @@ filter_rsvd_memory (unsigned long start, unsigned long end, void *arg)
return 0;
}
-static void
+static void __init
sort_regions (struct rsvd_region *rsvd_region, int max)
{
int j;
@@ -217,7 +218,7 @@ __initcall(register_memory);
* initrd, etc. There are currently %IA64_MAX_RSVD_REGIONS defined,
* see include/asm-ia64/meminit.h if you need to define more.
*/
-void
+void __init
reserve_memory (void)
{
int n = 0;
@@ -269,7 +270,7 @@ reserve_memory (void)
* Grab the initrd start and end from the boot parameter struct given us by
* the boot loader.
*/
-void
+void __init
find_initrd (void)
{
#ifdef CONFIG_BLK_DEV_INITRD
@@ -361,7 +362,7 @@ mark_bsp_online (void)
}
#ifdef CONFIG_SMP
-static void
+static void __init
check_for_logical_procs (void)
{
pal_logical_to_physical_t info;
@@ -388,6 +389,14 @@ check_for_logical_procs (void)
}
#endif
+static __initdata int nomca;
+static __init int setup_nomca(char *s)
+{
+ nomca = 1;
+ return 0;
+}
+early_param("nomca", setup_nomca);
+
void __init
setup_arch (char **cmdline_p)
{
@@ -401,35 +410,15 @@ setup_arch (char **cmdline_p)
efi_init();
io_port_init();
+ parse_early_param();
+
#ifdef CONFIG_IA64_GENERIC
- {
- 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);
- }
+ machvec_init(NULL);
#endif
if (early_console_setup(*cmdline_p) == 0)
mark_bsp_online();
- parse_early_param();
#ifdef CONFIG_ACPI
/* Initialize the ACPI boot-time table parser */
acpi_table_init();
@@ -445,7 +434,7 @@ setup_arch (char **cmdline_p)
find_memory();
/* process SAL system table: */
- ia64_sal_init(efi.sal_systab);
+ ia64_sal_init(__va(efi.sal_systab));
ia64_setup_printk_clock();
@@ -492,7 +481,7 @@ setup_arch (char **cmdline_p)
#endif
/* enable IA-64 Machine Check Abort Handling unless disabled */
- if (!strstr(saved_command_line, "nomca"))
+ if (!nomca)
ia64_mca_init();
platform_setup(cmdline_p);
@@ -622,7 +611,7 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo
};
-void
+static void __cpuinit
identify_cpu (struct cpuinfo_ia64 *c)
{
union {
@@ -699,7 +688,7 @@ setup_per_cpu_areas (void)
* In addition, the minimum of the i-cache stride sizes is calculated for
* "flush_icache_range()".
*/
-static void
+static void __cpuinit
get_max_cacheline_size (void)
{
unsigned long line_size, max = 1;
@@ -762,10 +751,10 @@ get_max_cacheline_size (void)
* cpu_init() initializes state that is per-CPU. This function acts
* as a 'CPU state barrier', nothing should get across.
*/
-void
+void __cpuinit
cpu_init (void)
{
- extern void __devinit ia64_mmu_init (void *);
+ extern void __cpuinit ia64_mmu_init (void *);
unsigned long num_phys_stacked;
pal_vm_info_2_u_t vmi;
unsigned int max_ctx;
@@ -893,9 +882,16 @@ void sched_cacheflush(void)
ia64_sal_cache_flush(3);
}
-void
+void __init
check_bugs (void)
{
ia64_patch_mckinley_e9((unsigned long) __start___mckinley_e9_bundles,
(unsigned long) __end___mckinley_e9_bundles);
}
+
+static int __init run_dmi_scan(void)
+{
+ dmi_scan_machine();
+ return 0;
+}
+core_initcall(run_dmi_scan);
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index c4b633b36da..44e9547878a 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -624,32 +624,8 @@ void __devinit smp_prepare_boot_cpu(void)
per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
}
-/*
- * mt_info[] is a temporary store for all info returned by
- * PAL_LOGICAL_TO_PHYSICAL, to be copied into cpuinfo_ia64 when the
- * specific cpu comes.
- */
-static struct {
- __u32 socket_id;
- __u16 core_id;
- __u16 thread_id;
- __u16 proc_fixed_addr;
- __u8 valid;
-} mt_info[NR_CPUS] __devinitdata;
-
#ifdef CONFIG_HOTPLUG_CPU
static inline void
-remove_from_mtinfo(int cpu)
-{
- int i;
-
- for_each_cpu(i)
- if (mt_info[i].valid && mt_info[i].socket_id ==
- cpu_data(cpu)->socket_id)
- mt_info[i].valid = 0;
-}
-
-static inline void
clear_cpu_sibling_map(int cpu)
{
int i;
@@ -678,12 +654,6 @@ remove_siblinginfo(int cpu)
/* remove it from all sibling map's */
clear_cpu_sibling_map(cpu);
-
- /* if this cpu is the last in the core group, remove all its info
- * from mt_info structure
- */
- if (last)
- remove_from_mtinfo(cpu);
}
extern void fixup_irqs(void);
@@ -878,40 +848,6 @@ init_smp_config(void)
ia64_sal_strerror(sal_ret));
}
-static inline int __devinit
-check_for_mtinfo_index(void)
-{
- int i;
-
- for_each_cpu(i)
- if (!mt_info[i].valid)
- return i;
-
- return -1;
-}
-
-/*
- * Search the mt_info to find out if this socket's cid/tid information is
- * cached or not. If the socket exists, fill in the core_id and thread_id
- * in cpuinfo
- */
-static int __devinit
-check_for_new_socket(__u16 logical_address, struct cpuinfo_ia64 *c)
-{
- int i;
- __u32 sid = c->socket_id;
-
- for_each_cpu(i) {
- if (mt_info[i].valid && mt_info[i].proc_fixed_addr == logical_address
- && mt_info[i].socket_id == sid) {
- c->core_id = mt_info[i].core_id;
- c->thread_id = mt_info[i].thread_id;
- return 1; /* not a new socket */
- }
- }
- return 0;
-}
-
/*
* identify_siblings(cpu) gets called from identify_cpu. This populates the
* information related to logical execution units in per_cpu_data structure.
@@ -921,14 +857,12 @@ identify_siblings(struct cpuinfo_ia64 *c)
{
s64 status;
u16 pltid;
- u64 proc_fixed_addr;
- int count, i;
pal_logical_to_physical_t info;
if (smp_num_cpucores == 1 && smp_num_siblings == 1)
return;
- if ((status = ia64_pal_logical_to_phys(0, &info)) != PAL_STATUS_SUCCESS) {
+ if ((status = ia64_pal_logical_to_phys(-1, &info)) != PAL_STATUS_SUCCESS) {
printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
status);
return;
@@ -937,47 +871,12 @@ identify_siblings(struct cpuinfo_ia64 *c)
printk(KERN_ERR "ia64_sal_pltid failed with %ld\n", status);
return;
}
- if ((status = ia64_pal_fixed_addr(&proc_fixed_addr)) != PAL_STATUS_SUCCESS) {
- printk(KERN_ERR "ia64_pal_fixed_addr failed with %ld\n", status);
- return;
- }
c->socket_id = (pltid << 8) | info.overview_ppid;
c->cores_per_socket = info.overview_cpp;
c->threads_per_core = info.overview_tpc;
- count = c->num_log = info.overview_num_log;
+ c->num_log = info.overview_num_log;
- /* If the thread and core id information is already cached, then
- * we will simply update cpu_info and return. Otherwise, we will
- * do the PAL calls and cache core and thread id's of all the siblings.
- */
- if (check_for_new_socket(proc_fixed_addr, c))
- return;
-
- for (i = 0; i < count; i++) {
- int index;
-
- if (i && (status = ia64_pal_logical_to_phys(i, &info))
- != PAL_STATUS_SUCCESS) {
- printk(KERN_ERR "ia64_pal_logical_to_phys failed"
- " with %ld\n", status);
- return;
- }
- if (info.log2_la == proc_fixed_addr) {
- c->core_id = info.log1_cid;
- c->thread_id = info.log1_tid;
- }
-
- index = check_for_mtinfo_index();
- /* We will not do the mt_info caching optimization in this case.
- */
- if (index < 0)
- continue;
-
- mt_info[index].valid = 1;
- mt_info[index].socket_id = c->socket_id;
- mt_info[index].core_id = info.log1_cid;
- mt_info[index].thread_id = info.log1_tid;
- mt_info[index].proc_fixed_addr = info.log2_la;
- }
+ c->core_id = info.log1_cid;
+ c->thread_id = info.log1_tid;
}
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index dabd6c32641..7c1ddc8ac44 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -30,19 +30,19 @@ extern spinlock_t timerlist_lock;
fpswa_interface_t *fpswa_interface;
EXPORT_SYMBOL(fpswa_interface);
-struct notifier_block *ia64die_chain;
+ATOMIC_NOTIFIER_HEAD(ia64die_chain);
int
register_die_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&ia64die_chain, nb);
+ return atomic_notifier_chain_register(&ia64die_chain, nb);
}
EXPORT_SYMBOL_GPL(register_die_notifier);
int
unregister_die_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&ia64die_chain, nb);
+ return atomic_notifier_chain_unregister(&ia64die_chain, nb);
}
EXPORT_SYMBOL_GPL(unregister_die_notifier);
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 73af6267d2e..0b9e56dd7f0 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -70,34 +70,9 @@ SECTIONS
__stop___ex_table = .;
}
- .data.patch.vtop : AT(ADDR(.data.patch.vtop) - LOAD_OFFSET)
- {
- __start___vtop_patchlist = .;
- *(.data.patch.vtop)
- __end___vtop_patchlist = .;
- }
-
- .data.patch.mckinley_e9 : AT(ADDR(.data.patch.mckinley_e9) - LOAD_OFFSET)
- {
- __start___mckinley_e9_bundles = .;
- *(.data.patch.mckinley_e9)
- __end___mckinley_e9_bundles = .;
- }
-
/* Global data */
_data = .;
-#if defined(CONFIG_IA64_GENERIC)
- /* Machine Vector */
- . = ALIGN(16);
- .machvec : AT(ADDR(.machvec) - LOAD_OFFSET)
- {
- machvec_start = .;
- *(.machvec)
- machvec_end = .;
- }
-#endif
-
/* Unwind info & table: */
. = ALIGN(8);
.IA_64.unwind_info : AT(ADDR(.IA_64.unwind_info) - LOAD_OFFSET)
@@ -154,6 +129,41 @@ SECTIONS
*(.initcall7.init)
__initcall_end = .;
}
+
+ /* MCA table */
+ . = ALIGN(16);
+ __mca_table : AT(ADDR(__mca_table) - LOAD_OFFSET)
+ {
+ __start___mca_table = .;
+ *(__mca_table)
+ __stop___mca_table = .;
+ }
+
+ .data.patch.vtop : AT(ADDR(.data.patch.vtop) - LOAD_OFFSET)
+ {
+ __start___vtop_patchlist = .;
+ *(.data.patch.vtop)
+ __end___vtop_patchlist = .;
+ }
+
+ .data.patch.mckinley_e9 : AT(ADDR(.data.patch.mckinley_e9) - LOAD_OFFSET)
+ {
+ __start___mckinley_e9_bundles = .;
+ *(.data.patch.mckinley_e9)
+ __end___mckinley_e9_bundles = .;
+ }
+
+#if defined(CONFIG_IA64_GENERIC)
+ /* Machine Vector */
+ . = ALIGN(16);
+ .machvec : AT(ADDR(.machvec) - LOAD_OFFSET)
+ {
+ machvec_start = .;
+ *(.machvec)
+ machvec_end = .;
+ }
+#endif
+
__con_initcall_start = .;
.con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET)
{ *(.con_initcall.init) }
diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile
index ac64664a180..d8536a2c22a 100644
--- a/arch/ia64/lib/Makefile
+++ b/arch/ia64/lib/Makefile
@@ -6,7 +6,7 @@ obj-y := io.o
lib-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o \
- bitop.o checksum.o clear_page.o csum_partial_copy.o \
+ checksum.o clear_page.o csum_partial_copy.o \
clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o \
flush.o ip_fast_csum.o do_csum.o \
memset.o strlen.o
diff --git a/arch/ia64/lib/bitop.c b/arch/ia64/lib/bitop.c
deleted file mode 100644
index 82e299c8464..00000000000
--- a/arch/ia64/lib/bitop.c
+++ /dev/null
@@ -1,88 +0,0 @@
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <asm/intrinsics.h>
-#include <linux/module.h>
-#include <linux/bitops.h>
-
-/*
- * Find next zero bit in a bitmap reasonably efficiently..
- */
-
-int __find_next_zero_bit (const void *addr, unsigned long size, unsigned long offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
- unsigned long result = offset & ~63UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 63UL;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (64-offset);
- if (size < 64)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 64;
- result += 64;
- }
- while (size & ~63UL) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += 64;
- size -= 64;
- }
- if (!size)
- return result;
- tmp = *p;
-found_first:
- tmp |= ~0UL << size;
- if (tmp == ~0UL) /* any bits zero? */
- return result + size; /* nope */
-found_middle:
- return result + ffz(tmp);
-}
-EXPORT_SYMBOL(__find_next_zero_bit);
-
-/*
- * Find next bit in a bitmap reasonably efficiently..
- */
-int __find_next_bit(const void *addr, unsigned long size, unsigned long offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
- unsigned long result = offset & ~63UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 63UL;
- if (offset) {
- tmp = *(p++);
- tmp &= ~0UL << offset;
- if (size < 64)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= 64;
- result += 64;
- }
- while (size & ~63UL) {
- if ((tmp = *(p++)))
- goto found_middle;
- result += 64;
- size -= 64;
- }
- if (!size)
- return result;
- tmp = *p;
- found_first:
- tmp &= ~0UL >> (64-size);
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
- found_middle:
- return result + __ffs(tmp);
-}
-EXPORT_SYMBOL(__find_next_bit);
diff --git a/arch/ia64/mm/Makefile b/arch/ia64/mm/Makefile
index d78d20f0a0f..bb0a01a8187 100644
--- a/arch/ia64/mm/Makefile
+++ b/arch/ia64/mm/Makefile
@@ -2,7 +2,7 @@
# Makefile for the ia64-specific parts of the memory manager.
#
-obj-y := init.o fault.o tlb.o extable.o
+obj-y := init.o fault.o tlb.o extable.o ioremap.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_NUMA) += numa.o
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index 9855ba31809..84fd1c14c8a 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -97,7 +97,7 @@ find_max_pfn (unsigned long start, unsigned long end, void *arg)
* Find a place to put the bootmap and return its starting address in
* bootmap_start. This address must be page-aligned.
*/
-int
+static int __init
find_bootmap_location (unsigned long start, unsigned long end, void *arg)
{
unsigned long needed = *(unsigned long *)arg;
@@ -141,7 +141,7 @@ find_bootmap_location (unsigned long start, unsigned long end, void *arg)
* Walk the EFI memory map and find usable memory for the system, taking
* into account reserved areas.
*/
-void
+void __init
find_memory (void)
{
unsigned long bootmap_size;
@@ -176,7 +176,7 @@ find_memory (void)
*
* Allocate and setup per-cpu data areas.
*/
-void *
+void * __cpuinit
per_cpu_init (void)
{
void *cpu_data;
@@ -228,7 +228,7 @@ count_dma_pages (u64 start, u64 end, void *arg)
* Set up the page tables.
*/
-void
+void __init
paging_init (void)
{
unsigned long max_dma;
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 573d5cc63e2..ec9eeb89975 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -379,31 +379,6 @@ static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize)
}
/**
- * pgdat_insert - insert the pgdat into global pgdat_list
- * @pgdat: the pgdat for a node.
- */
-static void __init pgdat_insert(pg_data_t *pgdat)
-{
- pg_data_t *prev = NULL, *next;
-
- for_each_pgdat(next)
- if (pgdat->node_id < next->node_id)
- break;
- else
- prev = next;
-
- if (prev) {
- prev->pgdat_next = pgdat;
- pgdat->pgdat_next = next;
- } else {
- pgdat->pgdat_next = pgdat_list;
- pgdat_list = pgdat;
- }
-
- return;
-}
-
-/**
* memory_less_nodes - allocate and initialize CPU only nodes pernode
* information.
*/
@@ -525,7 +500,7 @@ void __init find_memory(void)
* find_pernode_space() does most of this already, we just need to set
* local_per_cpu_offset
*/
-void *per_cpu_init(void)
+void __cpuinit *per_cpu_init(void)
{
int cpu;
static int first_time = 1;
@@ -560,7 +535,7 @@ void show_mem(void)
printk("Mem-info:\n");
show_free_areas();
printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
unsigned long present;
unsigned long flags;
int shared = 0, cached = 0, reserved = 0;
@@ -745,11 +720,5 @@ void __init paging_init(void)
pfn_offset, zholes_size);
}
- /*
- * Make memory less nodes become a member of the known nodes.
- */
- for_each_node_mask(node, memory_less_mask)
- pgdat_insert(mem_data[node].pgdat);
-
zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
}
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
index 9dbc7dadd16..8d506710fdb 100644
--- a/arch/ia64/mm/hugetlbpage.c
+++ b/arch/ia64/mm/hugetlbpage.c
@@ -113,8 +113,7 @@ void hugetlb_free_pgd_range(struct mmu_gather **tlb,
unsigned long floor, unsigned long ceiling)
{
/*
- * This is called only when is_hugepage_only_range(addr,),
- * and it follows that is_hugepage_only_range(end,) also.
+ * This is called to free hugetlb page tables.
*
* The offset of these addresses from the base of the hugetlb
* region must be scaled down by HPAGE_SIZE/PAGE_SIZE so that
@@ -126,9 +125,9 @@ void hugetlb_free_pgd_range(struct mmu_gather **tlb,
addr = htlbpage_to_page(addr);
end = htlbpage_to_page(end);
- if (is_hugepage_only_range(tlb->mm, floor, HPAGE_SIZE))
+ if (REGION_NUMBER(floor) == RGN_HPAGE)
floor = htlbpage_to_page(floor);
- if (is_hugepage_only_range(tlb->mm, ceiling, HPAGE_SIZE))
+ if (REGION_NUMBER(ceiling) == RGN_HPAGE)
ceiling = htlbpage_to_page(ceiling);
free_pgd_range(tlb, addr, end, floor, ceiling);
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 08d94e6bfa1..2ef1151cde9 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -206,7 +206,7 @@ free_initmem (void)
(__init_end - __init_begin) >> 10);
}
-void
+void __init
free_initrd_mem (unsigned long start, unsigned long end)
{
struct page *page;
@@ -261,7 +261,7 @@ free_initrd_mem (unsigned long start, unsigned long end)
/*
* This installs a clean page in the kernel's page table.
*/
-struct page *
+static struct page * __init
put_kernel_page (struct page *page, unsigned long address, pgprot_t pgprot)
{
pgd_t *pgd;
@@ -294,7 +294,7 @@ put_kernel_page (struct page *page, unsigned long address, pgprot_t pgprot)
return page;
}
-static void
+static void __init
setup_gate (void)
{
struct page *page;
@@ -411,7 +411,7 @@ ia64_mmu_init (void *my_cpu_data)
#ifdef CONFIG_VIRTUAL_MEM_MAP
-int
+int __init
create_mem_map_page_table (u64 start, u64 end, void *arg)
{
unsigned long address, start_page, end_page;
@@ -519,7 +519,7 @@ ia64_pfn_valid (unsigned long pfn)
}
EXPORT_SYMBOL(ia64_pfn_valid);
-int
+int __init
find_largest_hole (u64 start, u64 end, void *arg)
{
u64 *max_gap = arg;
@@ -535,7 +535,7 @@ find_largest_hole (u64 start, u64 end, void *arg)
}
#endif /* CONFIG_VIRTUAL_MEM_MAP */
-static int
+static int __init
count_reserved_pages (u64 start, u64 end, void *arg)
{
unsigned long num_reserved = 0;
@@ -556,7 +556,7 @@ count_reserved_pages (u64 start, u64 end, void *arg)
* purposes.
*/
-static int nolwsys;
+static int nolwsys __initdata;
static int __init
nolwsys_setup (char *s)
@@ -567,7 +567,7 @@ nolwsys_setup (char *s)
__setup("nolwsys", nolwsys_setup);
-void
+void __init
mem_init (void)
{
long reserved_pages, codesize, datasize, initsize;
@@ -600,7 +600,7 @@ mem_init (void)
kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START);
kclist_add(&kcore_kernel, _stext, _end - _stext);
- for_each_pgdat(pgdat)
+ for_each_online_pgdat(pgdat)
if (pgdat->bdata->node_bootmem_map)
totalram_pages += free_all_bootmem_node(pgdat);
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
new file mode 100644
index 00000000000..62328621f99
--- /dev/null
+++ b/arch/ia64/mm/ioremap.c
@@ -0,0 +1,43 @@
+/*
+ * (c) Copyright 2006 Hewlett-Packard Development Company, L.P.
+ * Bjorn Helgaas <bjorn.helgaas@hp.com>
+ *
+ * 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/compiler.h>
+#include <linux/module.h>
+#include <linux/efi.h>
+#include <asm/io.h>
+
+static inline void __iomem *
+__ioremap (unsigned long offset, unsigned long size)
+{
+ return (void __iomem *) (__IA64_UNCACHED_OFFSET | offset);
+}
+
+void __iomem *
+ioremap (unsigned long offset, unsigned long size)
+{
+ if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC))
+ return __ioremap(offset, size);
+
+ if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB))
+ return phys_to_virt(offset);
+
+ /*
+ * Someday this should check ACPI resources so we
+ * can do the right thing for hot-plugged regions.
+ */
+ return __ioremap(offset, size);
+}
+EXPORT_SYMBOL(ioremap);
+
+void __iomem *
+ioremap_nocache (unsigned long offset, unsigned long size)
+{
+ return __ioremap(offset, size);
+}
+EXPORT_SYMBOL(ioremap_nocache);
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index dfb3f290237..5101ac46264 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -13,6 +13,8 @@
#include <asm/sn/sn_feature_sets.h>
#include <asm/sn/geo.h>
#include <asm/sn/io.h>
+#include <asm/sn/l1.h>
+#include <asm/sn/module.h>
#include <asm/sn/pcibr_provider.h>
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/pcidev.h>
@@ -710,9 +712,36 @@ cnodeid_get_geoid(cnodeid_t cnode)
return hubdev->hdi_geoid;
}
+void sn_generate_path(struct pci_bus *pci_bus, char *address)
+{
+ nasid_t nasid;
+ cnodeid_t cnode;
+ geoid_t geoid;
+ moduleid_t moduleid;
+ u16 bricktype;
+
+ nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
+ cnode = nasid_to_cnodeid(nasid);
+ geoid = cnodeid_get_geoid(cnode);
+ moduleid = geo_module(geoid);
+
+ sprintf(address, "module_%c%c%c%c%.2d",
+ '0'+RACK_GET_CLASS(MODULE_GET_RACK(moduleid)),
+ '0'+RACK_GET_GROUP(MODULE_GET_RACK(moduleid)),
+ '0'+RACK_GET_NUM(MODULE_GET_RACK(moduleid)),
+ MODULE_GET_BTCHAR(moduleid), MODULE_GET_BPOS(moduleid));
+
+ /* Tollhouse requires slot id to be displayed */
+ bricktype = MODULE_GET_BTYPE(moduleid);
+ if ((bricktype == L1_BRICKTYPE_191010) ||
+ (bricktype == L1_BRICKTYPE_1932))
+ sprintf(address, "%s^%d", address, geo_slot(geoid));
+}
+
subsys_initcall(sn_pci_init);
EXPORT_SYMBOL(sn_pci_fixup_slot);
EXPORT_SYMBOL(sn_pci_unfixup_slot);
EXPORT_SYMBOL(sn_pci_controller_fixup);
EXPORT_SYMBOL(sn_bus_store_sysdata);
EXPORT_SYMBOL(sn_bus_free_sysdata);
+EXPORT_SYMBOL(sn_generate_path);
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index c373113d073..c265e02f503 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -350,9 +350,6 @@ static void force_interrupt(int irq)
static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
{
u64 regval;
- int irr_reg_num;
- int irr_bit;
- u64 irr_reg;
struct pcidev_info *pcidev_info;
struct pcibus_info *pcibus_info;
@@ -373,23 +370,7 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
pdi_pcibus_info;
regval = pcireg_intr_status_get(pcibus_info);
- irr_reg_num = irq_to_vector(irq) / 64;
- irr_bit = irq_to_vector(irq) % 64;
- switch (irr_reg_num) {
- case 0:
- irr_reg = ia64_getreg(_IA64_REG_CR_IRR0);
- break;
- case 1:
- irr_reg = ia64_getreg(_IA64_REG_CR_IRR1);
- break;
- case 2:
- irr_reg = ia64_getreg(_IA64_REG_CR_IRR2);
- break;
- case 3:
- irr_reg = ia64_getreg(_IA64_REG_CR_IRR3);
- break;
- }
- if (!test_bit(irr_bit, &irr_reg)) {
+ if (!ia64_get_irr(irq_to_vector(irq))) {
if (!test_bit(irq, pda->sn_in_service_ivecs)) {
regval &= 0xff;
if (sn_irq_info->irq_int_bit & regval &
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 8b6d5c84470..30988dfbddf 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -327,10 +327,11 @@ sn_scan_pcdp(void)
struct pcdp_interface_pci if_pci;
extern struct efi efi;
- pcdp = efi.hcdp;
- if (! pcdp)
+ if (efi.hcdp == EFI_INVALID_TABLE_ADDR)
return; /* no hcdp/pcdp table */
+ pcdp = __va(efi.hcdp);
+
if (pcdp->rev < 3)
return; /* only support PCDP (rev >= 3) */
diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
index c686d9c12f7..5100261310f 100644
--- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
+++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
@@ -93,19 +93,22 @@ static int coherence_id_open(struct inode *inode, struct file *file)
static struct proc_dir_entry
*sn_procfs_create_entry(const char *name, struct proc_dir_entry *parent,
int (*openfunc)(struct inode *, struct file *),
- int (*releasefunc)(struct inode *, struct file *))
+ int (*releasefunc)(struct inode *, struct file *),
+ ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *))
{
struct proc_dir_entry *e = create_proc_entry(name, 0444, parent);
if (e) {
- e->proc_fops = (struct file_operations *)kmalloc(
- sizeof(struct file_operations), GFP_KERNEL);
- if (e->proc_fops) {
- memset(e->proc_fops, 0, sizeof(struct file_operations));
- e->proc_fops->open = openfunc;
- e->proc_fops->read = seq_read;
- e->proc_fops->llseek = seq_lseek;
- e->proc_fops->release = releasefunc;
+ struct file_operations *f;
+
+ f = kzalloc(sizeof(*f), GFP_KERNEL);
+ if (f) {
+ f->open = openfunc;
+ f->read = seq_read;
+ f->llseek = seq_lseek;
+ f->release = releasefunc;
+ f->write = write;
+ e->proc_fops = f;
}
}
@@ -119,31 +122,29 @@ extern int sn_topology_release(struct inode *, struct file *);
void register_sn_procfs(void)
{
static struct proc_dir_entry *sgi_proc_dir = NULL;
- struct proc_dir_entry *e;
BUG_ON(sgi_proc_dir != NULL);
if (!(sgi_proc_dir = proc_mkdir("sgi_sn", NULL)))
return;
sn_procfs_create_entry("partition_id", sgi_proc_dir,
- partition_id_open, single_release);
+ partition_id_open, single_release, NULL);
sn_procfs_create_entry("system_serial_number", sgi_proc_dir,
- system_serial_number_open, single_release);
+ system_serial_number_open, single_release, NULL);
sn_procfs_create_entry("licenseID", sgi_proc_dir,
- licenseID_open, single_release);
+ licenseID_open, single_release, NULL);
- e = sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir,
- sn_force_interrupt_open, single_release);
- if (e)
- e->proc_fops->write = sn_force_interrupt_write_proc;
+ sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir,
+ sn_force_interrupt_open, single_release,
+ sn_force_interrupt_write_proc);
sn_procfs_create_entry("coherence_id", sgi_proc_dir,
- coherence_id_open, single_release);
+ coherence_id_open, single_release, NULL);
sn_procfs_create_entry("sn_topology", sgi_proc_dir,
- sn_topology_open, sn_topology_release);
+ sn_topology_open, sn_topology_release, NULL);
}
#endif /* CONFIG_PROC_FS */
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index 99cb28e7429..feaf1a6e810 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -369,9 +369,15 @@ static void tio_corelet_reset(nasid_t nasid, int corelet)
static int is_fpga_tio(int nasid, int *bt)
{
- int ioboard_type;
+ u16 ioboard_type;
+ s64 rc;
- ioboard_type = ia64_sn_sysctl_ioboard_get(nasid);
+ rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard_type);
+ if (rc) {
+ printk(KERN_WARNING "ia64_sn_sysctl_ioboard_get failed: %ld\n",
+ rc);
+ return 0;
+ }
switch (ioboard_type) {
case L1_BRICKTYPE_SA:
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index 98f716bd92f..ab1211ef017 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -74,6 +74,22 @@ static int sal_pcibr_error_interrupt(struct pcibus_info *soft)
return (int)ret_stuff.v0;
}
+u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus)
+{
+ s64 rc;
+ u16 ioboard;
+ nasid_t nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
+
+ rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard);
+ if (rc) {
+ printk(KERN_WARNING "ia64_sn_sysctl_ioboard_get failed: %ld\n",
+ rc);
+ return 0;
+ }
+
+ return ioboard;
+}
+
/*
* PCI Bridge Error interrupt handler. Gets invoked whenever a PCI
* bridge sends an error interrupt.
@@ -255,3 +271,4 @@ pcibr_init_provider(void)
EXPORT_SYMBOL_GPL(sal_pcibr_slot_enable);
EXPORT_SYMBOL_GPL(sal_pcibr_slot_disable);
+EXPORT_SYMBOL_GPL(sn_ioboard_to_pci_bus);
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index a3dcc3fab4b..05c864c6c2d 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -214,6 +214,14 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default n
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/m32r/Kconfig.debug b/arch/m32r/Kconfig.debug
index bbf711bab69..2e1019ddbb2 100644
--- a/arch/m32r/Kconfig.debug
+++ b/arch/m32r/Kconfig.debug
@@ -19,7 +19,7 @@ config DEBUG_STACK_USAGE
This option will slow down process creation somewhat.
config DEBUG_PAGEALLOC
- bool "Page alloc debugging"
+ bool "Debug page memory allocations"
depends on DEBUG_KERNEL && BROKEN
help
Unmap pages from the kernel linear mapping after free_pages().
diff --git a/arch/m32r/Makefile b/arch/m32r/Makefile
index 4b3c90ba926..f219c47d334 100644
--- a/arch/m32r/Makefile
+++ b/arch/m32r/Makefile
@@ -1,6 +1,9 @@
#
# m32r/Makefile
#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
LDFLAGS :=
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
@@ -39,7 +42,7 @@ drivers-$(CONFIG_OPROFILE) += arch/m32r/oprofile/
boot := arch/m32r/boot
-.PHONY: zImage
+PHONY += zImage
all: zImage
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index d742037a7cc..0d78942b4c7 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -24,6 +24,7 @@
#include <linux/tty.h>
#include <linux/cpu.h>
#include <linux/nodemask.h>
+#include <linux/pfn.h>
#include <asm/processor.h>
#include <asm/pgtable.h>
diff --git a/arch/m32r/mm/discontig.c b/arch/m32r/mm/discontig.c
index 08e72795555..cf610a7c5ff 100644
--- a/arch/m32r/mm/discontig.c
+++ b/arch/m32r/mm/discontig.c
@@ -13,6 +13,7 @@
#include <linux/initrd.h>
#include <linux/nodemask.h>
#include <linux/module.h>
+#include <linux/pfn.h>
#include <asm/setup.h>
@@ -137,12 +138,6 @@ unsigned long __init zone_sizes_init(void)
int nid, i;
mem_prof_t *mp;
- pgdat_list = NULL;
- for (nid = num_online_nodes() - 1 ; nid >= 0 ; nid--) {
- NODE_DATA(nid)->pgdat_next = pgdat_list;
- pgdat_list = NODE_DATA(nid);
- }
-
for_each_online_node(nid) {
mp = &mem_prof[nid];
for (i = 0 ; i < MAX_NR_ZONES ; i++) {
diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c
index c9e7dad860b..b71348fec1f 100644
--- a/arch/m32r/mm/init.c
+++ b/arch/m32r/mm/init.c
@@ -18,6 +18,7 @@
#include <linux/highmem.h>
#include <linux/bitops.h>
#include <linux/nodemask.h>
+#include <linux/pfn.h>
#include <asm/types.h>
#include <asm/processor.h>
#include <asm/page.h>
@@ -47,7 +48,7 @@ void show_mem(void)
printk("Mem-info:\n");
show_free_areas();
printk("Free swap: %6ldkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
unsigned long flags;
pgdat_resize_lock(pgdat, &flags);
for (i = 0; i < pgdat->node_spanned_pages; ++i) {
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 8849439e88d..805b81fedf8 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -17,6 +17,10 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index 3ffc84f9c29..c90cb5fcc8e 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -142,7 +142,7 @@ void __init config_bvme6000(void)
/* Now do the PIT configuration */
pit->pgcr = 0x00; /* Unidirectional 8 bit, no handshake for now */
- pit->psrr = 0x18; /* PIACK and PIRQ fucntions enabled */
+ pit->psrr = 0x18; /* PIACK and PIRQ functions enabled */
pit->pacr = 0x00; /* Sub Mode 00, H2 i/p, no DMA */
pit->padr = 0x00; /* Just to be tidy! */
pit->paddr = 0x00; /* All inputs for now (safest) */
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
index a69fe3048ed..b0e4c084df8 100644
--- a/arch/m68k/mvme16x/rtc.c
+++ b/arch/m68k/mvme16x/rtc.c
@@ -17,6 +17,7 @@
#include <linux/poll.h>
#include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */
#include <linux/smp_lock.h>
+#include <linux/bcd.h>
#include <asm/mvme16xhw.h>
#include <asm/io.h>
@@ -31,9 +32,6 @@
* ioctls.
*/
-#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10)
-#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10)
-
static const unsigned char days_in_mo[] =
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index e50858dbc23..3cde6822ead 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -25,6 +25,14 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default n
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index ac2012f033d..5080ea1799a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -801,6 +801,14 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
index 1080558c810..307e98c29dd 100644
--- a/arch/mips/au1000/common/setup.c
+++ b/arch/mips/au1000/common/setup.c
@@ -94,7 +94,7 @@ void __init plat_setup(void)
argptr = prom_getcmdline();
-#if defined(CONFIG_SERIAL_AU1X00_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
+#ifdef CONFIG_SERIAL_8250_CONSOLE
if ((argptr = strstr(argptr, "console=")) == NULL) {
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS0,115200");
diff --git a/arch/mips/ddb5xxx/common/rtc_ds1386.c b/arch/mips/ddb5xxx/common/rtc_ds1386.c
index 995896ac0e3..5dc34daa715 100644
--- a/arch/mips/ddb5xxx/common/rtc_ds1386.c
+++ b/arch/mips/ddb5xxx/common/rtc_ds1386.c
@@ -165,6 +165,6 @@ rtc_ds1386_init(unsigned long base)
WRITE_RTC(0xB, byte);
/* set the function pointers */
- rtc_get_time = rtc_ds1386_get_time;
- rtc_set_time = rtc_ds1386_set_time;
+ rtc_mips_get_time = rtc_ds1386_get_time;
+ rtc_mips_set_time = rtc_ds1386_set_time;
}
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
index 17482234413..74cb055d4bf 100644
--- a/arch/mips/dec/time.c
+++ b/arch/mips/dec/time.c
@@ -36,41 +36,13 @@
#include <asm/dec/ioasic_addrs.h>
#include <asm/dec/machtype.h>
-
-/*
- * Returns true if a clock update is in progress
- */
-static inline unsigned char dec_rtc_is_updating(void)
-{
- unsigned char uip;
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
- spin_unlock_irqrestore(&rtc_lock, flags);
- return uip;
-}
-
static unsigned long dec_rtc_get_time(void)
{
unsigned int year, mon, day, hour, min, sec, real_year;
- int i;
unsigned long flags;
- /* The Linux interpretation of the DS1287 clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
- /* read RTC exactly on falling edge of update flag */
- for (i = 0; i < 1000000; i++) /* may take up to 1 second... */
- if (dec_rtc_is_updating())
- break;
- for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */
- if (!dec_rtc_is_updating())
- break;
spin_lock_irqsave(&rtc_lock, flags);
- /* Isn't this overkill? UIP above should guarantee consistency */
+
do {
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
@@ -78,7 +50,16 @@ static unsigned long dec_rtc_get_time(void)
day = CMOS_READ(RTC_DAY_OF_MONTH);
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
+ /*
+ * The PROM will reset the year to either '72 or '73.
+ * Therefore we store the real year separately, in one
+ * of unused BBU RAM locations.
+ */
+ real_year = CMOS_READ(RTC_DEC_YEAR);
} while (sec != CMOS_READ(RTC_SECONDS));
+
+ spin_unlock_irqrestore(&rtc_lock, flags);
+
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
sec = BCD2BIN(sec);
min = BCD2BIN(min);
@@ -87,13 +68,7 @@ static unsigned long dec_rtc_get_time(void)
mon = BCD2BIN(mon);
year = BCD2BIN(year);
}
- /*
- * The PROM will reset the year to either '72 or '73.
- * Therefore we store the real year separately, in one
- * of unused BBU RAM locations.
- */
- real_year = CMOS_READ(RTC_DEC_YEAR);
- spin_unlock_irqrestore(&rtc_lock, flags);
+
year += real_year - 72 + 2000;
return mktime(year, mon, day, hour, min, sec);
@@ -193,8 +168,8 @@ static void dec_ioasic_hpt_init(unsigned int count)
void __init dec_time_init(void)
{
- rtc_get_time = dec_rtc_get_time;
- rtc_set_mmss = dec_rtc_set_mmss;
+ rtc_mips_get_time = dec_rtc_get_time;
+ rtc_mips_set_mmss = dec_rtc_set_mmss;
mips_timer_state = dec_timer_state;
mips_timer_ack = dec_timer_ack;
diff --git a/arch/mips/ite-boards/generic/time.c b/arch/mips/ite-boards/generic/time.c
index f5d67ee21ac..b79817bb6cc 100644
--- a/arch/mips/ite-boards/generic/time.c
+++ b/arch/mips/ite-boards/generic/time.c
@@ -227,8 +227,8 @@ void __init it8172_time_init(void)
local_irq_restore(flags);
- rtc_get_time = it8172_rtc_get_time;
- rtc_set_time = it8172_rtc_set_time;
+ rtc_mips_get_time = it8172_rtc_get_time;
+ rtc_mips_set_time = it8172_rtc_set_time;
}
#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
diff --git a/arch/mips/ite-boards/ivr/init.c b/arch/mips/ite-boards/ivr/init.c
index ea4e1935fec..b774db035b3 100644
--- a/arch/mips/ite-boards/ivr/init.c
+++ b/arch/mips/ite-boards/ivr/init.c
@@ -45,9 +45,6 @@ extern void __init prom_init_cmdline(void);
extern unsigned long __init prom_get_memsize(void);
extern void __init it8172_init_ram_resource(unsigned long memsize);
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
const char *get_system_type(void)
{
return "Globespan IVR";
diff --git a/arch/mips/ite-boards/qed-4n-s01b/init.c b/arch/mips/ite-boards/qed-4n-s01b/init.c
index 56dca7e0c21..e8ec8be66a8 100644
--- a/arch/mips/ite-boards/qed-4n-s01b/init.c
+++ b/arch/mips/ite-boards/qed-4n-s01b/init.c
@@ -45,9 +45,6 @@ extern void __init prom_init_cmdline(void);
extern unsigned long __init prom_get_memsize(void);
extern void __init it8172_init_ram_resource(unsigned long memsize);
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
const char *get_system_type(void)
{
return "ITE QED-4N-S01B";
diff --git a/arch/mips/jmr3927/common/rtc_ds1742.c b/arch/mips/jmr3927/common/rtc_ds1742.c
index 9a8bff153d8..a6bd3f4d304 100644
--- a/arch/mips/jmr3927/common/rtc_ds1742.c
+++ b/arch/mips/jmr3927/common/rtc_ds1742.c
@@ -159,8 +159,8 @@ rtc_ds1742_init(unsigned long base)
db_assert((rtc_base & 0xe0000000) == KSEG1);
/* set the function pointers */
- rtc_get_time = rtc_ds1742_get_time;
- rtc_set_time = rtc_ds1742_set_time;
+ rtc_mips_get_time = rtc_ds1742_get_time;
+ rtc_mips_set_time = rtc_ds1742_set_time;
/* clear oscillator stop bit */
CMOS_WRITE(RTC_READ, RTC_CONTROL);
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 08273a2a501..8150f071f80 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -603,7 +603,7 @@ repeat:
/* move to end of parent's list to avoid starvation */
write_lock_irq(&tasklist_lock);
remove_parent(p);
- add_parent(p, p->parent);
+ add_parent(p);
write_unlock_irq(&tasklist_lock);
retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
if (retval)
@@ -643,7 +643,7 @@ repeat:
write_lock_irq(&tasklist_lock);
remove_parent(p);
p->parent = p->real_parent;
- add_parent(p, p->parent);
+ add_parent(p);
do_notify_parent(p, SIGCHLD);
write_unlock_irq(&tasklist_lock);
} else
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 013bc93688e..3f40c37a9ee 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -30,7 +30,6 @@
#include <linux/utime.h>
#include <linux/utsname.h>
#include <linux/personality.h>
-#include <linux/timex.h>
#include <linux/dnotify.h>
#include <linux/module.h>
#include <linux/binfmts.h>
@@ -1157,79 +1156,6 @@ out:
return err;
}
-/* Handle adjtimex compatibility. */
-
-struct timex32 {
- u32 modes;
- s32 offset, freq, maxerror, esterror;
- s32 status, constant, precision, tolerance;
- struct compat_timeval time;
- s32 tick;
- s32 ppsfreq, jitter, shift, stabil;
- s32 jitcnt, calcnt, errcnt, stbcnt;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
-};
-
-extern int do_adjtimex(struct timex *);
-
-asmlinkage int sys32_adjtimex(struct timex32 __user *utp)
-{
- struct timex txc;
- int ret;
-
- memset(&txc, 0, sizeof(struct timex));
-
- if (get_user(txc.modes, &utp->modes) ||
- __get_user(txc.offset, &utp->offset) ||
- __get_user(txc.freq, &utp->freq) ||
- __get_user(txc.maxerror, &utp->maxerror) ||
- __get_user(txc.esterror, &utp->esterror) ||
- __get_user(txc.status, &utp->status) ||
- __get_user(txc.constant, &utp->constant) ||
- __get_user(txc.precision, &utp->precision) ||
- __get_user(txc.tolerance, &utp->tolerance) ||
- __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __get_user(txc.tick, &utp->tick) ||
- __get_user(txc.ppsfreq, &utp->ppsfreq) ||
- __get_user(txc.jitter, &utp->jitter) ||
- __get_user(txc.shift, &utp->shift) ||
- __get_user(txc.stabil, &utp->stabil) ||
- __get_user(txc.jitcnt, &utp->jitcnt) ||
- __get_user(txc.calcnt, &utp->calcnt) ||
- __get_user(txc.errcnt, &utp->errcnt) ||
- __get_user(txc.stbcnt, &utp->stbcnt))
- return -EFAULT;
-
- ret = do_adjtimex(&txc);
-
- if (put_user(txc.modes, &utp->modes) ||
- __put_user(txc.offset, &utp->offset) ||
- __put_user(txc.freq, &utp->freq) ||
- __put_user(txc.maxerror, &utp->maxerror) ||
- __put_user(txc.esterror, &utp->esterror) ||
- __put_user(txc.status, &utp->status) ||
- __put_user(txc.constant, &utp->constant) ||
- __put_user(txc.precision, &utp->precision) ||
- __put_user(txc.tolerance, &utp->tolerance) ||
- __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __put_user(txc.tick, &utp->tick) ||
- __put_user(txc.ppsfreq, &utp->ppsfreq) ||
- __put_user(txc.jitter, &utp->jitter) ||
- __put_user(txc.shift, &utp->shift) ||
- __put_user(txc.stabil, &utp->stabil) ||
- __put_user(txc.jitcnt, &utp->jitcnt) ||
- __put_user(txc.calcnt, &utp->calcnt) ||
- __put_user(txc.errcnt, &utp->errcnt) ||
- __put_user(txc.stbcnt, &utp->stbcnt))
- ret = -EFAULT;
-
- return ret;
-}
-
asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
s32 count)
{
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 02c8267e45e..05a2c0567da 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -273,7 +273,7 @@ EXPORT(sysn32_call_table)
PTR sys_pivot_root
PTR sys32_sysctl
PTR sys_prctl
- PTR sys32_adjtimex
+ PTR compat_sys_adjtimex
PTR compat_sys_setrlimit /* 6155 */
PTR sys_chroot
PTR sys_sync
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 797e0d87488..19c4ca481b0 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -328,7 +328,7 @@ sys_call_table:
PTR sys_setdomainname
PTR sys32_newuname
PTR sys_ni_syscall /* sys_modify_ldt */
- PTR sys32_adjtimex
+ PTR compat_sys_adjtimex
PTR sys_mprotect /* 4125 */
PTR compat_sys_sigprocmask
PTR sys_ni_syscall /* was creat_module */
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 0cb3b6097e0..dcbfd27071f 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -34,6 +34,7 @@
#include <linux/highmem.h>
#include <linux/console.h>
#include <linux/mmzone.h>
+#include <linux/pfn.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
@@ -257,10 +258,6 @@ static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_en
return 0;
}
-#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
-
#define MAXMEM HIGHMEM_START
#define MAXMEM_PFN PFN_DOWN(MAXMEM)
@@ -493,10 +490,6 @@ static inline void resource_init(void)
}
}
-#undef PFN_UP
-#undef PFN_DOWN
-#undef PFN_PHYS
-
#undef MAXMEM
#undef MAXMEM_PFN
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 0fc3730a294..5407b784cd0 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -645,27 +645,7 @@ static inline void getitimer_real(struct itimerval *value)
asmlinkage unsigned int irix_alarm(unsigned int seconds)
{
- struct itimerval it_new, it_old;
- unsigned int oldalarm;
-
- if (!seconds) {
- getitimer_real(&it_old);
- del_timer(&current->real_timer);
- } else {
- it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
- it_new.it_value.tv_sec = seconds;
- it_new.it_value.tv_usec = 0;
- do_setitimer(ITIMER_REAL, &it_new, &it_old);
- }
- oldalarm = it_old.it_value.tv_sec;
- /*
- * ehhh.. We can't return 0 if we have an alarm pending ...
- * And we'd better return too much than too little anyway
- */
- if (it_old.it_value.tv_usec)
- oldalarm++;
-
- return oldalarm;
+ return alarm_setitimer(seconds);
}
asmlinkage int irix_pause(void)
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 51273b7297a..5e51a2d8f3f 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -65,9 +65,9 @@ static int null_rtc_set_time(unsigned long sec)
return 0;
}
-unsigned long (*rtc_get_time)(void) = null_rtc_get_time;
-int (*rtc_set_time)(unsigned long) = null_rtc_set_time;
-int (*rtc_set_mmss)(unsigned long);
+unsigned long (*rtc_mips_get_time)(void) = null_rtc_get_time;
+int (*rtc_mips_set_time)(unsigned long) = null_rtc_set_time;
+int (*rtc_mips_set_mmss)(unsigned long);
/* usecs per counter cycle, shifted to left by 32 bits */
@@ -440,14 +440,14 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
* If we have an externally synchronized Linux clock, then update
- * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be
+ * CMOS clock accordingly every ~11 minutes. rtc_mips_set_time() has to be
* called as close as possible to 500 ms before the new second starts.
*/
if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
- if (rtc_set_mmss(xtime.tv_sec) == 0) {
+ if (rtc_mips_set_mmss(xtime.tv_sec) == 0) {
last_rtc_update = xtime.tv_sec;
} else {
/* do it again in 60 s */
@@ -565,7 +565,7 @@ asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs)
* b) (optional) calibrate and set the mips_hpt_frequency
* (only needed if you intended to use fixed_rate_gettimeoffset
* or use cpu counter as timer interrupt source)
- * 2) setup xtime based on rtc_get_time().
+ * 2) setup xtime based on rtc_mips_get_time().
* 3) choose a appropriate gettimeoffset routine.
* 4) calculate a couple of cached variables for later usage
* 5) board_timer_setup() -
@@ -633,10 +633,10 @@ void __init time_init(void)
if (board_time_init)
board_time_init();
- if (!rtc_set_mmss)
- rtc_set_mmss = rtc_set_time;
+ if (!rtc_mips_set_mmss)
+ rtc_mips_set_mmss = rtc_mips_set_time;
- xtime.tv_sec = rtc_get_time();
+ xtime.tv_sec = rtc_mips_get_time();
xtime.tv_nsec = 0;
set_normalized_timespec(&wall_to_monotonic,
@@ -772,8 +772,8 @@ void to_tm(unsigned long tim, struct rtc_time *tm)
EXPORT_SYMBOL(rtc_lock);
EXPORT_SYMBOL(to_tm);
-EXPORT_SYMBOL(rtc_set_time);
-EXPORT_SYMBOL(rtc_get_time);
+EXPORT_SYMBOL(rtc_mips_set_time);
+EXPORT_SYMBOL(rtc_mips_get_time);
unsigned long long sched_clock(void)
{
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
index 83eb08b7a07..bb70a8240e6 100644
--- a/arch/mips/lasat/setup.c
+++ b/arch/mips/lasat/setup.c
@@ -165,7 +165,8 @@ void __init plat_setup(void)
/* Set up panic notifier */
for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++)
- notifier_chain_register(&panic_notifier_list, &lasat_panic_block[i]);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &lasat_panic_block[i]);
lasat_reboot_setup();
@@ -174,8 +175,8 @@ void __init plat_setup(void)
#ifdef CONFIG_DS1603
ds1603 = &ds_defs[mips_machtype];
- rtc_get_time = ds1603_read;
- rtc_set_time = ds1603_set;
+ rtc_mips_get_time = ds1603_read;
+ rtc_mips_set_time = ds1603_set;
#endif
#ifdef DYNAMIC_SERIAL_INIT
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
index 8ff43a1c1e9..e3d5aaa90f0 100644
--- a/arch/mips/lasat/sysctl.c
+++ b/arch/mips/lasat/sysctl.c
@@ -30,12 +30,13 @@
#include <linux/string.h>
#include <linux/net.h>
#include <linux/inet.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include "sysctl.h"
#include "ds1603.h"
-static DECLARE_MUTEX(lasat_info_sem);
+static DEFINE_MUTEX(lasat_info_mutex);
/* Strategy function to write EEPROM after changing string entry */
int sysctl_lasatstring(ctl_table *table, int *name, int nlen,
@@ -43,17 +44,17 @@ int sysctl_lasatstring(ctl_table *table, int *name, int nlen,
void *newval, size_t newlen, void **context)
{
int r;
- down(&lasat_info_sem);
+ mutex_lock(&lasat_info_mutex);
r = sysctl_string(table, name,
nlen, oldval, oldlenp, newval, newlen, context);
if (r < 0) {
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return r;
}
if (newval && newlen) {
lasat_write_eeprom_info();
}
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return 1;
}
@@ -63,14 +64,14 @@ int proc_dolasatstring(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp, loff_t *ppos)
{
int r;
- down(&lasat_info_sem);
+ mutex_lock(&lasat_info_mutex);
r = proc_dostring(table, write, filp, buffer, lenp, ppos);
if ( (!write) || r) {
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return r;
}
lasat_write_eeprom_info();
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return 0;
}
@@ -79,14 +80,14 @@ int proc_dolasatint(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp, loff_t *ppos)
{
int r;
- down(&lasat_info_sem);
+ mutex_lock(&lasat_info_mutex);
r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
if ( (!write) || r) {
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return r;
}
lasat_write_eeprom_info();
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return 0;
}
@@ -98,7 +99,7 @@ int proc_dolasatrtc(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp, loff_t *ppos)
{
int r;
- down(&lasat_info_sem);
+ mutex_lock(&lasat_info_mutex);
if (!write) {
rtctmp = ds1603_read();
/* check for time < 0 and set to 0 */
@@ -107,11 +108,11 @@ int proc_dolasatrtc(ctl_table *table, int write, struct file *filp,
}
r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
if ( (!write) || r) {
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return r;
}
ds1603_set(rtctmp);
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return 0;
}
#endif
@@ -122,16 +123,16 @@ int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
void *newval, size_t newlen, void **context)
{
int r;
- down(&lasat_info_sem);
+ mutex_lock(&lasat_info_mutex);
r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context);
if (r < 0) {
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return r;
}
if (newval && newlen) {
lasat_write_eeprom_info();
}
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return 1;
}
@@ -142,19 +143,19 @@ int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen,
void *newval, size_t newlen, void **context)
{
int r;
- down(&lasat_info_sem);
+ mutex_lock(&lasat_info_mutex);
rtctmp = ds1603_read();
if (rtctmp < 0)
rtctmp = 0;
r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context);
if (r < 0) {
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return r;
}
if (newval && newlen) {
ds1603_set(rtctmp);
}
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return 1;
}
#endif
@@ -192,13 +193,13 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
return 0;
}
- down(&lasat_info_sem);
+ mutex_lock(&lasat_info_mutex);
if (write) {
len = 0;
p = buffer;
while (len < *lenp) {
if(get_user(c, p++)) {
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return -EFAULT;
}
if (c == 0 || c == '\n')
@@ -209,7 +210,7 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
len = sizeof(proc_lasat_ipbuf) - 1;
if (copy_from_user(proc_lasat_ipbuf, buffer, len))
{
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return -EFAULT;
}
proc_lasat_ipbuf[len] = 0;
@@ -230,12 +231,12 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
len = *lenp;
if (len)
if(copy_to_user(buffer, proc_lasat_ipbuf, len)) {
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return -EFAULT;
}
if (len < *lenp) {
if(put_user('\n', ((char *) buffer) + len)) {
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return -EFAULT;
}
len++;
@@ -244,7 +245,7 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
*ppos += len;
}
update_bcastaddr();
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return 0;
}
#endif /* defined(CONFIG_INET) */
@@ -256,10 +257,10 @@ static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen,
{
int r;
- down(&lasat_info_sem);
+ mutex_lock(&lasat_info_mutex);
r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context);
if (r < 0) {
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return r;
}
@@ -271,7 +272,7 @@ static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen,
lasat_write_eeprom_info();
lasat_init_board_info();
}
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return 0;
}
@@ -280,10 +281,10 @@ int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp, loff_t *ppos)
{
int r;
- down(&lasat_info_sem);
+ mutex_lock(&lasat_info_mutex);
r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
if ( (!write) || r) {
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return r;
}
if (filp && filp->f_dentry)
@@ -294,7 +295,7 @@ int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp,
lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess;
}
lasat_write_eeprom_info();
- up(&lasat_info_sem);
+ mutex_unlock(&lasat_info_mutex);
return 0;
}
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c
index 873cf3141a3..c20d401ecf8 100644
--- a/arch/mips/mips-boards/atlas/atlas_setup.c
+++ b/arch/mips/mips-boards/atlas/atlas_setup.c
@@ -65,7 +65,7 @@ void __init plat_setup(void)
board_time_init = mips_time_init;
board_timer_setup = mips_timer_setup;
- rtc_get_time = mips_rtc_get_time;
+ rtc_mips_get_time = mips_rtc_get_time;
}
static void __init serial_init(void)
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
index ee5e70c95cf..32c9210373a 100644
--- a/arch/mips/mips-boards/generic/memory.c
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -49,9 +49,6 @@ static char *mtypes[3] = {
/* References to section boundaries */
extern char _end;
-#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
-
struct prom_pmemblock * __init prom_getmdesc(void)
{
char *memsize_str;
@@ -109,10 +106,10 @@ struct prom_pmemblock * __init prom_getmdesc(void)
mdesc[3].type = yamon_dontuse;
mdesc[3].base = 0x00100000;
- mdesc[3].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base;
+ mdesc[3].size = CPHYSADDR(PAGE_ALIGN(&_end)) - mdesc[3].base;
mdesc[4].type = yamon_free;
- mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
+ mdesc[4].base = CPHYSADDR(PAGE_ALIGN(&_end));
mdesc[4].size = memsize - mdesc[4].base;
return &mdesc[0];
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
index 2209e8a9de3..b8488aab6df 100644
--- a/arch/mips/mips-boards/malta/malta_setup.c
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -225,5 +225,5 @@ void __init plat_setup(void)
board_time_init = mips_time_init;
board_timer_setup = mips_timer_setup;
- rtc_get_time = mips_rtc_get_time;
+ rtc_mips_get_time = mips_rtc_get_time;
}
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mips-boards/sim/sim_mem.c
index 1ec4e75656b..e57f737bab1 100644
--- a/arch/mips/mips-boards/sim/sim_mem.c
+++ b/arch/mips/mips-boards/sim/sim_mem.c
@@ -42,9 +42,6 @@ static char *mtypes[3] = {
/* References to section boundaries */
extern char _end;
-#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
-
struct prom_pmemblock * __init prom_getmdesc(void)
{
unsigned int memsize;
@@ -64,10 +61,10 @@ struct prom_pmemblock * __init prom_getmdesc(void)
mdesc[2].type = simmem_reserved;
mdesc[2].base = 0x00100000;
- mdesc[2].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[2].base;
+ mdesc[2].size = CPHYSADDR(PAGE_ALIGN(&_end)) - mdesc[2].base;
mdesc[3].type = simmem_free;
- mdesc[3].base = CPHYSADDR(PFN_ALIGN(&_end));
+ mdesc[3].base = CPHYSADDR(PAGE_ALIGN(&_end));
mdesc[3].size = memsize - mdesc[3].base;
return &mdesc[0];
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 52f7d59fe61..ad89c442f29 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -25,6 +25,7 @@
#include <linux/highmem.h>
#include <linux/swap.h>
#include <linux/proc_fs.h>
+#include <linux/pfn.h>
#include <asm/bootinfo.h>
#include <asm/cachectl.h>
@@ -177,9 +178,6 @@ void __init paging_init(void)
free_area_init(zones_size);
}
-#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-
static inline int page_is_ram(unsigned long pagenr)
{
int i;
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
index 3784c898db1..91d9637143d 100644
--- a/arch/mips/momentum/jaguar_atx/setup.c
+++ b/arch/mips/momentum/jaguar_atx/setup.c
@@ -229,8 +229,8 @@ void momenco_time_init(void)
mips_hpt_frequency = cpu_clock / 2;
board_timer_setup = momenco_timer_setup;
- rtc_get_time = m48t37y_get_time;
- rtc_set_time = m48t37y_set_time;
+ rtc_mips_get_time = m48t37y_get_time;
+ rtc_mips_set_time = m48t37y_set_time;
}
static struct resource mv_pci_io_mem0_resource = {
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
index f95677f4f06..370e75d0e75 100644
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ b/arch/mips/momentum/ocelot_3/setup.c
@@ -58,6 +58,7 @@
#include <linux/bootmem.h>
#include <linux/mv643xx.h>
#include <linux/pm.h>
+#include <linux/bcd.h>
#include <asm/time.h>
#include <asm/page.h>
@@ -131,9 +132,6 @@ void setup_wired_tlb_entries(void)
add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), (signed)0xfc000000, PM_16M);
}
-#define CONV_BCD_TO_BIN(val) (((val) & 0xf) + (((val) >> 4) * 10))
-#define CONV_BIN_TO_BCD(val) (((val) % 10) + (((val) / 10) << 4))
-
unsigned long m48t37y_get_time(void)
{
unsigned int year, month, day, hour, min, sec;
@@ -143,16 +141,16 @@ unsigned long m48t37y_get_time(void)
/* stop the update */
rtc_base[0x7ff8] = 0x40;
- year = CONV_BCD_TO_BIN(rtc_base[0x7fff]);
- year += CONV_BCD_TO_BIN(rtc_base[0x7ff1]) * 100;
+ year = BCD2BIN(rtc_base[0x7fff]);
+ year += BCD2BIN(rtc_base[0x7ff1]) * 100;
- month = CONV_BCD_TO_BIN(rtc_base[0x7ffe]);
+ month = BCD2BIN(rtc_base[0x7ffe]);
- day = CONV_BCD_TO_BIN(rtc_base[0x7ffd]);
+ day = BCD2BIN(rtc_base[0x7ffd]);
- hour = CONV_BCD_TO_BIN(rtc_base[0x7ffb]);
- min = CONV_BCD_TO_BIN(rtc_base[0x7ffa]);
- sec = CONV_BCD_TO_BIN(rtc_base[0x7ff9]);
+ hour = BCD2BIN(rtc_base[0x7ffb]);
+ min = BCD2BIN(rtc_base[0x7ffa]);
+ sec = BCD2BIN(rtc_base[0x7ff9]);
/* start the update */
rtc_base[0x7ff8] = 0x00;
@@ -175,22 +173,22 @@ int m48t37y_set_time(unsigned long sec)
rtc_base[0x7ff8] = 0x80;
/* year */
- rtc_base[0x7fff] = CONV_BIN_TO_BCD(tm.tm_year % 100);
- rtc_base[0x7ff1] = CONV_BIN_TO_BCD(tm.tm_year / 100);
+ rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
+ rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
/* month */
- rtc_base[0x7ffe] = CONV_BIN_TO_BCD(tm.tm_mon);
+ rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
/* day */
- rtc_base[0x7ffd] = CONV_BIN_TO_BCD(tm.tm_mday);
+ rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
/* hour/min/sec */
- rtc_base[0x7ffb] = CONV_BIN_TO_BCD(tm.tm_hour);
- rtc_base[0x7ffa] = CONV_BIN_TO_BCD(tm.tm_min);
- rtc_base[0x7ff9] = CONV_BIN_TO_BCD(tm.tm_sec);
+ rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
+ rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
+ rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
/* day of week -- not really used, but let's keep it up-to-date */
- rtc_base[0x7ffc] = CONV_BIN_TO_BCD(tm.tm_wday + 1);
+ rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
/* disable writing */
rtc_base[0x7ff8] = 0x00;
@@ -215,8 +213,8 @@ void momenco_time_init(void)
mips_hpt_frequency = cpu_clock / 2;
board_timer_setup = momenco_timer_setup;
- rtc_get_time = m48t37y_get_time;
- rtc_set_time = m48t37y_set_time;
+ rtc_mips_get_time = m48t37y_get_time;
+ rtc_mips_set_time = m48t37y_set_time;
}
/*
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
index bd02e60d037..a3e6f557559 100644
--- a/arch/mips/momentum/ocelot_c/setup.c
+++ b/arch/mips/momentum/ocelot_c/setup.c
@@ -227,8 +227,8 @@ void momenco_time_init(void)
printk("momenco_time_init cpu_clock=%d\n", cpu_clock);
board_timer_setup = momenco_timer_setup;
- rtc_get_time = m48t37y_get_time;
- rtc_set_time = m48t37y_set_time;
+ rtc_mips_get_time = m48t37y_get_time;
+ rtc_mips_set_time = m48t37y_set_time;
}
void __init plat_setup(void)
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
index 8bce711575d..3f724d661bd 100644
--- a/arch/mips/pmc-sierra/yosemite/setup.c
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -198,8 +198,8 @@ static void __init py_rtc_setup(void)
if (!m48t37_base)
printk(KERN_ERR "Mapping the RTC failed\n");
- rtc_get_time = m48t37y_get_time;
- rtc_set_time = m48t37y_set_time;
+ rtc_mips_get_time = m48t37y_get_time;
+ rtc_mips_set_time = m48t37y_set_time;
write_seqlock(&xtime_lock);
xtime.tv_sec = m48t37y_get_time();
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
index 92a3b3c15ed..a9c58e067b5 100644
--- a/arch/mips/sgi-ip22/ip22-reset.c
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -238,7 +238,7 @@ static int __init reboot_setup(void)
request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL);
init_timer(&blink_timer);
blink_timer.function = blink_timeout;
- notifier_chain_register(&panic_notifier_list, &panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
return 0;
}
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index b7300cc5c5a..cca688ad64a 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -212,8 +212,8 @@ static void indy_timer_setup(struct irqaction *irq)
void __init ip22_time_init(void)
{
/* setup hookup functions */
- rtc_get_time = indy_rtc_get_time;
- rtc_set_time = indy_rtc_set_time;
+ rtc_mips_get_time = indy_rtc_get_time;
+ rtc_mips_set_time = indy_rtc_set_time;
board_time_init = indy_time_init;
board_timer_setup = indy_timer_setup;
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index e0d095daa5e..6c00dce9f73 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -19,6 +19,7 @@
#include <linux/nodemask.h>
#include <linux/swap.h>
#include <linux/bootmem.h>
+#include <linux/pfn.h>
#include <asm/page.h>
#include <asm/sections.h>
@@ -28,8 +29,6 @@
#include <asm/sn/sn_private.h>
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-
#define SLOT_PFNSHIFT (SLOT_SHIFT - PAGE_SHIFT)
#define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT)
diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c
index 0c948008b02..ab9d9cef089 100644
--- a/arch/mips/sgi-ip32/ip32-reset.c
+++ b/arch/mips/sgi-ip32/ip32-reset.c
@@ -193,7 +193,7 @@ static __init int ip32_reboot_setup(void)
init_timer(&blink_timer);
blink_timer.function = blink_timeout;
- notifier_chain_register(&panic_notifier_list, &panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL);
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index 2f50c79b788..a2dd8ae1ea8 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -91,8 +91,8 @@ void __init plat_setup(void)
{
board_be_init = ip32_be_init;
- rtc_get_time = mc146818_get_cmos_time;
- rtc_set_mmss = mc146818_set_rtc_mmss;
+ rtc_mips_get_time = mc146818_get_cmos_time;
+ rtc_mips_set_mmss = mc146818_set_rtc_mmss;
board_time_init = ip32_time_init;
board_timer_setup = ip32_timer_setup;
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index b661d2425a3..4b5f74ff3ed 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -121,14 +121,14 @@ void __init plat_setup(void)
if (xicor_probe()) {
printk("swarm setup: Xicor 1241 RTC detected.\n");
- rtc_get_time = xicor_get_time;
- rtc_set_time = xicor_set_time;
+ rtc_mips_get_time = xicor_get_time;
+ rtc_mips_set_time = xicor_set_time;
}
if (m41t81_probe()) {
printk("swarm setup: M41T81 RTC detected.\n");
- rtc_get_time = m41t81_get_time;
- rtc_set_time = m41t81_set_time;
+ rtc_mips_get_time = m41t81_get_time;
+ rtc_mips_set_time = m41t81_set_time;
}
printk("This kernel optimized for "
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index 1141fcd13a5..01ba6c581e3 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -164,8 +164,8 @@ static struct pci_controller sni_controller = {
static inline void sni_pcimt_time_init(void)
{
- rtc_get_time = mc146818_get_cmos_time;
- rtc_set_time = mc146818_set_rtc_mmss;
+ rtc_mips_get_time = mc146818_get_cmos_time;
+ rtc_mips_set_time = mc146818_set_rtc_mmss;
}
void __init plat_setup(void)
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
index 2ad6401d2af..6dcf077f61a 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
@@ -1036,8 +1036,8 @@ toshiba_rbtx4927_time_init(void)
#ifdef CONFIG_RTC_DS1742
- rtc_get_time = rtc_ds1742_get_time;
- rtc_set_time = rtc_ds1742_set_time;
+ rtc_mips_get_time = rtc_ds1742_get_time;
+ rtc_mips_set_time = rtc_ds1742_set_time;
TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
":rtc_ds1742_init()-\n");
diff --git a/arch/mips/tx4938/common/rtc_rx5c348.c b/arch/mips/tx4938/common/rtc_rx5c348.c
index d249edbb6af..07f782fc072 100644
--- a/arch/mips/tx4938/common/rtc_rx5c348.c
+++ b/arch/mips/tx4938/common/rtc_rx5c348.c
@@ -14,6 +14,7 @@
#include <linux/string.h>
#include <linux/rtc.h>
#include <linux/time.h>
+#include <linux/bcd.h>
#include <asm/time.h>
#include <asm/tx4938/spi.h>
@@ -77,17 +78,6 @@ spi_rtc_io(unsigned char *inbuf, unsigned char *outbuf, unsigned int count)
inbufs, incounts, outbufs, outcounts, 0);
}
-/*
- * Conversion between binary and BCD.
- */
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
/* RTC-dependent code for time.c */
static int
@@ -197,6 +187,6 @@ rtc_rx5c348_init(int chipid)
srtc_24h = 1;
/* set the function pointers */
- rtc_get_time = rtc_rx5c348_get_time;
- rtc_set_time = rtc_rx5c348_set_time;
+ rtc_mips_get_time = rtc_rx5c348_get_time;
+ rtc_mips_set_time = rtc_rx5c348_set_time;
}
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index eca33cfa8a4..6b3c50964ca 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -25,6 +25,14 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c
index 2a01fe1bdc9..0cea6958f42 100644
--- a/arch/parisc/kernel/pdc_chassis.c
+++ b/arch/parisc/kernel/pdc_chassis.c
@@ -150,7 +150,8 @@ void __init parisc_pdc_chassis_init(void)
if (handle) {
/* initialize panic notifier chain */
- notifier_chain_register(&panic_notifier_list, &pdc_chassis_panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &pdc_chassis_panic_block);
/* initialize reboot notifier chain */
register_reboot_notifier(&pdc_chassis_reboot_block);
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index 61356901841..d286f68a3d3 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -21,7 +21,6 @@
#include <linux/times.h>
#include <linux/utsname.h>
#include <linux/time.h>
-#include <linux/timex.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
@@ -567,63 +566,6 @@ asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *off
}
-struct timex32 {
- unsigned int modes; /* mode selector */
- int offset; /* time offset (usec) */
- int freq; /* frequency offset (scaled ppm) */
- int maxerror; /* maximum error (usec) */
- int esterror; /* estimated error (usec) */
- int status; /* clock command/status */
- int constant; /* pll time constant */
- int precision; /* clock precision (usec) (read only) */
- int tolerance; /* clock frequency tolerance (ppm)
- * (read only)
- */
- struct compat_timeval time; /* (read only) */
- int tick; /* (modified) usecs between clock ticks */
-
- int ppsfreq; /* pps frequency (scaled ppm) (ro) */
- int jitter; /* pps jitter (us) (ro) */
- int shift; /* interval duration (s) (shift) (ro) */
- int stabil; /* pps stability (scaled ppm) (ro) */
- int jitcnt; /* jitter limit exceeded (ro) */
- int calcnt; /* calibration intervals (ro) */
- int errcnt; /* calibration errors (ro) */
- int stbcnt; /* stability limit exceeded (ro) */
-
- int :32; int :32; int :32; int :32;
- int :32; int :32; int :32; int :32;
- int :32; int :32; int :32; int :32;
-};
-
-asmlinkage long sys32_adjtimex(struct timex32 __user *txc_p32)
-{
- struct timex txc;
- struct timex32 t32;
- int ret;
- extern int do_adjtimex(struct timex *txc);
-
- if(copy_from_user(&t32, txc_p32, sizeof(struct timex32)))
- return -EFAULT;
-#undef CP
-#define CP(x) txc.x = t32.x
- CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror);
- CP(status); CP(constant); CP(precision); CP(tolerance);
- CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter);
- CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt);
- CP(stbcnt);
- ret = do_adjtimex(&txc);
-#undef CP
-#define CP(x) t32.x = txc.x
- CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror);
- CP(status); CP(constant); CP(precision); CP(tolerance);
- CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter);
- CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt);
- CP(stbcnt);
- return copy_to_user(txc_p32, &t32, sizeof(struct timex32)) ? -EFAULT : ret;
-}
-
-
struct sysinfo32 {
s32 uptime;
u32 loads[3];
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 71011eadb87..89b6c56ea0a 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -207,7 +207,7 @@
/* struct sockaddr... */
ENTRY_SAME(recvfrom)
/* struct timex contains longs */
- ENTRY_DIFF(adjtimex)
+ ENTRY_COMP(adjtimex)
ENTRY_SAME(mprotect) /* 125 */
/* old_sigset_t forced to 32 bits. Beware glibc sigset_t */
ENTRY_COMP(sigprocmask)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index fae42da7468..2cdc35ce804 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -37,6 +37,10 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default y
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
@@ -487,7 +491,7 @@ config PPC601_SYNC_FIX
If in doubt, say Y here.
config TAU
- bool "Thermal Management Support"
+ bool "On-chip CPU temperature sensor support"
depends on 6xx
help
G3 and G4 processors have an on-chip temperature sensor called the
@@ -496,7 +500,7 @@ config TAU
on-die temperature in /proc/cpuinfo if the cpu supports it.
Unfortunately, on some chip revisions, this sensor is very inaccurate
- and in some cases, does not work at all, so don't assume the cpu
+ and in many cases, does not work at all, so don't assume the cpu
temp is actually what /proc/cpuinfo says it is.
config TAU_INT
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 9254806f703..8d48e9e7162 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -110,11 +110,6 @@ config SERIAL_TEXT_DEBUG
depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \
PPC_GEN550 || PPC_MPC52xx
-config PPC_OCP
- bool
- depends on IBM_OCP || XILINX_OCP
- default y
-
choice
prompt "Early debugging (dangerous)"
bool
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index a3fc7a23158..6ec84d37a33 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -129,13 +129,8 @@ core-y += arch/powerpc/kernel/ \
arch/powerpc/lib/ \
arch/powerpc/sysdev/ \
arch/powerpc/platforms/
-core-$(CONFIG_PPC32) += arch/ppc/kernel/
-core-$(CONFIG_MATH_EMULATION) += arch/ppc/math-emu/
+core-$(CONFIG_MATH_EMULATION) += arch/powerpc/math-emu/
core-$(CONFIG_XMON) += arch/powerpc/xmon/
-core-$(CONFIG_APUS) += arch/ppc/amiga/
-drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/
-drivers-$(CONFIG_4xx) += arch/ppc/4xx_io/
-drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/
drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
@@ -150,7 +145,7 @@ CPPFLAGS_vmlinux.lds := -Upowerpc
BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage vmlinux.bin
-.PHONY: $(BOOT_TARGETS)
+PHONY += $(BOOT_TARGETS)
boot := arch/$(ARCH)/boot
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index 3c2acab6373..fe22e54ab2b 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc6
-# Wed Mar 15 16:19:48 2006
+# Linux kernel version: 2.6.16
+# Thu Mar 23 20:48:09 2006
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -30,6 +30,7 @@ CONFIG_POWER4=y
CONFIG_PPC_FPU=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=4
@@ -51,7 +52,8 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -85,7 +87,7 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
+CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
#
@@ -130,7 +132,8 @@ CONFIG_CELL_IIC=y
#
# Cell Broadband Engine options
#
-CONFIG_SPU_FS=y
+CONFIG_SPU_FS=m
+CONFIG_SPUFS_MMAP=y
#
# Kernel options
@@ -144,7 +147,7 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT is not set
CONFIG_PREEMPT_BKL=y
CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=m
CONFIG_FORCE_MAX_ZONEORDER=13
# CONFIG_IOMMU_VMERGE is not set
CONFIG_KEXEC=y
@@ -155,13 +158,16 @@ CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
+# CONFIG_FLATMEM_MANUAL is not set
# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_EXTREME=y
+# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
# CONFIG_PPC_64K_PAGES is not set
CONFIG_SCHED_SMT=y
CONFIG_PROC_DEVICETREE=y
@@ -232,6 +238,7 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_IP_VS is not set
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
@@ -244,25 +251,7 @@ CONFIG_NETFILTER=y
# Core Netfilter Configuration
#
# CONFIG_NETFILTER_NETLINK is not set
-CONFIG_NETFILTER_XTABLES=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XTABLES is not set
#
# IP: Netfilter Configuration
@@ -278,51 +267,13 @@ CONFIG_IP_NF_IRC=m
CONFIG_IP_NF_TFTP=m
CONFIG_IP_NF_AMANDA=m
# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
#
# IPv6: Netfilter Configuration (EXPERIMENTAL)
#
# CONFIG_IP6_NF_QUEUE is not set
-# CONFIG_IP6_NF_IPTABLES is not set
#
# DCCP Configuration (EXPERIMENTAL)
@@ -355,7 +306,6 @@ CONFIG_IP_NF_ARP_MANGLE=m
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
#
# Network testing
@@ -408,7 +358,7 @@ CONFIG_FW_LOADER=y
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
@@ -484,7 +434,23 @@ CONFIG_IDEDMA_AUTO=y
#
# Multi-device support (RAID and LVM)
#
-# CONFIG_MD is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_MULTIPATH_EMC is not set
#
# Fusion MPT device support
@@ -548,7 +514,7 @@ CONFIG_MII=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
CONFIG_E1000=m
-# CONFIG_E1000_NAPI is not set
+CONFIG_E1000_NAPI=y
# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
@@ -560,7 +526,7 @@ CONFIG_SKGE=m
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
-CONFIG_SPIDER_NET=y
+CONFIG_SPIDER_NET=m
# CONFIG_MV643XX_ETH is not set
#
@@ -678,6 +644,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_RTAS=y
#
# IPMI
@@ -694,14 +662,13 @@ CONFIG_WATCHDOG=y
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WATCHDOG_RTAS is not set
+CONFIG_WATCHDOG_RTAS=y
#
# PCI-based Watchdog Cards
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
-# CONFIG_RTC is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
# CONFIG_DTLK is not set
@@ -833,6 +800,7 @@ CONFIG_DUMMY_CONSOLE=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
@@ -852,7 +820,14 @@ CONFIG_USB_ARCH_HAS_OHCI=y
#
# InfiniBand support
#
-# CONFIG_INFINIBAND is not set
+CONFIG_INFINIBAND=y
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
#
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -1037,10 +1012,6 @@ CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=m
CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
#
# Instrumentation Support
@@ -1058,7 +1029,7 @@ CONFIG_LOG_BUF_SHIFT=15
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_MUTEXES is not set
+CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK is not set
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_KOBJECT is not set
diff --git a/arch/powerpc/configs/mpc8540_ads_defconfig b/arch/powerpc/configs/mpc8540_ads_defconfig
index 2a8290ee15c..7f0780f1aa3 100644
--- a/arch/powerpc/configs/mpc8540_ads_defconfig
+++ b/arch/powerpc/configs/mpc8540_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version:
-# Sat Jan 14 15:57:54 2006
+# Linux kernel version: 2.6.16
+# Mon Mar 27 23:37:36 2006
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -18,6 +19,7 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_PPC_UDBG_16550=y
# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_DEFAULT_UIMAGE=y
#
# Processor support
@@ -42,7 +44,6 @@ CONFIG_SPE=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -58,6 +59,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EMBEDDED=y
@@ -72,10 +74,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -90,6 +88,8 @@ CONFIG_BASE_SMALL=0
# Block layer
#
# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -183,6 +183,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -220,6 +221,11 @@ CONFIG_TCP_CONG_BIC=y
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
@@ -229,11 +235,6 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -487,6 +488,12 @@ CONFIG_GEN_RTC=y
# CONFIG_I2C is not set
#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
@@ -496,6 +503,7 @@ CONFIG_GEN_RTC=y
#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
@@ -503,10 +511,6 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -531,6 +535,7 @@ CONFIG_HWMON=y
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -551,7 +556,7 @@ CONFIG_HWMON=y
#
#
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
@@ -603,7 +608,6 @@ CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
@@ -658,6 +662,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
#
@@ -695,6 +700,8 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUGGER is not set
# CONFIG_BDI_SWITCH is not set
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 80e9fe2632b..0cc0995b81b 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -12,12 +12,12 @@ endif
obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
irq.o align.o signal_32.o pmc.o vdso.o \
- init_task.o process.o systbl.o
+ init_task.o process.o systbl.o idle.o
obj-y += vdso32/
obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
signal_64.o ptrace32.o \
paca.o cpu_setup_power4.o \
- firmware.o sysfs.o idle_64.o
+ firmware.o sysfs.o
obj-$(CONFIG_PPC64) += vdso64/
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
obj-$(CONFIG_POWER4) += idle_power4.o
@@ -34,6 +34,11 @@ obj-$(CONFIG_IBMEBUS) += ibmebus.o
obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
+obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
+obj-$(CONFIG_TAU) += tau_6xx.o
+obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o
+obj32-$(CONFIG_MODULES) += module_32.o
+obj-$(CONFIG_E500) += perfmon_fsl_booke.o
ifeq ($(CONFIG_PPC_MERGE),y)
@@ -51,7 +56,6 @@ obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
obj-$(CONFIG_MODULES) += ppc_ksyms.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o
-obj-$(CONFIG_6xx) += idle_6xx.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
@@ -77,6 +81,7 @@ smpobj-$(CONFIG_SMP) += smp.o
endif
+obj-$(CONFIG_PPC32) += $(obj32-y)
obj-$(CONFIG_PPC64) += $(obj64-y)
extra-$(CONFIG_PPC_FPU) += fpu.o
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 882889b1592..54b48f33005 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -105,8 +105,6 @@ int main(void)
DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size));
DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size));
DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page));
- DEFINE(PLATFORM_LPAR, PLATFORM_LPAR);
-
/* paca */
DEFINE(PACA_SIZE, sizeof(struct paca_struct));
DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index));
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S
index 55ed7716636..55ed7716636 100644
--- a/arch/ppc/kernel/cpu_setup_6xx.S
+++ b/arch/powerpc/kernel/cpu_setup_6xx.S
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 4827ca1ec89..b3a97946722 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -135,10 +135,10 @@ transfer_to_handler:
mfspr r11,SPRN_HID0
mtcr r11
BEGIN_FTR_SECTION
- bt- 8,power_save_6xx_restore /* Check DOZE */
+ bt- 8,4f /* Check DOZE */
END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
BEGIN_FTR_SECTION
- bt- 9,power_save_6xx_restore /* Check NAP */
+ bt- 9,4f /* Check NAP */
END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
#endif /* CONFIG_6xx */
.globl transfer_to_handler_cont
@@ -157,6 +157,10 @@ transfer_to_handler_cont:
SYNC
RFI /* jump to handler, enable MMU */
+#ifdef CONFIG_6xx
+4: b power_save_6xx_restore
+#endif
+
/*
* On kernel stack overflow, load up an initial stack pointer
* and call StackOverflow(regs), which should not return.
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 1060155d84c..19ad5c6b181 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -617,6 +617,12 @@ _GLOBAL(enter_rtas)
mfsrr1 r10
std r10,_SRR1(r1)
+ /* Temporary workaround to clear CR until RTAS can be modified to
+ * ignore all bits.
+ */
+ li r0,0
+ mtcr r0
+
/* There is no way it is acceptable to get here with interrupts enabled,
* check it with the asm equivalent of WARN_ON
*/
diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c
index 4d37a3cb80f..0bfe9061720 100644
--- a/arch/powerpc/kernel/firmware.c
+++ b/arch/powerpc/kernel/firmware.c
@@ -14,7 +14,9 @@
*/
#include <linux/config.h>
+#include <linux/module.h>
#include <asm/firmware.h>
-unsigned long ppc64_firmware_features;
+unsigned long powerpc_firmware_features;
+EXPORT_SYMBOL_GPL(powerpc_firmware_features);
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 35084f3a841..a5ae04a57c7 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -1544,7 +1544,11 @@ _STATIC(__boot_from_prom)
mr r28,r6
mr r27,r7
- /* Align the stack to 16-byte boundary for broken yaboot */
+ /*
+ * Align the stack to 16-byte boundary
+ * Depending on the size and layout of the ELF sections in the initial
+ * boot binary, the stack pointer will be unalignet on PowerMac
+ */
rldicr r1,r1,0,59
/* Make sure we are running in 64 bits mode */
@@ -1847,21 +1851,6 @@ _STATIC(start_here_multiplatform)
bl .__save_cpu_setup
sync
- /* Setup a valid physical PACA pointer in SPRG3 for early_setup
- * note that boot_cpuid can always be 0 nowadays since there is
- * nowhere it can be initialized differently before we reach this
- * code
- */
- LOAD_REG_IMMEDIATE(r27, boot_cpuid)
- add r27,r27,r26
- lwz r27,0(r27)
-
- LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */
- mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */
- add r13,r13,r24 /* for this processor. */
- add r13,r13,r26 /* convert to physical addr */
- mtspr SPRN_SPRG3,r13
-
/* Do very early kernel initializations, including initial hash table,
* stab and slb setup before we turn on relocation. */
@@ -1930,6 +1919,17 @@ _STATIC(start_here_common)
/* Not reached */
BUG_OPCODE
+/* Put the paca pointer into r13 and SPRG3 */
+_GLOBAL(setup_boot_paca)
+ LOAD_REG_IMMEDIATE(r3, boot_cpuid)
+ lwz r3,0(r3)
+ LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */
+ mulli r3,r3,PACA_SIZE /* Calculate vaddr of right paca */
+ add r13,r3,r4 /* for this processor. */
+ mtspr SPRN_SPRG3,r13
+
+ blr
+
/*
* We put a few things here that have to be page-aligned.
* This stuff goes at the beginning of the bss, which is page-aligned.
diff --git a/arch/powerpc/kernel/idle_64.c b/arch/powerpc/kernel/idle.c
index b879d3057ef..e9f321d74d8 100644
--- a/arch/powerpc/kernel/idle_64.c
+++ b/arch/powerpc/kernel/idle.c
@@ -2,13 +2,17 @@
* Idle daemon for PowerPC. Idle daemon will handle any action
* that needs to be taken when the system becomes idle.
*
- * Originally Written by Cort Dougan (cort@cs.nmt.edu)
+ * Originally written by Cort Dougan (cort@cs.nmt.edu).
+ * Subsequent 32-bit hacking by Tom Rini, Armin Kuster,
+ * Paul Mackerras and others.
*
* iSeries supported added by Mike Corrigan <mikejc@us.ibm.com>
*
* Additional shared processor, SMT, and firmware support
* Copyright (c) 2003 Dave Engebretsen <engebret@us.ibm.com>
*
+ * 32-bit and 64-bit versions merged by Paul Mackerras <paulus@samba.org>
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -29,18 +33,43 @@
#include <asm/machdep.h>
#include <asm/smp.h>
-extern void power4_idle(void);
+#ifdef CONFIG_HOTPLUG_CPU
+#define cpu_should_die() (cpu_is_offline(smp_processor_id()) && \
+ system_state == SYSTEM_RUNNING)
+#else
+#define cpu_should_die() 0
+#endif
-void default_idle(void)
+/*
+ * The body of the idle task.
+ */
+void cpu_idle(void)
{
- unsigned int cpu = smp_processor_id();
- set_thread_flag(TIF_POLLING_NRFLAG);
+ if (ppc_md.idle_loop)
+ ppc_md.idle_loop(); /* doesn't return */
+ set_thread_flag(TIF_POLLING_NRFLAG);
while (1) {
- if (!need_resched()) {
- while (!need_resched() && !cpu_is_offline(cpu)) {
- ppc64_runlatch_off();
+ ppc64_runlatch_off();
+ while (!need_resched() && !cpu_should_die()) {
+ if (ppc_md.power_save) {
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+ /*
+ * smp_mb is so clearing of TIF_POLLING_NRFLAG
+ * is ordered w.r.t. need_resched() test.
+ */
+ smp_mb();
+ local_irq_disable();
+
+ /* check again after disabling irqs */
+ if (!need_resched() && !cpu_should_die())
+ ppc_md.power_save();
+
+ local_irq_enable();
+ set_thread_flag(TIF_POLLING_NRFLAG);
+
+ } else {
/*
* Go into low thread priority and possibly
* low power mode.
@@ -48,46 +77,18 @@ void default_idle(void)
HMT_low();
HMT_very_low();
}
-
- HMT_medium();
}
+ HMT_medium();
ppc64_runlatch_on();
+ if (cpu_should_die())
+ cpu_die();
preempt_enable_no_resched();
schedule();
preempt_disable();
- if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
- cpu_die();
}
}
-void native_idle(void)
-{
- while (1) {
- ppc64_runlatch_off();
-
- if (!need_resched())
- power4_idle();
-
- if (need_resched()) {
- ppc64_runlatch_on();
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
- }
-
- if (cpu_is_offline(smp_processor_id()) &&
- system_state == SYSTEM_RUNNING)
- cpu_die();
- }
-}
-
-void cpu_idle(void)
-{
- BUG_ON(NULL == ppc_md.idle_loop);
- ppc_md.idle_loop();
-}
-
int powersave_nap;
#ifdef CONFIG_SYSCTL
diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S
index 444fdcc769f..12a4efbaa08 100644
--- a/arch/powerpc/kernel/idle_6xx.S
+++ b/arch/powerpc/kernel/idle_6xx.S
@@ -87,19 +87,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
cmpwi 0,r3,0
beqlr
- /* Clear MSR:EE */
- mfmsr r7
- rlwinm r0,r7,0,17,15
- mtmsr r0
-
- /* Check current_thread_info()->flags */
- rlwinm r4,r1,0,0,18
- lwz r4,TI_FLAGS(r4)
- andi. r0,r4,_TIF_NEED_RESCHED
- beq 1f
- mtmsr r7 /* out of line this ? */
- blr
-1:
/* Some pre-nap cleanups needed on some CPUs */
andis. r0,r3,HID0_NAP@h
beq 2f
@@ -157,7 +144,8 @@ BEGIN_FTR_SECTION
DSSALL
sync
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
- ori r7,r7,MSR_EE /* Could be ommited (already set) */
+ mfmsr r7
+ ori r7,r7,MSR_EE
oris r7,r7,MSR_POW@h
sync
isync
@@ -220,8 +208,6 @@ _GLOBAL(nap_save_msscr0)
_GLOBAL(nap_save_hid1)
.space 4*NR_CPUS
-_GLOBAL(powersave_nap)
- .long 0
_GLOBAL(powersave_lowspeed)
.long 0
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index c16b4afab58..6dad1c02496 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -1,11 +1,5 @@
/*
- * This file contains the power_save function for 6xx & 7xxx CPUs
- * rewritten in assembler
- *
- * Warning ! This code assumes that if your machine has a 750fx
- * it will have PLL 1 set to low speed mode (used during NAP/DOZE).
- * if this is not the case some additional changes will have to
- * be done to check a runtime var (a bit like powersave-nap)
+ * This file contains the power_save function for 970-family CPUs.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -26,49 +20,23 @@
.text
-/*
- * Here is the power_save_6xx function. This could eventually be
- * split into several functions & changing the function pointer
- * depending on the various features.
- */
_GLOBAL(power4_idle)
BEGIN_FTR_SECTION
blr
END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
- /* We must dynamically check for the NAP feature as it
- * can be cleared by CPU init after the fixups are done
- */
- LOAD_REG_ADDRBASE(r3,cur_cpu_spec)
- ld r4,ADDROFF(cur_cpu_spec)(r3)
- ld r4,CPU_SPEC_FEATURES(r4)
- andi. r0,r4,CPU_FTR_CAN_NAP
- beqlr
/* Now check if user or arch enabled NAP mode */
LOAD_REG_ADDRBASE(r3,powersave_nap)
lwz r4,ADDROFF(powersave_nap)(r3)
cmpwi 0,r4,0
beqlr
- /* Clear MSR:EE */
- mfmsr r7
- li r4,0
- ori r4,r4,MSR_EE
- andc r0,r7,r4
- mtmsrd r0
-
- /* Check current_thread_info()->flags */
- clrrdi r4,r1,THREAD_SHIFT
- ld r4,TI_FLAGS(r4)
- andi. r0,r4,_TIF_NEED_RESCHED
- beq 1f
- mtmsrd r7 /* out of line this ? */
- blr
-1:
/* Go to NAP now */
BEGIN_FTR_SECTION
DSSALL
sync
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+ mfmsr r7
+ ori r7,r7,MSR_EE
oris r7,r7,MSR_POW@h
sync
isync
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 771a59cbd21..bb5c9501234 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -379,7 +379,7 @@ void irq_ctx_init(void)
struct thread_info *tp;
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
tp = softirq_ctx[i];
tp->cpu = i;
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index cb1fe5878e8..ad7a9021220 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -30,9 +30,11 @@
#include <linux/kprobes.h>
#include <linux/ptrace.h>
#include <linux/preempt.h>
+#include <linux/module.h>
#include <asm/cacheflush.h>
#include <asm/kdebug.h>
#include <asm/sstep.h>
+#include <asm/uaccess.h>
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
@@ -372,17 +374,62 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-
- if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
- return 1;
-
- if (kcb->kprobe_status & KPROBE_HIT_SS) {
- resume_execution(cur, regs);
+ const struct exception_table_entry *entry;
+
+ switch(kcb->kprobe_status) {
+ case KPROBE_HIT_SS:
+ case KPROBE_REENTER:
+ /*
+ * We are here because the instruction being single
+ * stepped caused a page fault. We reset the current
+ * kprobe and the nip points back to the probe address
+ * and allow the page fault handler to continue as a
+ * normal page fault.
+ */
+ regs->nip = (unsigned long)cur->addr;
regs->msr &= ~MSR_SE;
regs->msr |= kcb->kprobe_saved_msr;
-
- reset_current_kprobe();
+ if (kcb->kprobe_status == KPROBE_REENTER)
+ restore_previous_kprobe(kcb);
+ else
+ reset_current_kprobe();
preempt_enable_no_resched();
+ break;
+ case KPROBE_HIT_ACTIVE:
+ case KPROBE_HIT_SSDONE:
+ /*
+ * We increment the nmissed count for accounting,
+ * we can also use npre/npostfault count for accouting
+ * these specific fault cases.
+ */
+ kprobes_inc_nmissed_count(cur);
+
+ /*
+ * We come here because instructions in the pre/post
+ * handler caused the page_fault, this could happen
+ * if handler tries to access user space by
+ * copy_from_user(), get_user() etc. Let the
+ * user-specified handler try to fix it first.
+ */
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+ return 1;
+
+ /*
+ * In case the user-specified fault handler returned
+ * zero, try to fix up.
+ */
+ if ((entry = search_exception_tables(regs->nip)) != NULL) {
+ regs->nip = entry->fixup;
+ return 1;
+ }
+
+ /*
+ * fixup_exception() could not handle it,
+ * Let do_page_fault() fix it.
+ */
+ break;
+ default:
+ break;
}
return 0;
}
@@ -396,6 +443,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
struct die_args *args = (struct die_args *)data;
int ret = NOTIFY_DONE;
+ if (args->regs && user_mode(args->regs))
+ return ret;
+
switch (val) {
case DIE_BPT:
if (kprobe_handler(args->regs))
diff --git a/arch/ppc/kernel/l2cr.S b/arch/powerpc/kernel/l2cr_6xx.S
index d7f4e982b53..d7f4e982b53 100644
--- a/arch/ppc/kernel/l2cr.S
+++ b/arch/powerpc/kernel/l2cr_6xx.S
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index c7a799a0951..6e67b5b49ba 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -37,7 +37,7 @@ static int legacy_serial_console = -1;
static int __init add_legacy_port(struct device_node *np, int want_index,
int iotype, phys_addr_t base,
phys_addr_t taddr, unsigned long irq,
- unsigned int flags)
+ upf_t flags)
{
u32 *clk, *spd, clock = BASE_BAUD * 16;
int index;
@@ -113,7 +113,7 @@ static int __init add_legacy_soc_port(struct device_node *np,
{
phys_addr_t addr;
u32 *addrp;
- unsigned int flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
+ upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
/* We only support ports that have a clock frequency properly
* encoded in the device-tree.
@@ -236,6 +236,23 @@ static int __init add_legacy_pci_port(struct device_node *np,
}
#endif
+static void __init setup_legacy_serial_console(int console)
+{
+ struct legacy_serial_info *info =
+ &legacy_serial_infos[console];
+ void __iomem *addr;
+
+ if (info->taddr == 0)
+ return;
+ addr = ioremap(info->taddr, 0x1000);
+ if (addr == NULL)
+ return;
+ if (info->speed == 0)
+ info->speed = udbg_probe_uart_speed(addr, info->clock);
+ DBG("default console speed = %d\n", info->speed);
+ udbg_init_uart(addr, info->speed, info->clock);
+}
+
/*
* This is called very early, as part of setup_system() or eventually
* setup_arch(), basically before anything else in this file. This function
@@ -318,25 +335,8 @@ void __init find_legacy_serial_ports(void)
#endif
DBG("legacy_serial_console = %d\n", legacy_serial_console);
-
- /* udbg is 64 bits only for now, that will change soon though ... */
- while (legacy_serial_console >= 0) {
- struct legacy_serial_info *info =
- &legacy_serial_infos[legacy_serial_console];
- void __iomem *addr;
-
- if (info->taddr == 0)
- break;
- addr = ioremap(info->taddr, 0x1000);
- if (addr == NULL)
- break;
- if (info->speed == 0)
- info->speed = udbg_probe_uart_speed(addr, info->clock);
- DBG("default console speed = %d\n", info->speed);
- udbg_init_uart(addr, info->speed, info->clock);
- break;
- }
-
+ if (legacy_serial_console >= 0)
+ setup_legacy_serial_console(legacy_serial_console);
DBG(" <- find_legacy_serial_port()\n");
}
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index e789fef4eb8..1b73508ecb2 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -56,7 +56,7 @@ static unsigned long get_purr(void)
unsigned long sum_purr = 0;
int cpu;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
sum_purr += lppaca[cpu].emulated_time_base;
#ifdef PURR_DEBUG
@@ -222,7 +222,7 @@ static unsigned long get_purr(void)
int cpu;
struct cpu_usage *cu;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
cu = &per_cpu(cpu_usage_array, cpu);
sum_purr += cu->current_tb;
}
diff --git a/arch/ppc/kernel/module.c b/arch/powerpc/kernel/module_32.c
index 92f4e5f64f0..92f4e5f64f0 100644
--- a/arch/ppc/kernel/module.c
+++ b/arch/powerpc/kernel/module_32.c
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index fd7db8d542d..ada50aa5b60 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -160,7 +160,7 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file,
case IOC_NVRAM_GET_OFFSET: {
int part, offset;
- if (_machine != PLATFORM_POWERMAC)
+ if (!machine_is(powermac))
return -EINVAL;
if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0)
return -EFAULT;
@@ -174,8 +174,9 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file,
return 0;
}
#endif /* CONFIG_PPC_PMAC */
+ default:
+ return -EINVAL;
}
- return -EINVAL;
}
struct file_operations nvram_fops = {
@@ -443,7 +444,7 @@ static int nvram_setup_partition(void)
* in our nvram, as Apple defined partitions use pretty much
* all of the space
*/
- if (_machine == PLATFORM_POWERMAC)
+ if (machine_is(powermac))
return -ENOSPC;
/* see if we have an OS partition that meets our needs.
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 5d1b708086b..f505a8827e3 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -56,14 +56,11 @@ struct lppaca lppaca[] = {
* processors. The processor VPD array needs one entry per physical
* processor (not thread).
*/
-#define PACA_INIT_COMMON(number, start, asrr, asrv) \
+#define PACA_INIT_COMMON(number) \
.lppaca_ptr = &lppaca[number], \
.lock_token = 0x8000, \
.paca_index = (number), /* Paca Index */ \
.kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \
- .stab_real = (asrr), /* Real pointer to segment table */ \
- .stab_addr = (asrv), /* Virt pointer to segment table */ \
- .cpu_start = (start), /* Processor start */ \
.hw_cpu_id = 0xffff,
#ifdef CONFIG_PPC_ISERIES
@@ -72,30 +69,20 @@ struct lppaca lppaca[] = {
#define PACA_INIT(number) \
{ \
- PACA_INIT_COMMON(number, 0, 0, 0) \
- PACA_INIT_ISERIES(number) \
-}
-
-#define BOOTCPU_PACA_INIT(number) \
-{ \
- PACA_INIT_COMMON(number, 1, 0, (u64)&initial_stab) \
+ PACA_INIT_COMMON(number) \
PACA_INIT_ISERIES(number) \
}
#else
#define PACA_INIT(number) \
{ \
- PACA_INIT_COMMON(number, 0, 0, 0) \
+ PACA_INIT_COMMON(number) \
}
-#define BOOTCPU_PACA_INIT(number) \
-{ \
- PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, (u64)&initial_stab) \
-}
#endif
struct paca_struct paca[] = {
- BOOTCPU_PACA_INIT(0),
+ PACA_INIT(0),
#if NR_CPUS > 1
PACA_INIT( 1), PACA_INIT( 2), PACA_INIT( 3),
#if NR_CPUS > 4
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 704c846b2b0..b129d2e4b75 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -787,7 +787,7 @@ pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
* fix has to be done by making the remapping per-host and always
* filling the pci_to_OF map. --BenH
*/
- if (_machine == _MACH_Pmac && busnr >= 0xf0)
+ if (machine_is(powermac) && busnr >= 0xf0)
busnr -= 0xf0;
else
#endif
@@ -1728,7 +1728,7 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
* (bus 0 is HT root), we return the AGP one instead.
*/
#ifdef CONFIG_PPC_PMAC
- if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4"))
+ if (machine_is(powermac) && machine_is_compatible("MacRISC4"))
if (bus == 0)
bus = 0xf0;
#endif /* CONFIG_PPC_PMAC */
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index ba92bab7cc2..4c4449be81c 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -78,6 +78,7 @@ int global_phb_number; /* Global phb counter */
/* Cached ISA bridge dev. */
struct pci_dev *ppc64_isabridge_dev = NULL;
+EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
static void fixup_broken_pcnet32(struct pci_dev* dev)
{
diff --git a/arch/ppc/kernel/perfmon_fsl_booke.c b/arch/powerpc/kernel/perfmon_fsl_booke.c
index 32455dfcc36..32455dfcc36 100644
--- a/arch/ppc/kernel/perfmon_fsl_booke.c
+++ b/arch/powerpc/kernel/perfmon_fsl_booke.c
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
index 7ba42a405f4..3c2cf661f6d 100644
--- a/arch/powerpc/kernel/proc_ppc64.c
+++ b/arch/powerpc/kernel/proc_ppc64.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/kernel.h>
+#include <asm/machdep.h>
#include <asm/vdso_datapage.h>
#include <asm/rtas.h>
#include <asm/uaccess.h>
@@ -51,7 +52,7 @@ static int __init proc_ppc64_create(void)
if (!root)
return 1;
- if (!(platform_is_pseries() || _machine == PLATFORM_CELL))
+ if (!machine_is(pseries) && !machine_is(cell))
return 0;
if (!proc_mkdir("rtas", root))
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 1770a066c21..706090c99f4 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -35,7 +35,6 @@
#include <linux/mqueue.h>
#include <linux/hardirq.h>
#include <linux/utsname.h>
-#include <linux/kprobes.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -46,6 +45,7 @@
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/time.h>
+#include <asm/syscalls.h>
#ifdef CONFIG_PPC64
#include <asm/firmware.h>
#endif
@@ -363,7 +363,11 @@ static void show_instructions(struct pt_regs *regs)
if (!(i % 8))
printk("\n");
- if (BAD_PC(pc) || __get_user(instr, (unsigned int *)pc)) {
+ /* We use __get_user here *only* to avoid an OOPS on a
+ * bad address because the pc *should* only be a
+ * kernel address.
+ */
+ if (BAD_PC(pc) || __get_user(instr, (unsigned int __user *)pc)) {
printk("XXXXXXXX ");
} else {
if (regs->nip == pc)
@@ -460,7 +464,6 @@ void show_regs(struct pt_regs * regs)
void exit_thread(void)
{
- kprobe_flush_task(current);
discard_lazy_cpu_state();
}
@@ -767,7 +770,7 @@ out:
return error;
}
-static int validate_sp(unsigned long sp, struct task_struct *p,
+int validate_sp(unsigned long sp, struct task_struct *p,
unsigned long nbytes)
{
unsigned long stack_page = (unsigned long)task_stack_page(p);
@@ -805,6 +808,8 @@ static int validate_sp(unsigned long sp, struct task_struct *p,
#define FRAME_MARKER 2
#endif
+EXPORT_SYMBOL(validate_sp);
+
unsigned long get_wchan(struct task_struct *p)
{
unsigned long ip, sp;
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index d63cd562d9d..4336390bcf3 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -383,14 +383,14 @@ static int __devinit finish_node_interrupts(struct device_node *np,
/* Apple uses bits in there in a different way, let's
* only keep the real sense bit on macs
*/
- if (_machine == PLATFORM_POWERMAC)
+ if (machine_is(powermac))
sense &= 0x1;
np->intrs[intrcount].sense = map_mpic_senses[sense];
}
#ifdef CONFIG_PPC64
/* We offset irq numbers for the u3 MPIC by 128 in PowerMac */
- if (_machine == PLATFORM_POWERMAC && ic && ic->parent) {
+ if (machine_is(powermac) && ic && ic->parent) {
char *name = get_property(ic->parent, "name", NULL);
if (name && !strcmp(name, "u3"))
np->intrs[intrcount].line += 128;
@@ -570,6 +570,18 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
return rc;
}
+unsigned long __init of_get_flat_dt_root(void)
+{
+ unsigned long p = ((unsigned long)initial_boot_params) +
+ initial_boot_params->off_dt_struct;
+
+ while(*((u32 *)p) == OF_DT_NOP)
+ p += 4;
+ BUG_ON (*((u32 *)p) != OF_DT_BEGIN_NODE);
+ p += 4;
+ return _ALIGN(p + strlen((char *)p) + 1, 4);
+}
+
/**
* This function can be used within scan_flattened_dt callback to get
* access to properties
@@ -612,6 +624,25 @@ void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
} while(1);
}
+int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
+{
+ const char* cp;
+ unsigned long cplen, l;
+
+ cp = of_get_flat_dt_prop(node, "compatible", &cplen);
+ if (cp == NULL)
+ return 0;
+ while (cplen > 0) {
+ if (strncasecmp(cp, compat, strlen(compat)) == 0)
+ return 1;
+ l = strlen(cp) + 1;
+ cp += l;
+ cplen -= l;
+ }
+
+ return 0;
+}
+
static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
unsigned long align)
{
@@ -686,7 +717,7 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
#ifdef DEBUG
if ((strlen(p) + l + 1) != allocl) {
DBG("%s: p: %d, l: %d, a: %d\n",
- pathp, strlen(p), l, allocl);
+ pathp, (int)strlen(p), l, allocl);
}
#endif
p += strlen(p);
@@ -854,35 +885,73 @@ void __init unflatten_device_tree(void)
DBG(" <- unflatten_device_tree()\n");
}
-
static int __init early_init_dt_scan_cpus(unsigned long node,
- const char *uname, int depth, void *data)
+ const char *uname, int depth,
+ void *data)
{
+ static int logical_cpuid = 0;
+ char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+#ifdef CONFIG_ALTIVEC
u32 *prop;
- unsigned long size;
- char *type = of_get_flat_dt_prop(node, "device_type", &size);
+#endif
+ u32 *intserv;
+ int i, nthreads;
+ unsigned long len;
+ int found = 0;
/* We are scanning "cpu" nodes only */
if (type == NULL || strcmp(type, "cpu") != 0)
return 0;
- boot_cpuid = 0;
- boot_cpuid_phys = 0;
- if (initial_boot_params && initial_boot_params->version >= 2) {
- /* version 2 of the kexec param format adds the phys cpuid
- * of booted proc.
- */
- boot_cpuid_phys = initial_boot_params->boot_cpuid_phys;
+ /* Get physical cpuid */
+ intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len);
+ if (intserv) {
+ nthreads = len / sizeof(int);
} else {
- /* Check if it's the boot-cpu, set it's hw index now */
- if (of_get_flat_dt_prop(node,
+ intserv = of_get_flat_dt_prop(node, "reg", NULL);
+ nthreads = 1;
+ }
+
+ /*
+ * Now see if any of these threads match our boot cpu.
+ * NOTE: This must match the parsing done in smp_setup_cpu_maps.
+ */
+ for (i = 0; i < nthreads; i++) {
+ /*
+ * version 2 of the kexec param format adds the phys cpuid of
+ * booted proc.
+ */
+ if (initial_boot_params && initial_boot_params->version >= 2) {
+ if (intserv[i] ==
+ initial_boot_params->boot_cpuid_phys) {
+ found = 1;
+ break;
+ }
+ } else {
+ /*
+ * Check if it's the boot-cpu, set it's hw index now,
+ * unfortunately this format did not support booting
+ * off secondary threads.
+ */
+ if (of_get_flat_dt_prop(node,
"linux,boot-cpu", NULL) != NULL) {
- prop = of_get_flat_dt_prop(node, "reg", NULL);
- if (prop != NULL)
- boot_cpuid_phys = *prop;
+ found = 1;
+ break;
+ }
}
+
+#ifdef CONFIG_SMP
+ /* logical cpu id is always 0 on UP kernels */
+ logical_cpuid++;
+#endif
+ }
+
+ if (found) {
+ DBG("boot cpu: logical %d physical %d\n", logical_cpuid,
+ intserv[i]);
+ boot_cpuid = logical_cpuid;
+ set_hard_smp_processor_id(boot_cpuid, intserv[i]);
}
- set_hard_smp_processor_id(0, boot_cpuid_phys);
#ifdef CONFIG_ALTIVEC
/* Check if we have a VMX and eventually update CPU features */
@@ -901,16 +970,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_PPC_PSERIES
- /*
- * Check for an SMT capable CPU and set the CPU feature. We do
- * this by looking at the size of the ibm,ppc-interrupt-server#s
- * property
- */
- prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
- &size);
- cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
- if (prop && ((size / sizeof(u32)) > 1))
+ if (nthreads > 1)
cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
+ else
+ cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
#endif
return 0;
@@ -919,7 +982,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
static int __init early_init_dt_scan_chosen(unsigned long node,
const char *uname, int depth, void *data)
{
- u32 *prop;
unsigned long *lprop;
unsigned long l;
char *p;
@@ -930,14 +992,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
(strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
return 0;
- /* get platform type */
- prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL);
- if (prop == NULL)
- return 0;
-#ifdef CONFIG_PPC_MULTIPLATFORM
- _machine = *prop;
-#endif
-
#ifdef CONFIG_PPC64
/* check if iommu is forced on or off */
if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
@@ -964,15 +1018,15 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
* set of RTAS infos now if available
*/
{
- u64 *basep, *entryp;
+ u64 *basep, *entryp, *sizep;
basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL);
entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
- prop = of_get_flat_dt_prop(node, "linux,rtas-size", NULL);
- if (basep && entryp && prop) {
+ sizep = of_get_flat_dt_prop(node, "linux,rtas-size", NULL);
+ if (basep && entryp && sizep) {
rtas.base = *basep;
rtas.entry = *entryp;
- rtas.size = *prop;
+ rtas.size = *sizep;
}
}
#endif /* CONFIG_PPC_RTAS */
@@ -1001,25 +1055,13 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
if (strstr(cmd_line, "mem=")) {
char *p, *q;
- unsigned long maxmem = 0;
for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
q = p + 4;
if (p > cmd_line && p[-1] != ' ')
continue;
- maxmem = simple_strtoul(q, &q, 0);
- if (*q == 'k' || *q == 'K') {
- maxmem <<= 10;
- ++q;
- } else if (*q == 'm' || *q == 'M') {
- maxmem <<= 20;
- ++q;
- } else if (*q == 'g' || *q == 'G') {
- maxmem <<= 30;
- ++q;
- }
+ memory_limit = memparse(q, &q);
}
- memory_limit = maxmem;
}
/* break now */
@@ -1755,7 +1797,7 @@ static int of_finish_dynamic_node(struct device_node *node)
/* We don't support that function on PowerMac, at least
* not yet
*/
- if (_machine == PLATFORM_POWERMAC)
+ if (machine_is(powermac))
return -ENODEV;
/* fix up new node's linux_phandle field */
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 813c2cd194c..d66c5e77fcf 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -180,6 +180,16 @@ static unsigned long __initdata prom_tce_alloc_start;
static unsigned long __initdata prom_tce_alloc_end;
#endif
+/* Platforms codes are now obsolete in the kernel. Now only used within this
+ * file and ultimately gone too. Feel free to change them if you need, they
+ * are not shared with anything outside of this file anymore
+ */
+#define PLATFORM_PSERIES 0x0100
+#define PLATFORM_PSERIES_LPAR 0x0101
+#define PLATFORM_LPAR 0x0001
+#define PLATFORM_POWERMAC 0x0400
+#define PLATFORM_GENERIC 0x0500
+
static int __initdata of_platform;
static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
@@ -397,6 +407,11 @@ static void __init __attribute__((noreturn)) prom_panic(const char *reason)
reason = PTRRELOC(reason);
#endif
prom_print(reason);
+ /* Do not call exit because it clears the screen on pmac
+ * it also causes some sort of double-fault on early pmacs */
+ if (RELOC(of_platform) == PLATFORM_POWERMAC)
+ asm("trap\n");
+
/* ToDo: should put up an SRC here on p/iSeries */
call_prom("exit", 0, 0);
@@ -1487,7 +1502,10 @@ static int __init prom_find_machine_type(void)
int len, i = 0;
#ifdef CONFIG_PPC64
phandle rtas;
+ int x;
#endif
+
+ /* Look for a PowerMac */
len = prom_getprop(_prom->root, "compatible",
compat, sizeof(compat)-1);
if (len > 0) {
@@ -1500,28 +1518,36 @@ static int __init prom_find_machine_type(void)
if (strstr(p, RELOC("Power Macintosh")) ||
strstr(p, RELOC("MacRISC")))
return PLATFORM_POWERMAC;
-#ifdef CONFIG_PPC64
- if (strstr(p, RELOC("Momentum,Maple")))
- return PLATFORM_MAPLE;
- if (strstr(p, RELOC("IBM,CPB")))
- return PLATFORM_CELL;
-#endif
i += sl + 1;
}
}
#ifdef CONFIG_PPC64
+ /* If not a mac, try to figure out if it's an IBM pSeries or any other
+ * PAPR compliant platform. We assume it is if :
+ * - /device_type is "chrp" (please, do NOT use that for future
+ * non-IBM designs !
+ * - it has /rtas
+ */
+ len = prom_getprop(_prom->root, "model",
+ compat, sizeof(compat)-1);
+ if (len <= 0)
+ return PLATFORM_GENERIC;
+ compat[len] = 0;
+ if (strcmp(compat, "chrp"))
+ return PLATFORM_GENERIC;
+
/* Default to pSeries. We need to know if we are running LPAR */
rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
- if (PHANDLE_VALID(rtas)) {
- int x = prom_getproplen(rtas, "ibm,hypertas-functions");
- if (x != PROM_ERROR) {
- prom_printf("Hypertas detected, assuming LPAR !\n");
- return PLATFORM_PSERIES_LPAR;
- }
+ if (!PHANDLE_VALID(rtas))
+ return PLATFORM_GENERIC;
+ x = prom_getproplen(rtas, "ibm,hypertas-functions");
+ if (x != PROM_ERROR) {
+ prom_printf("Hypertas detected, assuming LPAR !\n");
+ return PLATFORM_PSERIES_LPAR;
}
return PLATFORM_PSERIES;
#else
- return PLATFORM_CHRP;
+ return PLATFORM_GENERIC;
#endif
}
@@ -2029,7 +2055,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
{
struct prom_t *_prom;
unsigned long hdr;
- u32 getprop_rval;
unsigned long offset = reloc_offset();
#ifdef CONFIG_PPC32
@@ -2060,6 +2085,12 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
*/
prom_init_stdout();
+ /*
+ * Get default machine type. At this point, we do not differentiate
+ * between pSeries SMP and pSeries LPAR
+ */
+ RELOC(of_platform) = prom_find_machine_type();
+
/* Bail if this is a kdump kernel. */
if (PHYSICAL_START > 0)
prom_panic("Error: You can't boot a kdump kernel from OF!\n");
@@ -2069,15 +2100,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
*/
prom_check_initrd(r3, r4);
- /*
- * Get default machine type. At this point, we do not differentiate
- * between pSeries SMP and pSeries LPAR
- */
- RELOC(of_platform) = prom_find_machine_type();
- getprop_rval = RELOC(of_platform);
- prom_setprop(_prom->chosen, "/chosen", "linux,platform",
- &getprop_rval, sizeof(getprop_rval));
-
#ifdef CONFIG_PPC_PSERIES
/*
* On pSeries, inform the firmware about our capabilities
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
index 1f03fb28cc0..456286cf1d1 100644
--- a/arch/powerpc/kernel/rtas-proc.c
+++ b/arch/powerpc/kernel/rtas-proc.c
@@ -257,7 +257,7 @@ static int __init proc_rtas_init(void)
{
struct proc_dir_entry *entry;
- if (_machine != PLATFORM_PSERIES && _machine != PLATFORM_PSERIES_LPAR)
+ if (!machine_is(pseries))
return 1;
rtas_node = of_find_node_by_name(NULL, "rtas");
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index b5b2add7ad1..06636c927a7 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -25,6 +25,7 @@
#include <asm/hvcall.h>
#include <asm/semaphore.h>
#include <asm/machdep.h>
+#include <asm/firmware.h>
#include <asm/page.h>
#include <asm/param.h>
#include <asm/system.h>
@@ -32,6 +33,7 @@
#include <asm/uaccess.h>
#include <asm/lmb.h>
#include <asm/udbg.h>
+#include <asm/syscalls.h>
struct rtas_t rtas = {
.lock = SPIN_LOCK_UNLOCKED
@@ -591,7 +593,7 @@ static void rtas_percpu_suspend_me(void *info)
data->waiting = 0;
data->args->args[data->args->nargs] =
rtas_call(ibm_suspend_me_token, 0, 1, NULL);
- for_each_cpu(i)
+ for_each_possible_cpu(i)
plpar_hcall_norets(H_PROD,i);
} else {
data->waiting = -EBUSY;
@@ -624,7 +626,7 @@ static int rtas_ibm_suspend_me(struct rtas_args *args)
/* Prod each CPU. This won't hurt, and will wake
* anyone we successfully put to sleep with H_Join
*/
- for_each_cpu(i)
+ for_each_possible_cpu(i)
plpar_hcall_norets(H_PROD, i);
return data.waiting;
@@ -767,7 +769,7 @@ void __init rtas_initialize(void)
* the stop-self token if any
*/
#ifdef CONFIG_PPC64
- if (_machine == PLATFORM_PSERIES_LPAR) {
+ if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) {
rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
ibm_suspend_me_token = rtas_token("ibm,suspend-me");
}
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index c1d62bf11f2..c607f3b9ca1 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -9,6 +9,9 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+
+#undef DEBUG
+
#include <linux/config.h>
#include <linux/module.h>
#include <linux/string.h>
@@ -41,6 +44,7 @@
#include <asm/time.h>
#include <asm/cputable.h>
#include <asm/sections.h>
+#include <asm/firmware.h>
#include <asm/btext.h>
#include <asm/nvram.h>
#include <asm/setup.h>
@@ -56,8 +60,6 @@
#include "setup.h"
-#undef DEBUG
-
#ifdef DEBUG
#include <asm/udbg.h>
#define DBG(fmt...) udbg_printf(fmt)
@@ -65,10 +67,12 @@
#define DBG(fmt...)
#endif
-#ifdef CONFIG_PPC_MULTIPLATFORM
-int _machine = 0;
-EXPORT_SYMBOL(_machine);
-#endif
+/* The main machine-dep calls structure
+ */
+struct machdep_calls ppc_md;
+EXPORT_SYMBOL(ppc_md);
+struct machdep_calls *machine_id;
+EXPORT_SYMBOL(machine_id);
unsigned long klimit = (unsigned long) _end;
@@ -168,7 +172,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
bogosum/(500000/HZ), bogosum/(5000/HZ) % 100);
#endif /* CONFIG_SMP && CONFIG_PPC32 */
seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
-
+ if (ppc_md.name)
+ seq_printf(m, "platform\t: %s\n", ppc_md.name);
if (ppc_md.show_cpuinfo != NULL)
ppc_md.show_cpuinfo(m);
@@ -352,12 +357,13 @@ void __init check_for_initrd(void)
* must be called before using this.
*
* While we're here, we may as well set the "physical" cpu ids in the paca.
+ *
+ * NOTE: This must match the parsing done in early_init_dt_scan_cpus.
*/
void __init smp_setup_cpu_maps(void)
{
struct device_node *dn = NULL;
int cpu = 0;
- int swap_cpuid = 0;
while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
int *intserv;
@@ -376,30 +382,17 @@ void __init smp_setup_cpu_maps(void)
for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
cpu_set(cpu, cpu_present_map);
set_hard_smp_processor_id(cpu, intserv[j]);
-
- if (intserv[j] == boot_cpuid_phys)
- swap_cpuid = cpu;
cpu_set(cpu, cpu_possible_map);
cpu++;
}
}
- /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that
- * boot cpu is logical 0.
- */
- if (boot_cpuid_phys != get_hard_smp_processor_id(0)) {
- u32 tmp;
- tmp = get_hard_smp_processor_id(0);
- set_hard_smp_processor_id(0, boot_cpuid_phys);
- set_hard_smp_processor_id(swap_cpuid, tmp);
- }
-
#ifdef CONFIG_PPC64
/*
* On pSeries LPAR, we need to know how many cpus
* could possibly be added to this partition.
*/
- if (_machine == PLATFORM_PSERIES_LPAR &&
+ if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR) &&
(dn = of_find_node_by_path("/rtas"))) {
int num_addr_cell, num_size_cell, maxcpus;
unsigned int *ireg;
@@ -438,7 +431,7 @@ void __init smp_setup_cpu_maps(void)
/*
* Do the sibling map; assume only two threads per processor.
*/
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
cpu_set(cpu, cpu_sibling_map[cpu]);
if (cpu_has_feature(CPU_FTR_SMT))
cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
@@ -468,3 +461,34 @@ static int __init early_xmon(char *p)
}
early_param("xmon", early_xmon);
#endif
+
+void probe_machine(void)
+{
+ extern struct machdep_calls __machine_desc_start;
+ extern struct machdep_calls __machine_desc_end;
+
+ /*
+ * Iterate all ppc_md structures until we find the proper
+ * one for the current machine type
+ */
+ DBG("Probing machine type ...\n");
+
+ for (machine_id = &__machine_desc_start;
+ machine_id < &__machine_desc_end;
+ machine_id++) {
+ DBG(" %s ...", machine_id->name);
+ memcpy(&ppc_md, machine_id, sizeof(struct machdep_calls));
+ if (ppc_md.probe()) {
+ DBG(" match !\n");
+ break;
+ }
+ DBG("\n");
+ }
+ /* What can we do if we didn't find ? */
+ if (machine_id >= &__machine_desc_end) {
+ DBG("No suitable machine found !\n");
+ for (;;);
+ }
+
+ printk(KERN_INFO "Using %s machine description\n", ppc_md.name);
+}
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index dc2770df25b..a72bf5dceee 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -53,9 +53,6 @@
extern void platform_init(void);
extern void bootx_init(unsigned long r4, unsigned long phys);
-extern void ppc6xx_idle(void);
-extern void power4_idle(void);
-
boot_infos_t *boot_infos;
struct ide_machdep_calls ppc_ide_md;
@@ -70,10 +67,6 @@ unsigned int DMA_MODE_WRITE;
int have_of = 1;
#ifdef CONFIG_PPC_MULTIPLATFORM
-extern void prep_init(void);
-extern void pmac_init(void);
-extern void chrp_init(void);
-
dev_t boot_dev;
#endif /* CONFIG_PPC_MULTIPLATFORM */
@@ -85,9 +78,6 @@ unsigned long SYSRQ_KEY = 0x54;
unsigned long vgacon_remap_base;
#endif
-struct machdep_calls ppc_md;
-EXPORT_SYMBOL(ppc_md);
-
/*
* These are used in binfmt_elf.c to put aux entries on the stack
* for each elf executable being started.
@@ -111,7 +101,7 @@ unsigned long __init early_init(unsigned long dt_ptr)
/* First zero the BSS -- use memset_io, some platforms don't have
* caches on yet */
- memset_io(PTRRELOC(&__bss_start), 0, _end - __bss_start);
+ memset_io((void __iomem *)PTRRELOC(&__bss_start), 0, _end - __bss_start);
/*
* Identify the CPU type and fix up code sections
@@ -123,48 +113,6 @@ unsigned long __init early_init(unsigned long dt_ptr)
return KERNELBASE + offset;
}
-#ifdef CONFIG_PPC_MULTIPLATFORM
-/*
- * The PPC_MULTIPLATFORM version of platform_init...
- */
-void __init platform_init(void)
-{
- /* if we didn't get any bootinfo telling us what we are... */
- if (_machine == 0) {
- /* prep boot loader tells us if we're prep or not */
- if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
- _machine = _MACH_prep;
- }
-
-#ifdef CONFIG_PPC_PREP
- /* not much more to do here, if prep */
- if (_machine == _MACH_prep) {
- prep_init();
- return;
- }
-#endif
-
-#ifdef CONFIG_ADB
- if (strstr(cmd_line, "adb_sync")) {
- extern int __adb_probe_sync;
- __adb_probe_sync = 1;
- }
-#endif /* CONFIG_ADB */
-
- switch (_machine) {
-#ifdef CONFIG_PPC_PMAC
- case _MACH_Pmac:
- pmac_init();
- break;
-#endif
-#ifdef CONFIG_PPC_CHRP
- case _MACH_chrp:
- chrp_init();
- break;
-#endif
- }
-}
-#endif
/*
* Find out what kind of machine we're on and save any data we need
@@ -190,11 +138,17 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys)
strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
#endif /* CONFIG_CMDLINE */
- /* Base init based on machine type */
+#ifdef CONFIG_PPC_MULTIPLATFORM
+ probe_machine();
+#else
+ /* Base init based on machine type. Obsoloete, please kill ! */
platform_init();
+#endif
#ifdef CONFIG_6xx
- ppc_md.power_save = ppc6xx_idle;
+ if (cpu_has_feature(CPU_FTR_CAN_DOZE) ||
+ cpu_has_feature(CPU_FTR_CAN_NAP))
+ ppc_md.power_save = ppc6xx_idle;
#endif
if (ppc_md.progress)
@@ -272,7 +226,7 @@ int __init ppc_init(void)
if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
/* register CPU devices */
- for_each_cpu(i)
+ for_each_possible_cpu(i)
register_cpu(&cpu_devices[i], i, NULL);
/* call platform init */
@@ -352,12 +306,6 @@ void __init setup_arch(char **cmdline_p)
do_init_bootmem();
if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
-#ifdef CONFIG_PPC_OCP
- /* Initialize OCP device list */
- ocp_early_init();
- if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab);
-#endif
-
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
@@ -366,7 +314,4 @@ void __init setup_arch(char **cmdline_p)
if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
paging_init();
-
- /* this is for modules since _machine can be a define -- Cort */
- ppc_md.ppc_machine = _machine;
}
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 2f3fdad3559..59aa92cd6fa 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -73,7 +73,6 @@
int have_of = 1;
int boot_cpuid = 0;
-int boot_cpuid_phys = 0;
dev_t boot_dev;
u64 ppc64_pft_size;
@@ -96,11 +95,6 @@ int dcache_bsize;
int icache_bsize;
int ucache_bsize;
-/* The main machine-dep calls structure
- */
-struct machdep_calls ppc_md;
-EXPORT_SYMBOL(ppc_md);
-
#ifdef CONFIG_MAGIC_SYSRQ
unsigned long SYSRQ_KEY;
#endif /* CONFIG_MAGIC_SYSRQ */
@@ -161,32 +155,6 @@ early_param("smt-enabled", early_smt_enabled);
#define check_smt_enabled()
#endif /* CONFIG_SMP */
-extern struct machdep_calls pSeries_md;
-extern struct machdep_calls pmac_md;
-extern struct machdep_calls maple_md;
-extern struct machdep_calls cell_md;
-extern struct machdep_calls iseries_md;
-
-/* Ultimately, stuff them in an elf section like initcalls... */
-static struct machdep_calls __initdata *machines[] = {
-#ifdef CONFIG_PPC_PSERIES
- &pSeries_md,
-#endif /* CONFIG_PPC_PSERIES */
-#ifdef CONFIG_PPC_PMAC
- &pmac_md,
-#endif /* CONFIG_PPC_PMAC */
-#ifdef CONFIG_PPC_MAPLE
- &maple_md,
-#endif /* CONFIG_PPC_MAPLE */
-#ifdef CONFIG_PPC_CELL
- &cell_md,
-#endif
-#ifdef CONFIG_PPC_ISERIES
- &iseries_md,
-#endif
- NULL
-};
-
/*
* Early initialization entry point. This is called by head.S
* with MMU translation disabled. We rely on the "feature" of
@@ -208,13 +176,10 @@ static struct machdep_calls __initdata *machines[] = {
void __init early_setup(unsigned long dt_ptr)
{
- struct paca_struct *lpaca = get_paca();
- static struct machdep_calls **mach;
-
/* Enable early debugging if any specified (see udbg.h) */
udbg_early_init();
- DBG(" -> early_setup()\n");
+ DBG(" -> early_setup(), dt_ptr: 0x%lx\n", dt_ptr);
/*
* Do early initializations using the flattened device
@@ -223,22 +188,16 @@ void __init early_setup(unsigned long dt_ptr)
*/
early_init_devtree(__va(dt_ptr));
- /*
- * Iterate all ppc_md structures until we find the proper
- * one for the current machine type
- */
- DBG("Probing machine type for platform %x...\n", _machine);
+ /* Now we know the logical id of our boot cpu, setup the paca. */
+ setup_boot_paca();
- for (mach = machines; *mach; mach++) {
- if ((*mach)->probe(_machine))
- break;
- }
- /* What can we do if we didn't find ? */
- if (*mach == NULL) {
- DBG("No suitable machine found !\n");
- for (;;);
- }
- ppc_md = **mach;
+ /* Fix up paca fields required for the boot cpu */
+ get_paca()->cpu_start = 1;
+ get_paca()->stab_real = __pa((u64)&initial_stab);
+ get_paca()->stab_addr = (u64)&initial_stab;
+
+ /* Probe the machine type */
+ probe_machine();
#ifdef CONFIG_CRASH_DUMP
kdump_setup();
@@ -260,7 +219,7 @@ void __init early_setup(unsigned long dt_ptr)
if (cpu_has_feature(CPU_FTR_SLB))
slb_initialize();
else
- stab_initialize(lpaca->stab_real);
+ stab_initialize(get_paca()->stab_real);
}
DBG(" <- early_setup()\n");
@@ -340,7 +299,7 @@ static void __init initialize_cache_info(void)
const char *dc, *ic;
/* Then read cache informations */
- if (_machine == PLATFORM_POWERMAC) {
+ if (machine_is(powermac)) {
dc = "d-cache-block-size";
ic = "i-cache-block-size";
} else {
@@ -484,7 +443,6 @@ void __init setup_system(void)
printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size);
printk("ppc64_interrupt_controller = 0x%ld\n",
ppc64_interrupt_controller);
- printk("platform = 0x%x\n", _machine);
printk("physicalMemorySize = 0x%lx\n", lmb_phys_mem_size());
printk("ppc64_caches.dcache_line_size = 0x%x\n",
ppc64_caches.dline_size);
@@ -516,7 +474,7 @@ static void __init irqstack_early_init(void)
* interrupt stacks must be under 256MB, we cannot afford to take
* SLB misses on them.
*/
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
softirq_ctx[i] = (struct thread_info *)
__va(lmb_alloc_base(THREAD_SIZE,
THREAD_SIZE, 0x10000000));
@@ -549,7 +507,7 @@ static void __init emergency_stack_init(void)
*/
limit = min(0x10000000UL, lmb.rmo_size);
- for_each_cpu(i)
+ for_each_possible_cpu(i)
paca[i].emergency_sp =
__va(lmb_alloc_base(HW_PAGE_SIZE, 128, limit)) + HW_PAGE_SIZE;
}
@@ -579,7 +537,8 @@ void __init setup_arch(char **cmdline_p)
panic_timeout = 180;
if (ppc_md.panic)
- notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &ppc64_panic_block);
init_mm.start_code = PAGE_OFFSET;
init_mm.end_code = (unsigned long) _etext;
@@ -601,12 +560,6 @@ void __init setup_arch(char **cmdline_p)
ppc_md.setup_arch();
- /* Use the default idle loop if the platform hasn't provided one. */
- if (NULL == ppc_md.idle_loop) {
- ppc_md.idle_loop = default_idle;
- printk(KERN_INFO "Using default idle loop\n");
- }
-
paging_init();
ppc64_boot_msg(0x15, "Setup Done");
}
@@ -671,7 +624,7 @@ void __init setup_per_cpu_areas(void)
size = PERCPU_ENOUGH_ROOM;
#endif
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size);
if (!ptr)
panic("Cannot allocate cpu data for CPU %d\n", i);
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index d7a4e814974..01e3c08cb55 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -42,6 +42,7 @@
#include <asm/uaccess.h>
#include <asm/cacheflush.h>
+#include <asm/syscalls.h>
#include <asm/sigcontext.h>
#include <asm/vdso.h>
#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 47f910380a6..27f65b95184 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -33,6 +33,7 @@
#include <asm/pgtable.h>
#include <asm/unistd.h>
#include <asm/cacheflush.h>
+#include <asm/syscalls.h>
#include <asm/vdso.h>
#define DEBUG_SIG 0
@@ -211,7 +212,7 @@ static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs
/* Default to using normal stack */
newsp = regs->gpr[1];
- if (ka->sa.sa_flags & SA_ONSTACK) {
+ if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) {
if (! on_sig_stack(regs->gpr[1]))
newsp = (current->sas_ss_sp + current->sas_ss_size);
}
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 805eaedbc30..530f7dba0bd 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -362,7 +362,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
smp_space_timers(max_cpus);
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
if (cpu != boot_cpuid)
smp_create_idle(cpu);
}
diff --git a/arch/ppc/kernel/swsusp.S b/arch/powerpc/kernel/swsusp_32.S
index 69773cc1a85..69773cc1a85 100644
--- a/arch/ppc/kernel/swsusp.S
+++ b/arch/powerpc/kernel/swsusp_32.S
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index cd75ab2908f..ec274e68881 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -24,7 +24,6 @@
#include <linux/resource.h>
#include <linux/times.h>
#include <linux/utsname.h>
-#include <linux/timex.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
@@ -161,78 +160,6 @@ asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2)
return sys_sysfs((int)option, arg1, arg2);
}
-/* Handle adjtimex compatibility. */
-struct timex32 {
- u32 modes;
- s32 offset, freq, maxerror, esterror;
- s32 status, constant, precision, tolerance;
- struct compat_timeval time;
- s32 tick;
- s32 ppsfreq, jitter, shift, stabil;
- s32 jitcnt, calcnt, errcnt, stbcnt;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
-};
-
-extern int do_adjtimex(struct timex *);
-
-asmlinkage long compat_sys_adjtimex(struct timex32 __user *utp)
-{
- struct timex txc;
- int ret;
-
- memset(&txc, 0, sizeof(struct timex));
-
- if(get_user(txc.modes, &utp->modes) ||
- __get_user(txc.offset, &utp->offset) ||
- __get_user(txc.freq, &utp->freq) ||
- __get_user(txc.maxerror, &utp->maxerror) ||
- __get_user(txc.esterror, &utp->esterror) ||
- __get_user(txc.status, &utp->status) ||
- __get_user(txc.constant, &utp->constant) ||
- __get_user(txc.precision, &utp->precision) ||
- __get_user(txc.tolerance, &utp->tolerance) ||
- __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __get_user(txc.tick, &utp->tick) ||
- __get_user(txc.ppsfreq, &utp->ppsfreq) ||
- __get_user(txc.jitter, &utp->jitter) ||
- __get_user(txc.shift, &utp->shift) ||
- __get_user(txc.stabil, &utp->stabil) ||
- __get_user(txc.jitcnt, &utp->jitcnt) ||
- __get_user(txc.calcnt, &utp->calcnt) ||
- __get_user(txc.errcnt, &utp->errcnt) ||
- __get_user(txc.stbcnt, &utp->stbcnt))
- return -EFAULT;
-
- ret = do_adjtimex(&txc);
-
- if(put_user(txc.modes, &utp->modes) ||
- __put_user(txc.offset, &utp->offset) ||
- __put_user(txc.freq, &utp->freq) ||
- __put_user(txc.maxerror, &utp->maxerror) ||
- __put_user(txc.esterror, &utp->esterror) ||
- __put_user(txc.status, &utp->status) ||
- __put_user(txc.constant, &utp->constant) ||
- __put_user(txc.precision, &utp->precision) ||
- __put_user(txc.tolerance, &utp->tolerance) ||
- __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __put_user(txc.tick, &utp->tick) ||
- __put_user(txc.ppsfreq, &utp->ppsfreq) ||
- __put_user(txc.jitter, &utp->jitter) ||
- __put_user(txc.shift, &utp->shift) ||
- __put_user(txc.stabil, &utp->stabil) ||
- __put_user(txc.jitcnt, &utp->jitcnt) ||
- __put_user(txc.calcnt, &utp->calcnt) ||
- __put_user(txc.errcnt, &utp->errcnt) ||
- __put_user(txc.stbcnt, &utp->stbcnt))
- ret = -EFAULT;
-
- return ret;
-}
-
asmlinkage long compat_sys_pause(void)
{
current->state = TASK_INTERRUPTIBLE;
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
index ad895c99813..9b69d99a910 100644
--- a/arch/powerpc/kernel/syscalls.c
+++ b/arch/powerpc/kernel/syscalls.c
@@ -40,6 +40,7 @@
#include <asm/uaccess.h>
#include <asm/ipc.h>
#include <asm/semaphore.h>
+#include <asm/syscalls.h>
#include <asm/time.h>
#include <asm/unistd.h>
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 0f0c3a9ae2e..73560ef6f80 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -65,20 +65,20 @@ static int __init smt_setup(void)
unsigned int cpu;
if (!cpu_has_feature(CPU_FTR_SMT))
- return 1;
+ return -ENODEV;
options = find_path_device("/options");
if (!options)
- return 1;
+ return -ENODEV;
val = (unsigned int *)get_property(options, "ibm,smt-snooze-delay",
NULL);
if (!smt_snooze_cmdline && val) {
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
per_cpu(smt_snooze_delay, cpu) = *val;
}
- return 1;
+ return 0;
}
__initcall(smt_setup);
@@ -93,7 +93,7 @@ static int __init setup_smt_snooze_delay(char *str)
smt_snooze_cmdline = 1;
if (get_option(&str, &snooze)) {
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
per_cpu(smt_snooze_delay, cpu) = snooze;
}
@@ -347,7 +347,7 @@ static int __init topology_init(void)
register_cpu_notifier(&sysfs_cpu_nb);
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct cpu *c = &per_cpu(cpu_devices, cpu);
#ifdef CONFIG_NUMA
diff --git a/arch/ppc/kernel/temp.c b/arch/powerpc/kernel/tau_6xx.c
index 26bd8ea35a4..26bd8ea35a4 100644
--- a/arch/ppc/kernel/temp.c
+++ b/arch/powerpc/kernel/tau_6xx.c
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 4a27218a086..24e3ad756de 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -261,7 +261,7 @@ void snapshot_timebases(void)
if (!cpu_has_feature(CPU_FTR_PURR))
return;
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock);
on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1);
}
@@ -751,7 +751,7 @@ void __init smp_space_timers(unsigned int max_cpus)
* systems works better if the two threads' timebase interrupts
* are staggered by half a jiffy with respect to each other.
*/
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
if (i == boot_cpuid)
continue;
if (i == (boot_cpuid ^ 1))
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 98660aedeeb..4cbde211eb6 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -74,19 +74,19 @@ EXPORT_SYMBOL(__debugger_dabr_match);
EXPORT_SYMBOL(__debugger_fault_handler);
#endif
-struct notifier_block *powerpc_die_chain;
-static DEFINE_SPINLOCK(die_notifier_lock);
+ATOMIC_NOTIFIER_HEAD(powerpc_die_chain);
int register_die_notifier(struct notifier_block *nb)
{
- int err = 0;
- unsigned long flags;
+ return atomic_notifier_chain_register(&powerpc_die_chain, nb);
+}
+EXPORT_SYMBOL(register_die_notifier);
- spin_lock_irqsave(&die_notifier_lock, flags);
- err = notifier_chain_register(&powerpc_die_chain, nb);
- spin_unlock_irqrestore(&die_notifier_lock, flags);
- return err;
+int unregister_die_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&powerpc_die_chain, nb);
}
+EXPORT_SYMBOL(unregister_die_notifier);
/*
* Trap & Exception support
@@ -97,7 +97,6 @@ static DEFINE_SPINLOCK(die_lock);
int die(const char *str, struct pt_regs *regs, long err)
{
static int die_counter, crash_dump_start = 0;
- int nl = 0;
if (debugger(regs))
return 1;
@@ -106,7 +105,7 @@ int die(const char *str, struct pt_regs *regs, long err)
spin_lock_irq(&die_lock);
bust_spinlocks(1);
#ifdef CONFIG_PMAC_BACKLIGHT
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
set_backlight_enable(1);
set_backlight_level(BACKLIGHT_MAX);
}
@@ -114,46 +113,18 @@ int die(const char *str, struct pt_regs *regs, long err)
printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
#ifdef CONFIG_PREEMPT
printk("PREEMPT ");
- nl = 1;
#endif
#ifdef CONFIG_SMP
printk("SMP NR_CPUS=%d ", NR_CPUS);
- nl = 1;
#endif
#ifdef CONFIG_DEBUG_PAGEALLOC
printk("DEBUG_PAGEALLOC ");
- nl = 1;
#endif
#ifdef CONFIG_NUMA
printk("NUMA ");
- nl = 1;
#endif
-#ifdef CONFIG_PPC64
- switch (_machine) {
- case PLATFORM_PSERIES:
- printk("PSERIES ");
- nl = 1;
- break;
- case PLATFORM_PSERIES_LPAR:
- printk("PSERIES LPAR ");
- nl = 1;
- break;
- case PLATFORM_ISERIES_LPAR:
- printk("ISERIES LPAR ");
- nl = 1;
- break;
- case PLATFORM_POWERMAC:
- printk("POWERMAC ");
- nl = 1;
- break;
- case PLATFORM_CELL:
- printk("CELL ");
- nl = 1;
- break;
- }
-#endif
- if (nl)
- printk("\n");
+ printk("%s\n", ppc_md.name ? "" : ppc_md.name);
+
print_modules();
show_regs(regs);
bust_spinlocks(0);
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index ec837036842..573afb68d69 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -33,6 +33,7 @@
#include <asm/machdep.h>
#include <asm/cputable.h>
#include <asm/sections.h>
+#include <asm/firmware.h>
#include <asm/vdso.h>
#include <asm/vdso_datapage.h>
@@ -667,7 +668,13 @@ void __init vdso_init(void)
vdso_data->version.major = SYSTEMCFG_MAJOR;
vdso_data->version.minor = SYSTEMCFG_MINOR;
vdso_data->processor = mfspr(SPRN_PVR);
- vdso_data->platform = _machine;
+ /*
+ * Fake the old platform number for pSeries and iSeries and add
+ * in LPAR bit if necessary
+ */
+ vdso_data->platform = machine_is(iseries) ? 0x200 : 0x100;
+ if (firmware_has_feature(FW_FEATURE_LPAR))
+ vdso_data->platform |= 1;
vdso_data->physicalMemorySize = lmb_phys_mem_size();
vdso_data->dcache_size = ppc64_caches.dsize;
vdso_data->dcache_line_size = ppc64_caches.dline_size;
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 7fa7b15fd8e..fe79c2584cb 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -1,9 +1,11 @@
#include <linux/config.h>
#ifdef CONFIG_PPC64
#include <asm/page.h>
+#define PROVIDE32(x) PROVIDE(__unused__##x)
#else
#define PAGE_SIZE 4096
#define KERNELBASE CONFIG_KERNEL_START
+#define PROVIDE32(x) PROVIDE(x)
#endif
#include <asm-generic/vmlinux.lds.h>
@@ -18,43 +20,42 @@ jiffies = jiffies_64 + 4;
#endif
SECTIONS
{
- /* Sections to be discarded. */
- /DISCARD/ : {
- *(.exitcall.exit)
- *(.exit.data)
- }
-
- . = KERNELBASE;
-
- /* Read-only sections, merged into text segment: */
- .text : {
- *(.text .text.*)
- SCHED_TEXT
- LOCK_TEXT
- KPROBES_TEXT
- *(.fixup)
-#ifdef CONFIG_PPC32
- *(.got1)
- __got2_start = .;
- *(.got2)
- __got2_end = .;
-#else
- . = ALIGN(PAGE_SIZE);
- _etext = .;
-#endif
- }
-#ifdef CONFIG_PPC32
- _etext = .;
- PROVIDE (etext = .);
+ /* Sections to be discarded. */
+ /DISCARD/ : {
+ *(.exitcall.exit)
+ *(.exit.data)
+ }
- RODATA
- .fini : { *(.fini) } =0
- .ctors : { *(.ctors) }
- .dtors : { *(.dtors) }
+ . = KERNELBASE;
- .fixup : { *(.fixup) }
-#endif
+/*
+ * Text, read only data and other permanent read-only sections
+ */
+
+ /* Text and gots */
+ .text : {
+ *(.text .text.*)
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ *(.fixup)
+#ifdef CONFIG_PPC32
+ *(.got1)
+ __got2_start = .;
+ *(.got2)
+ __got2_end = .;
+#endif /* CONFIG_PPC32 */
+
+ . = ALIGN(PAGE_SIZE);
+ _etext = .;
+ PROVIDE32 (etext = .);
+ }
+
+ /* Read-only data */
+ RODATA
+
+ /* Exception & bug tables */
__ex_table : {
__start___ex_table = .;
*(__ex_table)
@@ -67,192 +68,172 @@ SECTIONS
__stop___bug_table = .;
}
-#ifdef CONFIG_PPC64
+/*
+ * Init sections discarded at runtime
+ */
+ . = ALIGN(PAGE_SIZE);
+ __init_begin = .;
+
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ }
+
+ /* .exit.text is discarded at runtime, not link time,
+ * to deal with references from __bug_table
+ */
+ .exit.text : { *(.exit.text) }
+
+ .init.data : {
+ *(.init.data);
+ __vtop_table_begin = .;
+ *(.vtop_fixup);
+ __vtop_table_end = .;
+ __ptov_table_begin = .;
+ *(.ptov_fixup);
+ __ptov_table_end = .;
+ }
+
+ . = ALIGN(16);
+ .init.setup : {
+ __setup_start = .;
+ *(.init.setup)
+ __setup_end = .;
+ }
+
+ .initcall.init : {
+ __initcall_start = .;
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ __initcall_end = .;
+ }
+
+ .con_initcall.init : {
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+ }
+
+ SECURITY_INIT
+
+ . = ALIGN(8);
__ftr_fixup : {
__start___ftr_fixup = .;
*(__ftr_fixup)
__stop___ftr_fixup = .;
}
- RODATA
-#endif
+ . = ALIGN(PAGE_SIZE);
+ .init.ramfs : {
+ __initramfs_start = .;
+ *(.init.ramfs)
+ __initramfs_end = .;
+ }
#ifdef CONFIG_PPC32
- /* Read-write section, merged into data segment: */
- . = ALIGN(PAGE_SIZE);
- _sdata = .;
- .data :
- {
- *(.data)
- *(.data1)
- *(.sdata)
- *(.sdata2)
- *(.got.plt) *(.got)
- *(.dynamic)
- CONSTRUCTORS
- }
-
- . = ALIGN(PAGE_SIZE);
- __nosave_begin = .;
- .data_nosave : { *(.data.nosave) }
- . = ALIGN(PAGE_SIZE);
- __nosave_end = .;
-
- . = ALIGN(32);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
- _edata = .;
- PROVIDE (edata = .);
-
- . = ALIGN(8192);
- .data.init_task : { *(.data.init_task) }
+ . = ALIGN(32);
+#else
+ . = ALIGN(128);
#endif
+ .data.percpu : {
+ __per_cpu_start = .;
+ *(.data.percpu)
+ __per_cpu_end = .;
+ }
- /* will be freed after init */
- . = ALIGN(PAGE_SIZE);
- __init_begin = .;
- .init.text : {
- _sinittext = .;
- *(.init.text)
- _einittext = .;
- }
-#ifdef CONFIG_PPC32
- /* .exit.text is discarded at runtime, not link time,
- to deal with references from __bug_table */
- .exit.text : { *(.exit.text) }
-#endif
- .init.data : {
- *(.init.data);
- __vtop_table_begin = .;
- *(.vtop_fixup);
- __vtop_table_end = .;
- __ptov_table_begin = .;
- *(.ptov_fixup);
- __ptov_table_end = .;
- }
-
- . = ALIGN(16);
- .init.setup : {
- __setup_start = .;
- *(.init.setup)
- __setup_end = .;
- }
-
- .initcall.init : {
- __initcall_start = .;
- *(.initcall1.init)
- *(.initcall2.init)
- *(.initcall3.init)
- *(.initcall4.init)
- *(.initcall5.init)
- *(.initcall6.init)
- *(.initcall7.init)
- __initcall_end = .;
- }
-
- .con_initcall.init : {
- __con_initcall_start = .;
- *(.con_initcall.init)
- __con_initcall_end = .;
- }
-
- SECURITY_INIT
+ . = ALIGN(8);
+ .machine.desc : {
+ __machine_desc_start = . ;
+ *(.machine.desc)
+ __machine_desc_end = . ;
+ }
+
+ /* freed after init ends here */
+ . = ALIGN(PAGE_SIZE);
+ __init_end = .;
+
+/*
+ * And now the various read/write data
+ */
+
+ . = ALIGN(PAGE_SIZE);
+ _sdata = .;
#ifdef CONFIG_PPC32
- __start___ftr_fixup = .;
- __ftr_fixup : { *(__ftr_fixup) }
- __stop___ftr_fixup = .;
+ .data :
+ {
+ *(.data)
+ *(.sdata)
+ *(.got.plt) *(.got)
+ }
#else
- . = ALIGN(PAGE_SIZE);
- .init.ramfs : {
- __initramfs_start = .;
- *(.init.ramfs)
- __initramfs_end = .;
- }
-#endif
+ .data : {
+ *(.data .data.rel* .toc1)
+ *(.branch_lt)
+ }
-#ifdef CONFIG_PPC32
- . = ALIGN(32);
+ .opd : {
+ *(.opd)
+ }
+
+ .got : {
+ __toc_start = .;
+ *(.got)
+ *(.toc)
+ }
#endif
- .data.percpu : {
- __per_cpu_start = .;
- *(.data.percpu)
- __per_cpu_end = .;
- }
- . = ALIGN(PAGE_SIZE);
-#ifdef CONFIG_PPC64
- . = ALIGN(16384);
- __init_end = .;
- /* freed after init ends here */
-
- /* Read/write sections */
- . = ALIGN(PAGE_SIZE);
- . = ALIGN(16384);
- _sdata = .;
- /* The initial task and kernel stack */
- .data.init_task : {
- *(.data.init_task)
- }
-
- . = ALIGN(PAGE_SIZE);
- .data.page_aligned : {
- *(.data.page_aligned)
- }
-
- .data.cacheline_aligned : {
- *(.data.cacheline_aligned)
- }
-
- .data : {
- *(.data .data.rel* .toc1)
- *(.branch_lt)
- }
-
- .opd : {
- *(.opd)
- }
-
- .got : {
- __toc_start = .;
- *(.got)
- *(.toc)
- . = ALIGN(PAGE_SIZE);
- _edata = .;
- }
-
- . = ALIGN(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
+ _edata = .;
+ PROVIDE32 (edata = .);
+
+ /* The initial task and kernel stack */
+#ifdef CONFIG_PPC32
+ . = ALIGN(8192);
#else
- __initramfs_start = .;
- .init.ramfs : {
- *(.init.ramfs)
- }
- __initramfs_end = .;
+ . = ALIGN(16384);
+#endif
+ .data.init_task : {
+ *(.data.init_task)
+ }
- . = ALIGN(4096);
- __init_end = .;
+ . = ALIGN(PAGE_SIZE);
+ .data.page_aligned : {
+ *(.data.page_aligned)
+ }
- . = ALIGN(4096);
- _sextratext = .;
- _eextratext = .;
+ .data.cacheline_aligned : {
+ *(.data.cacheline_aligned)
+ }
- __bss_start = .;
-#endif
+ . = ALIGN(PAGE_SIZE);
+ __data_nosave : {
+ __nosave_begin = .;
+ *(.data.nosave)
+ . = ALIGN(PAGE_SIZE);
+ __nosave_end = .;
+ }
- .bss : {
- __bss_start = .;
- *(.sbss) *(.scommon)
- *(.dynbss)
- *(.bss)
- *(COMMON)
- __bss_stop = .;
- }
+/*
+ * And finally the bss
+ */
+
+ .bss : {
+ __bss_start = .;
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ __bss_stop = .;
+ }
-#ifdef CONFIG_PPC64
- . = ALIGN(PAGE_SIZE);
-#endif
- _end = . ;
-#ifdef CONFIG_PPC32
- PROVIDE (end = .);
-#endif
+ . = ALIGN(PAGE_SIZE);
+ _end = . ;
+ PROVIDE32 (end = .);
}
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 666c2aa5501..c251d993661 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -18,7 +18,7 @@ extern char system_call_common[];
#ifdef CONFIG_PPC64
/* Bits in SRR1 that are copied from MSR */
-#define MSR_MASK 0xffffffff87c0ffff
+#define MSR_MASK 0xffffffff87c0ffffUL
#else
#define MSR_MASK 0x87c0ffff
#endif
diff --git a/arch/powerpc/lib/strcase.c b/arch/powerpc/lib/strcase.c
index 36b521091bb..f8ec1eba3fd 100644
--- a/arch/powerpc/lib/strcase.c
+++ b/arch/powerpc/lib/strcase.c
@@ -1,4 +1,6 @@
+#include <linux/types.h>
#include <linux/ctype.h>
+#include <linux/string.h>
int strcasecmp(const char *s1, const char *s2)
{
@@ -11,7 +13,7 @@ int strcasecmp(const char *s1, const char *s2)
return c1 - c2;
}
-int strncasecmp(const char *s1, const char *s2, int n)
+int strncasecmp(const char *s1, const char *s2, size_t n)
{
int c1, c2;
diff --git a/arch/ppc/math-emu/Makefile b/arch/powerpc/math-emu/Makefile
index 754143e8936..754143e8936 100644
--- a/arch/ppc/math-emu/Makefile
+++ b/arch/powerpc/math-emu/Makefile
diff --git a/arch/ppc/math-emu/double.h b/arch/powerpc/math-emu/double.h
index ffba8b67f05..ffba8b67f05 100644
--- a/arch/ppc/math-emu/double.h
+++ b/arch/powerpc/math-emu/double.h
diff --git a/arch/ppc/math-emu/fabs.c b/arch/powerpc/math-emu/fabs.c
index 41f0617f3d3..41f0617f3d3 100644
--- a/arch/ppc/math-emu/fabs.c
+++ b/arch/powerpc/math-emu/fabs.c
diff --git a/arch/ppc/math-emu/fadd.c b/arch/powerpc/math-emu/fadd.c
index fc8836488b6..fc8836488b6 100644
--- a/arch/ppc/math-emu/fadd.c
+++ b/arch/powerpc/math-emu/fadd.c
diff --git a/arch/ppc/math-emu/fadds.c b/arch/powerpc/math-emu/fadds.c
index 93025b6c8f3..93025b6c8f3 100644
--- a/arch/ppc/math-emu/fadds.c
+++ b/arch/powerpc/math-emu/fadds.c
diff --git a/arch/ppc/math-emu/fcmpo.c b/arch/powerpc/math-emu/fcmpo.c
index 4efac394b4c..4efac394b4c 100644
--- a/arch/ppc/math-emu/fcmpo.c
+++ b/arch/powerpc/math-emu/fcmpo.c
diff --git a/arch/ppc/math-emu/fcmpu.c b/arch/powerpc/math-emu/fcmpu.c
index b7e33176e61..b7e33176e61 100644
--- a/arch/ppc/math-emu/fcmpu.c
+++ b/arch/powerpc/math-emu/fcmpu.c
diff --git a/arch/ppc/math-emu/fctiw.c b/arch/powerpc/math-emu/fctiw.c
index 3b3c98b840c..3b3c98b840c 100644
--- a/arch/ppc/math-emu/fctiw.c
+++ b/arch/powerpc/math-emu/fctiw.c
diff --git a/arch/ppc/math-emu/fctiwz.c b/arch/powerpc/math-emu/fctiwz.c
index 7717eb6fcfb..7717eb6fcfb 100644
--- a/arch/ppc/math-emu/fctiwz.c
+++ b/arch/powerpc/math-emu/fctiwz.c
diff --git a/arch/ppc/math-emu/fdiv.c b/arch/powerpc/math-emu/fdiv.c
index f2fba825b2d..f2fba825b2d 100644
--- a/arch/ppc/math-emu/fdiv.c
+++ b/arch/powerpc/math-emu/fdiv.c
diff --git a/arch/ppc/math-emu/fdivs.c b/arch/powerpc/math-emu/fdivs.c
index b971196e317..b971196e317 100644
--- a/arch/ppc/math-emu/fdivs.c
+++ b/arch/powerpc/math-emu/fdivs.c
diff --git a/arch/ppc/math-emu/fmadd.c b/arch/powerpc/math-emu/fmadd.c
index 0a1dbce793e..0a1dbce793e 100644
--- a/arch/ppc/math-emu/fmadd.c
+++ b/arch/powerpc/math-emu/fmadd.c
diff --git a/arch/ppc/math-emu/fmadds.c b/arch/powerpc/math-emu/fmadds.c
index 0f70bba9445..0f70bba9445 100644
--- a/arch/ppc/math-emu/fmadds.c
+++ b/arch/powerpc/math-emu/fmadds.c
diff --git a/arch/ppc/math-emu/fmr.c b/arch/powerpc/math-emu/fmr.c
index 28df700c0c7..28df700c0c7 100644
--- a/arch/ppc/math-emu/fmr.c
+++ b/arch/powerpc/math-emu/fmr.c
diff --git a/arch/ppc/math-emu/fmsub.c b/arch/powerpc/math-emu/fmsub.c
index 203fd48a6fe..203fd48a6fe 100644
--- a/arch/ppc/math-emu/fmsub.c
+++ b/arch/powerpc/math-emu/fmsub.c
diff --git a/arch/ppc/math-emu/fmsubs.c b/arch/powerpc/math-emu/fmsubs.c
index 8ce68624c18..8ce68624c18 100644
--- a/arch/ppc/math-emu/fmsubs.c
+++ b/arch/powerpc/math-emu/fmsubs.c
diff --git a/arch/ppc/math-emu/fmul.c b/arch/powerpc/math-emu/fmul.c
index 66c7e79aae2..66c7e79aae2 100644
--- a/arch/ppc/math-emu/fmul.c
+++ b/arch/powerpc/math-emu/fmul.c
diff --git a/arch/ppc/math-emu/fmuls.c b/arch/powerpc/math-emu/fmuls.c
index 26bc4278271..26bc4278271 100644
--- a/arch/ppc/math-emu/fmuls.c
+++ b/arch/powerpc/math-emu/fmuls.c
diff --git a/arch/ppc/math-emu/fnabs.c b/arch/powerpc/math-emu/fnabs.c
index c6b913d179e..c6b913d179e 100644
--- a/arch/ppc/math-emu/fnabs.c
+++ b/arch/powerpc/math-emu/fnabs.c
diff --git a/arch/ppc/math-emu/fneg.c b/arch/powerpc/math-emu/fneg.c
index fe9a98deff6..fe9a98deff6 100644
--- a/arch/ppc/math-emu/fneg.c
+++ b/arch/powerpc/math-emu/fneg.c
diff --git a/arch/ppc/math-emu/fnmadd.c b/arch/powerpc/math-emu/fnmadd.c
index 7f312276d92..7f312276d92 100644
--- a/arch/ppc/math-emu/fnmadd.c
+++ b/arch/powerpc/math-emu/fnmadd.c
diff --git a/arch/ppc/math-emu/fnmadds.c b/arch/powerpc/math-emu/fnmadds.c
index 65454c9c70b..65454c9c70b 100644
--- a/arch/ppc/math-emu/fnmadds.c
+++ b/arch/powerpc/math-emu/fnmadds.c
diff --git a/arch/ppc/math-emu/fnmsub.c b/arch/powerpc/math-emu/fnmsub.c
index f1ca7482b5f..f1ca7482b5f 100644
--- a/arch/ppc/math-emu/fnmsub.c
+++ b/arch/powerpc/math-emu/fnmsub.c
diff --git a/arch/ppc/math-emu/fnmsubs.c b/arch/powerpc/math-emu/fnmsubs.c
index 5c9a09a87dc..5c9a09a87dc 100644
--- a/arch/ppc/math-emu/fnmsubs.c
+++ b/arch/powerpc/math-emu/fnmsubs.c
diff --git a/arch/ppc/math-emu/fres.c b/arch/powerpc/math-emu/fres.c
index ec11e46d20a..ec11e46d20a 100644
--- a/arch/ppc/math-emu/fres.c
+++ b/arch/powerpc/math-emu/fres.c
diff --git a/arch/ppc/math-emu/frsp.c b/arch/powerpc/math-emu/frsp.c
index d879b2a3d0c..d879b2a3d0c 100644
--- a/arch/ppc/math-emu/frsp.c
+++ b/arch/powerpc/math-emu/frsp.c
diff --git a/arch/ppc/math-emu/frsqrte.c b/arch/powerpc/math-emu/frsqrte.c
index a11ae182985..a11ae182985 100644
--- a/arch/ppc/math-emu/frsqrte.c
+++ b/arch/powerpc/math-emu/frsqrte.c
diff --git a/arch/ppc/math-emu/fsel.c b/arch/powerpc/math-emu/fsel.c
index e36e6e72819..e36e6e72819 100644
--- a/arch/ppc/math-emu/fsel.c
+++ b/arch/powerpc/math-emu/fsel.c
diff --git a/arch/ppc/math-emu/fsqrt.c b/arch/powerpc/math-emu/fsqrt.c
index 6f8319f64a8..6f8319f64a8 100644
--- a/arch/ppc/math-emu/fsqrt.c
+++ b/arch/powerpc/math-emu/fsqrt.c
diff --git a/arch/ppc/math-emu/fsqrts.c b/arch/powerpc/math-emu/fsqrts.c
index 3b2b1cf55c1..3b2b1cf55c1 100644
--- a/arch/ppc/math-emu/fsqrts.c
+++ b/arch/powerpc/math-emu/fsqrts.c
diff --git a/arch/ppc/math-emu/fsub.c b/arch/powerpc/math-emu/fsub.c
index 956679042bb..956679042bb 100644
--- a/arch/ppc/math-emu/fsub.c
+++ b/arch/powerpc/math-emu/fsub.c
diff --git a/arch/ppc/math-emu/fsubs.c b/arch/powerpc/math-emu/fsubs.c
index 3428117dfe8..3428117dfe8 100644
--- a/arch/ppc/math-emu/fsubs.c
+++ b/arch/powerpc/math-emu/fsubs.c
diff --git a/arch/ppc/math-emu/lfd.c b/arch/powerpc/math-emu/lfd.c
index 7d38101c329..7d38101c329 100644
--- a/arch/ppc/math-emu/lfd.c
+++ b/arch/powerpc/math-emu/lfd.c
diff --git a/arch/ppc/math-emu/lfs.c b/arch/powerpc/math-emu/lfs.c
index c86dee3d765..c86dee3d765 100644
--- a/arch/ppc/math-emu/lfs.c
+++ b/arch/powerpc/math-emu/lfs.c
diff --git a/arch/ppc/math-emu/math.c b/arch/powerpc/math-emu/math.c
index 58915347276..58915347276 100644
--- a/arch/ppc/math-emu/math.c
+++ b/arch/powerpc/math-emu/math.c
diff --git a/arch/ppc/math-emu/mcrfs.c b/arch/powerpc/math-emu/mcrfs.c
index 106dd912914..106dd912914 100644
--- a/arch/ppc/math-emu/mcrfs.c
+++ b/arch/powerpc/math-emu/mcrfs.c
diff --git a/arch/ppc/math-emu/mffs.c b/arch/powerpc/math-emu/mffs.c
index f477c9170e7..f477c9170e7 100644
--- a/arch/ppc/math-emu/mffs.c
+++ b/arch/powerpc/math-emu/mffs.c
diff --git a/arch/ppc/math-emu/mtfsb0.c b/arch/powerpc/math-emu/mtfsb0.c
index 99bfd80f4af..99bfd80f4af 100644
--- a/arch/ppc/math-emu/mtfsb0.c
+++ b/arch/powerpc/math-emu/mtfsb0.c
diff --git a/arch/ppc/math-emu/mtfsb1.c b/arch/powerpc/math-emu/mtfsb1.c
index 3d9e7ed92d2..3d9e7ed92d2 100644
--- a/arch/ppc/math-emu/mtfsb1.c
+++ b/arch/powerpc/math-emu/mtfsb1.c
diff --git a/arch/ppc/math-emu/mtfsf.c b/arch/powerpc/math-emu/mtfsf.c
index d70cf714994..d70cf714994 100644
--- a/arch/ppc/math-emu/mtfsf.c
+++ b/arch/powerpc/math-emu/mtfsf.c
diff --git a/arch/ppc/math-emu/mtfsfi.c b/arch/powerpc/math-emu/mtfsfi.c
index 71df854baa7..71df854baa7 100644
--- a/arch/ppc/math-emu/mtfsfi.c
+++ b/arch/powerpc/math-emu/mtfsfi.c
diff --git a/arch/ppc/math-emu/op-1.h b/arch/powerpc/math-emu/op-1.h
index c92fa95f562..c92fa95f562 100644
--- a/arch/ppc/math-emu/op-1.h
+++ b/arch/powerpc/math-emu/op-1.h
diff --git a/arch/ppc/math-emu/op-2.h b/arch/powerpc/math-emu/op-2.h
index b9b06b4c6ea..b9b06b4c6ea 100644
--- a/arch/ppc/math-emu/op-2.h
+++ b/arch/powerpc/math-emu/op-2.h
diff --git a/arch/ppc/math-emu/op-4.h b/arch/powerpc/math-emu/op-4.h
index fcdd6d064c5..fcdd6d064c5 100644
--- a/arch/ppc/math-emu/op-4.h
+++ b/arch/powerpc/math-emu/op-4.h
diff --git a/arch/ppc/math-emu/op-common.h b/arch/powerpc/math-emu/op-common.h
index afb82b6498c..afb82b6498c 100644
--- a/arch/ppc/math-emu/op-common.h
+++ b/arch/powerpc/math-emu/op-common.h
diff --git a/arch/ppc/math-emu/sfp-machine.h b/arch/powerpc/math-emu/sfp-machine.h
index 4b17d83cfcd..4b17d83cfcd 100644
--- a/arch/ppc/math-emu/sfp-machine.h
+++ b/arch/powerpc/math-emu/sfp-machine.h
diff --git a/arch/ppc/math-emu/single.h b/arch/powerpc/math-emu/single.h
index f19d9945181..f19d9945181 100644
--- a/arch/ppc/math-emu/single.h
+++ b/arch/powerpc/math-emu/single.h
diff --git a/arch/ppc/math-emu/soft-fp.h b/arch/powerpc/math-emu/soft-fp.h
index cca39598f87..cca39598f87 100644
--- a/arch/ppc/math-emu/soft-fp.h
+++ b/arch/powerpc/math-emu/soft-fp.h
diff --git a/arch/ppc/math-emu/stfd.c b/arch/powerpc/math-emu/stfd.c
index 3f8c2558a9e..3f8c2558a9e 100644
--- a/arch/ppc/math-emu/stfd.c
+++ b/arch/powerpc/math-emu/stfd.c
diff --git a/arch/ppc/math-emu/stfiwx.c b/arch/powerpc/math-emu/stfiwx.c
index 95caaeec6a0..95caaeec6a0 100644
--- a/arch/ppc/math-emu/stfiwx.c
+++ b/arch/powerpc/math-emu/stfiwx.c
diff --git a/arch/ppc/math-emu/stfs.c b/arch/powerpc/math-emu/stfs.c
index e87ca23c6dc..e87ca23c6dc 100644
--- a/arch/ppc/math-emu/stfs.c
+++ b/arch/powerpc/math-emu/stfs.c
diff --git a/arch/ppc/math-emu/types.c b/arch/powerpc/math-emu/types.c
index e1ed15d829d..e1ed15d829d 100644
--- a/arch/ppc/math-emu/types.c
+++ b/arch/powerpc/math-emu/types.c
diff --git a/arch/ppc/math-emu/udivmodti4.c b/arch/powerpc/math-emu/udivmodti4.c
index 7e112dc1e2f..7e112dc1e2f 100644
--- a/arch/ppc/math-emu/udivmodti4.c
+++ b/arch/powerpc/math-emu/udivmodti4.c
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index ec4adcb4bc2..5aea0909a5e 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -267,25 +267,29 @@ good_area:
#endif
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
pte_t *ptep;
+ pmd_t *pmdp;
/* Since 4xx/Book-E supports per-page execute permission,
* we lazily flush dcache to icache. */
ptep = NULL;
- if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) {
- struct page *page = pte_page(*ptep);
-
- if (! test_bit(PG_arch_1, &page->flags)) {
- flush_dcache_icache_page(page);
- set_bit(PG_arch_1, &page->flags);
+ if (get_pteptr(mm, address, &ptep, &pmdp)) {
+ spinlock_t *ptl = pte_lockptr(mm, pmdp);
+ spin_lock(ptl);
+ if (pte_present(*ptep)) {
+ struct page *page = pte_page(*ptep);
+
+ if (!test_bit(PG_arch_1, &page->flags)) {
+ flush_dcache_icache_page(page);
+ set_bit(PG_arch_1, &page->flags);
+ }
+ pte_update(ptep, 0, _PAGE_HWEXEC);
+ _tlbie(address);
+ pte_unmap_unlock(ptep, ptl);
+ up_read(&mm->mmap_sem);
+ return 0;
}
- pte_update(ptep, 0, _PAGE_HWEXEC);
- _tlbie(address);
- pte_unmap(ptep);
- up_read(&mm->mmap_sem);
- return 0;
+ pte_unmap_unlock(ptep, ptl);
}
- if (ptep != NULL)
- pte_unmap(ptep);
#endif
/* a write */
} else if (is_write) {
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 89b35c18131..c006d903963 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -167,7 +167,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
* normal insert callback here.
*/
#ifdef CONFIG_PPC_ISERIES
- if (_machine == PLATFORM_ISERIES_LPAR)
+ if (machine_is(iseries))
ret = iSeries_hpte_insert(hpteg, va,
paddr,
tmp_mode,
@@ -176,7 +176,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
else
#endif
#ifdef CONFIG_PPC_PSERIES
- if (_machine & PLATFORM_LPAR)
+ if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR))
ret = pSeries_lpar_hpte_insert(hpteg, va,
paddr,
tmp_mode,
@@ -295,8 +295,7 @@ static void __init htab_init_page_sizes(void)
* Not in the device-tree, let's fallback on known size
* list for 16M capable GP & GR
*/
- if ((_machine != PLATFORM_ISERIES_LPAR) &&
- cpu_has_feature(CPU_FTR_16M_PAGE))
+ if (cpu_has_feature(CPU_FTR_16M_PAGE) && !machine_is(iseries))
memcpy(mmu_psize_defs, mmu_psize_defaults_gp,
sizeof(mmu_psize_defaults_gp));
found:
diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c
index 8b0c132bc16..add8c1a9af6 100644
--- a/arch/powerpc/mm/imalloc.c
+++ b/arch/powerpc/mm/imalloc.c
@@ -13,12 +13,12 @@
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <asm/cacheflush.h>
#include "mmu_decl.h"
-static DECLARE_MUTEX(imlist_sem);
+static DEFINE_MUTEX(imlist_mutex);
struct vm_struct * imlist = NULL;
static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
@@ -257,7 +257,7 @@ struct vm_struct * im_get_free_area(unsigned long size)
struct vm_struct *area;
unsigned long addr;
- down(&imlist_sem);
+ mutex_lock(&imlist_mutex);
if (get_free_im_addr(size, &addr)) {
printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n",
__FUNCTION__, size);
@@ -272,7 +272,7 @@ struct vm_struct * im_get_free_area(unsigned long size)
__FUNCTION__, addr, size);
}
next_im_done:
- up(&imlist_sem);
+ mutex_unlock(&imlist_mutex);
return area;
}
@@ -281,9 +281,9 @@ struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
{
struct vm_struct *area;
- down(&imlist_sem);
+ mutex_lock(&imlist_mutex);
area = __im_get_area(v_addr, size, criteria);
- up(&imlist_sem);
+ mutex_unlock(&imlist_mutex);
return area;
}
@@ -297,17 +297,17 @@ void im_free(void * addr)
printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr);
return;
}
- down(&imlist_sem);
+ mutex_lock(&imlist_mutex);
for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
if (tmp->addr == addr) {
*p = tmp->next;
unmap_vm_area(tmp);
kfree(tmp);
- up(&imlist_sem);
+ mutex_unlock(&imlist_mutex);
return;
}
}
- up(&imlist_sem);
+ mutex_unlock(&imlist_mutex);
printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__,
addr);
}
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index badac10d700..741dd8802d4 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -195,7 +195,7 @@ void show_mem(void)
printk("Mem-info:\n");
show_free_areas();
printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
unsigned long flags;
pgdat_resize_lock(pgdat, &flags);
for (i = 0; i < pgdat->node_spanned_pages; i++) {
@@ -342,7 +342,7 @@ void __init mem_init(void)
#ifdef CONFIG_NEED_MULTIPLE_NODES
for_each_online_node(nid) {
if (NODE_DATA(nid)->node_spanned_pages != 0) {
- printk("freeing bootmem node %x\n", nid);
+ printk("freeing bootmem node %d\n", nid);
totalram_pages +=
free_all_bootmem_node(NODE_DATA(nid));
}
@@ -351,7 +351,7 @@ void __init mem_init(void)
max_mapnr = max_pfn;
totalram_pages += free_all_bootmem();
#endif
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
for (i = 0; i < pgdat->node_spanned_pages; i++) {
if (!pfn_valid(pgdat->node_start_pfn + i))
continue;
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index e89b22aa539..0a335f34974 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -756,6 +756,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
struct device_node *memory = NULL;
nodemask_t nodes;
int default_nid = any_online_node(NODE_MASK_ALL);
+ int nid;
if (!numa_enabled || (min_common_depth < 0))
return default_nid;
@@ -790,6 +791,7 @@ ha_new_range:
goto ha_new_range;
}
BUG(); /* section address should be found above */
+ return 0;
/* Temporary code to ensure that returned node is not empty */
got_nid:
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index d296eb6b454..90628601fac 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -372,7 +372,7 @@ void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
* the PTE pointer is unmodified if PTE is not found.
*/
int
-get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
+get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
{
pgd_t *pgd;
pmd_t *pmd;
@@ -387,6 +387,8 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
if (pte) {
retval = 1;
*ptep = pte;
+ if (pmdp)
+ *pmdp = pmd;
/* XXX caller needs to do pte_unmap, yuck */
}
}
@@ -424,7 +426,7 @@ unsigned long iopa(unsigned long addr)
mm = &init_mm;
pa = 0;
- if (get_pteptr(mm, addr, &pte)) {
+ if (get_pteptr(mm, addr, &pte, NULL)) {
pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
pte_unmap(pte);
}
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 91d25fb27f8..4a9291d9fef 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -239,7 +239,7 @@ void stabs_alloc(void)
if (cpu_has_feature(CPU_FTR_SLB))
return;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
unsigned long newstab;
if (cpu == 0)
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index 554cd7c7532..f5f9859a833 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -6,7 +6,7 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
oprofilefs.o oprofile_stats.o \
timer_int.o )
-oprofile-y := $(DRIVER_OBJS) common.o
+oprofile-y := $(DRIVER_OBJS) common.o backtrace.o
oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o
oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
oprofile-$(CONFIG_PPC32) += op_model_7450.o
diff --git a/arch/powerpc/oprofile/backtrace.c b/arch/powerpc/oprofile/backtrace.c
new file mode 100644
index 00000000000..75f57bc96b4
--- /dev/null
+++ b/arch/powerpc/oprofile/backtrace.c
@@ -0,0 +1,126 @@
+/**
+ * Copyright (C) 2005 Brian Rogan <bcr6@cornell.edu>, IBM
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+**/
+
+#include <linux/oprofile.h>
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#define STACK_SP(STACK) *(STACK)
+
+#define STACK_LR64(STACK) *((unsigned long *)(STACK) + 2)
+#define STACK_LR32(STACK) *((unsigned int *)(STACK) + 1)
+
+#ifdef CONFIG_PPC64
+#define STACK_LR(STACK) STACK_LR64(STACK)
+#else
+#define STACK_LR(STACK) STACK_LR32(STACK)
+#endif
+
+static unsigned int user_getsp32(unsigned int sp, int is_first)
+{
+ unsigned int stack_frame[2];
+
+ if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame)))
+ return 0;
+
+ /*
+ * The most likely reason for this is that we returned -EFAULT,
+ * which means that we've done all that we can do from
+ * interrupt context.
+ */
+ if (__copy_from_user_inatomic(stack_frame, (void *)(long)sp,
+ sizeof(stack_frame)))
+ return 0;
+
+ if (!is_first)
+ oprofile_add_trace(STACK_LR32(stack_frame));
+
+ /*
+ * We do not enforce increasing stack addresses here because
+ * we may transition to a different stack, eg a signal handler.
+ */
+ return STACK_SP(stack_frame);
+}
+
+#ifdef CONFIG_PPC64
+static unsigned long user_getsp64(unsigned long sp, int is_first)
+{
+ unsigned long stack_frame[3];
+
+ if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame)))
+ return 0;
+
+ if (__copy_from_user_inatomic(stack_frame, (void *)sp,
+ sizeof(stack_frame)))
+ return 0;
+
+ if (!is_first)
+ oprofile_add_trace(STACK_LR64(stack_frame));
+
+ return STACK_SP(stack_frame);
+}
+#endif
+
+static unsigned long kernel_getsp(unsigned long sp, int is_first)
+{
+ unsigned long *stack_frame = (unsigned long *)sp;
+
+ if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
+ return 0;
+
+ if (!is_first)
+ oprofile_add_trace(STACK_LR(stack_frame));
+
+ /*
+ * We do not enforce increasing stack addresses here because
+ * we might be transitioning from an interrupt stack to a kernel
+ * stack. validate_sp() is designed to understand this, so just
+ * use it.
+ */
+ return STACK_SP(stack_frame);
+}
+
+void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth)
+{
+ unsigned long sp = regs->gpr[1];
+ int first_frame = 1;
+
+ /* We ditch the top stackframe so need to loop through an extra time */
+ depth += 1;
+
+ if (!user_mode(regs)) {
+ while (depth--) {
+ sp = kernel_getsp(sp, first_frame);
+ if (!sp)
+ break;
+ first_frame = 0;
+ }
+ } else {
+#ifdef CONFIG_PPC64
+ if (!test_thread_flag(TIF_32BIT)) {
+ while (depth--) {
+ sp = user_getsp64(sp, first_frame);
+ if (!sp)
+ break;
+ first_frame = 0;
+ }
+
+ return;
+ }
+#endif
+
+ while (depth--) {
+ sp = user_getsp32(sp, first_frame);
+ if (!sp)
+ break;
+ first_frame = 0;
+ }
+ }
+}
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index cc2535be3a7..5b1de7e8041 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -117,18 +117,10 @@ static int op_powerpc_create_files(struct super_block *sb, struct dentry *root)
oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
-#ifdef CONFIG_PPC64
- oprofilefs_create_ulong(sb, root, "backtrace_spinlocks",
- &sys.backtrace_spinlocks);
-#endif
/* Default to tracing both kernel and user */
sys.enable_kernel = 1;
sys.enable_user = 1;
-#ifdef CONFIG_PPC64
- /* Turn on backtracing through spinlocks by default */
- sys.backtrace_spinlocks = 1;
-#endif
return 0;
}
@@ -168,6 +160,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
ops->shutdown = op_powerpc_shutdown;
ops->start = op_powerpc_start;
ops->stop = op_powerpc_stop;
+ ops->backtrace = op_powerpc_backtrace;
printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
ops->cpu_type);
diff --git a/arch/powerpc/oprofile/op_model_7450.c b/arch/powerpc/oprofile/op_model_7450.c
index 32abfdbb0eb..e0491c3c71f 100644
--- a/arch/powerpc/oprofile/op_model_7450.c
+++ b/arch/powerpc/oprofile/op_model_7450.c
@@ -176,13 +176,13 @@ static void fsl7450_handle_interrupt(struct pt_regs *regs,
mtmsr(mfmsr() | MSR_PMM);
pc = mfspr(SPRN_SIAR);
- is_kernel = (pc >= KERNELBASE);
+ is_kernel = is_kernel_addr(pc);
for (i = 0; i < NUM_CTRS; ++i) {
val = ctr_read(i);
if (val < 0) {
if (oprofile_running && ctr[i].enabled) {
- oprofile_add_pc(pc, is_kernel, i);
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_booke.c
index 26539cda602..93d63e62662 100644
--- a/arch/powerpc/oprofile/op_model_fsl_booke.c
+++ b/arch/powerpc/oprofile/op_model_fsl_booke.c
@@ -154,13 +154,13 @@ static void fsl_booke_handle_interrupt(struct pt_regs *regs,
mtmsr(mfmsr() | MSR_PMM);
pc = regs->nip;
- is_kernel = (pc >= KERNELBASE);
+ is_kernel = is_kernel_addr(pc);
for (i = 0; i < num_counters; ++i) {
val = ctr_read(i);
if (val < 0) {
if (oprofile_running && ctr[i].enabled) {
- oprofile_add_pc(pc, is_kernel, i);
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index 4b06e53eb9b..4c2beab1fdc 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -25,18 +25,14 @@ static unsigned long reset_value[OP_MAX_COUNTER];
static int oprofile_running;
static int mmcra_has_sihv;
+/* Unfortunately these bits vary between CPUs */
+static unsigned long mmcra_sihv = MMCRA_SIHV;
+static unsigned long mmcra_sipr = MMCRA_SIPR;
/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
static u32 mmcr0_val;
static u64 mmcr1_val;
-static u32 mmcra_val;
-
-/*
- * Since we do not have an NMI, backtracing through spinlocks is
- * only a best guess. In light of this, allow it to be disabled at
- * runtime.
- */
-static int backtrace_spinlocks;
+static u64 mmcra_val;
static void power4_reg_setup(struct op_counter_config *ctr,
struct op_system_config *sys,
@@ -63,8 +59,6 @@ static void power4_reg_setup(struct op_counter_config *ctr,
mmcr1_val = sys->mmcr1;
mmcra_val = sys->mmcra;
- backtrace_spinlocks = sys->backtrace_spinlocks;
-
for (i = 0; i < cur_cpu_spec->num_pmcs; ++i)
reset_value[i] = 0x80000000UL - ctr[i].count;
@@ -197,25 +191,6 @@ static void __attribute_used__ kernel_unknown_bucket(void)
{
}
-static unsigned long check_spinlock_pc(struct pt_regs *regs,
- unsigned long profile_pc)
-{
- unsigned long pc = instruction_pointer(regs);
-
- /*
- * If both the SIAR (sampled instruction) and the perfmon exception
- * occurred in a spinlock region then we account the sample to the
- * calling function. This isnt 100% correct, we really need soft
- * IRQ disable so we always get the perfmon exception at the
- * point at which the SIAR is set.
- */
- if (backtrace_spinlocks && in_lock_functions(pc) &&
- in_lock_functions(profile_pc))
- return regs->link;
- else
- return profile_pc;
-}
-
/*
* On GQ and newer the MMCRA stores the HV and PR bits at the time
* the SIAR was sampled. We use that to work out if the SIAR was sampled in
@@ -228,17 +203,17 @@ static unsigned long get_pc(struct pt_regs *regs)
/* Cant do much about it */
if (!mmcra_has_sihv)
- return check_spinlock_pc(regs, pc);
+ return pc;
mmcra = mfspr(SPRN_MMCRA);
/* Were we in the hypervisor? */
- if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & MMCRA_SIHV))
+ if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv))
/* function descriptor madness */
return *((unsigned long *)hypervisor_bucket);
/* We were in userspace, nothing to do */
- if (mmcra & MMCRA_SIPR)
+ if (mmcra & mmcra_sipr)
return pc;
#ifdef CONFIG_PPC_RTAS
@@ -257,7 +232,7 @@ static unsigned long get_pc(struct pt_regs *regs)
/* function descriptor madness */
return *((unsigned long *)kernel_unknown_bucket);
- return check_spinlock_pc(regs, pc);
+ return pc;
}
static int get_kernel(unsigned long pc)
@@ -268,7 +243,7 @@ static int get_kernel(unsigned long pc)
is_kernel = is_kernel_addr(pc);
} else {
unsigned long mmcra = mfspr(SPRN_MMCRA);
- is_kernel = ((mmcra & MMCRA_SIPR) == 0);
+ is_kernel = ((mmcra & mmcra_sipr) == 0);
}
return is_kernel;
@@ -293,7 +268,7 @@ static void power4_handle_interrupt(struct pt_regs *regs,
val = ctr_read(i);
if (val < 0) {
if (oprofile_running && ctr[i].enabled) {
- oprofile_add_pc(pc, is_kernel, i);
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
diff --git a/arch/powerpc/oprofile/op_model_rs64.c b/arch/powerpc/oprofile/op_model_rs64.c
index 5c909ee609f..042f8f4867a 100644
--- a/arch/powerpc/oprofile/op_model_rs64.c
+++ b/arch/powerpc/oprofile/op_model_rs64.c
@@ -175,10 +175,13 @@ static void rs64_handle_interrupt(struct pt_regs *regs,
struct op_counter_config *ctr)
{
unsigned int mmcr0;
+ int is_kernel;
int val;
int i;
unsigned long pc = mfspr(SPRN_SIAR);
+ is_kernel = is_kernel_addr(pc);
+
/* set the PMM bit (see comment below) */
mtmsrd(mfmsr() | MSR_PMM);
@@ -186,7 +189,7 @@ static void rs64_handle_interrupt(struct pt_regs *regs,
val = ctr_read(i);
if (val < 0) {
if (ctr[i].enabled) {
- oprofile_add_pc(pc, is_kernel_addr(pc), i);
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index d3d0ff745e8..06e371282f5 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -7,6 +7,7 @@ choice
config MPC8540_ADS
bool "Freescale MPC8540 ADS"
+ select DEFAULT_UIMAGE
help
This option enables support for the MPC 8540 ADS board
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 3157071e241..c2a3db8edb0 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -10,4 +10,9 @@ config SPU_FS
Units on machines implementing the Broadband Processor
Architecture.
+config SPUFS_MMAP
+ bool
+ depends on SPU_FS && SPARSEMEM && !PPC_64K_PAGES
+ default y
+
endmenu
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 3b998a393e3..e570bad0639 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -6,5 +6,11 @@ obj-$(CONFIG_SPU_FS) += spu-base.o spufs/
spu-base-y += spu_base.o spu_priv1.o
-builtin-spufs-$(CONFIG_SPU_FS) += spu_syscalls.o
-obj-y += $(builtin-spufs-m)
+# needed only when building loadable spufs.ko
+spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o
+obj-y += $(spufs-modular-m)
+
+# always needed in kernel
+spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o
+obj-y += $(spufs-builtin-y) $(spufs-builtin-m)
+
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 63aa52acf44..978be1c30c1 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -63,7 +63,24 @@ static DEFINE_PER_CPU(struct iic, iic);
void iic_local_enable(void)
{
- out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
+ struct iic *iic = &__get_cpu_var(iic);
+ u64 tmp;
+
+ /*
+ * There seems to be a bug that is present in DD2.x CPUs
+ * and still only partially fixed in DD3.1.
+ * This bug causes a value written to the priority register
+ * not to make it there, resulting in a system hang unless we
+ * write it again.
+ * Masking with 0xf0 is done because the Cell BE does not
+ * implement the lower four bits of the interrupt priority,
+ * they always read back as zeroes, although future CPUs
+ * might implement different bits.
+ */
+ do {
+ out_be64(&iic->regs->prio, 0xff);
+ tmp = in_be64(&iic->regs->prio);
+ } while ((tmp & 0xf0) != 0xf0);
}
void iic_local_disable(void)
@@ -123,7 +140,7 @@ static int iic_external_get_irq(struct iic_pending_bits pending)
pending.class != 2)
break;
irq = IIC_EXT_OFFSET
- + spider_get_irq(pending.prio + node * IIC_NODE_STRIDE)
+ + spider_get_irq(node)
+ node * IIC_NODE_STRIDE;
break;
case 0x01 ... 0x04:
@@ -174,38 +191,98 @@ int iic_get_irq(struct pt_regs *regs)
return irq;
}
-static int setup_iic(int cpu, struct iic *iic)
+/* hardcoded part to be compatible with older firmware */
+
+static int setup_iic_hardcoded(void)
{
struct device_node *np;
- int nodeid = cpu / 2;
+ int nodeid, cpu;
unsigned long regs;
+ struct iic *iic;
- for (np = of_find_node_by_type(NULL, "cpu");
- np;
- np = of_find_node_by_type(np, "cpu")) {
- if (nodeid == *(int *)get_property(np, "node-id", NULL))
- break;
+ for_each_cpu(cpu) {
+ iic = &per_cpu(iic, cpu);
+ nodeid = cpu/2;
+
+ for (np = of_find_node_by_type(NULL, "cpu");
+ np;
+ np = of_find_node_by_type(np, "cpu")) {
+ if (nodeid == *(int *)get_property(np, "node-id", NULL))
+ break;
+ }
+
+ if (!np) {
+ printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);
+ iic->regs = NULL;
+ iic->target_id = 0xff;
+ return -ENODEV;
+ }
+
+ regs = *(long *)get_property(np, "iic", NULL);
+
+ /* hack until we have decided on the devtree info */
+ regs += 0x400;
+ if (cpu & 1)
+ regs += 0x20;
+
+ printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs);
+ iic->regs = ioremap(regs, sizeof(struct iic_regs));
+ iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe);
}
- if (!np) {
- printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);
- iic->regs = NULL;
- iic->target_id = 0xff;
- return -ENODEV;
- }
+ return 0;
+}
- regs = *(long *)get_property(np, "iic", NULL);
+static int setup_iic(void)
+{
+ struct device_node *dn;
+ unsigned long *regs;
+ char *compatible;
+ unsigned *np, found = 0;
+ struct iic *iic = NULL;
+
+ for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
+ compatible = (char *)get_property(dn, "compatible", NULL);
+
+ if (!compatible) {
+ printk(KERN_WARNING "no compatible property found !\n");
+ continue;
+ }
- /* hack until we have decided on the devtree info */
- regs += 0x400;
- if (cpu & 1)
- regs += 0x20;
+ if (strstr(compatible, "IBM,CBEA-Internal-Interrupt-Controller"))
+ regs = (unsigned long *)get_property(dn,"reg", NULL);
+ else
+ continue;
- printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs);
- iic->regs = __ioremap(regs, sizeof(struct iic_regs),
- _PAGE_NO_CACHE);
- iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe);
- return 0;
+ if (!regs)
+ printk(KERN_WARNING "IIC: no reg property\n");
+
+ np = (unsigned int *)get_property(dn, "ibm,interrupt-server-ranges", NULL);
+
+ if (!np) {
+ printk(KERN_WARNING "IIC: CPU association not found\n");
+ iic->regs = NULL;
+ iic->target_id = 0xff;
+ return -ENODEV;
+ }
+
+ iic = &per_cpu(iic, np[0]);
+ iic->regs = ioremap(regs[0], sizeof(struct iic_regs));
+ iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe);
+ printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs);
+
+ iic = &per_cpu(iic, np[1]);
+ iic->regs = ioremap(regs[2], sizeof(struct iic_regs));
+ iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe);
+ printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs);
+
+ found++;
+ }
+
+ if (found)
+ return 0;
+ else
+ return -ENODEV;
}
#ifdef CONFIG_SMP
@@ -283,10 +360,12 @@ void iic_init_IRQ(void)
int cpu, irq_offset;
struct iic *iic;
+ if (setup_iic() < 0)
+ setup_iic_hardcoded();
+
irq_offset = 0;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
iic = &per_cpu(iic, cpu);
- setup_iic(cpu, iic);
if (iic->regs)
out_be64(&iic->regs->prio, 0xff);
}
diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h
index a14bd38791c..799f77d98f9 100644
--- a/arch/powerpc/platforms/cell/interrupt.h
+++ b/arch/powerpc/platforms/cell/interrupt.h
@@ -57,7 +57,7 @@ extern void iic_local_disable(void);
extern u8 iic_get_target_id(int cpu);
extern void spider_init_IRQ(void);
-extern int spider_get_irq(unsigned long int_pending);
+extern int spider_get_irq(int node);
#endif
#endif /* ASM_CELL_PIC_H */
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 46e7cb9c3e6..a49ceb799a8 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -289,7 +289,7 @@ static void cell_do_map_iommu(struct cell_iommu *iommu,
ioc_base = iommu->mapped_base;
ioc_mmio_base = iommu->mapped_mmio_base;
- for (real_address = 0, io_address = 0;
+ for (real_address = 0, io_address = map_start;
io_address <= map_start + map_size;
real_address += io_page_size, io_address += io_page_size) {
ioste = get_iost_entry(fake_iopt, io_address, io_page_size);
@@ -302,7 +302,7 @@ static void cell_do_map_iommu(struct cell_iommu *iommu,
set_iopt_cache(ioc_mmio_base,
get_ioc_hash_1way(ioste, io_address),
get_ioc_tag(ioste, io_address),
- get_iopt_entry(real_address-map_start, ioid, IOPT_PROT_RW));
+ get_iopt_entry(real_address, ioid, IOPT_PROT_RW));
}
}
@@ -344,8 +344,8 @@ static int cell_map_iommu_hardcoded(int num_nodes)
/* node 0 */
iommu = &cell_iommus[0];
- iommu->mapped_base = __ioremap(0x20000511000, 0x1000, _PAGE_NO_CACHE);
- iommu->mapped_mmio_base = __ioremap(0x20000510000, 0x1000, _PAGE_NO_CACHE);
+ iommu->mapped_base = ioremap(0x20000511000, 0x1000);
+ iommu->mapped_mmio_base = ioremap(0x20000510000, 0x1000);
enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
@@ -357,8 +357,8 @@ static int cell_map_iommu_hardcoded(int num_nodes)
/* node 1 */
iommu = &cell_iommus[1];
- iommu->mapped_base = __ioremap(0x30000511000, 0x1000, _PAGE_NO_CACHE);
- iommu->mapped_mmio_base = __ioremap(0x30000510000, 0x1000, _PAGE_NO_CACHE);
+ iommu->mapped_base = ioremap(0x30000511000, 0x1000);
+ iommu->mapped_mmio_base = ioremap(0x30000510000, 0x1000);
enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
@@ -407,8 +407,8 @@ static int cell_map_iommu(void)
iommu->base = *base;
iommu->mmio_base = *mmio_base;
- iommu->mapped_base = __ioremap(*base, 0x1000, _PAGE_NO_CACHE);
- iommu->mapped_mmio_base = __ioremap(*mmio_base, 0x1000, _PAGE_NO_CACHE);
+ iommu->mapped_base = ioremap(*base, 0x1000);
+ iommu->mapped_mmio_base = ioremap(*mmio_base, 0x1000);
enable_mapping(iommu->mapped_base,
iommu->mapped_mmio_base);
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index e0e051c675d..7eed8c62451 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -203,7 +203,7 @@ found:
pr_debug("pervasive area for CPU %d at %lx, size %x\n",
cpu, real_address, size);
- p->regs = __ioremap(real_address, size, _PAGE_NO_CACHE);
+ p->regs = ioremap(real_address, size);
p->thread = thread;
return 0;
}
@@ -217,7 +217,7 @@ void __init cell_pervasive_init(void)
if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
return;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
p = &cbe_pervasive[cpu];
ret = cbe_find_pmd_mmio(cpu, p);
if (ret)
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index fec8e65b36e..dac5d0365fd 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -195,9 +195,13 @@ static void __init cell_init_early(void)
}
-static int __init cell_probe(int platform)
+static int __init cell_probe(void)
{
- if (platform != PLATFORM_CELL)
+ /* XXX This is temporary, the Cell maintainer will come up with
+ * more appropriate detection logic
+ */
+ unsigned long root = of_get_flat_dt_root();
+ if (!of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
return 0;
return 1;
@@ -212,7 +216,8 @@ static int cell_check_legacy_ioport(unsigned int baseport)
return -ENODEV;
}
-struct machdep_calls __initdata cell_md = {
+define_machine(cell) {
+ .name = "Cell",
.probe = cell_probe,
.setup_arch = cell_setup_arch,
.init_early = cell_init_early,
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index e74132188bd..55cbdd77a62 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -84,10 +84,11 @@ static void __iomem *spider_get_irq_config(int irq)
static void spider_enable_irq(unsigned int irq)
{
+ int nodeid = (irq / IIC_NODE_STRIDE) * 0x10;
void __iomem *cfg = spider_get_irq_config(irq);
irq = spider_get_nr(irq);
- out_be32(cfg, in_be32(cfg) | 0x3107000eu);
+ out_be32(cfg, (in_be32(cfg) & ~0xf0)| 0x3107000eu | nodeid);
out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq);
}
@@ -131,61 +132,108 @@ static struct hw_interrupt_type spider_pic = {
.end = spider_end_irq,
};
-
-int spider_get_irq(unsigned long int_pending)
+int spider_get_irq(int node)
{
- void __iomem *regs = spider_get_pic(int_pending);
unsigned long cs;
- int irq;
-
- cs = in_be32(regs + TIR_CS);
+ void __iomem *regs = spider_pics[node];
- irq = cs >> 24;
- if (irq != 63)
- return irq;
+ cs = in_be32(regs + TIR_CS) >> 24;
- return -1;
+ if (cs == 63)
+ return -1;
+ else
+ return cs;
}
-
-void spider_init_IRQ(void)
+
+/* hardcoded part to be compatible with older firmware */
+
+void spider_init_IRQ_hardcoded(void)
{
int node;
- struct device_node *dn;
- unsigned int *property;
long spiderpic;
+ long pics[] = { 0x24000008000, 0x34000008000 };
int n;
-/* FIXME: detect multiple PICs as soon as the device tree has them */
- for (node = 0; node < 1; node++) {
- dn = of_find_node_by_path("/");
- n = prom_n_addr_cells(dn);
- property = (unsigned int *) get_property(dn,
- "platform-spider-pic", NULL);
+ pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__);
- if (!property)
- continue;
- for (spiderpic = 0; n > 0; --n)
- spiderpic = (spiderpic << 32) + *property++;
+ for (node = 0; node < num_present_cpus()/2; node++) {
+ spiderpic = pics[node];
printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic);
- spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE);
+ spider_pics[node] = ioremap(spiderpic, 0x800);
for (n = 0; n < IIC_NUM_EXT; n++) {
int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
get_irq_desc(irq)->handler = &spider_pic;
+ }
/* do not mask any interrupts because of level */
out_be32(spider_pics[node] + TIR_MSK, 0x0);
-
+
/* disable edge detection clear */
/* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
-
+
/* enable interrupt packets to be output */
out_be32(spider_pics[node] + TIR_PIEN,
in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
-
+
/* Enable the interrupt detection enable bit. Do this last! */
out_be32(spider_pics[node] + TIR_DEN,
- in_be32(spider_pics[node] +TIR_DEN) | 0x1);
+ in_be32(spider_pics[node] + TIR_DEN) | 0x1);
+ }
+}
+
+void spider_init_IRQ(void)
+{
+ long spider_reg;
+ struct device_node *dn;
+ char *compatible;
+ int n, node = 0;
+
+ for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
+ compatible = (char *)get_property(dn, "compatible", NULL);
+ if (!compatible)
+ continue;
+
+ if (strstr(compatible, "CBEA,platform-spider-pic"))
+ spider_reg = *(long *)get_property(dn,"reg", NULL);
+ else if (strstr(compatible, "sti,platform-spider-pic")) {
+ spider_init_IRQ_hardcoded();
+ return;
+ } else
+ continue;
+
+ if (!spider_reg)
+ printk("interrupt controller does not have reg property !\n");
+
+ n = prom_n_addr_cells(dn);
+
+ if ( n != 2)
+ printk("reg property with invalid number of elements \n");
+
+ spider_pics[node] = ioremap(spider_reg, 0x800);
+
+ printk("SPIDER addr: %lx with %i addr_cells mapped to %p\n",
+ spider_reg, n, spider_pics[node]);
+
+ for (n = 0; n < IIC_NUM_EXT; n++) {
+ int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
+ get_irq_desc(irq)->handler = &spider_pic;
}
+
+ /* do not mask any interrupts because of level */
+ out_be32(spider_pics[node] + TIR_MSK, 0x0);
+
+ /* disable edge detection clear */
+ /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
+
+ /* enable interrupt packets to be output */
+ out_be32(spider_pics[node] + TIR_PIEN,
+ in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
+
+ /* Enable the interrupt detection enable bit. Do this last! */
+ out_be32(spider_pics[node] + TIR_DEN,
+ in_be32(spider_pics[node] + TIR_DEN) | 0x1);
+
+ node++;
}
}
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index d75ae03df68..269dda4fd0b 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -32,7 +32,7 @@
#include <asm/io.h>
#include <asm/prom.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <asm/spu.h>
#include <asm/mmu_context.h>
@@ -111,7 +111,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX
static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
{
- pr_debug("%s\n", __FUNCTION__);
+ pr_debug("%s, %lx, %lx\n", __FUNCTION__, dsisr, ea);
/* Handle kernel space hash faults immediately.
User hash faults need to be deferred to process context. */
@@ -168,7 +168,7 @@ static int __spu_trap_halt(struct spu *spu)
static int __spu_trap_tag_group(struct spu *spu)
{
pr_debug("%s\n", __FUNCTION__);
- /* wake_up(&spu->dma_wq); */
+ spu->mfc_callback(spu);
return 0;
}
@@ -242,6 +242,8 @@ spu_irq_class_1(int irq, void *data, struct pt_regs *regs)
spu_mfc_dsisr_set(spu, 0ul);
spu_int_stat_clear(spu, 1, stat);
spin_unlock(&spu->register_lock);
+ pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat,
+ dar, dsisr);
if (stat & 1) /* segment fault */
__spu_trap_data_seg(spu, dar);
@@ -342,7 +344,7 @@ spu_free_irqs(struct spu *spu)
}
static LIST_HEAD(spu_list);
-static DECLARE_MUTEX(spu_mutex);
+static DEFINE_MUTEX(spu_mutex);
static void spu_init_channels(struct spu *spu)
{
@@ -382,7 +384,7 @@ struct spu *spu_alloc(void)
{
struct spu *spu;
- down(&spu_mutex);
+ mutex_lock(&spu_mutex);
if (!list_empty(&spu_list)) {
spu = list_entry(spu_list.next, struct spu, list);
list_del_init(&spu->list);
@@ -391,7 +393,7 @@ struct spu *spu_alloc(void)
pr_debug("No SPU left\n");
spu = NULL;
}
- up(&spu_mutex);
+ mutex_unlock(&spu_mutex);
if (spu)
spu_init_channels(spu);
@@ -402,9 +404,9 @@ EXPORT_SYMBOL_GPL(spu_alloc);
void spu_free(struct spu *spu)
{
- down(&spu_mutex);
+ mutex_lock(&spu_mutex);
list_add_tail(&spu->list, &spu_list);
- up(&spu_mutex);
+ mutex_unlock(&spu_mutex);
}
EXPORT_SYMBOL_GPL(spu_free);
@@ -484,14 +486,13 @@ int spu_irq_class_1_bottom(struct spu *spu)
ea = spu->dar;
dsisr = spu->dsisr;
- if (dsisr & MFC_DSISR_PTE_NOT_FOUND) {
+ if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) {
access = (_PAGE_PRESENT | _PAGE_USER);
access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL;
if (hash_page(ea, access, 0x300) != 0)
error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
}
- if ((error & CLASS1_ENABLE_STORAGE_FAULT_INTR) ||
- (dsisr & MFC_DSISR_ACCESS_DENIED)) {
+ if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) {
if ((ret = spu_handle_mm_fault(spu)) != 0)
error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
else
@@ -568,6 +569,11 @@ static int __init spu_map_device(struct spu *spu, struct device_node *spe)
if (!spu->local_store)
goto out;
+ prop = get_property(spe, "problem", NULL);
+ if (!prop)
+ goto out_unmap;
+ spu->problem_phys = *(unsigned long *)prop;
+
spu->problem= map_spe_prop(spe, "problem");
if (!spu->problem)
goto out_unmap;
@@ -632,15 +638,16 @@ static int __init create_spu(struct device_node *spe)
spu->ibox_callback = NULL;
spu->wbox_callback = NULL;
spu->stop_callback = NULL;
+ spu->mfc_callback = NULL;
- down(&spu_mutex);
+ mutex_lock(&spu_mutex);
spu->number = number++;
ret = spu_request_irqs(spu);
if (ret)
goto out_unmap;
list_add(&spu->list, &spu_list);
- up(&spu_mutex);
+ mutex_unlock(&spu_mutex);
pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n",
spu->name, spu->isrc, spu->local_store,
@@ -648,7 +655,7 @@ static int __init create_spu(struct device_node *spe)
goto out;
out_unmap:
- up(&spu_mutex);
+ mutex_unlock(&spu_mutex);
spu_unmap(spu);
out_free:
kfree(spu);
@@ -668,10 +675,10 @@ static void destroy_spu(struct spu *spu)
static void cleanup_spu_base(void)
{
struct spu *spu, *tmp;
- down(&spu_mutex);
+ mutex_lock(&spu_mutex);
list_for_each_entry_safe(spu, tmp, &spu_list, list)
destroy_spu(spu);
- up(&spu_mutex);
+ mutex_unlock(&spu_mutex);
}
module_exit(cleanup_spu_base);
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
new file mode 100644
index 00000000000..3a4245c926a
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spu_callbacks.c
@@ -0,0 +1,345 @@
+/*
+ * System call callback functions for SPUs
+ */
+
+#define DEBUG
+
+#include <linux/kallsyms.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+
+#include <asm/spu.h>
+#include <asm/syscalls.h>
+#include <asm/unistd.h>
+
+/*
+ * This table defines the system calls that an SPU can call.
+ * It is currently a subset of the 64 bit powerpc system calls,
+ * with the exact semantics.
+ *
+ * The reasons for disabling some of the system calls are:
+ * 1. They interact with the way SPU syscalls are handled
+ * and we can't let them execute ever:
+ * restart_syscall, exit, for, execve, ptrace, ...
+ * 2. They are deprecated and replaced by other means:
+ * uselib, pciconfig_*, sysfs, ...
+ * 3. They are somewhat interacting with the system in a way
+ * we don't want an SPU to:
+ * reboot, init_module, mount, kexec_load
+ * 4. They are optional and we can't rely on them being
+ * linked into the kernel. Unfortunately, the cond_syscall
+ * helper does not work here as it does not add the necessary
+ * opd symbols:
+ * mbind, mq_open, ipc, ...
+ */
+
+void *spu_syscall_table[] = {
+ [__NR_restart_syscall] sys_ni_syscall, /* sys_restart_syscall */
+ [__NR_exit] sys_ni_syscall, /* sys_exit */
+ [__NR_fork] sys_ni_syscall, /* ppc_fork */
+ [__NR_read] sys_read,
+ [__NR_write] sys_write,
+ [__NR_open] sys_open,
+ [__NR_close] sys_close,
+ [__NR_waitpid] sys_waitpid,
+ [__NR_creat] sys_creat,
+ [__NR_link] sys_link,
+ [__NR_unlink] sys_unlink,
+ [__NR_execve] sys_ni_syscall, /* sys_execve */
+ [__NR_chdir] sys_chdir,
+ [__NR_time] sys_time,
+ [__NR_mknod] sys_mknod,
+ [__NR_chmod] sys_chmod,
+ [__NR_lchown] sys_lchown,
+ [__NR_break] sys_ni_syscall,
+ [__NR_oldstat] sys_ni_syscall,
+ [__NR_lseek] sys_lseek,
+ [__NR_getpid] sys_getpid,
+ [__NR_mount] sys_ni_syscall, /* sys_mount */
+ [__NR_umount] sys_ni_syscall,
+ [__NR_setuid] sys_setuid,
+ [__NR_getuid] sys_getuid,
+ [__NR_stime] sys_stime,
+ [__NR_ptrace] sys_ni_syscall, /* sys_ptrace */
+ [__NR_alarm] sys_alarm,
+ [__NR_oldfstat] sys_ni_syscall,
+ [__NR_pause] sys_ni_syscall, /* sys_pause */
+ [__NR_utime] sys_ni_syscall, /* sys_utime */
+ [__NR_stty] sys_ni_syscall,
+ [__NR_gtty] sys_ni_syscall,
+ [__NR_access] sys_access,
+ [__NR_nice] sys_nice,
+ [__NR_ftime] sys_ni_syscall,
+ [__NR_sync] sys_sync,
+ [__NR_kill] sys_kill,
+ [__NR_rename] sys_rename,
+ [__NR_mkdir] sys_mkdir,
+ [__NR_rmdir] sys_rmdir,
+ [__NR_dup] sys_dup,
+ [__NR_pipe] sys_pipe,
+ [__NR_times] sys_times,
+ [__NR_prof] sys_ni_syscall,
+ [__NR_brk] sys_brk,
+ [__NR_setgid] sys_setgid,
+ [__NR_getgid] sys_getgid,
+ [__NR_signal] sys_ni_syscall, /* sys_signal */
+ [__NR_geteuid] sys_geteuid,
+ [__NR_getegid] sys_getegid,
+ [__NR_acct] sys_ni_syscall, /* sys_acct */
+ [__NR_umount2] sys_ni_syscall, /* sys_umount */
+ [__NR_lock] sys_ni_syscall,
+ [__NR_ioctl] sys_ioctl,
+ [__NR_fcntl] sys_fcntl,
+ [__NR_mpx] sys_ni_syscall,
+ [__NR_setpgid] sys_setpgid,
+ [__NR_ulimit] sys_ni_syscall,
+ [__NR_oldolduname] sys_ni_syscall,
+ [__NR_umask] sys_umask,
+ [__NR_chroot] sys_chroot,
+ [__NR_ustat] sys_ni_syscall, /* sys_ustat */
+ [__NR_dup2] sys_dup2,
+ [__NR_getppid] sys_getppid,
+ [__NR_getpgrp] sys_getpgrp,
+ [__NR_setsid] sys_setsid,
+ [__NR_sigaction] sys_ni_syscall,
+ [__NR_sgetmask] sys_sgetmask,
+ [__NR_ssetmask] sys_ssetmask,
+ [__NR_setreuid] sys_setreuid,
+ [__NR_setregid] sys_setregid,
+ [__NR_sigsuspend] sys_ni_syscall,
+ [__NR_sigpending] sys_ni_syscall,
+ [__NR_sethostname] sys_sethostname,
+ [__NR_setrlimit] sys_setrlimit,
+ [__NR_getrlimit] sys_ni_syscall,
+ [__NR_getrusage] sys_getrusage,
+ [__NR_gettimeofday] sys_gettimeofday,
+ [__NR_settimeofday] sys_settimeofday,
+ [__NR_getgroups] sys_getgroups,
+ [__NR_setgroups] sys_setgroups,
+ [__NR_select] sys_ni_syscall,
+ [__NR_symlink] sys_symlink,
+ [__NR_oldlstat] sys_ni_syscall,
+ [__NR_readlink] sys_readlink,
+ [__NR_uselib] sys_ni_syscall, /* sys_uselib */
+ [__NR_swapon] sys_ni_syscall, /* sys_swapon */
+ [__NR_reboot] sys_ni_syscall, /* sys_reboot */
+ [__NR_readdir] sys_ni_syscall,
+ [__NR_mmap] sys_mmap,
+ [__NR_munmap] sys_munmap,
+ [__NR_truncate] sys_truncate,
+ [__NR_ftruncate] sys_ftruncate,
+ [__NR_fchmod] sys_fchmod,
+ [__NR_fchown] sys_fchown,
+ [__NR_getpriority] sys_getpriority,
+ [__NR_setpriority] sys_setpriority,
+ [__NR_profil] sys_ni_syscall,
+ [__NR_statfs] sys_ni_syscall, /* sys_statfs */
+ [__NR_fstatfs] sys_ni_syscall, /* sys_fstatfs */
+ [__NR_ioperm] sys_ni_syscall,
+ [__NR_socketcall] sys_socketcall,
+ [__NR_syslog] sys_syslog,
+ [__NR_setitimer] sys_setitimer,
+ [__NR_getitimer] sys_getitimer,
+ [__NR_stat] sys_newstat,
+ [__NR_lstat] sys_newlstat,
+ [__NR_fstat] sys_newfstat,
+ [__NR_olduname] sys_ni_syscall,
+ [__NR_iopl] sys_ni_syscall,
+ [__NR_vhangup] sys_vhangup,
+ [__NR_idle] sys_ni_syscall,
+ [__NR_vm86] sys_ni_syscall,
+ [__NR_wait4] sys_wait4,
+ [__NR_swapoff] sys_ni_syscall, /* sys_swapoff */
+ [__NR_sysinfo] sys_sysinfo,
+ [__NR_ipc] sys_ni_syscall, /* sys_ipc */
+ [__NR_fsync] sys_fsync,
+ [__NR_sigreturn] sys_ni_syscall,
+ [__NR_clone] sys_ni_syscall, /* ppc_clone */
+ [__NR_setdomainname] sys_setdomainname,
+ [__NR_uname] ppc_newuname,
+ [__NR_modify_ldt] sys_ni_syscall,
+ [__NR_adjtimex] sys_adjtimex,
+ [__NR_mprotect] sys_mprotect,
+ [__NR_sigprocmask] sys_ni_syscall,
+ [__NR_create_module] sys_ni_syscall,
+ [__NR_init_module] sys_ni_syscall, /* sys_init_module */
+ [__NR_delete_module] sys_ni_syscall, /* sys_delete_module */
+ [__NR_get_kernel_syms] sys_ni_syscall,
+ [__NR_quotactl] sys_ni_syscall, /* sys_quotactl */
+ [__NR_getpgid] sys_getpgid,
+ [__NR_fchdir] sys_fchdir,
+ [__NR_bdflush] sys_bdflush,
+ [__NR_sysfs] sys_ni_syscall, /* sys_sysfs */
+ [__NR_personality] ppc64_personality,
+ [__NR_afs_syscall] sys_ni_syscall,
+ [__NR_setfsuid] sys_setfsuid,
+ [__NR_setfsgid] sys_setfsgid,
+ [__NR__llseek] sys_llseek,
+ [__NR_getdents] sys_getdents,
+ [__NR__newselect] sys_select,
+ [__NR_flock] sys_flock,
+ [__NR_msync] sys_msync,
+ [__NR_readv] sys_readv,
+ [__NR_writev] sys_writev,
+ [__NR_getsid] sys_getsid,
+ [__NR_fdatasync] sys_fdatasync,
+ [__NR__sysctl] sys_ni_syscall, /* sys_sysctl */
+ [__NR_mlock] sys_mlock,
+ [__NR_munlock] sys_munlock,
+ [__NR_mlockall] sys_mlockall,
+ [__NR_munlockall] sys_munlockall,
+ [__NR_sched_setparam] sys_sched_setparam,
+ [__NR_sched_getparam] sys_sched_getparam,
+ [__NR_sched_setscheduler] sys_sched_setscheduler,
+ [__NR_sched_getscheduler] sys_sched_getscheduler,
+ [__NR_sched_yield] sys_sched_yield,
+ [__NR_sched_get_priority_max] sys_sched_get_priority_max,
+ [__NR_sched_get_priority_min] sys_sched_get_priority_min,
+ [__NR_sched_rr_get_interval] sys_sched_rr_get_interval,
+ [__NR_nanosleep] sys_nanosleep,
+ [__NR_mremap] sys_mremap,
+ [__NR_setresuid] sys_setresuid,
+ [__NR_getresuid] sys_getresuid,
+ [__NR_query_module] sys_ni_syscall,
+ [__NR_poll] sys_poll,
+ [__NR_nfsservctl] sys_ni_syscall, /* sys_nfsservctl */
+ [__NR_setresgid] sys_setresgid,
+ [__NR_getresgid] sys_getresgid,
+ [__NR_prctl] sys_prctl,
+ [__NR_rt_sigreturn] sys_ni_syscall, /* ppc64_rt_sigreturn */
+ [__NR_rt_sigaction] sys_ni_syscall, /* sys_rt_sigaction */
+ [__NR_rt_sigprocmask] sys_ni_syscall, /* sys_rt_sigprocmask */
+ [__NR_rt_sigpending] sys_ni_syscall, /* sys_rt_sigpending */
+ [__NR_rt_sigtimedwait] sys_ni_syscall, /* sys_rt_sigtimedwait */
+ [__NR_rt_sigqueueinfo] sys_ni_syscall, /* sys_rt_sigqueueinfo */
+ [__NR_rt_sigsuspend] sys_ni_syscall, /* sys_rt_sigsuspend */
+ [__NR_pread64] sys_pread64,
+ [__NR_pwrite64] sys_pwrite64,
+ [__NR_chown] sys_chown,
+ [__NR_getcwd] sys_getcwd,
+ [__NR_capget] sys_capget,
+ [__NR_capset] sys_capset,
+ [__NR_sigaltstack] sys_ni_syscall, /* sys_sigaltstack */
+ [__NR_sendfile] sys_sendfile64,
+ [__NR_getpmsg] sys_ni_syscall,
+ [__NR_putpmsg] sys_ni_syscall,
+ [__NR_vfork] sys_ni_syscall, /* ppc_vfork */
+ [__NR_ugetrlimit] sys_getrlimit,
+ [__NR_readahead] sys_readahead,
+ [192] sys_ni_syscall,
+ [193] sys_ni_syscall,
+ [194] sys_ni_syscall,
+ [195] sys_ni_syscall,
+ [196] sys_ni_syscall,
+ [197] sys_ni_syscall,
+ [__NR_pciconfig_read] sys_ni_syscall, /* sys_pciconfig_read */
+ [__NR_pciconfig_write] sys_ni_syscall, /* sys_pciconfig_write */
+ [__NR_pciconfig_iobase] sys_ni_syscall, /* sys_pciconfig_iobase */
+ [__NR_multiplexer] sys_ni_syscall,
+ [__NR_getdents64] sys_getdents64,
+ [__NR_pivot_root] sys_pivot_root,
+ [204] sys_ni_syscall,
+ [__NR_madvise] sys_madvise,
+ [__NR_mincore] sys_mincore,
+ [__NR_gettid] sys_gettid,
+ [__NR_tkill] sys_tkill,
+ [__NR_setxattr] sys_setxattr,
+ [__NR_lsetxattr] sys_lsetxattr,
+ [__NR_fsetxattr] sys_fsetxattr,
+ [__NR_getxattr] sys_getxattr,
+ [__NR_lgetxattr] sys_lgetxattr,
+ [__NR_fgetxattr] sys_fgetxattr,
+ [__NR_listxattr] sys_listxattr,
+ [__NR_llistxattr] sys_llistxattr,
+ [__NR_flistxattr] sys_flistxattr,
+ [__NR_removexattr] sys_removexattr,
+ [__NR_lremovexattr] sys_lremovexattr,
+ [__NR_fremovexattr] sys_fremovexattr,
+ [__NR_futex] sys_futex,
+ [__NR_sched_setaffinity] sys_sched_setaffinity,
+ [__NR_sched_getaffinity] sys_sched_getaffinity,
+ [__NR_tuxcall] sys_ni_syscall,
+ [226] sys_ni_syscall,
+ [__NR_io_setup] sys_io_setup,
+ [__NR_io_destroy] sys_io_destroy,
+ [__NR_io_getevents] sys_io_getevents,
+ [__NR_io_submit] sys_io_submit,
+ [__NR_io_cancel] sys_io_cancel,
+ [__NR_set_tid_address] sys_ni_syscall, /* sys_set_tid_address */
+ [__NR_fadvise64] sys_fadvise64,
+ [__NR_exit_group] sys_ni_syscall, /* sys_exit_group */
+ [__NR_lookup_dcookie] sys_ni_syscall, /* sys_lookup_dcookie */
+ [__NR_epoll_create] sys_epoll_create,
+ [__NR_epoll_ctl] sys_epoll_ctl,
+ [__NR_epoll_wait] sys_epoll_wait,
+ [__NR_remap_file_pages] sys_remap_file_pages,
+ [__NR_timer_create] sys_timer_create,
+ [__NR_timer_settime] sys_timer_settime,
+ [__NR_timer_gettime] sys_timer_gettime,
+ [__NR_timer_getoverrun] sys_timer_getoverrun,
+ [__NR_timer_delete] sys_timer_delete,
+ [__NR_clock_settime] sys_clock_settime,
+ [__NR_clock_gettime] sys_clock_gettime,
+ [__NR_clock_getres] sys_clock_getres,
+ [__NR_clock_nanosleep] sys_clock_nanosleep,
+ [__NR_swapcontext] sys_ni_syscall, /* ppc64_swapcontext */
+ [__NR_tgkill] sys_tgkill,
+ [__NR_utimes] sys_utimes,
+ [__NR_statfs64] sys_statfs64,
+ [__NR_fstatfs64] sys_fstatfs64,
+ [254] sys_ni_syscall,
+ [__NR_rtas] ppc_rtas,
+ [256] sys_ni_syscall,
+ [257] sys_ni_syscall,
+ [258] sys_ni_syscall,
+ [__NR_mbind] sys_ni_syscall, /* sys_mbind */
+ [__NR_get_mempolicy] sys_ni_syscall, /* sys_get_mempolicy */
+ [__NR_set_mempolicy] sys_ni_syscall, /* sys_set_mempolicy */
+ [__NR_mq_open] sys_ni_syscall, /* sys_mq_open */
+ [__NR_mq_unlink] sys_ni_syscall, /* sys_mq_unlink */
+ [__NR_mq_timedsend] sys_ni_syscall, /* sys_mq_timedsend */
+ [__NR_mq_timedreceive] sys_ni_syscall, /* sys_mq_timedreceive */
+ [__NR_mq_notify] sys_ni_syscall, /* sys_mq_notify */
+ [__NR_mq_getsetattr] sys_ni_syscall, /* sys_mq_getsetattr */
+ [__NR_kexec_load] sys_ni_syscall, /* sys_kexec_load */
+ [__NR_add_key] sys_ni_syscall, /* sys_add_key */
+ [__NR_request_key] sys_ni_syscall, /* sys_request_key */
+ [__NR_keyctl] sys_ni_syscall, /* sys_keyctl */
+ [__NR_waitid] sys_ni_syscall, /* sys_waitid */
+ [__NR_ioprio_set] sys_ni_syscall, /* sys_ioprio_set */
+ [__NR_ioprio_get] sys_ni_syscall, /* sys_ioprio_get */
+ [__NR_inotify_init] sys_ni_syscall, /* sys_inotify_init */
+ [__NR_inotify_add_watch] sys_ni_syscall, /* sys_inotify_add_watch */
+ [__NR_inotify_rm_watch] sys_ni_syscall, /* sys_inotify_rm_watch */
+ [__NR_spu_run] sys_ni_syscall, /* sys_spu_run */
+ [__NR_spu_create] sys_ni_syscall, /* sys_spu_create */
+ [__NR_pselect6] sys_ni_syscall, /* sys_pselect */
+ [__NR_ppoll] sys_ni_syscall, /* sys_ppoll */
+ [__NR_unshare] sys_unshare,
+};
+
+long spu_sys_callback(struct spu_syscall_block *s)
+{
+ long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6);
+
+ BUILD_BUG_ON(ARRAY_SIZE(spu_syscall_table) != __NR_syscalls);
+
+ syscall = spu_syscall_table[s->nr_ret];
+
+ if (s->nr_ret >= __NR_syscalls) {
+ pr_debug("%s: invalid syscall #%ld", __FUNCTION__, s->nr_ret);
+ return -ENOSYS;
+ }
+
+#ifdef DEBUG
+ print_symbol(KERN_DEBUG "SPU-syscall %s:", (unsigned long)syscall);
+ printk("syscall%ld(%lx, %lx, %lx, %lx, %lx, %lx)\n",
+ s->nr_ret,
+ s->parm[0], s->parm[1], s->parm[2],
+ s->parm[3], s->parm[4], s->parm[5]);
+#endif
+
+ return syscall(s->parm[0], s->parm[1], s->parm[2],
+ s->parm[3], s->parm[4], s->parm[5]);
+}
+EXPORT_SYMBOL_GPL(spu_sys_callback);
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c
index a5c489a53c6..f1d35ddc9df 100644
--- a/arch/powerpc/platforms/cell/spufs/backing_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -285,6 +285,49 @@ static void spu_backing_runcntl_stop(struct spu_context *ctx)
spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP);
}
+static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask,
+ u32 mode)
+{
+ struct spu_problem_collapsed *prob = &ctx->csa.prob;
+ int ret;
+
+ spin_lock(&ctx->csa.register_lock);
+ ret = -EAGAIN;
+ if (prob->dma_querytype_RW)
+ goto out;
+ ret = 0;
+ /* FIXME: what are the side-effects of this? */
+ prob->dma_querymask_RW = mask;
+ prob->dma_querytype_RW = mode;
+out:
+ spin_unlock(&ctx->csa.register_lock);
+
+ return ret;
+}
+
+static u32 spu_backing_read_mfc_tagstatus(struct spu_context * ctx)
+{
+ return ctx->csa.prob.dma_tagstatus_R;
+}
+
+static u32 spu_backing_get_mfc_free_elements(struct spu_context *ctx)
+{
+ return ctx->csa.prob.dma_qstatus_R;
+}
+
+static int spu_backing_send_mfc_command(struct spu_context *ctx,
+ struct mfc_dma_command *cmd)
+{
+ int ret;
+
+ spin_lock(&ctx->csa.register_lock);
+ ret = -EAGAIN;
+ /* FIXME: set up priv2->puq */
+ spin_unlock(&ctx->csa.register_lock);
+
+ return ret;
+}
+
struct spu_context_ops spu_backing_ops = {
.mbox_read = spu_backing_mbox_read,
.mbox_stat_read = spu_backing_mbox_stat_read,
@@ -305,4 +348,8 @@ struct spu_context_ops spu_backing_ops = {
.get_ls = spu_backing_get_ls,
.runcntl_write = spu_backing_runcntl_write,
.runcntl_stop = spu_backing_runcntl_stop,
+ .set_mfc_query = spu_backing_set_mfc_query,
+ .read_mfc_tagstatus = spu_backing_read_mfc_tagstatus,
+ .get_mfc_free_elements = spu_backing_get_mfc_free_elements,
+ .send_mfc_command = spu_backing_send_mfc_command,
};
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 336f238102f..8bb33abfad1 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -27,7 +27,7 @@
#include <asm/spu_csa.h>
#include "spufs.h"
-struct spu_context *alloc_spu_context(struct address_space *local_store)
+struct spu_context *alloc_spu_context(void)
{
struct spu_context *ctx;
ctx = kmalloc(sizeof *ctx, GFP_KERNEL);
@@ -47,10 +47,17 @@ struct spu_context *alloc_spu_context(struct address_space *local_store)
init_waitqueue_head(&ctx->ibox_wq);
init_waitqueue_head(&ctx->wbox_wq);
init_waitqueue_head(&ctx->stop_wq);
+ init_waitqueue_head(&ctx->mfc_wq);
ctx->ibox_fasync = NULL;
ctx->wbox_fasync = NULL;
+ ctx->mfc_fasync = NULL;
+ ctx->mfc = NULL;
+ ctx->tagwait = 0;
ctx->state = SPU_STATE_SAVED;
- ctx->local_store = local_store;
+ ctx->local_store = NULL;
+ ctx->cntl = NULL;
+ ctx->signal1 = NULL;
+ ctx->signal2 = NULL;
ctx->spu = NULL;
ctx->ops = &spu_backing_ops;
ctx->owner = get_task_mm(current);
@@ -68,8 +75,6 @@ void destroy_spu_context(struct kref *kref)
ctx = container_of(kref, struct spu_context, kref);
down_write(&ctx->state_sema);
spu_deactivate(ctx);
- ctx->ibox_fasync = NULL;
- ctx->wbox_fasync = NULL;
up_write(&ctx->state_sema);
spu_fini_csa(&ctx->csa);
kfree(ctx);
@@ -109,7 +114,16 @@ void spu_release(struct spu_context *ctx)
void spu_unmap_mappings(struct spu_context *ctx)
{
- unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
+ if (ctx->local_store)
+ unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
+ if (ctx->mfc)
+ unmap_mapping_range(ctx->mfc, 0, 0x4000, 1);
+ if (ctx->cntl)
+ unmap_mapping_range(ctx->cntl, 0, 0x4000, 1);
+ if (ctx->signal1)
+ unmap_mapping_range(ctx->signal1, 0, 0x4000, 1);
+ if (ctx->signal2)
+ unmap_mapping_range(ctx->signal2, 0, 0x4000, 1);
}
int spu_acquire_runnable(struct spu_context *ctx)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index dfa649c9b95..366185e9266 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -20,6 +20,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#undef DEBUG
+
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/module.h>
@@ -39,8 +41,10 @@ static int
spufs_mem_open(struct inode *inode, struct file *file)
{
struct spufs_inode_info *i = SPUFS_I(inode);
- file->private_data = i->i_ctx;
- file->f_mapping = i->i_ctx->local_store;
+ struct spu_context *ctx = i->i_ctx;
+ file->private_data = ctx;
+ file->f_mapping = inode->i_mapping;
+ ctx->local_store = inode->i_mapping;
return 0;
}
@@ -84,7 +88,7 @@ spufs_mem_write(struct file *file, const char __user *buffer,
return ret;
}
-#ifdef CONFIG_SPARSEMEM
+#ifdef CONFIG_SPUFS_MMAP
static struct page *
spufs_mem_mmap_nopage(struct vm_area_struct *vma,
unsigned long address, int *type)
@@ -136,11 +140,113 @@ static struct file_operations spufs_mem_fops = {
.read = spufs_mem_read,
.write = spufs_mem_write,
.llseek = generic_file_llseek,
-#ifdef CONFIG_SPARSEMEM
+#ifdef CONFIG_SPUFS_MMAP
.mmap = spufs_mem_mmap,
#endif
};
+#ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
+ unsigned long address,
+ int *type, unsigned long ps_offs)
+{
+ struct page *page = NOPAGE_SIGBUS;
+ int fault_type = VM_FAULT_SIGBUS;
+ struct spu_context *ctx = vma->vm_file->private_data;
+ unsigned long offset = address - vma->vm_start;
+ unsigned long area;
+ int ret;
+
+ offset += vma->vm_pgoff << PAGE_SHIFT;
+ if (offset >= 0x4000)
+ goto out;
+
+ ret = spu_acquire_runnable(ctx);
+ if (ret)
+ goto out;
+
+ area = ctx->spu->problem_phys + ps_offs;
+ page = pfn_to_page((area + offset) >> PAGE_SHIFT);
+ fault_type = VM_FAULT_MINOR;
+ page_cache_get(page);
+
+ spu_release(ctx);
+
+ out:
+ if (type)
+ *type = fault_type;
+
+ return page;
+}
+
+static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
+{
+ return spufs_ps_nopage(vma, address, type, 0x4000);
+}
+
+static struct vm_operations_struct spufs_cntl_mmap_vmops = {
+ .nopage = spufs_cntl_mmap_nopage,
+};
+
+/*
+ * mmap support for problem state control area [0x4000 - 0x4fff].
+ * Mapping this area requires that the application have CAP_SYS_RAWIO,
+ * as these registers require special care when read/writing.
+ */
+static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ if (!(vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+ | _PAGE_NO_CACHE);
+
+ vma->vm_ops = &spufs_cntl_mmap_vmops;
+ return 0;
+}
+#endif
+
+static int spufs_cntl_open(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+
+ file->private_data = ctx;
+ file->f_mapping = inode->i_mapping;
+ ctx->cntl = inode->i_mapping;
+ return 0;
+}
+
+static ssize_t
+spufs_cntl_read(struct file *file, char __user *buffer,
+ size_t size, loff_t *pos)
+{
+ /* FIXME: read from spu status */
+ return -EINVAL;
+}
+
+static ssize_t
+spufs_cntl_write(struct file *file, const char __user *buffer,
+ size_t size, loff_t *pos)
+{
+ /* FIXME: write to runctl bit */
+ return -EINVAL;
+}
+
+static struct file_operations spufs_cntl_fops = {
+ .open = spufs_cntl_open,
+ .read = spufs_cntl_read,
+ .write = spufs_cntl_write,
+#ifdef CONFIG_SPUFS_MMAP
+ .mmap = spufs_cntl_mmap,
+#endif
+};
+
static int
spufs_regs_open(struct inode *inode, struct file *file)
{
@@ -501,6 +607,16 @@ static struct file_operations spufs_wbox_stat_fops = {
.read = spufs_wbox_stat_read,
};
+static int spufs_signal1_open(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+ file->private_data = ctx;
+ file->f_mapping = inode->i_mapping;
+ ctx->signal1 = inode->i_mapping;
+ return nonseekable_open(inode, file);
+}
+
static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
size_t len, loff_t *pos)
{
@@ -541,12 +657,50 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
return 4;
}
+#ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
+{
+ return spufs_ps_nopage(vma, address, type, 0x14000);
+}
+
+static struct vm_operations_struct spufs_signal1_mmap_vmops = {
+ .nopage = spufs_signal1_mmap_nopage,
+};
+
+static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ if (!(vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+ | _PAGE_NO_CACHE);
+
+ vma->vm_ops = &spufs_signal1_mmap_vmops;
+ return 0;
+}
+#endif
+
static struct file_operations spufs_signal1_fops = {
- .open = spufs_pipe_open,
+ .open = spufs_signal1_open,
.read = spufs_signal1_read,
.write = spufs_signal1_write,
+#ifdef CONFIG_SPUFS_MMAP
+ .mmap = spufs_signal1_mmap,
+#endif
};
+static int spufs_signal2_open(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+ file->private_data = ctx;
+ file->f_mapping = inode->i_mapping;
+ ctx->signal2 = inode->i_mapping;
+ return nonseekable_open(inode, file);
+}
+
static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
size_t len, loff_t *pos)
{
@@ -589,10 +743,39 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
return 4;
}
+#ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
+{
+ return spufs_ps_nopage(vma, address, type, 0x1c000);
+}
+
+static struct vm_operations_struct spufs_signal2_mmap_vmops = {
+ .nopage = spufs_signal2_mmap_nopage,
+};
+
+static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ if (!(vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+
+ /* FIXME: */
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+ | _PAGE_NO_CACHE);
+
+ vma->vm_ops = &spufs_signal2_mmap_vmops;
+ return 0;
+}
+#endif
+
static struct file_operations spufs_signal2_fops = {
- .open = spufs_pipe_open,
+ .open = spufs_signal2_open,
.read = spufs_signal2_read,
.write = spufs_signal2_write,
+#ifdef CONFIG_SPUFS_MMAP
+ .mmap = spufs_signal2_mmap,
+#endif
};
static void spufs_signal1_type_set(void *data, u64 val)
@@ -641,6 +824,332 @@ static u64 spufs_signal2_type_get(void *data)
DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
spufs_signal2_type_set, "%llu");
+#ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
+{
+ return spufs_ps_nopage(vma, address, type, 0x3000);
+}
+
+static struct vm_operations_struct spufs_mfc_mmap_vmops = {
+ .nopage = spufs_mfc_mmap_nopage,
+};
+
+/*
+ * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
+ * Mapping this area requires that the application have CAP_SYS_RAWIO,
+ * as these registers require special care when read/writing.
+ */
+static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ if (!(vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+ | _PAGE_NO_CACHE);
+
+ vma->vm_ops = &spufs_mfc_mmap_vmops;
+ return 0;
+}
+#endif
+
+static int spufs_mfc_open(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ struct spu_context *ctx = i->i_ctx;
+
+ /* we don't want to deal with DMA into other processes */
+ if (ctx->owner != current->mm)
+ return -EINVAL;
+
+ if (atomic_read(&inode->i_count) != 1)
+ return -EBUSY;
+
+ file->private_data = ctx;
+ return nonseekable_open(inode, file);
+}
+
+/* interrupt-level mfc callback function. */
+void spufs_mfc_callback(struct spu *spu)
+{
+ struct spu_context *ctx = spu->ctx;
+
+ wake_up_all(&ctx->mfc_wq);
+
+ pr_debug("%s %s\n", __FUNCTION__, spu->name);
+ if (ctx->mfc_fasync) {
+ u32 free_elements, tagstatus;
+ unsigned int mask;
+
+ /* no need for spu_acquire in interrupt context */
+ free_elements = ctx->ops->get_mfc_free_elements(ctx);
+ tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
+
+ mask = 0;
+ if (free_elements & 0xffff)
+ mask |= POLLOUT;
+ if (tagstatus & ctx->tagwait)
+ mask |= POLLIN;
+
+ kill_fasync(&ctx->mfc_fasync, SIGIO, mask);
+ }
+}
+
+static int spufs_read_mfc_tagstatus(struct spu_context *ctx, u32 *status)
+{
+ /* See if there is one tag group is complete */
+ /* FIXME we need locking around tagwait */
+ *status = ctx->ops->read_mfc_tagstatus(ctx) & ctx->tagwait;
+ ctx->tagwait &= ~*status;
+ if (*status)
+ return 1;
+
+ /* enable interrupt waiting for any tag group,
+ may silently fail if interrupts are already enabled */
+ ctx->ops->set_mfc_query(ctx, ctx->tagwait, 1);
+ return 0;
+}
+
+static ssize_t spufs_mfc_read(struct file *file, char __user *buffer,
+ size_t size, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ int ret = -EINVAL;
+ u32 status;
+
+ if (size != 4)
+ goto out;
+
+ spu_acquire(ctx);
+ if (file->f_flags & O_NONBLOCK) {
+ status = ctx->ops->read_mfc_tagstatus(ctx);
+ if (!(status & ctx->tagwait))
+ ret = -EAGAIN;
+ else
+ ctx->tagwait &= ~status;
+ } else {
+ ret = spufs_wait(ctx->mfc_wq,
+ spufs_read_mfc_tagstatus(ctx, &status));
+ }
+ spu_release(ctx);
+
+ if (ret)
+ goto out;
+
+ ret = 4;
+ if (copy_to_user(buffer, &status, 4))
+ ret = -EFAULT;
+
+out:
+ return ret;
+}
+
+static int spufs_check_valid_dma(struct mfc_dma_command *cmd)
+{
+ pr_debug("queueing DMA %x %lx %x %x %x\n", cmd->lsa,
+ cmd->ea, cmd->size, cmd->tag, cmd->cmd);
+
+ switch (cmd->cmd) {
+ case MFC_PUT_CMD:
+ case MFC_PUTF_CMD:
+ case MFC_PUTB_CMD:
+ case MFC_GET_CMD:
+ case MFC_GETF_CMD:
+ case MFC_GETB_CMD:
+ break;
+ default:
+ pr_debug("invalid DMA opcode %x\n", cmd->cmd);
+ return -EIO;
+ }
+
+ if ((cmd->lsa & 0xf) != (cmd->ea &0xf)) {
+ pr_debug("invalid DMA alignment, ea %lx lsa %x\n",
+ cmd->ea, cmd->lsa);
+ return -EIO;
+ }
+
+ switch (cmd->size & 0xf) {
+ case 1:
+ break;
+ case 2:
+ if (cmd->lsa & 1)
+ goto error;
+ break;
+ case 4:
+ if (cmd->lsa & 3)
+ goto error;
+ break;
+ case 8:
+ if (cmd->lsa & 7)
+ goto error;
+ break;
+ case 0:
+ if (cmd->lsa & 15)
+ goto error;
+ break;
+ error:
+ default:
+ pr_debug("invalid DMA alignment %x for size %x\n",
+ cmd->lsa & 0xf, cmd->size);
+ return -EIO;
+ }
+
+ if (cmd->size > 16 * 1024) {
+ pr_debug("invalid DMA size %x\n", cmd->size);
+ return -EIO;
+ }
+
+ if (cmd->tag & 0xfff0) {
+ /* we reserve the higher tag numbers for kernel use */
+ pr_debug("invalid DMA tag\n");
+ return -EIO;
+ }
+
+ if (cmd->class) {
+ /* not supported in this version */
+ pr_debug("invalid DMA class\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int spu_send_mfc_command(struct spu_context *ctx,
+ struct mfc_dma_command cmd,
+ int *error)
+{
+ *error = ctx->ops->send_mfc_command(ctx, &cmd);
+ if (*error == -EAGAIN) {
+ /* wait for any tag group to complete
+ so we have space for the new command */
+ ctx->ops->set_mfc_query(ctx, ctx->tagwait, 1);
+ /* try again, because the queue might be
+ empty again */
+ *error = ctx->ops->send_mfc_command(ctx, &cmd);
+ if (*error == -EAGAIN)
+ return 0;
+ }
+ return 1;
+}
+
+static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
+ size_t size, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ struct mfc_dma_command cmd;
+ int ret = -EINVAL;
+
+ if (size != sizeof cmd)
+ goto out;
+
+ ret = -EFAULT;
+ if (copy_from_user(&cmd, buffer, sizeof cmd))
+ goto out;
+
+ ret = spufs_check_valid_dma(&cmd);
+ if (ret)
+ goto out;
+
+ spu_acquire_runnable(ctx);
+ if (file->f_flags & O_NONBLOCK) {
+ ret = ctx->ops->send_mfc_command(ctx, &cmd);
+ } else {
+ int status;
+ ret = spufs_wait(ctx->mfc_wq,
+ spu_send_mfc_command(ctx, cmd, &status));
+ if (status)
+ ret = status;
+ }
+ spu_release(ctx);
+
+ if (ret)
+ goto out;
+
+ ctx->tagwait |= 1 << cmd.tag;
+
+out:
+ return ret;
+}
+
+static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait)
+{
+ struct spu_context *ctx = file->private_data;
+ u32 free_elements, tagstatus;
+ unsigned int mask;
+
+ spu_acquire(ctx);
+ ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2);
+ free_elements = ctx->ops->get_mfc_free_elements(ctx);
+ tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
+ spu_release(ctx);
+
+ poll_wait(file, &ctx->mfc_wq, wait);
+
+ mask = 0;
+ if (free_elements & 0xffff)
+ mask |= POLLOUT | POLLWRNORM;
+ if (tagstatus & ctx->tagwait)
+ mask |= POLLIN | POLLRDNORM;
+
+ pr_debug("%s: free %d tagstatus %d tagwait %d\n", __FUNCTION__,
+ free_elements, tagstatus, ctx->tagwait);
+
+ return mask;
+}
+
+static int spufs_mfc_flush(struct file *file)
+{
+ struct spu_context *ctx = file->private_data;
+ int ret;
+
+ spu_acquire(ctx);
+#if 0
+/* this currently hangs */
+ ret = spufs_wait(ctx->mfc_wq,
+ ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2));
+ if (ret)
+ goto out;
+ ret = spufs_wait(ctx->mfc_wq,
+ ctx->ops->read_mfc_tagstatus(ctx) == ctx->tagwait);
+out:
+#else
+ ret = 0;
+#endif
+ spu_release(ctx);
+
+ return ret;
+}
+
+static int spufs_mfc_fsync(struct file *file, struct dentry *dentry,
+ int datasync)
+{
+ return spufs_mfc_flush(file);
+}
+
+static int spufs_mfc_fasync(int fd, struct file *file, int on)
+{
+ struct spu_context *ctx = file->private_data;
+
+ return fasync_helper(fd, file, on, &ctx->mfc_fasync);
+}
+
+static struct file_operations spufs_mfc_fops = {
+ .open = spufs_mfc_open,
+ .read = spufs_mfc_read,
+ .write = spufs_mfc_write,
+ .poll = spufs_mfc_poll,
+ .flush = spufs_mfc_flush,
+ .fsync = spufs_mfc_fsync,
+ .fasync = spufs_mfc_fasync,
+#ifdef CONFIG_SPUFS_MMAP
+ .mmap = spufs_mfc_mmap,
+#endif
+};
+
static void spufs_npc_set(void *data, u64 val)
{
struct spu_context *ctx = data;
@@ -783,6 +1292,8 @@ struct tree_descr spufs_dir_contents[] = {
{ "signal2", &spufs_signal2_fops, 0666, },
{ "signal1_type", &spufs_signal1_type, 0666, },
{ "signal2_type", &spufs_signal2_type, 0666, },
+ { "mfc", &spufs_mfc_fops, 0666, },
+ { "cntl", &spufs_cntl_fops, 0666, },
{ "npc", &spufs_npc_ops, 0666, },
{ "fpcr", &spufs_fpcr_fops, 0666, },
{ "decr", &spufs_decr_ops, 0666, },
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
index 5445719bff7..a13a8b5a014 100644
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -232,6 +232,59 @@ static void spu_hw_runcntl_stop(struct spu_context *ctx)
spin_unlock_irq(&ctx->spu->register_lock);
}
+static int spu_hw_set_mfc_query(struct spu_context * ctx, u32 mask, u32 mode)
+{
+ struct spu_problem *prob = ctx->spu->problem;
+ int ret;
+
+ spin_lock_irq(&ctx->spu->register_lock);
+ ret = -EAGAIN;
+ if (in_be32(&prob->dma_querytype_RW))
+ goto out;
+ ret = 0;
+ out_be32(&prob->dma_querymask_RW, mask);
+ out_be32(&prob->dma_querytype_RW, mode);
+out:
+ spin_unlock_irq(&ctx->spu->register_lock);
+ return ret;
+}
+
+static u32 spu_hw_read_mfc_tagstatus(struct spu_context * ctx)
+{
+ return in_be32(&ctx->spu->problem->dma_tagstatus_R);
+}
+
+static u32 spu_hw_get_mfc_free_elements(struct spu_context *ctx)
+{
+ return in_be32(&ctx->spu->problem->dma_qstatus_R);
+}
+
+static int spu_hw_send_mfc_command(struct spu_context *ctx,
+ struct mfc_dma_command *cmd)
+{
+ u32 status;
+ struct spu_problem *prob = ctx->spu->problem;
+
+ spin_lock_irq(&ctx->spu->register_lock);
+ out_be32(&prob->mfc_lsa_W, cmd->lsa);
+ out_be64(&prob->mfc_ea_W, cmd->ea);
+ out_be32(&prob->mfc_union_W.by32.mfc_size_tag32,
+ cmd->size << 16 | cmd->tag);
+ out_be32(&prob->mfc_union_W.by32.mfc_class_cmd32,
+ cmd->class << 16 | cmd->cmd);
+ status = in_be32(&prob->mfc_union_W.by32.mfc_class_cmd32);
+ spin_unlock_irq(&ctx->spu->register_lock);
+
+ switch (status & 0xffff) {
+ case 0:
+ return 0;
+ case 2:
+ return -EAGAIN;
+ default:
+ return -EINVAL;
+ }
+}
+
struct spu_context_ops spu_hw_ops = {
.mbox_read = spu_hw_mbox_read,
.mbox_stat_read = spu_hw_mbox_stat_read,
@@ -252,4 +305,8 @@ struct spu_context_ops spu_hw_ops = {
.get_ls = spu_hw_get_ls,
.runcntl_write = spu_hw_runcntl_write,
.runcntl_stop = spu_hw_runcntl_stop,
+ .set_mfc_query = spu_hw_set_mfc_query,
+ .read_mfc_tagstatus = spu_hw_read_mfc_tagstatus,
+ .get_mfc_free_elements = spu_hw_get_mfc_free_elements,
+ .send_mfc_command = spu_hw_send_mfc_command,
};
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index b3962c3a034..d9554199afa 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -103,7 +103,7 @@ spufs_setattr(struct dentry *dentry, struct iattr *attr)
static int
spufs_new_file(struct super_block *sb, struct dentry *dentry,
- struct file_operations *fops, int mode,
+ const struct file_operations *fops, int mode,
struct spu_context *ctx)
{
static struct inode_operations spufs_file_iops = {
@@ -241,7 +241,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
inode->i_gid = dir->i_gid;
inode->i_mode &= S_ISGID;
}
- ctx = alloc_spu_context(inode->i_mapping);
+ ctx = alloc_spu_context();
SPUFS_I(inode)->i_ctx = ctx;
if (!ctx)
goto out_iput;
@@ -442,7 +442,7 @@ static struct file_system_type spufs_type = {
.kill_sb = kill_litter_super,
};
-static int spufs_init(void)
+static int __init spufs_init(void)
{
int ret;
ret = -ENOMEM;
@@ -472,7 +472,7 @@ out:
}
module_init(spufs_init);
-static void spufs_exit(void)
+static void __exit spufs_exit(void)
{
spu_sched_exit();
unregister_spu_syscalls(&spufs_calls);
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 18ea8866c61..c04e078c0fe 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -76,6 +76,90 @@ static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc,
return 0;
}
+/*
+ * SPU syscall restarting is tricky because we violate the basic
+ * assumption that the signal handler is running on the interrupted
+ * thread. Here instead, the handler runs on PowerPC user space code,
+ * while the syscall was called from the SPU.
+ * This means we can only do a very rough approximation of POSIX
+ * signal semantics.
+ */
+int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret,
+ unsigned int *npc)
+{
+ int ret;
+
+ switch (*spu_ret) {
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ /*
+ * Enter the regular syscall restarting for
+ * sys_spu_run, then restart the SPU syscall
+ * callback.
+ */
+ *npc -= 8;
+ ret = -ERESTARTSYS;
+ break;
+ case -ERESTARTNOHAND:
+ case -ERESTART_RESTARTBLOCK:
+ /*
+ * Restart block is too hard for now, just return -EINTR
+ * to the SPU.
+ * ERESTARTNOHAND comes from sys_pause, we also return
+ * -EINTR from there.
+ * Assume that we need to be restarted ourselves though.
+ */
+ *spu_ret = -EINTR;
+ ret = -ERESTARTSYS;
+ break;
+ default:
+ printk(KERN_WARNING "%s: unexpected return code %ld\n",
+ __FUNCTION__, *spu_ret);
+ ret = 0;
+ }
+ return ret;
+}
+
+int spu_process_callback(struct spu_context *ctx)
+{
+ struct spu_syscall_block s;
+ u32 ls_pointer, npc;
+ char *ls;
+ long spu_ret;
+ int ret;
+
+ /* get syscall block from local store */
+ npc = ctx->ops->npc_read(ctx);
+ ls = ctx->ops->get_ls(ctx);
+ ls_pointer = *(u32*)(ls + npc);
+ if (ls_pointer > (LS_SIZE - sizeof(s)))
+ return -EFAULT;
+ memcpy(&s, ls + ls_pointer, sizeof (s));
+
+ /* do actual syscall without pinning the spu */
+ ret = 0;
+ spu_ret = -ENOSYS;
+ npc += 4;
+
+ if (s.nr_ret < __NR_syscalls) {
+ spu_release(ctx);
+ /* do actual system call from here */
+ spu_ret = spu_sys_callback(&s);
+ if (spu_ret <= -ERESTARTSYS) {
+ ret = spu_handle_restartsys(ctx, &spu_ret, &npc);
+ }
+ spu_acquire(ctx);
+ if (ret == -ERESTARTSYS)
+ return ret;
+ }
+
+ /* write result, jump over indirect pointer */
+ memcpy(ls + ls_pointer, &spu_ret, sizeof (spu_ret));
+ ctx->ops->npc_write(ctx, npc);
+ ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
+ return ret;
+}
+
static inline int spu_process_events(struct spu_context *ctx)
{
struct spu *spu = ctx->spu;
@@ -107,6 +191,13 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status));
if (unlikely(ret))
break;
+ if ((*status & SPU_STATUS_STOPPED_BY_STOP) &&
+ (*status >> SPU_STOP_STATUS_SHIFT == 0x2104)) {
+ ret = spu_process_callback(ctx);
+ if (ret)
+ break;
+ *status &= ~SPU_STATUS_STOPPED_BY_STOP;
+ }
if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
ret = spu_reacquire_runnable(ctx, npc, status);
if (ret)
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 963182fbd1a..bf652cd7700 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -180,6 +180,7 @@ static inline void bind_context(struct spu *spu, struct spu_context *ctx)
spu->ibox_callback = spufs_ibox_callback;
spu->wbox_callback = spufs_wbox_callback;
spu->stop_callback = spufs_stop_callback;
+ spu->mfc_callback = spufs_mfc_callback;
mb();
spu_unmap_mappings(ctx);
spu_restore(&ctx->csa, spu);
@@ -197,6 +198,7 @@ static inline void unbind_context(struct spu *spu, struct spu_context *ctx)
spu->ibox_callback = NULL;
spu->wbox_callback = NULL;
spu->stop_callback = NULL;
+ spu->mfc_callback = NULL;
spu->mm = NULL;
spu->pid = 0;
spu->prio = MAX_PRIO;
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index db2601f0abd..4485738e210 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -43,7 +43,11 @@ struct spu_context {
struct spu *spu; /* pointer to a physical SPU */
struct spu_state csa; /* SPU context save area. */
spinlock_t mmio_lock; /* protects mmio access */
- struct address_space *local_store;/* local store backing store */
+ struct address_space *local_store; /* local store mapping. */
+ struct address_space *mfc; /* 'mfc' area mappings. */
+ struct address_space *cntl; /* 'control' area mappings. */
+ struct address_space *signal1; /* 'signal1' area mappings. */
+ struct address_space *signal2; /* 'signal2' area mappings. */
enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
struct rw_semaphore state_sema;
@@ -55,13 +59,27 @@ struct spu_context {
wait_queue_head_t ibox_wq;
wait_queue_head_t wbox_wq;
wait_queue_head_t stop_wq;
+ wait_queue_head_t mfc_wq;
struct fasync_struct *ibox_fasync;
struct fasync_struct *wbox_fasync;
+ struct fasync_struct *mfc_fasync;
+ u32 tagwait;
struct spu_context_ops *ops;
struct work_struct reap_work;
u64 flags;
};
+struct mfc_dma_command {
+ int32_t pad; /* reserved */
+ uint32_t lsa; /* local storage address */
+ uint64_t ea; /* effective address */
+ uint16_t size; /* transfer size */
+ uint16_t tag; /* command tag */
+ uint16_t class; /* class ID */
+ uint16_t cmd; /* command opcode */
+};
+
+
/* SPU context query/set operations. */
struct spu_context_ops {
int (*mbox_read) (struct spu_context * ctx, u32 * data);
@@ -84,6 +102,11 @@ struct spu_context_ops {
char*(*get_ls) (struct spu_context * ctx);
void (*runcntl_write) (struct spu_context * ctx, u32 data);
void (*runcntl_stop) (struct spu_context * ctx);
+ int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode);
+ u32 (*read_mfc_tagstatus)(struct spu_context * ctx);
+ u32 (*get_mfc_free_elements)(struct spu_context *ctx);
+ int (*send_mfc_command)(struct spu_context *ctx,
+ struct mfc_dma_command *cmd);
};
extern struct spu_context_ops spu_hw_ops;
@@ -106,7 +129,7 @@ long spufs_create_thread(struct nameidata *nd,
extern struct file_operations spufs_context_fops;
/* context management */
-struct spu_context * alloc_spu_context(struct address_space *local_store);
+struct spu_context * alloc_spu_context(void);
void destroy_spu_context(struct kref *kref);
struct spu_context * get_spu_context(struct spu_context *ctx);
int put_spu_context(struct spu_context *ctx);
@@ -159,5 +182,6 @@ size_t spu_ibox_read(struct spu_context *ctx, u32 *data);
void spufs_ibox_callback(struct spu *spu);
void spufs_wbox_callback(struct spu *spu);
void spufs_stop_callback(struct spu *spu);
+void spufs_mfc_callback(struct spu *spu);
#endif
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 212db28531f..97898d5d34e 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -2145,7 +2145,8 @@ static void init_priv1(struct spu_state *csa)
csa->priv1.int_mask_class1_RW = CLASS1_ENABLE_SEGMENT_FAULT_INTR |
CLASS1_ENABLE_STORAGE_FAULT_INTR;
csa->priv1.int_mask_class2_RW = CLASS2_ENABLE_SPU_STOP_INTR |
- CLASS2_ENABLE_SPU_HALT_INTR;
+ CLASS2_ENABLE_SPU_HALT_INTR |
+ CLASS2_ENABLE_SPU_DMA_TAG_GROUP_COMPLETE_INTR;
}
static void init_priv2(struct spu_state *csa)
diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h
index 814f54742e0..63f0aee4c15 100644
--- a/arch/powerpc/platforms/chrp/chrp.h
+++ b/arch/powerpc/platforms/chrp/chrp.h
@@ -8,4 +8,4 @@ extern int chrp_set_rtc_time(struct rtc_time *);
extern long chrp_time_init(void);
extern void chrp_find_bridges(void);
-extern void chrp_event_scan(void);
+extern void chrp_event_scan(unsigned long);
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 8bf4307e323..23a20171870 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -35,6 +35,7 @@
#include <linux/root_dev.h>
#include <linux/initrd.h>
#include <linux/module.h>
+#include <linux/timer.h>
#include <asm/io.h>
#include <asm/pgtable.h>
@@ -61,6 +62,10 @@ EXPORT_SYMBOL(_chrp_type);
struct mpic *chrp_mpic;
+/* Used for doing CHRP event-scans */
+DEFINE_PER_CPU(struct timer_list, heartbeat_timer);
+unsigned long event_scan_interval;
+
/*
* XXX this should be in xmon.h, but putting it there means xmon.h
* has to include <linux/interrupt.h> (to get irqreturn_t), which
@@ -229,8 +234,6 @@ void __init chrp_setup_arch(void)
{
struct device_node *root = find_path_device ("/");
char *machine = NULL;
- struct device_node *device;
- unsigned int *p = NULL;
/* init to some ~sane value until calibrate_delay() runs */
loops_per_jiffy = 50000000/HZ;
@@ -287,23 +290,12 @@ void __init chrp_setup_arch(void)
*/
sio_init();
- /* Get the event scan rate for the rtas so we know how
- * often it expects a heartbeat. -- Cort
- */
- device = find_devices("rtas");
- if (device)
- p = (unsigned int *) get_property
- (device, "rtas-event-scan-rate", NULL);
- if (p && *p) {
- ppc_md.heartbeat = chrp_event_scan;
- ppc_md.heartbeat_reset = HZ / (*p * 30) - 1;
- ppc_md.heartbeat_count = 1;
- printk("RTAS Event Scan Rate: %u (%lu jiffies)\n",
- *p, ppc_md.heartbeat_reset);
- }
-
pci_create_OF_bus_map();
+#ifdef CONFIG_SMP
+ smp_ops = &chrp_smp_ops;
+#endif /* CONFIG_SMP */
+
/*
* Print the banner, then scroll down so boot progress
* can be printed. -- Cort
@@ -312,7 +304,7 @@ void __init chrp_setup_arch(void)
}
void
-chrp_event_scan(void)
+chrp_event_scan(unsigned long unused)
{
unsigned char log[1024];
int ret = 0;
@@ -320,7 +312,8 @@ chrp_event_scan(void)
/* XXX: we should loop until the hardware says no more error logs -- Cort */
rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0,
__pa(log), 1024);
- ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+ mod_timer(&__get_cpu_var(heartbeat_timer),
+ jiffies + event_scan_interval);
}
/*
@@ -465,6 +458,9 @@ void __init chrp_init_IRQ(void)
void __init
chrp_init2(void)
{
+ struct device_node *device;
+ unsigned int *p = NULL;
+
#ifdef CONFIG_NVRAM
chrp_nvram_init();
#endif
@@ -476,12 +472,53 @@ chrp_init2(void)
request_region(0x80,0x10,"dma page reg");
request_region(0xc0,0x20,"dma2");
+ /* Get the event scan rate for the rtas so we know how
+ * often it expects a heartbeat. -- Cort
+ */
+ device = find_devices("rtas");
+ if (device)
+ p = (unsigned int *) get_property
+ (device, "rtas-event-scan-rate", NULL);
+ if (p && *p) {
+ /*
+ * Arrange to call chrp_event_scan at least *p times
+ * per minute. We use 59 rather than 60 here so that
+ * the rate will be slightly higher than the minimum.
+ * This all assumes we don't do hotplug CPU on any
+ * machine that needs the event scans done.
+ */
+ unsigned long interval, offset;
+ int cpu, ncpus;
+ struct timer_list *timer;
+
+ interval = HZ * 59 / *p;
+ offset = HZ;
+ ncpus = num_online_cpus();
+ event_scan_interval = ncpus * interval;
+ for (cpu = 0; cpu < ncpus; ++cpu) {
+ timer = &per_cpu(heartbeat_timer, cpu);
+ setup_timer(timer, chrp_event_scan, 0);
+ timer->expires = jiffies + offset;
+ add_timer_on(timer, cpu);
+ offset += interval;
+ }
+ printk("RTAS Event Scan Rate: %u (%lu jiffies)\n",
+ *p, interval);
+ }
+
if (ppc_md.progress)
ppc_md.progress(" Have fun! ", 0x7777);
}
-void __init chrp_init(void)
+static int __init chrp_probe(void)
{
+ char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
+ "device_type", NULL);
+ if (dtype == NULL)
+ return 0;
+ if (strcmp(dtype, "chrp"))
+ return 0;
+
ISA_DMA_THRESHOLD = ~0L;
DMA_MODE_READ = 0x44;
DMA_MODE_WRITE = 0x48;
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c
index 12c6f689b1a..7d788902693 100644
--- a/arch/powerpc/platforms/chrp/time.c
+++ b/arch/powerpc/platforms/chrp/time.c
@@ -120,33 +120,15 @@ int chrp_set_rtc_time(struct rtc_time *tmarg)
void chrp_get_rtc_time(struct rtc_time *tm)
{
unsigned int year, mon, day, hour, min, sec;
- int uip, i;
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
-
- /* Since the UIP flag is set for about 2.2 ms and the clock
- * is typically written with a precision of 1 jiffy, trying
- * to obtain a precision better than a few milliseconds is
- * an illusion. Only consistency is interesting, this also
- * allows to use the routine for /dev/rtc without a potential
- * 1 second kernel busy loop triggered by any reader of /dev/rtc.
- */
-
- for ( i = 0; i<1000000; i++) {
- uip = chrp_cmos_clock_read(RTC_FREQ_SELECT);
+ do {
sec = chrp_cmos_clock_read(RTC_SECONDS);
min = chrp_cmos_clock_read(RTC_MINUTES);
hour = chrp_cmos_clock_read(RTC_HOURS);
day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
mon = chrp_cmos_clock_read(RTC_MONTH);
year = chrp_cmos_clock_read(RTC_YEAR);
- uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT);
- if ((uip & RTC_UIP)==0) break;
- }
+ } while (sec != chrp_cmos_clock_read(RTC_SECONDS));
if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
BCD_TO_BIN(sec);
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index fa4550611c1..6ce8a404ba6 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -675,18 +675,20 @@ static void iseries_dedicated_idle(void)
void __init iSeries_init_IRQ(void) { }
#endif
-static int __init iseries_probe(int platform)
+static int __init iseries_probe(void)
{
- if (PLATFORM_ISERIES_LPAR != platform)
+ unsigned long root = of_get_flat_dt_root();
+ if (!of_flat_dt_is_compatible(root, "IBM,iSeries"))
return 0;
- ppc64_firmware_features |= FW_FEATURE_ISERIES;
- ppc64_firmware_features |= FW_FEATURE_LPAR;
+ powerpc_firmware_features |= FW_FEATURE_ISERIES;
+ powerpc_firmware_features |= FW_FEATURE_LPAR;
return 1;
}
-struct machdep_calls __initdata iseries_md = {
+define_machine(iseries) {
+ .name = "iSeries",
.setup_arch = iSeries_setup_arch,
.show_cpuinfo = iSeries_show_cpuinfo,
.init_IRQ = iSeries_init_IRQ,
@@ -930,7 +932,6 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
/* /chosen */
dt_start_node(dt, "chosen");
- dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR);
dt_prop_str(dt, "bootargs", cmd_line);
if (cmd_mem_limit)
dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit);
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index ec5c1e10c40..24c0aef4ea3 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -259,9 +259,10 @@ static void __init maple_progress(char *s, unsigned short hex)
/*
* Called very early, MMU is off, device-tree isn't unflattened
*/
-static int __init maple_probe(int platform)
+static int __init maple_probe(void)
{
- if (platform != PLATFORM_MAPLE)
+ unsigned long root = of_get_flat_dt_root();
+ if (!of_flat_dt_is_compatible(root, "Momentum,Maple"))
return 0;
/*
* On U3, the DART (iommu) must be allocated now since it
@@ -274,7 +275,8 @@ static int __init maple_probe(int platform)
return 1;
}
-struct machdep_calls __initdata maple_md = {
+define_machine(maple_md) {
+ .name = "Maple",
.probe = maple_probe,
.setup_arch = maple_setup_arch,
.init_early = maple_init_early,
@@ -290,7 +292,7 @@ struct machdep_calls __initdata maple_md = {
.get_rtc_time = maple_get_rtc_time,
.calibrate_decr = generic_calibrate_decr,
.progress = maple_progress,
- .idle_loop = native_idle,
+ .power_save = power4_idle,
#ifdef CONFIG_KEXEC
.machine_kexec = default_machine_kexec,
.machine_kexec_prepare = default_machine_kexec_prepare,
diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c
index 5e6981d1737..b9a2b3d4bf3 100644
--- a/arch/powerpc/platforms/maple/time.c
+++ b/arch/powerpc/platforms/maple/time.c
@@ -60,34 +60,14 @@ static void maple_clock_write(unsigned long val, int addr)
void maple_get_rtc_time(struct rtc_time *tm)
{
- int uip, i;
-
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
-
- /* Since the UIP flag is set for about 2.2 ms and the clock
- * is typically written with a precision of 1 jiffy, trying
- * to obtain a precision better than a few milliseconds is
- * an illusion. Only consistency is interesting, this also
- * allows to use the routine for /dev/rtc without a potential
- * 1 second kernel busy loop triggered by any reader of /dev/rtc.
- */
-
- for (i = 0; i<1000000; i++) {
- uip = maple_clock_read(RTC_FREQ_SELECT);
+ do {
tm->tm_sec = maple_clock_read(RTC_SECONDS);
tm->tm_min = maple_clock_read(RTC_MINUTES);
tm->tm_hour = maple_clock_read(RTC_HOURS);
tm->tm_mday = maple_clock_read(RTC_DAY_OF_MONTH);
tm->tm_mon = maple_clock_read(RTC_MONTH);
tm->tm_year = maple_clock_read(RTC_YEAR);
- uip |= maple_clock_read(RTC_FREQ_SELECT);
- if ((uip & RTC_UIP)==0)
- break;
- }
+ } while (tm->tm_sec != maple_clock_read(RTC_SECONDS));
if (!(maple_clock_read(RTC_CONTROL) & RTC_DM_BINARY)
|| RTC_ALWAYS_BCD) {
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c
index fa8b4d7b5de..eacbfd9beab 100644
--- a/arch/powerpc/platforms/powermac/bootx_init.c
+++ b/arch/powerpc/platforms/powermac/bootx_init.c
@@ -161,9 +161,7 @@ static void __init bootx_dt_add_prop(char *name, void *data, int size,
static void __init bootx_add_chosen_props(unsigned long base,
unsigned long *mem_end)
{
- u32 val = _MACH_Pmac;
-
- bootx_dt_add_prop("linux,platform", &val, 4, mem_end);
+ u32 val;
if (bootx_info->kernelParamsOffset) {
char *args = (char *)((unsigned long)bootx_info) +
@@ -493,7 +491,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4)
&& (strcmp(model, "iMac,1") == 0
|| strcmp(model, "PowerMac1,1") == 0)) {
bootx_printf("iMac,1 detected, shutting down USB \n");
- out_le32((unsigned *)0x80880008, 1); /* XXX */
+ out_le32((unsigned __iomem *)0x80880008, 1); /* XXX */
}
}
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c
index a415e8d2f7a..b57e465a1b7 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_64.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_64.c
@@ -21,6 +21,7 @@
#include <linux/cpufreq.h>
#include <linux/init.h>
#include <linux/completion.h>
+#include <linux/mutex.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/irq.h>
@@ -90,7 +91,7 @@ static void (*g5_switch_volt)(int speed_mode);
static int (*g5_switch_freq)(int speed_mode);
static int (*g5_query_freq)(void);
-static DECLARE_MUTEX(g5_switch_mutex);
+static DEFINE_MUTEX(g5_switch_mutex);
static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */
@@ -327,7 +328,7 @@ static int g5_cpufreq_target(struct cpufreq_policy *policy,
if (g5_pmode_cur == newstate)
return 0;
- down(&g5_switch_mutex);
+ mutex_lock(&g5_switch_mutex);
freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency;
freqs.new = g5_cpu_freqs[newstate].frequency;
@@ -337,7 +338,7 @@ static int g5_cpufreq_target(struct cpufreq_policy *policy,
rc = g5_switch_freq(newstate);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
- up(&g5_switch_mutex);
+ mutex_unlock(&g5_switch_mutex);
return rc;
}
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index e49eddd5042..a5063cd675c 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -2951,7 +2951,7 @@ static void *pmac_early_vresume_data;
void pmac_set_early_video_resume(void (*proc)(void *data), void *data)
{
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return;
preempt_disable();
pmac_early_vresume_proc = proc;
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 87eb6bb7f0e..e14f9ac55cf 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -1457,6 +1457,9 @@ int __init pmac_i2c_init(void)
return 0;
i2c_inited = 1;
+ if (!machine_is(powermac))
+ return 0;
+
/* Probe keywest-i2c busses */
kw_i2c_probe();
diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c
index 5fd28995c74..262f967b880 100644
--- a/arch/powerpc/platforms/powermac/nvram.c
+++ b/arch/powerpc/platforms/powermac/nvram.c
@@ -74,7 +74,7 @@ struct core99_header {
* Read and write the non-volatile RAM on PowerMacs and CHRP machines.
*/
static int nvram_naddrs;
-static volatile unsigned char *nvram_data;
+static volatile unsigned char __iomem *nvram_data;
static int is_core_99;
static int core99_bank = 0;
static int nvram_partitions[3];
@@ -148,7 +148,7 @@ static ssize_t core99_nvram_size(void)
}
#ifdef CONFIG_PPC32
-static volatile unsigned char *nvram_addr;
+static volatile unsigned char __iomem *nvram_addr;
static int nvram_mult;
static unsigned char direct_nvram_read_byte(int addr)
@@ -285,7 +285,7 @@ static int sm_erase_bank(int bank)
int stat, i;
unsigned long timeout;
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+ u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);
@@ -317,7 +317,7 @@ static int sm_write_bank(int bank, u8* datas)
int i, stat = 0;
unsigned long timeout;
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+ u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);
@@ -352,7 +352,7 @@ static int amd_erase_bank(int bank)
int i, stat = 0;
unsigned long timeout;
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+ u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
DBG("nvram: AMD Erasing bank %d...\n", bank);
@@ -399,7 +399,7 @@ static int amd_write_bank(int bank, u8* datas)
int i, stat = 0;
unsigned long timeout;
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+ u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
DBG("nvram: AMD Writing bank %d...\n", bank);
@@ -597,7 +597,7 @@ int __init pmac_nvram_init(void)
}
#ifdef CONFIG_PPC32
- if (_machine == _MACH_chrp && nvram_naddrs == 1) {
+ if (machine_is(chrp) && nvram_naddrs == 1) {
nvram_data = ioremap(r1.start, s1);
nvram_mult = 1;
ppc_md.nvram_read_val = direct_nvram_read_byte;
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index de3f30e6b33..f5d8d15d74f 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -1201,7 +1201,7 @@ void __init pmac_pcibios_after_init(void)
#ifdef CONFIG_PPC32
void pmac_pci_fixup_cardbus(struct pci_dev* dev)
{
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return;
/*
* Fix the interrupt routing on the various cardbus bridges
@@ -1244,8 +1244,9 @@ void pmac_pci_fixup_pciata(struct pci_dev* dev)
* On PowerMacs, we try to switch any PCI ATA controller to
* fully native mode
*/
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return;
+
/* Some controllers don't have the class IDE */
if (dev->vendor == PCI_VENDOR_ID_PROMISE)
switch(dev->device) {
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c
index 9b7150f1041..a3bd3e728fa 100644
--- a/arch/powerpc/platforms/powermac/pfunc_base.c
+++ b/arch/powerpc/platforms/powermac/pfunc_base.c
@@ -336,6 +336,8 @@ int __init pmac_pfunc_base_install(void)
return 0;
pfbase_inited = 1;
+ if (!machine_is(powermac))
+ return 0;
DBG("Installing base platform functions...\n");
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 385aab90c4d..4d15e396655 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -350,6 +350,13 @@ static void __init pmac_setup_arch(void)
smp_ops = &psurge_smp_ops;
#endif
#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_ADB
+ if (strstr(cmd_line, "adb_sync")) {
+ extern int __adb_probe_sync;
+ __adb_probe_sync = 1;
+ }
+#endif /* CONFIG_ADB */
}
char *bootpath;
@@ -576,30 +583,6 @@ pmac_halt(void)
pmac_power_off();
}
-#ifdef CONFIG_PPC32
-void __init pmac_init(void)
-{
- /* isa_io_base gets set in pmac_pci_init */
- isa_mem_base = PMAC_ISA_MEM_BASE;
- pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
- ISA_DMA_THRESHOLD = ~0L;
- DMA_MODE_READ = 1;
- DMA_MODE_WRITE = 2;
-
- ppc_md = pmac_md;
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
- ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
- ppc_ide_md.default_io_base = pmac_ide_get_base;
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
-#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
-
- if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
-
-}
-#endif
-
/*
* Early initialization.
*/
@@ -646,6 +629,12 @@ static int __init pmac_declare_of_platform_devices(void)
{
struct device_node *np;
+ if (machine_is(chrp))
+ return -1;
+
+ if (!machine_is(powermac))
+ return 0;
+
np = of_find_node_by_name(NULL, "valkyrie");
if (np)
of_platform_device_create(np, "valkyrie", NULL);
@@ -666,12 +655,15 @@ device_initcall(pmac_declare_of_platform_devices);
/*
* Called very early, MMU is off, device-tree isn't unflattened
*/
-static int __init pmac_probe(int platform)
+static int __init pmac_probe(void)
{
-#ifdef CONFIG_PPC64
- if (platform != PLATFORM_POWERMAC)
+ unsigned long root = of_get_flat_dt_root();
+
+ if (!of_flat_dt_is_compatible(root, "Power Macintosh") &&
+ !of_flat_dt_is_compatible(root, "MacRISC"))
return 0;
+#ifdef CONFIG_PPC64
/*
* On U3, the DART (iommu) must be allocated now since it
* has an impact on htab_initialize (due to the large page it
@@ -681,6 +673,23 @@ static int __init pmac_probe(int platform)
alloc_dart_table();
#endif
+#ifdef CONFIG_PPC32
+ /* isa_io_base gets set in pmac_pci_init */
+ isa_mem_base = PMAC_ISA_MEM_BASE;
+ pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
+ ISA_DMA_THRESHOLD = ~0L;
+ DMA_MODE_READ = 1;
+ DMA_MODE_WRITE = 2;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
+ ppc_ide_md.default_io_base = pmac_ide_get_base;
+#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
+
+#endif /* CONFIG_PPC32 */
+
#ifdef CONFIG_PMAC_SMU
/*
* SMU based G5s need some memory below 2Gb, at least the current
@@ -709,10 +718,8 @@ static int pmac_pci_probe_mode(struct pci_bus *bus)
}
#endif
-struct machdep_calls __initdata pmac_md = {
-#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
- .cpu_die = generic_mach_cpu_die,
-#endif
+define_machine(powermac) {
+ .name = "PowerMac",
.probe = pmac_probe,
.setup_arch = pmac_setup_arch,
.init_early = pmac_init_early,
@@ -733,7 +740,7 @@ struct machdep_calls __initdata pmac_md = {
.progress = udbg_progress,
#ifdef CONFIG_PPC64
.pci_probe_mode = pmac_pci_probe_mode,
- .idle_loop = native_idle,
+ .power_save = power4_idle,
.enable_pmcs = power4_enable_pmcs,
#ifdef CONFIG_KEXEC
.machine_kexec = default_machine_kexec,
@@ -746,4 +753,7 @@ struct machdep_calls __initdata pmac_md = {
.pcibios_after_init = pmac_pcibios_after_init,
.phys_mem_access_prot = pci_phys_mem_access_prot,
#endif
+#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
+ .cpu_die = generic_mach_cpu_die,
+#endif
};
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index 5d9afa1fa02..890758aa966 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -336,10 +336,10 @@ static struct pmu_sleep_notifier time_sleep_notifier = {
*/
void __init pmac_calibrate_decr(void)
{
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && defined(CONFIG_ADB_PMU)
/* XXX why here? */
pmu_register_sleep_notifier(&time_sleep_notifier);
-#endif /* CONFIG_PM */
+#endif
generic_calibrate_decr();
diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c
index c4352a8db64..b4fa9f03b46 100644
--- a/arch/powerpc/platforms/powermac/udbg_scc.c
+++ b/arch/powerpc/platforms/powermac/udbg_scc.c
@@ -116,7 +116,7 @@ void udbg_scc_init(int force_scc)
/* Setup for 57600 8N1 */
if (ch == ch_a)
addr += 0x20;
- sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
+ sccc = ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
sccc += addr & ~PAGE_MASK;
sccd = sccc + 0x10;
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 2ab9dcdfb41..9b2b1cb117b 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -1018,7 +1018,7 @@ static int __init eeh_init_proc(void)
{
struct proc_dir_entry *e;
- if (platform_is_pseries()) {
+ if (machine_is(pseries)) {
e = create_proc_entry("ppc64/eeh", 0, NULL);
if (e)
e->proc_fops = &proc_eeh_operations;
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index b811d5ff92f..cc2495a0cdd 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -257,6 +257,7 @@ void handle_eeh_events (struct eeh_event *event)
struct pci_bus *frozen_bus;
int rc = 0;
enum pci_ers_result result = PCI_ERS_RESULT_NONE;
+ const char *pci_str, *drv_str;
frozen_dn = find_device_pe(event->dn);
frozen_bus = pcibios_find_pci_bus(frozen_dn);
@@ -291,6 +292,13 @@ void handle_eeh_events (struct eeh_event *event)
frozen_pdn = PCI_DN(frozen_dn);
frozen_pdn->eeh_freeze_count++;
+
+ pci_str = pci_name (frozen_pdn->pcidev);
+ drv_str = pcid_name (frozen_pdn->pcidev);
+ if (!pci_str) {
+ pci_str = pci_name (event->dev);
+ drv_str = pcid_name (event->dev);
+ }
if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
goto hard_fail;
@@ -306,9 +314,7 @@ void handle_eeh_events (struct eeh_event *event)
eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */);
printk(KERN_WARNING
"EEH: This PCI device has failed %d times since last reboot: %s - %s\n",
- frozen_pdn->eeh_freeze_count,
- pci_name (frozen_pdn->pcidev),
- pcid_name(frozen_pdn->pcidev));
+ frozen_pdn->eeh_freeze_count, drv_str, pci_str);
/* Walk the various device drivers attached to this slot through
* a reset sequence, giving each an opportunity to do what it needs
@@ -360,9 +366,7 @@ hard_fail:
"EEH: PCI device %s - %s has failed %d times \n"
"and has been permanently disabled. Please try reseating\n"
"this device or replacing it.\n",
- pci_name (frozen_pdn->pcidev),
- pcid_name(frozen_pdn->pcidev),
- frozen_pdn->eeh_freeze_count);
+ drv_str, pci_str, frozen_pdn->eeh_freeze_count);
eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
index 989f4bc136c..c01d8f0cbe6 100644
--- a/arch/powerpc/platforms/pseries/firmware.c
+++ b/arch/powerpc/platforms/pseries/firmware.c
@@ -91,7 +91,7 @@ void __init fw_feature_init(void)
continue;
/* we have a match */
- ppc64_firmware_features |=
+ powerpc_firmware_features |=
firmware_features_table[i].val;
break;
}
diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c
index 138e128a388..ba6befd9663 100644
--- a/arch/powerpc/platforms/pseries/hvconsole.c
+++ b/arch/powerpc/platforms/pseries/hvconsole.c
@@ -62,6 +62,11 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
unsigned long *lbuf = (unsigned long *) buf;
long ret;
+
+ /* hcall will ret H_PARAMETER if 'count' exceeds firmware max.*/
+ if (count > MAX_VIO_PUT_CHARS)
+ count = MAX_VIO_PUT_CHARS;
+
ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0],
lbuf[1]);
if (ret == H_Success)
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index 946ad59e335..e97e67f5e07 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -120,7 +120,7 @@ static void fixup_winbond_82c105(struct pci_dev* dev)
int i;
unsigned int reg;
- if (!platform_is_pseries())
+ if (!machine_is(pseries))
return;
printk("Using INTC for W82c105 IDE controller.\n");
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 44abdeb9ca0..6bfacc21708 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -28,6 +28,7 @@
#include <linux/pci.h>
#include <asm/pci-bridge.h>
#include <asm/ppc-pci.h>
+#include <asm/firmware.h>
static struct pci_bus *
find_bus_among_children(struct pci_bus *bus,
@@ -152,20 +153,24 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
void
pcibios_add_pci_devices(struct pci_bus * bus)
{
- int slotno, num;
+ int slotno, num, mode;
struct pci_dev *dev;
struct device_node *dn = pci_bus_to_OF_node(bus);
eeh_add_device_tree_early(dn);
- if (_machine == PLATFORM_PSERIES_LPAR) {
+ mode = PCI_PROBE_NORMAL;
+ if (ppc_md.pci_probe_mode)
+ mode = ppc_md.pci_probe_mode(bus);
+
+ if (mode == PCI_PROBE_DEVTREE) {
/* use ofdt-based probe */
of_scan_bus(dn, bus);
if (!list_empty(&bus->devices)) {
pcibios_fixup_new_pci_devices(bus, 0);
pci_bus_add_devices(bus);
}
- } else {
+ } else if (mode == PCI_PROBE_NORMAL) {
/* use legacy probe */
slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index b046bcf7443..9639c66b453 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -132,7 +132,7 @@ static int __init init_ras_IRQ(void)
of_node_put(np);
}
- return 1;
+ return 0;
}
__initcall(init_ras_IRQ);
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 86cfa6ecdcf..1773103354b 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -17,8 +17,9 @@
#include <linux/proc_fs.h>
#include <asm/prom.h>
-#include <asm/pSeries_reconfig.h>
+#include <asm/machdep.h>
#include <asm/uaccess.h>
+#include <asm/pSeries_reconfig.h>
@@ -94,16 +95,16 @@ static struct device_node *derive_parent(const char *path)
return parent;
}
-static struct notifier_block *pSeries_reconfig_chain;
+static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
int pSeries_reconfig_notifier_register(struct notifier_block *nb)
{
- return notifier_chain_register(&pSeries_reconfig_chain, nb);
+ return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb);
}
void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
{
- notifier_chain_unregister(&pSeries_reconfig_chain, nb);
+ blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
}
static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
@@ -131,7 +132,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
goto out_err;
}
- err = notifier_call_chain(&pSeries_reconfig_chain,
+ err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
PSERIES_RECONFIG_ADD, np);
if (err == NOTIFY_BAD) {
printk(KERN_ERR "Failed to add device node %s\n", path);
@@ -171,7 +172,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
remove_node_proc_entries(np);
- notifier_call_chain(&pSeries_reconfig_chain,
+ blocking_notifier_call_chain(&pSeries_reconfig_chain,
PSERIES_RECONFIG_REMOVE, np);
of_detach_node(np);
@@ -508,7 +509,7 @@ static int proc_ppc64_create_ofdt(void)
{
struct proc_dir_entry *ent;
- if (!platform_is_pseries())
+ if (!machine_is(pseries))
return 0;
ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL);
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
index a6f628d4c9d..fcc4d561a23 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -27,6 +27,7 @@
#include <asm/prom.h>
#include <asm/nvram.h>
#include <asm/atomic.h>
+#include <asm/machdep.h>
#if 0
#define DEBUG(A...) printk(KERN_ERR A)
@@ -481,7 +482,7 @@ static int __init rtas_init(void)
{
struct proc_dir_entry *entry;
- if (!platform_is_pseries())
+ if (!machine_is(pseries))
return 0;
/* No RTAS */
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 44d5c7fdcd9..b2fbf8ba8fb 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -81,8 +81,8 @@ extern void find_udbg_vterm(void);
int fwnmi_active; /* TRUE if an FWNMI handler is present */
-static void pseries_shared_idle(void);
-static void pseries_dedicated_idle(void);
+static void pseries_shared_idle_sleep(void);
+static void pseries_dedicated_idle_sleep(void);
struct mpic *pSeries_mpic;
@@ -236,14 +236,13 @@ static void __init pSeries_setup_arch(void)
vpa_init(boot_cpuid);
if (get_lppaca()->shared_proc) {
printk(KERN_INFO "Using shared processor idle loop\n");
- ppc_md.idle_loop = pseries_shared_idle;
+ ppc_md.power_save = pseries_shared_idle_sleep;
} else {
printk(KERN_INFO "Using dedicated idle loop\n");
- ppc_md.idle_loop = pseries_dedicated_idle;
+ ppc_md.power_save = pseries_dedicated_idle_sleep;
}
} else {
printk(KERN_INFO "Using default idle loop\n");
- ppc_md.idle_loop = default_idle;
}
if (firmware_has_feature(FW_FEATURE_LPAR))
@@ -373,156 +372,123 @@ static int pSeries_check_legacy_ioport(unsigned int baseport)
/*
* Called very early, MMU is off, device-tree isn't unflattened
*/
-extern struct machdep_calls pSeries_md;
-static int __init pSeries_probe(int platform)
+static int __init pSeries_probe_hypertas(unsigned long node,
+ const char *uname, int depth,
+ void *data)
{
- if (platform != PLATFORM_PSERIES &&
- platform != PLATFORM_PSERIES_LPAR)
- return 0;
-
- /* if we have some ppc_md fixups for LPAR to do, do
- * it here ...
- */
+ if (depth != 1 ||
+ (strcmp(uname, "rtas") != 0 && strcmp(uname, "rtas@0") != 0))
+ return 0;
- if (platform == PLATFORM_PSERIES_LPAR)
- ppc64_firmware_features |= FW_FEATURE_LPAR;
+ if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL)
+ powerpc_firmware_features |= FW_FEATURE_LPAR;
- return 1;
+ return 1;
}
-DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
-
-static inline void dedicated_idle_sleep(unsigned int cpu)
+static int __init pSeries_probe(void)
{
- struct lppaca *plppaca = &lppaca[cpu ^ 1];
+ char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
+ "device_type", NULL);
+ if (dtype == NULL)
+ return 0;
+ if (strcmp(dtype, "chrp"))
+ return 0;
- /* Only sleep if the other thread is not idle */
- if (!(plppaca->idle)) {
- local_irq_disable();
+ DBG("pSeries detected, looking for LPAR capability...\n");
- /*
- * We are about to sleep the thread and so wont be polling any
- * more.
- */
- clear_thread_flag(TIF_POLLING_NRFLAG);
- smp_mb__after_clear_bit();
-
- /*
- * SMT dynamic mode. Cede will result in this thread going
- * dormant, if the partner thread is still doing work. Thread
- * wakes up if partner goes idle, an interrupt is presented, or
- * a prod occurs. Returning from the cede enables external
- * interrupts.
- */
- if (!need_resched())
- cede_processor();
- else
- local_irq_enable();
- set_thread_flag(TIF_POLLING_NRFLAG);
- } else {
- /*
- * Give the HV an opportunity at the processor, since we are
- * not doing any work.
- */
- poll_pending();
- }
+ /* Now try to figure out if we are running on LPAR */
+ of_scan_flat_dt(pSeries_probe_hypertas, NULL);
+
+ DBG("Machine is%s LPAR !\n",
+ (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
+
+ return 1;
}
-static void pseries_dedicated_idle(void)
+
+DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
+
+static void pseries_dedicated_idle_sleep(void)
{
unsigned int cpu = smp_processor_id();
unsigned long start_snooze;
unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
- set_thread_flag(TIF_POLLING_NRFLAG);
-
- while (1) {
- /*
- * Indicate to the HV that we are idle. Now would be
- * a good time to find other work to dispatch.
- */
- get_lppaca()->idle = 1;
-
- if (!need_resched()) {
- start_snooze = get_tb() +
- *smt_snooze_delay * tb_ticks_per_usec;
-
- while (!need_resched() && !cpu_is_offline(cpu)) {
- ppc64_runlatch_off();
-
- /*
- * Go into low thread priority and possibly
- * low power mode.
- */
- HMT_low();
- HMT_very_low();
-
- if (*smt_snooze_delay != 0 &&
- get_tb() > start_snooze) {
- HMT_medium();
- dedicated_idle_sleep(cpu);
- }
-
- }
-
- HMT_medium();
- }
-
- get_lppaca()->idle = 0;
- ppc64_runlatch_on();
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
+ /*
+ * Indicate to the HV that we are idle. Now would be
+ * a good time to find other work to dispatch.
+ */
+ get_lppaca()->idle = 1;
- if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
- cpu_die();
- }
-}
+ /*
+ * We come in with interrupts disabled, and need_resched()
+ * has been checked recently. If we should poll for a little
+ * while, do so.
+ */
+ if (*smt_snooze_delay) {
+ start_snooze = get_tb() +
+ *smt_snooze_delay * tb_ticks_per_usec;
+ local_irq_enable();
+ set_thread_flag(TIF_POLLING_NRFLAG);
-static void pseries_shared_idle(void)
-{
- unsigned int cpu = smp_processor_id();
+ while (get_tb() < start_snooze) {
+ if (need_resched() || cpu_is_offline(cpu))
+ goto out;
+ ppc64_runlatch_off();
+ HMT_low();
+ HMT_very_low();
+ }
- while (1) {
- /*
- * Indicate to the HV that we are idle. Now would be
- * a good time to find other work to dispatch.
- */
- get_lppaca()->idle = 1;
+ HMT_medium();
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+ smp_mb();
+ local_irq_disable();
+ if (need_resched() || cpu_is_offline(cpu))
+ goto out;
+ }
- while (!need_resched() && !cpu_is_offline(cpu)) {
- local_irq_disable();
- ppc64_runlatch_off();
+ /*
+ * Cede if the other thread is not idle, so that it can
+ * go single-threaded. If the other thread is idle,
+ * we ask the hypervisor if it has pending work it
+ * wants to do and cede if it does. Otherwise we keep
+ * polling in order to reduce interrupt latency.
+ *
+ * Doing the cede when the other thread is active will
+ * result in this thread going dormant, meaning the other
+ * thread gets to run in single-threaded (ST) mode, which
+ * is slightly faster than SMT mode with this thread at
+ * very low priority. The cede enables interrupts, which
+ * doesn't matter here.
+ */
+ if (!lppaca[cpu ^ 1].idle || poll_pending() == H_Pending)
+ cede_processor();
- /*
- * Yield the processor to the hypervisor. We return if
- * an external interrupt occurs (which are driven prior
- * to returning here) or if a prod occurs from another
- * processor. When returning here, external interrupts
- * are enabled.
- *
- * Check need_resched() again with interrupts disabled
- * to avoid a race.
- */
- if (!need_resched())
- cede_processor();
- else
- local_irq_enable();
-
- HMT_medium();
- }
+out:
+ HMT_medium();
+ get_lppaca()->idle = 0;
+}
- get_lppaca()->idle = 0;
- ppc64_runlatch_on();
+static void pseries_shared_idle_sleep(void)
+{
+ /*
+ * Indicate to the HV that we are idle. Now would be
+ * a good time to find other work to dispatch.
+ */
+ get_lppaca()->idle = 1;
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
+ /*
+ * Yield the processor to the hypervisor. We return if
+ * an external interrupt occurs (which are driven prior
+ * to returning here) or if a prod occurs from another
+ * processor. When returning here, external interrupts
+ * are enabled.
+ */
+ cede_processor();
- if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
- cpu_die();
- }
+ get_lppaca()->idle = 0;
}
static int pSeries_pci_probe_mode(struct pci_bus *bus)
@@ -553,7 +519,8 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
}
#endif
-struct machdep_calls __initdata pSeries_md = {
+define_machine(pseries) {
+ .name = "pSeries",
.probe = pSeries_probe,
.setup_arch = pSeries_setup_arch,
.init_early = pSeries_init_early,
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index eb86cdb9b80..4864cb32be2 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -500,7 +500,7 @@ nextnode:
np;
np = of_find_node_by_type(np, "cpu")) {
ireg = (uint *)get_property(np, "reg", &ilen);
- if (ireg && ireg[0] == boot_cpuid_phys) {
+ if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) {
ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s",
&ilen);
i = ilen / sizeof(int);
@@ -541,7 +541,7 @@ nextnode:
ops = &pSeriesLP_ops;
else {
#ifdef CONFIG_SMP
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
int hard_id;
/* FIXME: Do this dynamically! --RR */
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
index 49eb2a7e65c..a892356d5c3 100644
--- a/arch/ppc/8xx_io/cs4218_tdm.c
+++ b/arch/ppc/8xx_io/cs4218_tdm.c
@@ -126,11 +126,11 @@ static int numReadBufs = 4, readbufSize = 32;
*/
static volatile cbd_t *rx_base, *rx_cur, *tx_base, *tx_cur;
-MODULE_PARM(catchRadius, "i");
-MODULE_PARM(numBufs, "i");
-MODULE_PARM(bufSize, "i");
-MODULE_PARM(numreadBufs, "i");
-MODULE_PARM(readbufSize, "i");
+module_param(catchRadius, int, 0);
+module_param(numBufs, int, 0);
+module_param(bufSize, int, 0);
+module_param(numreadBufs, int, 0);
+module_param(readbufSize, int, 0);
#define arraysize(x) (sizeof(x)/sizeof(*(x)))
#define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff))
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 54a0a9bb12d..e9a8f5d1dfc 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -19,6 +19,10 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default y
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
@@ -57,15 +61,15 @@ config 6xx
select PPC_FPU
help
There are four types of PowerPC chips supported. The more common
- types (601, 603, 604, 740, 750, 7400), the Motorola embedded
- versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM
- embedded versions (403 and 405) and the POWER3 processor.
- (For support for more recent 64-bit processors, set ARCH=powerpc.)
+ types (601, 603, 604, 740, 750, 7400), the older Freescale
+ (formerly Motorola) embedded versions (821, 823, 850, 855, 860,
+ 52xx, 82xx, 83xx), the IBM embedded versions (403 and 405) and
+ the Book E embedded processors from IBM (44x) and Freescale (85xx).
+ For support for 64-bit processors, set ARCH=powerpc.
Unless you are building a kernel for one of the embedded processor
- systems or a POWER3-based IBM RS/6000, choose 6xx.
- Note that the kernel runs in 32-bit mode even on 64-bit chips.
- Also note that because the 52xx, 82xx, & 83xx family has a 603e core,
- specific support for that chipset is asked later on.
+ systems, choose 6xx.
+ Also note that because the 52xx, 82xx, & 83xx family have a 603e
+ core, specific support for that chipset is asked later on.
config 40x
bool "40x"
@@ -73,10 +77,6 @@ config 40x
config 44x
bool "44x"
-config POWER3
- select PPC_FPU
- bool "POWER3"
-
config 8xx
bool "8xx"
@@ -248,14 +248,9 @@ config PPC601_SYNC_FIX
source arch/ppc/platforms/4xx/Kconfig
source arch/ppc/platforms/85xx/Kconfig
-config PPC64BRIDGE
- bool
- depends on POWER3
- default y
-
config PPC_STD_MMU
bool
- depends on 6xx || POWER3
+ depends on 6xx
default y
config NOT_COHERENT_CACHE
@@ -530,8 +525,8 @@ endmenu
choice
prompt "Machine Type"
- depends on 6xx || POWER3
- default PPC_MULTIPLATFORM
+ depends on 6xx
+ default PPC_PREP
---help---
Linux currently supports several different kinds of PowerPC-based
machines: Apple Power Macintoshes and clones (such as the Motorola
@@ -541,15 +536,14 @@ choice
Platform) machines (including all of the recent IBM RS/6000 and
pSeries machines), and several embedded PowerPC systems containing
4xx, 6xx, 7xx, 8xx, 74xx, and 82xx processors. Currently, the
- default option is to build a kernel which works on PReP and CHRP.
+ default option is to build a kernel which works on PReP.
- Note that support for Apple machines is now only available with
- ARCH=powerpc, and has been removed from this menu. If you wish
- to build a kernel for an Apple machine, exit this configuration
- process and re-run it with ARCH=powerpc.
+ Note that support for Apple and CHRP machines is now only available
+ with ARCH=powerpc, and has been removed from this menu. If you
+ wish to build a kernel for an Apple or CHRP machine, exit this
+ configuration process and re-run it with ARCH=powerpc.
- Select CHRP/PReP if configuring for an IBM RS/6000 or
- pSeries machine, or a PReP machine.
+ Select PReP if configuring for a PReP machine.
Select Gemini if configuring for a Synergy Microsystems' Gemini
series Single Board Computer. More information is available at:
@@ -558,8 +552,8 @@ choice
Select APUS if configuring for a PowerUP Amiga. More information is
available at: <http://linux-apus.sourceforge.net/>.
-config PPC_MULTIPLATFORM
- bool "CHRP/PReP"
+config PPC_PREP
+ bool "PReP"
config APUS
bool "Amiga-APUS"
@@ -711,6 +705,13 @@ config LITE5200
much but it's only been tested on this board version. I think this
board is also known as IceCube.
+config LITE5200B
+ bool "Freescale LITE5200B"
+ depends LITE5200
+ help
+ Support for the LITE5200B dev board for the MPC5200 from Freescale.
+ This is the new board with 2 PCI slots.
+
config MPC834x_SYS
bool "Freescale MPC834x SYS"
help
@@ -796,25 +797,6 @@ config CPM2
you wish to build a kernel for a machine with a CPM2 coprocessor
on it (826x, 827x, 8560).
-config PPC_CHRP
- bool "Support for CHRP (Common Hardware Reference Platform) machines"
- depends on PPC_MULTIPLATFORM
- select PPC_I8259
- select PPC_INDIRECT_PCI
- default y
-
-config PPC_PREP
- bool "Support for PReP (PowerPC Reference Platform) machines"
- depends on PPC_MULTIPLATFORM
- select PPC_I8259
- select PPC_INDIRECT_PCI
- default y
-
-config PPC_OF
- bool
- depends on PPC_CHRP
- default y
-
config PPC_GEN550
bool
depends on SANDPOINT || SPRUCE || PPLUS || \
@@ -973,14 +955,6 @@ source "mm/Kconfig"
source "fs/Kconfig.binfmt"
-config PROC_DEVICETREE
- bool "Support for Open Firmware device tree in /proc"
- depends on PPC_OF && PROC_FS
- help
- This option adds a device-tree directory under /proc which contains
- an image of the device tree that the kernel copies from Open
- Firmware. If unsure, say Y here.
-
config PREP_RESIDUAL
bool "Support for PReP Residual Data"
depends on PPC_PREP
@@ -1173,8 +1147,7 @@ menu "Bus options"
config ISA
bool "Support for ISA-bus hardware"
- depends on PPC_PREP || PPC_CHRP
- select PPC_I8259
+ depends on PPC_PREP
help
Find out whether you have ISA slots on your motherboard. ISA is the
name of a bus system, i.e. the way the CPU talks to the other stuff
@@ -1184,18 +1157,18 @@ config ISA
config GENERIC_ISA_DMA
bool
- depends on POWER3 || 6xx && !CPM2
+ depends on 6xx && !CPM2
default y
config PPC_I8259
bool
- default y if 85xx
+ default y if 85xx || PPC_PREP
default n
config PPC_INDIRECT_PCI
bool
depends on PCI
- default y if 40x || 44x || 85xx || 83xx
+ default y if 40x || 44x || 85xx || 83xx || PPC_PREP
default n
config EISA
@@ -1386,7 +1359,7 @@ config CONSISTENT_SIZE
config BOOT_LOAD_BOOL
bool "Set the boot link/load address"
- depends on ADVANCED_OPTIONS && !PPC_MULTIPLATFORM
+ depends on ADVANCED_OPTIONS && !PPC_PREP
help
This option allows you to set the initial load address of the zImage
or zImage.initrd file. This can be useful if you are on a board
diff --git a/arch/ppc/Kconfig.debug b/arch/ppc/Kconfig.debug
index 8cc75abf3d8..f94b8774097 100644
--- a/arch/ppc/Kconfig.debug
+++ b/arch/ppc/Kconfig.debug
@@ -53,13 +53,6 @@ config BDI_SWITCH
Unless you are intending to debug the kernel with one of these
machines, say N here.
-config BOOTX_TEXT
- bool "Support for early boot text console (BootX or OpenFirmware only)"
- depends PPC_OF
- help
- Say Y here to see progress messages from the boot firmware in text
- mode. Requires either BootX or Open Firmware.
-
config SERIAL_TEXT_DEBUG
bool "Support for early boot texts over serial port"
depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index 98e940beeb3..0db66dcf072 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -40,10 +40,8 @@ ifndef CONFIG_FSL_BOOKE
CFLAGS += -mstring
endif
-cpu-as-$(CONFIG_PPC64BRIDGE) += -Wa,-mppc64bridge
cpu-as-$(CONFIG_4xx) += -Wa,-m405
cpu-as-$(CONFIG_6xx) += -Wa,-maltivec
-cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec
cpu-as-$(CONFIG_E500) += -Wa,-me500
cpu-as-$(CONFIG_E200) += -Wa,-me200
@@ -59,8 +57,6 @@ head-$(CONFIG_4xx) := arch/ppc/kernel/head_4xx.o
head-$(CONFIG_44x) := arch/ppc/kernel/head_44x.o
head-$(CONFIG_FSL_BOOKE) := arch/ppc/kernel/head_fsl_booke.o
-head-$(CONFIG_6xx) += arch/ppc/kernel/idle_6xx.o
-head-$(CONFIG_POWER4) += arch/ppc/kernel/idle_power4.o
head-$(CONFIG_PPC_FPU) += arch/powerpc/kernel/fpu.o
core-y += arch/ppc/kernel/ arch/powerpc/kernel/ \
@@ -71,7 +67,7 @@ core-y += arch/ppc/kernel/ arch/powerpc/kernel/ \
core-$(CONFIG_4xx) += arch/ppc/platforms/4xx/
core-$(CONFIG_83xx) += arch/ppc/platforms/83xx/
core-$(CONFIG_85xx) += arch/ppc/platforms/85xx/
-core-$(CONFIG_MATH_EMULATION) += arch/ppc/math-emu/
+core-$(CONFIG_MATH_EMULATION) += arch/powerpc/math-emu/
core-$(CONFIG_XMON) += arch/ppc/xmon/
core-$(CONFIG_APUS) += arch/ppc/amiga/
drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/
@@ -82,7 +78,7 @@ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm
-.PHONY: $(BOOT_TARGETS)
+PHONY += $(BOOT_TARGETS)
all: uImage zImage
diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile
index f565699a9fe..b739e25d472 100644
--- a/arch/ppc/boot/Makefile
+++ b/arch/ppc/boot/Makefile
@@ -1,3 +1,9 @@
+#
+# arch/ppc/boot/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
@@ -13,16 +19,15 @@ HOSTCFLAGS += -Iarch/$(ARCH)/boot/include
BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd
bootdir-y := simple
-bootdir-$(CONFIG_PPC_OF) += openfirmware
subdir-y := lib common images
-subdir-$(CONFIG_PPC_MULTIPLATFORM) += of1275
+subdir-$(CONFIG_PPC_PREP) += of1275
# for cleaning
-subdir- += simple openfirmware
+subdir- += simple
-hostprogs-y := $(addprefix utils/, addnote mknote hack-coff mkprep mkbugboot mktree)
+hostprogs-y := $(addprefix utils/, mkprep mkbugboot mktree)
-.PHONY: $(BOOT_TARGETS) $(bootdir-y)
+PHONY += $(BOOT_TARGETS) $(bootdir-y)
$(BOOT_TARGETS): $(bootdir-y)
diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile
deleted file mode 100644
index 2a411ec2e65..00000000000
--- a/arch/ppc/boot/openfirmware/Makefile
+++ /dev/null
@@ -1,106 +0,0 @@
-# Makefile for making bootable images on various OpenFirmware machines.
-#
-# Paul Mackerras January 1997
-# XCOFF bootable images for PowerMacs
-# Geert Uytterhoeven September 1997
-# ELF bootable iamges for CHRP machines.
-# Tom Rini January 2001
-# Cleaned up, moved into arch/ppc/boot/pmac
-# Tom Rini July/August 2002
-# Merged 'chrp' and 'pmac' into 'openfirmware', and cleaned up the
-# rules.
-
-zImage.initrd znetboot.initrd: del-ramdisk-sec := -R .ramdisk
-zImage.initrd znetboot.initrd: initrd := .initrd
-
-
-boot := arch/ppc/boot
-common := $(boot)/common
-utils := $(boot)/utils
-bootlib := $(boot)/lib
-of1275 := $(boot)/of1275
-images := $(boot)/images
-
-CHRP_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00800000
-
-COMMONOBJS := start.o misc.o common.o
-CHRPOBJS := crt0.o $(COMMONOBJS) chrpmain.o
-
-targets := $(CHRPOBJS) dummy.o
-CHRPOBJS := $(addprefix $(obj)/, $(CHRPOBJS))
-
-LIBS := lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a
-
-ifdef CONFIG_SMP
-END := .smp
-endif
-ifdef CONFIG_PPC64BRIDGE
-END += .64
-endif
-
-
-$(images)/ramdisk.image.gz:
- @echo ' MISSING $@'
- @echo ' RAM disk image must be provided separately'
- @/bin/false
-
-quiet_cmd_genimage = GEN $@
- cmd_genimage = $(OBJCOPY) -R .comment \
- --add-section=.image=$(images)/vmlinux.gz \
- --set-section-flags=.image=contents,alloc,load,readonly,data $< $@
-
-targets += image.o
-$(obj)/image.o: $(obj)/dummy.o $(images)/vmlinux.gz FORCE
- $(call if_changed,genimage)
-
-# Place the ramdisk in the initrd image.
-quiet_cmd_genimage-initrd = GEN $@
- cmd_genimage-initrd = $(OBJCOPY) $< $@ \
- --add-section=.ramdisk=$(images)/ramdisk.image.gz \
- --set-section-flags=.ramdisk=contents,alloc,load,readonly,data
-targets += image.initrd.o
-$(obj)/image.initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz FORCE
- $(call if_changed,genimage-initrd)
-
-
-targets += crt0.o
-$(obj)/crt0.o: $(common)/crt0.S FORCE
- $(call if_changed_dep,as_o_S)
-
-quiet_cmd_gen-chrp = CHRP $@
- cmd_gen-chrp = $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) $< $(LIBS) && \
- $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec)
-
-$(images)/zImage.chrp: $(obj)/image.o $(CHRPOBJS) $(LIBS) \
- $(srctree)/$(boot)/ld.script
- $(call cmd,gen-chrp)
-$(images)/zImage.initrd.chrp: $(obj)/image.initrd.o $(CHRPOBJS) $(LIBS) \
- $(srctree)/$(boot)/ld.script
- $(call cmd,gen-chrp)
-
-quiet_cmd_addnote = ADDNOTE $@
- cmd_addnote = cat $< > $@ && $(utils)/addnote $@
-$(images)/zImage.chrp-rs6k $(images)/zImage.initrd.chrp-rs6k: \
- %-rs6k: %
- $(call cmd,addnote)
-
-# The targets used on the make command-line
-
-.PHONY: zImage zImage.initrd
-zImage: $(images)/zImage.chrp \
- $(images)/zImage.chrp-rs6k
- @echo ' kernel: $@ is ready ($<)'
-zImage.initrd: $(images)/zImage.initrd.chrp \
- $(images)/zImage.initrd.chrp-rs6k
- @echo ' kernel: $@ is ready ($<)'
-
-TFTPIMAGE := /tftpboot/zImage
-
-.PHONY: znetboot znetboot.initrd
-znetboot: $(images)/zImage.chrp
- cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END)
- @echo ' kernel: $@ is ready ($<)'
-znetboot.initrd:$(images)/zImage.initrd.chrp
- cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END)
- @echo ' kernel: $@ is ready ($<)'
-
diff --git a/arch/ppc/boot/openfirmware/chrpmain.c b/arch/ppc/boot/openfirmware/chrpmain.c
deleted file mode 100644
index 245dbd9fc12..00000000000
--- a/arch/ppc/boot/openfirmware/chrpmain.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <linux/string.h>
-#include "nonstdio.h"
-#include "of1275.h"
-#include <asm/processor.h>
-#include <asm/page.h>
-
-/* Passed from the linker */
-extern char __image_begin, __image_end;
-extern char __ramdisk_begin, __ramdisk_end;
-extern char _start, _end;
-
-extern unsigned int heap_max;
-extern void flush_cache(void *, unsigned long);
-extern void gunzip(void *, int, unsigned char *, int *);
-extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
- unsigned int progend);
-
-char *avail_ram;
-char *begin_avail, *end_avail;
-char *avail_high;
-
-#define RAM_START 0x00000000
-#define RAM_END (64<<20)
-
-#define BOOT_START ((unsigned long)_start)
-#define BOOT_END ((unsigned long)(_end + 0xFFF) & ~0xFFF)
-
-#define RAM_FREE ((unsigned long)(_end+0x1000)&~0xFFF)
-#define PROG_START 0x00010000
-#define PROG_SIZE 0x007f0000 /* 8MB */
-
-#define SCRATCH_SIZE (128 << 10)
-
-static char scratch[SCRATCH_SIZE]; /* 128k of scratch space for gunzip */
-
-typedef void (*kernel_start_t)(int, int, void *, unsigned int, unsigned int);
-
-void
-boot(int a1, int a2, void *prom)
-{
- unsigned sa, len;
- void *dst;
- unsigned char *im;
- unsigned int initrd_size, initrd_start;
-
- printf("chrpboot starting: loaded at 0x%p\n\r", &_start);
-
- initrd_size = &__ramdisk_end - &__ramdisk_begin;
- if (initrd_size) {
- initrd_start = (RAM_END - initrd_size) & ~0xFFF;
- a1 = initrd_start;
- a2 = initrd_size;
- claim(initrd_start, RAM_END - initrd_start, 0);
- printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r",
- initrd_start, &__ramdisk_begin, initrd_size);
- memcpy((char *)initrd_start, &__ramdisk_begin, initrd_size);
- } else {
- initrd_start = 0;
- initrd_size = 0;
- a2 = 0xdeadbeef;
- }
-
- im = &__image_begin;
- len = &__image_end - &__image_begin;
- /* claim 4MB starting at PROG_START */
- claim(PROG_START, PROG_SIZE - PROG_START, 0);
- dst = (void *) PROG_START;
- if (im[0] == 0x1f && im[1] == 0x8b) {
- avail_ram = scratch;
- begin_avail = avail_high = avail_ram;
- end_avail = scratch + sizeof(scratch);
- printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len);
- gunzip(dst, PROG_SIZE - PROG_START, im, &len);
- printf("done %u bytes\n\r", len);
- printf("%u bytes of heap consumed, max in use %u\n\r",
- avail_high - begin_avail, heap_max);
- } else {
- memmove(dst, im, len);
- }
-
- flush_cache(dst, len);
- make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_chrp,
- (PROG_START + PROG_SIZE));
-
- sa = PROG_START;
- printf("start address = 0x%x\n\r", sa);
-
- (*(kernel_start_t)sa)(a1, a2, prom, initrd_start, initrd_size);
-
- printf("returned?\n\r");
-
- pause();
-}
diff --git a/arch/ppc/boot/openfirmware/common.c b/arch/ppc/boot/openfirmware/common.c
deleted file mode 100644
index 0f46756a903..00000000000
--- a/arch/ppc/boot/openfirmware/common.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include "nonstdio.h"
-#include "of1275.h"
-#include <linux/string.h>
-#include <linux/zlib.h>
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-
-/* Information from the linker */
-
-extern int strcmp(const char *s1, const char *s2);
-extern char *avail_ram, *avail_high;
-extern char *end_avail;
-
-unsigned int heap_use, heap_max;
-
-struct memchunk {
- unsigned int size;
- struct memchunk *next;
-};
-
-static struct memchunk *freechunks;
-
-static void *zalloc(unsigned size)
-{
- void *p;
- struct memchunk **mpp, *mp;
-
- size = (size + 7) & -8;
- heap_use += size;
- if (heap_use > heap_max)
- heap_max = heap_use;
- for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
- if (mp->size == size) {
- *mpp = mp->next;
- return mp;
- }
- }
- p = avail_ram;
- avail_ram += size;
- if (avail_ram > avail_high)
- avail_high = avail_ram;
- if (avail_ram > end_avail) {
- printf("oops... out of memory\n\r");
- pause();
- }
- return p;
-}
-
-#define HEAD_CRC 2
-#define EXTRA_FIELD 4
-#define ORIG_NAME 8
-#define COMMENT 0x10
-#define RESERVED 0xe0
-
-void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
-{
- z_stream s;
- int r, i, flags;
-
- /* skip header */
- i = 10;
- flags = src[3];
- if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
- printf("bad gzipped data\n\r");
- exit();
- }
- if ((flags & EXTRA_FIELD) != 0)
- i = 12 + src[10] + (src[11] << 8);
- if ((flags & ORIG_NAME) != 0)
- while (src[i++] != 0)
- ;
- if ((flags & COMMENT) != 0)
- while (src[i++] != 0)
- ;
- if ((flags & HEAD_CRC) != 0)
- i += 2;
- if (i >= *lenp) {
- printf("gunzip: ran out of data in header\n\r");
- exit();
- }
-
- /* Initialize ourself. */
- s.workspace = zalloc(zlib_inflate_workspacesize());
- r = zlib_inflateInit2(&s, -MAX_WBITS);
- if (r != Z_OK) {
- printf("zlib_inflateInit2 returned %d\n\r", r);
- exit();
- }
- s.next_in = src + i;
- s.avail_in = *lenp - i;
- s.next_out = dst;
- s.avail_out = dstlen;
- r = zlib_inflate(&s, Z_FINISH);
- if (r != Z_OK && r != Z_STREAM_END) {
- printf("inflate returned %d msg: %s\n\r", r, s.msg);
- exit();
- }
- *lenp = s.next_out - (unsigned char *) dst;
- zlib_inflateEnd(&s);
-}
-
-/* Make a bi_rec in OF. We need to be passed a name for BI_BOOTLOADER_ID,
- * a machine type for BI_MACHTYPE, and the location where the end of the
- * bootloader is (PROG_START + PROG_SIZE)
- */
-void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
- unsigned long progend)
-{
- struct bi_record *rec;
-
-
- /* leave a 1MB gap then align to the next 1MB boundary */
- addr = _ALIGN(addr+ (1<<20) - 1, (1<<20));
- /* oldworld machine seem very unhappy about this. -- Tom */
- if (addr >= progend)
- claim(addr, 0x1000, 0);
-
- rec = (struct bi_record *)addr;
- rec->tag = BI_FIRST;
- rec->size = sizeof(struct bi_record);
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
- rec->tag = BI_BOOTLOADER_ID;
- sprintf( (char *)rec->data, name);
- rec->size = sizeof(struct bi_record) + strlen(name) + 1;
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
- rec->tag = BI_MACHTYPE;
- rec->data[0] = mach;
- rec->data[1] = 1;
- rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
- rec->tag = BI_LAST;
- rec->size = sizeof(struct bi_record);
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
-}
diff --git a/arch/ppc/boot/openfirmware/dummy.c b/arch/ppc/boot/openfirmware/dummy.c
deleted file mode 100644
index 31dbf45bf99..00000000000
--- a/arch/ppc/boot/openfirmware/dummy.c
+++ /dev/null
@@ -1,4 +0,0 @@
-int main(void)
-{
- return 0;
-}
diff --git a/arch/ppc/boot/openfirmware/misc.S b/arch/ppc/boot/openfirmware/misc.S
deleted file mode 100644
index ab9e897cadd..00000000000
--- a/arch/ppc/boot/openfirmware/misc.S
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
- .text
-
-/*
- * Use the BAT2 & 3 registers to map the 1st 16MB of RAM to
- * the address given as the 1st argument.
- */
- .globl setup_bats
-setup_bats:
- mfpvr 5
- rlwinm 5,5,16,16,31 /* r3 = 1 for 601, 4 for 604 */
- cmpwi 0,5,1
- li 0,0
- bne 4f
- mtibatl 3,0 /* invalidate BAT first */
- ori 3,3,4 /* set up BAT registers for 601 */
- li 4,0x7f
- mtibatu 2,3
- mtibatl 2,4
- oris 3,3,0x80
- oris 4,4,0x80
- mtibatu 3,3
- mtibatl 3,4
- b 5f
-4: mtdbatu 3,0 /* invalidate BATs first */
- mtibatu 3,0
- ori 3,3,0xff /* set up BAT registers for 604 */
- li 4,2
- mtdbatl 2,4
- mtdbatu 2,3
- mtibatl 2,4
- mtibatu 2,3
- oris 3,3,0x80
- oris 4,4,0x80
- mtdbatl 3,4
- mtdbatu 3,3
- mtibatl 3,4
- mtibatu 3,3
-5: sync
- isync
- blr
-
-/*
- * Flush the dcache and invalidate the icache for a range of addresses.
- *
- * flush_cache(addr, len)
- */
- .global flush_cache
-flush_cache:
- addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */
- rlwinm. 4,4,27,5,31
- mtctr 4
- beqlr
-1: dcbf 0,3
- icbi 0,3
- addi 3,3,0x20
- bdnz 1b
- sync
- isync
- blr
diff --git a/arch/ppc/boot/openfirmware/start.c b/arch/ppc/boot/openfirmware/start.c
deleted file mode 100644
index 1617a26956b..00000000000
--- a/arch/ppc/boot/openfirmware/start.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <stdarg.h>
-#include "of1275.h"
-
-extern int strlen(const char *s);
-extern void boot(int a1, int a2, void *prom);
-
-phandle stdin;
-phandle stdout;
-phandle stderr;
-
-void printk(char *fmt, ...);
-
-void
-start(int a1, int a2, void *promptr)
-{
- ofinit(promptr);
- if (ofstdio(&stdin, &stdout, &stderr))
- exit();
-
- boot(a1, a2, promptr);
- for (;;)
- exit();
-}
-
-int writestring(void *f, char *ptr, int nb)
-{
- int w = 0, i;
- char *ret = "\r";
-
- for (i = 0; i < nb; ++i) {
- if (ptr[i] == '\n') {
- if (i > w) {
- write(f, ptr + w, i - w);
- w = i;
- }
- write(f, ret, 1);
- }
- }
- if (w < nb)
- write(f, ptr + w, nb - w);
- return nb;
-}
-
-int
-putc(int c, void *f)
-{
- char ch = c;
-
- return writestring(f, &ch, 1) == 1? c: -1;
-}
-
-int
-putchar(int c)
-{
- return putc(c, stdout);
-}
-
-int
-fputs(char *str, void *f)
-{
- int n = strlen(str);
-
- return writestring(f, str, n) == n? 0: -1;
-}
-
-int
-readchar(void)
-{
- char ch;
-
- for (;;) {
- switch (read(stdin, &ch, 1)) {
- case 1:
- return ch;
- case -1:
- printk("read(stdin) returned -1\n");
- return -1;
- }
- }
-}
-
-static char line[256];
-static char *lineptr;
-static int lineleft;
-
-int
-getchar(void)
-{
- int c;
-
- if (lineleft == 0) {
- lineptr = line;
- for (;;) {
- c = readchar();
- if (c == -1 || c == 4)
- break;
- if (c == '\r' || c == '\n') {
- *lineptr++ = '\n';
- putchar('\n');
- break;
- }
- switch (c) {
- case 0177:
- case '\b':
- if (lineptr > line) {
- putchar('\b');
- putchar(' ');
- putchar('\b');
- --lineptr;
- }
- break;
- case 'U' & 0x1F:
- while (lineptr > line) {
- putchar('\b');
- putchar(' ');
- putchar('\b');
- --lineptr;
- }
- break;
- default:
- if (lineptr >= &line[sizeof(line) - 1])
- putchar('\a');
- else {
- putchar(c);
- *lineptr++ = c;
- }
- }
- }
- lineleft = lineptr - line;
- lineptr = line;
- }
- if (lineleft == 0)
- return -1;
- --lineleft;
- return *lineptr++;
-}
-
-extern int vsprintf(char *buf, const char *fmt, va_list args);
-static char sprint_buf[1024];
-
-void
-printk(char *fmt, ...)
-{
- va_list args;
- int n;
-
- va_start(args, fmt);
- n = vsprintf(sprint_buf, fmt, args);
- va_end(args);
- writestring(stdout, sprint_buf, n);
-}
-
-int
-printf(char *fmt, ...)
-{
- va_list args;
- int n;
-
- va_start(args, fmt);
- n = vsprintf(sprint_buf, fmt, args);
- va_end(args);
- writestring(stdout, sprint_buf, n);
- return n;
-}
diff --git a/arch/ppc/boot/simple/mpc10x_memory.c b/arch/ppc/boot/simple/mpc10x_memory.c
index c24290823f7..8da8f576031 100644
--- a/arch/ppc/boot/simple/mpc10x_memory.c
+++ b/arch/ppc/boot/simple/mpc10x_memory.c
@@ -50,10 +50,10 @@ MPC10X_PCI_OP(read, dword, u32 *, in_le32, 0)
* the system. This assumes that the firmware has correctly set up the memory
* controller registers. On CONFIG_PPC_PREP, we know we are being called
* under a PReP memory map. On all other machines, we assume we are under
- * a CHRP memory map. Further, on CONFIG_PPC_MULTIPLATFORM we must rename
+ * a CHRP memory map. Further, on CONFIG_PPC_PREP we must rename
* this function.
*/
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_PREP
#define get_mem_size mpc10x_get_mem_size
#endif
unsigned long
diff --git a/arch/ppc/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S
index 7efddc50756..2533113c1cc 100644
--- a/arch/ppc/boot/simple/relocate.S
+++ b/arch/ppc/boot/simple/relocate.S
@@ -194,7 +194,7 @@ start_ldr:
/*
* Start at the begining.
*/
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_PREP
li r9,0xc
mtlr r9
/* tell kernel we're prep, by putting 0xdeadc0de at KERNELLOAD,
diff --git a/arch/ppc/boot/utils/addnote.c b/arch/ppc/boot/utils/addnote.c
deleted file mode 100644
index 6c52b18f2d0..00000000000
--- a/arch/ppc/boot/utils/addnote.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Program to hack in a PT_NOTE program header entry in an ELF file.
- * This is needed for OF on RS/6000s to load an image correctly.
- * Note that OF needs a program header entry for the note, not an
- * ELF section.
- *
- * Copyright 2000 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.
- *
- * Usage: addnote zImage
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-
-char arch[] = "PowerPC";
-
-#define N_DESCR 6
-unsigned int descr[N_DESCR] = {
-#if 1
- /* values for IBM RS/6000 machines */
- 0xffffffff, /* real-mode = true */
- 0x00c00000, /* real-base, i.e. where we expect OF to be */
- 0xffffffff, /* real-size */
- 0xffffffff, /* virt-base */
- 0xffffffff, /* virt-size */
- 0x4000, /* load-base */
-#else
- /* values for longtrail CHRP */
- 0, /* real-mode = false */
- 0xffffffff, /* real-base */
- 0xffffffff, /* real-size */
- 0xffffffff, /* virt-base */
- 0xffffffff, /* virt-size */
- 0x00600000, /* load-base */
-#endif
-};
-
-unsigned char buf[512];
-
-#define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1]))
-#define GET_32BE(off) ((GET_16BE(off) << 16) + GET_16BE((off)+2))
-
-#define PUT_16BE(off, v) (buf[off] = ((v) >> 8) & 0xff, \
- buf[(off) + 1] = (v) & 0xff)
-#define PUT_32BE(off, v) (PUT_16BE((off), (v) >> 16), \
- PUT_16BE((off) + 2, (v)))
-
-/* Structure of an ELF file */
-#define E_IDENT 0 /* ELF header */
-#define E_PHOFF 28
-#define E_PHENTSIZE 42
-#define E_PHNUM 44
-#define E_HSIZE 52 /* size of ELF header */
-
-#define EI_MAGIC 0 /* offsets in E_IDENT area */
-#define EI_CLASS 4
-#define EI_DATA 5
-
-#define PH_TYPE 0 /* ELF program header */
-#define PH_OFFSET 4
-#define PH_FILESZ 16
-#define PH_HSIZE 32 /* size of program header */
-
-#define PT_NOTE 4 /* Program header type = note */
-
-#define ELFCLASS32 1
-#define ELFDATA2MSB 2
-
-unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
-
-int main(int ac, char **av)
-{
- int fd, n, i;
- int ph, ps, np;
- int nnote, ns;
-
- if (ac != 2) {
- fprintf(stderr, "Usage: %s elf-file\n", av[0]);
- exit(1);
- }
- fd = open(av[1], O_RDWR);
- if (fd < 0) {
- perror(av[1]);
- exit(1);
- }
-
- nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4;
-
- n = read(fd, buf, sizeof(buf));
- if (n < 0) {
- perror("read");
- exit(1);
- }
-
- if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0)
- goto notelf;
-
- if (buf[E_IDENT+EI_CLASS] != ELFCLASS32
- || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) {
- fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n",
- av[1]);
- exit(1);
- }
-
- ph = GET_32BE(E_PHOFF);
- ps = GET_16BE(E_PHENTSIZE);
- np = GET_16BE(E_PHNUM);
- if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
- goto notelf;
- if (ph + (np + 1) * ps + nnote > n)
- goto nospace;
-
- for (i = 0; i < np; ++i) {
- if (GET_32BE(ph + PH_TYPE) == PT_NOTE) {
- fprintf(stderr, "%s already has a note entry\n",
- av[1]);
- exit(0);
- }
- ph += ps;
- }
-
- /* XXX check that the area we want to use is all zeroes */
- for (i = 0; i < ps + nnote; ++i)
- if (buf[ph + i] != 0)
- goto nospace;
-
- /* fill in the program header entry */
- ns = ph + ps;
- PUT_32BE(ph + PH_TYPE, PT_NOTE);
- PUT_32BE(ph + PH_OFFSET, ns);
- PUT_32BE(ph + PH_FILESZ, nnote);
-
- /* fill in the note area we point to */
- /* XXX we should probably make this a proper section */
- PUT_32BE(ns, strlen(arch) + 1);
- PUT_32BE(ns + 4, N_DESCR * 4);
- PUT_32BE(ns + 8, 0x1275);
- strcpy(&buf[ns + 12], arch);
- ns += 12 + strlen(arch) + 1;
- for (i = 0; i < N_DESCR; ++i)
- PUT_32BE(ns + i * 4, descr[i]);
-
- /* Update the number of program headers */
- PUT_16BE(E_PHNUM, np + 1);
-
- /* write back */
- lseek(fd, (long) 0, SEEK_SET);
- i = write(fd, buf, n);
- if (i < 0) {
- perror("write");
- exit(1);
- }
- if (i < n) {
- fprintf(stderr, "%s: write truncated\n", av[1]);
- exit(1);
- }
-
- exit(0);
-
- notelf:
- fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]);
- exit(1);
-
- nospace:
- fprintf(stderr, "sorry, I can't find space in %s to put the note\n",
- av[0]);
- exit(1);
-}
diff --git a/arch/ppc/boot/utils/hack-coff.c b/arch/ppc/boot/utils/hack-coff.c
deleted file mode 100644
index 5e5a6573a1e..00000000000
--- a/arch/ppc/boot/utils/hack-coff.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * hack-coff.c - hack the header of an xcoff file to fill in
- * a few fields needed by the Open Firmware xcoff loader on
- * Power Macs but not initialized by objcopy.
- *
- * Copyright (C) Paul Mackerras 1997.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include "rs6000.h"
-
-#define AOUT_MAGIC 0x010b
-
-#define get_16be(x) ((((unsigned char *)(x))[0] << 8) \
- + ((unsigned char *)(x))[1])
-#define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \
- ((unsigned char *)(x))[1] = (v) & 0xff)
-#define get_32be(x) ((((unsigned char *)(x))[0] << 24) \
- + (((unsigned char *)(x))[1] << 16) \
- + (((unsigned char *)(x))[2] << 8) \
- + ((unsigned char *)(x))[3])
-
-int
-main(int ac, char **av)
-{
- int fd;
- int i, nsect;
- int aoutsz;
- struct external_filehdr fhdr;
- AOUTHDR aout;
- struct external_scnhdr shdr;
-
- if (ac != 2) {
- fprintf(stderr, "Usage: hack-coff coff-file\n");
- exit(1);
- }
- if ((fd = open(av[1], 2)) == -1) {
- perror(av[2]);
- exit(1);
- }
- if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr))
- goto readerr;
- i = get_16be(fhdr.f_magic);
- if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) {
- fprintf(stderr, "%s: not an xcoff file\n", av[1]);
- exit(1);
- }
- aoutsz = get_16be(fhdr.f_opthdr);
- if (read(fd, &aout, aoutsz) != aoutsz)
- goto readerr;
- nsect = get_16be(fhdr.f_nscns);
- for (i = 0; i < nsect; ++i) {
- if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr))
- goto readerr;
- if (strcmp(shdr.s_name, ".text") == 0) {
- put_16be(aout.o_snentry, i+1);
- put_16be(aout.o_sntext, i+1);
- } else if (strcmp(shdr.s_name, ".data") == 0) {
- put_16be(aout.o_sndata, i+1);
- } else if (strcmp(shdr.s_name, ".bss") == 0) {
- put_16be(aout.o_snbss, i+1);
- }
- }
- put_16be(aout.magic, AOUT_MAGIC);
- if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1
- || write(fd, &aout, aoutsz) != aoutsz) {
- fprintf(stderr, "%s: write error\n", av[1]);
- exit(1);
- }
- close(fd);
- exit(0);
-
-readerr:
- fprintf(stderr, "%s: read error or file too short\n", av[1]);
- exit(1);
-}
diff --git a/arch/ppc/boot/utils/mknote.c b/arch/ppc/boot/utils/mknote.c
deleted file mode 100644
index b9fbb2cbfc8..00000000000
--- a/arch/ppc/boot/utils/mknote.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) Cort Dougan 1999.
- *
- * 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.
- *
- * Generate a note section as per the CHRP specification.
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff );
-
-int main(void)
-{
-/* header */
- /* namesz */
- PL(strlen("PowerPC")+1);
- /* descrsz */
- PL(6*4);
- /* type */
- PL(0x1275);
- /* name */
- printf("PowerPC"); printf("%c", 0);
-
-/* descriptor */
- /* real-mode */
- PL(0xffffffff);
- /* real-base */
- PL(0x00c00000);
- /* real-size */
- PL(0xffffffff);
- /* virt-base */
- PL(0xffffffff);
- /* virt-size */
- PL(0xffffffff);
- /* load-base */
- PL(0x4000);
- return 0;
-}
diff --git a/arch/ppc/configs/ibmchrp_defconfig b/arch/ppc/configs/ibmchrp_defconfig
deleted file mode 100644
index 27f3e69c1f9..00000000000
--- a/arch/ppc/configs/ibmchrp_defconfig
+++ /dev/null
@@ -1,875 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_GENERIC_NVRAM=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-# CONFIG_STANDALONE is not set
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Processor
-#
-CONFIG_6xx=y
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_POWER4 is not set
-# CONFIG_8xx is not set
-# CONFIG_ALTIVEC is not set
-# CONFIG_TAU is not set
-# CONFIG_CPU_FREQ is not set
-# CONFIG_PPC601_SYNC_FIX is not set
-CONFIG_PPC_STD_MMU=y
-
-#
-# Platform options
-#
-CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_APUS is not set
-# CONFIG_WILLOW is not set
-# CONFIG_PCORE is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_EV64260 is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MCPN765 is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX6 is not set
-# CONFIG_TQM8260 is not set
-CONFIG_PPC_CHRP=y
-CONFIG_PPC_PMAC=y
-CONFIG_PPC_PREP=y
-CONFIG_PPC_OF=y
-CONFIG_PPCBUG_NVRAM=y
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-CONFIG_HIGHMEM=y
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_PROC_DEVICETREE=y
-CONFIG_PPC_RTAS=y
-# CONFIG_PREP_RESIDUAL is not set
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# Bus options
-#
-CONFIG_ISA=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_HIGHMEM_START=0xfe000000
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE=0x80000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_LBD=y
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-CONFIG_SCSI_SPI_ATTRS=y
-# CONFIG_SCSI_FC_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
-# CONFIG_SCSI_MAC53C94 is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_ADB is not set
-# CONFIG_ADB_CUDA is not set
-# CONFIG_ADB_PMU is not set
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_QUEUE is not set
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-# CONFIG_IP_NF_MATCH_PKTTYPE is not set
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_MANGLE is not set
-# CONFIG_IP_NF_TARGET_LOG is not set
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=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 is not set
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_RAW=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=y
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_CS89x0 is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_INPORT is not set
-# CONFIG_MOUSE_LOGIBM is not set
-# CONFIG_MOUSE_PC110PAD is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-# CONFIG_SERIAL_8250_CONSOLE is not set
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-# CONFIG_SERIAL_PMACZILOG is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_OF=y
-# CONFIG_FB_CONTROL is not set
-# CONFIG_FB_PLATINUM is not set
-# CONFIG_FB_VALKYRIE is not set
-# CONFIG_FB_CT65550 is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_RIVA is not set
-CONFIG_FB_MATROX=y
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-# CONFIG_FB_MATROX_G450 is not set
-CONFIG_FB_MATROX_G100A=y
-CONFIG_FB_MATROX_G100=y
-# CONFIG_FB_MATROX_MULTIHEAD is not set
-# CONFIG_FB_RADEON_OLD is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-CONFIG_FB_3DFX=y
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-# CONFIG_NFS_FS is not set
-# CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# 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_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Library routines
-#
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_BOOTX_TEXT is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/pmac_defconfig b/arch/ppc/configs/pmac_defconfig
deleted file mode 100644
index a2db8b541c9..00000000000
--- a/arch/ppc/configs/pmac_defconfig
+++ /dev/null
@@ -1,1591 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc3
-# Wed Jul 13 14:13:13 2005
-#
-CONFIG_MMU=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_ALL is not set
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
-
-#
-# Processor
-#
-CONFIG_6xx=y
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_POWER4 is not set
-# CONFIG_8xx is not set
-# CONFIG_E200 is not set
-# CONFIG_E500 is not set
-CONFIG_PPC_FPU=y
-CONFIG_ALTIVEC=y
-CONFIG_TAU=y
-# CONFIG_TAU_INT is not set
-# CONFIG_TAU_AVERAGE is not set
-# CONFIG_KEXEC is not set
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_TABLE=y
-# CONFIG_CPU_FREQ_DEBUG is not set
-CONFIG_CPU_FREQ_STAT=m
-CONFIG_CPU_FREQ_STAT_DETAILS=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=m
-CONFIG_CPU_FREQ_GOV_USERSPACE=m
-CONFIG_CPU_FREQ_GOV_ONDEMAND=m
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
-CONFIG_CPU_FREQ_PMAC=y
-CONFIG_PPC601_SYNC_FIX=y
-CONFIG_PM=y
-CONFIG_PPC_STD_MMU=y
-
-#
-# Platform options
-#
-CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_APUS is not set
-# CONFIG_KATANA is not set
-# CONFIG_WILLOW is not set
-# CONFIG_CPCI690 is not set
-# CONFIG_PCORE is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_CHESTNUT is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_HDPU is not set
-# CONFIG_EV64260 is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MCPN765 is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_RADSTONE_PPC7D is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBC82xx is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX8260 is not set
-# CONFIG_TQM8260 is not set
-# CONFIG_ADS8272 is not set
-# CONFIG_PQ2FADS is not set
-# CONFIG_LITE5200 is not set
-# CONFIG_MPC834x_SYS is not set
-CONFIG_PPC_CHRP=y
-CONFIG_PPC_PMAC=y
-CONFIG_PPC_PREP=y
-CONFIG_PPC_OF=y
-CONFIG_PPCBUG_NVRAM=y
-# CONFIG_SMP is not set
-# CONFIG_HIGHMEM is not set
-# CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_PREP_RESIDUAL is not set
-# CONFIG_CMDLINE_BOOL is not set
-# CONFIG_PM_DEBUG is not set
-CONFIG_SOFTWARE_SUSPEND=y
-CONFIG_PM_STD_PARTITION=""
-# CONFIG_SECCOMP is not set
-CONFIG_ISA_DMA_API=y
-
-#
-# Bus options
-#
-# CONFIG_ISA is not set
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-# CONFIG_PCI_DEBUG is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-CONFIG_PCCARD=m
-# CONFIG_PCMCIA_DEBUG is not set
-CONFIG_PCMCIA=m
-# CONFIG_PCMCIA_LOAD_CIS is not set
-# CONFIG_PCMCIA_IOCTL is not set
-CONFIG_CARDBUS=y
-
-#
-# PC-card bridges
-#
-CONFIG_YENTA=m
-# CONFIG_PD6729 is not set
-# CONFIG_I82092 is not set
-# CONFIG_TCIC is not set
-CONFIG_PCCARD_NONSTATIC=m
-
-#
-# Advanced setup
-#
-CONFIG_ADVANCED_OPTIONS=y
-CONFIG_HIGHMEM_START=0xfe000000
-# CONFIG_LOWMEM_SIZE_BOOL is not set
-CONFIG_LOWMEM_SIZE=0x30000000
-# CONFIG_KERNEL_START_BOOL is not set
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE_BOOL=y
-CONFIG_TASK_SIZE=0xc0000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
-CONFIG_IP_NF_MATCH_SCTP=m
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_CONNMARK=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_CONNMARK=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
-CONFIG_NET_POLL_CONTROLLER=y
-# CONFIG_HAMRADIO is not set
-CONFIG_IRDA=m
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-# CONFIG_IRDA_ULTRA is not set
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-CONFIG_IRTTY_SIR=m
-
-#
-# Dongle support
-#
-# CONFIG_DONGLE is not set
-
-#
-# Old SIR device drivers
-#
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
-# FIR device drivers
-#
-# CONFIG_USB_IRDA is not set
-# CONFIG_SIGMATEL_FIR is not set
-# CONFIG_NSC_FIR is not set
-# CONFIG_WINBOND_FIR is not set
-# CONFIG_TOSHIBA_FIR is not set
-# CONFIG_SMC_IRCC_FIR is not set
-# CONFIG_ALI_FIR is not set
-# CONFIG_VLSI_FIR is not set
-# CONFIG_VIA_FIR is not set
-# CONFIG_BT is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-# CONFIG_STANDALONE is not set
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-CONFIG_MAC_FLOPPY=m
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-CONFIG_LBD=y
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECS is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
-CONFIG_BLK_DEV_IDESCSI=y
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_IDE_GENERIC is not set
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-CONFIG_BLK_DEV_GENERIC=y
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-CONFIG_BLK_DEV_PDC202XX_NEW=y
-# CONFIG_PDC202XX_FORCE is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_IDE_PMAC=y
-CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
-CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_BLK_DEV_IDE_PMAC_BLINK=y
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-CONFIG_SCSI_SPI_ATTRS=y
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-CONFIG_SCSI_AIC7XXX=m
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-CONFIG_AIC7XXX_DEBUG_ENABLE=y
-CONFIG_AIC7XXX_DEBUG_MASK=0
-CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
-CONFIG_SCSI_AIC7XXX_OLD=m
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=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_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-CONFIG_SCSI_MESH=y
-CONFIG_SCSI_MESH_SYNC_RATE=5
-CONFIG_SCSI_MESH_RESET_DELAY_MS=1000
-CONFIG_SCSI_MAC53C94=y
-
-#
-# PCMCIA SCSI adapter support
-#
-# CONFIG_PCMCIA_AHA152X is not set
-# CONFIG_PCMCIA_FDOMAIN is not set
-# CONFIG_PCMCIA_NINJA_SCSI is not set
-# CONFIG_PCMCIA_QLOGIC is not set
-# CONFIG_PCMCIA_SYM53C500 is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-CONFIG_IEEE1394=m
-
-#
-# Subsystem Options
-#
-# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_OUI_DB is not set
-CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
-CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
-# CONFIG_IEEE1394_EXPORT_FULL_API is not set
-
-#
-# Device Drivers
-#
-# CONFIG_IEEE1394_PCILYNX is not set
-CONFIG_IEEE1394_OHCI1394=m
-
-#
-# Protocol Drivers
-#
-CONFIG_IEEE1394_VIDEO1394=m
-CONFIG_IEEE1394_SBP2=m
-# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
-CONFIG_IEEE1394_ETH1394=m
-CONFIG_IEEE1394_DV1394=m
-CONFIG_IEEE1394_RAWIO=m
-CONFIG_IEEE1394_CMP=m
-CONFIG_IEEE1394_AMDTP=m
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-CONFIG_ADB=y
-CONFIG_ADB_CUDA=y
-CONFIG_ADB_PMU=y
-CONFIG_PMAC_APM_EMU=y
-CONFIG_PMAC_MEDIABAY=y
-CONFIG_PMAC_BACKLIGHT=y
-CONFIG_ADB_MACIO=y
-CONFIG_INPUT_ADBHID=y
-CONFIG_MAC_EMUMOUSEBTN=y
-CONFIG_THERM_WINDTUNNEL=m
-CONFIG_THERM_ADT746X=m
-# CONFIG_ANSLCD is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACE=y
-# CONFIG_MACE_AAUI_PORT is not set
-CONFIG_BMAC=y
-# CONFIG_HAPPYMEAL is not set
-CONFIG_SUNGEM=y
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=y
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_MV643XX_ETH is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-# CONFIG_PCMCIA_WAVELAN is not set
-# CONFIG_PCMCIA_NETWAVE is not set
-
-#
-# Wireless 802.11 Frequency Hopping cards support
-#
-# CONFIG_PCMCIA_RAYCS is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-CONFIG_HERMES=m
-CONFIG_APPLE_AIRPORT=m
-# CONFIG_PLX_HERMES is not set
-# CONFIG_TMD_HERMES is not set
-# CONFIG_PCI_HERMES is not set
-# CONFIG_ATMEL is not set
-
-#
-# Wireless 802.11b Pcmcia/Cardbus cards support
-#
-CONFIG_PCMCIA_HERMES=m
-# CONFIG_AIRO_CS is not set
-# CONFIG_PCMCIA_WL3501 is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-CONFIG_NETCONSOLE=m
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-# CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_INPUT_MOUSE=y
-# CONFIG_MOUSE_PS2 is not set
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=m
-CONFIG_SERIAL_8250_CS=m
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_SERIAL_PMACZILOG=y
-CONFIG_SERIAL_PMACZILOG_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-CONFIG_AGP=m
-CONFIG_AGP_UNINORTH=m
-CONFIG_DRM=m
-# CONFIG_DRM_TDFX is not set
-CONFIG_DRM_R128=m
-CONFIG_DRM_RADEON=m
-# CONFIG_DRM_MGA is not set
-# CONFIG_DRM_SIS is not set
-# CONFIG_DRM_VIA is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=m
-
-#
-# I2C Algorithms
-#
-CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_HYDRA is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_ISA is not set
-CONFIG_I2C_KEYWEST=m
-# CONFIG_I2C_MPC is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_SENSORS_M41T00 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
-CONFIG_FB_MACMODES=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_OF=y
-CONFIG_FB_CONTROL=y
-CONFIG_FB_PLATINUM=y
-CONFIG_FB_VALKYRIE=y
-CONFIG_FB_CT65550=y
-# CONFIG_FB_ASILIANT is not set
-CONFIG_FB_IMSTT=y
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-CONFIG_FB_MATROX=y
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G=y
-# CONFIG_FB_MATROX_I2C is not set
-# CONFIG_FB_MATROX_MULTIHEAD is not set
-# CONFIG_FB_RADEON_OLD is not set
-CONFIG_FB_RADEON=y
-CONFIG_FB_RADEON_I2C=y
-# CONFIG_FB_RADEON_DEBUG is not set
-CONFIG_FB_ATY128=y
-CONFIG_FB_ATY=y
-CONFIG_FB_ATY_CT=y
-CONFIG_FB_ATY_GENERIC_LCD=y
-# CONFIG_FB_ATY_XL_INIT is not set
-CONFIG_FB_ATY_GX=y
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-CONFIG_FB_3DFX=y
-CONFIG_FB_3DFX_ACCEL=y
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_LCD_DEVICE=y
-
-#
-# Sound
-#
-CONFIG_SOUND=m
-CONFIG_DMASOUND_PMAC=m
-CONFIG_DMASOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
-CONFIG_SND=m
-CONFIG_SND_TIMER=m
-CONFIG_SND_PCM=m
-CONFIG_SND_HWDEP=m
-CONFIG_SND_RAWMIDI=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-CONFIG_SND_DUMMY=m
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# PCI devices
-#
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_ATIIXP is not set
-# CONFIG_SND_ATIIXP_MODEM is not set
-# CONFIG_SND_AU8810 is not set
-# CONFIG_SND_AU8820 is not set
-# CONFIG_SND_AU8830 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_EMU10K1X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_FM801 is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-# CONFIG_SND_INTEL8X0 is not set
-# CONFIG_SND_INTEL8X0M is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VIA82XX_MODEM is not set
-# CONFIG_SND_VX222 is not set
-# CONFIG_SND_HDA_INTEL is not set
-
-#
-# ALSA PowerMac devices
-#
-CONFIG_SND_POWERMAC=m
-
-#
-# USB devices
-#
-CONFIG_SND_USB_AUDIO=m
-CONFIG_SND_USB_USX2Y=m
-
-#
-# PCMCIA devices
-#
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
-CONFIG_USB_DYNAMIC_MINORS=y
-CONFIG_USB_SUSPEND=y
-# CONFIG_USB_OTG is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_EHCI_HCD is not set
-# CONFIG_USB_ISP116X_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-# CONFIG_USB_UHCI_HCD is not set
-# CONFIG_USB_SL811_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-# CONFIG_USB_STORAGE is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-CONFIG_USB_PEGASUS=m
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_USB_ZD1201 is not set
-# CONFIG_USB_MON is not set
-
-#
-# USB port drivers
-#
-
-#
-# USB Serial Converter support
-#
-CONFIG_USB_SERIAL=m
-# CONFIG_USB_SERIAL_GENERIC is not set
-# CONFIG_USB_SERIAL_AIRPRIME is not set
-# CONFIG_USB_SERIAL_BELKIN is not set
-# CONFIG_USB_SERIAL_WHITEHEAT is not set
-# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_CP2101 is not set
-# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
-# CONFIG_USB_SERIAL_EMPEG is not set
-# CONFIG_USB_SERIAL_FTDI_SIO is not set
-CONFIG_USB_SERIAL_VISOR=m
-# CONFIG_USB_SERIAL_IPAQ is not set
-# CONFIG_USB_SERIAL_IR is not set
-# CONFIG_USB_SERIAL_EDGEPORT is not set
-# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
-# CONFIG_USB_SERIAL_GARMIN is not set
-# CONFIG_USB_SERIAL_IPW is not set
-# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-CONFIG_USB_SERIAL_KEYSPAN=m
-CONFIG_USB_SERIAL_KEYSPAN_MPR=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19=y
-CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
-# CONFIG_USB_SERIAL_KLSI is not set
-# CONFIG_USB_SERIAL_KOBIL_SCT is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
-# CONFIG_USB_SERIAL_PL2303 is not set
-# CONFIG_USB_SERIAL_HP4X is not set
-# CONFIG_USB_SERIAL_SAFE is not set
-# CONFIG_USB_SERIAL_TI is not set
-# CONFIG_USB_SERIAL_CYBERJACK is not set
-# CONFIG_USB_SERIAL_XIRCOM is not set
-# CONFIG_USB_SERIAL_OPTION is not set
-# CONFIG_USB_SERIAL_OMNINET is not set
-CONFIG_USB_EZUSB=y
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# SN Devices
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-# CONFIG_EXT2_FS_POSIX_ACL is not set
-# CONFIG_EXT2_FS_SECURITY is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-
-#
-# XFS support
-#
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_TMPFS_SECURITY=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=m
-CONFIG_HFSPLUS_FS=m
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_CRAMFS=m
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V2_ACL=y
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_V3_ACL=y
-# CONFIG_NFSD_V4 is not set
-CONFIG_NFSD_TCP=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_ACL_SUPPORT=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# 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=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-CONFIG_NLS_ISO8859_15=m
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-CONFIG_NLS_UTF8=m
-
-#
-# Library routines
-#
-CONFIG_CRC_CCITT=y
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOG_BUF_SHIFT=16
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_XMON is not set
-# CONFIG_BDI_SWITCH is not set
-CONFIG_BOOTX_TEXT=y
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/ppc/configs/power3_defconfig b/arch/ppc/configs/power3_defconfig
deleted file mode 100644
index a1ef929bca5..00000000000
--- a/arch/ppc/configs/power3_defconfig
+++ /dev/null
@@ -1,1035 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_GENERIC_NVRAM=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-# CONFIG_STANDALONE is not set
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=15
-# CONFIG_HOTPLUG is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-CONFIG_STOP_MACHINE=y
-
-#
-# Processor
-#
-# CONFIG_6xx is not set
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-CONFIG_POWER3=y
-# CONFIG_POWER4 is not set
-# CONFIG_8xx is not set
-# CONFIG_CPU_FREQ is not set
-CONFIG_PPC64BRIDGE=y
-CONFIG_PPC_STD_MMU=y
-
-#
-# Platform options
-#
-CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_APUS is not set
-# CONFIG_WILLOW is not set
-# CONFIG_PCORE is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_EV64260 is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MCPN765 is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX6 is not set
-# CONFIG_TQM8260 is not set
-CONFIG_PPC_CHRP=y
-CONFIG_PPC_PMAC=y
-CONFIG_PPC_PREP=y
-CONFIG_PPC_OF=y
-CONFIG_PPCBUG_NVRAM=y
-CONFIG_SMP=y
-# CONFIG_IRQ_ALL_CPUS is not set
-CONFIG_NR_CPUS=32
-# CONFIG_PREEMPT is not set
-CONFIG_HIGHMEM=y
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_PROC_DEVICETREE=y
-CONFIG_PPC_RTAS=y
-# CONFIG_PREP_RESIDUAL is not set
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# Bus options
-#
-CONFIG_ISA=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-
-#
-# Advanced setup
-#
-CONFIG_ADVANCED_OPTIONS=y
-# CONFIG_HIGHMEM_START_BOOL is not set
-CONFIG_HIGHMEM_START=0xfe000000
-# CONFIG_LOWMEM_SIZE_BOOL is not set
-CONFIG_LOWMEM_SIZE=0x30000000
-# CONFIG_KERNEL_START_BOOL is not set
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE_BOOL=y
-CONFIG_TASK_SIZE=0xc0000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
-# CONFIG_PARPORT_SERIAL is not set
-CONFIG_PARPORT_PC_FIFO=y
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_OTHER is not set
-# CONFIG_PARPORT_1284 is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_LBD=y
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI Transport Attributes
-#
-CONFIG_SCSI_SPI_ATTRS=y
-# CONFIG_SCSI_FC_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_NCR53C406A is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
-# CONFIG_SCSI_MAC53C94 is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-CONFIG_MD_RAID5=y
-CONFIG_MD_RAID6=y
-# CONFIG_MD_MULTIPATH is not set
-CONFIG_BLK_DEV_DM=y
-CONFIG_DM_CRYPT=y
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_ADB is not set
-# CONFIG_ADB_CUDA is not set
-# CONFIG_ADB_PMU is not set
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=y
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_CS89x0 is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-CONFIG_E100=y
-# CONFIG_E100_NAPI is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-CONFIG_E1000=y
-# CONFIG_E1000_NAPI is not set
-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-CONFIG_GAMEPORT=m
-CONFIG_SOUND_GAMEPORT=m
-# CONFIG_GAMEPORT_NS558 is not set
-# CONFIG_GAMEPORT_L4 is not set
-# 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_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_INPORT is not set
-# CONFIG_MOUSE_LOGIBM is not set
-# CONFIG_MOUSE_PC110PAD is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_PMACZILOG is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-CONFIG_PRINTER=m
-# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
-# CONFIG_TIPAR is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-CONFIG_I2C_ALGOBIT=y
-CONFIG_I2C_ALGOPCF=y
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_HYDRA is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_KEYWEST is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-
-#
-# Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_OF=y
-# CONFIG_FB_CONTROL is not set
-# CONFIG_FB_PLATINUM is not set
-# CONFIG_FB_VALKYRIE is not set
-# CONFIG_FB_CT65550 is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_RIVA is not set
-CONFIG_FB_MATROX=y
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-# CONFIG_FB_MATROX_G450 is not set
-CONFIG_FB_MATROX_G100A=y
-CONFIG_FB_MATROX_G100=y
-CONFIG_FB_MATROX_I2C=y
-# CONFIG_FB_MATROX_MAVEN is not set
-CONFIG_FB_MATROX_MULTIHEAD=y
-# CONFIG_FB_RADEON_OLD is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-# CONFIG_DMASOUND_PMAC is not set
-
-#
-# Advanced Linux Sound Architecture
-#
-CONFIG_SND=m
-CONFIG_SND_TIMER=m
-CONFIG_SND_PCM=m
-CONFIG_SND_HWDEP=m
-CONFIG_SND_RAWMIDI=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-CONFIG_SND_MPU401_UART=m
-CONFIG_SND_OPL3_LIB=m
-CONFIG_SND_DUMMY=m
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# ISA devices
-#
-# CONFIG_SND_AD1848 is not set
-# CONFIG_SND_CS4231 is not set
-CONFIG_SND_CS4232=m
-# CONFIG_SND_CS4236 is not set
-# CONFIG_SND_ES1688 is not set
-# CONFIG_SND_ES18XX is not set
-# CONFIG_SND_GUSCLASSIC is not set
-# CONFIG_SND_GUSEXTREME is not set
-# CONFIG_SND_GUSMAX is not set
-# CONFIG_SND_INTERWAVE is not set
-# CONFIG_SND_INTERWAVE_STB is not set
-# CONFIG_SND_OPTI92X_AD1848 is not set
-# CONFIG_SND_OPTI92X_CS4231 is not set
-# CONFIG_SND_OPTI93X is not set
-# CONFIG_SND_SB8 is not set
-# CONFIG_SND_SB16 is not set
-# CONFIG_SND_SBAWE is not set
-# CONFIG_SND_WAVEFRONT is not set
-# CONFIG_SND_CMI8330 is not set
-# CONFIG_SND_OPL3SA2 is not set
-# CONFIG_SND_SGALAXY is not set
-# CONFIG_SND_SSCAPE is not set
-
-#
-# PCI devices
-#
-CONFIG_SND_AC97_CODEC=m
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_ATIIXP is not set
-# CONFIG_SND_AU8810 is not set
-# CONFIG_SND_AU8820 is not set
-# CONFIG_SND_AU8830 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-CONFIG_SND_CS46XX=m
-# CONFIG_SND_CS46XX_NEW_DSP is not set
-CONFIG_SND_CS4281=m
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_FM801 is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-# CONFIG_SND_INTEL8X0 is not set
-# CONFIG_SND_INTEL8X0M is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VX222 is not set
-
-#
-# ALSA PowerMac devices
-#
-# CONFIG_SND_POWERMAC is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-# CONFIG_ZISOFS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=y
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 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_ISO8859_1=y
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Library routines
-#
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_BOOTX_TEXT=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-# CONFIG_CRYPTO_SERPENT is not set
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_TEST is not set
diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/prep_defconfig
index 4d33bee23a8..4d33bee23a8 100644
--- a/arch/ppc/configs/common_defconfig
+++ b/arch/ppc/configs/prep_defconfig
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index e399bbb969a..466437f4bcb 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -1,48 +1,24 @@
#
# Makefile for the linux kernel.
#
-ifneq ($(CONFIG_PPC_MERGE),y)
-
extra-$(CONFIG_PPC_STD_MMU) := head.o
extra-$(CONFIG_40x) := head_4xx.o
extra-$(CONFIG_44x) := head_44x.o
extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o
extra-$(CONFIG_8xx) := head_8xx.o
-extra-$(CONFIG_6xx) += idle_6xx.o
extra-y += vmlinux.lds
-obj-y := entry.o traps.o idle.o time.o misc.o \
+obj-y := entry.o traps.o time.o misc.o \
setup.o \
ppc_htab.o
-obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
-obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
-obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
+obj-$(CONFIG_MODULES) += ppc_ksyms.o
obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_RAPIDIO) += rio.o
obj-$(CONFIG_KGDB) += ppc-stub.o
obj-$(CONFIG_SMP) += smp.o smp-tbsync.o
-obj-$(CONFIG_TAU) += temp.o
-ifndef CONFIG_E200
-obj-$(CONFIG_FSL_BOOKE) += perfmon_fsl_booke.o
-endif
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
ifndef CONFIG_MATH_EMULATION
obj-$(CONFIG_8xx) += softemu8xx.o
endif
-
-# These are here while we do the architecture merge
-
-else
-obj-y := idle.o
-obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
-obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
-obj-$(CONFIG_MODULES) += module.o
-obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o
-obj-$(CONFIG_KGDB) += ppc-stub.o
-obj-$(CONFIG_TAU) += temp.o
-ifndef CONFIG_E200
-obj-$(CONFIG_FSL_BOOKE) += perfmon_fsl_booke.o
-endif
-endif
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 3a281597848..5891ecbdc70 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -135,10 +135,10 @@ transfer_to_handler:
mfspr r11,SPRN_HID0
mtcr r11
BEGIN_FTR_SECTION
- bt- 8,power_save_6xx_restore /* Check DOZE */
+ bt- 8,4f /* Check DOZE */
END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
BEGIN_FTR_SECTION
- bt- 9,power_save_6xx_restore /* Check NAP */
+ bt- 9,4f /* Check NAP */
END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
#endif /* CONFIG_6xx */
.globl transfer_to_handler_cont
@@ -157,6 +157,10 @@ transfer_to_handler_cont:
SYNC
RFI /* jump to handler, enable MMU */
+#ifdef CONFIG_6xx
+4: b power_save_6xx_restore
+#endif
+
/*
* On kernel stack overflow, load up an initial stack pointer
* and call StackOverflow(regs), which should not return.
@@ -926,55 +930,3 @@ END_FTR_SECTION_IFSET(CPU_FTR_601)
b 4b
.comm ee_restarts,4
-
-/*
- * PROM code for specific machines follows. Put it
- * here so it's easy to add arch-specific sections later.
- * -- Cort
- */
-#ifdef CONFIG_PPC_OF
-/*
- * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
- * called with the MMU off.
- */
-_GLOBAL(enter_rtas)
- stwu r1,-INT_FRAME_SIZE(r1)
- mflr r0
- stw r0,INT_FRAME_SIZE+4(r1)
- lis r4,rtas_data@ha
- lwz r4,rtas_data@l(r4)
- lis r6,1f@ha /* physical return address for rtas */
- addi r6,r6,1f@l
- tophys(r6,r6)
- tophys(r7,r1)
- lis r8,rtas_entry@ha
- lwz r8,rtas_entry@l(r8)
- mfmsr r9
- stw r9,8(r1)
- LOAD_MSR_KERNEL(r0,MSR_KERNEL)
- SYNC /* disable interrupts so SRR0/1 */
- MTMSRD(r0) /* don't get trashed */
- li r9,MSR_KERNEL & ~(MSR_IR|MSR_DR)
- mtlr r6
- CLR_TOP32(r7)
- mtspr SPRN_SPRG2,r7
- mtspr SPRN_SRR0,r8
- mtspr SPRN_SRR1,r9
- RFI
-1: tophys(r9,r1)
- lwz r8,INT_FRAME_SIZE+4(r9) /* get return address */
- lwz r9,8(r9) /* original msr value */
- FIX_SRR1(r9,r0)
- addi r1,r1,INT_FRAME_SIZE
- li r0,0
- mtspr SPRN_SPRG2,r0
- mtspr SPRN_SRR0,r8
- mtspr SPRN_SRR1,r9
- RFI /* return to caller */
-
- .globl machine_check_in_rtas
-machine_check_in_rtas:
- twi 31,0,0
- /* XXX load up BATs and panic */
-
-#endif /* CONFIG_PPC_OF */
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 53ea845fb91..01303efedda 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -37,19 +37,6 @@
#include <asm/amigappc.h>
#endif
-#ifdef CONFIG_PPC64BRIDGE
-#define LOAD_BAT(n, reg, RA, RB) \
- ld RA,(n*32)+0(reg); \
- ld RB,(n*32)+8(reg); \
- mtspr SPRN_IBAT##n##U,RA; \
- mtspr SPRN_IBAT##n##L,RB; \
- ld RA,(n*32)+16(reg); \
- ld RB,(n*32)+24(reg); \
- mtspr SPRN_DBAT##n##U,RA; \
- mtspr SPRN_DBAT##n##L,RB; \
-
-#else /* CONFIG_PPC64BRIDGE */
-
/* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
#define LOAD_BAT(n, reg, RA, RB) \
/* see the comment for clear_bats() -- Cort */ \
@@ -66,7 +53,6 @@
mtspr SPRN_DBAT##n##U,RA; \
mtspr SPRN_DBAT##n##L,RB; \
1:
-#endif /* CONFIG_PPC64BRIDGE */
.text
.stabs "arch/ppc/kernel/",N_SO,0,0,0f
@@ -129,11 +115,6 @@ _start:
.globl __start
__start:
-/*
- * We have to do any OF calls before we map ourselves to KERNELBASE,
- * because OF may have I/O devices mapped into that area
- * (particularly on CHRP).
- */
mr r31,r3 /* save parameters */
mr r30,r4
mr r29,r5
@@ -148,14 +129,6 @@ __start:
*/
bl early_init
-/*
- * On POWER4, we first need to tweak some CPU configuration registers
- * like real mode cache inhibit or exception base
- */
-#ifdef CONFIG_POWER4
- bl __970_cpu_preinit
-#endif /* CONFIG_POWER4 */
-
#ifdef CONFIG_APUS
/* On APUS the __va/__pa constants need to be set to the correct
* values before continuing.
@@ -169,7 +142,6 @@ __start:
*/
bl mmu_off
__after_mmu_off:
-#ifndef CONFIG_POWER4
bl clear_bats
bl flush_tlbs
@@ -177,10 +149,6 @@ __after_mmu_off:
#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
bl setup_disp_bat
#endif
-#else /* CONFIG_POWER4 */
- bl reloc_offset
- bl initial_mm_power4
-#endif /* CONFIG_POWER4 */
/*
* Call setup_cpu for CPU 0 and initialize 6xx Idle
@@ -192,18 +160,11 @@ __after_mmu_off:
bl reloc_offset
bl init_idle_6xx
#endif /* CONFIG_6xx */
-#ifdef CONFIG_POWER4
- bl reloc_offset
- bl init_idle_power4
-#endif /* CONFIG_POWER4 */
#ifndef CONFIG_APUS
/*
* We need to run with _start at physical address 0.
- * On CHRP, we are loaded at 0x10000 since OF on CHRP uses
- * the exception vectors at 0 (and therefore this copy
- * overwrites OF's exception vectors with our own).
* If the MMU is already turned on, we copy stuff to KERNELBASE,
* otherwise we copy it to 0.
*/
@@ -358,51 +319,19 @@ i##n: \
#endif
/* Machine check */
-/*
- * On CHRP, this is complicated by the fact that we could get a
- * machine check inside RTAS, and we have no guarantee that certain
- * critical registers will have the values we expect. The set of
- * registers that might have bad values includes all the GPRs
- * and all the BATs. We indicate that we are in RTAS by putting
- * a non-zero value, the address of the exception frame to use,
- * in SPRG2. The machine check handler checks SPRG2 and uses its
- * value if it is non-zero. If we ever needed to free up SPRG2,
- * we could use a field in the thread_info or thread_struct instead.
- * (Other exception handlers assume that r1 is a valid kernel stack
- * pointer when we take an exception from supervisor mode.)
- * -- paulus.
- */
. = 0x200
mtspr SPRN_SPRG0,r10
mtspr SPRN_SPRG1,r11
mfcr r10
-#ifdef CONFIG_PPC_CHRP
- mfspr r11,SPRN_SPRG2
- cmpwi 0,r11,0
- bne 7f
-#endif /* CONFIG_PPC_CHRP */
EXCEPTION_PROLOG_1
7: EXCEPTION_PROLOG_2
addi r3,r1,STACK_FRAME_OVERHEAD
-#ifdef CONFIG_PPC_CHRP
- mfspr r4,SPRN_SPRG2
- cmpwi cr1,r4,0
- bne cr1,1f
-#endif
EXC_XFER_STD(0x200, machine_check_exception)
-#ifdef CONFIG_PPC_CHRP
-1: b machine_check_in_rtas
-#endif
/* Data access exception. */
. = 0x300
-#ifdef CONFIG_PPC64BRIDGE
- b DataAccess
-DataAccessCont:
-#else
DataAccess:
EXCEPTION_PROLOG
-#endif /* CONFIG_PPC64BRIDGE */
mfspr r10,SPRN_DSISR
andis. r0,r10,0xa470 /* weird error? */
bne 1f /* if not, try to put a PTE */
@@ -414,21 +343,10 @@ DataAccess:
mfspr r4,SPRN_DAR
EXC_XFER_EE_LITE(0x300, handle_page_fault)
-#ifdef CONFIG_PPC64BRIDGE
-/* SLB fault on data access. */
- . = 0x380
- b DataSegment
-#endif /* CONFIG_PPC64BRIDGE */
-
/* Instruction access exception. */
. = 0x400
-#ifdef CONFIG_PPC64BRIDGE
- b InstructionAccess
-InstructionAccessCont:
-#else
InstructionAccess:
EXCEPTION_PROLOG
-#endif /* CONFIG_PPC64BRIDGE */
andis. r0,r9,0x4000 /* no pte found? */
beq 1f /* if so, try to put a PTE */
li r3,0 /* into the hash table */
@@ -438,12 +356,6 @@ InstructionAccess:
mr r5,r9
EXC_XFER_EE_LITE(0x400, handle_page_fault)
-#ifdef CONFIG_PPC64BRIDGE
-/* SLB fault on instruction access. */
- . = 0x480
- b InstructionSegment
-#endif /* CONFIG_PPC64BRIDGE */
-
/* External interrupt */
EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
@@ -708,15 +620,9 @@ DataStoreTLBMiss:
EXCEPTION(0x1300, Trap_13, instruction_breakpoint_exception, EXC_XFER_EE)
EXCEPTION(0x1400, SMI, SMIException, EXC_XFER_EE)
EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
-#ifdef CONFIG_POWER4
- EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x1700, Trap_17, altivec_assist_exception, EXC_XFER_EE)
- EXCEPTION(0x1800, Trap_18, TAUException, EXC_XFER_STD)
-#else /* !CONFIG_POWER4 */
EXCEPTION(0x1600, Trap_16, altivec_assist_exception, EXC_XFER_EE)
EXCEPTION(0x1700, Trap_17, TAUException, EXC_XFER_STD)
EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
-#endif /* CONFIG_POWER4 */
EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x1a00, Trap_1a, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x1b00, Trap_1b, unknown_exception, EXC_XFER_EE)
@@ -754,28 +660,6 @@ AltiVecUnavailable:
addi r3,r1,STACK_FRAME_OVERHEAD
EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception)
-#ifdef CONFIG_PPC64BRIDGE
-DataAccess:
- EXCEPTION_PROLOG
- b DataAccessCont
-
-InstructionAccess:
- EXCEPTION_PROLOG
- b InstructionAccessCont
-
-DataSegment:
- EXCEPTION_PROLOG
- addi r3,r1,STACK_FRAME_OVERHEAD
- mfspr r4,SPRN_DAR
- stw r4,_DAR(r11)
- EXC_XFER_STD(0x380, unknown_exception)
-
-InstructionSegment:
- EXCEPTION_PROLOG
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_STD(0x480, unknown_exception)
-#endif /* CONFIG_PPC64BRIDGE */
-
#ifdef CONFIG_ALTIVEC
/* Note that the AltiVec support is closely modeled after the FP
* support. Changes to one are likely to be applicable to the
@@ -1048,13 +932,6 @@ __secondary_start_pmac_0:
.globl __secondary_start
__secondary_start:
-#ifdef CONFIG_PPC64BRIDGE
- mfmsr r0
- clrldi r0,r0,1 /* make sure it's in 32-bit mode */
- SYNC
- MTMSRD(r0)
- isync
-#endif
/* Copy some CPU settings from CPU 0 */
bl __restore_cpu_setup
@@ -1065,10 +942,6 @@ __secondary_start:
lis r3,-KERNELBASE@h
bl init_idle_6xx
#endif /* CONFIG_6xx */
-#ifdef CONFIG_POWER4
- lis r3,-KERNELBASE@h
- bl init_idle_power4
-#endif /* CONFIG_POWER4 */
/* get current_thread_info and current */
lis r1,secondary_ti@ha
@@ -1109,12 +982,12 @@ __secondary_start:
* Those generic dummy functions are kept for CPUs not
* included in CONFIG_6xx
*/
-#if !defined(CONFIG_6xx) && !defined(CONFIG_POWER4)
+#if !defined(CONFIG_6xx)
_GLOBAL(__save_cpu_setup)
blr
_GLOBAL(__restore_cpu_setup)
blr
-#endif /* !defined(CONFIG_6xx) && !defined(CONFIG_POWER4) */
+#endif /* !defined(CONFIG_6xx) */
/*
@@ -1132,11 +1005,6 @@ load_up_mmu:
tophys(r6,r6)
lwz r6,_SDR1@l(r6)
mtspr SPRN_SDR1,r6
-#ifdef CONFIG_PPC64BRIDGE
- /* clear the ASR so we only use the pseudo-segment registers. */
- li r6,0
- mtasr r6
-#endif /* CONFIG_PPC64BRIDGE */
li r0,16 /* load up segment register values */
mtctr r0 /* for context 0 */
lis r3,0x2000 /* Ku = 1, VSID = 0 */
@@ -1145,7 +1013,7 @@ load_up_mmu:
addi r3,r3,0x111 /* increment VSID */
addis r4,r4,0x1000 /* address of next segment */
bdnz 3b
-#ifndef CONFIG_POWER4
+
/* Load the BAT registers with the values set up by MMU_init.
MMU_init takes care of whether we're on a 601 or not. */
mfpvr r3
@@ -1158,7 +1026,7 @@ load_up_mmu:
LOAD_BAT(1,r3,r4,r5)
LOAD_BAT(2,r3,r4,r5)
LOAD_BAT(3,r3,r4,r5)
-#endif /* CONFIG_POWER4 */
+
blr
/*
@@ -1269,9 +1137,6 @@ _GLOBAL(set_context)
li r4,0
isync
3:
-#ifdef CONFIG_PPC64BRIDGE
- slbie r4
-#endif /* CONFIG_PPC64BRIDGE */
mtsrin r3,r4
addi r3,r3,0x111 /* next VSID */
rlwinm r3,r3,0,8,3 /* clear out any overflow from VSID field */
@@ -1358,7 +1223,6 @@ mmu_off:
sync
RFI
-#ifndef CONFIG_POWER4
/*
* Use the first pair of BAT registers to map the 1st 16MB
* of RAM to KERNELBASE. From this point on we can't safely
@@ -1366,7 +1230,6 @@ mmu_off:
*/
initial_bats:
lis r11,KERNELBASE@h
-#ifndef CONFIG_PPC64BRIDGE
mfspr r9,SPRN_PVR
rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
cmpwi 0,r9,1
@@ -1381,7 +1244,6 @@ initial_bats:
mtspr SPRN_IBAT1L,r10
isync
blr
-#endif /* CONFIG_PPC64BRIDGE */
4: tophys(r8,r11)
#ifdef CONFIG_SMP
@@ -1395,11 +1257,6 @@ initial_bats:
ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */
#endif /* CONFIG_APUS */
-#ifdef CONFIG_PPC64BRIDGE
- /* clear out the high 32 bits in the BAT */
- clrldi r11,r11,32
- clrldi r8,r8,32
-#endif /* CONFIG_PPC64BRIDGE */
mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */
mtspr SPRN_IBAT0L,r8
@@ -1432,38 +1289,6 @@ setup_disp_bat:
#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
-#else /* CONFIG_POWER4 */
-/*
- * Load up the SDR1 and segment register values now
- * since we don't have the BATs.
- * Also make sure we are running in 32-bit mode.
- */
-
-initial_mm_power4:
- addis r14,r3,_SDR1@ha /* get the value from _SDR1 */
- lwz r14,_SDR1@l(r14) /* assume hash table below 4GB */
- mtspr SPRN_SDR1,r14
- slbia
- lis r4,0x2000 /* set pseudo-segment reg 12 */
- ori r5,r4,0x0ccc
- mtsr 12,r5
-#if 0
- ori r5,r4,0x0888 /* set pseudo-segment reg 8 */
- mtsr 8,r5 /* (for access to serial port) */
-#endif
-#ifdef CONFIG_BOOTX_TEXT
- ori r5,r4,0x0999 /* set pseudo-segment reg 9 */
- mtsr 9,r5 /* (for access to screen) */
-#endif
- mfmsr r0
- clrldi r0,r0,1
- sync
- mtmsr r0
- isync
- blr
-
-#endif /* CONFIG_POWER4 */
-
#ifdef CONFIG_8260
/* Jump into the system reset for the rom.
* We first disable the MMU, and then jump to the ROM reset address.
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
deleted file mode 100644
index 1be3ca5bae4..00000000000
--- a/arch/ppc/kernel/idle.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Idle daemon for PowerPC. Idle daemon will handle any action
- * that needs to be taken when the system becomes idle.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu). Subsequently hacked
- * on by Tom Rini, Armin Kuster, Paul Mackerras and others.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/sysctl.h>
-#include <linux/cpu.h>
-
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/mmu.h>
-#include <asm/cache.h>
-#include <asm/cputable.h>
-#include <asm/machdep.h>
-#include <asm/smp.h>
-
-void default_idle(void)
-{
- void (*powersave)(void);
-
- powersave = ppc_md.power_save;
-
- if (!need_resched()) {
- if (powersave != NULL)
- powersave();
-#ifdef CONFIG_SMP
- else {
- set_thread_flag(TIF_POLLING_NRFLAG);
- while (!need_resched() &&
- !cpu_is_offline(smp_processor_id()))
- barrier();
- clear_thread_flag(TIF_POLLING_NRFLAG);
- }
-#endif
- }
-}
-
-/*
- * The body of the idle task.
- */
-void cpu_idle(void)
-{
- int cpu = smp_processor_id();
-
- for (;;) {
- while (!need_resched()) {
- if (ppc_md.idle != NULL)
- ppc_md.idle();
- else
- default_idle();
- }
-
- if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
- cpu_die();
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
- }
-}
-
-#if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx)
-/*
- * Register the sysctl to set/clear powersave_nap.
- */
-extern int powersave_nap;
-
-static ctl_table powersave_nap_ctl_table[]={
- {
- .ctl_name = KERN_PPC_POWERSAVE_NAP,
- .procname = "powersave-nap",
- .data = &powersave_nap,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- { 0, },
-};
-static ctl_table powersave_nap_sysctl_root[] = {
- { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, },
- { 0,},
-};
-
-static int __init
-register_powersave_nap_sysctl(void)
-{
- register_sysctl_table(powersave_nap_sysctl_root, 0);
-
- return 0;
-}
-
-__initcall(register_powersave_nap_sysctl);
-#endif
diff --git a/arch/ppc/kernel/idle_6xx.S b/arch/ppc/kernel/idle_6xx.S
deleted file mode 100644
index 1a2194cf682..00000000000
--- a/arch/ppc/kernel/idle_6xx.S
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * This file contains the power_save function for 6xx & 7xxx CPUs
- * rewritten in assembler
- *
- * Warning ! This code assumes that if your machine has a 750fx
- * it will have PLL 1 set to low speed mode (used during NAP/DOZE).
- * if this is not the case some additional changes will have to
- * be done to check a runtime var (a bit like powersave-nap)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/cputable.h>
-#include <asm/thread_info.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-#undef DEBUG
-
- .text
-
-/*
- * Init idle, called at early CPU setup time from head.S for each CPU
- * Make sure no rest of NAP mode remains in HID0, save default
- * values for some CPU specific registers. Called with r24
- * containing CPU number and r3 reloc offset
- */
-_GLOBAL(init_idle_6xx)
-BEGIN_FTR_SECTION
- mfspr r4,SPRN_HID0
- rlwinm r4,r4,0,10,8 /* Clear NAP */
- mtspr SPRN_HID0, r4
- b 1f
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
- blr
-1:
- slwi r5,r24,2
- add r5,r5,r3
-BEGIN_FTR_SECTION
- mfspr r4,SPRN_MSSCR0
- addis r6,r5, nap_save_msscr0@ha
- stw r4,nap_save_msscr0@l(r6)
-END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-BEGIN_FTR_SECTION
- mfspr r4,SPRN_HID1
- addis r6,r5,nap_save_hid1@ha
- stw r4,nap_save_hid1@l(r6)
-END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
- blr
-
-/*
- * Here is the power_save_6xx function. This could eventually be
- * split into several functions & changing the function pointer
- * depending on the various features.
- */
-_GLOBAL(ppc6xx_idle)
- /* Check if we can nap or doze, put HID0 mask in r3
- */
- lis r3, 0
-BEGIN_FTR_SECTION
- lis r3,HID0_DOZE@h
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-BEGIN_FTR_SECTION
- /* We must dynamically check for the NAP feature as it
- * can be cleared by CPU init after the fixups are done
- */
- lis r4,cur_cpu_spec@ha
- lwz r4,cur_cpu_spec@l(r4)
- lwz r4,CPU_SPEC_FEATURES(r4)
- andi. r0,r4,CPU_FTR_CAN_NAP
- beq 1f
- /* Now check if user or arch enabled NAP mode */
- lis r4,powersave_nap@ha
- lwz r4,powersave_nap@l(r4)
- cmpwi 0,r4,0
- beq 1f
- lis r3,HID0_NAP@h
-1:
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
- cmpwi 0,r3,0
- beqlr
-
- /* Clear MSR:EE */
- mfmsr r7
- rlwinm r0,r7,0,17,15
- mtmsr r0
-
- /* Check current_thread_info()->flags */
- rlwinm r4,r1,0,0,18
- lwz r4,TI_FLAGS(r4)
- andi. r0,r4,_TIF_NEED_RESCHED
- beq 1f
- mtmsr r7 /* out of line this ? */
- blr
-1:
- /* Some pre-nap cleanups needed on some CPUs */
- andis. r0,r3,HID0_NAP@h
- beq 2f
-BEGIN_FTR_SECTION
- /* Disable L2 prefetch on some 745x and try to ensure
- * L2 prefetch engines are idle. As explained by errata
- * text, we can't be sure they are, we just hope very hard
- * that well be enough (sic !). At least I noticed Apple
- * doesn't even bother doing the dcbf's here...
- */
- mfspr r4,SPRN_MSSCR0
- rlwinm r4,r4,0,0,29
- sync
- mtspr SPRN_MSSCR0,r4
- sync
- isync
- lis r4,KERNELBASE@h
- dcbf 0,r4
- dcbf 0,r4
- dcbf 0,r4
- dcbf 0,r4
-END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-#ifdef DEBUG
- lis r6,nap_enter_count@ha
- lwz r4,nap_enter_count@l(r6)
- addi r4,r4,1
- stw r4,nap_enter_count@l(r6)
-#endif
-2:
-BEGIN_FTR_SECTION
- /* Go to low speed mode on some 750FX */
- lis r4,powersave_lowspeed@ha
- lwz r4,powersave_lowspeed@l(r4)
- cmpwi 0,r4,0
- beq 1f
- mfspr r4,SPRN_HID1
- oris r4,r4,0x0001
- mtspr SPRN_HID1,r4
-1:
-END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
-
- /* Go to NAP or DOZE now */
- mfspr r4,SPRN_HID0
- lis r5,(HID0_NAP|HID0_SLEEP)@h
-BEGIN_FTR_SECTION
- oris r5,r5,HID0_DOZE@h
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
- andc r4,r4,r5
- or r4,r4,r3
-BEGIN_FTR_SECTION
- oris r4,r4,HID0_DPM@h /* that should be done once for all */
-END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
- mtspr SPRN_HID0,r4
-BEGIN_FTR_SECTION
- DSSALL
- sync
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
- ori r7,r7,MSR_EE /* Could be ommited (already set) */
- oris r7,r7,MSR_POW@h
- sync
- isync
- mtmsr r7
- isync
- sync
- blr
-
-/*
- * Return from NAP/DOZE mode, restore some CPU specific registers,
- * we are called with DR/IR still off and r2 containing physical
- * address of current.
- */
-_GLOBAL(power_save_6xx_restore)
- mfspr r11,SPRN_HID0
- rlwinm. r11,r11,0,10,8 /* Clear NAP & copy NAP bit !state to cr1 EQ */
- cror 4*cr1+eq,4*cr0+eq,4*cr0+eq
-BEGIN_FTR_SECTION
- rlwinm r11,r11,0,9,7 /* Clear DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
- mtspr SPRN_HID0, r11
-
-#ifdef DEBUG
- beq cr1,1f
- lis r11,(nap_return_count-KERNELBASE)@ha
- lwz r9,nap_return_count@l(r11)
- addi r9,r9,1
- stw r9,nap_return_count@l(r11)
-1:
-#endif
-
- rlwinm r9,r1,0,0,18
- tophys(r9,r9)
- lwz r11,TI_CPU(r9)
- slwi r11,r11,2
- /* Todo make sure all these are in the same page
- * and load r22 (@ha part + CPU offset) only once
- */
-BEGIN_FTR_SECTION
- beq cr1,1f
- addis r9,r11,(nap_save_msscr0-KERNELBASE)@ha
- lwz r9,nap_save_msscr0@l(r9)
- mtspr SPRN_MSSCR0, r9
- sync
- isync
-1:
-END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-BEGIN_FTR_SECTION
- addis r9,r11,(nap_save_hid1-KERNELBASE)@ha
- lwz r9,nap_save_hid1@l(r9)
- mtspr SPRN_HID1, r9
-END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
- b transfer_to_handler_cont
-
- .data
-
-_GLOBAL(nap_save_msscr0)
- .space 4*NR_CPUS
-
-_GLOBAL(nap_save_hid1)
- .space 4*NR_CPUS
-
-_GLOBAL(powersave_nap)
- .long 0
-_GLOBAL(powersave_lowspeed)
- .long 0
-
-#ifdef DEBUG
-_GLOBAL(nap_enter_count)
- .space 4
-_GLOBAL(nap_return_count)
- .space 4
-#endif
diff --git a/arch/ppc/kernel/idle_power4.S b/arch/ppc/kernel/idle_power4.S
deleted file mode 100644
index cc0d535365c..00000000000
--- a/arch/ppc/kernel/idle_power4.S
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * This file contains the power_save function for 6xx & 7xxx CPUs
- * rewritten in assembler
- *
- * Warning ! This code assumes that if your machine has a 750fx
- * it will have PLL 1 set to low speed mode (used during NAP/DOZE).
- * if this is not the case some additional changes will have to
- * be done to check a runtime var (a bit like powersave-nap)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/cputable.h>
-#include <asm/thread_info.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-#undef DEBUG
-
- .text
-
-/*
- * Init idle, called at early CPU setup time from head.S for each CPU
- * So nothing for now. Called with r24 containing CPU number and r3
- * reloc offset
- */
- .globl init_idle_power4
-init_idle_power4:
- blr
-
-/*
- * Here is the power_save_6xx function. This could eventually be
- * split into several functions & changing the function pointer
- * depending on the various features.
- */
- .globl power4_idle
-power4_idle:
-BEGIN_FTR_SECTION
- blr
-END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
- /* We must dynamically check for the NAP feature as it
- * can be cleared by CPU init after the fixups are done
- */
- lis r4,cur_cpu_spec@ha
- lwz r4,cur_cpu_spec@l(r4)
- lwz r4,CPU_SPEC_FEATURES(r4)
- andi. r0,r4,CPU_FTR_CAN_NAP
- beqlr
- /* Now check if user or arch enabled NAP mode */
- lis r4,powersave_nap@ha
- lwz r4,powersave_nap@l(r4)
- cmpwi 0,r4,0
- beqlr
-
- /* Clear MSR:EE */
- mfmsr r7
- rlwinm r0,r7,0,17,15
- mtmsr r0
-
- /* Check current_thread_info()->flags */
- rlwinm r4,r1,0,0,18
- lwz r4,TI_FLAGS(r4)
- andi. r0,r4,_TIF_NEED_RESCHED
- beq 1f
- mtmsr r7 /* out of line this ? */
- blr
-1:
- /* Go to NAP now */
-BEGIN_FTR_SECTION
- DSSALL
- sync
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
- ori r7,r7,MSR_EE /* Could be ommited (already set) */
- oris r7,r7,MSR_POW@h
- sync
- isync
- mtmsr r7
- isync
- sync
- blr
-
- .globl powersave_nap
-powersave_nap:
- .long 0
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 04d04c5bfdd..809673a36f7 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -46,9 +46,6 @@ static void pcibios_fixup_resources(struct pci_dev* dev);
static void fixup_broken_pcnet32(struct pci_dev* dev);
static int reparent_resources(struct resource *parent, struct resource *res);
static void fixup_cpc710_pci64(struct pci_dev* dev);
-#ifdef CONFIG_PPC_OF
-static u8* pci_to_OF_bus_map;
-#endif
/* By default, we don't re-assign bus numbers.
*/
@@ -625,406 +622,13 @@ pcibios_alloc_controller(void)
return hose;
}
-#ifdef CONFIG_PPC_OF
-/*
- * Functions below are used on OpenFirmware machines.
- */
-static void
-make_one_node_map(struct device_node* node, u8 pci_bus)
-{
- int *bus_range;
- int len;
-
- if (pci_bus >= pci_bus_count)
- return;
- bus_range = (int *) get_property(node, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s, "
- "assuming it starts at 0\n", node->full_name);
- pci_to_OF_bus_map[pci_bus] = 0;
- } else
- pci_to_OF_bus_map[pci_bus] = bus_range[0];
-
- for (node=node->child; node != 0;node = node->sibling) {
- struct pci_dev* dev;
- unsigned int *class_code, *reg;
-
- class_code = (unsigned int *) get_property(node, "class-code", NULL);
- if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
- continue;
- reg = (unsigned int *)get_property(node, "reg", NULL);
- if (!reg)
- continue;
- dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff));
- if (!dev || !dev->subordinate)
- continue;
- make_one_node_map(node, dev->subordinate->number);
- }
-}
-
-void
-pcibios_make_OF_bus_map(void)
-{
- int i;
- struct pci_controller* hose;
- u8* of_prop_map;
-
- pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);
- if (!pci_to_OF_bus_map) {
- printk(KERN_ERR "Can't allocate OF bus map !\n");
- return;
- }
-
- /* We fill the bus map with invalid values, that helps
- * debugging.
- */
- for (i=0; i<pci_bus_count; i++)
- pci_to_OF_bus_map[i] = 0xff;
-
- /* For each hose, we begin searching bridges */
- for(hose=hose_head; hose; hose=hose->next) {
- struct device_node* node;
- node = (struct device_node *)hose->arch_data;
- if (!node)
- continue;
- make_one_node_map(node, hose->first_busno);
- }
- of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", NULL);
- if (of_prop_map)
- memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count);
-#ifdef DEBUG
- printk("PCI->OF bus map:\n");
- for (i=0; i<pci_bus_count; i++) {
- if (pci_to_OF_bus_map[i] == 0xff)
- continue;
- printk("%d -> %d\n", i, pci_to_OF_bus_map[i]);
- }
-#endif
-}
-
-typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data);
-
-static struct device_node*
-scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data)
-{
- struct device_node* sub_node;
-
- for (; node != 0;node = node->sibling) {
- unsigned int *class_code;
-
- if (filter(node, data))
- return node;
-
- /* For PCI<->PCI bridges or CardBus bridges, we go down
- * Note: some OFs create a parent node "multifunc-device" as
- * a fake root for all functions of a multi-function device,
- * we go down them as well.
- */
- class_code = (unsigned int *) get_property(node, "class-code", NULL);
- if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
- strcmp(node->name, "multifunc-device"))
- continue;
- sub_node = scan_OF_pci_childs(node->child, filter, data);
- if (sub_node)
- return sub_node;
- }
- return NULL;
-}
-
-static int
-scan_OF_pci_childs_iterator(struct device_node* node, void* data)
-{
- unsigned int *reg;
- u8* fdata = (u8*)data;
-
- reg = (unsigned int *) get_property(node, "reg", NULL);
- if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]
- && ((reg[0] >> 16) & 0xff) == fdata[0])
- return 1;
- return 0;
-}
-
-static struct device_node*
-scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
-{
- u8 filter_data[2] = {bus, dev_fn};
-
- return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data);
-}
-
-/*
- * Scans the OF tree for a device node matching a PCI device
- */
-struct device_node *
-pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
-{
- struct pci_controller *hose;
- struct device_node *node;
- int busnr;
-
- if (!have_of)
- return NULL;
-
- /* Lookup the hose */
- busnr = bus->number;
- hose = pci_bus_to_hose(busnr);
- if (!hose)
- return NULL;
-
- /* Check it has an OF node associated */
- node = (struct device_node *) hose->arch_data;
- if (!node)
- return NULL;
-
- /* Fixup bus number according to what OF think it is. */
- if (pci_to_OF_bus_map)
- busnr = pci_to_OF_bus_map[busnr];
- if (busnr == 0xff)
- return NULL;
-
- /* Now, lookup childs of the hose */
- return scan_OF_childs_for_device(node->child, busnr, devfn);
-}
-EXPORT_SYMBOL(pci_busdev_to_OF_node);
-
-struct device_node*
-pci_device_to_OF_node(struct pci_dev *dev)
-{
- return pci_busdev_to_OF_node(dev->bus, dev->devfn);
-}
-EXPORT_SYMBOL(pci_device_to_OF_node);
-
-/* This routine is meant to be used early during boot, when the
- * PCI bus numbers have not yet been assigned, and you need to
- * issue PCI config cycles to an OF device.
- * It could also be used to "fix" RTAS config cycles if you want
- * to set pci_assign_all_buses to 1 and still use RTAS for PCI
- * config cycles.
- */
-struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
-{
- if (!have_of)
- return NULL;
- while(node) {
- struct pci_controller* hose;
- for (hose=hose_head;hose;hose=hose->next)
- if (hose->arch_data == node)
- return hose;
- node=node->parent;
- }
- return NULL;
-}
-
-static int
-find_OF_pci_device_filter(struct device_node* node, void* data)
-{
- return ((void *)node == data);
-}
-
-/*
- * Returns the PCI device matching a given OF node
- */
-int
-pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
-{
- unsigned int *reg;
- struct pci_controller* hose;
- struct pci_dev* dev = NULL;
-
- if (!have_of)
- return -ENODEV;
- /* Make sure it's really a PCI device */
- hose = pci_find_hose_for_OF_device(node);
- if (!hose || !hose->arch_data)
- return -ENODEV;
- if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,
- find_OF_pci_device_filter, (void *)node))
- return -ENODEV;
- reg = (unsigned int *) get_property(node, "reg", NULL);
- if (!reg)
- return -ENODEV;
- *bus = (reg[0] >> 16) & 0xff;
- *devfn = ((reg[0] >> 8) & 0xff);
-
- /* Ok, here we need some tweak. If we have already renumbered
- * all busses, we can't rely on the OF bus number any more.
- * the pci_to_OF_bus_map is not enough as several PCI busses
- * may match the same OF bus number.
- */
- if (!pci_to_OF_bus_map)
- return 0;
-
- for_each_pci_dev(dev)
- if (pci_to_OF_bus_map[dev->bus->number] == *bus &&
- dev->devfn == *devfn) {
- *bus = dev->bus->number;
- pci_dev_put(dev);
- return 0;
- }
-
- return -ENODEV;
-}
-EXPORT_SYMBOL(pci_device_from_OF_node);
-
-void __init
-pci_process_bridge_OF_ranges(struct pci_controller *hose,
- struct device_node *dev, int primary)
-{
- static unsigned int static_lc_ranges[256] __initdata;
- unsigned int *dt_ranges, *lc_ranges, *ranges, *prev;
- unsigned int size;
- int rlen = 0, orig_rlen;
- int memno = 0;
- struct resource *res;
- int np, na = prom_n_addr_cells(dev);
- np = na + 5;
-
- /* First we try to merge ranges to fix a problem with some pmacs
- * that can have more than 3 ranges, fortunately using contiguous
- * addresses -- BenH
- */
- dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
- if (!dt_ranges)
- return;
- /* Sanity check, though hopefully that never happens */
- if (rlen > sizeof(static_lc_ranges)) {
- printk(KERN_WARNING "OF ranges property too large !\n");
- rlen = sizeof(static_lc_ranges);
- }
- lc_ranges = static_lc_ranges;
- memcpy(lc_ranges, dt_ranges, rlen);
- orig_rlen = rlen;
-
- /* Let's work on a copy of the "ranges" property instead of damaging
- * the device-tree image in memory
- */
- ranges = lc_ranges;
- prev = NULL;
- while ((rlen -= np * sizeof(unsigned int)) >= 0) {
- if (prev) {
- if (prev[0] == ranges[0] && prev[1] == ranges[1] &&
- (prev[2] + prev[na+4]) == ranges[2] &&
- (prev[na+2] + prev[na+4]) == ranges[na+2]) {
- prev[na+4] += ranges[na+4];
- ranges[0] = 0;
- ranges += np;
- continue;
- }
- }
- prev = ranges;
- ranges += np;
- }
-
- /*
- * The ranges property is laid out as an array of elements,
- * each of which comprises:
- * cells 0 - 2: a PCI address
- * cells 3 or 3+4: a CPU physical address
- * (size depending on dev->n_addr_cells)
- * cells 4+5 or 5+6: the size of the range
- */
- ranges = lc_ranges;
- rlen = orig_rlen;
- while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {
- res = NULL;
- size = ranges[na+4];
- switch ((ranges[0] >> 24) & 0x3) {
- case 1: /* I/O space */
- if (ranges[2] != 0)
- break;
- hose->io_base_phys = ranges[na+2];
- /* limit I/O space to 16MB */
- if (size > 0x01000000)
- size = 0x01000000;
- hose->io_base_virt = ioremap(ranges[na+2], size);
- if (primary)
- isa_io_base = (unsigned long) hose->io_base_virt;
- res = &hose->io_resource;
- res->flags = IORESOURCE_IO;
- res->start = ranges[2];
- DBG("PCI: IO 0x%lx -> 0x%lx\n",
- res->start, res->start + size - 1);
- break;
- case 2: /* memory space */
- memno = 0;
- if (ranges[1] == 0 && ranges[2] == 0
- && ranges[na+4] <= (16 << 20)) {
- /* 1st 16MB, i.e. ISA memory area */
- if (primary)
- isa_mem_base = ranges[na+2];
- memno = 1;
- }
- while (memno < 3 && hose->mem_resources[memno].flags)
- ++memno;
- if (memno == 0)
- hose->pci_mem_offset = ranges[na+2] - ranges[2];
- if (memno < 3) {
- res = &hose->mem_resources[memno];
- res->flags = IORESOURCE_MEM;
- if(ranges[0] & 0x40000000)
- res->flags |= IORESOURCE_PREFETCH;
- res->start = ranges[na+2];
- DBG("PCI: MEM[%d] 0x%lx -> 0x%lx\n", memno,
- res->start, res->start + size - 1);
- }
- break;
- }
- if (res != NULL) {
- res->name = dev->full_name;
- res->end = res->start + size - 1;
- res->parent = NULL;
- res->sibling = NULL;
- res->child = NULL;
- }
- ranges += np;
- }
-}
-
-/* We create the "pci-OF-bus-map" property now so it appears in the
- * /proc device tree
- */
-void __init
-pci_create_OF_bus_map(void)
-{
- struct property* of_prop;
-
- of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256);
- if (of_prop && find_path_device("/")) {
- memset(of_prop, -1, sizeof(struct property) + 256);
- of_prop->name = "pci-OF-bus-map";
- of_prop->length = 256;
- of_prop->value = (unsigned char *)&of_prop[1];
- prom_add_property(find_path_device("/"), of_prop);
- }
-}
-
-static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct pci_dev *pdev;
- struct device_node *np;
-
- pdev = to_pci_dev (dev);
- np = pci_device_to_OF_node(pdev);
- if (np == NULL || np->full_name == NULL)
- return 0;
- return sprintf(buf, "%s", np->full_name);
-}
-static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-
-#else /* CONFIG_PPC_OF */
void pcibios_make_OF_bus_map(void)
{
}
-#endif /* CONFIG_PPC_OF */
/* Add sysfs properties */
void pcibios_add_platform_entries(struct pci_dev *pdev)
{
-#ifdef CONFIG_PPC_OF
- device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_OF */
}
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
index 2f5c7650274..75c64504374 100644
--- a/arch/ppc/kernel/ppc_htab.c
+++ b/arch/ppc/kernel/ppc_htab.c
@@ -52,7 +52,7 @@ static int ppc_htab_open(struct inode *inode, struct file *file)
return single_open(file, ppc_htab_show, NULL);
}
-struct file_operations ppc_htab_operations = {
+const struct file_operations ppc_htab_operations = {
.open = ppc_htab_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -104,7 +104,7 @@ static char *pmc2_lookup(unsigned long mmcr0)
static int ppc_htab_show(struct seq_file *m, void *v)
{
unsigned long mmcr0 = 0, pmc1 = 0, pmc2 = 0;
-#if defined(CONFIG_PPC_STD_MMU) && !defined(CONFIG_PPC64BRIDGE)
+#if defined(CONFIG_PPC_STD_MMU)
unsigned int kptes = 0, uptes = 0;
PTE *ptr;
#endif /* CONFIG_PPC_STD_MMU */
@@ -133,7 +133,6 @@ static int ppc_htab_show(struct seq_file *m, void *v)
return 0;
}
-#ifndef CONFIG_PPC64BRIDGE
for (ptr = Hash; ptr < Hash_end; ptr++) {
unsigned int mctx, vsid;
@@ -147,7 +146,6 @@ static int ppc_htab_show(struct seq_file *m, void *v)
else
uptes++;
}
-#endif
seq_printf(m,
"PTE Hash Table Information\n"
@@ -155,20 +153,16 @@ static int ppc_htab_show(struct seq_file *m, void *v)
"Buckets\t\t: %lu\n"
"Address\t\t: %08lx\n"
"Entries\t\t: %lu\n"
-#ifndef CONFIG_PPC64BRIDGE
"User ptes\t: %u\n"
"Kernel ptes\t: %u\n"
"Percent full\t: %lu%%\n"
-#endif
, (unsigned long)(Hash_size>>10),
(Hash_size/(sizeof(PTE)*8)),
(unsigned long)Hash,
Hash_size/sizeof(PTE)
-#ifndef CONFIG_PPC64BRIDGE
, uptes,
kptes,
((kptes+uptes)*100) / (Hash_size/sizeof(PTE))
-#endif
);
seq_printf(m,
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 82adb460134..865ba74991a 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -18,7 +18,6 @@
#include <linux/bitops.h>
#include <asm/page.h>
-#include <asm/semaphore.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -30,7 +29,6 @@
#include <linux/adb.h>
#include <linux/cuda.h>
#include <linux/pmu.h>
-#include <asm/prom.h>
#include <asm/system.h>
#include <asm/pci-bridge.h>
#include <asm/irq.h>
@@ -208,27 +206,6 @@ EXPORT_SYMBOL(adb_try_handler_change);
EXPORT_SYMBOL(cuda_request);
EXPORT_SYMBOL(cuda_poll);
#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_PPC_OF
-EXPORT_SYMBOL(find_devices);
-EXPORT_SYMBOL(find_type_devices);
-EXPORT_SYMBOL(find_compatible_devices);
-EXPORT_SYMBOL(find_path_device);
-EXPORT_SYMBOL(device_is_compatible);
-EXPORT_SYMBOL(machine_is_compatible);
-EXPORT_SYMBOL(find_all_nodes);
-EXPORT_SYMBOL(get_property);
-EXPORT_SYMBOL(request_OF_resource);
-EXPORT_SYMBOL(release_OF_resource);
-EXPORT_SYMBOL(of_find_node_by_name);
-EXPORT_SYMBOL(of_find_node_by_type);
-EXPORT_SYMBOL(of_find_compatible_node);
-EXPORT_SYMBOL(of_find_node_by_path);
-EXPORT_SYMBOL(of_find_all_nodes);
-EXPORT_SYMBOL(of_get_parent);
-EXPORT_SYMBOL(of_get_next_child);
-EXPORT_SYMBOL(of_node_get);
-EXPORT_SYMBOL(of_node_put);
-#endif /* CONFIG_PPC_OF */
#if defined(CONFIG_BOOTX_TEXT)
EXPORT_SYMBOL(btext_update_display);
#endif
@@ -262,9 +239,6 @@ EXPORT_SYMBOL(console_drivers);
EXPORT_SYMBOL(xmon);
EXPORT_SYMBOL(xmon_printf);
#endif
-EXPORT_SYMBOL(__up);
-EXPORT_SYMBOL(__down);
-EXPORT_SYMBOL(__down_interruptible);
#if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
extern void (*debugger)(struct pt_regs *regs);
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 53e9deacee8..1f79e84ab46 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -1,5 +1,5 @@
/*
- * Common prep/chrp boot and setup code.
+ * Common prep boot and setup code.
*/
#include <linux/config.h>
@@ -72,17 +72,12 @@ unsigned long ISA_DMA_THRESHOLD;
unsigned int DMA_MODE_READ;
unsigned int DMA_MODE_WRITE;
-#ifdef CONFIG_PPC_MULTIPLATFORM
-int _machine = 0;
-EXPORT_SYMBOL(_machine);
-
+#ifdef CONFIG_PPC_PREP
extern void prep_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7);
-extern void chrp_init(unsigned long r3, unsigned long r4,
- unsigned long r5, unsigned long r6, unsigned long r7);
dev_t boot_dev;
-#endif /* CONFIG_PPC_MULTIPLATFORM */
+#endif /* CONFIG_PPC_PREP */
int have_of;
EXPORT_SYMBOL(have_of);
@@ -319,72 +314,12 @@ early_init(int r3, int r4, int r5)
identify_cpu(offset, 0);
do_cpu_ftr_fixups(offset);
-#if defined(CONFIG_PPC_OF)
- reloc_got2(offset);
-
- /*
- * don't do anything on prep
- * for now, don't use bootinfo because it breaks yaboot 0.5
- * and assume that if we didn't find a magic number, we have OF
- */
- if (*(unsigned long *)(0) != 0xdeadc0de)
- phys = prom_init(r3, r4, (prom_entry)r5);
-
- reloc_got2(-offset);
-#endif
-
return phys;
}
-#ifdef CONFIG_PPC_OF
-/*
- * Assume here that all clock rates are the same in a
- * smp system. -- Cort
- */
-int
-of_show_percpuinfo(struct seq_file *m, int i)
-{
- struct device_node *cpu_node;
- u32 *fp;
- int s;
-
- cpu_node = find_type_devices("cpu");
- if (!cpu_node)
- return 0;
- for (s = 0; s < i && cpu_node->next; s++)
- cpu_node = cpu_node->next;
- fp = (u32 *)get_property(cpu_node, "clock-frequency", NULL);
- if (fp)
- seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000);
- return 0;
-}
-
-void __init
-intuit_machine_type(void)
-{
- char *model;
- struct device_node *root;
-
- /* ask the OF info if we're a chrp or pmac */
- root = find_path_device("/");
- if (root != 0) {
- /* assume pmac unless proven to be chrp -- Cort */
- _machine = _MACH_Pmac;
- model = get_property(root, "device_type", NULL);
- if (model && !strncmp("chrp", model, 4))
- _machine = _MACH_chrp;
- else {
- model = get_property(root, "model", NULL);
- if (model && !strncmp(model, "IBM", 3))
- _machine = _MACH_chrp;
- }
- }
-}
-#endif
-
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_PREP
/*
- * The PPC_MULTIPLATFORM version of platform_init...
+ * The PPC_PREP version of platform_init...
*/
void __init
platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
@@ -399,161 +334,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
parse_bootinfo(find_bootinfo());
- /* if we didn't get any bootinfo telling us what we are... */
- if (_machine == 0) {
- /* prep boot loader tells us if we're prep or not */
- if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
- _machine = _MACH_prep;
- }
-
-#ifdef CONFIG_PPC_PREP
- /* not much more to do here, if prep */
- if (_machine == _MACH_prep) {
- prep_init(r3, r4, r5, r6, r7);
- return;
- }
-#endif
-
-#ifdef CONFIG_PPC_OF
- have_of = 1;
-
- /* prom_init has already been called from __start */
- if (boot_infos)
- relocate_nodes();
-
- /* If we aren't PReP, we can find out if we're Pmac
- * or CHRP with this. */
- if (_machine == 0)
- intuit_machine_type();
-
- /* finish_device_tree may need _machine defined. */
- finish_device_tree();
-
- /*
- * If we were booted via quik, r3 points to the physical
- * address of the command-line parameters.
- * If we were booted from an xcoff image (i.e. netbooted or
- * booted from floppy), we get the command line from the
- * bootargs property of the /chosen node.
- * If an initial ramdisk is present, r3 and r4
- * are used for initrd_start and initrd_size,
- * otherwise they contain 0xdeadbeef.
- */
- if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) {
- strlcpy(cmd_line, (char *)r3 + KERNELBASE,
- sizeof(cmd_line));
- } else if (boot_infos != 0) {
- /* booted by BootX - check for ramdisk */
- if (boot_infos->kernelParamsOffset != 0)
- strlcpy(cmd_line, (char *) boot_infos
- + boot_infos->kernelParamsOffset,
- sizeof(cmd_line));
-#ifdef CONFIG_BLK_DEV_INITRD
- if (boot_infos->ramDisk) {
- initrd_start = (unsigned long) boot_infos
- + boot_infos->ramDisk;
- initrd_end = initrd_start + boot_infos->ramDiskSize;
- initrd_below_start_ok = 1;
- }
-#endif
- } else {
- struct device_node *chosen;
- char *p;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (r3 && r4 && r4 != 0xdeadbeef) {
- if (r3 < KERNELBASE)
- r3 += KERNELBASE;
- initrd_start = r3;
- initrd_end = r3 + r4;
- ROOT_DEV = Root_RAM0;
- initrd_below_start_ok = 1;
- }
-#endif
- chosen = find_devices("chosen");
- if (chosen != NULL) {
- p = get_property(chosen, "bootargs", NULL);
- if (p && *p) {
- strlcpy(cmd_line, p, sizeof(cmd_line));
- }
- }
- }
-#ifdef CONFIG_ADB
- if (strstr(cmd_line, "adb_sync")) {
- extern int __adb_probe_sync;
- __adb_probe_sync = 1;
- }
-#endif /* CONFIG_ADB */
-
- switch (_machine) {
-#ifdef CONFIG_PPC_CHRP
- case _MACH_chrp:
- chrp_init(r3, r4, r5, r6, r7);
- break;
-#endif
- }
-#endif /* CONFIG_PPC_OF */
+ prep_init(r3, r4, r5, r6, r7);
}
-#endif /* CONFIG_PPC_MULTIPLATFORM */
-
-#ifdef CONFIG_PPC_OF
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
-extern char *of_stdout_device;
-
-static int __init set_preferred_console(void)
-{
- struct device_node *prom_stdout;
- char *name;
- int offset = 0;
-
- if (of_stdout_device == NULL)
- return -ENODEV;
-
- /* The user has requested a console so this is already set up. */
- if (strstr(saved_command_line, "console="))
- return -EBUSY;
-
- prom_stdout = find_path_device(of_stdout_device);
- if (!prom_stdout)
- return -ENODEV;
-
- name = (char *)get_property(prom_stdout, "name", NULL);
- if (!name)
- return -ENODEV;
-
- if (strcmp(name, "serial") == 0) {
- int i;
- u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
- if (i > 8) {
- switch (reg[1]) {
- case 0x3f8:
- offset = 0;
- break;
- case 0x2f8:
- offset = 1;
- break;
- case 0x898:
- offset = 2;
- break;
- case 0x890:
- offset = 3;
- break;
- default:
- /* We dont recognise the serial port */
- return -ENODEV;
- }
- }
- } else if (strcmp(name, "ch-a") == 0)
- offset = 0;
- else if (strcmp(name, "ch-b") == 0)
- offset = 1;
- else
- return -ENODEV;
- return add_preferred_console("ttyS", offset, NULL);
-}
-console_initcall(set_preferred_console);
-#endif /* CONFIG_SERIAL_CORE_CONSOLE */
-#endif /* CONFIG_PPC_OF */
+#endif /* CONFIG_PPC_PREP */
struct bi_record *find_bootinfo(void)
{
@@ -589,23 +372,6 @@ void parse_bootinfo(struct bi_record *rec)
initrd_end = data[0] + data[1] + KERNELBASE;
break;
#endif /* CONFIG_BLK_DEV_INITRD */
-#ifdef CONFIG_PPC_MULTIPLATFORM
- case BI_MACHTYPE:
- /* Machine types changed with the merge. Since the
- * bootinfo are now deprecated, we can just hard code
- * the appropriate conversion here for when we are
- * called with yaboot which passes us a machine type
- * this way.
- */
- switch(data[0]) {
- case 1: _machine = _MACH_prep; break;
- case 2: _machine = _MACH_Pmac; break;
- case 4: _machine = _MACH_chrp; break;
- default:
- _machine = data[0];
- }
- break;
-#endif
case BI_MEMSIZE:
boot_mem_size = data[0];
break;
@@ -631,9 +397,6 @@ machine_init(unsigned long r3, unsigned long r4, unsigned long r5,
#ifdef CONFIG_6xx
ppc_md.power_save = ppc6xx_idle;
#endif
-#ifdef CONFIG_POWER4
- ppc_md.power_save = power4_idle;
-#endif
platform_init(r3, r4, r5, r6, r7);
@@ -711,7 +474,7 @@ int __init ppc_init(void)
if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
/* register CPU devices */
- for_each_cpu(i)
+ for_each_possible_cpu(i)
register_cpu(&cpu_devices[i], i, NULL);
/* call platform init */
@@ -799,7 +562,4 @@ void __init setup_arch(char **cmdline_p)
if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
paging_init();
-
- /* this is for modules since _machine can be a define -- Cort */
- ppc_md.ppc_machine = _machine;
}
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index e55cdda6149..f77795a64da 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -311,7 +311,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
/* Backup CPU 0 state */
__save_cpu_setup();
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
if (cpu == smp_processor_id())
continue;
/* create a process for the processor */
diff --git a/arch/ppc/lib/strcase.c b/arch/ppc/lib/strcase.c
index 36b521091bb..3b0094cc2b5 100644
--- a/arch/ppc/lib/strcase.c
+++ b/arch/ppc/lib/strcase.c
@@ -1,4 +1,5 @@
#include <linux/ctype.h>
+#include <linux/types.h>
int strcasecmp(const char *s1, const char *s2)
{
@@ -11,7 +12,7 @@ int strcasecmp(const char *s1, const char *s2)
return c1 - c2;
}
-int strncasecmp(const char *s1, const char *s2, int n)
+int strncasecmp(const char *s1, const char *s2, size_t n)
{
int c1, c2;
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 0217188ef46..8e08ca32531 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -202,6 +202,7 @@ good_area:
/* an exec - 4xx/Book-E allows for per-page execute permission */
} else if (TRAP(regs) == 0x400) {
pte_t *ptep;
+ pmd_t *pmdp;
#if 0
/* It would be nice to actually enforce the VM execute
@@ -215,21 +216,24 @@ good_area:
/* Since 4xx/Book-E supports per-page execute permission,
* we lazily flush dcache to icache. */
ptep = NULL;
- if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) {
- struct page *page = pte_page(*ptep);
-
- if (! test_bit(PG_arch_1, &page->flags)) {
- flush_dcache_icache_page(page);
- set_bit(PG_arch_1, &page->flags);
+ if (get_pteptr(mm, address, &ptep, &pmdp)) {
+ spinlock_t *ptl = pte_lockptr(mm, pmdp);
+ spin_lock(ptl);
+ if (pte_present(*ptep)) {
+ struct page *page = pte_page(*ptep);
+
+ if (!test_bit(PG_arch_1, &page->flags)) {
+ flush_dcache_icache_page(page);
+ set_bit(PG_arch_1, &page->flags);
+ }
+ pte_update(ptep, 0, _PAGE_HWEXEC);
+ _tlbie(address);
+ pte_unmap_unlock(ptep, ptl);
+ up_read(&mm->mmap_sem);
+ return 0;
}
- pte_update(ptep, 0, _PAGE_HWEXEC);
- _tlbie(address);
- pte_unmap(ptep);
- up_read(&mm->mmap_sem);
- return 0;
+ pte_unmap_unlock(ptep, ptl);
}
- if (ptep != NULL)
- pte_unmap(ptep);
#endif
/* a read */
} else {
diff --git a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S
index f09fa88db35..31d0a924317 100644
--- a/arch/ppc/mm/hashtable.S
+++ b/arch/ppc/mm/hashtable.S
@@ -74,12 +74,6 @@ _GLOBAL(hash_page_sync)
*/
.text
_GLOBAL(hash_page)
-#ifdef CONFIG_PPC64BRIDGE
- mfmsr r0
- clrldi r0,r0,1 /* make sure it's in 32-bit mode */
- MTMSRD(r0)
- isync
-#endif
tophys(r7,0) /* gets -KERNELBASE into r7 */
#ifdef CONFIG_SMP
addis r8,r7,mmu_hash_lock@h
@@ -303,7 +297,6 @@ Hash_base = 0xc0180000
Hash_bits = 12 /* e.g. 256kB hash table */
Hash_msk = (((1 << Hash_bits) - 1) * 64)
-#ifndef CONFIG_PPC64BRIDGE
/* defines for the PTE format for 32-bit PPCs */
#define PTE_SIZE 8
#define PTEG_SIZE 64
@@ -317,21 +310,6 @@ Hash_msk = (((1 << Hash_bits) - 1) * 64)
#define SET_V(r) oris r,r,PTE_V@h
#define CLR_V(r,t) rlwinm r,r,0,1,31
-#else
-/* defines for the PTE format for 64-bit PPCs */
-#define PTE_SIZE 16
-#define PTEG_SIZE 128
-#define LG_PTEG_SIZE 7
-#define LDPTEu ldu
-#define STPTE std
-#define CMPPTE cmpd
-#define PTE_H 2
-#define PTE_V 1
-#define TST_V(r) andi. r,r,PTE_V
-#define SET_V(r) ori r,r,PTE_V
-#define CLR_V(r,t) li t,PTE_V; andc r,r,t
-#endif /* CONFIG_PPC64BRIDGE */
-
#define HASH_LEFT 31-(LG_PTEG_SIZE+Hash_bits-1)
#define HASH_RIGHT 31-LG_PTEG_SIZE
@@ -349,14 +327,8 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_NEED_COHERENT)
/* Construct the high word of the PPC-style PTE (r5) */
-#ifndef CONFIG_PPC64BRIDGE
rlwinm r5,r3,7,1,24 /* put VSID in 0x7fffff80 bits */
rlwimi r5,r4,10,26,31 /* put in API (abbrev page index) */
-#else /* CONFIG_PPC64BRIDGE */
- clrlwi r3,r3,8 /* reduce vsid to 24 bits */
- sldi r5,r3,12 /* shift vsid into position */
- rlwimi r5,r4,16,20,24 /* put in API (abbrev page index) */
-#endif /* CONFIG_PPC64BRIDGE */
SET_V(r5) /* set V (valid) bit */
/* Get the address of the primary PTE group in the hash table (r3) */
@@ -540,14 +512,8 @@ _GLOBAL(flush_hash_pages)
add r3,r3,r0 /* note code below trims to 24 bits */
/* Construct the high word of the PPC-style PTE (r11) */
-#ifndef CONFIG_PPC64BRIDGE
rlwinm r11,r3,7,1,24 /* put VSID in 0x7fffff80 bits */
rlwimi r11,r4,10,26,31 /* put in API (abbrev page index) */
-#else /* CONFIG_PPC64BRIDGE */
- clrlwi r3,r3,8 /* reduce vsid to 24 bits */
- sldi r11,r3,12 /* shift vsid into position */
- rlwimi r11,r4,16,20,24 /* put in API (abbrev page index) */
-#endif /* CONFIG_PPC64BRIDGE */
SET_V(r11) /* set V (valid) bit */
#ifdef CONFIG_SMP
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index cb1c294fb93..386e000bcb7 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -412,14 +412,6 @@ void __init mem_init(void)
}
#endif /* CONFIG_BLK_DEV_INITRD */
-#ifdef CONFIG_PPC_OF
- /* mark the RTAS pages as reserved */
- if ( rtas_data )
- for (addr = (ulong)__va(rtas_data);
- addr < PAGE_ALIGN((ulong)__va(rtas_data)+rtas_size) ;
- addr += PAGE_SIZE)
- SetPageReserved(virt_to_page(addr));
-#endif
for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory;
addr += PAGE_SIZE) {
if (!PageReserved(virt_to_page(addr)))
@@ -494,11 +486,6 @@ set_phys_avail(unsigned long total_memory)
initrd_end - initrd_start, 1);
}
#endif /* CONFIG_BLK_DEV_INITRD */
-#ifdef CONFIG_PPC_OF
- /* remove the RTAS pages from the available memory */
- if (rtas_data)
- mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1);
-#endif
}
/* Mark some memory as reserved by removing it from phys_avail. */
diff --git a/arch/ppc/mm/mmu_context.c b/arch/ppc/mm/mmu_context.c
index a8816e0f6a8..b4a4b3f02a1 100644
--- a/arch/ppc/mm/mmu_context.c
+++ b/arch/ppc/mm/mmu_context.c
@@ -2,7 +2,7 @@
* This file contains the routines for handling the MMU on those
* PowerPC implementations where the MMU substantially follows the
* architecture specification. This includes the 6xx, 7xx, 7xxx,
- * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
+ * 8260, and 83xx implementations but excludes the 8xx and 4xx.
* -- paulus
*
* Derived from arch/ppc/mm/init.c:
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index 6ea9185fd12..706bca8eb14 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -39,7 +39,7 @@ unsigned long ioremap_base;
unsigned long ioremap_bot;
int io_bat_index;
-#if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
+#if defined(CONFIG_6xx)
#define HAVE_BATS 1
#endif
@@ -368,7 +368,7 @@ void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
* the PTE pointer is unmodified if PTE is not found.
*/
int
-get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
+get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
{
pgd_t *pgd;
pmd_t *pmd;
@@ -383,6 +383,8 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
if (pte) {
retval = 1;
*ptep = pte;
+ if (pmdp)
+ *pmdp = pmd;
/* XXX caller needs to do pte_unmap, yuck */
}
}
@@ -420,7 +422,7 @@ unsigned long iopa(unsigned long addr)
mm = &init_mm;
pa = 0;
- if (get_pteptr(mm, addr, &pte)) {
+ if (get_pteptr(mm, addr, &pte, NULL)) {
pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
pte_unmap(pte);
}
diff --git a/arch/ppc/mm/ppc_mmu.c b/arch/ppc/mm/ppc_mmu.c
index 9a381ed5eb2..25bb6f3347c 100644
--- a/arch/ppc/mm/ppc_mmu.c
+++ b/arch/ppc/mm/ppc_mmu.c
@@ -2,7 +2,7 @@
* This file contains the routines for handling the MMU on those
* PowerPC implementations where the MMU substantially follows the
* architecture specification. This includes the 6xx, 7xx, 7xxx,
- * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
+ * 8260, and 83xx implementations but excludes the 8xx and 4xx.
* -- paulus
*
* Derived from arch/ppc/mm/init.c:
@@ -42,11 +42,7 @@ unsigned long _SDR1;
union ubat { /* BAT register values to be loaded */
BAT bat;
-#ifdef CONFIG_PPC64BRIDGE
- u64 word[2];
-#else
u32 word[2];
-#endif
} BATS[4][2]; /* 4 pairs of IBAT, DBAT */
struct batrange { /* stores address ranges mapped by BATs */
@@ -83,9 +79,6 @@ unsigned long p_mapped_by_bats(unsigned long pa)
unsigned long __init mmu_mapin_ram(void)
{
-#ifdef CONFIG_POWER4
- return 0;
-#else
unsigned long tot, bl, done;
unsigned long max_size = (256<<20);
unsigned long align;
@@ -122,7 +115,6 @@ unsigned long __init mmu_mapin_ram(void)
}
return done;
-#endif
}
/*
@@ -205,27 +197,10 @@ void __init MMU_init_hw(void)
if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105);
-#ifdef CONFIG_PPC64BRIDGE
-#define LG_HPTEG_SIZE 7 /* 128 bytes per HPTEG */
-#define SDR1_LOW_BITS (lg_n_hpteg - 11)
-#define MIN_N_HPTEG 2048 /* min 256kB hash table */
-#else
#define LG_HPTEG_SIZE 6 /* 64 bytes per HPTEG */
#define SDR1_LOW_BITS ((n_hpteg - 1) >> 10)
#define MIN_N_HPTEG 1024 /* min 64kB hash table */
-#endif
-
-#ifdef CONFIG_POWER4
- /* The hash table has already been allocated and initialized
- in prom.c */
- n_hpteg = Hash_size >> LG_HPTEG_SIZE;
- lg_n_hpteg = __ilog2(n_hpteg);
-
- /* Remove the hash table from the available memory */
- if (Hash)
- reserve_phys_mem(__pa(Hash), Hash_size);
-#else /* CONFIG_POWER4 */
/*
* Allow 1 HPTE (1/8 HPTEG) for each page of memory.
* This is less than the recommended amount, but then
@@ -248,7 +223,6 @@ void __init MMU_init_hw(void)
Hash = mem_pieces_find(Hash_size, Hash_size);
cacheable_memzero(Hash, Hash_size);
_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
-#endif /* CONFIG_POWER4 */
Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index e8b91a33ce9..90c62229442 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -2,18 +2,10 @@
# Makefile for the linux kernel.
#
-# Extra CFLAGS so we don't have to do relative includes
-CFLAGS_chrp_setup.o += -Iarch/$(ARCH)/mm
-
obj-$(CONFIG_APUS) += apus_setup.o
ifeq ($(CONFIG_APUS),y)
obj-$(CONFIG_PCI) += apus_pci.o
endif
-obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o \
- chrp_pegasos_eth.o
-ifeq ($(CONFIG_PPC_CHRP),y)
-obj-$(CONFIG_NVRAM) += chrp_nvram.o
-endif
obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o
obj-$(CONFIG_PREP_RESIDUAL) += residual.o
obj-$(CONFIG_PQ2ADS) += pq2ads.o
@@ -40,7 +32,3 @@ obj-$(CONFIG_EV64360) += ev64360.o
obj-$(CONFIG_MPC86XADS) += mpc866ads_setup.o
obj-$(CONFIG_MPC885ADS) += mpc885ads_setup.o
obj-$(CONFIG_ADS8272) += mpc8272ads_setup.o
-
-ifeq ($(CONFIG_SMP),y)
-obj-$(CONFIG_PPC_CHRP) += chrp_smp.o
-endif
diff --git a/arch/ppc/platforms/chrp_nvram.c b/arch/ppc/platforms/chrp_nvram.c
deleted file mode 100644
index 465ba9b090e..00000000000
--- a/arch/ppc/platforms/chrp_nvram.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * c 2001 PPC 64 Team, IBM Corp
- *
- * 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.
- *
- * /dev/nvram driver for PPC
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <asm/uaccess.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-
-static unsigned int nvram_size;
-static unsigned char nvram_buf[4];
-static DEFINE_SPINLOCK(nvram_lock);
-
-static unsigned char chrp_nvram_read(int addr)
-{
- unsigned long done, flags;
- unsigned char ret;
-
- if (addr >= nvram_size) {
- printk(KERN_DEBUG "%s: read addr %d > nvram_size %u\n",
- current->comm, addr, nvram_size);
- return 0xff;
- }
- spin_lock_irqsave(&nvram_lock, flags);
- if ((call_rtas("nvram-fetch", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done)
- ret = 0xff;
- else
- ret = nvram_buf[0];
- spin_unlock_irqrestore(&nvram_lock, flags);
-
- return ret;
-}
-
-static void chrp_nvram_write(int addr, unsigned char val)
-{
- unsigned long done, flags;
-
- if (addr >= nvram_size) {
- printk(KERN_DEBUG "%s: write addr %d > nvram_size %u\n",
- current->comm, addr, nvram_size);
- return;
- }
- spin_lock_irqsave(&nvram_lock, flags);
- nvram_buf[0] = val;
- if ((call_rtas("nvram-store", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done)
- printk(KERN_DEBUG "rtas IO error storing 0x%02x at %d", val, addr);
- spin_unlock_irqrestore(&nvram_lock, flags);
-}
-
-void __init chrp_nvram_init(void)
-{
- struct device_node *nvram;
- unsigned int *nbytes_p, proplen;
-
- nvram = of_find_node_by_type(NULL, "nvram");
- if (nvram == NULL)
- return;
-
- nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen);
- if (nbytes_p == NULL || proplen != sizeof(unsigned int))
- return;
-
- nvram_size = *nbytes_p;
-
- printk(KERN_INFO "CHRP nvram contains %u bytes\n", nvram_size);
- of_node_put(nvram);
-
- ppc_md.nvram_read_val = chrp_nvram_read;
- ppc_md.nvram_write_val = chrp_nvram_write;
-
- return;
-}
diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c
deleted file mode 100644
index c7fe6182bb7..00000000000
--- a/arch/ppc/platforms/chrp_pci.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * CHRP pci routines.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/hydra.h>
-#include <asm/prom.h>
-#include <asm/gg2.h>
-#include <asm/machdep.h>
-#include <asm/sections.h>
-#include <asm/pci-bridge.h>
-#include <asm/open_pic.h>
-
-/* LongTrail */
-void __iomem *gg2_pci_config_base;
-
-/*
- * The VLSI Golden Gate II has only 512K of PCI configuration space, so we
- * limit the bus number to 3 bits
- */
-
-int gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off,
- int len, u32 *val)
-{
- volatile void __iomem *cfg_data;
- struct pci_controller *hose = bus->sysdata;
-
- if (bus->number > 7)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * Note: the caller has already checked that off is
- * suitably aligned and that len is 1, 2 or 4.
- */
- cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
- switch (len) {
- case 1:
- *val = in_8(cfg_data);
- break;
- case 2:
- *val = in_le16(cfg_data);
- break;
- default:
- *val = in_le32(cfg_data);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-int gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off,
- int len, u32 val)
-{
- volatile void __iomem *cfg_data;
- struct pci_controller *hose = bus->sysdata;
-
- if (bus->number > 7)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * Note: the caller has already checked that off is
- * suitably aligned and that len is 1, 2 or 4.
- */
- cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
- switch (len) {
- case 1:
- out_8(cfg_data, val);
- break;
- case 2:
- out_le16(cfg_data, val);
- break;
- default:
- out_le32(cfg_data, val);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops gg2_pci_ops =
-{
- gg2_read_config,
- gg2_write_config
-};
-
-/*
- * Access functions for PCI config space using RTAS calls.
- */
-int
-rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 *val)
-{
- struct pci_controller *hose = bus->sysdata;
- unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
- | (((bus->number - hose->first_busno) & 0xff) << 16)
- | (hose->index << 24);
- unsigned long ret = ~0UL;
- int rval;
-
- rval = call_rtas("read-pci-config", 2, 2, &ret, addr, len);
- *val = ret;
- return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
-}
-
-int
-rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 val)
-{
- struct pci_controller *hose = bus->sysdata;
- unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
- | (((bus->number - hose->first_busno) & 0xff) << 16)
- | (hose->index << 24);
- int rval;
-
- rval = call_rtas("write-pci-config", 3, 1, NULL, addr, len, val);
- return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops rtas_pci_ops =
-{
- rtas_read_config,
- rtas_write_config
-};
-
-volatile struct Hydra __iomem *Hydra = NULL;
-
-int __init
-hydra_init(void)
-{
- struct device_node *np;
-
- np = find_devices("mac-io");
- if (np == NULL || np->n_addrs == 0)
- return 0;
- Hydra = ioremap(np->addrs[0].address, np->addrs[0].size);
- printk("Hydra Mac I/O at %x\n", np->addrs[0].address);
- printk("Hydra Feature_Control was %x",
- in_le32(&Hydra->Feature_Control));
- out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN |
- HYDRA_FC_SCSI_CELL_EN |
- HYDRA_FC_SCCA_ENABLE |
- HYDRA_FC_SCCB_ENABLE |
- HYDRA_FC_ARB_BYPASS |
- HYDRA_FC_MPIC_ENABLE |
- HYDRA_FC_SLOW_SCC_PCLK |
- HYDRA_FC_MPIC_IS_MASTER));
- printk(", now %x\n", in_le32(&Hydra->Feature_Control));
- return 1;
-}
-
-void __init
-chrp_pcibios_fixup(void)
-{
- struct pci_dev *dev = NULL;
- struct device_node *np;
-
- /* PCI interrupts are controlled by the OpenPIC */
- for_each_pci_dev(dev) {
- np = pci_device_to_OF_node(dev);
- if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
- dev->irq = np->intrs[0].line;
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
- }
-}
-
-#define PRG_CL_RESET_VALID 0x00010000
-
-static void __init
-setup_python(struct pci_controller *hose, struct device_node *dev)
-{
- u32 __iomem *reg;
- u32 val;
- unsigned long addr = dev->addrs[0].address;
-
- setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010);
-
- /* Clear the magic go-slow bit */
- reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40);
- val = in_be32(&reg[12]);
- if (val & PRG_CL_RESET_VALID) {
- out_be32(&reg[12], val & ~PRG_CL_RESET_VALID);
- in_be32(&reg[12]);
- }
- iounmap(reg);
-}
-
-/* Marvell Discovery II based Pegasos 2 */
-static void __init setup_peg2(struct pci_controller *hose, struct device_node *dev)
-{
- struct device_node *root = find_path_device("/");
- struct device_node *rtas;
-
- rtas = of_find_node_by_name (root, "rtas");
- if (rtas) {
- hose->ops = &rtas_pci_ops;
- } else {
- printk ("RTAS supporting Pegasos OF not found, please upgrade"
- " your firmware\n");
- }
- pci_assign_all_buses = 1;
-}
-
-void __init
-chrp_find_bridges(void)
-{
- struct device_node *dev;
- int *bus_range;
- int len, index = -1;
- struct pci_controller *hose;
- unsigned int *dma;
- char *model, *machine;
- int is_longtrail = 0, is_mot = 0, is_pegasos = 0;
- struct device_node *root = find_path_device("/");
-
- /*
- * The PCI host bridge nodes on some machines don't have
- * properties to adequately identify them, so we have to
- * look at what sort of machine this is as well.
- */
- machine = get_property(root, "model", NULL);
- if (machine != NULL) {
- is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0;
- is_mot = strncmp(machine, "MOT", 3) == 0;
- if (strncmp(machine, "Pegasos2", 8) == 0)
- is_pegasos = 2;
- else if (strncmp(machine, "Pegasos", 7) == 0)
- is_pegasos = 1;
- }
- for (dev = root->child; dev != NULL; dev = dev->sibling) {
- if (dev->type == NULL || strcmp(dev->type, "pci") != 0)
- continue;
- ++index;
- /* The GG2 bridge on the LongTrail doesn't have an address */
- if (dev->n_addrs < 1 && !is_longtrail) {
- printk(KERN_WARNING "Can't use %s: no address\n",
- dev->full_name);
- continue;
- }
- bus_range = (int *) get_property(dev, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s\n",
- dev->full_name);
- continue;
- }
- if (bus_range[1] == bus_range[0])
- printk(KERN_INFO "PCI bus %d", bus_range[0]);
- else
- printk(KERN_INFO "PCI buses %d..%d",
- bus_range[0], bus_range[1]);
- printk(" controlled by %s", dev->type);
- if (dev->n_addrs > 0)
- printk(" at %x", dev->addrs[0].address);
- printk("\n");
-
- hose = pcibios_alloc_controller();
- if (!hose) {
- printk("Can't allocate PCI controller structure for %s\n",
- dev->full_name);
- continue;
- }
- hose->arch_data = dev;
- hose->first_busno = bus_range[0];
- hose->last_busno = bus_range[1];
-
- model = get_property(dev, "model", NULL);
- if (model == NULL)
- model = "<none>";
- if (device_is_compatible(dev, "IBM,python")) {
- setup_python(hose, dev);
- } else if (is_mot
- || strncmp(model, "Motorola, Grackle", 17) == 0) {
- setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
- } else if (is_longtrail) {
- void __iomem *p = ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
- hose->ops = &gg2_pci_ops;
- hose->cfg_data = p;
- gg2_pci_config_base = p;
- } else if (is_pegasos == 1) {
- setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc);
- } else if (is_pegasos == 2) {
- setup_peg2(hose, dev);
- } else {
- printk("No methods for %s (model %s), using RTAS\n",
- dev->full_name, model);
- hose->ops = &rtas_pci_ops;
- }
-
- pci_process_bridge_OF_ranges(hose, dev, index == 0);
-
- /* check the first bridge for a property that we can
- use to set pci_dram_offset */
- dma = (unsigned int *)
- get_property(dev, "ibm,dma-ranges", &len);
- if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) {
- pci_dram_offset = dma[2] - dma[3];
- printk("pci_dram_offset = %lx\n", pci_dram_offset);
- }
- }
-
- /* Do not fixup interrupts from OF tree on pegasos */
- if (is_pegasos == 0)
- ppc_md.pcibios_fixup = chrp_pcibios_fixup;
-}
diff --git a/arch/ppc/platforms/chrp_pegasos_eth.c b/arch/ppc/platforms/chrp_pegasos_eth.c
deleted file mode 100644
index 9305c8aa137..00000000000
--- a/arch/ppc/platforms/chrp_pegasos_eth.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2005 Sven Luther <sl@bplan-gmbh.de>
- * Thanks to :
- * Dale Farnsworth <dale@farnsworth.org>
- * Mark A. Greer <mgreer@mvista.com>
- * Nicolas DET <nd@bplan-gmbh.de>
- * Benjamin Herrenschmidt <benh@kernel.crashing.org>
- * And anyone else who helped me on this.
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/mv643xx.h>
-#include <linux/pci.h>
-
-#define PEGASOS2_MARVELL_REGBASE (0xf1000000)
-#define PEGASOS2_MARVELL_REGSIZE (0x00004000)
-#define PEGASOS2_SRAM_BASE (0xf2000000)
-#define PEGASOS2_SRAM_SIZE (256*1024)
-
-#define PEGASOS2_SRAM_BASE_ETH0 (PEGASOS2_SRAM_BASE)
-#define PEGASOS2_SRAM_BASE_ETH1 (PEGASOS2_SRAM_BASE_ETH0 + (PEGASOS2_SRAM_SIZE / 2) )
-
-
-#define PEGASOS2_SRAM_RXRING_SIZE (PEGASOS2_SRAM_SIZE/4)
-#define PEGASOS2_SRAM_TXRING_SIZE (PEGASOS2_SRAM_SIZE/4)
-
-#undef BE_VERBOSE
-
-static struct resource mv643xx_eth_shared_resources[] = {
- [0] = {
- .name = "ethernet shared base",
- .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
- .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
- MV643XX_ETH_SHARED_REGS_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device mv643xx_eth_shared_device = {
- .name = MV643XX_ETH_SHARED_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources),
- .resource = mv643xx_eth_shared_resources,
-};
-
-static struct resource mv643xx_eth0_resources[] = {
- [0] = {
- .name = "eth0 irq",
- .start = 9,
- .end = 9,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-
-static struct mv643xx_eth_platform_data eth0_pd = {
- .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH0,
- .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
- .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
-
- .rx_sram_addr = PEGASOS2_SRAM_BASE_ETH0 + PEGASOS2_SRAM_TXRING_SIZE,
- .rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
- .rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
-};
-
-static struct platform_device eth0_device = {
- .name = MV643XX_ETH_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv643xx_eth0_resources),
- .resource = mv643xx_eth0_resources,
- .dev = {
- .platform_data = &eth0_pd,
- },
-};
-
-static struct resource mv643xx_eth1_resources[] = {
- [0] = {
- .name = "eth1 irq",
- .start = 9,
- .end = 9,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
- .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH1,
- .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
- .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
-
- .rx_sram_addr = PEGASOS2_SRAM_BASE_ETH1 + PEGASOS2_SRAM_TXRING_SIZE,
- .rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
- .rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
-};
-
-static struct platform_device eth1_device = {
- .name = MV643XX_ETH_NAME,
- .id = 1,
- .num_resources = ARRAY_SIZE(mv643xx_eth1_resources),
- .resource = mv643xx_eth1_resources,
- .dev = {
- .platform_data = &eth1_pd,
- },
-};
-
-static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
- &mv643xx_eth_shared_device,
- &eth0_device,
- &eth1_device,
-};
-
-/***********/
-/***********/
-#define MV_READ(offset,val) { val = readl(mv643xx_reg_base + offset); }
-#define MV_WRITE(offset,data) writel(data, mv643xx_reg_base + offset)
-
-static void __iomem *mv643xx_reg_base;
-
-static int Enable_SRAM(void)
-{
- u32 ALong;
-
- if (mv643xx_reg_base == NULL)
- mv643xx_reg_base = ioremap(PEGASOS2_MARVELL_REGBASE,
- PEGASOS2_MARVELL_REGSIZE);
-
- if (mv643xx_reg_base == NULL)
- return -ENOMEM;
-
-#ifdef BE_VERBOSE
- printk("Pegasos II/Marvell MV64361: register remapped from %p to %p\n",
- (void *)PEGASOS2_MARVELL_REGBASE, (void *)mv643xx_reg_base);
-#endif
-
- MV_WRITE(MV64340_SRAM_CONFIG, 0);
-
- MV_WRITE(MV64340_INTEGRATED_SRAM_BASE_ADDR, PEGASOS2_SRAM_BASE >> 16);
-
- MV_READ(MV64340_BASE_ADDR_ENABLE, ALong);
- ALong &= ~(1 << 19);
- MV_WRITE(MV64340_BASE_ADDR_ENABLE, ALong);
-
- ALong = 0x02;
- ALong |= PEGASOS2_SRAM_BASE & 0xffff0000;
- MV_WRITE(MV643XX_ETH_BAR_4, ALong);
-
- MV_WRITE(MV643XX_ETH_SIZE_REG_4, (PEGASOS2_SRAM_SIZE-1) & 0xffff0000);
-
- MV_READ(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
- ALong &= ~(1 << 4);
- MV_WRITE(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
-
-#ifdef BE_VERBOSE
- printk("Pegasos II/Marvell MV64361: register unmapped\n");
- printk("Pegasos II/Marvell MV64361: SRAM at %p, size=%x\n", (void*) PEGASOS2_SRAM_BASE, PEGASOS2_SRAM_SIZE);
-#endif
-
- iounmap(mv643xx_reg_base);
- mv643xx_reg_base = NULL;
-
- return 1;
-}
-
-
-/***********/
-/***********/
-int mv643xx_eth_add_pds(void)
-{
- int ret = 0;
- static struct pci_device_id pci_marvell_mv64360[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360) },
- { }
- };
-
-#ifdef BE_VERBOSE
- printk("Pegasos II/Marvell MV64361: init\n");
-#endif
-
- if (pci_dev_present(pci_marvell_mv64360)) {
- ret = platform_add_devices(mv643xx_eth_pd_devs,
- ARRAY_SIZE(mv643xx_eth_pd_devs));
-
- if ( Enable_SRAM() < 0)
- {
- eth0_pd.tx_sram_addr = 0;
- eth0_pd.tx_sram_size = 0;
- eth0_pd.rx_sram_addr = 0;
- eth0_pd.rx_sram_size = 0;
-
- eth1_pd.tx_sram_addr = 0;
- eth1_pd.tx_sram_size = 0;
- eth1_pd.rx_sram_addr = 0;
- eth1_pd.rx_sram_size = 0;
-
-#ifdef BE_VERBOSE
- printk("Pegasos II/Marvell MV64361: Can't enable the "
- "SRAM\n");
-#endif
- }
- }
-
-#ifdef BE_VERBOSE
- printk("Pegasos II/Marvell MV64361: init is over\n");
-#endif
-
- return ret;
-}
-
-device_initcall(mv643xx_eth_add_pds);
diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c
deleted file mode 100644
index f9fd3f4f8e2..00000000000
--- a/arch/ppc/platforms/chrp_setup.c
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- * Copyright (C) 1995 Linus Torvalds
- * Adapted from 'alpha' version by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
- */
-
-/*
- * bootup setup stuff..
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/version.h>
-#include <linux/adb.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/console.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-#include <linux/initrd.h>
-#include <linux/module.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/prom.h>
-#include <asm/gg2.h>
-#include <asm/pci-bridge.h>
-#include <asm/dma.h>
-#include <asm/machdep.h>
-#include <asm/irq.h>
-#include <asm/hydra.h>
-#include <asm/sections.h>
-#include <asm/time.h>
-#include <asm/btext.h>
-#include <asm/i8259.h>
-#include <asm/open_pic.h>
-#include <asm/xmon.h>
-#include "mem_pieces.h"
-
-unsigned long chrp_get_rtc_time(void);
-int chrp_set_rtc_time(unsigned long nowtime);
-void chrp_calibrate_decr(void);
-long chrp_time_init(void);
-
-void chrp_find_bridges(void);
-void chrp_event_scan(void);
-void rtas_display_progress(char *, unsigned short);
-void rtas_indicator_progress(char *, unsigned short);
-void btext_progress(char *, unsigned short);
-
-extern int of_show_percpuinfo(struct seq_file *, int);
-
-int _chrp_type;
-EXPORT_SYMBOL(_chrp_type);
-
-/*
- * XXX this should be in xmon.h, but putting it there means xmon.h
- * has to include <linux/interrupt.h> (to get irqreturn_t), which
- * causes all sorts of problems. -- paulus
- */
-extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);
-
-extern dev_t boot_dev;
-
-extern PTE *Hash, *Hash_end;
-extern unsigned long Hash_size, Hash_mask;
-extern int probingmem;
-extern unsigned long loops_per_jiffy;
-static int max_width;
-
-#ifdef CONFIG_SMP
-extern struct smp_ops_t chrp_smp_ops;
-#endif
-
-static const char *gg2_memtypes[4] = {
- "FPM", "SDRAM", "EDO", "BEDO"
-};
-static const char *gg2_cachesizes[4] = {
- "256 KB", "512 KB", "1 MB", "Reserved"
-};
-static const char *gg2_cachetypes[4] = {
- "Asynchronous", "Reserved", "Flow-Through Synchronous",
- "Pipelined Synchronous"
-};
-static const char *gg2_cachemodes[4] = {
- "Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
-};
-
-int
-chrp_show_cpuinfo(struct seq_file *m)
-{
- int i, sdramen;
- unsigned int t;
- struct device_node *root;
- const char *model = "";
-
- root = find_path_device("/");
- if (root)
- model = get_property(root, "model", NULL);
- seq_printf(m, "machine\t\t: CHRP %s\n", model);
-
- /* longtrail (goldengate) stuff */
- if (!strncmp(model, "IBM,LongTrail", 13)) {
- /* VLSI VAS96011/12 `Golden Gate 2' */
- /* Memory banks */
- sdramen = (in_le32(gg2_pci_config_base + GG2_PCI_DRAM_CTRL)
- >>31) & 1;
- for (i = 0; i < (sdramen ? 4 : 6); i++) {
- t = in_le32(gg2_pci_config_base+
- GG2_PCI_DRAM_BANK0+
- i*4);
- if (!(t & 1))
- continue;
- switch ((t>>8) & 0x1f) {
- case 0x1f:
- model = "4 MB";
- break;
- case 0x1e:
- model = "8 MB";
- break;
- case 0x1c:
- model = "16 MB";
- break;
- case 0x18:
- model = "32 MB";
- break;
- case 0x10:
- model = "64 MB";
- break;
- case 0x00:
- model = "128 MB";
- break;
- default:
- model = "Reserved";
- break;
- }
- seq_printf(m, "memory bank %d\t: %s %s\n", i, model,
- gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]);
- }
- /* L2 cache */
- t = in_le32(gg2_pci_config_base+GG2_PCI_CC_CTRL);
- seq_printf(m, "board l2\t: %s %s (%s)\n",
- gg2_cachesizes[(t>>7) & 3],
- gg2_cachetypes[(t>>2) & 3],
- gg2_cachemodes[t & 3]);
- }
- return 0;
-}
-
-/*
- * Fixes for the National Semiconductor PC78308VUL SuperI/O
- *
- * Some versions of Open Firmware incorrectly initialize the IRQ settings
- * for keyboard and mouse
- */
-static inline void __init sio_write(u8 val, u8 index)
-{
- outb(index, 0x15c);
- outb(val, 0x15d);
-}
-
-static inline u8 __init sio_read(u8 index)
-{
- outb(index, 0x15c);
- return inb(0x15d);
-}
-
-static void __init sio_fixup_irq(const char *name, u8 device, u8 level,
- u8 type)
-{
- u8 level0, type0, active;
-
- /* select logical device */
- sio_write(device, 0x07);
- active = sio_read(0x30);
- level0 = sio_read(0x70);
- type0 = sio_read(0x71);
- if (level0 != level || type0 != type || !active) {
- printk(KERN_WARNING "sio: %s irq level %d, type %d, %sactive: "
- "remapping to level %d, type %d, active\n",
- name, level0, type0, !active ? "in" : "", level, type);
- sio_write(0x01, 0x30);
- sio_write(level, 0x70);
- sio_write(type, 0x71);
- }
-}
-
-static void __init sio_init(void)
-{
- struct device_node *root;
-
- if ((root = find_path_device("/")) &&
- !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) {
- /* logical device 0 (KBC/Keyboard) */
- sio_fixup_irq("keyboard", 0, 1, 2);
- /* select logical device 1 (KBC/Mouse) */
- sio_fixup_irq("mouse", 1, 12, 2);
- }
-}
-
-
-static void __init pegasos_set_l2cr(void)
-{
- struct device_node *np;
-
- /* On Pegasos, enable the l2 cache if needed, as the OF forgets it */
- if (_chrp_type != _CHRP_Pegasos)
- return;
-
- /* Enable L2 cache if needed */
- np = find_type_devices("cpu");
- if (np != NULL) {
- unsigned int *l2cr = (unsigned int *)
- get_property (np, "l2cr", NULL);
- if (l2cr == NULL) {
- printk ("Pegasos l2cr : no cpu l2cr property found\n");
- return;
- }
- if (!((*l2cr) & 0x80000000)) {
- printk ("Pegasos l2cr : L2 cache was not active, "
- "activating\n");
- _set_L2CR(0);
- _set_L2CR((*l2cr) | 0x80000000);
- }
- }
-}
-
-void __init chrp_setup_arch(void)
-{
- struct device_node *device;
-
- /* init to some ~sane value until calibrate_delay() runs */
- loops_per_jiffy = 50000000/HZ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- /* this is fine for chrp */
- initrd_below_start_ok = 1;
-
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
- ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
-
- /* On pegasos, enable the L2 cache if not already done by OF */
- pegasos_set_l2cr();
-
- /* Lookup PCI host bridges */
- chrp_find_bridges();
-
-#ifndef CONFIG_PPC64BRIDGE
- /*
- * Temporary fixes for PCI devices.
- * -- Geert
- */
- hydra_init(); /* Mac I/O */
-
-#endif /* CONFIG_PPC64BRIDGE */
-
- /*
- * Fix the Super I/O configuration
- */
- sio_init();
-
- /* Get the event scan rate for the rtas so we know how
- * often it expects a heartbeat. -- Cort
- */
- if ( rtas_data ) {
- struct property *p;
- device = find_devices("rtas");
- for ( p = device->properties;
- p && strncmp(p->name, "rtas-event-scan-rate", 20);
- p = p->next )
- /* nothing */ ;
- if ( p && *(unsigned long *)p->value ) {
- ppc_md.heartbeat = chrp_event_scan;
- ppc_md.heartbeat_reset = (HZ/(*(unsigned long *)p->value)*30)-1;
- ppc_md.heartbeat_count = 1;
- printk("RTAS Event Scan Rate: %lu (%lu jiffies)\n",
- *(unsigned long *)p->value, ppc_md.heartbeat_reset );
- }
- }
-
- pci_create_OF_bus_map();
-}
-
-void
-chrp_event_scan(void)
-{
- unsigned char log[1024];
- unsigned long ret = 0;
- /* XXX: we should loop until the hardware says no more error logs -- Cort */
- call_rtas( "event-scan", 4, 1, &ret, 0xffffffff, 0,
- __pa(log), 1024 );
- ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
-}
-
-void
-chrp_restart(char *cmd)
-{
- printk("RTAS system-reboot returned %d\n",
- call_rtas("system-reboot", 0, 1, NULL));
- for (;;);
-}
-
-void
-chrp_power_off(void)
-{
- /* allow power on only with power button press */
- printk("RTAS power-off returned %d\n",
- call_rtas("power-off", 2, 1, NULL,0xffffffff,0xffffffff));
- for (;;);
-}
-
-void
-chrp_halt(void)
-{
- chrp_power_off();
-}
-
-/*
- * Finds the open-pic node and sets OpenPIC_Addr based on its reg property.
- * Then checks if it has an interrupt-ranges property. If it does then
- * we have a distributed open-pic, so call openpic_set_sources to tell
- * the openpic code where to find the interrupt source registers.
- */
-static void __init chrp_find_openpic(void)
-{
- struct device_node *np;
- int len, i;
- unsigned int *iranges;
- void __iomem *isu;
-
- np = find_type_devices("open-pic");
- if (np == NULL || np->n_addrs == 0)
- return;
- printk(KERN_INFO "OpenPIC at %x (size %x)\n",
- np->addrs[0].address, np->addrs[0].size);
- OpenPIC_Addr = ioremap(np->addrs[0].address, 0x40000);
- if (OpenPIC_Addr == NULL) {
- printk(KERN_ERR "Failed to map OpenPIC!\n");
- return;
- }
-
- iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len);
- if (iranges == NULL || len < 2 * sizeof(unsigned int))
- return; /* not distributed */
-
- /*
- * The first pair of cells in interrupt-ranges refers to the
- * IDU; subsequent pairs refer to the ISUs.
- */
- len /= 2 * sizeof(unsigned int);
- if (np->n_addrs < len) {
- printk(KERN_ERR "Insufficient addresses for distributed"
- " OpenPIC (%d < %d)\n", np->n_addrs, len);
- return;
- }
- if (iranges[1] != 0) {
- printk(KERN_INFO "OpenPIC irqs %d..%d in IDU\n",
- iranges[0], iranges[0] + iranges[1] - 1);
- openpic_set_sources(iranges[0], iranges[1], NULL);
- }
- for (i = 1; i < len; ++i) {
- iranges += 2;
- printk(KERN_INFO "OpenPIC irqs %d..%d in ISU at %x (%x)\n",
- iranges[0], iranges[0] + iranges[1] - 1,
- np->addrs[i].address, np->addrs[i].size);
- isu = ioremap(np->addrs[i].address, np->addrs[i].size);
- if (isu != NULL)
- openpic_set_sources(iranges[0], iranges[1], isu);
- else
- printk(KERN_ERR "Failed to map OpenPIC ISU at %x!\n",
- np->addrs[i].address);
- }
-}
-
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
-static struct irqaction xmon_irqaction = {
- .handler = xmon_irq,
- .mask = CPU_MASK_NONE,
- .name = "XMON break",
-};
-#endif
-
-void __init chrp_init_IRQ(void)
-{
- struct device_node *np;
- unsigned long chrp_int_ack = 0;
- unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
- struct device_node *kbd;
-#endif
-
- for (np = find_devices("pci"); np != NULL; np = np->next) {
- unsigned int *addrp = (unsigned int *)
- get_property(np, "8259-interrupt-acknowledge", NULL);
-
- if (addrp == NULL)
- continue;
- chrp_int_ack = addrp[prom_n_addr_cells(np)-1];
- break;
- }
- if (np == NULL)
- printk(KERN_ERR "Cannot find PCI interrupt acknowledge address\n");
-
- chrp_find_openpic();
-
- if (OpenPIC_Addr) {
- prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
- OpenPIC_InitSenses = init_senses;
- OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
-
- openpic_init(NUM_8259_INTERRUPTS);
- /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
- openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
- i8259_irq);
-
- }
- i8259_init(chrp_int_ack, 0);
-
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
- /* see if there is a keyboard in the device tree
- with a parent of type "adb" */
- for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
- if (kbd->parent && kbd->parent->type
- && strcmp(kbd->parent->type, "adb") == 0)
- break;
- if (kbd)
- setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction);
-#endif
-}
-
-void __init
-chrp_init2(void)
-{
-#ifdef CONFIG_NVRAM
- chrp_nvram_init();
-#endif
-
- request_region(0x20,0x20,"pic1");
- request_region(0xa0,0x20,"pic2");
- request_region(0x00,0x20,"dma1");
- request_region(0x40,0x20,"timer");
- request_region(0x80,0x10,"dma page reg");
- request_region(0xc0,0x20,"dma2");
-
- if (ppc_md.progress)
- ppc_md.progress(" Have fun! ", 0x7777);
-}
-
-static struct device_node *memory_node;
-
-static int __init get_mem_prop(char *name, struct mem_pieces *mp)
-{
- struct reg_property *rp;
- int i, s;
- unsigned int *ip;
- int nac = prom_n_addr_cells(memory_node);
- int nsc = prom_n_size_cells(memory_node);
-
- ip = (unsigned int *) get_property(memory_node, name, &s);
- if (ip == NULL) {
- printk(KERN_ERR "error: couldn't get %s property on /memory\n",
- name);
- return 0;
- }
- s /= (nsc + nac) * 4;
- rp = mp->regions;
- for (i = 0; i < s; ++i, ip += nac+nsc) {
- if (nac >= 2 && ip[nac-2] != 0)
- continue;
- rp->address = ip[nac-1];
- if (nsc >= 2 && ip[nac+nsc-2] != 0)
- rp->size = ~0U;
- else
- rp->size = ip[nac+nsc-1];
- ++rp;
- }
- mp->n_regions = rp - mp->regions;
-
- /* Make sure the pieces are sorted. */
- mem_pieces_sort(mp);
- mem_pieces_coalesce(mp);
- return 1;
-}
-
-static unsigned long __init chrp_find_end_of_memory(void)
-{
- unsigned long a, total;
- struct mem_pieces phys_mem;
-
- /*
- * Find out where physical memory is, and check that it
- * starts at 0 and is contiguous. It seems that RAM is
- * always physically contiguous on Power Macintoshes.
- *
- * Supporting discontiguous physical memory isn't hard,
- * it just makes the virtual <-> physical mapping functions
- * more complicated (or else you end up wasting space
- * in mem_map).
- */
- memory_node = find_devices("memory");
- if (memory_node == NULL || !get_mem_prop("reg", &phys_mem)
- || phys_mem.n_regions == 0)
- panic("No RAM??");
- a = phys_mem.regions[0].address;
- if (a != 0)
- panic("RAM doesn't start at physical address 0");
- total = phys_mem.regions[0].size;
-
- if (phys_mem.n_regions > 1) {
- printk("RAM starting at 0x%x is not contiguous\n",
- phys_mem.regions[1].address);
- printk("Using RAM from 0 to 0x%lx\n", total-1);
- }
-
- return total;
-}
-
-void __init
-chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- struct device_node *root = find_path_device ("/");
- char *machine = NULL;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- /* take care of initrd if we have one */
- if ( r6 )
- {
- initrd_start = r6 + KERNELBASE;
- initrd_end = r6 + r7 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- ISA_DMA_THRESHOLD = ~0L;
- DMA_MODE_READ = 0x44;
- DMA_MODE_WRITE = 0x48;
- isa_io_base = CHRP_ISA_IO_BASE; /* default value */
- ppc_do_canonicalize_irqs = 1;
-
- if (root)
- machine = get_property(root, "model", NULL);
- if (machine && strncmp(machine, "Pegasos", 7) == 0) {
- _chrp_type = _CHRP_Pegasos;
- } else if (machine && strncmp(machine, "IBM", 3) == 0) {
- _chrp_type = _CHRP_IBM;
- } else if (machine && strncmp(machine, "MOT", 3) == 0) {
- _chrp_type = _CHRP_Motorola;
- } else {
- /* Let's assume it is an IBM chrp if all else fails */
- _chrp_type = _CHRP_IBM;
- }
-
- ppc_md.setup_arch = chrp_setup_arch;
- ppc_md.show_percpuinfo = of_show_percpuinfo;
- ppc_md.show_cpuinfo = chrp_show_cpuinfo;
-
- ppc_md.init_IRQ = chrp_init_IRQ;
- if (_chrp_type == _CHRP_Pegasos)
- ppc_md.get_irq = i8259_irq;
- else
- ppc_md.get_irq = openpic_get_irq;
-
- ppc_md.init = chrp_init2;
-
- ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
-
- ppc_md.restart = chrp_restart;
- ppc_md.power_off = chrp_power_off;
- ppc_md.halt = chrp_halt;
-
- ppc_md.time_init = chrp_time_init;
- ppc_md.set_rtc_time = chrp_set_rtc_time;
- ppc_md.get_rtc_time = chrp_get_rtc_time;
- ppc_md.calibrate_decr = chrp_calibrate_decr;
-
- ppc_md.find_end_of_memory = chrp_find_end_of_memory;
-
- if (rtas_data) {
- struct device_node *rtas;
- unsigned int *p;
-
- rtas = find_devices("rtas");
- if (rtas != NULL) {
- if (get_property(rtas, "display-character", NULL)) {
- ppc_md.progress = rtas_display_progress;
- p = (unsigned int *) get_property
- (rtas, "ibm,display-line-length", NULL);
- if (p)
- max_width = *p;
- } else if (get_property(rtas, "set-indicator", NULL))
- ppc_md.progress = rtas_indicator_progress;
- }
- }
-#ifdef CONFIG_BOOTX_TEXT
- if (ppc_md.progress == NULL && boot_text_mapped)
- ppc_md.progress = btext_progress;
-#endif
-
-#ifdef CONFIG_SMP
- smp_ops = &chrp_smp_ops;
-#endif /* CONFIG_SMP */
-
- /*
- * Print the banner, then scroll down so boot progress
- * can be printed. -- Cort
- */
- if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
-}
-
-void
-rtas_display_progress(char *s, unsigned short hex)
-{
- int width;
- char *os = s;
-
- if ( call_rtas( "display-character", 1, 1, NULL, '\r' ) )
- return;
-
- width = max_width;
- while ( *os )
- {
- if ( (*os == '\n') || (*os == '\r') )
- width = max_width;
- else
- width--;
- call_rtas( "display-character", 1, 1, NULL, *os++ );
- /* if we overwrite the screen length */
- if ( width == 0 )
- while ( (*os != 0) && (*os != '\n') && (*os != '\r') )
- os++;
- }
-
- /*while ( width-- > 0 )*/
- call_rtas( "display-character", 1, 1, NULL, ' ' );
-}
-
-void
-rtas_indicator_progress(char *s, unsigned short hex)
-{
- call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex);
-}
-
-#ifdef CONFIG_BOOTX_TEXT
-void
-btext_progress(char *s, unsigned short hex)
-{
- prom_print(s);
- prom_print("\n");
-}
-#endif /* CONFIG_BOOTX_TEXT */
diff --git a/arch/ppc/platforms/chrp_smp.c b/arch/ppc/platforms/chrp_smp.c
deleted file mode 100644
index 97e539557ec..00000000000
--- a/arch/ppc/platforms/chrp_smp.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Smp support for CHRP machines.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
- * deal of code from the sparc and intel versions.
- *
- * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.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>
-
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/smp.h>
-#include <asm/residual.h>
-#include <asm/time.h>
-#include <asm/open_pic.h>
-#include <asm/machdep.h>
-
-extern unsigned long smp_chrp_cpu_nr;
-
-static int __init
-smp_chrp_probe(void)
-{
- if (smp_chrp_cpu_nr > 1)
- openpic_request_IPIs();
-
- return smp_chrp_cpu_nr;
-}
-
-static void __devinit
-smp_chrp_kick_cpu(int nr)
-{
- *(unsigned long *)KERNELBASE = nr;
- asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
-}
-
-static void __devinit
-smp_chrp_setup_cpu(int cpu_nr)
-{
- if (OpenPIC_Addr)
- do_openpic_setup_cpu();
-}
-
-static DEFINE_SPINLOCK(timebase_lock);
-static unsigned int timebase_upper = 0, timebase_lower = 0;
-
-void __devinit
-smp_chrp_give_timebase(void)
-{
- spin_lock(&timebase_lock);
- call_rtas("freeze-time-base", 0, 1, NULL);
- timebase_upper = get_tbu();
- timebase_lower = get_tbl();
- spin_unlock(&timebase_lock);
-
- while (timebase_upper || timebase_lower)
- barrier();
- call_rtas("thaw-time-base", 0, 1, NULL);
-}
-
-void __devinit
-smp_chrp_take_timebase(void)
-{
- while (!(timebase_upper || timebase_lower))
- barrier();
- spin_lock(&timebase_lock);
- set_tb(timebase_upper, timebase_lower);
- timebase_upper = 0;
- timebase_lower = 0;
- spin_unlock(&timebase_lock);
- printk("CPU %i taken timebase\n", smp_processor_id());
-}
-
-/* CHRP with openpic */
-struct smp_ops_t chrp_smp_ops = {
- .message_pass = smp_openpic_message_pass,
- .probe = smp_chrp_probe,
- .kick_cpu = smp_chrp_kick_cpu,
- .setup_cpu = smp_chrp_setup_cpu,
- .give_timebase = smp_chrp_give_timebase,
- .take_timebase = smp_chrp_take_timebase,
-};
diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c
deleted file mode 100644
index c8627770af1..00000000000
--- a/arch/ppc/platforms/chrp_time.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 1991, 1992, 1995 Linus Torvalds
- *
- * Adapted for PowerPC (PReP) by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu).
- * Copied and modified from arch/i386/kernel/time.c
- *
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/kernel_stat.h>
-#include <linux/mc146818rtc.h>
-#include <linux/init.h>
-#include <linux/bcd.h>
-
-#include <asm/io.h>
-#include <asm/nvram.h>
-#include <asm/prom.h>
-#include <asm/sections.h>
-#include <asm/time.h>
-
-extern spinlock_t rtc_lock;
-
-static int nvram_as1 = NVRAM_AS1;
-static int nvram_as0 = NVRAM_AS0;
-static int nvram_data = NVRAM_DATA;
-
-long __init chrp_time_init(void)
-{
- struct device_node *rtcs;
- int base;
-
- rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
- if (rtcs == NULL)
- rtcs = find_compatible_devices("rtc", "ds1385-rtc");
- if (rtcs == NULL || rtcs->addrs == NULL)
- return 0;
- base = rtcs->addrs[0].address;
- nvram_as1 = 0;
- nvram_as0 = base;
- nvram_data = base + 1;
-
- return 0;
-}
-
-int chrp_cmos_clock_read(int addr)
-{
- if (nvram_as1 != 0)
- outb(addr>>8, nvram_as1);
- outb(addr, nvram_as0);
- return (inb(nvram_data));
-}
-
-void chrp_cmos_clock_write(unsigned long val, int addr)
-{
- if (nvram_as1 != 0)
- outb(addr>>8, nvram_as1);
- outb(addr, nvram_as0);
- outb(val, nvram_data);
- return;
-}
-
-/*
- * Set the hardware clock. -- Cort
- */
-int chrp_set_rtc_time(unsigned long nowtime)
-{
- unsigned char save_control, save_freq_select;
- struct rtc_time tm;
-
- spin_lock(&rtc_lock);
- to_tm(nowtime, &tm);
-
- save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
-
- chrp_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);
-
- save_freq_select = chrp_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
-
- chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
- tm.tm_year -= 1900;
- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BIN_TO_BCD(tm.tm_sec);
- BIN_TO_BCD(tm.tm_min);
- BIN_TO_BCD(tm.tm_hour);
- BIN_TO_BCD(tm.tm_mon);
- BIN_TO_BCD(tm.tm_mday);
- BIN_TO_BCD(tm.tm_year);
- }
- chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
- chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES);
- chrp_cmos_clock_write(tm.tm_hour,RTC_HOURS);
- chrp_cmos_clock_write(tm.tm_mon,RTC_MONTH);
- chrp_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);
- chrp_cmos_clock_write(tm.tm_year,RTC_YEAR);
-
- /* The following flags have to be released exactly in this order,
- * otherwise the DS12887 (popular MC146818A clone with integrated
- * battery and quartz) will not reset the oscillator and will not
- * update precisely 500 ms later. You won't find this mentioned in
- * the Dallas Semiconductor data sheets, but who believes data
- * sheets anyway ... -- Markus Kuhn
- */
- chrp_cmos_clock_write(save_control, RTC_CONTROL);
- chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
-
- spin_unlock(&rtc_lock);
- return 0;
-}
-
-unsigned long chrp_get_rtc_time(void)
-{
- unsigned int year, mon, day, hour, min, sec;
- int uip, i;
-
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
-
- /* Since the UIP flag is set for about 2.2 ms and the clock
- * is typically written with a precision of 1 jiffy, trying
- * to obtain a precision better than a few milliseconds is
- * an illusion. Only consistency is interesting, this also
- * allows to use the routine for /dev/rtc without a potential
- * 1 second kernel busy loop triggered by any reader of /dev/rtc.
- */
-
- for ( i = 0; i<1000000; i++) {
- uip = chrp_cmos_clock_read(RTC_FREQ_SELECT);
- sec = chrp_cmos_clock_read(RTC_SECONDS);
- min = chrp_cmos_clock_read(RTC_MINUTES);
- hour = chrp_cmos_clock_read(RTC_HOURS);
- day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
- mon = chrp_cmos_clock_read(RTC_MONTH);
- year = chrp_cmos_clock_read(RTC_YEAR);
- uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT);
- if ((uip & RTC_UIP)==0) break;
- }
-
- if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
- if ((year += 1900) < 1970)
- year += 100;
- return mktime(year, mon, day, hour, min, sec);
-}
-
-/*
- * Calibrate the decrementer frequency with the VIA timer 1.
- */
-#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */
-
-/* VIA registers */
-#define RS 0x200 /* skip between registers */
-#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
-#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
-#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
-#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
-#define ACR (11*RS) /* Auxiliary control register */
-#define IFR (13*RS) /* Interrupt flag register */
-
-/* Bits in ACR */
-#define T1MODE 0xc0 /* Timer 1 mode */
-#define T1MODE_CONT 0x40 /* continuous interrupts */
-
-/* Bits in IFR and IER */
-#define T1_INT 0x40 /* Timer 1 interrupt */
-
-static int __init chrp_via_calibrate_decr(void)
-{
- struct device_node *vias;
- volatile unsigned char __iomem *via;
- int count = VIA_TIMER_FREQ_6 / 100;
- unsigned int dstart, dend;
-
- vias = find_devices("via-cuda");
- if (vias == 0)
- vias = find_devices("via");
- if (vias == 0 || vias->n_addrs == 0)
- return 0;
- via = ioremap(vias->addrs[0].address, vias->addrs[0].size);
-
- /* set timer 1 for continuous interrupts */
- out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
- /* set the counter to a small value */
- out_8(&via[T1CH], 2);
- /* set the latch to `count' */
- out_8(&via[T1LL], count);
- out_8(&via[T1LH], count >> 8);
- /* wait until it hits 0 */
- while ((in_8(&via[IFR]) & T1_INT) == 0)
- ;
- dstart = get_dec();
- /* clear the interrupt & wait until it hits 0 again */
- in_8(&via[T1CL]);
- while ((in_8(&via[IFR]) & T1_INT) == 0)
- ;
- dend = get_dec();
-
- tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100);
- tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);
-
- printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
- tb_ticks_per_jiffy, dstart - dend);
-
- iounmap(via);
-
- return 1;
-}
-
-void __init chrp_calibrate_decr(void)
-{
- struct device_node *cpu;
- unsigned int freq, *fp;
-
- if (chrp_via_calibrate_decr())
- return;
-
- /*
- * The cpu node should have a timebase-frequency property
- * to tell us the rate at which the decrementer counts.
- */
- freq = 16666000; /* hardcoded default */
- cpu = find_type_devices("cpu");
- if (cpu != 0) {
- fp = (unsigned int *)
- get_property(cpu, "timebase-frequency", NULL);
- if (fp != 0)
- freq = *fp;
- }
- printk("time_init: decrementer frequency = %u.%.6u MHz\n",
- freq/1000000, freq%1000000);
- tb_ticks_per_jiffy = freq / HZ;
- tb_to_us = mulhwu_scale_factor(freq, 1000000);
-}
diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c
index 5171b53bccb..fecbe9adc9e 100644
--- a/arch/ppc/platforms/lite5200.c
+++ b/arch/ppc/platforms/lite5200.c
@@ -34,8 +34,7 @@
#include <asm/mpc52xx.h>
#include <asm/ppc_sys.h>
#include <asm/machdep.h>
-
-#include <syslib/mpc52xx_pci.h>
+#include <asm/pci-bridge.h>
extern int powersave_nap;
@@ -68,44 +67,53 @@ lite5200_show_cpuinfo(struct seq_file *m)
}
#ifdef CONFIG_PCI
+#ifdef CONFIG_LITE5200B
+static int
+lite5200_map_irq(struct pci_dev *dev, unsigned char idsel,
+ unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {MPC52xx_IRQ0, MPC52xx_IRQ1, MPC52xx_IRQ2, MPC52xx_IRQ3},
+ {MPC52xx_IRQ1, MPC52xx_IRQ2, MPC52xx_IRQ3, MPC52xx_IRQ0},
+ };
+
+ const long min_idsel = 24, max_idsel = 25, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+#else /* Original Lite */
static int
lite5200_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
{
return (pin == 1) && (idsel==24) ? MPC52xx_IRQ0 : -1;
}
#endif
+#endif
static void __init
lite5200_setup_cpu(void)
{
- struct mpc52xx_cdm __iomem *cdm;
struct mpc52xx_gpio __iomem *gpio;
struct mpc52xx_intr __iomem *intr;
- struct mpc52xx_xlb __iomem *xlb;
u32 port_config;
u32 intr_ctrl;
/* Map zones */
- cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
- xlb = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);
intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
- if (!cdm || !gpio || !xlb || !intr) {
- printk("lite5200.c: Error while mapping CDM/GPIO/XLB/INTR during"
- "lite5200_setup_cpu\n");
+ if (!gpio || !intr) {
+ printk(KERN_ERR __FILE__ ": "
+ "Error while mapping GPIO/INTR during "
+ "lite5200_setup_cpu\n");
goto unmap_regs;
}
- /* Use internal 48 Mhz */
- out_8(&cdm->ext_48mhz_en, 0x00);
- out_8(&cdm->fd_enable, 0x01);
- if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */
- out_be16(&cdm->fd_counters, 0x0001);
- else
- out_be16(&cdm->fd_counters, 0x5555);
-
/* Get port mux config */
port_config = in_be32(&gpio->port_config);
@@ -116,29 +124,29 @@ lite5200_setup_cpu(void)
port_config &= ~0x00007000; /* Differential mode - USB1 only */
port_config |= 0x00001000;
+ /* ATA CS is on csb_4/5 */
+ port_config &= ~0x03000000;
+ port_config |= 0x01000000;
+
/* Commit port config */
out_be32(&gpio->port_config, port_config);
- /* Configure the XLB Arbiter */
- out_be32(&xlb->master_pri_enable, 0xff);
- out_be32(&xlb->master_priority, 0x11111111);
-
- /* Enable ram snooping for 1GB window */
- out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP);
- out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d);
-
- /* IRQ[0-3] setup : IRQ0 - Level Active Low */
- /* IRQ[1-3] - Level Active High */
+ /* IRQ[0-3] setup */
intr_ctrl = in_be32(&intr->ctrl);
intr_ctrl &= ~0x00ff0000;
- intr_ctrl |= 0x00c00000;
+#ifdef CONFIG_LITE5200B
+ /* IRQ[0-3] Level Active Low */
+ intr_ctrl |= 0x00ff0000;
+#else
+ /* IRQ0 Level Active Low
+ * IRQ[1-3] Level Active High */
+ intr_ctrl |= 0x00c00000;
+#endif
out_be32(&intr->ctrl, intr_ctrl);
/* Unmap reg zone */
unmap_regs:
- if (cdm) iounmap(cdm);
if (gpio) iounmap(gpio);
- if (xlb) iounmap(xlb);
if (intr) iounmap(intr);
}
@@ -146,7 +154,8 @@ static void __init
lite5200_setup_arch(void)
{
/* CPU & Port mux setup */
- lite5200_setup_cpu();
+ mpc52xx_setup_cpu(); /* Generic */
+ lite5200_setup_cpu(); /* Platform specific */
#ifdef CONFIG_PCI
/* PCI Bridge setup */
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index a0fc628ffb1..e86f6156d58 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -736,7 +736,7 @@ ibm_statusled_progress(char *s, unsigned short hex)
hex = 0xfff;
if (!notifier_installed) {
++notifier_installed;
- notifier_chain_register(&panic_notifier_list,
+ atomic_notifier_chain_register(&panic_notifier_list,
&ibm_statusled_block);
}
}
@@ -1067,15 +1067,13 @@ prep_map_io(void)
static int __init
prep_request_io(void)
{
- if (_machine == _MACH_prep) {
#ifdef CONFIG_NVRAM
- request_region(PREP_NVRAM_AS0, 0x8, "nvram");
+ request_region(PREP_NVRAM_AS0, 0x8, "nvram");
#endif
- request_region(0x00,0x20,"dma1");
- request_region(0x40,0x20,"timer");
- request_region(0x80,0x10,"dma page reg");
- request_region(0xc0,0x20,"dma2");
- }
+ request_region(0x00,0x20,"dma1");
+ request_region(0x40,0x20,"timer");
+ request_region(0x80,0x10,"dma page reg");
+ request_region(0xc0,0x20,"dma2");
return 0;
}
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 5cb62c6a51c..490749ca88f 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -38,8 +38,6 @@ endif
obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \
ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o
obj-$(CONFIG_PCI_QSPAN) += qspan_pci.o
-obj-$(CONFIG_PPC_OF) += prom_init.o prom.o
-obj-$(CONFIG_PPC_CHRP) += open_pic.o
obj-$(CONFIG_PPC_PREP) += open_pic.o todc_time.o
obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o
obj-$(CONFIG_CPCI690) += todc_time.o pci_auto.o
diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c
index 9ec525f9fe9..5a5a7a9cd24 100644
--- a/arch/ppc/syslib/mpc52xx_pci.c
+++ b/arch/ppc/syslib/mpc52xx_pci.c
@@ -225,7 +225,8 @@ mpc52xx_pci_fixup_resources(struct pci_dev *dev)
/* The PCI Host bridge of MPC52xx has a prefetch memory resource
fixed to 1Gb. Doesn't fit in the resource system so we remove it */
if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
- (dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200) ) {
+ ( dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
+ || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
struct resource *res = &dev->resource[1];
res->start = res->end = res->flags = 0;
}
diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
index 2ee48ce0a51..ee6379bb415 100644
--- a/arch/ppc/syslib/mpc52xx_setup.c
+++ b/arch/ppc/syslib/mpc52xx_setup.c
@@ -24,6 +24,8 @@
#include <asm/pgtable.h>
#include <asm/ppcboot.h>
+#include <syslib/mpc52xx_pci.h>
+
extern bd_t __res;
static int core_mult[] = { /* CPU Frequency multiplier, taken */
@@ -216,6 +218,52 @@ mpc52xx_calibrate_decr(void)
tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
}
+
+void __init
+mpc52xx_setup_cpu(void)
+{
+ struct mpc52xx_cdm __iomem *cdm;
+ struct mpc52xx_xlb __iomem *xlb;
+
+ /* Map zones */
+ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
+ xlb = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);
+
+ if (!cdm || !xlb) {
+ printk(KERN_ERR __FILE__ ": "
+ "Error while mapping CDM/XLB during "
+ "mpc52xx_setup_cpu\n");
+ goto unmap_regs;
+ }
+
+ /* Use internal 48 Mhz */
+ out_8(&cdm->ext_48mhz_en, 0x00);
+ out_8(&cdm->fd_enable, 0x01);
+ if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */
+ out_be16(&cdm->fd_counters, 0x0001);
+ else
+ out_be16(&cdm->fd_counters, 0x5555);
+
+ /* Configure the XLB Arbiter priorities */
+ out_be32(&xlb->master_pri_enable, 0xff);
+ out_be32(&xlb->master_priority, 0x11111111);
+
+ /* Enable ram snooping for 1GB window */
+ out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP);
+ out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d);
+
+ /* Disable XLB pipelining */
+ /* (cfr errate 292. We could do this only just before ATA PIO
+ transaction and re-enable it after ...) */
+ out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS);
+
+ /* Unmap reg zone */
+unmap_regs:
+ if (cdm) iounmap(cdm);
+ if (xlb) iounmap(xlb);
+}
+
+
int mpc52xx_match_psc_function(int psc_idx, const char *func)
{
struct mpc52xx_psc_func *cf = mpc52xx_psc_functions;
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
index 38e5b93fbe4..70456c8f998 100644
--- a/arch/ppc/syslib/open_pic.c
+++ b/arch/ppc/syslib/open_pic.c
@@ -216,7 +216,7 @@ static void openpic_safe_writefield(volatile u_int __iomem *addr, u_int mask,
u_int openpic_read_IPI(volatile u_int __iomem * addr)
{
u_int val = 0;
-#if defined(OPENPIC_BIG_ENDIAN) || defined(CONFIG_POWER3)
+#if defined(OPENPIC_BIG_ENDIAN)
val = in_be32(addr);
#else
val = in_le32(addr);
diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c
deleted file mode 100644
index 482f837fd37..00000000000
--- a/arch/ppc/syslib/prom.c
+++ /dev/null
@@ -1,1429 +0,0 @@
-/*
- * Procedures for interfacing to the Open Firmware PROM on
- * Power Macintosh computers.
- *
- * In particular, we are interested in the device tree
- * and in using some of its services (exit, write to stdout).
- *
- * Paul Mackerras August 1996.
- * Copyright (C) 1996 Paul Mackerras.
- */
-#include <stdarg.h>
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/threads.h>
-#include <linux/spinlock.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-
-#include <asm/sections.h>
-#include <asm/prom.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/bootx.h>
-#include <asm/system.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-#include <asm/bootinfo.h>
-#include <asm/btext.h>
-#include <asm/pci-bridge.h>
-#include <asm/open_pic.h>
-
-
-struct pci_address {
- unsigned a_hi;
- unsigned a_mid;
- unsigned a_lo;
-};
-
-struct pci_reg_property {
- struct pci_address addr;
- unsigned size_hi;
- unsigned size_lo;
-};
-
-struct isa_reg_property {
- unsigned space;
- unsigned address;
- unsigned size;
-};
-
-typedef unsigned long interpret_func(struct device_node *, unsigned long,
- int, int);
-static interpret_func interpret_pci_props;
-static interpret_func interpret_dbdma_props;
-static interpret_func interpret_isa_props;
-static interpret_func interpret_macio_props;
-static interpret_func interpret_root_props;
-
-extern char *klimit;
-
-/* Set for a newworld or CHRP machine */
-int use_of_interrupt_tree;
-struct device_node *dflt_interrupt_controller;
-int num_interrupt_controllers;
-
-extern unsigned int rtas_entry; /* physical pointer */
-
-extern struct device_node *allnodes;
-
-static unsigned long finish_node(struct device_node *, unsigned long,
- interpret_func *, int, int);
-static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
-static struct device_node *find_phandle(phandle);
-
-extern void enter_rtas(void *);
-void phys_call_rtas(int, int, int, ...);
-
-extern char cmd_line[512]; /* XXX */
-extern boot_infos_t *boot_infos;
-unsigned long dev_tree_size;
-
-void
-phys_call_rtas(int service, int nargs, int nret, ...)
-{
- va_list list;
- union {
- unsigned long words[16];
- double align;
- } u;
- void (*rtas)(void *, unsigned long);
- int i;
-
- u.words[0] = service;
- u.words[1] = nargs;
- u.words[2] = nret;
- va_start(list, nret);
- for (i = 0; i < nargs; ++i)
- u.words[i+3] = va_arg(list, unsigned long);
- va_end(list);
-
- rtas = (void (*)(void *, unsigned long)) rtas_entry;
- rtas(&u, rtas_data);
-}
-
-/*
- * finish_device_tree is called once things are running normally
- * (i.e. with text and data mapped to the address they were linked at).
- * It traverses the device tree and fills in the name, type,
- * {n_}addrs and {n_}intrs fields of each node.
- */
-void __init
-finish_device_tree(void)
-{
- unsigned long mem = (unsigned long) klimit;
- struct device_node *np;
-
- /* All CHRPs now use the interrupt tree */
- for (np = allnodes; np != NULL; np = np->allnext) {
- if (get_property(np, "interrupt-parent", NULL)) {
- use_of_interrupt_tree = 1;
- break;
- }
- }
-
- if (use_of_interrupt_tree) {
- /*
- * We want to find out here how many interrupt-controller
- * nodes there are, and if we are booted from BootX,
- * we need a pointer to the first (and hopefully only)
- * such node. But we can't use find_devices here since
- * np->name has not been set yet. -- paulus
- */
- int n = 0;
- char *name, *ic;
- int iclen;
-
- for (np = allnodes; np != NULL; np = np->allnext) {
- ic = get_property(np, "interrupt-controller", &iclen);
- name = get_property(np, "name", NULL);
- /* checking iclen makes sure we don't get a false
- match on /chosen.interrupt_controller */
- if ((name != NULL
- && strcmp(name, "interrupt-controller") == 0)
- || (ic != NULL && iclen == 0 && strcmp(name, "AppleKiwi"))) {
- if (n == 0)
- dflt_interrupt_controller = np;
- ++n;
- }
- }
- num_interrupt_controllers = n;
- }
-
- mem = finish_node(allnodes, mem, NULL, 1, 1);
- dev_tree_size = mem - (unsigned long) allnodes;
- klimit = (char *) mem;
-}
-
-static unsigned long __init
-finish_node(struct device_node *np, unsigned long mem_start,
- interpret_func *ifunc, int naddrc, int nsizec)
-{
- struct device_node *child;
- int *ip;
-
- np->name = get_property(np, "name", NULL);
- np->type = get_property(np, "device_type", NULL);
-
- if (!np->name)
- np->name = "<NULL>";
- if (!np->type)
- np->type = "<NULL>";
-
- /* get the device addresses and interrupts */
- if (ifunc != NULL)
- mem_start = ifunc(np, mem_start, naddrc, nsizec);
-
- if (use_of_interrupt_tree)
- mem_start = finish_node_interrupts(np, mem_start);
-
- /* Look for #address-cells and #size-cells properties. */
- ip = (int *) get_property(np, "#address-cells", NULL);
- if (ip != NULL)
- naddrc = *ip;
- ip = (int *) get_property(np, "#size-cells", NULL);
- if (ip != NULL)
- nsizec = *ip;
-
- if (np->parent == NULL)
- ifunc = interpret_root_props;
- else if (np->type == 0)
- ifunc = NULL;
- else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
- ifunc = interpret_pci_props;
- else if (!strcmp(np->type, "dbdma"))
- ifunc = interpret_dbdma_props;
- else if (!strcmp(np->type, "mac-io")
- || ifunc == interpret_macio_props)
- ifunc = interpret_macio_props;
- else if (!strcmp(np->type, "isa"))
- ifunc = interpret_isa_props;
- else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3"))
- ifunc = interpret_root_props;
- else if (!((ifunc == interpret_dbdma_props
- || ifunc == interpret_macio_props)
- && (!strcmp(np->type, "escc")
- || !strcmp(np->type, "media-bay"))))
- ifunc = NULL;
-
- /* if we were booted from BootX, convert the full name */
- if (boot_infos
- && strncmp(np->full_name, "Devices:device-tree", 19) == 0) {
- if (np->full_name[19] == 0) {
- strcpy(np->full_name, "/");
- } else if (np->full_name[19] == ':') {
- char *p = np->full_name + 19;
- np->full_name = p;
- for (; *p; ++p)
- if (*p == ':')
- *p = '/';
- }
- }
-
- for (child = np->child; child != NULL; child = child->sibling)
- mem_start = finish_node(child, mem_start, ifunc,
- naddrc, nsizec);
-
- return mem_start;
-}
-
-/*
- * Find the interrupt parent of a node.
- */
-static struct device_node * __init
-intr_parent(struct device_node *p)
-{
- phandle *parp;
-
- parp = (phandle *) get_property(p, "interrupt-parent", NULL);
- if (parp == NULL)
- return p->parent;
- p = find_phandle(*parp);
- if (p != NULL)
- return p;
- /*
- * On a powermac booted with BootX, we don't get to know the
- * phandles for any nodes, so find_phandle will return NULL.
- * Fortunately these machines only have one interrupt controller
- * so there isn't in fact any ambiguity. -- paulus
- */
- if (num_interrupt_controllers == 1)
- p = dflt_interrupt_controller;
- return p;
-}
-
-/*
- * Find out the size of each entry of the interrupts property
- * for a node.
- */
-static int __init
-prom_n_intr_cells(struct device_node *np)
-{
- struct device_node *p;
- unsigned int *icp;
-
- for (p = np; (p = intr_parent(p)) != NULL; ) {
- icp = (unsigned int *)
- get_property(p, "#interrupt-cells", NULL);
- if (icp != NULL)
- return *icp;
- if (get_property(p, "interrupt-controller", NULL) != NULL
- || get_property(p, "interrupt-map", NULL) != NULL) {
- printk("oops, node %s doesn't have #interrupt-cells\n",
- p->full_name);
- return 1;
- }
- }
- printk("prom_n_intr_cells failed for %s\n", np->full_name);
- return 1;
-}
-
-/*
- * Map an interrupt from a device up to the platform interrupt
- * descriptor.
- */
-static int __init
-map_interrupt(unsigned int **irq, struct device_node **ictrler,
- struct device_node *np, unsigned int *ints, int nintrc)
-{
- struct device_node *p, *ipar;
- unsigned int *imap, *imask, *ip;
- int i, imaplen, match;
- int newintrc = 1, newaddrc = 1;
- unsigned int *reg;
- int naddrc;
-
- reg = (unsigned int *) get_property(np, "reg", NULL);
- naddrc = prom_n_addr_cells(np);
- p = intr_parent(np);
- while (p != NULL) {
- if (get_property(p, "interrupt-controller", NULL) != NULL)
- /* this node is an interrupt controller, stop here */
- break;
- imap = (unsigned int *)
- get_property(p, "interrupt-map", &imaplen);
- if (imap == NULL) {
- p = intr_parent(p);
- continue;
- }
- imask = (unsigned int *)
- get_property(p, "interrupt-map-mask", NULL);
- if (imask == NULL) {
- printk("oops, %s has interrupt-map but no mask\n",
- p->full_name);
- return 0;
- }
- imaplen /= sizeof(unsigned int);
- match = 0;
- ipar = NULL;
- while (imaplen > 0 && !match) {
- /* check the child-interrupt field */
- match = 1;
- for (i = 0; i < naddrc && match; ++i)
- match = ((reg[i] ^ imap[i]) & imask[i]) == 0;
- for (; i < naddrc + nintrc && match; ++i)
- match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0;
- imap += naddrc + nintrc;
- imaplen -= naddrc + nintrc;
- /* grab the interrupt parent */
- ipar = find_phandle((phandle) *imap++);
- --imaplen;
- if (ipar == NULL && num_interrupt_controllers == 1)
- /* cope with BootX not giving us phandles */
- ipar = dflt_interrupt_controller;
- if (ipar == NULL) {
- printk("oops, no int parent %x in map of %s\n",
- imap[-1], p->full_name);
- return 0;
- }
- /* find the parent's # addr and intr cells */
- ip = (unsigned int *)
- get_property(ipar, "#interrupt-cells", NULL);
- if (ip == NULL) {
- printk("oops, no #interrupt-cells on %s\n",
- ipar->full_name);
- return 0;
- }
- newintrc = *ip;
- ip = (unsigned int *)
- get_property(ipar, "#address-cells", NULL);
- newaddrc = (ip == NULL)? 0: *ip;
- imap += newaddrc + newintrc;
- imaplen -= newaddrc + newintrc;
- }
- if (imaplen < 0) {
- printk("oops, error decoding int-map on %s, len=%d\n",
- p->full_name, imaplen);
- return 0;
- }
- if (!match) {
- printk("oops, no match in %s int-map for %s\n",
- p->full_name, np->full_name);
- return 0;
- }
- p = ipar;
- naddrc = newaddrc;
- nintrc = newintrc;
- ints = imap - nintrc;
- reg = ints - naddrc;
- }
- if (p == NULL)
- printk("hmmm, int tree for %s doesn't have ctrler\n",
- np->full_name);
- *irq = ints;
- *ictrler = p;
- return nintrc;
-}
-
-/*
- * New version of finish_node_interrupts.
- */
-static unsigned long __init
-finish_node_interrupts(struct device_node *np, unsigned long mem_start)
-{
- unsigned int *ints;
- int intlen, intrcells;
- int i, j, n, offset;
- unsigned int *irq;
- struct device_node *ic;
-
- ints = (unsigned int *) get_property(np, "interrupts", &intlen);
- if (ints == NULL)
- return mem_start;
- intrcells = prom_n_intr_cells(np);
- intlen /= intrcells * sizeof(unsigned int);
- np->n_intrs = intlen;
- np->intrs = (struct interrupt_info *) mem_start;
- mem_start += intlen * sizeof(struct interrupt_info);
-
- for (i = 0; i < intlen; ++i) {
- np->intrs[i].line = 0;
- np->intrs[i].sense = 1;
- n = map_interrupt(&irq, &ic, np, ints, intrcells);
- if (n <= 0)
- continue;
- offset = 0;
- /*
- * On a CHRP we have an 8259 which is subordinate to
- * the openpic in the interrupt tree, but we want the
- * openpic's interrupt numbers offsetted, not the 8259's.
- * So we apply the offset if the controller is at the
- * root of the interrupt tree, i.e. has no interrupt-parent.
- * This doesn't cope with the general case of multiple
- * cascaded interrupt controllers, but then neither will
- * irq.c at the moment either. -- paulus
- * The G5 triggers that code, I add a machine test. On
- * those machines, we want to offset interrupts from the
- * second openpic by 128 -- BenH
- */
- if (num_interrupt_controllers > 1
- && ic != NULL
- && get_property(ic, "interrupt-parent", NULL) == NULL)
- offset = 16;
-
- np->intrs[i].line = irq[0] + offset;
- if (n > 1)
- np->intrs[i].sense = irq[1];
- if (n > 2) {
- printk("hmmm, got %d intr cells for %s:", n,
- np->full_name);
- for (j = 0; j < n; ++j)
- printk(" %d", irq[j]);
- printk("\n");
- }
- ints += intrcells;
- }
-
- return mem_start;
-}
-
-/*
- * When BootX makes a copy of the device tree from the MacOS
- * Name Registry, it is in the format we use but all of the pointers
- * are offsets from the start of the tree.
- * This procedure updates the pointers.
- */
-void __init
-relocate_nodes(void)
-{
- unsigned long base;
- struct device_node *np;
- struct property *pp;
-
-#define ADDBASE(x) (x = (typeof (x))((x)? ((unsigned long)(x) + base): 0))
-
- base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset;
- allnodes = (struct device_node *)(base + 4);
- for (np = allnodes; np != 0; np = np->allnext) {
- ADDBASE(np->full_name);
- ADDBASE(np->properties);
- ADDBASE(np->parent);
- ADDBASE(np->child);
- ADDBASE(np->sibling);
- ADDBASE(np->allnext);
- for (pp = np->properties; pp != 0; pp = pp->next) {
- ADDBASE(pp->name);
- ADDBASE(pp->value);
- ADDBASE(pp->next);
- }
- }
-}
-
-int
-prom_n_addr_cells(struct device_node* np)
-{
- int* ip;
- do {
- if (np->parent)
- np = np->parent;
- ip = (int *) get_property(np, "#address-cells", NULL);
- if (ip != NULL)
- return *ip;
- } while (np->parent);
- /* No #address-cells property for the root node, default to 1 */
- return 1;
-}
-
-int
-prom_n_size_cells(struct device_node* np)
-{
- int* ip;
- do {
- if (np->parent)
- np = np->parent;
- ip = (int *) get_property(np, "#size-cells", NULL);
- if (ip != NULL)
- return *ip;
- } while (np->parent);
- /* No #size-cells property for the root node, default to 1 */
- return 1;
-}
-
-static unsigned long __init
-map_addr(struct device_node *np, unsigned long space, unsigned long addr)
-{
- int na;
- unsigned int *ranges;
- int rlen = 0;
- unsigned int type;
-
- type = (space >> 24) & 3;
- if (type == 0)
- return addr;
-
- while ((np = np->parent) != NULL) {
- if (strcmp(np->type, "pci") != 0)
- continue;
- /* PCI bridge: map the address through the ranges property */
- na = prom_n_addr_cells(np);
- ranges = (unsigned int *) get_property(np, "ranges", &rlen);
- while ((rlen -= (na + 5) * sizeof(unsigned int)) >= 0) {
- if (((ranges[0] >> 24) & 3) == type
- && ranges[2] <= addr
- && addr - ranges[2] < ranges[na+4]) {
- /* ok, this matches, translate it */
- addr += ranges[na+2] - ranges[2];
- break;
- }
- ranges += na + 5;
- }
- }
- return addr;
-}
-
-static unsigned long __init
-interpret_pci_props(struct device_node *np, unsigned long mem_start,
- int naddrc, int nsizec)
-{
- struct address_range *adr;
- struct pci_reg_property *pci_addrs;
- int i, l, *ip;
-
- pci_addrs = (struct pci_reg_property *)
- get_property(np, "assigned-addresses", &l);
- if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {
- i = 0;
- adr = (struct address_range *) mem_start;
- while ((l -= sizeof(struct pci_reg_property)) >= 0) {
- adr[i].space = pci_addrs[i].addr.a_hi;
- adr[i].address = map_addr(np, pci_addrs[i].addr.a_hi,
- pci_addrs[i].addr.a_lo);
- adr[i].size = pci_addrs[i].size_lo;
- ++i;
- }
- np->addrs = adr;
- np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
- }
-
- if (use_of_interrupt_tree)
- return mem_start;
-
- ip = (int *) get_property(np, "AAPL,interrupts", &l);
- if (ip == 0 && np->parent)
- ip = (int *) get_property(np->parent, "AAPL,interrupts", &l);
- if (ip == 0)
- ip = (int *) get_property(np, "interrupts", &l);
- if (ip != 0) {
- np->intrs = (struct interrupt_info *) mem_start;
- np->n_intrs = l / sizeof(int);
- mem_start += np->n_intrs * sizeof(struct interrupt_info);
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = *ip++;
- np->intrs[i].sense = 1;
- }
- }
-
- return mem_start;
-}
-
-static unsigned long __init
-interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
- int naddrc, int nsizec)
-{
- struct reg_property *rp;
- struct address_range *adr;
- unsigned long base_address;
- int i, l, *ip;
- struct device_node *db;
-
- base_address = 0;
- for (db = np->parent; db != NULL; db = db->parent) {
- if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) {
- base_address = db->addrs[0].address;
- break;
- }
- }
-
- rp = (struct reg_property *) get_property(np, "reg", &l);
- if (rp != 0 && l >= sizeof(struct reg_property)) {
- i = 0;
- adr = (struct address_range *) mem_start;
- while ((l -= sizeof(struct reg_property)) >= 0) {
- adr[i].space = 2;
- adr[i].address = rp[i].address + base_address;
- adr[i].size = rp[i].size;
- ++i;
- }
- np->addrs = adr;
- np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
- }
-
- if (use_of_interrupt_tree)
- return mem_start;
-
- ip = (int *) get_property(np, "AAPL,interrupts", &l);
- if (ip == 0)
- ip = (int *) get_property(np, "interrupts", &l);
- if (ip != 0) {
- np->intrs = (struct interrupt_info *) mem_start;
- np->n_intrs = l / sizeof(int);
- mem_start += np->n_intrs * sizeof(struct interrupt_info);
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = *ip++;
- np->intrs[i].sense = 1;
- }
- }
-
- return mem_start;
-}
-
-static unsigned long __init
-interpret_macio_props(struct device_node *np, unsigned long mem_start,
- int naddrc, int nsizec)
-{
- struct reg_property *rp;
- struct address_range *adr;
- unsigned long base_address;
- int i, l, *ip;
- struct device_node *db;
-
- base_address = 0;
- for (db = np->parent; db != NULL; db = db->parent) {
- if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {
- base_address = db->addrs[0].address;
- break;
- }
- }
-
- rp = (struct reg_property *) get_property(np, "reg", &l);
- if (rp != 0 && l >= sizeof(struct reg_property)) {
- i = 0;
- adr = (struct address_range *) mem_start;
- while ((l -= sizeof(struct reg_property)) >= 0) {
- adr[i].space = 2;
- adr[i].address = rp[i].address + base_address;
- adr[i].size = rp[i].size;
- ++i;
- }
- np->addrs = adr;
- np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
- }
-
- if (use_of_interrupt_tree)
- return mem_start;
-
- ip = (int *) get_property(np, "interrupts", &l);
- if (ip == 0)
- ip = (int *) get_property(np, "AAPL,interrupts", &l);
- if (ip != 0) {
- np->intrs = (struct interrupt_info *) mem_start;
- np->n_intrs = l / sizeof(int);
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = *ip++;
- np->intrs[i].sense = 1;
- }
- mem_start += np->n_intrs * sizeof(struct interrupt_info);
- }
-
- return mem_start;
-}
-
-static unsigned long __init
-interpret_isa_props(struct device_node *np, unsigned long mem_start,
- int naddrc, int nsizec)
-{
- struct isa_reg_property *rp;
- struct address_range *adr;
- int i, l, *ip;
-
- rp = (struct isa_reg_property *) get_property(np, "reg", &l);
- if (rp != 0 && l >= sizeof(struct isa_reg_property)) {
- i = 0;
- adr = (struct address_range *) mem_start;
- while ((l -= sizeof(struct reg_property)) >= 0) {
- adr[i].space = rp[i].space;
- adr[i].address = rp[i].address
- + (adr[i].space? 0: _ISA_MEM_BASE);
- adr[i].size = rp[i].size;
- ++i;
- }
- np->addrs = adr;
- np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
- }
-
- if (use_of_interrupt_tree)
- return mem_start;
-
- ip = (int *) get_property(np, "interrupts", &l);
- if (ip != 0) {
- np->intrs = (struct interrupt_info *) mem_start;
- np->n_intrs = l / (2 * sizeof(int));
- mem_start += np->n_intrs * sizeof(struct interrupt_info);
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = *ip++;
- np->intrs[i].sense = *ip++;
- }
- }
-
- return mem_start;
-}
-
-static unsigned long __init
-interpret_root_props(struct device_node *np, unsigned long mem_start,
- int naddrc, int nsizec)
-{
- struct address_range *adr;
- int i, l, *ip;
- unsigned int *rp;
- int rpsize = (naddrc + nsizec) * sizeof(unsigned int);
-
- rp = (unsigned int *) get_property(np, "reg", &l);
- if (rp != 0 && l >= rpsize) {
- i = 0;
- adr = (struct address_range *) mem_start;
- while ((l -= rpsize) >= 0) {
- adr[i].space = (naddrc >= 2? rp[naddrc-2]: 2);
- adr[i].address = rp[naddrc - 1];
- adr[i].size = rp[naddrc + nsizec - 1];
- ++i;
- rp += naddrc + nsizec;
- }
- np->addrs = adr;
- np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
- }
-
- if (use_of_interrupt_tree)
- return mem_start;
-
- ip = (int *) get_property(np, "AAPL,interrupts", &l);
- if (ip == 0)
- ip = (int *) get_property(np, "interrupts", &l);
- if (ip != 0) {
- np->intrs = (struct interrupt_info *) mem_start;
- np->n_intrs = l / sizeof(int);
- mem_start += np->n_intrs * sizeof(struct interrupt_info);
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = *ip++;
- np->intrs[i].sense = 1;
- }
- }
-
- return mem_start;
-}
-
-/*
- * Work out the sense (active-low level / active-high edge)
- * of each interrupt from the device tree.
- */
-void __init
-prom_get_irq_senses(unsigned char *senses, int off, int max)
-{
- struct device_node *np;
- int i, j;
-
- /* default to level-triggered */
- memset(senses, 1, max - off);
- if (!use_of_interrupt_tree)
- return;
-
- for (np = allnodes; np != 0; np = np->allnext) {
- for (j = 0; j < np->n_intrs; j++) {
- i = np->intrs[j].line;
- if (i >= off && i < max) {
- if (np->intrs[j].sense == 1)
- senses[i-off] = (IRQ_SENSE_LEVEL
- | IRQ_POLARITY_NEGATIVE);
- else
- senses[i-off] = (IRQ_SENSE_EDGE
- | IRQ_POLARITY_POSITIVE);
- }
- }
- }
-}
-
-/*
- * Construct and return a list of the device_nodes with a given name.
- */
-struct device_node *
-find_devices(const char *name)
-{
- struct device_node *head, **prevp, *np;
-
- prevp = &head;
- for (np = allnodes; np != 0; np = np->allnext) {
- if (np->name != 0 && strcasecmp(np->name, name) == 0) {
- *prevp = np;
- prevp = &np->next;
- }
- }
- *prevp = NULL;
- return head;
-}
-
-/*
- * Construct and return a list of the device_nodes with a given type.
- */
-struct device_node *
-find_type_devices(const char *type)
-{
- struct device_node *head, **prevp, *np;
-
- prevp = &head;
- for (np = allnodes; np != 0; np = np->allnext) {
- if (np->type != 0 && strcasecmp(np->type, type) == 0) {
- *prevp = np;
- prevp = &np->next;
- }
- }
- *prevp = NULL;
- return head;
-}
-
-/*
- * Returns all nodes linked together
- */
-struct device_node *
-find_all_nodes(void)
-{
- struct device_node *head, **prevp, *np;
-
- prevp = &head;
- for (np = allnodes; np != 0; np = np->allnext) {
- *prevp = np;
- prevp = &np->next;
- }
- *prevp = NULL;
- return head;
-}
-
-/* Checks if the given "compat" string matches one of the strings in
- * the device's "compatible" property
- */
-int
-device_is_compatible(struct device_node *device, const char *compat)
-{
- const char* cp;
- int cplen, l;
-
- cp = (char *) get_property(device, "compatible", &cplen);
- if (cp == NULL)
- return 0;
- while (cplen > 0) {
- if (strncasecmp(cp, compat, strlen(compat)) == 0)
- return 1;
- l = strlen(cp) + 1;
- cp += l;
- cplen -= l;
- }
-
- return 0;
-}
-
-
-/*
- * Indicates whether the root node has a given value in its
- * compatible property.
- */
-int
-machine_is_compatible(const char *compat)
-{
- struct device_node *root;
-
- root = find_path_device("/");
- if (root == 0)
- return 0;
- return device_is_compatible(root, compat);
-}
-
-/*
- * Construct and return a list of the device_nodes with a given type
- * and compatible property.
- */
-struct device_node *
-find_compatible_devices(const char *type, const char *compat)
-{
- struct device_node *head, **prevp, *np;
-
- prevp = &head;
- for (np = allnodes; np != 0; np = np->allnext) {
- if (type != NULL
- && !(np->type != 0 && strcasecmp(np->type, type) == 0))
- continue;
- if (device_is_compatible(np, compat)) {
- *prevp = np;
- prevp = &np->next;
- }
- }
- *prevp = NULL;
- return head;
-}
-
-/*
- * Find the device_node with a given full_name.
- */
-struct device_node *
-find_path_device(const char *path)
-{
- struct device_node *np;
-
- for (np = allnodes; np != 0; np = np->allnext)
- if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
- return np;
- return NULL;
-}
-
-/*******
- *
- * New implementation of the OF "find" APIs, return a refcounted
- * object, call of_node_put() when done. Currently, still lacks
- * locking as old implementation, this is beeing done for ppc64.
- *
- * Note that property management will need some locking as well,
- * this isn't dealt with yet
- *
- *******/
-
-/**
- * of_find_node_by_name - Find a node by it's "name" property
- * @from: The node to start searching from or NULL, the node
- * you pass will not be searched, only the next one
- * will; typically, you pass what the previous call
- * returned. of_node_put() will be called on it
- * @name: The name string to match against
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_find_node_by_name(struct device_node *from,
- const char *name)
-{
- struct device_node *np = from ? from->allnext : allnodes;
-
- for (; np != 0; np = np->allnext)
- if (np->name != 0 && strcasecmp(np->name, name) == 0)
- break;
- if (from)
- of_node_put(from);
- return of_node_get(np);
-}
-
-/**
- * of_find_node_by_type - Find a node by it's "device_type" property
- * @from: The node to start searching from or NULL, the node
- * you pass will not be searched, only the next one
- * will; typically, you pass what the previous call
- * returned. of_node_put() will be called on it
- * @name: The type string to match against
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_find_node_by_type(struct device_node *from,
- const char *type)
-{
- struct device_node *np = from ? from->allnext : allnodes;
-
- for (; np != 0; np = np->allnext)
- if (np->type != 0 && strcasecmp(np->type, type) == 0)
- break;
- if (from)
- of_node_put(from);
- return of_node_get(np);
-}
-
-/**
- * of_find_compatible_node - Find a node based on type and one of the
- * tokens in it's "compatible" property
- * @from: The node to start searching from or NULL, the node
- * you pass will not be searched, only the next one
- * will; typically, you pass what the previous call
- * returned. of_node_put() will be called on it
- * @type: The type string to match "device_type" or NULL to ignore
- * @compatible: The string to match to one of the tokens in the device
- * "compatible" list.
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_find_compatible_node(struct device_node *from,
- const char *type, const char *compatible)
-{
- struct device_node *np = from ? from->allnext : allnodes;
-
- for (; np != 0; np = np->allnext) {
- if (type != NULL
- && !(np->type != 0 && strcasecmp(np->type, type) == 0))
- continue;
- if (device_is_compatible(np, compatible))
- break;
- }
- if (from)
- of_node_put(from);
- return of_node_get(np);
-}
-
-/**
- * of_find_node_by_path - Find a node matching a full OF path
- * @path: The full path to match
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_find_node_by_path(const char *path)
-{
- struct device_node *np = allnodes;
-
- for (; np != 0; np = np->allnext)
- if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
- break;
- return of_node_get(np);
-}
-
-/**
- * of_find_all_nodes - Get next node in global list
- * @prev: Previous node or NULL to start iteration
- * of_node_put() will be called on it
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_find_all_nodes(struct device_node *prev)
-{
- return of_node_get(prev ? prev->allnext : allnodes);
-}
-
-/**
- * of_get_parent - Get a node's parent if any
- * @node: Node to get parent
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_get_parent(const struct device_node *node)
-{
- return node ? of_node_get(node->parent) : NULL;
-}
-
-/**
- * of_get_next_child - Iterate a node childs
- * @node: parent node
- * @prev: previous child of the parent node, or NULL to get first
- *
- * Returns a node pointer with refcount incremented, use
- * of_node_put() on it when done.
- */
-struct device_node *of_get_next_child(const struct device_node *node,
- struct device_node *prev)
-{
- struct device_node *next = prev ? prev->sibling : node->child;
-
- for (; next != 0; next = next->sibling)
- if (of_node_get(next))
- break;
- if (prev)
- of_node_put(prev);
- return next;
-}
-
-/**
- * of_node_get - Increment refcount of a node
- * @node: Node to inc refcount, NULL is supported to
- * simplify writing of callers
- *
- * Returns the node itself or NULL if gone. Current implementation
- * does nothing as we don't yet do dynamic node allocation on ppc32
- */
-struct device_node *of_node_get(struct device_node *node)
-{
- return node;
-}
-
-/**
- * of_node_put - Decrement refcount of a node
- * @node: Node to dec refcount, NULL is supported to
- * simplify writing of callers
- *
- * Current implementation does nothing as we don't yet do dynamic node
- * allocation on ppc32
- */
-void of_node_put(struct device_node *node)
-{
-}
-
-/*
- * Find the device_node with a given phandle.
- */
-static struct device_node * __init
-find_phandle(phandle ph)
-{
- struct device_node *np;
-
- for (np = allnodes; np != 0; np = np->allnext)
- if (np->node == ph)
- return np;
- return NULL;
-}
-
-/*
- * Find a property with a given name for a given node
- * and return the value.
- */
-unsigned char *
-get_property(struct device_node *np, const char *name, int *lenp)
-{
- struct property *pp;
-
- for (pp = np->properties; pp != 0; pp = pp->next)
- if (pp->name != NULL && strcmp(pp->name, name) == 0) {
- if (lenp != 0)
- *lenp = pp->length;
- return pp->value;
- }
- return NULL;
-}
-
-/*
- * Add a property to a node
- */
-int
-prom_add_property(struct device_node* np, struct property* prop)
-{
- struct property **next = &np->properties;
-
- prop->next = NULL;
- while (*next)
- next = &(*next)->next;
- *next = prop;
-
- return 0;
-}
-
-/* I quickly hacked that one, check against spec ! */
-static inline unsigned long
-bus_space_to_resource_flags(unsigned int bus_space)
-{
- u8 space = (bus_space >> 24) & 0xf;
- if (space == 0)
- space = 0x02;
- if (space == 0x02)
- return IORESOURCE_MEM;
- else if (space == 0x01)
- return IORESOURCE_IO;
- else {
- printk(KERN_WARNING "prom.c: bus_space_to_resource_flags(), space: %x\n",
- bus_space);
- return 0;
- }
-}
-
-static struct resource*
-find_parent_pci_resource(struct pci_dev* pdev, struct address_range *range)
-{
- unsigned long mask;
- int i;
-
- /* Check this one */
- mask = bus_space_to_resource_flags(range->space);
- for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
- if ((pdev->resource[i].flags & mask) == mask &&
- pdev->resource[i].start <= range->address &&
- pdev->resource[i].end > range->address) {
- if ((range->address + range->size - 1) > pdev->resource[i].end) {
- /* Add better message */
- printk(KERN_WARNING "PCI/OF resource overlap !\n");
- return NULL;
- }
- break;
- }
- }
- if (i == DEVICE_COUNT_RESOURCE)
- return NULL;
- return &pdev->resource[i];
-}
-
-/*
- * Request an OF device resource. Currently handles child of PCI devices,
- * or other nodes attached to the root node. Ultimately, put some
- * link to resources in the OF node.
- */
-struct resource*
-request_OF_resource(struct device_node* node, int index, const char* name_postfix)
-{
- struct pci_dev* pcidev;
- u8 pci_bus, pci_devfn;
- unsigned long iomask;
- struct device_node* nd;
- struct resource* parent;
- struct resource *res = NULL;
- int nlen, plen;
-
- if (index >= node->n_addrs)
- goto fail;
-
- /* Sanity check on bus space */
- iomask = bus_space_to_resource_flags(node->addrs[index].space);
- if (iomask & IORESOURCE_MEM)
- parent = &iomem_resource;
- else if (iomask & IORESOURCE_IO)
- parent = &ioport_resource;
- else
- goto fail;
-
- /* Find a PCI parent if any */
- nd = node;
- pcidev = NULL;
- while(nd) {
- if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
- pcidev = pci_find_slot(pci_bus, pci_devfn);
- if (pcidev) break;
- nd = nd->parent;
- }
- if (pcidev)
- parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
- if (!parent) {
- printk(KERN_WARNING "request_OF_resource(%s), parent not found\n",
- node->name);
- goto fail;
- }
-
- res = __request_region(parent, node->addrs[index].address, node->addrs[index].size, NULL);
- if (!res)
- goto fail;
- nlen = strlen(node->name);
- plen = name_postfix ? strlen(name_postfix) : 0;
- res->name = (const char *)kmalloc(nlen+plen+1, GFP_KERNEL);
- if (res->name) {
- strcpy((char *)res->name, node->name);
- if (plen)
- strcpy((char *)res->name+nlen, name_postfix);
- }
- return res;
-fail:
- return NULL;
-}
-
-int
-release_OF_resource(struct device_node* node, int index)
-{
- struct pci_dev* pcidev;
- u8 pci_bus, pci_devfn;
- unsigned long iomask, start, end;
- struct device_node* nd;
- struct resource* parent;
- struct resource *res = NULL;
-
- if (index >= node->n_addrs)
- return -EINVAL;
-
- /* Sanity check on bus space */
- iomask = bus_space_to_resource_flags(node->addrs[index].space);
- if (iomask & IORESOURCE_MEM)
- parent = &iomem_resource;
- else if (iomask & IORESOURCE_IO)
- parent = &ioport_resource;
- else
- return -EINVAL;
-
- /* Find a PCI parent if any */
- nd = node;
- pcidev = NULL;
- while(nd) {
- if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
- pcidev = pci_find_slot(pci_bus, pci_devfn);
- if (pcidev) break;
- nd = nd->parent;
- }
- if (pcidev)
- parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
- if (!parent) {
- printk(KERN_WARNING "release_OF_resource(%s), parent not found\n",
- node->name);
- return -ENODEV;
- }
-
- /* Find us in the parent and its childs */
- res = parent->child;
- start = node->addrs[index].address;
- end = start + node->addrs[index].size - 1;
- while (res) {
- if (res->start == start && res->end == end &&
- (res->flags & IORESOURCE_BUSY))
- break;
- if (res->start <= start && res->end >= end)
- res = res->child;
- else
- res = res->sibling;
- }
- if (!res)
- return -ENODEV;
-
- kfree(res->name);
- res->name = NULL;
- release_resource(res);
- kfree(res);
-
- return 0;
-}
-
-#if 0
-void
-print_properties(struct device_node *np)
-{
- struct property *pp;
- char *cp;
- int i, n;
-
- for (pp = np->properties; pp != 0; pp = pp->next) {
- printk(KERN_INFO "%s", pp->name);
- for (i = strlen(pp->name); i < 16; ++i)
- printk(" ");
- cp = (char *) pp->value;
- for (i = pp->length; i > 0; --i, ++cp)
- if ((i > 1 && (*cp < 0x20 || *cp > 0x7e))
- || (i == 1 && *cp != 0))
- break;
- if (i == 0 && pp->length > 1) {
- /* looks like a string */
- printk(" %s\n", (char *) pp->value);
- } else {
- /* dump it in hex */
- n = pp->length;
- if (n > 64)
- n = 64;
- if (pp->length % 4 == 0) {
- unsigned int *p = (unsigned int *) pp->value;
-
- n /= 4;
- for (i = 0; i < n; ++i) {
- if (i != 0 && (i % 4) == 0)
- printk("\n ");
- printk(" %08x", *p++);
- }
- } else {
- unsigned char *bp = pp->value;
-
- for (i = 0; i < n; ++i) {
- if (i != 0 && (i % 16) == 0)
- printk("\n ");
- printk(" %02x", *bp++);
- }
- }
- printk("\n");
- if (pp->length > 64)
- printk(" ... (length = %d)\n",
- pp->length);
- }
- }
-}
-#endif
-
-static DEFINE_SPINLOCK(rtas_lock);
-
-/* this can be called after setup -- Cort */
-int
-call_rtas(const char *service, int nargs, int nret,
- unsigned long *outputs, ...)
-{
- va_list list;
- int i;
- unsigned long s;
- struct device_node *rtas;
- int *tokp;
- union {
- unsigned long words[16];
- double align;
- } u;
-
- rtas = find_devices("rtas");
- if (rtas == NULL)
- return -1;
- tokp = (int *) get_property(rtas, service, NULL);
- if (tokp == NULL) {
- printk(KERN_ERR "No RTAS service called %s\n", service);
- return -1;
- }
- u.words[0] = *tokp;
- u.words[1] = nargs;
- u.words[2] = nret;
- va_start(list, outputs);
- for (i = 0; i < nargs; ++i)
- u.words[i+3] = va_arg(list, unsigned long);
- va_end(list);
-
- /*
- * RTAS doesn't use floating point.
- * Or at least, according to the CHRP spec we enter RTAS
- * with FP disabled, and it doesn't change the FP registers.
- * -- paulus.
- */
- spin_lock_irqsave(&rtas_lock, s);
- enter_rtas((void *)__pa(&u));
- spin_unlock_irqrestore(&rtas_lock, s);
-
- if (nret > 1 && outputs != NULL)
- for (i = 0; i < nret-1; ++i)
- outputs[i] = u.words[i+nargs+4];
- return u.words[nargs+3];
-}
diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c
deleted file mode 100644
index df14422ae1c..00000000000
--- a/arch/ppc/syslib/prom_init.c
+++ /dev/null
@@ -1,1011 +0,0 @@
-/*
- * Note that prom_init() and anything called from prom_init()
- * may be running at an address that is different from the address
- * that it was linked at. References to static data items are
- * handled by compiling this file with -mrelocatable-lib.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/threads.h>
-#include <linux/spinlock.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-
-#include <asm/sections.h>
-#include <asm/prom.h>
-#include <asm/page.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/bootx.h>
-#include <asm/system.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-#include <asm/bootinfo.h>
-#include <asm/btext.h>
-#include <asm/pci-bridge.h>
-#include <asm/open_pic.h>
-#include <asm/cacheflush.h>
-
-#ifdef CONFIG_LOGO_LINUX_CLUT224
-#include <linux/linux_logo.h>
-extern const struct linux_logo logo_linux_clut224;
-#endif
-
-/*
- * Properties whose value is longer than this get excluded from our
- * copy of the device tree. This way we don't waste space storing
- * things like "driver,AAPL,MacOS,PowerPC" properties. But this value
- * does need to be big enough to ensure that we don't lose things
- * like the interrupt-map property on a PCI-PCI bridge.
- */
-#define MAX_PROPERTY_LENGTH 4096
-
-#ifndef FB_MAX /* avoid pulling in all of the fb stuff */
-#define FB_MAX 8
-#endif
-
-#define ALIGNUL(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
-
-typedef u32 prom_arg_t;
-
-struct prom_args {
- const char *service;
- int nargs;
- int nret;
- prom_arg_t args[10];
-};
-
-struct pci_address {
- unsigned a_hi;
- unsigned a_mid;
- unsigned a_lo;
-};
-
-struct pci_reg_property {
- struct pci_address addr;
- unsigned size_hi;
- unsigned size_lo;
-};
-
-struct pci_range {
- struct pci_address addr;
- unsigned phys;
- unsigned size_hi;
- unsigned size_lo;
-};
-
-struct isa_reg_property {
- unsigned space;
- unsigned address;
- unsigned size;
-};
-
-struct pci_intr_map {
- struct pci_address addr;
- unsigned dunno;
- phandle int_ctrler;
- unsigned intr;
-};
-
-static void prom_exit(void);
-static int call_prom(const char *service, int nargs, int nret, ...);
-static int call_prom_ret(const char *service, int nargs, int nret,
- prom_arg_t *rets, ...);
-static void prom_print_hex(unsigned int v);
-static int prom_set_color(ihandle ih, int i, int r, int g, int b);
-static int prom_next_node(phandle *nodep);
-static unsigned long check_display(unsigned long mem);
-static void setup_disp_fake_bi(ihandle dp);
-static unsigned long copy_device_tree(unsigned long mem_start,
- unsigned long mem_end);
-static unsigned long inspect_node(phandle node, struct device_node *dad,
- unsigned long mem_start, unsigned long mem_end,
- struct device_node ***allnextpp);
-static void prom_hold_cpus(unsigned long mem);
-static void prom_instantiate_rtas(void);
-static void * early_get_property(unsigned long base, unsigned long node,
- char *prop);
-
-prom_entry prom __initdata;
-ihandle prom_chosen __initdata;
-ihandle prom_stdout __initdata;
-
-static char *prom_display_paths[FB_MAX] __initdata;
-static phandle prom_display_nodes[FB_MAX] __initdata;
-static unsigned int prom_num_displays __initdata;
-static ihandle prom_disp_node __initdata;
-char *of_stdout_device __initdata;
-
-unsigned int rtas_data; /* physical pointer */
-unsigned int rtas_entry; /* physical pointer */
-unsigned int rtas_size;
-unsigned int old_rtas;
-
-boot_infos_t *boot_infos;
-char *bootpath;
-char *bootdevice;
-struct device_node *allnodes;
-
-extern char *klimit;
-
-static void __init
-prom_exit(void)
-{
- struct prom_args args;
-
- args.service = "exit";
- args.nargs = 0;
- args.nret = 0;
- prom(&args);
- for (;;) /* should never get here */
- ;
-}
-
-static int __init
-call_prom(const char *service, int nargs, int nret, ...)
-{
- va_list list;
- int i;
- struct prom_args prom_args;
-
- prom_args.service = service;
- prom_args.nargs = nargs;
- prom_args.nret = nret;
- va_start(list, nret);
- for (i = 0; i < nargs; ++i)
- prom_args.args[i] = va_arg(list, prom_arg_t);
- va_end(list);
- for (i = 0; i < nret; ++i)
- prom_args.args[i + nargs] = 0;
- prom(&prom_args);
- return prom_args.args[nargs];
-}
-
-static int __init
-call_prom_ret(const char *service, int nargs, int nret, prom_arg_t *rets, ...)
-{
- va_list list;
- int i;
- struct prom_args prom_args;
-
- prom_args.service = service;
- prom_args.nargs = nargs;
- prom_args.nret = nret;
- va_start(list, rets);
- for (i = 0; i < nargs; ++i)
- prom_args.args[i] = va_arg(list, int);
- va_end(list);
- for (i = 0; i < nret; ++i)
- prom_args.args[i + nargs] = 0;
- prom(&prom_args);
- for (i = 1; i < nret; ++i)
- rets[i-1] = prom_args.args[nargs + i];
- return prom_args.args[nargs];
-}
-
-void __init
-prom_print(const char *msg)
-{
- const char *p, *q;
-
- if (prom_stdout == 0)
- return;
-
- for (p = msg; *p != 0; p = q) {
- for (q = p; *q != 0 && *q != '\n'; ++q)
- ;
- if (q > p)
- call_prom("write", 3, 1, prom_stdout, p, q - p);
- if (*q != 0) {
- ++q;
- call_prom("write", 3, 1, prom_stdout, "\r\n", 2);
- }
- }
-}
-
-static void __init
-prom_print_hex(unsigned int v)
-{
- char buf[16];
- int i, c;
-
- for (i = 0; i < 8; ++i) {
- c = (v >> ((7-i)*4)) & 0xf;
- c += (c >= 10)? ('a' - 10): '0';
- buf[i] = c;
- }
- buf[i] = ' ';
- buf[i+1] = 0;
- prom_print(buf);
-}
-
-static int __init
-prom_set_color(ihandle ih, int i, int r, int g, int b)
-{
- return call_prom("call-method", 6, 1, "color!", ih, i, b, g, r);
-}
-
-static int __init
-prom_next_node(phandle *nodep)
-{
- phandle node;
-
- if ((node = *nodep) != 0
- && (*nodep = call_prom("child", 1, 1, node)) != 0)
- return 1;
- if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
- return 1;
- for (;;) {
- if ((node = call_prom("parent", 1, 1, node)) == 0)
- return 0;
- if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
- return 1;
- }
-}
-
-#ifdef CONFIG_POWER4
-/*
- * Set up a hash table with a set of entries in it to map the
- * first 64MB of RAM. This is used on 64-bit machines since
- * some of them don't have BATs.
- */
-
-static inline void make_pte(unsigned long htab, unsigned int hsize,
- unsigned int va, unsigned int pa, int mode)
-{
- unsigned int *pteg;
- unsigned int hash, i, vsid;
-
- vsid = ((va >> 28) * 0x111) << 12;
- hash = ((va ^ vsid) >> 5) & 0x7fff80;
- pteg = (unsigned int *)(htab + (hash & (hsize - 1)));
- for (i = 0; i < 8; ++i, pteg += 4) {
- if ((pteg[1] & 1) == 0) {
- pteg[1] = vsid | ((va >> 16) & 0xf80) | 1;
- pteg[3] = pa | mode;
- break;
- }
- }
-}
-
-extern unsigned long _SDR1;
-extern PTE *Hash;
-extern unsigned long Hash_size;
-
-static void __init
-prom_alloc_htab(void)
-{
- unsigned int hsize;
- unsigned long htab;
- unsigned int addr;
-
- /*
- * Because of OF bugs we can't use the "claim" client
- * interface to allocate memory for the hash table.
- * This code is only used on 64-bit PPCs, and the only
- * 64-bit PPCs at the moment are RS/6000s, and their
- * OF is based at 0xc00000 (the 12M point), so we just
- * arbitrarily use the 0x800000 - 0xc00000 region for the
- * hash table.
- * -- paulus.
- */
- hsize = 4 << 20; /* POWER4 has no BATs */
- htab = (8 << 20);
- call_prom("claim", 3, 1, htab, hsize, 0);
- Hash = (void *)(htab + KERNELBASE);
- Hash_size = hsize;
- _SDR1 = htab + __ilog2(hsize) - 18;
-
- /*
- * Put in PTEs for the first 64MB of RAM
- */
- memset((void *)htab, 0, hsize);
- for (addr = 0; addr < 0x4000000; addr += 0x1000)
- make_pte(htab, hsize, addr + KERNELBASE, addr,
- _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX);
-#if 0 /* DEBUG stuff mapping the SCC */
- make_pte(htab, hsize, 0x80013000, 0x80013000,
- _PAGE_ACCESSED | _PAGE_NO_CACHE | _PAGE_GUARDED | PP_RWXX);
-#endif
-}
-#endif /* CONFIG_POWER4 */
-
-
-/*
- * If we have a display that we don't know how to drive,
- * we will want to try to execute OF's open method for it
- * later. However, OF will probably fall over if we do that
- * we've taken over the MMU.
- * So we check whether we will need to open the display,
- * and if so, open it now.
- */
-static unsigned long __init
-check_display(unsigned long mem)
-{
- phandle node;
- ihandle ih;
- int i, j;
- char type[16], *path;
- static unsigned char default_colors[] = {
- 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xaa,
- 0x00, 0xaa, 0x00,
- 0x00, 0xaa, 0xaa,
- 0xaa, 0x00, 0x00,
- 0xaa, 0x00, 0xaa,
- 0xaa, 0xaa, 0x00,
- 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55,
- 0x55, 0x55, 0xff,
- 0x55, 0xff, 0x55,
- 0x55, 0xff, 0xff,
- 0xff, 0x55, 0x55,
- 0xff, 0x55, 0xff,
- 0xff, 0xff, 0x55,
- 0xff, 0xff, 0xff
- };
- const unsigned char *clut;
-
- prom_disp_node = 0;
-
- for (node = 0; prom_next_node(&node); ) {
- type[0] = 0;
- call_prom("getprop", 4, 1, node, "device_type",
- type, sizeof(type));
- if (strcmp(type, "display") != 0)
- continue;
- /* It seems OF doesn't null-terminate the path :-( */
- path = (char *) mem;
- memset(path, 0, 256);
- if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
- continue;
-
- /*
- * If this display is the device that OF is using for stdout,
- * move it to the front of the list.
- */
- mem += strlen(path) + 1;
- i = prom_num_displays++;
- if (of_stdout_device != 0 && i > 0
- && strcmp(of_stdout_device, path) == 0) {
- for (; i > 0; --i) {
- prom_display_paths[i]
- = prom_display_paths[i-1];
- prom_display_nodes[i]
- = prom_display_nodes[i-1];
- }
- }
- prom_display_paths[i] = path;
- prom_display_nodes[i] = node;
- if (i == 0)
- prom_disp_node = node;
- if (prom_num_displays >= FB_MAX)
- break;
- }
-
- for (j=0; j<prom_num_displays; j++) {
- path = prom_display_paths[j];
- node = prom_display_nodes[j];
- prom_print("opening display ");
- prom_print(path);
- ih = call_prom("open", 1, 1, path);
- if (ih == 0 || ih == (ihandle) -1) {
- prom_print("... failed\n");
- for (i=j+1; i<prom_num_displays; i++) {
- prom_display_paths[i-1] = prom_display_paths[i];
- prom_display_nodes[i-1] = prom_display_nodes[i];
- }
- if (--prom_num_displays > 0) {
- prom_disp_node = prom_display_nodes[j];
- j--;
- } else
- prom_disp_node = 0;
- continue;
- } else {
- prom_print("... ok\n");
- call_prom("setprop", 4, 1, node, "linux,opened", 0, 0);
-
- /*
- * Setup a usable color table when the appropriate
- * method is available.
- * Should update this to use set-colors.
- */
- clut = default_colors;
- for (i = 0; i < 32; i++, clut += 3)
- if (prom_set_color(ih, i, clut[0], clut[1],
- clut[2]) != 0)
- break;
-
-#ifdef CONFIG_LOGO_LINUX_CLUT224
- clut = PTRRELOC(logo_linux_clut224.clut);
- for (i = 0; i < logo_linux_clut224.clutsize;
- i++, clut += 3)
- if (prom_set_color(ih, i + 32, clut[0],
- clut[1], clut[2]) != 0)
- break;
-#endif /* CONFIG_LOGO_LINUX_CLUT224 */
- }
- }
-
- if (prom_stdout) {
- phandle p;
- p = call_prom("instance-to-package", 1, 1, prom_stdout);
- if (p && p != -1) {
- type[0] = 0;
- call_prom("getprop", 4, 1, p, "device_type",
- type, sizeof(type));
- if (strcmp(type, "display") == 0)
- call_prom("setprop", 4, 1, p, "linux,boot-display",
- 0, 0);
- }
- }
-
- return ALIGNUL(mem);
-}
-
-/* This function will enable the early boot text when doing OF booting. This
- * way, xmon output should work too
- */
-static void __init
-setup_disp_fake_bi(ihandle dp)
-{
-#ifdef CONFIG_BOOTX_TEXT
- int width = 640, height = 480, depth = 8, pitch;
- unsigned address;
- struct pci_reg_property addrs[8];
- int i, naddrs;
- char name[32];
- char *getprop = "getprop";
-
- prom_print("Initializing fake screen: ");
-
- memset(name, 0, sizeof(name));
- call_prom(getprop, 4, 1, dp, "name", name, sizeof(name));
- name[sizeof(name)-1] = 0;
- prom_print(name);
- prom_print("\n");
- call_prom(getprop, 4, 1, dp, "width", &width, sizeof(width));
- call_prom(getprop, 4, 1, dp, "height", &height, sizeof(height));
- call_prom(getprop, 4, 1, dp, "depth", &depth, sizeof(depth));
- pitch = width * ((depth + 7) / 8);
- call_prom(getprop, 4, 1, dp, "linebytes",
- &pitch, sizeof(pitch));
- if (pitch == 1)
- pitch = 0x1000; /* for strange IBM display */
- address = 0;
- call_prom(getprop, 4, 1, dp, "address",
- &address, sizeof(address));
- if (address == 0) {
- /* look for an assigned address with a size of >= 1MB */
- naddrs = call_prom(getprop, 4, 1, dp, "assigned-addresses",
- addrs, sizeof(addrs));
- naddrs /= sizeof(struct pci_reg_property);
- for (i = 0; i < naddrs; ++i) {
- if (addrs[i].size_lo >= (1 << 20)) {
- address = addrs[i].addr.a_lo;
- /* use the BE aperture if possible */
- if (addrs[i].size_lo >= (16 << 20))
- address += (8 << 20);
- break;
- }
- }
- if (address == 0) {
- prom_print("Failed to get address\n");
- return;
- }
- }
- /* kludge for valkyrie */
- if (strcmp(name, "valkyrie") == 0)
- address += 0x1000;
-
-#ifdef CONFIG_POWER4
-#if CONFIG_TASK_SIZE > 0x80000000
-#error CONFIG_TASK_SIZE cannot be above 0x80000000 with BOOTX_TEXT on G5
-#endif
- {
- extern boot_infos_t disp_bi;
- unsigned long va, pa, i, offset;
- va = 0x90000000;
- pa = address & 0xfffff000ul;
- offset = address & 0x00000fff;
-
- for (i=0; i<0x4000; i++) {
- make_pte((unsigned long)Hash - KERNELBASE, Hash_size, va, pa,
- _PAGE_ACCESSED | _PAGE_NO_CACHE |
- _PAGE_GUARDED | PP_RWXX);
- va += 0x1000;
- pa += 0x1000;
- }
- btext_setup_display(width, height, depth, pitch, 0x90000000 | offset);
- disp_bi.dispDeviceBase = (u8 *)address;
- }
-#else /* CONFIG_POWER4 */
- btext_setup_display(width, height, depth, pitch, address);
- btext_prepare_BAT();
-#endif /* CONFIG_POWER4 */
-#endif /* CONFIG_BOOTX_TEXT */
-}
-
-/*
- * Make a copy of the device tree from the PROM.
- */
-static unsigned long __init
-copy_device_tree(unsigned long mem_start, unsigned long mem_end)
-{
- phandle root;
- unsigned long new_start;
- struct device_node **allnextp;
-
- root = call_prom("peer", 1, 1, (phandle)0);
- if (root == (phandle)0) {
- prom_print("couldn't get device tree root\n");
- prom_exit();
- }
- allnextp = &allnodes;
- mem_start = ALIGNUL(mem_start);
- new_start = inspect_node(root, NULL, mem_start, mem_end, &allnextp);
- *allnextp = NULL;
- return new_start;
-}
-
-static unsigned long __init
-inspect_node(phandle node, struct device_node *dad,
- unsigned long mem_start, unsigned long mem_end,
- struct device_node ***allnextpp)
-{
- int l;
- phandle child;
- struct device_node *np;
- struct property *pp, **prev_propp;
- char *prev_name, *namep;
- unsigned char *valp;
-
- np = (struct device_node *) mem_start;
- mem_start += sizeof(struct device_node);
- memset(np, 0, sizeof(*np));
- np->node = node;
- **allnextpp = PTRUNRELOC(np);
- *allnextpp = &np->allnext;
- if (dad != 0) {
- np->parent = PTRUNRELOC(dad);
- /* we temporarily use the `next' field as `last_child'. */
- if (dad->next == 0)
- dad->child = PTRUNRELOC(np);
- else
- dad->next->sibling = PTRUNRELOC(np);
- dad->next = np;
- }
-
- /* get and store all properties */
- prev_propp = &np->properties;
- prev_name = "";
- for (;;) {
- pp = (struct property *) mem_start;
- namep = (char *) (pp + 1);
- pp->name = PTRUNRELOC(namep);
- if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0)
- break;
- mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
- prev_name = namep;
- valp = (unsigned char *) mem_start;
- pp->value = PTRUNRELOC(valp);
- pp->length = call_prom("getprop", 4, 1, node, namep,
- valp, mem_end - mem_start);
- if (pp->length < 0)
- continue;
-#ifdef MAX_PROPERTY_LENGTH
- if (pp->length > MAX_PROPERTY_LENGTH)
- continue; /* ignore this property */
-#endif
- mem_start = ALIGNUL(mem_start + pp->length);
- *prev_propp = PTRUNRELOC(pp);
- prev_propp = &pp->next;
- }
- if (np->node != 0) {
- /* Add a "linux,phandle" property" */
- pp = (struct property *) mem_start;
- *prev_propp = PTRUNRELOC(pp);
- prev_propp = &pp->next;
- namep = (char *) (pp + 1);
- pp->name = PTRUNRELOC(namep);
- strcpy(namep, "linux,phandle");
- mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
- pp->value = (unsigned char *) PTRUNRELOC(&np->node);
- pp->length = sizeof(np->node);
- }
- *prev_propp = NULL;
-
- /* get the node's full name */
- l = call_prom("package-to-path", 3, 1, node,
- mem_start, mem_end - mem_start);
- if (l >= 0) {
- char *p, *ep;
-
- np->full_name = PTRUNRELOC((char *) mem_start);
- *(char *)(mem_start + l) = 0;
- /* Fixup an Apple bug where they have bogus \0 chars in the
- * middle of the path in some properties
- */
- for (p = (char *)mem_start, ep = p + l; p < ep; p++)
- if ((*p) == '\0') {
- memmove(p, p+1, ep - p);
- ep--;
- }
- mem_start = ALIGNUL(mem_start + l + 1);
- }
-
- /* do all our children */
- child = call_prom("child", 1, 1, node);
- while (child != 0) {
- mem_start = inspect_node(child, np, mem_start, mem_end,
- allnextpp);
- child = call_prom("peer", 1, 1, child);
- }
-
- return mem_start;
-}
-
-unsigned long smp_chrp_cpu_nr __initdata = 0;
-
-/*
- * With CHRP SMP we need to use the OF to start the other
- * processors so we can't wait until smp_boot_cpus (the OF is
- * trashed by then) so we have to put the processors into
- * a holding pattern controlled by the kernel (not OF) before
- * we destroy the OF.
- *
- * This uses a chunk of high memory, puts some holding pattern
- * code there and sends the other processors off to there until
- * smp_boot_cpus tells them to do something. We do that by using
- * physical address 0x0. The holding pattern checks that address
- * until its cpu # is there, when it is that cpu jumps to
- * __secondary_start(). smp_boot_cpus() takes care of setting those
- * values.
- *
- * We also use physical address 0x4 here to tell when a cpu
- * is in its holding pattern code.
- *
- * -- Cort
- *
- * Note that we have to do this if we have more than one CPU,
- * even if this is a UP kernel. Otherwise when we trash OF
- * the other CPUs will start executing some random instructions
- * and crash the system. -- paulus
- */
-static void __init
-prom_hold_cpus(unsigned long mem)
-{
- extern void __secondary_hold(void);
- unsigned long i;
- int cpu;
- phandle node;
- char type[16], *path;
- unsigned int reg;
-
- /*
- * XXX: hack to make sure we're chrp, assume that if we're
- * chrp we have a device_type property -- Cort
- */
- node = call_prom("finddevice", 1, 1, "/");
- if (call_prom("getprop", 4, 1, node,
- "device_type", type, sizeof(type)) <= 0)
- return;
-
- /* copy the holding pattern code to someplace safe (0) */
- /* the holding pattern is now within the first 0x100
- bytes of the kernel image -- paulus */
- memcpy((void *)0, _stext, 0x100);
- flush_icache_range(0, 0x100);
-
- /* look for cpus */
- *(unsigned long *)(0x0) = 0;
- asm volatile("dcbf 0,%0": : "r" (0) : "memory");
- for (node = 0; prom_next_node(&node); ) {
- type[0] = 0;
- call_prom("getprop", 4, 1, node, "device_type",
- type, sizeof(type));
- if (strcmp(type, "cpu") != 0)
- continue;
- path = (char *) mem;
- memset(path, 0, 256);
- if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
- continue;
- reg = -1;
- call_prom("getprop", 4, 1, node, "reg", &reg, sizeof(reg));
- cpu = smp_chrp_cpu_nr++;
-#ifdef CONFIG_SMP
- smp_hw_index[cpu] = reg;
-#endif /* CONFIG_SMP */
- /* XXX: hack - don't start cpu 0, this cpu -- Cort */
- if (cpu == 0)
- continue;
- prom_print("starting cpu ");
- prom_print(path);
- *(ulong *)(0x4) = 0;
- call_prom("start-cpu", 3, 0, node,
- (char *)__secondary_hold - _stext, cpu);
- prom_print("...");
- for ( i = 0 ; (i < 10000) && (*(ulong *)(0x4) == 0); i++ )
- ;
- if (*(ulong *)(0x4) == cpu)
- prom_print("ok\n");
- else {
- prom_print("failed: ");
- prom_print_hex(*(ulong *)0x4);
- prom_print("\n");
- }
- }
-}
-
-static void __init
-prom_instantiate_rtas(void)
-{
- ihandle prom_rtas;
- prom_arg_t result;
-
- prom_rtas = call_prom("finddevice", 1, 1, "/rtas");
- if (prom_rtas == -1)
- return;
-
- rtas_size = 0;
- call_prom("getprop", 4, 1, prom_rtas,
- "rtas-size", &rtas_size, sizeof(rtas_size));
- prom_print("instantiating rtas");
- if (rtas_size == 0) {
- rtas_data = 0;
- } else {
- /*
- * Ask OF for some space for RTAS.
- * Actually OF has bugs so we just arbitrarily
- * use memory at the 6MB point.
- */
- rtas_data = 6 << 20;
- prom_print(" at ");
- prom_print_hex(rtas_data);
- }
-
- prom_rtas = call_prom("open", 1, 1, "/rtas");
- prom_print("...");
- rtas_entry = 0;
- if (call_prom_ret("call-method", 3, 2, &result,
- "instantiate-rtas", prom_rtas, rtas_data) == 0)
- rtas_entry = result;
- if ((rtas_entry == -1) || (rtas_entry == 0))
- prom_print(" failed\n");
- else
- prom_print(" done\n");
-}
-
-/*
- * We enter here early on, when the Open Firmware prom is still
- * handling exceptions and the MMU hash table for us.
- */
-unsigned long __init
-prom_init(int r3, int r4, prom_entry pp)
-{
- unsigned long mem;
- ihandle prom_mmu;
- unsigned long offset = reloc_offset();
- int i, l;
- char *p, *d;
- unsigned long phys;
- prom_arg_t result[3];
- char model[32];
- phandle node;
- int rc;
-
- /* Default */
- phys = (unsigned long) &_stext;
-
- /* First get a handle for the stdout device */
- prom = pp;
- prom_chosen = call_prom("finddevice", 1, 1, "/chosen");
- if (prom_chosen == -1)
- prom_exit();
- if (call_prom("getprop", 4, 1, prom_chosen, "stdout",
- &prom_stdout, sizeof(prom_stdout)) <= 0)
- prom_exit();
-
- /* Get the full OF pathname of the stdout device */
- mem = (unsigned long) klimit + offset;
- p = (char *) mem;
- memset(p, 0, 256);
- call_prom("instance-to-path", 3, 1, prom_stdout, p, 255);
- of_stdout_device = p;
- mem += strlen(p) + 1;
-
- /* Get the boot device and translate it to a full OF pathname. */
- p = (char *) mem;
- l = call_prom("getprop", 4, 1, prom_chosen, "bootpath", p, 1<<20);
- if (l > 0) {
- p[l] = 0; /* should already be null-terminated */
- bootpath = PTRUNRELOC(p);
- mem += l + 1;
- d = (char *) mem;
- *d = 0;
- call_prom("canon", 3, 1, p, d, 1<<20);
- bootdevice = PTRUNRELOC(d);
- mem = ALIGNUL(mem + strlen(d) + 1);
- }
-
- prom_instantiate_rtas();
-
-#ifdef CONFIG_POWER4
- /*
- * Find out how much memory we have and allocate a
- * suitably-sized hash table.
- */
- prom_alloc_htab();
-#endif
- mem = check_display(mem);
-
- prom_print("copying OF device tree...");
- mem = copy_device_tree(mem, mem + (1<<20));
- prom_print("done\n");
-
- prom_hold_cpus(mem);
-
- klimit = (char *) (mem - offset);
-
- node = call_prom("finddevice", 1, 1, "/");
- rc = call_prom("getprop", 4, 1, node, "model", model, sizeof(model));
- if (rc > 0 && !strncmp (model, "Pegasos", 7)
- && strncmp (model, "Pegasos2", 8)) {
- /* Pegasos 1 has a broken translate method in the OF,
- * and furthermore the BATs are mapped 1:1 so the phys
- * address calculated above is correct, so let's use
- * it directly.
- */
- } else if (offset == 0) {
- /* If we are already running at 0xc0000000, we assume we were
- * loaded by an OF bootloader which did set a BAT for us.
- * This breaks OF translate so we force phys to be 0.
- */
- prom_print("(already at 0xc0000000) phys=0\n");
- phys = 0;
- } else if (call_prom("getprop", 4, 1, prom_chosen, "mmu",
- &prom_mmu, sizeof(prom_mmu)) <= 0) {
- prom_print(" no MMU found\n");
- } else if (call_prom_ret("call-method", 4, 4, result, "translate",
- prom_mmu, &_stext, 1) != 0) {
- prom_print(" (translate failed)\n");
- } else {
- /* We assume the phys. address size is 3 cells */
- phys = result[2];
- }
-
- if (prom_disp_node != 0)
- setup_disp_fake_bi(prom_disp_node);
-
- /* Use quiesce call to get OF to shut down any devices it's using */
- prom_print("Calling quiesce ...\n");
- call_prom("quiesce", 0, 0);
-
- /* Relocate various pointers which will be used once the
- kernel is running at the address it was linked at. */
- for (i = 0; i < prom_num_displays; ++i)
- prom_display_paths[i] = PTRUNRELOC(prom_display_paths[i]);
-
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
- /* Relocate the of stdout for console autodetection */
- of_stdout_device = PTRUNRELOC(of_stdout_device);
-#endif
-
- prom_print("returning 0x");
- prom_print_hex(phys);
- prom_print("from prom_init\n");
- prom_stdout = 0;
-
- return phys;
-}
-
-/*
- * early_get_property is used to access the device tree image prepared
- * by BootX very early on, before the pointers in it have been relocated.
- */
-static void * __init
-early_get_property(unsigned long base, unsigned long node, char *prop)
-{
- struct device_node *np = (struct device_node *)(base + node);
- struct property *pp;
-
- for (pp = np->properties; pp != 0; pp = pp->next) {
- pp = (struct property *) (base + (unsigned long)pp);
- if (strcmp((char *)((unsigned long)pp->name + base),
- prop) == 0) {
- return (void *)((unsigned long)pp->value + base);
- }
- }
- return NULL;
-}
-
-/* Is boot-info compatible ? */
-#define BOOT_INFO_IS_COMPATIBLE(bi) ((bi)->compatible_version <= BOOT_INFO_VERSION)
-#define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2)
-#define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4)
-
-void __init
-bootx_init(unsigned long r4, unsigned long phys)
-{
- boot_infos_t *bi = (boot_infos_t *) r4;
- unsigned long space;
- unsigned long ptr, x;
- char *model;
-
- boot_infos = PTRUNRELOC(bi);
- if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
- bi->logicalDisplayBase = NULL;
-
-#ifdef CONFIG_BOOTX_TEXT
- btext_init(bi);
-
- /*
- * Test if boot-info is compatible. Done only in config
- * CONFIG_BOOTX_TEXT since there is nothing much we can do
- * with an incompatible version, except display a message
- * and eventually hang the processor...
- *
- * I'll try to keep enough of boot-info compatible in the
- * future to always allow display of this message;
- */
- if (!BOOT_INFO_IS_COMPATIBLE(bi)) {
- btext_drawstring(" !!! WARNING - Incompatible version of BootX !!!\n\n\n");
- btext_flushscreen();
- }
-#endif /* CONFIG_BOOTX_TEXT */
-
- /* New BootX enters kernel with MMU off, i/os are not allowed
- here. This hack will have been done by the boostrap anyway.
- */
- if (bi->version < 4) {
- /*
- * XXX If this is an iMac, turn off the USB controller.
- */
- model = (char *) early_get_property
- (r4 + bi->deviceTreeOffset, 4, "model");
- if (model
- && (strcmp(model, "iMac,1") == 0
- || strcmp(model, "PowerMac1,1") == 0)) {
- out_le32((unsigned *)0x80880008, 1); /* XXX */
- }
- }
-
- /* Move klimit to enclose device tree, args, ramdisk, etc... */
- if (bi->version < 5) {
- space = bi->deviceTreeOffset + bi->deviceTreeSize;
- if (bi->ramDisk)
- space = bi->ramDisk + bi->ramDiskSize;
- } else
- space = bi->totalParamsSize;
- klimit = PTRUNRELOC((char *) bi + space);
-
- /* New BootX will have flushed all TLBs and enters kernel with
- MMU switched OFF, so this should not be useful anymore.
- */
- if (bi->version < 4) {
- /*
- * Touch each page to make sure the PTEs for them
- * are in the hash table - the aim is to try to avoid
- * getting DSI exceptions while copying the kernel image.
- */
- for (ptr = ((unsigned long) &_stext) & PAGE_MASK;
- ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
- x = *(volatile unsigned long *)ptr;
- }
-
-#ifdef CONFIG_BOOTX_TEXT
- /*
- * Note that after we call btext_prepare_BAT, we can't do
- * prom_draw*, flushscreen or clearscreen until we turn the MMU
- * on, since btext_prepare_BAT sets disp_bi.logicalDisplayBase
- * to a virtual address.
- */
- btext_prepare_BAT();
-#endif
-}
diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
index ff86b2d814c..cfc2d6ad464 100644
--- a/arch/ppc/xmon/start.c
+++ b/arch/ppc/xmon/start.c
@@ -58,7 +58,7 @@ static struct sysrq_key_op sysrq_xmon_op =
void
xmon_map_scc(void)
{
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_PREP
volatile unsigned char *base;
#elif defined(CONFIG_GEMINI)
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 2b7364ed23b..01c5c082f97 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -14,6 +14,10 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default y
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/s390/crypto/crypt_s390_query.c b/arch/s390/crypto/crypt_s390_query.c
index def02bdc44a..54fb11d7fad 100644
--- a/arch/s390/crypto/crypt_s390_query.c
+++ b/arch/s390/crypto/crypt_s390_query.c
@@ -55,7 +55,7 @@ static void query_available_functions(void)
printk(KERN_INFO "KMC_AES_256: %d\n",
crypt_s390_func_available(KMC_AES_256_ENCRYPT));
- /* query available KIMD fucntions */
+ /* query available KIMD functions */
printk(KERN_INFO "KIMD_QUERY: %d\n",
crypt_s390_func_available(KIMD_QUERY));
printk(KERN_INFO "KIMD_SHA_1: %d\n",
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index cc058dc3bc8..5e14de37c17 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -26,7 +26,6 @@
#include <linux/resource.h>
#include <linux/times.h>
#include <linux/utsname.h>
-#include <linux/timex.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
@@ -705,79 +704,6 @@ asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
return ret;
}
-/* Handle adjtimex compatibility. */
-
-struct timex32 {
- u32 modes;
- s32 offset, freq, maxerror, esterror;
- s32 status, constant, precision, tolerance;
- struct compat_timeval time;
- s32 tick;
- s32 ppsfreq, jitter, shift, stabil;
- s32 jitcnt, calcnt, errcnt, stbcnt;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
-};
-
-extern int do_adjtimex(struct timex *);
-
-asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
-{
- struct timex txc;
- int ret;
-
- memset(&txc, 0, sizeof(struct timex));
-
- if(get_user(txc.modes, &utp->modes) ||
- __get_user(txc.offset, &utp->offset) ||
- __get_user(txc.freq, &utp->freq) ||
- __get_user(txc.maxerror, &utp->maxerror) ||
- __get_user(txc.esterror, &utp->esterror) ||
- __get_user(txc.status, &utp->status) ||
- __get_user(txc.constant, &utp->constant) ||
- __get_user(txc.precision, &utp->precision) ||
- __get_user(txc.tolerance, &utp->tolerance) ||
- __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __get_user(txc.tick, &utp->tick) ||
- __get_user(txc.ppsfreq, &utp->ppsfreq) ||
- __get_user(txc.jitter, &utp->jitter) ||
- __get_user(txc.shift, &utp->shift) ||
- __get_user(txc.stabil, &utp->stabil) ||
- __get_user(txc.jitcnt, &utp->jitcnt) ||
- __get_user(txc.calcnt, &utp->calcnt) ||
- __get_user(txc.errcnt, &utp->errcnt) ||
- __get_user(txc.stbcnt, &utp->stbcnt))
- return -EFAULT;
-
- ret = do_adjtimex(&txc);
-
- if(put_user(txc.modes, &utp->modes) ||
- __put_user(txc.offset, &utp->offset) ||
- __put_user(txc.freq, &utp->freq) ||
- __put_user(txc.maxerror, &utp->maxerror) ||
- __put_user(txc.esterror, &utp->esterror) ||
- __put_user(txc.status, &utp->status) ||
- __put_user(txc.constant, &utp->constant) ||
- __put_user(txc.precision, &utp->precision) ||
- __put_user(txc.tolerance, &utp->tolerance) ||
- __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __put_user(txc.tick, &utp->tick) ||
- __put_user(txc.ppsfreq, &utp->ppsfreq) ||
- __put_user(txc.jitter, &utp->jitter) ||
- __put_user(txc.shift, &utp->shift) ||
- __put_user(txc.stabil, &utp->stabil) ||
- __put_user(txc.jitcnt, &utp->jitcnt) ||
- __put_user(txc.calcnt, &utp->calcnt) ||
- __put_user(txc.errcnt, &utp->errcnt) ||
- __put_user(txc.stbcnt, &utp->stbcnt))
- ret = -EFAULT;
-
- return ret;
-}
-
#ifdef CONFIG_SYSCTL
struct __sysctl_args32 {
u32 name;
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 50e80138e7a..199da68bd7b 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -551,10 +551,10 @@ sys32_newuname_wrapper:
llgtr %r2,%r2 # struct new_utsname *
jg s390x_newuname # branch to system call
- .globl sys32_adjtimex_wrapper
-sys32_adjtimex_wrapper:
- llgtr %r2,%r2 # struct timex_emu31 *
- jg sys32_adjtimex # branch to system call
+ .globl compat_sys_adjtimex_wrapper
+compat_sys_adjtimex_wrapper:
+ llgtr %r2,%r2 # struct compat_timex *
+ jg compat_sys_adjtimex # branch to system call
.globl sys32_mprotect_wrapper
sys32_mprotect_wrapper:
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 99182a415fe..4a0f5a1551e 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -76,17 +76,17 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
/*
* Need to know about CPUs going idle?
*/
-static struct notifier_block *idle_chain;
+static ATOMIC_NOTIFIER_HEAD(idle_chain);
int register_idle_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&idle_chain, nb);
+ return atomic_notifier_chain_register(&idle_chain, nb);
}
EXPORT_SYMBOL(register_idle_notifier);
int unregister_idle_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&idle_chain, nb);
+ return atomic_notifier_chain_unregister(&idle_chain, nb);
}
EXPORT_SYMBOL(unregister_idle_notifier);
@@ -95,7 +95,7 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code)
/* disable monitor call class 0 */
__ctl_clear_bit(8, 15);
- notifier_call_chain(&idle_chain, CPU_NOT_IDLE,
+ atomic_notifier_call_chain(&idle_chain, CPU_NOT_IDLE,
(void *)(long) smp_processor_id());
}
@@ -116,7 +116,8 @@ static void default_idle(void)
return;
}
- rc = notifier_call_chain(&idle_chain, CPU_IDLE, (void *)(long) cpu);
+ rc = atomic_notifier_call_chain(&idle_chain,
+ CPU_IDLE, (void *)(long) cpu);
if (rc != NOTIFY_OK && rc != NOTIFY_DONE)
BUG();
if (rc != NOTIFY_OK) {
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 7c88d85c359..2f56654da82 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -132,7 +132,7 @@ SYSCALL(sys_clone_glue,sys_clone_glue,sys32_clone_glue) /* 120 */
SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper)
SYSCALL(sys_newuname,s390x_newuname,sys32_newuname_wrapper)
NI_SYSCALL /* modify_ldt for i386 */
-SYSCALL(sys_adjtimex,sys_adjtimex,sys32_adjtimex_wrapper)
+SYSCALL(sys_adjtimex,sys_adjtimex,compat_sys_adjtimex_wrapper)
SYSCALL(sys_mprotect,sys_mprotect,sys32_mprotect_wrapper) /* 125 */
SYSCALL(sys_sigprocmask,sys_sigprocmask,compat_sys_sigprocmask_wrapper)
NI_SYSCALL /* old "create module" */
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index e9b275d9073..58583f45947 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -21,6 +21,14 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_HARDIRQS
bool
default y
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 08c9515c480..c72e17a96ee 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -172,7 +172,7 @@ include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/MARKER
archprepare: maketools include/asm-sh/.cpu include/asm-sh/.mach
-.PHONY: maketools FORCE
+PHONY += maketools FORCE
maketools: include/linux/version.h FORCE
$(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h
diff --git a/arch/sh/boards/mpc1211/rtc.c b/arch/sh/boards/mpc1211/rtc.c
index 4d100f04807..a76c655dcee 100644
--- a/arch/sh/boards/mpc1211/rtc.c
+++ b/arch/sh/boards/mpc1211/rtc.c
@@ -9,36 +9,16 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/time.h>
+#include <linux/bcd.h>
#include <linux/mc146818rtc.h>
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
-/* arc/i386/kernel/time.c */
unsigned long get_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- int i;
spin_lock(&rtc_lock);
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
+
+ do {
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
hour = CMOS_READ(RTC_HOURS);
@@ -46,18 +26,22 @@ unsigned long get_cmos_time(void)
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
} while (sec != CMOS_READ(RTC_SECONDS));
- if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
+
+ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
+
spin_unlock(&rtc_lock);
- if ((year += 1900) < 1970)
+
+ year += 1900;
+ if (year < 1970)
year += 100;
+
return mktime(year, mon, day, hour, min, sec);
}
diff --git a/arch/sh/boards/sh03/rtc.c b/arch/sh/boards/sh03/rtc.c
index cbeca7037ba..d609863cfe5 100644
--- a/arch/sh/boards/sh03/rtc.c
+++ b/arch/sh/boards/sh03/rtc.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/time.h>
+#include <linux/bcd.h>
#include <asm/io.h>
#include <linux/rtc.h>
#include <linux/spinlock.h>
@@ -33,14 +34,6 @@
#define RTC_BUSY 1
#define RTC_STOP 2
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
extern void (*rtc_get_time)(struct timespec *);
extern int (*rtc_set_time)(const time_t);
extern spinlock_t rtc_lock;
@@ -48,13 +41,9 @@ extern spinlock_t rtc_lock;
unsigned long get_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- int i;
spin_lock(&rtc_lock);
again:
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (!(ctrl_inb(RTC_CTL) & RTC_BUSY))
- break;
do {
sec = (ctrl_inb(RTC_SEC1) & 0xf) + (ctrl_inb(RTC_SEC10) & 0x7) * 10;
min = (ctrl_inb(RTC_MIN1) & 0xf) + (ctrl_inb(RTC_MIN10) & 0xf) * 10;
diff --git a/arch/sh/kernel/cpu/rtc.c b/arch/sh/kernel/cpu/rtc.c
index f8361f5e788..4304cf75cfa 100644
--- a/arch/sh/kernel/cpu/rtc.c
+++ b/arch/sh/kernel/cpu/rtc.c
@@ -9,18 +9,10 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/time.h>
-
+#include <linux/bcd.h>
#include <asm/io.h>
#include <asm/rtc.h>
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
void sh_rtc_gettimeofday(struct timespec *ts)
{
unsigned int sec128, sec, sec2, min, hr, wk, day, mon, yr, yr100, cf_bit;
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index c0e79843f58..7ee4ca20361 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -20,6 +20,7 @@
#include <linux/root_dev.h>
#include <linux/utsname.h>
#include <linux/cpu.h>
+#include <linux/pfn.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/sections.h>
@@ -275,10 +276,6 @@ void __init setup_arch(char **cmdline_p)
sh_mv_setup(cmdline_p);
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
-
/*
* Find the highest page frame number we have available
*/
diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig
index 07b172deb87..58c678e0666 100644
--- a/arch/sh64/Kconfig
+++ b/arch/sh64/Kconfig
@@ -21,6 +21,14 @@ config RWSEM_GENERIC_SPINLOCK
bool
default y
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/sh64/kernel/setup.c b/arch/sh64/kernel/setup.c
index c7a7b816a30..d2711c9c9d1 100644
--- a/arch/sh64/kernel/setup.c
+++ b/arch/sh64/kernel/setup.c
@@ -48,6 +48,7 @@
#include <linux/root_dev.h>
#include <linux/cpu.h>
#include <linux/initrd.h>
+#include <linux/pfn.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/pgtable.h>
diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
index 0773c9f389f..6b8f4d22abc 100644
--- a/arch/sh64/kernel/time.c
+++ b/arch/sh64/kernel/time.c
@@ -30,6 +30,7 @@
#include <linux/profile.h>
#include <linux/smp.h>
#include <linux/module.h>
+#include <linux/bcd.h>
#include <asm/registers.h> /* required by inline __asm__ stmt. */
@@ -105,14 +106,6 @@
#define RCR1 rtc_base+0x38
#define RCR2 rtc_base+0x3c
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
#define TICK_SIZE (tick_nsec / 1000)
extern unsigned long wall_jiffies;
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index f944b58cdfe..9431e967aa4 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -23,7 +23,6 @@ menu "General machine setup"
config SMP
bool "Symmetric multi-processing support (does not work on sun4/sun4c)"
- depends on BROKEN
---help---
This enables support for systems with more than one CPU. If you have
a system with only one CPU, say N. If you have a system with more
@@ -151,6 +150,14 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index 4c60a6ef54a..aac8af5aae5 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -154,9 +154,11 @@ void (*sparc_init_timers)(irqreturn_t (*)(int, void *,struct pt_regs *)) =
struct irqaction static_irqaction[MAX_STATIC_ALLOC];
int static_irq_count;
-struct irqaction *irq_action[NR_IRQS] = {
- [0 ... (NR_IRQS-1)] = NULL
-};
+struct {
+ struct irqaction *action;
+ int flags;
+} sparc_irq[NR_IRQS];
+#define SPARC_IRQ_INPROGRESS 1
/* Used to protect the IRQ action lists */
DEFINE_SPINLOCK(irq_action_lock);
@@ -177,7 +179,7 @@ int show_interrupts(struct seq_file *p, void *v)
}
spin_lock_irqsave(&irq_action_lock, flags);
if (i < NR_IRQS) {
- action = *(i + irq_action);
+ action = sparc_irq[i].action;
if (!action)
goto out_unlock;
seq_printf(p, "%3d: ", i);
@@ -186,7 +188,7 @@ int show_interrupts(struct seq_file *p, void *v)
#else
for_each_online_cpu(j) {
seq_printf(p, "%10u ",
- kstat_cpu(cpu_logical_map(j)).irqs[i]);
+ kstat_cpu(j).irqs[i]);
}
#endif
seq_printf(p, " %c %s",
@@ -207,7 +209,7 @@ out_unlock:
void free_irq(unsigned int irq, void *dev_id)
{
struct irqaction * action;
- struct irqaction * tmp = NULL;
+ struct irqaction **actionp;
unsigned long flags;
unsigned int cpu_irq;
@@ -225,7 +227,8 @@ void free_irq(unsigned int irq, void *dev_id)
spin_lock_irqsave(&irq_action_lock, flags);
- action = *(cpu_irq + irq_action);
+ actionp = &sparc_irq[cpu_irq].action;
+ action = *actionp;
if (!action->handler) {
printk("Trying to free free IRQ%d\n",irq);
@@ -235,7 +238,7 @@ void free_irq(unsigned int irq, void *dev_id)
for (; action; action = action->next) {
if (action->dev_id == dev_id)
break;
- tmp = action;
+ actionp = &action->next;
}
if (!action) {
printk("Trying to free free shared IRQ%d\n",irq);
@@ -254,11 +257,8 @@ void free_irq(unsigned int irq, void *dev_id)
irq, action->name);
goto out_unlock;
}
-
- if (action && tmp)
- tmp->next = action->next;
- else
- *(cpu_irq + irq_action) = action->next;
+
+ *actionp = action->next;
spin_unlock_irqrestore(&irq_action_lock, flags);
@@ -268,7 +268,7 @@ void free_irq(unsigned int irq, void *dev_id)
kfree(action);
- if (!(*(cpu_irq + irq_action)))
+ if (!sparc_irq[cpu_irq].action)
disable_irq(irq);
out_unlock:
@@ -287,8 +287,11 @@ EXPORT_SYMBOL(free_irq);
#ifdef CONFIG_SMP
void synchronize_irq(unsigned int irq)
{
- printk("synchronize_irq says: implement me!\n");
- BUG();
+ unsigned int cpu_irq;
+
+ cpu_irq = irq & (NR_IRQS - 1);
+ while (sparc_irq[cpu_irq].flags & SPARC_IRQ_INPROGRESS)
+ cpu_relax();
}
#endif /* SMP */
@@ -299,7 +302,7 @@ void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs)
unsigned int cpu_irq;
cpu_irq = irq & (NR_IRQS - 1);
- action = *(cpu_irq + irq_action);
+ action = sparc_irq[cpu_irq].action;
printk("IO device interrupt, irq = %d\n", irq);
printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc,
@@ -330,7 +333,8 @@ void handler_irq(int irq, struct pt_regs * regs)
if(irq < 10)
smp4m_irq_rotate(cpu);
#endif
- action = *(irq + irq_action);
+ action = sparc_irq[irq].action;
+ sparc_irq[irq].flags |= SPARC_IRQ_INPROGRESS;
kstat_cpu(cpu).irqs[irq]++;
do {
if (!action || !action->handler)
@@ -338,6 +342,7 @@ void handler_irq(int irq, struct pt_regs * regs)
action->handler(irq, action->dev_id, regs);
action = action->next;
} while (action);
+ sparc_irq[irq].flags &= ~SPARC_IRQ_INPROGRESS;
enable_pil_irq(irq);
irq_exit();
}
@@ -389,7 +394,7 @@ int request_fast_irq(unsigned int irq,
spin_lock_irqsave(&irq_action_lock, flags);
- action = *(cpu_irq + irq_action);
+ action = sparc_irq[cpu_irq].action;
if(action) {
if(action->flags & SA_SHIRQ)
panic("Trying to register fast irq when already shared.\n");
@@ -452,7 +457,7 @@ int request_fast_irq(unsigned int irq,
action->dev_id = NULL;
action->next = NULL;
- *(cpu_irq + irq_action) = action;
+ sparc_irq[cpu_irq].action = action;
enable_irq(irq);
@@ -467,7 +472,7 @@ int request_irq(unsigned int irq,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags, const char * devname, void *dev_id)
{
- struct irqaction * action, *tmp = NULL;
+ struct irqaction * action, **actionp;
unsigned long flags;
unsigned int cpu_irq;
int ret;
@@ -490,20 +495,20 @@ int request_irq(unsigned int irq,
spin_lock_irqsave(&irq_action_lock, flags);
- action = *(cpu_irq + irq_action);
+ actionp = &sparc_irq[cpu_irq].action;
+ action = *actionp;
if (action) {
- if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
- for (tmp = action; tmp->next; tmp = tmp->next);
- } else {
+ if (!(action->flags & SA_SHIRQ) || !(irqflags & SA_SHIRQ)) {
ret = -EBUSY;
goto out_unlock;
}
- if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
+ if ((action->flags & SA_INTERRUPT) != (irqflags & SA_INTERRUPT)) {
printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
ret = -EBUSY;
goto out_unlock;
- }
- action = NULL; /* Or else! */
+ }
+ for ( ; action; action = *actionp)
+ actionp = &action->next;
}
/* If this is flagged as statically allocated then we use our
@@ -532,10 +537,7 @@ int request_irq(unsigned int irq,
action->next = NULL;
action->dev_id = dev_id;
- if (tmp)
- tmp->next = action;
- else
- *(cpu_irq + irq_action) = action;
+ *actionp = action;
enable_irq(irq);
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index ea5682ce703..2be81211519 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -45,6 +45,7 @@ volatile int __cpu_logical_map[NR_CPUS];
cpumask_t cpu_online_map = CPU_MASK_NONE;
cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
+cpumask_t smp_commenced_mask = CPU_MASK_NONE;
/* The only guaranteed locking primitive available on all Sparc
* processors is 'ldstub [%reg + immediate], %dest_reg' which atomically
@@ -57,11 +58,6 @@ cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
/* Used to make bitops atomic */
unsigned char bitops_spinlock = 0;
-volatile unsigned long ipi_count;
-
-volatile int smp_process_available=0;
-volatile int smp_commenced = 0;
-
void __init smp_store_cpu_info(int id)
{
int cpu_node;
@@ -79,6 +75,22 @@ void __init smp_store_cpu_info(int id)
void __init smp_cpus_done(unsigned int max_cpus)
{
+ extern void smp4m_smp_done(void);
+ unsigned long bogosum = 0;
+ int cpu, num;
+
+ for (cpu = 0, num = 0; cpu < NR_CPUS; cpu++)
+ if (cpu_online(cpu)) {
+ num++;
+ bogosum += cpu_data(cpu).udelay_val;
+ }
+
+ printk("Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
+ num, bogosum/(500000/HZ),
+ (bogosum/(5000/HZ))%100);
+
+ BUG_ON(sparc_cpu_model != sun4m);
+ smp4m_smp_done();
}
void cpu_panic(void)
@@ -89,17 +101,6 @@ void cpu_panic(void)
struct linux_prom_registers smp_penguin_ctable __initdata = { 0 };
-void __init smp_boot_cpus(void)
-{
- extern void smp4m_boot_cpus(void);
- extern void smp4d_boot_cpus(void);
-
- if (sparc_cpu_model == sun4m)
- smp4m_boot_cpus();
- else
- smp4d_boot_cpus();
-}
-
void smp_send_reschedule(int cpu)
{
/* See sparc64 */
@@ -252,20 +253,61 @@ int setup_profiling_timer(unsigned int multiplier)
return 0;
}
-void __init smp_prepare_cpus(unsigned int maxcpus)
+void __init smp_prepare_cpus(unsigned int max_cpus)
{
+ extern void smp4m_boot_cpus(void);
+ int i, cpuid, ncpus, extra;
+
+ BUG_ON(sparc_cpu_model != sun4m);
+ printk("Entering SMP Mode...\n");
+
+ ncpus = 1;
+ extra = 0;
+ for (i = 0; !cpu_find_by_instance(i, NULL, &cpuid); i++) {
+ if (cpuid == boot_cpu_id)
+ continue;
+ if (cpuid < NR_CPUS && ncpus++ < max_cpus)
+ cpu_set(cpuid, phys_cpu_present_map);
+ else
+ extra++;
+ }
+ if (max_cpus >= NR_CPUS && extra)
+ printk("Warning: NR_CPUS is too low to start all cpus\n");
+
+ smp_store_cpu_info(boot_cpu_id);
+
+ smp4m_boot_cpus();
}
void __devinit smp_prepare_boot_cpu(void)
{
- current_thread_info()->cpu = hard_smp_processor_id();
- cpu_set(smp_processor_id(), cpu_online_map);
- cpu_set(smp_processor_id(), phys_cpu_present_map);
+ int cpuid = hard_smp_processor_id();
+
+ if (cpuid >= NR_CPUS) {
+ prom_printf("Serious problem, boot cpu id >= NR_CPUS\n");
+ prom_halt();
+ }
+ if (cpuid != 0)
+ printk("boot cpu id != 0, this could work but is untested\n");
+
+ current_thread_info()->cpu = cpuid;
+ cpu_set(cpuid, cpu_online_map);
+ cpu_set(cpuid, phys_cpu_present_map);
}
int __devinit __cpu_up(unsigned int cpu)
{
- panic("smp doesn't work\n");
+ extern int smp4m_boot_one_cpu(int);
+ int ret;
+
+ ret = smp4m_boot_one_cpu(cpu);
+
+ if (!ret) {
+ cpu_set(cpu, smp_commenced_mask);
+ while (!cpu_online(cpu))
+ mb();
+ }
+ return ret;
}
void smp_bogo(struct seq_file *m)
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 19b25399d7e..2c21d790763 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -136,10 +136,6 @@ EXPORT_PER_CPU_SYMBOL(__cpu_data);
/* IRQ implementation. */
EXPORT_SYMBOL(synchronize_irq);
-/* Misc SMP information */
-EXPORT_SYMBOL(__cpu_number_map);
-EXPORT_SYMBOL(__cpu_logical_map);
-
/* CPU online map and active count. */
EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(phys_cpu_present_map);
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index cea7fc6fc6e..ca656d9bd6f 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -54,7 +54,7 @@ unsigned char cpu_leds[32];
unsigned char sbus_tid[32];
#endif
-extern struct irqaction *irq_action[];
+static struct irqaction *irq_action[NR_IRQS];
extern spinlock_t irq_action_lock;
struct sbus_action {
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 41bb9596be4..b141b7ee671 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -46,14 +46,16 @@ extern volatile int smp_processors_ready;
extern int smp_num_cpus;
static int smp_highest_cpu;
extern volatile unsigned long cpu_callin_map[NR_CPUS];
-extern struct cpuinfo_sparc cpu_data[NR_CPUS];
+extern cpuinfo_sparc cpu_data[NR_CPUS];
extern unsigned char boot_cpu_id;
extern int smp_activated;
extern volatile int __cpu_number_map[NR_CPUS];
extern volatile int __cpu_logical_map[NR_CPUS];
extern volatile unsigned long ipi_count;
extern volatile int smp_process_available;
-extern volatile int smp_commenced;
+
+extern cpumask_t smp_commenced_mask;
+
extern int __smp4d_processor_id(void);
/* #define SMP_DEBUG */
@@ -136,7 +138,7 @@ void __init smp4d_callin(void)
local_irq_enable(); /* We don't allow PIL 14 yet */
- while(!smp_commenced)
+ while (!cpu_isset(cpuid, smp_commenced_mask))
barrier();
spin_lock_irqsave(&sun4d_imsk_lock, flags);
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 1dde312eebd..70b375a4c2c 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -40,15 +40,11 @@ extern ctxd_t *srmmu_ctx_table_phys;
extern void calibrate_delay(void);
extern volatile int smp_processors_ready;
-extern int smp_num_cpus;
extern volatile unsigned long cpu_callin_map[NR_CPUS];
extern unsigned char boot_cpu_id;
-extern int smp_activated;
-extern volatile int __cpu_number_map[NR_CPUS];
-extern volatile int __cpu_logical_map[NR_CPUS];
-extern volatile unsigned long ipi_count;
-extern volatile int smp_process_available;
-extern volatile int smp_commenced;
+
+extern cpumask_t smp_commenced_mask;
+
extern int __smp4m_processor_id(void);
/*#define SMP_DEBUG*/
@@ -77,8 +73,6 @@ void __init smp4m_callin(void)
local_flush_cache_all();
local_flush_tlb_all();
- set_irq_udt(boot_cpu_id);
-
/* Get our local ticker going. */
smp_setup_percpu_timer();
@@ -95,8 +89,9 @@ void __init smp4m_callin(void)
* to call the scheduler code.
*/
/* Allow master to continue. */
- swap((unsigned long *)&cpu_callin_map[cpuid], 1);
+ swap(&cpu_callin_map[cpuid], 1);
+ /* XXX: What's up with all the flushes? */
local_flush_cache_all();
local_flush_tlb_all();
@@ -111,13 +106,14 @@ void __init smp4m_callin(void)
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
- while(!smp_commenced)
- barrier();
-
- local_flush_cache_all();
- local_flush_tlb_all();
+ while (!cpu_isset(cpuid, smp_commenced_mask))
+ mb();
local_irq_enable();
+
+ cpu_set(cpuid, cpu_online_map);
+ /* last one in gets all the interrupts (for testing) */
+ set_irq_udt(boot_cpu_id);
}
extern void init_IRQ(void);
@@ -134,102 +130,76 @@ extern unsigned long trapbase_cpu3[];
void __init smp4m_boot_cpus(void)
{
- int cpucount = 0;
- int i, mid;
+ smp_setup_percpu_timer();
+ local_flush_cache_all();
+}
- printk("Entering SMP Mode...\n");
+int smp4m_boot_one_cpu(int i)
+{
+ extern unsigned long sun4m_cpu_startup;
+ unsigned long *entry = &sun4m_cpu_startup;
+ struct task_struct *p;
+ int timeout;
+ int cpu_node;
- local_irq_enable();
- cpus_clear(cpu_present_map);
+ cpu_find_by_mid(i, &cpu_node);
+
+ /* Cook up an idler for this guy. */
+ p = fork_idle(i);
+ current_set[i] = task_thread_info(p);
+ /* See trampoline.S for details... */
+ entry += ((i-1) * 3);
- for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++)
- cpu_set(mid, cpu_present_map);
+ /*
+ * Initialize the contexts table
+ * Since the call to prom_startcpu() trashes the structure,
+ * we need to re-initialize it for each cpu
+ */
+ smp_penguin_ctable.which_io = 0;
+ smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
+ smp_penguin_ctable.reg_size = 0;
- for(i=0; i < NR_CPUS; i++) {
- __cpu_number_map[i] = -1;
- __cpu_logical_map[i] = -1;
+ /* whirrr, whirrr, whirrrrrrrrr... */
+ printk("Starting CPU %d at %p\n", i, entry);
+ local_flush_cache_all();
+ prom_startcpu(cpu_node,
+ &smp_penguin_ctable, 0, (char *)entry);
+
+ /* wheee... it's going... */
+ for(timeout = 0; timeout < 10000; timeout++) {
+ if(cpu_callin_map[i])
+ break;
+ udelay(200);
}
- __cpu_number_map[boot_cpu_id] = 0;
- __cpu_logical_map[0] = boot_cpu_id;
- current_thread_info()->cpu = boot_cpu_id;
+ if (!(cpu_callin_map[i])) {
+ printk("Processor %d is stuck.\n", i);
+ return -ENODEV;
+ }
- smp_store_cpu_info(boot_cpu_id);
- set_irq_udt(boot_cpu_id);
- smp_setup_percpu_timer();
local_flush_cache_all();
- if(cpu_find_by_instance(1, NULL, NULL))
- return; /* Not an MP box. */
- for(i = 0; i < NR_CPUS; i++) {
- if(i == boot_cpu_id)
- continue;
-
- if (cpu_isset(i, cpu_present_map)) {
- extern unsigned long sun4m_cpu_startup;
- unsigned long *entry = &sun4m_cpu_startup;
- struct task_struct *p;
- int timeout;
-
- /* Cook up an idler for this guy. */
- p = fork_idle(i);
- cpucount++;
- current_set[i] = task_thread_info(p);
- /* See trampoline.S for details... */
- entry += ((i-1) * 3);
-
- /*
- * Initialize the contexts table
- * Since the call to prom_startcpu() trashes the structure,
- * we need to re-initialize it for each cpu
- */
- smp_penguin_ctable.which_io = 0;
- smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
- smp_penguin_ctable.reg_size = 0;
-
- /* whirrr, whirrr, whirrrrrrrrr... */
- printk("Starting CPU %d at %p\n", i, entry);
- local_flush_cache_all();
- prom_startcpu(cpu_data(i).prom_node,
- &smp_penguin_ctable, 0, (char *)entry);
-
- /* wheee... it's going... */
- for(timeout = 0; timeout < 10000; timeout++) {
- if(cpu_callin_map[i])
- break;
- udelay(200);
- }
- if(cpu_callin_map[i]) {
- /* Another "Red Snapper". */
- __cpu_number_map[i] = i;
- __cpu_logical_map[i] = i;
- } else {
- cpucount--;
- printk("Processor %d is stuck.\n", i);
- }
- }
- if(!(cpu_callin_map[i])) {
- cpu_clear(i, cpu_present_map);
- __cpu_number_map[i] = -1;
+ return 0;
+}
+
+void __init smp4m_smp_done(void)
+{
+ int i, first;
+ int *prev;
+
+ /* setup cpu list for irq rotation */
+ first = 0;
+ prev = &first;
+ for (i = 0; i < NR_CPUS; i++) {
+ if (cpu_online(i)) {
+ *prev = i;
+ prev = &cpu_data(i).next;
}
}
+ *prev = first;
local_flush_cache_all();
- if(cpucount == 0) {
- printk("Error: only one Processor found.\n");
- cpu_present_map = cpumask_of_cpu(smp_processor_id());
- } else {
- unsigned long bogosum = 0;
- for_each_present_cpu(i)
- bogosum += cpu_data(i).udelay_val;
- printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n",
- cpucount + 1,
- bogosum/(500000/HZ),
- (bogosum/(5000/HZ))%100);
- smp_activated = 1;
- smp_num_cpus = cpucount + 1;
- }
/* Free unneeded trap tables */
- if (!cpu_isset(i, cpu_present_map)) {
+ if (!cpu_isset(1, cpu_present_map)) {
ClearPageReserved(virt_to_page(trapbase_cpu1));
init_page_count(virt_to_page(trapbase_cpu1));
free_page((unsigned long)trapbase_cpu1);
@@ -263,6 +233,9 @@ void __init smp4m_boot_cpus(void)
*/
void smp4m_irq_rotate(int cpu)
{
+ int next = cpu_data(cpu).next;
+ if (next != cpu)
+ set_irq_udt(next);
}
/* Cross calls, in order to work efficiently and atomically do all
@@ -289,7 +262,7 @@ void smp4m_message_pass(int target, int msg, unsigned long data, int wait)
smp_cpu_in_msg[me]++;
if(target == MSG_ALL_BUT_SELF || target == MSG_ALL) {
- mask = cpu_present_map;
+ mask = cpu_online_map;
if(target == MSG_ALL_BUT_SELF)
cpu_clear(me, mask);
for(i = 0; i < 4; i++) {
@@ -314,8 +287,8 @@ static struct smp_funcall {
unsigned long arg3;
unsigned long arg4;
unsigned long arg5;
- unsigned long processors_in[NR_CPUS]; /* Set when ipi entered. */
- unsigned long processors_out[NR_CPUS]; /* Set when ipi exited. */
+ unsigned long processors_in[SUN4M_NCPUS]; /* Set when ipi entered. */
+ unsigned long processors_out[SUN4M_NCPUS]; /* Set when ipi exited. */
} ccall_info;
static DEFINE_SPINLOCK(cross_call_lock);
@@ -324,8 +297,7 @@ static DEFINE_SPINLOCK(cross_call_lock);
void smp4m_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
unsigned long arg3, unsigned long arg4, unsigned long arg5)
{
- if(smp_processors_ready) {
- register int ncpus = smp_num_cpus;
+ register int ncpus = SUN4M_NCPUS;
unsigned long flags;
spin_lock_irqsave(&cross_call_lock, flags);
@@ -340,7 +312,7 @@ void smp4m_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
/* Init receive/complete mapping, plus fire the IPI's off. */
{
- cpumask_t mask = cpu_present_map;
+ cpumask_t mask = cpu_online_map;
register int i;
cpu_clear(smp_processor_id(), mask);
@@ -373,7 +345,6 @@ void smp4m_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
}
spin_unlock_irqrestore(&cross_call_lock, flags);
- }
}
/* Running cross calls. */
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 27b0e0ba858..58c65cc8d0d 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1302,7 +1302,12 @@ void __init srmmu_paging_init(void)
flush_cache_all();
srmmu_set_ctable_ptr((unsigned long)srmmu_ctx_table_phys);
+#ifdef CONFIG_SMP
+ /* Stop from hanging here... */
+ local_flush_tlb_all();
+#else
flush_tlb_all();
+#endif
poke_srmmu();
#ifdef CONFIG_SUN_IO
@@ -1419,6 +1424,7 @@ static void __init init_vac_layout(void)
max_size = vac_cache_size;
if(vac_line_size < min_line_size)
min_line_size = vac_line_size;
+ //FIXME: cpus not contiguous!!
cpu++;
if (cpu >= NR_CPUS || !cpu_online(cpu))
break;
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 267afddf63c..d1e2fc56648 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -162,6 +162,14 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default y
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y if !ULTRA_HAS_POPULATION_COUNT
+
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug
index 3e31be494e5..afe0a7720a2 100644
--- a/arch/sparc64/Kconfig.debug
+++ b/arch/sparc64/Kconfig.debug
@@ -24,7 +24,7 @@ config DEBUG_BOOTMEM
bool "Debug BOOTMEM initialization"
config DEBUG_PAGEALLOC
- bool "Page alloc debugging"
+ bool "Debug page memory allocations"
depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND
help
Unmap pages from the kernel linear mapping after free_pages().
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index f819a9663a8..900fb0b940d 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.16
-# Mon Mar 20 01:23:21 2006
+# Sun Mar 26 14:58:11 2006
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
@@ -38,6 +38,7 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_UID16=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -53,10 +54,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -68,7 +65,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
@@ -76,6 +72,7 @@ CONFIG_KMOD=y
#
# Block layer
#
+CONFIG_BLK_DEV_IO_TRACE=y
#
# IO Schedulers
@@ -111,6 +108,8 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
CONFIG_US3_FREQ=m
CONFIG_US2E_FREQ=m
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HUGETLB_PAGE_SIZE_4MB=y
# CONFIG_HUGETLB_PAGE_SIZE_512K is not set
@@ -128,7 +127,6 @@ CONFIG_HAVE_MEMORY_PRESENT=y
CONFIG_SPARSEMEM_EXTREME=y
CONFIG_MEMORY_HOTPLUG=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_MIGRATION=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_SBUS=y
CONFIG_SBUSCHAR=y
@@ -136,7 +134,6 @@ CONFIG_SUN_AUXIO=y
CONFIG_SUN_IO=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_DEBUG is not set
CONFIG_SUN_OPENPROMFS=m
CONFIG_SPARC32_COMPAT=y
@@ -201,6 +198,8 @@ CONFIG_TCP_CONG_VEGAS=m
CONFIG_TCP_CONG_SCALABLE=m
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
@@ -213,10 +212,12 @@ CONFIG_IPV6_TUNNEL=m
#
CONFIG_IP_DCCP=m
CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
#
# DCCP CCIDs Configuration (EXPERIMENTAL)
#
+CONFIG_IP_DCCP_CCID2=m
CONFIG_IP_DCCP_CCID3=m
CONFIG_IP_DCCP_TFRC_LIB=m
@@ -224,7 +225,6 @@ CONFIG_IP_DCCP_TFRC_LIB=m
# DCCP Kernel Hacking
#
# CONFIG_IP_DCCP_DEBUG is not set
-# CONFIG_IP_DCCP_UNLOAD_HACK is not set
#
# SCTP Configuration (EXPERIMENTAL)
@@ -309,6 +309,7 @@ CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_UB=m
# CONFIG_BLK_DEV_RAM is not set
CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_CDROM_PKTCDVD_WCACHE=y
@@ -722,7 +723,6 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -808,10 +808,6 @@ CONFIG_HWMON=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -820,6 +816,7 @@ CONFIG_HWMON=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -901,10 +898,12 @@ CONFIG_SND_SEQ_DUMMY=m
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
# CONFIG_SND_RTCTIMER is not set
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
@@ -987,6 +986,7 @@ CONFIG_SND_SUN_CS4231=m
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -1014,7 +1014,6 @@ CONFIG_USB_UHCI_HCD=m
#
# USB Device Class drivers
#
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
@@ -1058,15 +1057,6 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_MICROTEK is not set
#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1194,7 +1184,6 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
# CONFIG_CONFIGFS_FS is not set
#
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index b9a9ce70e55..ffc7309e9f2 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -6,9 +6,11 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kprobes.h>
+#include <linux/module.h>
#include <asm/kdebug.h>
#include <asm/signal.h>
#include <asm/cacheflush.h>
+#include <asm/uaccess.h>
/* We do not have hardware single-stepping on sparc64.
* So we implement software single-stepping with breakpoint
@@ -302,16 +304,68 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ const struct exception_table_entry *entry;
+
+ switch(kcb->kprobe_status) {
+ case KPROBE_HIT_SS:
+ case KPROBE_REENTER:
+ /*
+ * We are here because the instruction being single
+ * stepped caused a page fault. We reset the current
+ * kprobe and the tpc points back to the probe address
+ * and allow the page fault handler to continue as a
+ * normal page fault.
+ */
+ regs->tpc = (unsigned long)cur->addr;
+ regs->tnpc = kcb->kprobe_orig_tnpc;
+ regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
+ kcb->kprobe_orig_tstate_pil);
+ if (kcb->kprobe_status == KPROBE_REENTER)
+ restore_previous_kprobe(kcb);
+ else
+ reset_current_kprobe();
+ preempt_enable_no_resched();
+ break;
+ case KPROBE_HIT_ACTIVE:
+ case KPROBE_HIT_SSDONE:
+ /*
+ * We increment the nmissed count for accounting,
+ * we can also use npre/npostfault count for accouting
+ * these specific fault cases.
+ */
+ kprobes_inc_nmissed_count(cur);
+
+ /*
+ * We come here because instructions in the pre/post
+ * handler caused the page_fault, this could happen
+ * if handler tries to access user space by
+ * copy_from_user(), get_user() etc. Let the
+ * user-specified handler try to fix it first.
+ */
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+ return 1;
- if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
- return 1;
+ /*
+ * In case the user-specified fault handler returned
+ * zero, try to fix up.
+ */
- if (kcb->kprobe_status & KPROBE_HIT_SS) {
- resume_execution(cur, regs, kcb);
+ entry = search_exception_tables(regs->tpc);
+ if (entry) {
+ regs->tpc = entry->fixup;
+ regs->tnpc = regs->tpc + 4;
+ return 1;
+ }
- reset_current_kprobe();
- preempt_enable_no_resched();
+ /*
+ * fixup_exception() could not handle it,
+ * Let do_page_fault() fix it.
+ */
+ break;
+ default:
+ break;
}
+
return 0;
}
@@ -324,6 +378,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
struct die_args *args = (struct die_args *)data;
int ret = NOTIFY_DONE;
+ if (args->regs && user_mode(args->regs))
+ return ret;
+
switch (val) {
case DIE_DEBUG:
if (kprobe_handler(args->regs))
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 1b6e2ade100..7dc28a48426 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -1298,6 +1298,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
while (!cpu_find_by_instance(instance, NULL, &mid)) {
if (mid != boot_cpu_id) {
cpu_clear(mid, phys_cpu_present_map);
+ cpu_clear(mid, cpu_present_map);
if (num_possible_cpus() <= max_cpus)
break;
}
@@ -1332,8 +1333,10 @@ void __init smp_setup_cpu_possible_map(void)
instance = 0;
while (!cpu_find_by_instance(instance, NULL, &mid)) {
- if (mid < NR_CPUS)
+ if (mid < NR_CPUS) {
cpu_set(mid, phys_cpu_present_map);
+ cpu_set(mid, cpu_present_map);
+ }
instance++;
}
}
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 9914a17651b..f5e8db1de76 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -175,11 +175,6 @@ EXPORT_SYMBOL(set_bit);
EXPORT_SYMBOL(clear_bit);
EXPORT_SYMBOL(change_bit);
-/* Bit searching */
-EXPORT_SYMBOL(find_next_bit);
-EXPORT_SYMBOL(find_next_zero_bit);
-EXPORT_SYMBOL(find_next_zero_le_bit);
-
EXPORT_SYMBOL(ivector_table);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
@@ -279,18 +274,9 @@ EXPORT_SYMBOL(__prom_getsibling);
/* sparc library symbols */
EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(__strlen_user);
EXPORT_SYMBOL(__strnlen_user);
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strstr);
#ifdef CONFIG_SOLARIS_EMUL_MODULE
EXPORT_SYMBOL(linux_sparc_syscall);
@@ -324,7 +310,6 @@ EXPORT_SYMBOL(__memscan_zero);
EXPORT_SYMBOL(__memscan_generic);
EXPORT_SYMBOL(__memcmp);
EXPORT_SYMBOL(__memset);
-EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(csum_partial_copy_nocheck);
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 0e41df02448..2e906bad56f 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -19,7 +19,6 @@
#include <linux/resource.h>
#include <linux/times.h>
#include <linux/utsname.h>
-#include <linux/timex.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
@@ -945,79 +944,6 @@ asmlinkage long compat_sys_sendfile64(int out_fd, int in_fd,
return ret;
}
-/* Handle adjtimex compatibility. */
-
-struct timex32 {
- u32 modes;
- s32 offset, freq, maxerror, esterror;
- s32 status, constant, precision, tolerance;
- struct compat_timeval time;
- s32 tick;
- s32 ppsfreq, jitter, shift, stabil;
- s32 jitcnt, calcnt, errcnt, stbcnt;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
-};
-
-extern int do_adjtimex(struct timex *);
-
-asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
-{
- struct timex txc;
- int ret;
-
- memset(&txc, 0, sizeof(struct timex));
-
- if (get_user(txc.modes, &utp->modes) ||
- __get_user(txc.offset, &utp->offset) ||
- __get_user(txc.freq, &utp->freq) ||
- __get_user(txc.maxerror, &utp->maxerror) ||
- __get_user(txc.esterror, &utp->esterror) ||
- __get_user(txc.status, &utp->status) ||
- __get_user(txc.constant, &utp->constant) ||
- __get_user(txc.precision, &utp->precision) ||
- __get_user(txc.tolerance, &utp->tolerance) ||
- __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __get_user(txc.tick, &utp->tick) ||
- __get_user(txc.ppsfreq, &utp->ppsfreq) ||
- __get_user(txc.jitter, &utp->jitter) ||
- __get_user(txc.shift, &utp->shift) ||
- __get_user(txc.stabil, &utp->stabil) ||
- __get_user(txc.jitcnt, &utp->jitcnt) ||
- __get_user(txc.calcnt, &utp->calcnt) ||
- __get_user(txc.errcnt, &utp->errcnt) ||
- __get_user(txc.stbcnt, &utp->stbcnt))
- return -EFAULT;
-
- ret = do_adjtimex(&txc);
-
- if (put_user(txc.modes, &utp->modes) ||
- __put_user(txc.offset, &utp->offset) ||
- __put_user(txc.freq, &utp->freq) ||
- __put_user(txc.maxerror, &utp->maxerror) ||
- __put_user(txc.esterror, &utp->esterror) ||
- __put_user(txc.status, &utp->status) ||
- __put_user(txc.constant, &utp->constant) ||
- __put_user(txc.precision, &utp->precision) ||
- __put_user(txc.tolerance, &utp->tolerance) ||
- __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __put_user(txc.tick, &utp->tick) ||
- __put_user(txc.ppsfreq, &utp->ppsfreq) ||
- __put_user(txc.jitter, &utp->jitter) ||
- __put_user(txc.shift, &utp->shift) ||
- __put_user(txc.stabil, &utp->stabil) ||
- __put_user(txc.jitcnt, &utp->jitcnt) ||
- __put_user(txc.calcnt, &utp->calcnt) ||
- __put_user(txc.errcnt, &utp->errcnt) ||
- __put_user(txc.stbcnt, &utp->stbcnt))
- ret = -EFAULT;
-
- return ret;
-}
-
/* This is just a version for 32-bit applications which does
* not force O_LARGEFILE on.
*/
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index c3adb7ac167..3b250f2318f 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -63,7 +63,7 @@ sys_call_table32:
/*200*/ .word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir
.word sys32_readahead, sys32_socketcall, sys32_syslog, sys32_lookup_dcookie, sys32_fadvise64
/*210*/ .word sys32_fadvise64_64, sys32_tgkill, sys32_waitpid, sys_swapoff, sys32_sysinfo
- .word sys32_ipc, sys32_sigreturn, sys_clone, sys32_ioprio_get, sys32_adjtimex
+ .word sys32_ipc, sys32_sigreturn, sys_clone, sys32_ioprio_get, compat_sys_adjtimex
/*220*/ .word sys32_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys32_getpgid
.word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16
/*230*/ .word sys32_select, compat_sys_time, sys_nis_syscall, compat_sys_stime, compat_sys_statfs64
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 7d61f1bfd3d..e55b5c6ece0 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -641,23 +641,8 @@ static void __init set_system_time(void)
mon = MSTK_REG_MONTH(mregs);
year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
} else {
- int i;
-
/* Dallas 12887 RTC chip. */
- /* Stolen from arch/i386/kernel/time.c, see there for
- * credits and descriptive comments.
- */
- for (i = 0; i < 1000000; i++) {
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
- udelay(10);
- }
- for (i = 0; i < 1000000; i++) {
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
- udelay(10);
- }
do {
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
@@ -666,6 +651,7 @@ static void __init set_system_time(void)
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
} while (sec != CMOS_READ(RTC_SECONDS));
+
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
BCD_TO_BIN(sec);
BCD_TO_BIN(min);
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index df612e4f75f..ff090bb9734 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -43,18 +43,19 @@
#include <linux/kmod.h>
#endif
-struct notifier_block *sparc64die_chain;
-static DEFINE_SPINLOCK(die_notifier_lock);
+ATOMIC_NOTIFIER_HEAD(sparc64die_chain);
int register_die_notifier(struct notifier_block *nb)
{
- int err = 0;
- unsigned long flags;
- spin_lock_irqsave(&die_notifier_lock, flags);
- err = notifier_chain_register(&sparc64die_chain, nb);
- spin_unlock_irqrestore(&die_notifier_lock, flags);
- return err;
+ return atomic_notifier_chain_register(&sparc64die_chain, nb);
}
+EXPORT_SYMBOL(register_die_notifier);
+
+int unregister_die_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&sparc64die_chain, nb);
+}
+EXPORT_SYMBOL(unregister_die_notifier);
/* When an irrecoverable trap occurs at tl > 0, the trap entry
* code logs the trap state registers at every level in the trap
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index 8812ded19f0..4a725d8985f 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -14,6 +14,6 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \
NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o NGpatch.o \
NGpage.o NGbzero.o \
copy_in_user.o user_fixup.o memmove.o \
- mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o
+ mcount.o ipcsum.o rwsem.o xor.o delay.o
obj-y += iomap.o
diff --git a/arch/sparc64/lib/find_bit.c b/arch/sparc64/lib/find_bit.c
deleted file mode 100644
index 6059557067b..00000000000
--- a/arch/sparc64/lib/find_bit.c
+++ /dev/null
@@ -1,127 +0,0 @@
-#include <linux/bitops.h>
-
-/**
- * find_next_bit - find the next set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
- unsigned long offset)
-{
- const unsigned long *p = addr + (offset >> 6);
- unsigned long result = offset & ~63UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 63UL;
- if (offset) {
- tmp = *(p++);
- tmp &= (~0UL << offset);
- if (size < 64)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= 64;
- result += 64;
- }
- while (size & ~63UL) {
- if ((tmp = *(p++)))
- goto found_middle;
- result += 64;
- size -= 64;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp &= (~0UL >> (64 - size));
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
-found_middle:
- return result + __ffs(tmp);
-}
-
-/* find_next_zero_bit() finds the first zero bit in a bit string of length
- * 'size' bits, starting the search at bit 'offset'. This is largely based
- * on Linus's ALPHA routines, which are pretty portable BTW.
- */
-
-unsigned long find_next_zero_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset)
-{
- const unsigned long *p = addr + (offset >> 6);
- unsigned long result = offset & ~63UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 63UL;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (64-offset);
- if (size < 64)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 64;
- result += 64;
- }
- while (size & ~63UL) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += 64;
- size -= 64;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp |= ~0UL << size;
- if (tmp == ~0UL) /* Are any bits zero? */
- return result + size; /* Nope. */
-found_middle:
- return result + ffz(tmp);
-}
-
-unsigned long find_next_zero_le_bit(unsigned long *addr, unsigned long size, unsigned long offset)
-{
- unsigned long *p = addr + (offset >> 6);
- unsigned long result = offset & ~63UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 63UL;
- if(offset) {
- tmp = __swab64p(p++);
- tmp |= (~0UL >> (64-offset));
- if(size < 64)
- goto found_first;
- if(~tmp)
- goto found_middle;
- size -= 64;
- result += 64;
- }
- while(size & ~63) {
- if(~(tmp = __swab64p(p++)))
- goto found_middle;
- result += 64;
- size -= 64;
- }
- if(!size)
- return result;
- tmp = __swab64p(p);
-found_first:
- tmp |= (~0UL << size);
- if (tmp == ~0UL) /* Are any bits zero? */
- return result + size; /* Nope. */
-found_middle:
- return result + ffz(tmp);
-}
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index d21ff3230c0..0db2f7d9fab 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -413,12 +413,12 @@ good_area:
#ifdef CONFIG_HUGETLB_PAGE
mm_rss -= (mm->context.huge_pte_count * (HPAGE_SIZE / PAGE_SIZE));
#endif
- if (unlikely(mm_rss >=
+ if (unlikely(mm_rss >
mm->context.tsb_block[MM_TSB_BASE].tsb_rss_limit))
tsb_grow(mm, MM_TSB_BASE, mm_rss);
#ifdef CONFIG_HUGETLB_PAGE
mm_rss = mm->context.huge_pte_count;
- if (unlikely(mm_rss >=
+ if (unlikely(mm_rss >
mm->context.tsb_block[MM_TSB_HUGE].tsb_rss_limit))
tsb_grow(mm, MM_TSB_HUGE, mm_rss);
#endif
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index ef79ed25aec..85e6a55b3b5 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -52,3 +52,8 @@ config ARCH_HAS_SC_SIGNALS
config ARCH_REUSE_HOST_VSYSCALL_AREA
bool
default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
diff --git a/arch/um/Kconfig.x86_64 b/arch/um/Kconfig.x86_64
index aae19bc4b06..f60e9e50642 100644
--- a/arch/um/Kconfig.x86_64
+++ b/arch/um/Kconfig.x86_64
@@ -46,3 +46,8 @@ config ARCH_REUSE_HOST_VSYSCALL_AREA
config SMP_BROKEN
bool
default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
diff --git a/arch/um/Makefile b/arch/um/Makefile
index c58b657f009..8d14c7a831b 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -1,4 +1,7 @@
-#
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
# Licensed under the GPL
#
@@ -88,7 +91,7 @@ CONFIG_KERNEL_HALF_GIGS ?= 0
SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000)
-.PHONY: linux
+PHONY += linux
all: linux
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 54388d10bcf..1488816588e 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -762,7 +762,8 @@ static struct notifier_block panic_exit_notifier = {
static int add_notifier(void)
{
- notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &panic_exit_notifier);
return(0);
}
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index fa617e0719a..0336575d244 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -71,7 +71,7 @@ struct io_thread_req {
int error;
};
-extern int open_ubd_file(char *file, struct openflags *openflags,
+extern int open_ubd_file(char *file, struct openflags *openflags, int shared,
char **backing_file_out, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out,
int *create_cow_out);
@@ -137,7 +137,7 @@ static int fake_major = MAJOR_NR;
static struct gendisk *ubd_gendisk[MAX_DEV];
static struct gendisk *fake_gendisk[MAX_DEV];
-
+
#ifdef CONFIG_BLK_DEV_UBD_SYNC
#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 1, .c = 0, \
.cl = 1 })
@@ -168,6 +168,7 @@ struct ubd {
__u64 size;
struct openflags boot_openflags;
struct openflags openflags;
+ int shared;
int no_cow;
struct cow cow;
struct platform_device pdev;
@@ -189,6 +190,7 @@ struct ubd {
.boot_openflags = OPEN_FLAGS, \
.openflags = OPEN_FLAGS, \
.no_cow = 0, \
+ .shared = 0, \
.cow = DEFAULT_COW, \
}
@@ -305,7 +307,7 @@ static int ubd_setup_common(char *str, int *index_out)
}
major = simple_strtoul(str, &end, 0);
if((*end != '\0') || (end == str)){
- printk(KERN_ERR
+ printk(KERN_ERR
"ubd_setup : didn't parse major number\n");
return(1);
}
@@ -316,7 +318,7 @@ static int ubd_setup_common(char *str, int *index_out)
printk(KERN_ERR "Can't assign a fake major twice\n");
goto out1;
}
-
+
fake_major = major;
printk(KERN_INFO "Setting extra ubd major number to %d\n",
@@ -351,7 +353,7 @@ static int ubd_setup_common(char *str, int *index_out)
if (index_out)
*index_out = n;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < sizeof("rscd="); i++) {
switch (*str) {
case 'r':
flags.w = 0;
@@ -362,11 +364,14 @@ static int ubd_setup_common(char *str, int *index_out)
case 'd':
dev->no_cow = 1;
break;
+ case 'c':
+ dev->shared = 1;
+ break;
case '=':
str++;
goto break_loop;
default:
- printk(KERN_ERR "ubd_setup : Expected '=' or flag letter (r,s or d)\n");
+ printk(KERN_ERR "ubd_setup : Expected '=' or flag letter (r, s, c, or d)\n");
goto out;
}
str++;
@@ -515,7 +520,7 @@ static void ubd_handler(void)
spin_unlock(&ubd_io_lock);
return;
}
-
+
ubd_finish(rq, req.error);
reactivate_fd(thread_fd, UBD_IRQ);
do_ubd_request(ubd_queue);
@@ -532,7 +537,7 @@ static int io_pid = -1;
void kill_io_thread(void)
{
- if(io_pid != -1)
+ if(io_pid != -1)
os_kill_process(io_pid, 1);
}
@@ -567,14 +572,15 @@ static int ubd_open_dev(struct ubd *dev)
create_cow = 0;
create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
back_ptr = dev->no_cow ? NULL : &dev->cow.file;
- dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr,
- &dev->cow.bitmap_offset, &dev->cow.bitmap_len,
- &dev->cow.data_offset, create_ptr);
+ dev->fd = open_ubd_file(dev->file, &dev->openflags, dev->shared,
+ back_ptr, &dev->cow.bitmap_offset,
+ &dev->cow.bitmap_len, &dev->cow.data_offset,
+ create_ptr);
if((dev->fd == -ENOENT) && create_cow){
- dev->fd = create_cow_file(dev->file, dev->cow.file,
+ dev->fd = create_cow_file(dev->file, dev->cow.file,
dev->openflags, 1 << 9, PAGE_SIZE,
- &dev->cow.bitmap_offset,
+ &dev->cow.bitmap_offset,
&dev->cow.bitmap_len,
&dev->cow.data_offset);
if(dev->fd >= 0){
@@ -598,16 +604,16 @@ static int ubd_open_dev(struct ubd *dev)
}
flush_tlb_kernel_vm();
- err = read_cow_bitmap(dev->fd, dev->cow.bitmap,
- dev->cow.bitmap_offset,
+ err = read_cow_bitmap(dev->fd, dev->cow.bitmap,
+ dev->cow.bitmap_offset,
dev->cow.bitmap_len);
if(err < 0)
goto error;
flags = dev->openflags;
flags.w = 0;
- err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL,
- NULL, NULL);
+ err = open_ubd_file(dev->cow.file, &flags, dev->shared, NULL,
+ NULL, NULL, NULL, NULL);
if(err < 0) goto error;
dev->cow.fd = err;
}
@@ -685,11 +691,11 @@ static int ubd_add(int n)
dev->size = ROUND_BLOCK(dev->size);
err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);
- if(err)
+ if(err)
goto out_close;
-
+
if(fake_major != MAJOR_NR)
- ubd_new_disk(fake_major, dev->size, n,
+ ubd_new_disk(fake_major, dev->size, n,
&fake_gendisk[n]);
/* perhaps this should also be under the "if (fake_major)" above */
@@ -854,7 +860,7 @@ int ubd_init(void)
return -1;
}
platform_driver_register(&ubd_driver);
- for (i = 0; i < MAX_DEV; i++)
+ for (i = 0; i < MAX_DEV; i++)
ubd_add(i);
return 0;
}
@@ -872,16 +878,16 @@ int ubd_driver_init(void){
* enough. So use anyway the io thread. */
}
stack = alloc_stack(0, 0);
- io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
+ io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
&thread_fd);
if(io_pid < 0){
- printk(KERN_ERR
+ printk(KERN_ERR
"ubd : Failed to start I/O thread (errno = %d) - "
"falling back to synchronous I/O\n", -io_pid);
io_pid = -1;
return(0);
}
- err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
+ err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
SA_INTERRUPT, "ubd", ubd_dev);
if(err != 0)
printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
@@ -978,7 +984,7 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
if(req->op == UBD_READ) {
for(i = 0; i < req->length >> 9; i++){
if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
- ubd_set_bit(i, (unsigned char *)
+ ubd_set_bit(i, (unsigned char *)
&req->sector_mask);
}
}
@@ -999,7 +1005,7 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
/* This should be impossible now */
if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
- printk("Write attempted on readonly ubd device %s\n",
+ printk("Write attempted on readonly ubd device %s\n",
disk->disk_name);
end_request(req, 0);
return(1);
@@ -1182,7 +1188,7 @@ int read_cow_bitmap(int fd, void *buf, int offset, int len)
return(0);
}
-int open_ubd_file(char *file, struct openflags *openflags,
+int open_ubd_file(char *file, struct openflags *openflags, int shared,
char **backing_file_out, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out,
int *create_cow_out)
@@ -1206,10 +1212,14 @@ int open_ubd_file(char *file, struct openflags *openflags,
return fd;
}
- err = os_lock_file(fd, openflags->w);
- if(err < 0){
- printk("Failed to lock '%s', err = %d\n", file, -err);
- goto out_close;
+ if(shared)
+ printk("Not locking \"%s\" on the host\n", file);
+ else {
+ err = os_lock_file(fd, openflags->w);
+ if(err < 0){
+ printk("Failed to lock '%s', err = %d\n", file, -err);
+ goto out_close;
+ }
}
/* Succesful return case! */
@@ -1260,7 +1270,7 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
int err, fd;
flags.c = 1;
- fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
+ fd = open_ubd_file(cow_file, &flags, 0, NULL, NULL, NULL, NULL, NULL);
if(fd < 0){
err = fd;
printk("Open of COW file '%s' failed, errno = %d\n", cow_file,
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index b61deb8b362..69a93c804f0 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -6,6 +6,17 @@
#ifndef __IRQ_USER_H__
#define __IRQ_USER_H__
+struct irq_fd {
+ struct irq_fd *next;
+ void *id;
+ int fd;
+ int type;
+ int irq;
+ int pid;
+ int events;
+ int current_events;
+};
+
enum { IRQ_READ, IRQ_WRITE };
extern void sigio_handler(int sig, union uml_pt_regs *regs);
@@ -16,8 +27,6 @@ extern void reactivate_fd(int fd, int irqnum);
extern void deactivate_fd(int fd, int irqnum);
extern int deactivate_all_fds(void);
extern void forward_interrupts(int pid);
-extern void init_irq_signals(int on_sigstack);
-extern void forward_ipi(int fd, int pid);
extern int activate_ipi(int fd, int pid);
extern unsigned long irq_lock(void);
extern void irq_unlock(unsigned long flags);
diff --git a/arch/um/include/kern.h b/arch/um/include/kern.h
index 7d223beccbc..4ce3fc650e5 100644
--- a/arch/um/include/kern.h
+++ b/arch/um/include/kern.h
@@ -29,7 +29,7 @@ extern int getuid(void);
extern int getgid(void);
extern int pause(void);
extern int write(int, const void *, int);
-extern int exit(int);
+extern void exit(int);
extern int close(int);
extern int read(unsigned int, char *, int);
extern int pipe(int *);
diff --git a/arch/um/include/misc_constants.h b/arch/um/include/misc_constants.h
new file mode 100644
index 00000000000..989bc08de36
--- /dev/null
+++ b/arch/um/include/misc_constants.h
@@ -0,0 +1,6 @@
+#ifndef __MISC_CONSTANT_H_
+#define __MISC_CONSTANT_H_
+
+#include <user_constants.h>
+
+#endif
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 2a1c64d8d0b..d3d1bc6074e 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -12,6 +12,7 @@
#include "sysdep/ptrace.h"
#include "kern_util.h"
#include "skas/mm_id.h"
+#include "irq_user.h"
#define OS_TYPE_FILE 1
#define OS_TYPE_DIR 2
@@ -121,6 +122,7 @@ static inline struct openflags of_cloexec(struct openflags flags)
return(flags);
}
+/* file.c */
extern int os_stat_file(const char *file_name, struct uml_stat *buf);
extern int os_stat_fd(const int fd, struct uml_stat *buf);
extern int os_access(const char *file, int mode);
@@ -156,10 +158,20 @@ extern int os_connect_socket(char *name);
extern int os_file_type(char *file);
extern int os_file_mode(char *file, struct openflags *mode_out);
extern int os_lock_file(int fd, int excl);
+extern void os_flush_stdout(void);
+extern int os_stat_filesystem(char *path, long *bsize_out,
+ long long *blocks_out, long long *bfree_out,
+ long long *bavail_out, long long *files_out,
+ long long *ffree_out, void *fsid_out,
+ int fsid_size, long *namelen_out,
+ long *spare_out);
+extern int os_change_dir(char *dir);
+extern int os_fchange_dir(int fd);
/* start_up.c */
extern void os_early_checks(void);
extern int can_do_skas(void);
+extern void os_check_bugs(void);
/* Make sure they are clear when running in TT mode. Required by
* SEGV_MAYBE_FIXABLE */
@@ -198,6 +210,8 @@ extern void os_flush_stdout(void);
/* tt.c
* for tt mode only (will be deleted in future...)
*/
+extern void forward_ipi(int fd, int pid);
+extern void kill_child_dead(int pid);
extern void stop(void);
extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
extern int protect_memory(unsigned long addr, unsigned long len,
@@ -294,4 +308,26 @@ extern void initial_thread_cb_skas(void (*proc)(void *),
extern void halt_skas(void);
extern void reboot_skas(void);
+/* irq.c */
+extern int os_waiting_for_events(struct irq_fd *active_fds);
+extern int os_isatty(int fd);
+extern int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds);
+extern void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
+ struct irq_fd *active_fds, struct irq_fd ***last_irq_ptr2);
+extern void os_free_irq_later(struct irq_fd *active_fds,
+ int irq, void *dev_id);
+extern int os_get_pollfd(int i);
+extern void os_set_pollfd(int i, int fd);
+extern void os_set_ioignore(void);
+extern void init_irq_signals(int on_sigstack);
+
+/* sigio.c */
+extern void write_sigio_workaround(void);
+extern int add_sigio_fd(int fd, int read);
+extern int ignore_sigio_fd(int fd);
+
+/* skas/trap */
+extern void sig_handler_common_skas(int sig, void *sc_ptr);
+extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
+
#endif
diff --git a/arch/um/include/sigio.h b/arch/um/include/sigio.h
index 37d76e29a14..fe99ea163c2 100644
--- a/arch/um/include/sigio.h
+++ b/arch/um/include/sigio.h
@@ -8,9 +8,6 @@
extern int write_sigio_irq(int fd);
extern int register_sigio_fd(int fd);
-extern int read_sigio_fd(int fd);
-extern int add_sigio_fd(int fd, int read);
-extern int ignore_sigio_fd(int fd);
extern void sigio_lock(void);
extern void sigio_unlock(void);
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h
index 260065cfeef..8bc6916bbbb 100644
--- a/arch/um/include/skas/mode-skas.h
+++ b/arch/um/include/skas/mode-skas.h
@@ -13,7 +13,6 @@ extern unsigned long exec_fp_regs[];
extern unsigned long exec_fpx_regs[];
extern int have_fpx_regs;
-extern void sig_handler_common_skas(int sig, void *sc_ptr);
extern void kill_off_processes_skas(void);
#endif
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h
index 86357282d68..853b26f148c 100644
--- a/arch/um/include/skas/skas.h
+++ b/arch/um/include/skas/skas.h
@@ -17,7 +17,6 @@ extern int user_thread(unsigned long stack, int flags);
extern void new_thread_proc(void *stack, void (*handler)(int sig));
extern void new_thread_handler(int sig);
extern void handle_syscall(union uml_pt_regs *regs);
-extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
extern int new_mm(unsigned long stack);
extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
extern long execute_syscall_skas(void *r);
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index a6f1f176cf8..992a7e1e0fc 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -58,7 +58,6 @@ extern int attach(int pid);
extern void kill_child_dead(int pid);
extern int cont(int pid);
extern void check_sigio(void);
-extern void write_sigio_workaround(void);
extern void arch_check_bugs(void);
extern int cpu_feature(char *what, char *buf, int len);
extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 693018ba80f..fe08971b64c 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -7,23 +7,20 @@ extra-y := vmlinux.lds
clean-files :=
obj-y = config.o exec_kern.o exitcode.o \
- init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
- process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
+ init_task.o irq.o ksyms.o mem.o physmem.o \
+ process_kern.o ptrace.o reboot.o resource.o sigio_kern.o \
signal_kern.o smp.o syscall_kern.o sysrq.o \
time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o
obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
-obj-$(CONFIG_TTY_LOG) += tty_log.o
obj-$(CONFIG_SYSCALL_DEBUG) += syscall.o
obj-$(CONFIG_MODE_TT) += tt/
obj-$(CONFIG_MODE_SKAS) += skas/
-user-objs-$(CONFIG_TTY_LOG) += tty_log.o
-
-USER_OBJS := $(user-objs-y) config.o tty_log.o
+USER_OBJS := config.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index c264e1c05ab..1ca84319317 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -30,8 +30,6 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp);
}
-extern void log_exec(char **argv, void *tty);
-
static long execve1(char *file, char __user * __user *argv,
char __user *__user *env)
{
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index bbf94bf2921..c39ea3abeda 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -31,6 +31,8 @@
#include "irq_user.h"
#include "irq_kern.h"
#include "os.h"
+#include "sigio.h"
+#include "misc_constants.h"
/*
* Generic, controller-independent functions:
@@ -77,6 +79,298 @@ skip:
return 0;
}
+struct irq_fd *active_fds = NULL;
+static struct irq_fd **last_irq_ptr = &active_fds;
+
+extern void free_irqs(void);
+
+void sigio_handler(int sig, union uml_pt_regs *regs)
+{
+ struct irq_fd *irq_fd;
+ int n;
+
+ if(smp_sigio_handler()) return;
+ while(1){
+ n = os_waiting_for_events(active_fds);
+ if (n <= 0) {
+ if(n == -EINTR) continue;
+ else break;
+ }
+
+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
+ if(irq_fd->current_events != 0){
+ irq_fd->current_events = 0;
+ do_IRQ(irq_fd->irq, regs);
+ }
+ }
+ }
+
+ free_irqs();
+}
+
+static void maybe_sigio_broken(int fd, int type)
+{
+ if(os_isatty(fd)){
+ if((type == IRQ_WRITE) && !pty_output_sigio){
+ write_sigio_workaround();
+ add_sigio_fd(fd, 0);
+ }
+ else if((type == IRQ_READ) && !pty_close_sigio){
+ write_sigio_workaround();
+ add_sigio_fd(fd, 1);
+ }
+ }
+}
+
+
+int activate_fd(int irq, int fd, int type, void *dev_id)
+{
+ struct pollfd *tmp_pfd;
+ struct irq_fd *new_fd, *irq_fd;
+ unsigned long flags;
+ int pid, events, err, n;
+
+ pid = os_getpid();
+ err = os_set_fd_async(fd, pid);
+ if(err < 0)
+ goto out;
+
+ new_fd = um_kmalloc(sizeof(*new_fd));
+ err = -ENOMEM;
+ if(new_fd == NULL)
+ goto out;
+
+ if(type == IRQ_READ) events = UM_POLLIN | UM_POLLPRI;
+ else events = UM_POLLOUT;
+ *new_fd = ((struct irq_fd) { .next = NULL,
+ .id = dev_id,
+ .fd = fd,
+ .type = type,
+ .irq = irq,
+ .pid = pid,
+ .events = events,
+ .current_events = 0 } );
+
+ /* Critical section - locked by a spinlock because this stuff can
+ * be changed from interrupt handlers. The stuff above is done
+ * outside the lock because it allocates memory.
+ */
+
+ /* Actually, it only looks like it can be called from interrupt
+ * context. The culprit is reactivate_fd, which calls
+ * maybe_sigio_broken, which calls write_sigio_workaround,
+ * which calls activate_fd. However, write_sigio_workaround should
+ * only be called once, at boot time. That would make it clear that
+ * this is called only from process context, and can be locked with
+ * a semaphore.
+ */
+ flags = irq_lock();
+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
+ if((irq_fd->fd == fd) && (irq_fd->type == type)){
+ printk("Registering fd %d twice\n", fd);
+ printk("Irqs : %d, %d\n", irq_fd->irq, irq);
+ printk("Ids : 0x%p, 0x%p\n", irq_fd->id, dev_id);
+ goto out_unlock;
+ }
+ }
+
+ /*-------------*/
+ if(type == IRQ_WRITE)
+ fd = -1;
+
+ tmp_pfd = NULL;
+ n = 0;
+
+ while(1){
+ n = os_create_pollfd(fd, events, tmp_pfd, n);
+ if (n == 0)
+ break;
+
+ /* n > 0
+ * It means we couldn't put new pollfd to current pollfds
+ * and tmp_fds is NULL or too small for new pollfds array.
+ * Needed size is equal to n as minimum.
+ *
+ * Here we have to drop the lock in order to call
+ * kmalloc, which might sleep.
+ * If something else came in and changed the pollfds array
+ * so we will not be able to put new pollfd struct to pollfds
+ * then we free the buffer tmp_fds and try again.
+ */
+ irq_unlock(flags);
+ if (tmp_pfd != NULL) {
+ kfree(tmp_pfd);
+ tmp_pfd = NULL;
+ }
+
+ tmp_pfd = um_kmalloc(n);
+ if (tmp_pfd == NULL)
+ goto out_kfree;
+
+ flags = irq_lock();
+ }
+ /*-------------*/
+
+ *last_irq_ptr = new_fd;
+ last_irq_ptr = &new_fd->next;
+
+ irq_unlock(flags);
+
+ /* This calls activate_fd, so it has to be outside the critical
+ * section.
+ */
+ maybe_sigio_broken(fd, type);
+
+ return(0);
+
+ out_unlock:
+ irq_unlock(flags);
+ out_kfree:
+ kfree(new_fd);
+ out:
+ return(err);
+}
+
+static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
+{
+ unsigned long flags;
+
+ flags = irq_lock();
+ os_free_irq_by_cb(test, arg, active_fds, &last_irq_ptr);
+ irq_unlock(flags);
+}
+
+struct irq_and_dev {
+ int irq;
+ void *dev;
+};
+
+static int same_irq_and_dev(struct irq_fd *irq, void *d)
+{
+ struct irq_and_dev *data = d;
+
+ return((irq->irq == data->irq) && (irq->id == data->dev));
+}
+
+void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
+{
+ struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq,
+ .dev = dev });
+
+ free_irq_by_cb(same_irq_and_dev, &data);
+}
+
+static int same_fd(struct irq_fd *irq, void *fd)
+{
+ return(irq->fd == *((int *) fd));
+}
+
+void free_irq_by_fd(int fd)
+{
+ free_irq_by_cb(same_fd, &fd);
+}
+
+static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
+{
+ struct irq_fd *irq;
+ int i = 0;
+ int fdi;
+
+ for(irq=active_fds; irq != NULL; irq = irq->next){
+ if((irq->fd == fd) && (irq->irq == irqnum)) break;
+ i++;
+ }
+ if(irq == NULL){
+ printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
+ goto out;
+ }
+ fdi = os_get_pollfd(i);
+ if((fdi != -1) && (fdi != fd)){
+ printk("find_irq_by_fd - mismatch between active_fds and "
+ "pollfds, fd %d vs %d, need %d\n", irq->fd,
+ fdi, fd);
+ irq = NULL;
+ goto out;
+ }
+ *index_out = i;
+ out:
+ return(irq);
+}
+
+void reactivate_fd(int fd, int irqnum)
+{
+ struct irq_fd *irq;
+ unsigned long flags;
+ int i;
+
+ flags = irq_lock();
+ irq = find_irq_by_fd(fd, irqnum, &i);
+ if(irq == NULL){
+ irq_unlock(flags);
+ return;
+ }
+ os_set_pollfd(i, irq->fd);
+ irq_unlock(flags);
+
+ /* This calls activate_fd, so it has to be outside the critical
+ * section.
+ */
+ maybe_sigio_broken(fd, irq->type);
+}
+
+void deactivate_fd(int fd, int irqnum)
+{
+ struct irq_fd *irq;
+ unsigned long flags;
+ int i;
+
+ flags = irq_lock();
+ irq = find_irq_by_fd(fd, irqnum, &i);
+ if(irq == NULL)
+ goto out;
+ os_set_pollfd(i, -1);
+ out:
+ irq_unlock(flags);
+}
+
+int deactivate_all_fds(void)
+{
+ struct irq_fd *irq;
+ int err;
+
+ for(irq=active_fds;irq != NULL;irq = irq->next){
+ err = os_clear_fd_async(irq->fd);
+ if(err)
+ return(err);
+ }
+ /* If there is a signal already queued, after unblocking ignore it */
+ os_set_ioignore();
+
+ return(0);
+}
+
+void forward_interrupts(int pid)
+{
+ struct irq_fd *irq;
+ unsigned long flags;
+ int err;
+
+ flags = irq_lock();
+ for(irq=active_fds;irq != NULL;irq = irq->next){
+ err = os_set_owner(irq->fd, pid);
+ if(err < 0){
+ /* XXX Just remove the irq rather than
+ * print out an infinite stream of these
+ */
+ printk("Failed to forward %d to pid %d, err = %d\n",
+ irq->fd, pid, -err);
+ }
+
+ irq->pid = pid;
+ }
+ irq_unlock(flags);
+}
+
/*
* do_IRQ handles all normal device IRQ's (the special
* SMP cross-CPU interrupts have their own specific
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
deleted file mode 100644
index 0e32f5f4a88..00000000000
--- a/arch/um/kernel/irq_user.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/poll.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include "user_util.h"
-#include "kern_util.h"
-#include "user.h"
-#include "process.h"
-#include "sigio.h"
-#include "irq_user.h"
-#include "os.h"
-
-struct irq_fd {
- struct irq_fd *next;
- void *id;
- int fd;
- int type;
- int irq;
- int pid;
- int events;
- int current_events;
-};
-
-static struct irq_fd *active_fds = NULL;
-static struct irq_fd **last_irq_ptr = &active_fds;
-
-static struct pollfd *pollfds = NULL;
-static int pollfds_num = 0;
-static int pollfds_size = 0;
-
-extern int io_count, intr_count;
-
-extern void free_irqs(void);
-
-void sigio_handler(int sig, union uml_pt_regs *regs)
-{
- struct irq_fd *irq_fd;
- int i, n;
-
- if(smp_sigio_handler()) return;
- while(1){
- n = poll(pollfds, pollfds_num, 0);
- if(n < 0){
- if(errno == EINTR) continue;
- printk("sigio_handler : poll returned %d, "
- "errno = %d\n", n, errno);
- break;
- }
- if(n == 0) break;
-
- irq_fd = active_fds;
- for(i = 0; i < pollfds_num; i++){
- if(pollfds[i].revents != 0){
- irq_fd->current_events = pollfds[i].revents;
- pollfds[i].fd = -1;
- }
- irq_fd = irq_fd->next;
- }
-
- for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
- if(irq_fd->current_events != 0){
- irq_fd->current_events = 0;
- do_IRQ(irq_fd->irq, regs);
- }
- }
- }
-
- free_irqs();
-}
-
-int activate_ipi(int fd, int pid)
-{
- return(os_set_fd_async(fd, pid));
-}
-
-static void maybe_sigio_broken(int fd, int type)
-{
- if(isatty(fd)){
- if((type == IRQ_WRITE) && !pty_output_sigio){
- write_sigio_workaround();
- add_sigio_fd(fd, 0);
- }
- else if((type == IRQ_READ) && !pty_close_sigio){
- write_sigio_workaround();
- add_sigio_fd(fd, 1);
- }
- }
-}
-
-int activate_fd(int irq, int fd, int type, void *dev_id)
-{
- struct pollfd *tmp_pfd;
- struct irq_fd *new_fd, *irq_fd;
- unsigned long flags;
- int pid, events, err, n, size;
-
- pid = os_getpid();
- err = os_set_fd_async(fd, pid);
- if(err < 0)
- goto out;
-
- new_fd = um_kmalloc(sizeof(*new_fd));
- err = -ENOMEM;
- if(new_fd == NULL)
- goto out;
-
- if(type == IRQ_READ) events = POLLIN | POLLPRI;
- else events = POLLOUT;
- *new_fd = ((struct irq_fd) { .next = NULL,
- .id = dev_id,
- .fd = fd,
- .type = type,
- .irq = irq,
- .pid = pid,
- .events = events,
- .current_events = 0 } );
-
- /* Critical section - locked by a spinlock because this stuff can
- * be changed from interrupt handlers. The stuff above is done
- * outside the lock because it allocates memory.
- */
-
- /* Actually, it only looks like it can be called from interrupt
- * context. The culprit is reactivate_fd, which calls
- * maybe_sigio_broken, which calls write_sigio_workaround,
- * which calls activate_fd. However, write_sigio_workaround should
- * only be called once, at boot time. That would make it clear that
- * this is called only from process context, and can be locked with
- * a semaphore.
- */
- flags = irq_lock();
- for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
- if((irq_fd->fd == fd) && (irq_fd->type == type)){
- printk("Registering fd %d twice\n", fd);
- printk("Irqs : %d, %d\n", irq_fd->irq, irq);
- printk("Ids : 0x%x, 0x%x\n", irq_fd->id, dev_id);
- goto out_unlock;
- }
- }
-
- n = pollfds_num;
- if(n == pollfds_size){
- while(1){
- /* Here we have to drop the lock in order to call
- * kmalloc, which might sleep. If something else
- * came in and changed the pollfds array, we free
- * the buffer and try again.
- */
- irq_unlock(flags);
- size = (pollfds_num + 1) * sizeof(pollfds[0]);
- tmp_pfd = um_kmalloc(size);
- flags = irq_lock();
- if(tmp_pfd == NULL)
- goto out_unlock;
- if(n == pollfds_size)
- break;
- kfree(tmp_pfd);
- }
- if(pollfds != NULL){
- memcpy(tmp_pfd, pollfds,
- sizeof(pollfds[0]) * pollfds_size);
- kfree(pollfds);
- }
- pollfds = tmp_pfd;
- pollfds_size++;
- }
-
- if(type == IRQ_WRITE)
- fd = -1;
-
- pollfds[pollfds_num] = ((struct pollfd) { .fd = fd,
- .events = events,
- .revents = 0 });
- pollfds_num++;
-
- *last_irq_ptr = new_fd;
- last_irq_ptr = &new_fd->next;
-
- irq_unlock(flags);
-
- /* This calls activate_fd, so it has to be outside the critical
- * section.
- */
- maybe_sigio_broken(fd, type);
-
- return(0);
-
- out_unlock:
- irq_unlock(flags);
- kfree(new_fd);
- out:
- return(err);
-}
-
-static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
-{
- struct irq_fd **prev;
- unsigned long flags;
- int i = 0;
-
- flags = irq_lock();
- prev = &active_fds;
- while(*prev != NULL){
- if((*test)(*prev, arg)){
- struct irq_fd *old_fd = *prev;
- if((pollfds[i].fd != -1) &&
- (pollfds[i].fd != (*prev)->fd)){
- printk("free_irq_by_cb - mismatch between "
- "active_fds and pollfds, fd %d vs %d\n",
- (*prev)->fd, pollfds[i].fd);
- goto out;
- }
-
- pollfds_num--;
-
- /* This moves the *whole* array after pollfds[i] (though
- * it doesn't spot as such)! */
-
- memmove(&pollfds[i], &pollfds[i + 1],
- (pollfds_num - i) * sizeof(pollfds[0]));
-
- if(last_irq_ptr == &old_fd->next)
- last_irq_ptr = prev;
- *prev = (*prev)->next;
- if(old_fd->type == IRQ_WRITE)
- ignore_sigio_fd(old_fd->fd);
- kfree(old_fd);
- continue;
- }
- prev = &(*prev)->next;
- i++;
- }
- out:
- irq_unlock(flags);
-}
-
-struct irq_and_dev {
- int irq;
- void *dev;
-};
-
-static int same_irq_and_dev(struct irq_fd *irq, void *d)
-{
- struct irq_and_dev *data = d;
-
- return((irq->irq == data->irq) && (irq->id == data->dev));
-}
-
-void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
-{
- struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq,
- .dev = dev });
-
- free_irq_by_cb(same_irq_and_dev, &data);
-}
-
-static int same_fd(struct irq_fd *irq, void *fd)
-{
- return(irq->fd == *((int *) fd));
-}
-
-void free_irq_by_fd(int fd)
-{
- free_irq_by_cb(same_fd, &fd);
-}
-
-static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
-{
- struct irq_fd *irq;
- int i = 0;
-
- for(irq=active_fds; irq != NULL; irq = irq->next){
- if((irq->fd == fd) && (irq->irq == irqnum)) break;
- i++;
- }
- if(irq == NULL){
- printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
- goto out;
- }
- if((pollfds[i].fd != -1) && (pollfds[i].fd != fd)){
- printk("find_irq_by_fd - mismatch between active_fds and "
- "pollfds, fd %d vs %d, need %d\n", irq->fd,
- pollfds[i].fd, fd);
- irq = NULL;
- goto out;
- }
- *index_out = i;
- out:
- return(irq);
-}
-
-void reactivate_fd(int fd, int irqnum)
-{
- struct irq_fd *irq;
- unsigned long flags;
- int i;
-
- flags = irq_lock();
- irq = find_irq_by_fd(fd, irqnum, &i);
- if(irq == NULL){
- irq_unlock(flags);
- return;
- }
-
- pollfds[i].fd = irq->fd;
-
- irq_unlock(flags);
-
- /* This calls activate_fd, so it has to be outside the critical
- * section.
- */
- maybe_sigio_broken(fd, irq->type);
-}
-
-void deactivate_fd(int fd, int irqnum)
-{
- struct irq_fd *irq;
- unsigned long flags;
- int i;
-
- flags = irq_lock();
- irq = find_irq_by_fd(fd, irqnum, &i);
- if(irq == NULL)
- goto out;
- pollfds[i].fd = -1;
- out:
- irq_unlock(flags);
-}
-
-int deactivate_all_fds(void)
-{
- struct irq_fd *irq;
- int err;
-
- for(irq=active_fds;irq != NULL;irq = irq->next){
- err = os_clear_fd_async(irq->fd);
- if(err)
- return(err);
- }
- /* If there is a signal already queued, after unblocking ignore it */
- set_handler(SIGIO, SIG_IGN, 0, -1);
-
- return(0);
-}
-
-void forward_ipi(int fd, int pid)
-{
- int err;
-
- err = os_set_owner(fd, pid);
- if(err < 0)
- printk("forward_ipi: set_owner failed, fd = %d, me = %d, "
- "target = %d, err = %d\n", fd, os_getpid(), pid, -err);
-}
-
-void forward_interrupts(int pid)
-{
- struct irq_fd *irq;
- unsigned long flags;
- int err;
-
- flags = irq_lock();
- for(irq=active_fds;irq != NULL;irq = irq->next){
- err = os_set_owner(irq->fd, pid);
- if(err < 0){
- /* XXX Just remove the irq rather than
- * print out an infinite stream of these
- */
- printk("Failed to forward %d to pid %d, err = %d\n",
- irq->fd, pid, -err);
- }
-
- irq->pid = pid;
- }
- irq_unlock(flags);
-}
-
-void init_irq_signals(int on_sigstack)
-{
- __sighandler_t h;
- int flags;
-
- flags = on_sigstack ? SA_ONSTACK : 0;
- if(timer_irq_inited) h = (__sighandler_t) alarm_handler;
- else h = boot_timer_handler;
-
- set_handler(SIGVTALRM, h, flags | SA_RESTART,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
- set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- signal(SIGWINCH, SIG_IGN);
-}
-
-/*
- * 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/physmem.c b/arch/um/kernel/physmem.c
index 0e65340eee3..0500800df1c 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -9,6 +9,7 @@
#include "linux/vmalloc.h"
#include "linux/bootmem.h"
#include "linux/module.h"
+#include "linux/pfn.h"
#include "asm/types.h"
#include "asm/pgtable.h"
#include "kern_util.h"
@@ -316,8 +317,6 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
}
}
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-
extern int __syscall_stub_start, __binary_start;
void setup_physmem(unsigned long start, unsigned long reserve_end,
diff --git a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio_kern.c
index 229988463c4..1c1300fb1e9 100644
--- a/arch/um/kernel/sigio_kern.c
+++ b/arch/um/kernel/sigio_kern.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
@@ -12,13 +12,16 @@
#include "sigio.h"
#include "irq_user.h"
#include "irq_kern.h"
+#include "os.h"
/* Protected by sigio_lock() called from write_sigio_workaround */
static int sigio_irq_fd = -1;
static irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused)
{
- read_sigio_fd(sigio_irq_fd);
+ char c;
+
+ os_read_file(sigio_irq_fd, &c, sizeof(c));
reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
return(IRQ_HANDLED);
}
@@ -51,6 +54,9 @@ void sigio_unlock(void)
spin_unlock(&sigio_spinlock);
}
+extern void sigio_cleanup(void);
+__uml_exitcall(sigio_cleanup);
+
/*
* 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/smp.c b/arch/um/kernel/smp.c
index 72113b0a96e..511116aebaf 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
@@ -77,9 +77,9 @@ static int idle_proc(void *cpup)
if(err < 0)
panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
- activate_ipi(cpu_data[cpu].ipi_pipe[0],
+ os_set_fd_async(cpu_data[cpu].ipi_pipe[0],
current->thread.mode.tt.extern_pid);
-
+
wmb();
if (cpu_test_and_set(cpu, cpu_callin_map)) {
printk("huh, CPU#%d already present??\n", cpu);
@@ -106,7 +106,7 @@ static struct task_struct *idle_thread(int cpu)
panic("copy_process failed in idle_thread, error = %ld",
PTR_ERR(new_task));
- cpu_tasks[cpu] = ((struct cpu_task)
+ cpu_tasks[cpu] = ((struct cpu_task)
{ .pid = new_task->thread.mode.tt.extern_pid,
.task = new_task } );
idle_threads[cpu] = new_task;
@@ -134,16 +134,15 @@ void smp_prepare_cpus(unsigned int maxcpus)
if(err < 0)
panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
- activate_ipi(cpu_data[me].ipi_pipe[0],
+ os_set_fd_async(cpu_data[me].ipi_pipe[0],
current->thread.mode.tt.extern_pid);
for(cpu = 1; cpu < ncpus; cpu++){
printk("Booting processor %d...\n", cpu);
-
+
idle = idle_thread(cpu);
init_idle(idle, cpu);
- unhash_process(idle);
waittime = 200000000;
while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
@@ -223,7 +222,7 @@ void smp_call_function_slave(int cpu)
atomic_inc(&scf_finished);
}
-int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
+int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
int wait)
{
int cpus = num_online_cpus() - 1;
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 80c9c18aae9..7d51dd7201c 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -421,7 +421,7 @@ int linux_main(int argc, char **argv)
#ifndef CONFIG_HIGHMEM
highmem = 0;
printf("CONFIG_HIGHMEM not enabled - physical memory shrunk "
- "to %lu bytes\n", physmem_size);
+ "to %Lu bytes\n", physmem_size);
#endif
}
@@ -433,8 +433,8 @@ int linux_main(int argc, char **argv)
setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
if(init_maps(physmem_size, iomem_size, highmem)){
- printf("Failed to allocate mem_map for %lu bytes of physical "
- "memory and %lu bytes of highmem\n", physmem_size,
+ printf("Failed to allocate mem_map for %Lu bytes of physical "
+ "memory and %Lu bytes of highmem\n", physmem_size,
highmem);
exit(1);
}
@@ -477,7 +477,8 @@ static struct notifier_block panic_exit_notifier = {
void __init setup_arch(char **cmdline_p)
{
- notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &panic_exit_notifier);
paging_init();
strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
@@ -487,8 +488,7 @@ void __init setup_arch(char **cmdline_p)
void __init check_bugs(void)
{
arch_check_bugs();
- check_sigio();
- check_devanon();
+ os_check_bugs();
}
void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 08a4e628b24..1659386b42b 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,14 +3,17 @@
# Licensed under the GPL
#
-obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
- start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o user_syms.o \
- util.o drivers/ sys-$(SUBARCH)/
+obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \
+ signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o \
+ user_syms.o util.o drivers/ sys-$(SUBARCH)/
obj-$(CONFIG_MODE_SKAS) += skas/
+obj-$(CONFIG_TTY_LOG) += tty_log.o
+user-objs-$(CONFIG_TTY_LOG) += tty_log.o
-USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
- start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o util.o
+USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \
+ process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o \
+ uaccess.o umid.o util.o
elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
CFLAGS_elf_aux.o += -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
new file mode 100644
index 00000000000..e599be423da
--- /dev/null
+++ b/arch/um/os-Linux/irq.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include "user_util.h"
+#include "kern_util.h"
+#include "user.h"
+#include "process.h"
+#include "sigio.h"
+#include "irq_user.h"
+#include "os.h"
+
+static struct pollfd *pollfds = NULL;
+static int pollfds_num = 0;
+static int pollfds_size = 0;
+
+int os_waiting_for_events(struct irq_fd *active_fds)
+{
+ struct irq_fd *irq_fd;
+ int i, n, err;
+
+ n = poll(pollfds, pollfds_num, 0);
+ if(n < 0){
+ err = -errno;
+ if(errno != EINTR)
+ printk("sigio_handler: os_waiting_for_events:"
+ " poll returned %d, errno = %d\n", n, errno);
+ return err;
+ }
+
+ if(n == 0)
+ return 0;
+
+ irq_fd = active_fds;
+
+ for(i = 0; i < pollfds_num; i++){
+ if(pollfds[i].revents != 0){
+ irq_fd->current_events = pollfds[i].revents;
+ pollfds[i].fd = -1;
+ }
+ irq_fd = irq_fd->next;
+ }
+ return n;
+}
+
+int os_isatty(int fd)
+{
+ return(isatty(fd));
+}
+
+int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds)
+{
+ if (pollfds_num == pollfds_size) {
+ if (size_tmpfds <= pollfds_size * sizeof(pollfds[0])) {
+ /* return min size needed for new pollfds area */
+ return((pollfds_size + 1) * sizeof(pollfds[0]));
+ }
+
+ if(pollfds != NULL){
+ memcpy(tmp_pfd, pollfds,
+ sizeof(pollfds[0]) * pollfds_size);
+ /* remove old pollfds */
+ kfree(pollfds);
+ }
+ pollfds = tmp_pfd;
+ pollfds_size++;
+ } else {
+ /* remove not used tmp_pfd */
+ if (tmp_pfd != NULL)
+ kfree(tmp_pfd);
+ }
+
+ pollfds[pollfds_num] = ((struct pollfd) { .fd = fd,
+ .events = events,
+ .revents = 0 });
+ pollfds_num++;
+
+ return(0);
+}
+
+void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
+ struct irq_fd *active_fds, struct irq_fd ***last_irq_ptr2)
+{
+ struct irq_fd **prev;
+ int i = 0;
+
+ prev = &active_fds;
+ while(*prev != NULL){
+ if((*test)(*prev, arg)){
+ struct irq_fd *old_fd = *prev;
+ if((pollfds[i].fd != -1) &&
+ (pollfds[i].fd != (*prev)->fd)){
+ printk("os_free_irq_by_cb - mismatch between "
+ "active_fds and pollfds, fd %d vs %d\n",
+ (*prev)->fd, pollfds[i].fd);
+ goto out;
+ }
+
+ pollfds_num--;
+
+ /* This moves the *whole* array after pollfds[i]
+ * (though it doesn't spot as such)!
+ */
+
+ memmove(&pollfds[i], &pollfds[i + 1],
+ (pollfds_num - i) * sizeof(pollfds[0]));
+ if(*last_irq_ptr2 == &old_fd->next)
+ *last_irq_ptr2 = prev;
+
+ *prev = (*prev)->next;
+ if(old_fd->type == IRQ_WRITE)
+ ignore_sigio_fd(old_fd->fd);
+ kfree(old_fd);
+ continue;
+ }
+ prev = &(*prev)->next;
+ i++;
+ }
+ out:
+ return;
+}
+
+
+int os_get_pollfd(int i)
+{
+ return(pollfds[i].fd);
+}
+
+void os_set_pollfd(int i, int fd)
+{
+ pollfds[i].fd = fd;
+}
+
+void os_set_ioignore(void)
+{
+ set_handler(SIGIO, SIG_IGN, 0, -1);
+}
+
+void init_irq_signals(int on_sigstack)
+{
+ __sighandler_t h;
+ int flags;
+
+ flags = on_sigstack ? SA_ONSTACK : 0;
+ if(timer_irq_inited) h = (__sighandler_t) alarm_handler;
+ else h = boot_timer_handler;
+
+ set_handler(SIGVTALRM, h, flags | SA_RESTART,
+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
+ set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ signal(SIGWINCH, SIG_IGN);
+}
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/os-Linux/sigio.c
index f7b18e157d3..9ba94294714 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/os-Linux/sigio.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -20,128 +20,7 @@
#include "sigio.h"
#include "os.h"
-/* Changed during early boot */
-int pty_output_sigio = 0;
-int pty_close_sigio = 0;
-
-/* Used as a flag during SIGIO testing early in boot */
-static volatile int got_sigio = 0;
-
-void __init handler(int sig)
-{
- got_sigio = 1;
-}
-
-struct openpty_arg {
- int master;
- int slave;
- int err;
-};
-
-static void openpty_cb(void *arg)
-{
- struct openpty_arg *info = arg;
-
- info->err = 0;
- if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
- info->err = -errno;
-}
-
-void __init check_one_sigio(void (*proc)(int, int))
-{
- struct sigaction old, new;
- struct openpty_arg pty = { .master = -1, .slave = -1 };
- int master, slave, err;
-
- initial_thread_cb(openpty_cb, &pty);
- if(pty.err){
- printk("openpty failed, errno = %d\n", -pty.err);
- return;
- }
-
- master = pty.master;
- slave = pty.slave;
-
- if((master == -1) || (slave == -1)){
- printk("openpty failed to allocate a pty\n");
- return;
- }
-
- /* Not now, but complain so we now where we failed. */
- err = raw(master);
- if (err < 0)
- panic("check_sigio : __raw failed, errno = %d\n", -err);
-
- err = os_sigio_async(master, slave);
- if(err < 0)
- panic("tty_fds : sigio_async failed, err = %d\n", -err);
-
- if(sigaction(SIGIO, NULL, &old) < 0)
- panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
- new = old;
- new.sa_handler = handler;
- if(sigaction(SIGIO, &new, NULL) < 0)
- panic("check_sigio : sigaction 2 failed, errno = %d\n", errno);
-
- got_sigio = 0;
- (*proc)(master, slave);
-
- os_close_file(master);
- os_close_file(slave);
-
- if(sigaction(SIGIO, &old, NULL) < 0)
- panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
-}
-
-static void tty_output(int master, int slave)
-{
- int n;
- char buf[512];
-
- printk("Checking that host ptys support output SIGIO...");
-
- memset(buf, 0, sizeof(buf));
-
- while(os_write_file(master, buf, sizeof(buf)) > 0) ;
- if(errno != EAGAIN)
- panic("check_sigio : write failed, errno = %d\n", errno);
- while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
-
- if (got_sigio) {
- printk("Yes\n");
- pty_output_sigio = 1;
- } else if (n == -EAGAIN) {
- printk("No, enabling workaround\n");
- } else {
- panic("check_sigio : read failed, err = %d\n", n);
- }
-}
-
-static void tty_close(int master, int slave)
-{
- printk("Checking that host ptys support SIGIO on close...");
-
- os_close_file(slave);
- if(got_sigio){
- printk("Yes\n");
- pty_close_sigio = 1;
- }
- else printk("No, enabling workaround\n");
-}
-
-void __init check_sigio(void)
-{
- if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
- (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
- printk("No pseudo-terminals available - skipping pty SIGIO "
- "check\n");
- return;
- }
- check_one_sigio(tty_output);
- check_one_sigio(tty_close);
-}
-
-/* Protected by sigio_lock(), also used by sigio_cleanup, which is an
+/* Protected by sigio_lock(), also used by sigio_cleanup, which is an
* exitcall.
*/
static int write_sigio_pid = -1;
@@ -150,8 +29,10 @@ static int write_sigio_pid = -1;
* the descriptors closed after it is killed. So, it can't see them change.
* On the UML side, they are changed under the sigio_lock.
*/
-static int write_sigio_fds[2] = { -1, -1 };
-static int sigio_private[2] = { -1, -1 };
+#define SIGIO_FDS_INIT {-1, -1}
+
+static int write_sigio_fds[2] = SIGIO_FDS_INIT;
+static int sigio_private[2] = SIGIO_FDS_INIT;
struct pollfds {
struct pollfd *poll;
@@ -264,13 +145,13 @@ static void update_thread(void)
return;
fail:
/* Critical section start */
- if(write_sigio_pid != -1)
+ if(write_sigio_pid != -1)
os_kill_process(write_sigio_pid, 1);
write_sigio_pid = -1;
- os_close_file(sigio_private[0]);
- os_close_file(sigio_private[1]);
- os_close_file(write_sigio_fds[0]);
- os_close_file(write_sigio_fds[1]);
+ close(sigio_private[0]);
+ close(sigio_private[1]);
+ close(write_sigio_fds[0]);
+ close(write_sigio_fds[1]);
/* Critical section end */
set_signals(flags);
}
@@ -281,13 +162,13 @@ int add_sigio_fd(int fd, int read)
sigio_lock();
for(i = 0; i < current_poll.used; i++){
- if(current_poll.poll[i].fd == fd)
+ if(current_poll.poll[i].fd == fd)
goto out;
}
n = current_poll.used + 1;
err = need_poll(n);
- if(err)
+ if(err)
goto out;
for(i = 0; i < current_poll.used; i++)
@@ -316,7 +197,7 @@ int ignore_sigio_fd(int fd)
}
if(i == current_poll.used)
goto out;
-
+
err = need_poll(current_poll.used - 1);
if(err)
goto out;
@@ -337,7 +218,7 @@ int ignore_sigio_fd(int fd)
return(err);
}
-static struct pollfd* setup_initial_poll(int fd)
+static struct pollfd *setup_initial_poll(int fd)
{
struct pollfd *p;
@@ -377,7 +258,7 @@ void write_sigio_workaround(void)
}
err = os_pipe(l_sigio_private, 1, 1);
if(err < 0){
- printk("write_sigio_workaround - os_pipe 1 failed, "
+ printk("write_sigio_workaround - os_pipe 2 failed, "
"err = %d\n", -err);
goto out_close1;
}
@@ -391,76 +272,52 @@ void write_sigio_workaround(void)
/* Did we race? Don't try to optimize this, please, it's not so likely
* to happen, and no more than once at the boot. */
if(write_sigio_pid != -1)
- goto out_unlock;
+ goto out_free;
- write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
- CLONE_FILES | CLONE_VM, &stack, 0);
-
- if (write_sigio_pid < 0)
- goto out_clear;
+ current_poll = ((struct pollfds) { .poll = p,
+ .used = 1,
+ .size = 1 });
if (write_sigio_irq(l_write_sigio_fds[0]))
- goto out_kill;
+ goto out_clear_poll;
- /* Success, finally. */
memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
- current_poll = ((struct pollfds) { .poll = p,
- .used = 1,
- .size = 1 });
+ write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
+ CLONE_FILES | CLONE_VM, &stack, 0);
- sigio_unlock();
- return;
+ if (write_sigio_pid < 0)
+ goto out_clear;
- out_kill:
- l_write_sigio_pid = write_sigio_pid;
- write_sigio_pid = -1;
sigio_unlock();
- /* Going to call waitpid, avoid holding the lock. */
- os_kill_process(l_write_sigio_pid, 1);
- goto out_free;
+ return;
- out_clear:
+out_clear:
write_sigio_pid = -1;
- out_unlock:
- sigio_unlock();
- out_free:
+ write_sigio_fds[0] = -1;
+ write_sigio_fds[1] = -1;
+ sigio_private[0] = -1;
+ sigio_private[1] = -1;
+out_clear_poll:
+ current_poll = ((struct pollfds) { .poll = NULL,
+ .size = 0,
+ .used = 0 });
+out_free:
kfree(p);
- out_close2:
- os_close_file(l_sigio_private[0]);
- os_close_file(l_sigio_private[1]);
- out_close1:
- os_close_file(l_write_sigio_fds[0]);
- os_close_file(l_write_sigio_fds[1]);
- return;
-}
-
-int read_sigio_fd(int fd)
-{
- int n;
- char c;
-
- n = os_read_file(fd, &c, sizeof(c));
- if(n != sizeof(c)){
- if(n < 0) {
- printk("read_sigio_fd - read failed, err = %d\n", -n);
- return(n);
- }
- else {
- printk("read_sigio_fd - short read, bytes = %d\n", n);
- return(-EIO);
- }
- }
- return(n);
+ sigio_unlock();
+out_close2:
+ close(l_sigio_private[0]);
+ close(l_sigio_private[1]);
+out_close1:
+ close(l_write_sigio_fds[0]);
+ close(l_write_sigio_fds[1]);
}
-static void sigio_cleanup(void)
+void sigio_cleanup(void)
{
- if (write_sigio_pid != -1) {
+ if(write_sigio_pid != -1){
os_kill_process(write_sigio_pid, 1);
write_sigio_pid = -1;
}
}
-
-__uml_exitcall(sigio_cleanup);
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 829d6b0d8b0..32753131f8d 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -3,6 +3,7 @@
* Licensed under the GPL
*/
+#include <pty.h>
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
@@ -539,3 +540,130 @@ int __init parse_iomem(char *str, int *add)
return(1);
}
+
+/* Changed during early boot */
+int pty_output_sigio = 0;
+int pty_close_sigio = 0;
+
+/* Used as a flag during SIGIO testing early in boot */
+static volatile int got_sigio = 0;
+
+static void __init handler(int sig)
+{
+ got_sigio = 1;
+}
+
+struct openpty_arg {
+ int master;
+ int slave;
+ int err;
+};
+
+static void openpty_cb(void *arg)
+{
+ struct openpty_arg *info = arg;
+
+ info->err = 0;
+ if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
+ info->err = -errno;
+}
+
+static void __init check_one_sigio(void (*proc)(int, int))
+{
+ struct sigaction old, new;
+ struct openpty_arg pty = { .master = -1, .slave = -1 };
+ int master, slave, err;
+
+ initial_thread_cb(openpty_cb, &pty);
+ if(pty.err){
+ printk("openpty failed, errno = %d\n", -pty.err);
+ return;
+ }
+
+ master = pty.master;
+ slave = pty.slave;
+
+ if((master == -1) || (slave == -1)){
+ printk("openpty failed to allocate a pty\n");
+ return;
+ }
+
+ /* Not now, but complain so we now where we failed. */
+ err = raw(master);
+ if (err < 0)
+ panic("check_sigio : __raw failed, errno = %d\n", -err);
+
+ err = os_sigio_async(master, slave);
+ if(err < 0)
+ panic("tty_fds : sigio_async failed, err = %d\n", -err);
+
+ if(sigaction(SIGIO, NULL, &old) < 0)
+ panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
+ new = old;
+ new.sa_handler = handler;
+ if(sigaction(SIGIO, &new, NULL) < 0)
+ panic("check_sigio : sigaction 2 failed, errno = %d\n", errno);
+
+ got_sigio = 0;
+ (*proc)(master, slave);
+
+ close(master);
+ close(slave);
+
+ if(sigaction(SIGIO, &old, NULL) < 0)
+ panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
+}
+
+static void tty_output(int master, int slave)
+{
+ int n;
+ char buf[512];
+
+ printk("Checking that host ptys support output SIGIO...");
+
+ memset(buf, 0, sizeof(buf));
+
+ while(os_write_file(master, buf, sizeof(buf)) > 0) ;
+ if(errno != EAGAIN)
+ panic("check_sigio : write failed, errno = %d\n", errno);
+ while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
+
+ if(got_sigio){
+ printk("Yes\n");
+ pty_output_sigio = 1;
+ }
+ else if(n == -EAGAIN) printk("No, enabling workaround\n");
+ else panic("check_sigio : read failed, err = %d\n", n);
+}
+
+static void tty_close(int master, int slave)
+{
+ printk("Checking that host ptys support SIGIO on close...");
+
+ close(slave);
+ if(got_sigio){
+ printk("Yes\n");
+ pty_close_sigio = 1;
+ }
+ else printk("No, enabling workaround\n");
+}
+
+void __init check_sigio(void)
+{
+ if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
+ (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
+ printk("No pseudo-terminals available - skipping pty SIGIO "
+ "check\n");
+ return;
+ }
+ check_one_sigio(tty_output);
+ check_one_sigio(tty_close);
+}
+
+void os_check_bugs(void)
+{
+ check_ptrace();
+ check_sigio();
+ check_devanon();
+}
+
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c
index 919d19f1153..5461a065bbb 100644
--- a/arch/um/os-Linux/tt.c
+++ b/arch/um/os-Linux/tt.c
@@ -110,6 +110,16 @@ int wait_for_stop(int pid, int sig, int cont_type, void *relay)
}
}
+void forward_ipi(int fd, int pid)
+{
+ int err;
+
+ err = os_set_owner(fd, pid);
+ if(err < 0)
+ printk("forward_ipi: set_owner failed, fd = %d, me = %d, "
+ "target = %d, err = %d\n", fd, os_getpid(), pid, -err);
+}
+
/*
*-------------------------
* only for tt mode (will be deleted in future...)
diff --git a/arch/um/kernel/tty_log.c b/arch/um/os-Linux/tty_log.c
index 9ada656f68c..c6ba56c1560 100644
--- a/arch/um/kernel/tty_log.c
+++ b/arch/um/os-Linux/tty_log.c
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and
* geoffrey hing <ghing@net.ohio-state.edu>
* Licensed under the GPL
*/
@@ -58,7 +58,7 @@ int open_tty_log(void *tty, void *current_tty)
return(tty_log_fd);
}
- sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec,
+ sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec,
(unsigned int) tv.tv_usec);
fd = os_open_file(buf, of_append(of_create(of_rdwr(OPENFLAGS()))),
@@ -216,15 +216,3 @@ __uml_setup("tty_log_fd=", set_tty_log_fd,
" tty data will be written. Preconfigure the descriptor with something\n"
" like '10>tty_log tty_log_fd=10'.\n\n"
);
-
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index ecf107ae5ac..198e5916328 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -143,8 +143,10 @@ static int not_dead_yet(char *dir)
goto out_close;
}
- if((kill(p, 0) == 0) || (errno != ESRCH))
+ if((kill(p, 0) == 0) || (errno != ESRCH)){
+ printk("umid \"%s\" is already in use by pid %d\n", umid, p);
return 1;
+ }
err = actually_do_remove(dir);
if(err)
@@ -234,33 +236,44 @@ int __init make_umid(void)
err = mkdir(tmp, 0777);
if(err < 0){
err = -errno;
- if(errno != EEXIST)
+ if(err != -EEXIST)
goto err;
- if(not_dead_yet(tmp) < 0)
+ /* 1 -> this umid is already in use
+ * < 0 -> we couldn't remove the umid directory
+ * In either case, we can't use this umid, so return -EEXIST.
+ */
+ if(not_dead_yet(tmp) != 0)
goto err;
err = mkdir(tmp, 0777);
}
- if(err < 0){
- printk("Failed to create '%s' - err = %d\n", umid, err);
- goto err_rmdir;
+ if(err){
+ err = -errno;
+ printk("Failed to create '%s' - err = %d\n", umid, -errno);
+ goto err;
}
umid_setup = 1;
create_pid_file();
- return 0;
-
- err_rmdir:
- rmdir(tmp);
+ err = 0;
err:
return err;
}
static int __init make_umid_init(void)
{
+ if(!make_umid())
+ return 0;
+
+ /* If initializing with the given umid failed, then try again with
+ * a random one.
+ */
+ printk("Failed to initialize umid \"%s\", trying with a random umid\n",
+ umid);
+ *umid = '\0';
make_umid();
return 0;
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index e839ce65ad2..8032a105949 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -6,6 +6,7 @@
#include <linux/config.h>
#include <linux/compiler.h>
#include "linux/sched.h"
+#include "linux/mm.h"
#include "asm/elf.h"
#include "asm/ptrace.h"
#include "asm/uaccess.h"
@@ -26,9 +27,17 @@ int is_syscall(unsigned long addr)
n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
if(n){
- printk("is_syscall : failed to read instruction from 0x%lx\n",
- addr);
- return(0);
+ /* access_process_vm() grants access to vsyscall and stub,
+ * while copy_from_user doesn't. Maybe access_process_vm is
+ * slow, but that doesn't matter, since it will be called only
+ * in case of singlestepping, if copy_from_user failed.
+ */
+ n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
+ if(n != sizeof(instr)) {
+ printk("is_syscall : failed to read instruction from "
+ "0x%lx\n", addr);
+ return(1);
+ }
}
/* int 0x80 or sysenter */
return((instr == 0x80cd) || (instr == 0x340f));
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 7cd1a82dc8c..33a40f5ef0d 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -58,7 +58,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
}
int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
- struct pt_regs *regs)
+ struct pt_regs *regs, unsigned long sp)
{
struct sigcontext sc;
unsigned long fpregs[HOST_FP_SIZE];
@@ -72,7 +72,7 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
sc.edi = REGS_EDI(regs->regs.skas.regs);
sc.esi = REGS_ESI(regs->regs.skas.regs);
sc.ebp = REGS_EBP(regs->regs.skas.regs);
- sc.esp = REGS_SP(regs->regs.skas.regs);
+ sc.esp = sp;
sc.ebx = REGS_EBX(regs->regs.skas.regs);
sc.edx = REGS_EDX(regs->regs.skas.regs);
sc.ecx = REGS_ECX(regs->regs.skas.regs);
@@ -132,7 +132,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
}
int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
- struct sigcontext *from, int fpsize)
+ struct sigcontext *from, int fpsize, unsigned long sp)
{
struct _fpstate *to_fp, *from_fp;
int err;
@@ -140,11 +140,18 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
to_fp = (fp ? fp : (struct _fpstate *) (to + 1));
from_fp = from->fpstate;
err = copy_to_user(to, from, sizeof(*to));
+
+ /* The SP in the sigcontext is the updated one for the signal
+ * delivery. The sp passed in is the original, and this needs
+ * to be restored, so we stick it in separately.
+ */
+ err |= copy_to_user(&SC_SP(to), sp, sizeof(sp));
+
if(from_fp != NULL){
err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
err |= copy_to_user(to_fp, from_fp, fpsize);
}
- return(err);
+ return err;
}
#endif
@@ -159,11 +166,11 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
}
static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
- struct pt_regs *from)
+ struct pt_regs *from, unsigned long sp)
{
return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
- sizeof(*fp)),
- copy_sc_to_user_skas(to, fp, from)));
+ sizeof(*fp), sp),
+ copy_sc_to_user_skas(to, fp, from, sp)));
}
static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp,
@@ -174,7 +181,7 @@ static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp,
err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
- err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs);
+ err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, sp);
err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
return(err);
}
@@ -207,6 +214,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
{
struct sigframe __user *frame;
void *restorer;
+ unsigned long save_sp = PT_REGS_SP(regs);
int err = 0;
stack_top &= -8UL;
@@ -218,9 +226,19 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
if(ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
+ /* Update SP now because the page fault handler refuses to extend
+ * the stack if the faulting address is too far below the current
+ * SP, which frame now certainly is. If there's an error, the original
+ * value is restored on the way out.
+ * When writing the sigcontext to the stack, we have to write the
+ * original value, so that's passed to copy_sc_to_user, which does
+ * the right thing with it.
+ */
+ PT_REGS_SP(regs) = (unsigned long) frame;
+
err |= __put_user(restorer, &frame->pretcode);
err |= __put_user(sig, &frame->sig);
- err |= copy_sc_to_user(&frame->sc, NULL, regs);
+ err |= copy_sc_to_user(&frame->sc, NULL, regs, save_sp);
err |= __put_user(mask->sig[0], &frame->sc.oldmask);
if (_NSIG_WORDS > 1)
err |= __copy_to_user(&frame->extramask, &mask->sig[1],
@@ -238,7 +256,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
if(err)
- return(err);
+ goto err;
PT_REGS_SP(regs) = (unsigned long) frame;
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
@@ -248,7 +266,11 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
ptrace_notify(SIGTRAP);
- return(0);
+ return 0;
+
+err:
+ PT_REGS_SP(regs) = save_sp;
+ return err;
}
int setup_signal_stack_si(unsigned long stack_top, int sig,
@@ -257,6 +279,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
{
struct rt_sigframe __user *frame;
void *restorer;
+ unsigned long save_sp = PT_REGS_SP(regs);
int err = 0;
stack_top &= -8UL;
@@ -268,13 +291,16 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
if(ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
+ /* See comment above about why this is here */
+ PT_REGS_SP(regs) = (unsigned long) frame;
+
err |= __put_user(restorer, &frame->pretcode);
err |= __put_user(sig, &frame->sig);
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info);
err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
- PT_REGS_SP(regs));
+ save_sp);
/*
* This is movl $,%eax ; int $0x80
@@ -288,9 +314,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
if(err)
- return(err);
+ goto err;
- PT_REGS_SP(regs) = (unsigned long) frame;
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
PT_REGS_EAX(regs) = (unsigned long) sig;
PT_REGS_EDX(regs) = (unsigned long) &frame->info;
@@ -298,7 +323,11 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
ptrace_notify(SIGTRAP);
- return(0);
+ return 0;
+
+err:
+ PT_REGS_SP(regs) = save_sp;
+ return err;
}
long sys_sigreturn(struct pt_regs regs)
diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c
index 26b68675053..6f4ef2b7fa4 100644
--- a/arch/um/sys-i386/user-offsets.c
+++ b/arch/um/sys-i386/user-offsets.c
@@ -3,12 +3,13 @@
#include <asm/ptrace.h>
#include <asm/user.h>
#include <linux/stddef.h>
+#include <sys/poll.h>
#define DEFINE(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define DEFINE_LONGS(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
#define OFFSET(sym, str, mem) \
DEFINE(sym, offsetof(struct str, mem));
@@ -67,4 +68,9 @@ void foo(void)
DEFINE(HOST_ES, ES);
DEFINE(HOST_GS, GS);
DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
+
+ /* XXX Duplicated between i386 and x86_64 */
+ DEFINE(UM_POLLIN, POLLIN);
+ DEFINE(UM_POLLPRI, POLLPRI);
+ DEFINE(UM_POLLOUT, POLLOUT);
}
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index 74eee5c7c6d..147bbf05cbc 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -8,6 +8,7 @@
#include <asm/ptrace.h>
#include <linux/sched.h>
#include <linux/errno.h>
+#include <linux/mm.h>
#include <asm/uaccess.h>
#include <asm/elf.h>
@@ -136,9 +137,28 @@ void arch_switch(void)
*/
}
+/* XXX Mostly copied from sys-i386 */
int is_syscall(unsigned long addr)
{
- panic("is_syscall");
+ unsigned short instr;
+ int n;
+
+ n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
+ if(n){
+ /* access_process_vm() grants access to vsyscall and stub,
+ * while copy_from_user doesn't. Maybe access_process_vm is
+ * slow, but that doesn't matter, since it will be called only
+ * in case of singlestepping, if copy_from_user failed.
+ */
+ n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
+ if(n != sizeof(instr)) {
+ printk("is_syscall : failed to read instruction from "
+ "0x%lx\n", addr);
+ return(1);
+ }
+ }
+ /* sysenter */
+ return(instr == 0x050f);
}
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu )
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index fe1d065332b..e75c4e1838b 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -55,7 +55,8 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
}
int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
- struct pt_regs *regs, unsigned long mask)
+ struct pt_regs *regs, unsigned long mask,
+ unsigned long sp)
{
struct faultinfo * fi = &current->thread.arch.faultinfo;
int err = 0;
@@ -70,7 +71,11 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
err |= PUTREG(regs, RDI, to, rdi);
err |= PUTREG(regs, RSI, to, rsi);
err |= PUTREG(regs, RBP, to, rbp);
- err |= PUTREG(regs, RSP, to, rsp);
+ /* Must use orignal RSP, which is passed in, rather than what's in
+ * the pt_regs, because that's already been updated to point at the
+ * signal frame.
+ */
+ err |= __put_user(sp, &to->rsp);
err |= PUTREG(regs, RBX, to, rbx);
err |= PUTREG(regs, RDX, to, rdx);
err |= PUTREG(regs, RCX, to, rcx);
@@ -102,7 +107,7 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
#ifdef CONFIG_MODE_TT
int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
- int fpsize)
+ int fpsize)
{
struct _fpstate *to_fp, *from_fp;
unsigned long sigs;
@@ -120,7 +125,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
}
int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
- struct sigcontext *from, int fpsize)
+ struct sigcontext *from, int fpsize, unsigned long sp)
{
struct _fpstate *to_fp, *from_fp;
int err;
@@ -128,11 +133,17 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
to_fp = (fp ? fp : (struct _fpstate *) (to + 1));
from_fp = from->fpstate;
err = copy_to_user(to, from, sizeof(*to));
+ /* The SP in the sigcontext is the updated one for the signal
+ * delivery. The sp passed in is the original, and this needs
+ * to be restored, so we stick it in separately.
+ */
+ err |= copy_to_user(&SC_SP(to), sp, sizeof(sp));
+
if(from_fp != NULL){
err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
err |= copy_to_user(to_fp, from_fp, fpsize);
}
- return(err);
+ return err;
}
#endif
@@ -148,11 +159,12 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
}
static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
- struct pt_regs *from, unsigned long mask)
+ struct pt_regs *from, unsigned long mask,
+ unsigned long sp)
{
return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
- sizeof(*fp)),
- copy_sc_to_user_skas(to, fp, from, mask)));
+ sizeof(*fp), sp),
+ copy_sc_to_user_skas(to, fp, from, mask, sp)));
}
struct rt_sigframe
@@ -170,6 +182,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
{
struct rt_sigframe __user *frame;
struct _fpstate __user *fp = NULL;
+ unsigned long save_sp = PT_REGS_RSP(regs);
int err = 0;
struct task_struct *me = current;
@@ -193,14 +206,25 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
goto out;
}
+ /* Update SP now because the page fault handler refuses to extend
+ * the stack if the faulting address is too far below the current
+ * SP, which frame now certainly is. If there's an error, the original
+ * value is restored on the way out.
+ * When writing the sigcontext to the stack, we have to write the
+ * original value, so that's passed to copy_sc_to_user, which does
+ * the right thing with it.
+ */
+ PT_REGS_RSP(regs) = (unsigned long) frame;
+
/* 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)),
+ err |= __put_user(sas_ss_flags(save_sp),
&frame->uc.uc_stack.ss_flags);
err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
- err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
+ err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0],
+ save_sp);
err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate);
if (sizeof(*set) == 16) {
__put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
@@ -217,10 +241,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
else
/* could use a vstub here */
- goto out;
+ goto restore_sp;
if (err)
- goto out;
+ goto restore_sp;
/* Set up registers for signal handler */
{
@@ -238,10 +262,12 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
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);
+ return err;
+
+restore_sp:
+ PT_REGS_RSP(regs) = save_sp;
+ return err;
}
long sys_rt_sigreturn(struct pt_regs *regs)
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c
index 7bd54a921cf..899cebb57c3 100644
--- a/arch/um/sys-x86_64/user-offsets.c
+++ b/arch/um/sys-x86_64/user-offsets.c
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stddef.h>
#include <signal.h>
+#include <sys/poll.h>
#define __FRAME_OFFSETS
#include <asm/ptrace.h>
#include <asm/types.h>
@@ -88,4 +89,9 @@ void foo(void)
DEFINE_LONGS(HOST_IP, RIP);
DEFINE_LONGS(HOST_SP, RSP);
DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
+
+ /* XXX Duplicated between i386 and x86_64 */
+ DEFINE(UM_POLLIN, POLLIN);
+ DEFINE(UM_POLLPRI, POLLPRI);
+ DEFINE(UM_POLLOUT, POLLOUT);
}
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
index e7fc3e50034..37ec644603a 100644
--- a/arch/v850/Kconfig
+++ b/arch/v850/Kconfig
@@ -16,6 +16,12 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
default n
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+config GENERIC_HWEIGHT
+ bool
+ default y
config GENERIC_CALIBRATE_DELAY
bool
default y
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index e18eb79bf85..4310b4a311a 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -45,6 +45,10 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
@@ -246,6 +250,15 @@ config SCHED_SMT
cost of slightly increased overhead in some places. If unsure say
N here.
+config SCHED_MC
+ bool "Multi-core scheduler support"
+ depends on SMP
+ default y
+ help
+ Multi-core scheduler support improves the CPU scheduler's decision
+ making when dealing with multi-core CPU chips at a cost of slightly
+ increased overhead in some places. If unsure say N here.
+
source "kernel/Kconfig.preempt"
config NUMA
@@ -321,9 +334,13 @@ config HAVE_ARCH_EARLY_PFN_TO_NID
def_bool y
depends on NUMA
+config OUT_OF_LINE_PFN_TO_PAGE
+ def_bool y
+ depends on DISCONTIGMEM
+
config NR_CPUS
int "Maximum number of CPUs (2-256)"
- range 2 256
+ range 2 255
depends on SMP
default "8"
help
@@ -364,13 +381,15 @@ config GART_IOMMU
select SWIOTLB
depends on PCI
help
- Support the IOMMU. Needed to run systems with more than 3GB of memory
- properly with 32-bit PCI devices that do not support DAC (Double Address
- Cycle). The IOMMU can be turned off at runtime with the iommu=off parameter.
- Normally the kernel will take the right choice by itself.
- This option includes a driver for the AMD Opteron/Athlon64 northbridge IOMMU
- and a software emulation used on other systems.
- If unsure, say Y.
+ Support for hardware IOMMU in AMD's Opteron/Athlon64 Processors
+ and for the bounce buffering software IOMMU.
+ Needed to run systems with more than 3GB of memory properly with
+ 32-bit PCI devices that do not support DAC (Double Address Cycle).
+ The IOMMU can be turned off at runtime with the iommu=off parameter.
+ Normally the kernel will take the right choice by itself.
+ This option includes a driver for the AMD Opteron/Athlon64 IOMMU
+ northbridge and a software emulation used on other systems without
+ hardware IOMMU. If unsure, say Y.
# need this always enabled with GART_IOMMU for the VIA workaround
config SWIOTLB
@@ -429,10 +448,10 @@ config CRASH_DUMP
config PHYSICAL_START
hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
default "0x1000000" if CRASH_DUMP
- default "0x100000"
+ default "0x200000"
help
This gives the physical address where the kernel is loaded. Normally
- for regular kernels this value is 0x100000 (1MB). But in the case
+ for regular kernels this value is 0x200000 (2MB). But in the case
of kexec on panic the fail safe kernel needs to run at a different
address than the panic-ed kernel. This option is used to set the load
address for kernels used to capture crash dump on being kexec'ed
@@ -464,6 +483,14 @@ config SECCOMP
source kernel/Kconfig.hz
+config REORDER
+ bool "Function reordering"
+ default n
+ help
+ This option enables the toolchain to reorder functions for a more
+ optimal TLB usage. If you have pretty much any version of binutils,
+ this can increase your kernel build time by roughly one minute.
+
endmenu
#
@@ -512,16 +539,6 @@ config PCI_MMCONFIG
bool "Support mmconfig PCI config space access"
depends on PCI && ACPI
-config UNORDERED_IO
- bool "Unordered IO mapping access"
- depends on EXPERIMENTAL
- help
- Use unordered stores to access IO memory mappings in device drivers.
- Still very experimental. When a driver works on IA64/ppc64/pa-risc it should
- work with this option, but it makes the drivers behave differently
- from i386. Requires that the driver writer used memory barriers
- properly.
-
source "drivers/pci/pcie/Kconfig"
source "drivers/pci/Kconfig"
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index d7fd46479c5..585fd4a559c 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -29,12 +29,14 @@ CHECKFLAGS += -D__x86_64__ -m64
cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
+cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic)
CFLAGS += $(cflags-y)
CFLAGS += -m64
CFLAGS += -mno-red-zone
CFLAGS += -mcmodel=kernel
CFLAGS += -pipe
+cflags-$(CONFIG_REORDER) += -ffunction-sections
# this makes reading assembly source easier, but produces worse code
# actually it makes the kernel smaller too.
CFLAGS += -fno-reorder-blocks
@@ -67,8 +69,8 @@ drivers-$(CONFIG_OPROFILE) += arch/x86_64/oprofile/
boot := arch/x86_64/boot
-.PHONY: bzImage bzlilo install archmrproper \
- fdimage fdimage144 fdimage288 archclean
+PHONY += bzImage bzlilo install archmrproper \
+ fdimage fdimage144 fdimage288 isoimage archclean
#Default target when executing "make"
all: bzImage
@@ -85,7 +87,7 @@ bzlilo: vmlinux
bzdisk: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk
-fdimage fdimage144 fdimage288: vmlinux
+fdimage fdimage144 fdimage288 isoimage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
install:
@@ -97,11 +99,16 @@ archclean:
define archhelp
echo '* bzImage - Compressed kernel image (arch/$(ARCH)/boot/bzImage)'
echo ' install - Install kernel using'
- echo ' (your) ~/bin/installkernel or'
- echo ' (distribution) /sbin/installkernel or'
- echo ' install to $$(INSTALL_PATH) and run lilo'
+ echo ' (your) ~/bin/installkernel or'
+ echo ' (distribution) /sbin/installkernel or'
+ echo ' install to $$(INSTALL_PATH) and run lilo'
+ echo ' bzdisk - Create a boot floppy in /dev/fd0'
+ echo ' fdimage - Create a boot floppy image'
+ echo ' isoimage - Create a boot CD-ROM image'
endef
-CLEAN_FILES += arch/$(ARCH)/boot/fdimage arch/$(ARCH)/boot/mtools.conf
+CLEAN_FILES += arch/$(ARCH)/boot/fdimage \
+ arch/$(ARCH)/boot/image.iso \
+ arch/$(ARCH)/boot/mtools.conf
diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile
index 29f8396ed15..43ee6c50c27 100644
--- a/arch/x86_64/boot/Makefile
+++ b/arch/x86_64/boot/Makefile
@@ -60,8 +60,12 @@ $(obj)/setup $(obj)/bootsect: %: %.o FORCE
$(obj)/compressed/vmlinux: FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@
-# Set this if you want to pass append arguments to the zdisk/fdimage kernel
+# Set this if you want to pass append arguments to the zdisk/fdimage/isoimage kernel
FDARGS =
+# Set this if you want an initrd included with the zdisk/fdimage/isoimage kernel
+FDINITRD =
+
+image_cmdline = default linux $(FDARGS) $(if $(FDINITRD),initrd=initrd.img,)
$(obj)/mtools.conf: $(src)/mtools.conf.in
sed -e 's|@OBJ@|$(obj)|g' < $< > $@
@@ -70,8 +74,11 @@ $(obj)/mtools.conf: $(src)/mtools.conf.in
zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync
syslinux /dev/fd0 ; sync
- echo 'default linux $(FDARGS)' | \
+ echo '$(image_cmdline)' | \
MTOOLSRC=$(obj)/mtools.conf mcopy - a:syslinux.cfg
+ if [ -f '$(FDINITRD)' ] ; then \
+ MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' a:initrd.img ; \
+ fi
MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync
# These require being root or having syslinux 2.02 or higher installed
@@ -79,18 +86,39 @@ fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync
syslinux $(obj)/fdimage ; sync
- echo 'default linux $(FDARGS)' | \
+ echo '$(image_cmdline)' | \
MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg
+ if [ -f '$(FDINITRD)' ] ; then \
+ MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' v:initrd.img ; \
+ fi
MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync
fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync
syslinux $(obj)/fdimage ; sync
- echo 'default linux $(FDARGS)' | \
+ echo '$(image_cmdline)' | \
MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg
+ if [ -f '$(FDINITRD)' ] ; then \
+ MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' w:initrd.img ; \
+ fi
MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync
+isoimage: $(BOOTIMAGE)
+ -rm -rf $(obj)/isoimage
+ mkdir $(obj)/isoimage
+ cp `echo /usr/lib*/syslinux/isolinux.bin | awk '{ print $1; }'` \
+ $(obj)/isoimage
+ cp $(BOOTIMAGE) $(obj)/isoimage/linux
+ echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg
+ if [ -f '$(FDINITRD)' ] ; then \
+ cp '$(FDINITRD)' $(obj)/isoimage/initrd.img ; \
+ fi
+ mkisofs -J -r -o $(obj)/image.iso -b isolinux.bin -c boot.cat \
+ -no-emul-boot -boot-load-size 4 -boot-info-table \
+ $(obj)/isoimage
+ rm -rf $(obj)/isoimage
+
zlilo: $(BOOTIMAGE)
if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index ce4de61ed85..566ecc97ee5 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.16-rc3-git9
-# Sat Feb 18 00:27:03 2006
+# Linux kernel version: 2.6.16-git9
+# Sat Mar 25 15:18:40 2006
#
CONFIG_X86_64=y
CONFIG_64BIT=y
@@ -38,6 +38,7 @@ CONFIG_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_UID16=y
CONFIG_VM86=y
@@ -79,6 +80,7 @@ CONFIG_STOP_MACHINE=y
# Block layer
#
CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -139,7 +141,6 @@ CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
CONFIG_NR_CPUS=32
CONFIG_HOTPLUG_CPU=y
CONFIG_HPET_TIMER=y
-CONFIG_X86_PM_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
CONFIG_GART_IOMMU=y
CONFIG_SWIOTLB=y
@@ -148,12 +149,13 @@ CONFIG_X86_MCE_INTEL=y
CONFIG_X86_MCE_AMD=y
# CONFIG_KEXEC is not set
# CONFIG_CRASH_DUMP is not set
-CONFIG_PHYSICAL_START=0x100000
+CONFIG_PHYSICAL_START=0x200000
CONFIG_SECCOMP=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+# CONFIG_REORDER is not set
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_ISA_DMA_API=y
@@ -189,12 +191,14 @@ 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_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
CONFIG_ACPI_EC=y
CONFIG_ACPI_POWER=y
CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_HOTPLUG_MEMORY=y
#
# CPU Frequency scaling
@@ -232,10 +236,8 @@ CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y
CONFIG_PCI=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_MMCONFIG=y
-CONFIG_UNORDERED_IO=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCI_MSI=y
-# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_DEBUG is not set
#
@@ -294,6 +296,7 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_BIC=y
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
@@ -701,6 +704,7 @@ CONFIG_S2IO=m
# Wireless LAN (non-hamradio)
#
# CONFIG_NET_RADIO is not set
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
#
# Wan interfaces
@@ -861,6 +865,8 @@ CONFIG_RTC=y
CONFIG_AGP=y
CONFIG_AGP_AMD64=y
CONFIG_AGP_INTEL=y
+# CONFIG_AGP_SIS is not set
+# CONFIG_AGP_VIA is not set
# CONFIG_DRM is not set
# CONFIG_MWAVE is not set
CONFIG_RAW_DRIVER=y
@@ -907,10 +913,6 @@ CONFIG_HWMON=y
# CONFIG_IBM_ASM is not set
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -974,6 +976,7 @@ CONFIG_SOUND_ICH=y
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -1002,7 +1005,6 @@ CONFIG_USB_UHCI_HCD=y
#
# USB Device Class drivers
#
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
# CONFIG_USB_ACM is not set
CONFIG_USB_PRINTER=y
@@ -1121,11 +1123,7 @@ CONFIG_USB_MON=y
# CONFIG_INFINIBAND is not set
#
-# SN Devices
-#
-
-#
-# EDAC - error detection and reporting (RAS)
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
# CONFIG_EDAC is not set
@@ -1198,7 +1196,6 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -1321,6 +1318,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
# CONFIG_FRAME_POINTER is not set
+# CONFIG_UNWIND_INFO is not set
# CONFIG_FORCED_INLINING is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUG_RODATA is not set
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index 572b3b28772..e776139afb2 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -58,7 +58,7 @@ struct elf_phdr;
#define USE_ELF_CORE_DUMP 1
-/* Overwrite elfcore.h */
+/* Override elfcore.h */
#define _LINUX_ELFCORE_H 1
typedef unsigned int elf_greg_t;
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 00dee176c08..35b2faccdc6 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -501,7 +501,7 @@ ia32_sys_call_table:
.quad sys_setdomainname
.quad sys_uname
.quad sys_modify_ldt
- .quad sys32_adjtimex
+ .quad compat_sys_adjtimex
.quad sys32_mprotect /* 125 */
.quad compat_sys_sigprocmask
.quad quiet_ni_syscall /* create_module */
@@ -688,6 +688,8 @@ ia32_sys_call_table:
.quad sys_ni_syscall /* pselect6 for now */
.quad sys_ni_syscall /* ppoll for now */
.quad sys_unshare /* 310 */
+ .quad compat_sys_set_robust_list
+ .quad compat_sys_get_robust_list
ia32_syscall_end:
.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
.quad ni_syscall
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index 2bc55af9541..f182b20858e 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -30,7 +30,6 @@
#include <linux/resource.h>
#include <linux/times.h>
#include <linux/utsname.h>
-#include <linux/timex.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
@@ -430,24 +429,12 @@ put_tv32(struct compat_timeval __user *o, struct timeval *i)
return err;
}
-extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
+extern unsigned int alarm_setitimer(unsigned int seconds);
asmlinkage long
sys32_alarm(unsigned int seconds)
{
- struct itimerval it_new, it_old;
- unsigned int oldalarm;
-
- it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
- it_new.it_value.tv_sec = seconds;
- it_new.it_value.tv_usec = 0;
- do_setitimer(ITIMER_REAL, &it_new, &it_old);
- oldalarm = it_old.it_value.tv_sec;
- /* ehhh.. We can't return 0 if we have an alarm pending.. */
- /* And we'd better return too much than too little anyway */
- if (it_old.it_value.tv_usec)
- oldalarm++;
- return oldalarm;
+ return alarm_setitimer(seconds);
}
/* Translations due to time_t size differences. Which affects all
@@ -779,82 +766,6 @@ sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count)
return ret;
}
-/* Handle adjtimex compatibility. */
-
-struct timex32 {
- u32 modes;
- s32 offset, freq, maxerror, esterror;
- s32 status, constant, precision, tolerance;
- struct compat_timeval time;
- s32 tick;
- s32 ppsfreq, jitter, shift, stabil;
- s32 jitcnt, calcnt, errcnt, stbcnt;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
- s32 :32; s32 :32; s32 :32; s32 :32;
-};
-
-extern int do_adjtimex(struct timex *);
-
-asmlinkage long
-sys32_adjtimex(struct timex32 __user *utp)
-{
- struct timex txc;
- int ret;
-
- memset(&txc, 0, sizeof(struct timex));
-
- if (!access_ok(VERIFY_READ, utp, sizeof(struct timex32)) ||
- __get_user(txc.modes, &utp->modes) ||
- __get_user(txc.offset, &utp->offset) ||
- __get_user(txc.freq, &utp->freq) ||
- __get_user(txc.maxerror, &utp->maxerror) ||
- __get_user(txc.esterror, &utp->esterror) ||
- __get_user(txc.status, &utp->status) ||
- __get_user(txc.constant, &utp->constant) ||
- __get_user(txc.precision, &utp->precision) ||
- __get_user(txc.tolerance, &utp->tolerance) ||
- __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __get_user(txc.tick, &utp->tick) ||
- __get_user(txc.ppsfreq, &utp->ppsfreq) ||
- __get_user(txc.jitter, &utp->jitter) ||
- __get_user(txc.shift, &utp->shift) ||
- __get_user(txc.stabil, &utp->stabil) ||
- __get_user(txc.jitcnt, &utp->jitcnt) ||
- __get_user(txc.calcnt, &utp->calcnt) ||
- __get_user(txc.errcnt, &utp->errcnt) ||
- __get_user(txc.stbcnt, &utp->stbcnt))
- return -EFAULT;
-
- ret = do_adjtimex(&txc);
-
- if (!access_ok(VERIFY_WRITE, utp, sizeof(struct timex32)) ||
- __put_user(txc.modes, &utp->modes) ||
- __put_user(txc.offset, &utp->offset) ||
- __put_user(txc.freq, &utp->freq) ||
- __put_user(txc.maxerror, &utp->maxerror) ||
- __put_user(txc.esterror, &utp->esterror) ||
- __put_user(txc.status, &utp->status) ||
- __put_user(txc.constant, &utp->constant) ||
- __put_user(txc.precision, &utp->precision) ||
- __put_user(txc.tolerance, &utp->tolerance) ||
- __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
- __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
- __put_user(txc.tick, &utp->tick) ||
- __put_user(txc.ppsfreq, &utp->ppsfreq) ||
- __put_user(txc.jitter, &utp->jitter) ||
- __put_user(txc.shift, &utp->shift) ||
- __put_user(txc.stabil, &utp->stabil) ||
- __put_user(txc.jitcnt, &utp->jitcnt) ||
- __put_user(txc.calcnt, &utp->calcnt) ||
- __put_user(txc.errcnt, &utp->errcnt) ||
- __put_user(txc.stbcnt, &utp->stbcnt))
- ret = -EFAULT;
-
- return ret;
-}
-
asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index a0f955b9995..fffd6b0a2fa 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -60,7 +60,7 @@ static u32 __init allocate_aperture(void)
printk("Cannot allocate aperture memory hole (%p,%uK)\n",
p, aper_size>>10);
if (p)
- free_bootmem_node(nd0, (unsigned long)p, aper_size);
+ free_bootmem_node(nd0, __pa(p), aper_size);
return 0;
}
printk("Mapping aperture over %d KB of RAM @ %lx\n",
@@ -161,7 +161,7 @@ static __u32 __init search_agp_bridge(u32 *order, int *valid_agp)
int num, slot, func;
/* Poor man's PCI discovery */
- for (num = 0; num < 32; num++) {
+ for (num = 0; num < 256; num++) {
for (slot = 0; slot < 32; slot++) {
for (func = 0; func < 8; func++) {
u32 class, cap;
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index e5b14c57eaa..d54620147e8 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -342,6 +342,7 @@ void __init init_bsp_APIC(void)
void __cpuinit setup_local_APIC (void)
{
unsigned int value, maxlvt;
+ int i, j;
value = apic_read(APIC_LVR);
@@ -371,6 +372,25 @@ void __cpuinit setup_local_APIC (void)
apic_write(APIC_TASKPRI, value);
/*
+ * After a crash, we no longer service the interrupts and a pending
+ * interrupt from previous kernel might still have ISR bit set.
+ *
+ * Most probably by now CPU has serviced that pending interrupt and
+ * it might not have done the ack_APIC_irq() because it thought,
+ * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it
+ * does not clear the ISR bit and cpu thinks it has already serivced
+ * the interrupt. Hence a vector might get locked. It was noticed
+ * for timer irq (vector 0x31). Issue an extra EOI to clear ISR.
+ */
+ for (i = APIC_ISR_NR - 1; i >= 0; i--) {
+ value = apic_read(APIC_ISR + i*0x10);
+ for (j = 31; j >= 0; j--) {
+ if (value & (1<<j))
+ ack_APIC_irq();
+ }
+ }
+
+ /*
* Now that we are all set up, enable the APIC
*/
value = apic_read(APIC_SPIV);
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 7c10e9009d6..8538bfea30e 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -553,7 +553,7 @@ iret_label:
/* force a signal here? this matches i386 behaviour */
/* running with kernel gs */
bad_iret:
- movq $-9999,%rdi /* better code? */
+ movq $11,%rdi /* SIGSEGV */
sti
jmp do_exit
.previous
diff --git a/arch/x86_64/kernel/functionlist b/arch/x86_64/kernel/functionlist
new file mode 100644
index 00000000000..2bcebdc3eed
--- /dev/null
+++ b/arch/x86_64/kernel/functionlist
@@ -0,0 +1,1286 @@
+*(.text.flush_thread)
+*(.text.check_poison_obj)
+*(.text.copy_page)
+*(.text.__set_personality)
+*(.text.gart_map_sg)
+*(.text.kmem_cache_free)
+*(.text.find_get_page)
+*(.text._raw_spin_lock)
+*(.text.ide_outb)
+*(.text.unmap_vmas)
+*(.text.copy_page_range)
+*(.text.kprobe_handler)
+*(.text.__handle_mm_fault)
+*(.text.__d_lookup)
+*(.text.copy_user_generic)
+*(.text.__link_path_walk)
+*(.text.get_page_from_freelist)
+*(.text.kmem_cache_alloc)
+*(.text.drive_cmd_intr)
+*(.text.ia32_setup_sigcontext)
+*(.text.huge_pte_offset)
+*(.text.do_page_fault)
+*(.text.page_remove_rmap)
+*(.text.release_pages)
+*(.text.ide_end_request)
+*(.text.__mutex_lock_slowpath)
+*(.text.__find_get_block)
+*(.text.kfree)
+*(.text.vfs_read)
+*(.text._raw_spin_unlock)
+*(.text.free_hot_cold_page)
+*(.text.fget_light)
+*(.text.schedule)
+*(.text.memcmp)
+*(.text.touch_atime)
+*(.text.__might_sleep)
+*(.text.__down_read_trylock)
+*(.text.arch_pick_mmap_layout)
+*(.text.find_vma)
+*(.text.__make_request)
+*(.text.do_generic_mapping_read)
+*(.text.mutex_lock_interruptible)
+*(.text.__generic_file_aio_read)
+*(.text._atomic_dec_and_lock)
+*(.text.__wake_up_bit)
+*(.text.add_to_page_cache)
+*(.text.cache_alloc_debugcheck_after)
+*(.text.vm_normal_page)
+*(.text.mutex_debug_check_no_locks_freed)
+*(.text.net_rx_action)
+*(.text.__find_first_zero_bit)
+*(.text.put_page)
+*(.text._raw_read_lock)
+*(.text.__delay)
+*(.text.dnotify_parent)
+*(.text.do_path_lookup)
+*(.text.do_sync_read)
+*(.text.do_lookup)
+*(.text.bit_waitqueue)
+*(.text.file_read_actor)
+*(.text.strncpy_from_user)
+*(.text.__pagevec_lru_add_active)
+*(.text.fget)
+*(.text.dput)
+*(.text.__strnlen_user)
+*(.text.inotify_inode_queue_event)
+*(.text.rw_verify_area)
+*(.text.ide_intr)
+*(.text.inotify_dentry_parent_queue_event)
+*(.text.permission)
+*(.text.memscan)
+*(.text.hpet_rtc_interrupt)
+*(.text.do_mmap_pgoff)
+*(.text.current_fs_time)
+*(.text.vfs_getattr)
+*(.text.kmem_flagcheck)
+*(.text.mark_page_accessed)
+*(.text.free_pages_and_swap_cache)
+*(.text.generic_fillattr)
+*(.text.__block_prepare_write)
+*(.text.__set_page_dirty_nobuffers)
+*(.text.link_path_walk)
+*(.text.find_get_pages_tag)
+*(.text.ide_do_request)
+*(.text.__alloc_pages)
+*(.text.generic_permission)
+*(.text.mod_page_state_offset)
+*(.text.free_pgd_range)
+*(.text.generic_file_buffered_write)
+*(.text.number)
+*(.text.ide_do_rw_disk)
+*(.text.__brelse)
+*(.text.__mod_page_state_offset)
+*(.text.rotate_reclaimable_page)
+*(.text.find_vma_prepare)
+*(.text.find_vma_prev)
+*(.text.lru_cache_add_active)
+*(.text.__kmalloc_track_caller)
+*(.text.smp_invalidate_interrupt)
+*(.text.handle_IRQ_event)
+*(.text.__find_get_block_slow)
+*(.text.do_wp_page)
+*(.text.do_select)
+*(.text.set_user_nice)
+*(.text.sys_read)
+*(.text.do_munmap)
+*(.text.csum_partial)
+*(.text.__do_softirq)
+*(.text.may_open)
+*(.text.getname)
+*(.text.get_empty_filp)
+*(.text.__fput)
+*(.text.remove_mapping)
+*(.text.filp_ctor)
+*(.text.poison_obj)
+*(.text.unmap_region)
+*(.text.test_set_page_writeback)
+*(.text.__do_page_cache_readahead)
+*(.text.sock_def_readable)
+*(.text.ide_outl)
+*(.text.shrink_zone)
+*(.text.rb_insert_color)
+*(.text.get_request)
+*(.text.sys_pread64)
+*(.text.spin_bug)
+*(.text.ide_outsl)
+*(.text.mask_and_ack_8259A)
+*(.text.filemap_nopage)
+*(.text.page_add_file_rmap)
+*(.text.find_lock_page)
+*(.text.tcp_poll)
+*(.text.__mark_inode_dirty)
+*(.text.file_ra_state_init)
+*(.text.generic_file_llseek)
+*(.text.__pagevec_lru_add)
+*(.text.page_cache_readahead)
+*(.text.n_tty_receive_buf)
+*(.text.zonelist_policy)
+*(.text.vma_adjust)
+*(.text.test_clear_page_dirty)
+*(.text.sync_buffer)
+*(.text.do_exit)
+*(.text.__bitmap_weight)
+*(.text.alloc_pages_current)
+*(.text.get_unused_fd)
+*(.text.zone_watermark_ok)
+*(.text.cpuset_update_task_memory_state)
+*(.text.__bitmap_empty)
+*(.text.sys_munmap)
+*(.text.__inode_dir_notify)
+*(.text.__generic_file_aio_write_nolock)
+*(.text.__pte_alloc)
+*(.text.sys_select)
+*(.text.vm_acct_memory)
+*(.text.vfs_write)
+*(.text.__lru_add_drain)
+*(.text.prio_tree_insert)
+*(.text.generic_file_aio_read)
+*(.text.vma_merge)
+*(.text.block_write_full_page)
+*(.text.__page_set_anon_rmap)
+*(.text.apic_timer_interrupt)
+*(.text.release_console_sem)
+*(.text.sys_write)
+*(.text.sys_brk)
+*(.text.dup_mm)
+*(.text.read_current_timer)
+*(.text.ll_rw_block)
+*(.text.blk_rq_map_sg)
+*(.text.dbg_userword)
+*(.text.__block_commit_write)
+*(.text.cache_grow)
+*(.text.copy_strings)
+*(.text.release_task)
+*(.text.do_sync_write)
+*(.text.unlock_page)
+*(.text.load_elf_binary)
+*(.text.__follow_mount)
+*(.text.__getblk)
+*(.text.do_sys_open)
+*(.text.current_kernel_time)
+*(.text.call_rcu)
+*(.text.write_chan)
+*(.text.vsnprintf)
+*(.text.dummy_inode_setsecurity)
+*(.text.submit_bh)
+*(.text.poll_freewait)
+*(.text.bio_alloc_bioset)
+*(.text.skb_clone)
+*(.text.page_waitqueue)
+*(.text.__mutex_lock_interruptible_slowpath)
+*(.text.get_index)
+*(.text.csum_partial_copy_generic)
+*(.text.bad_range)
+*(.text.remove_vma)
+*(.text.cp_new_stat)
+*(.text.alloc_arraycache)
+*(.text.test_clear_page_writeback)
+*(.text.strsep)
+*(.text.open_namei)
+*(.text._raw_read_unlock)
+*(.text.get_vma_policy)
+*(.text.__down_write_trylock)
+*(.text.find_get_pages)
+*(.text.tcp_rcv_established)
+*(.text.generic_make_request)
+*(.text.__block_write_full_page)
+*(.text.cfq_set_request)
+*(.text.sys_inotify_init)
+*(.text.split_vma)
+*(.text.__mod_timer)
+*(.text.get_options)
+*(.text.vma_link)
+*(.text.mpage_writepages)
+*(.text.truncate_complete_page)
+*(.text.tcp_recvmsg)
+*(.text.sigprocmask)
+*(.text.filemap_populate)
+*(.text.sys_close)
+*(.text.inotify_dev_queue_event)
+*(.text.do_task_stat)
+*(.text.__dentry_open)
+*(.text.unlink_file_vma)
+*(.text.__pollwait)
+*(.text.packet_rcv_spkt)
+*(.text.drop_buffers)
+*(.text.free_pgtables)
+*(.text.generic_file_direct_write)
+*(.text.copy_process)
+*(.text.netif_receive_skb)
+*(.text.dnotify_flush)
+*(.text.print_bad_pte)
+*(.text.anon_vma_unlink)
+*(.text.sys_mprotect)
+*(.text.sync_sb_inodes)
+*(.text.find_inode_fast)
+*(.text.dummy_inode_readlink)
+*(.text.putname)
+*(.text.init_smp_flush)
+*(.text.dbg_redzone2)
+*(.text.sk_run_filter)
+*(.text.may_expand_vm)
+*(.text.generic_file_aio_write)
+*(.text.find_next_zero_bit)
+*(.text.file_kill)
+*(.text.audit_getname)
+*(.text.arch_unmap_area_topdown)
+*(.text.alloc_page_vma)
+*(.text.tcp_transmit_skb)
+*(.text.rb_next)
+*(.text.dbg_redzone1)
+*(.text.generic_file_mmap)
+*(.text.vfs_fstat)
+*(.text.sys_time)
+*(.text.page_lock_anon_vma)
+*(.text.get_unmapped_area)
+*(.text.remote_llseek)
+*(.text.__up_read)
+*(.text.fd_install)
+*(.text.eventpoll_init_file)
+*(.text.dma_alloc_coherent)
+*(.text.create_empty_buffers)
+*(.text.__mutex_unlock_slowpath)
+*(.text.dup_fd)
+*(.text.d_alloc)
+*(.text.tty_ldisc_try)
+*(.text.sys_stime)
+*(.text.__rb_rotate_right)
+*(.text.d_validate)
+*(.text.rb_erase)
+*(.text.path_release)
+*(.text.memmove)
+*(.text.invalidate_complete_page)
+*(.text.clear_inode)
+*(.text.cache_estimate)
+*(.text.alloc_buffer_head)
+*(.text.smp_call_function_interrupt)
+*(.text.flush_tlb_others)
+*(.text.file_move)
+*(.text.balance_dirty_pages_ratelimited)
+*(.text.vma_prio_tree_add)
+*(.text.timespec_trunc)
+*(.text.mempool_alloc)
+*(.text.iget_locked)
+*(.text.d_alloc_root)
+*(.text.cpuset_populate_dir)
+*(.text.anon_vma_prepare)
+*(.text.sys_newstat)
+*(.text.alloc_page_interleave)
+*(.text.__path_lookup_intent_open)
+*(.text.__pagevec_free)
+*(.text.inode_init_once)
+*(.text.free_vfsmnt)
+*(.text.__user_walk_fd)
+*(.text.cfq_idle_slice_timer)
+*(.text.sys_mmap)
+*(.text.sys_llseek)
+*(.text.prio_tree_remove)
+*(.text.filp_close)
+*(.text.file_permission)
+*(.text.vma_prio_tree_remove)
+*(.text.tcp_ack)
+*(.text.nameidata_to_filp)
+*(.text.sys_lseek)
+*(.text.percpu_counter_mod)
+*(.text.igrab)
+*(.text.__bread)
+*(.text.alloc_inode)
+*(.text.filldir)
+*(.text.__rb_rotate_left)
+*(.text.irq_affinity_write_proc)
+*(.text.init_request_from_bio)
+*(.text.find_or_create_page)
+*(.text.tty_poll)
+*(.text.tcp_sendmsg)
+*(.text.ide_wait_stat)
+*(.text.free_buffer_head)
+*(.text.flush_signal_handlers)
+*(.text.tcp_v4_rcv)
+*(.text.nr_blockdev_pages)
+*(.text.locks_remove_flock)
+*(.text.__iowrite32_copy)
+*(.text.do_filp_open)
+*(.text.try_to_release_page)
+*(.text.page_add_new_anon_rmap)
+*(.text.kmem_cache_size)
+*(.text.eth_type_trans)
+*(.text.try_to_free_buffers)
+*(.text.schedule_tail)
+*(.text.proc_lookup)
+*(.text.no_llseek)
+*(.text.kfree_skbmem)
+*(.text.do_wait)
+*(.text.do_mpage_readpage)
+*(.text.vfs_stat_fd)
+*(.text.tty_write)
+*(.text.705)
+*(.text.sync_page)
+*(.text.__remove_shared_vm_struct)
+*(.text.__kfree_skb)
+*(.text.sock_poll)
+*(.text.get_request_wait)
+*(.text.do_sigaction)
+*(.text.do_brk)
+*(.text.tcp_event_data_recv)
+*(.text.read_chan)
+*(.text.pipe_writev)
+*(.text.__emul_lookup_dentry)
+*(.text.rtc_get_rtc_time)
+*(.text.print_objinfo)
+*(.text.file_update_time)
+*(.text.do_signal)
+*(.text.disable_8259A_irq)
+*(.text.blk_queue_bounce)
+*(.text.__anon_vma_link)
+*(.text.__vma_link)
+*(.text.vfs_rename)
+*(.text.sys_newlstat)
+*(.text.sys_newfstat)
+*(.text.sys_mknod)
+*(.text.__show_regs)
+*(.text.iput)
+*(.text.get_signal_to_deliver)
+*(.text.flush_tlb_page)
+*(.text.debug_mutex_wake_waiter)
+*(.text.copy_thread)
+*(.text.clear_page_dirty_for_io)
+*(.text.buffer_io_error)
+*(.text.vfs_permission)
+*(.text.truncate_inode_pages_range)
+*(.text.sys_recvfrom)
+*(.text.remove_suid)
+*(.text.mark_buffer_dirty)
+*(.text.local_bh_enable)
+*(.text.get_zeroed_page)
+*(.text.get_vmalloc_info)
+*(.text.flush_old_exec)
+*(.text.dummy_inode_permission)
+*(.text.__bio_add_page)
+*(.text.prio_tree_replace)
+*(.text.notify_change)
+*(.text.mntput_no_expire)
+*(.text.fput)
+*(.text.__end_that_request_first)
+*(.text.wake_up_bit)
+*(.text.unuse_mm)
+*(.text.skb_release_data)
+*(.text.shrink_icache_memory)
+*(.text.sched_balance_self)
+*(.text.__pmd_alloc)
+*(.text.pipe_poll)
+*(.text.normal_poll)
+*(.text.__free_pages)
+*(.text.follow_mount)
+*(.text.cdrom_start_packet_command)
+*(.text.blk_recount_segments)
+*(.text.bio_put)
+*(.text.__alloc_skb)
+*(.text.__wake_up)
+*(.text.vm_stat_account)
+*(.text.sys_fcntl)
+*(.text.sys_fadvise64)
+*(.text._raw_write_unlock)
+*(.text.__pud_alloc)
+*(.text.alloc_page_buffers)
+*(.text.vfs_llseek)
+*(.text.sockfd_lookup)
+*(.text._raw_write_lock)
+*(.text.put_compound_page)
+*(.text.prune_dcache)
+*(.text.pipe_readv)
+*(.text.mempool_free)
+*(.text.make_ahead_window)
+*(.text.lru_add_drain)
+*(.text.constant_test_bit)
+*(.text.__clear_user)
+*(.text.arch_unmap_area)
+*(.text.anon_vma_link)
+*(.text.sys_chroot)
+*(.text.setup_arg_pages)
+*(.text.radix_tree_preload)
+*(.text.init_rwsem)
+*(.text.generic_osync_inode)
+*(.text.generic_delete_inode)
+*(.text.do_sys_poll)
+*(.text.dev_queue_xmit)
+*(.text.default_llseek)
+*(.text.__writeback_single_inode)
+*(.text.vfs_ioctl)
+*(.text.__up_write)
+*(.text.unix_poll)
+*(.text.sys_rt_sigprocmask)
+*(.text.sock_recvmsg)
+*(.text.recalc_bh_state)
+*(.text.__put_unused_fd)
+*(.text.process_backlog)
+*(.text.locks_remove_posix)
+*(.text.lease_modify)
+*(.text.expand_files)
+*(.text.end_buffer_read_nobh)
+*(.text.d_splice_alias)
+*(.text.debug_mutex_init_waiter)
+*(.text.copy_from_user)
+*(.text.cap_vm_enough_memory)
+*(.text.show_vfsmnt)
+*(.text.release_sock)
+*(.text.pfifo_fast_enqueue)
+*(.text.half_md4_transform)
+*(.text.fs_may_remount_ro)
+*(.text.do_fork)
+*(.text.copy_hugetlb_page_range)
+*(.text.cache_free_debugcheck)
+*(.text.__tcp_select_window)
+*(.text.task_handoff_register)
+*(.text.sys_open)
+*(.text.strlcpy)
+*(.text.skb_copy_datagram_iovec)
+*(.text.set_up_list3s)
+*(.text.release_open_intent)
+*(.text.qdisc_restart)
+*(.text.n_tty_chars_in_buffer)
+*(.text.inode_change_ok)
+*(.text.__downgrade_write)
+*(.text.debug_mutex_unlock)
+*(.text.add_timer_randomness)
+*(.text.sock_common_recvmsg)
+*(.text.set_bh_page)
+*(.text.printk_lock)
+*(.text.path_release_on_umount)
+*(.text.ip_output)
+*(.text.ide_build_dmatable)
+*(.text.__get_user_8)
+*(.text.end_buffer_read_sync)
+*(.text.__d_path)
+*(.text.d_move)
+*(.text.del_timer)
+*(.text.constant_test_bit)
+*(.text.blockable_page_cache_readahead)
+*(.text.tty_read)
+*(.text.sys_readlink)
+*(.text.sys_faccessat)
+*(.text.read_swap_cache_async)
+*(.text.pty_write_room)
+*(.text.page_address_in_vma)
+*(.text.kthread)
+*(.text.cfq_exit_io_context)
+*(.text.__tcp_push_pending_frames)
+*(.text.sys_pipe)
+*(.text.submit_bio)
+*(.text.pid_revalidate)
+*(.text.page_referenced_file)
+*(.text.lock_sock)
+*(.text.get_page_state_node)
+*(.text.generic_block_bmap)
+*(.text.do_setitimer)
+*(.text.dev_queue_xmit_nit)
+*(.text.copy_from_read_buf)
+*(.text.__const_udelay)
+*(.text.console_conditional_schedule)
+*(.text.wake_up_new_task)
+*(.text.wait_for_completion_interruptible)
+*(.text.tcp_rcv_rtt_update)
+*(.text.sys_mlockall)
+*(.text.set_fs_altroot)
+*(.text.schedule_timeout)
+*(.text.nr_free_pagecache_pages)
+*(.text.nf_iterate)
+*(.text.mapping_tagged)
+*(.text.ip_queue_xmit)
+*(.text.ip_local_deliver)
+*(.text.follow_page)
+*(.text.elf_map)
+*(.text.dummy_file_permission)
+*(.text.dispose_list)
+*(.text.dentry_open)
+*(.text.dentry_iput)
+*(.text.bio_alloc)
+*(.text.alloc_skb_from_cache)
+*(.text.wait_on_page_bit)
+*(.text.vfs_readdir)
+*(.text.vfs_lstat)
+*(.text.seq_escape)
+*(.text.__posix_lock_file)
+*(.text.mm_release)
+*(.text.kref_put)
+*(.text.ip_rcv)
+*(.text.__iget)
+*(.text.free_pages)
+*(.text.find_mergeable_anon_vma)
+*(.text.find_extend_vma)
+*(.text.dummy_inode_listsecurity)
+*(.text.bio_add_page)
+*(.text.__vm_enough_memory)
+*(.text.vfs_stat)
+*(.text.tty_paranoia_check)
+*(.text.tcp_read_sock)
+*(.text.tcp_data_queue)
+*(.text.sys_uname)
+*(.text.sys_renameat)
+*(.text.__strncpy_from_user)
+*(.text.__mutex_init)
+*(.text.__lookup_hash)
+*(.text.kref_get)
+*(.text.ip_route_input)
+*(.text.__insert_inode_hash)
+*(.text.do_sock_write)
+*(.text.blk_done_softirq)
+*(.text.__wake_up_sync)
+*(.text.__vma_link_rb)
+*(.text.tty_ioctl)
+*(.text.tracesys)
+*(.text.sys_getdents)
+*(.text.sys_dup)
+*(.text.stub_execve)
+*(.text.sha_transform)
+*(.text.radix_tree_tag_clear)
+*(.text.put_unused_fd)
+*(.text.put_files_struct)
+*(.text.mpage_readpages)
+*(.text.may_delete)
+*(.text.kmem_cache_create)
+*(.text.ip_mc_output)
+*(.text.interleave_nodes)
+*(.text.groups_search)
+*(.text.generic_drop_inode)
+*(.text.generic_commit_write)
+*(.text.fcntl_setlk)
+*(.text.exit_mmap)
+*(.text.end_page_writeback)
+*(.text.__d_rehash)
+*(.text.debug_mutex_free_waiter)
+*(.text.csum_ipv6_magic)
+*(.text.count)
+*(.text.cleanup_rbuf)
+*(.text.check_spinlock_acquired_node)
+*(.text.can_vma_merge_after)
+*(.text.bio_endio)
+*(.text.alloc_pidmap)
+*(.text.write_ldt)
+*(.text.vmtruncate_range)
+*(.text.vfs_create)
+*(.text.__user_walk)
+*(.text.update_send_head)
+*(.text.unmap_underlying_metadata)
+*(.text.tty_ldisc_deref)
+*(.text.tcp_setsockopt)
+*(.text.tcp_send_ack)
+*(.text.sys_pause)
+*(.text.sys_gettimeofday)
+*(.text.sync_dirty_buffer)
+*(.text.strncmp)
+*(.text.release_posix_timer)
+*(.text.proc_file_read)
+*(.text.prepare_to_wait)
+*(.text.locks_mandatory_locked)
+*(.text.interruptible_sleep_on_timeout)
+*(.text.inode_sub_bytes)
+*(.text.in_group_p)
+*(.text.hrtimer_try_to_cancel)
+*(.text.filldir64)
+*(.text.fasync_helper)
+*(.text.dummy_sb_pivotroot)
+*(.text.d_lookup)
+*(.text.d_instantiate)
+*(.text.__d_find_alias)
+*(.text.cpu_idle_wait)
+*(.text.cond_resched_lock)
+*(.text.chown_common)
+*(.text.blk_congestion_wait)
+*(.text.activate_page)
+*(.text.unlock_buffer)
+*(.text.tty_wakeup)
+*(.text.tcp_v4_do_rcv)
+*(.text.tcp_current_mss)
+*(.text.sys_openat)
+*(.text.sys_fchdir)
+*(.text.strnlen_user)
+*(.text.strnlen)
+*(.text.strchr)
+*(.text.sock_common_getsockopt)
+*(.text.skb_checksum)
+*(.text.remove_wait_queue)
+*(.text.rb_replace_node)
+*(.text.radix_tree_node_ctor)
+*(.text.pty_chars_in_buffer)
+*(.text.profile_hit)
+*(.text.prio_tree_left)
+*(.text.pgd_clear_bad)
+*(.text.pfifo_fast_dequeue)
+*(.text.page_referenced)
+*(.text.open_exec)
+*(.text.mmput)
+*(.text.mm_init)
+*(.text.__ide_dma_off_quietly)
+*(.text.ide_dma_intr)
+*(.text.hrtimer_start)
+*(.text.get_io_context)
+*(.text.__get_free_pages)
+*(.text.find_first_zero_bit)
+*(.text.file_free_rcu)
+*(.text.dummy_socket_sendmsg)
+*(.text.do_unlinkat)
+*(.text.do_arch_prctl)
+*(.text.destroy_inode)
+*(.text.can_vma_merge_before)
+*(.text.block_sync_page)
+*(.text.block_prepare_write)
+*(.text.bio_init)
+*(.text.arch_ptrace)
+*(.text.wake_up_inode)
+*(.text.wait_on_retry_sync_kiocb)
+*(.text.vma_prio_tree_next)
+*(.text.tcp_rcv_space_adjust)
+*(.text.__tcp_ack_snd_check)
+*(.text.sys_utime)
+*(.text.sys_recvmsg)
+*(.text.sys_mremap)
+*(.text.sys_bdflush)
+*(.text.sleep_on)
+*(.text.set_page_dirty_lock)
+*(.text.seq_path)
+*(.text.schedule_timeout_interruptible)
+*(.text.sched_fork)
+*(.text.rt_run_flush)
+*(.text.profile_munmap)
+*(.text.prepare_binprm)
+*(.text.__pagevec_release_nonlru)
+*(.text.m_show)
+*(.text.lookup_mnt)
+*(.text.__lookup_mnt)
+*(.text.lock_timer_base)
+*(.text.is_subdir)
+*(.text.invalidate_bh_lru)
+*(.text.init_buffer_head)
+*(.text.ifind_fast)
+*(.text.ide_dma_start)
+*(.text.__get_page_state)
+*(.text.flock_to_posix_lock)
+*(.text.__find_symbol)
+*(.text.do_futex)
+*(.text.do_execve)
+*(.text.dirty_writeback_centisecs_handler)
+*(.text.dev_watchdog)
+*(.text.can_share_swap_page)
+*(.text.blkdev_put)
+*(.text.bio_get_nr_vecs)
+*(.text.xfrm_compile_policy)
+*(.text.vma_prio_tree_insert)
+*(.text.vfs_lstat_fd)
+*(.text.__user_path_lookup_open)
+*(.text.thread_return)
+*(.text.tcp_send_delayed_ack)
+*(.text.sock_def_error_report)
+*(.text.shrink_slab)
+*(.text.serial_out)
+*(.text.seq_read)
+*(.text.secure_ip_id)
+*(.text.search_binary_handler)
+*(.text.proc_pid_unhash)
+*(.text.pagevec_lookup)
+*(.text.new_inode)
+*(.text.memcpy_toiovec)
+*(.text.locks_free_lock)
+*(.text.__lock_page)
+*(.text.__lock_buffer)
+*(.text.load_module)
+*(.text.is_bad_inode)
+*(.text.invalidate_inode_buffers)
+*(.text.insert_vm_struct)
+*(.text.inode_setattr)
+*(.text.inode_add_bytes)
+*(.text.ide_read_24)
+*(.text.ide_get_error_location)
+*(.text.ide_do_drive_cmd)
+*(.text.get_locked_pte)
+*(.text.get_filesystem_list)
+*(.text.generic_file_open)
+*(.text.follow_down)
+*(.text.find_next_bit)
+*(.text.__find_first_bit)
+*(.text.exit_mm)
+*(.text.exec_keys)
+*(.text.end_buffer_write_sync)
+*(.text.end_bio_bh_io_sync)
+*(.text.dummy_socket_shutdown)
+*(.text.d_rehash)
+*(.text.d_path)
+*(.text.do_ioctl)
+*(.text.dget_locked)
+*(.text.copy_thread_group_keys)
+*(.text.cdrom_end_request)
+*(.text.cap_bprm_apply_creds)
+*(.text.blk_rq_bio_prep)
+*(.text.__bitmap_intersects)
+*(.text.bio_phys_segments)
+*(.text.bio_free)
+*(.text.arch_get_unmapped_area_topdown)
+*(.text.writeback_in_progress)
+*(.text.vfs_follow_link)
+*(.text.tcp_rcv_state_process)
+*(.text.tcp_check_space)
+*(.text.sys_stat)
+*(.text.sys_rt_sigreturn)
+*(.text.sys_rt_sigaction)
+*(.text.sys_remap_file_pages)
+*(.text.sys_pwrite64)
+*(.text.sys_fchownat)
+*(.text.sys_fchmodat)
+*(.text.strncat)
+*(.text.strlcat)
+*(.text.strcmp)
+*(.text.steal_locks)
+*(.text.sock_create)
+*(.text.sk_stream_rfree)
+*(.text.sk_stream_mem_schedule)
+*(.text.skip_atoi)
+*(.text.sk_alloc)
+*(.text.show_stat)
+*(.text.set_fs_pwd)
+*(.text.set_binfmt)
+*(.text.pty_unthrottle)
+*(.text.proc_symlink)
+*(.text.pipe_release)
+*(.text.pageout)
+*(.text.n_tty_write_wakeup)
+*(.text.n_tty_ioctl)
+*(.text.nr_free_zone_pages)
+*(.text.migration_thread)
+*(.text.mempool_free_slab)
+*(.text.meminfo_read_proc)
+*(.text.max_sane_readahead)
+*(.text.lru_cache_add)
+*(.text.kill_fasync)
+*(.text.kernel_read)
+*(.text.invalidate_mapping_pages)
+*(.text.inode_has_buffers)
+*(.text.init_once)
+*(.text.inet_sendmsg)
+*(.text.idedisk_issue_flush)
+*(.text.generic_file_write)
+*(.text.free_more_memory)
+*(.text.__free_fdtable)
+*(.text.filp_dtor)
+*(.text.exit_sem)
+*(.text.exit_itimers)
+*(.text.error_interrupt)
+*(.text.end_buffer_async_write)
+*(.text.eligible_child)
+*(.text.elf_map)
+*(.text.dump_task_regs)
+*(.text.dummy_task_setscheduler)
+*(.text.dummy_socket_accept)
+*(.text.dummy_file_free_security)
+*(.text.__down_read)
+*(.text.do_sock_read)
+*(.text.do_sigaltstack)
+*(.text.do_mremap)
+*(.text.current_io_context)
+*(.text.cpu_swap_callback)
+*(.text.copy_vma)
+*(.text.cap_bprm_set_security)
+*(.text.blk_insert_request)
+*(.text.bio_map_kern_endio)
+*(.text.bio_hw_segments)
+*(.text.bictcp_cong_avoid)
+*(.text.add_interrupt_randomness)
+*(.text.wait_for_completion)
+*(.text.version_read_proc)
+*(.text.unix_write_space)
+*(.text.tty_ldisc_ref_wait)
+*(.text.tty_ldisc_put)
+*(.text.try_to_wake_up)
+*(.text.tcp_v4_tw_remember_stamp)
+*(.text.tcp_try_undo_dsack)
+*(.text.tcp_may_send_now)
+*(.text.sys_waitid)
+*(.text.sys_sched_getparam)
+*(.text.sys_getppid)
+*(.text.sys_getcwd)
+*(.text.sys_dup2)
+*(.text.sys_chmod)
+*(.text.sys_chdir)
+*(.text.sprintf)
+*(.text.sock_wfree)
+*(.text.sock_aio_write)
+*(.text.skb_drop_fraglist)
+*(.text.skb_dequeue)
+*(.text.set_close_on_exec)
+*(.text.set_brk)
+*(.text.seq_puts)
+*(.text.SELECT_DRIVE)
+*(.text.sched_exec)
+*(.text.return_EIO)
+*(.text.remove_from_page_cache)
+*(.text.rcu_start_batch)
+*(.text.__put_task_struct)
+*(.text.proc_pid_readdir)
+*(.text.proc_get_inode)
+*(.text.prepare_to_wait_exclusive)
+*(.text.pipe_wait)
+*(.text.pipe_new)
+*(.text.pdflush_operation)
+*(.text.__pagevec_release)
+*(.text.pagevec_lookup_tag)
+*(.text.packet_rcv)
+*(.text.n_tty_set_room)
+*(.text.nr_free_pages)
+*(.text.__net_timestamp)
+*(.text.mpage_end_io_read)
+*(.text.mod_timer)
+*(.text.__memcpy)
+*(.text.mb_cache_shrink_fn)
+*(.text.lock_rename)
+*(.text.kstrdup)
+*(.text.is_ignored)
+*(.text.int_very_careful)
+*(.text.inotify_inode_is_dead)
+*(.text.inotify_get_cookie)
+*(.text.inode_get_bytes)
+*(.text.init_timer)
+*(.text.init_dev)
+*(.text.inet_getname)
+*(.text.ide_map_sg)
+*(.text.__ide_dma_end)
+*(.text.hrtimer_get_remaining)
+*(.text.get_task_mm)
+*(.text.get_random_int)
+*(.text.free_pipe_info)
+*(.text.filemap_write_and_wait_range)
+*(.text.exit_thread)
+*(.text.enter_idle)
+*(.text.end_that_request_first)
+*(.text.end_8259A_irq)
+*(.text.dummy_file_alloc_security)
+*(.text.do_group_exit)
+*(.text.debug_mutex_init)
+*(.text.cpuset_exit)
+*(.text.cpu_idle)
+*(.text.copy_semundo)
+*(.text.copy_files)
+*(.text.chrdev_open)
+*(.text.cdrom_transfer_packet_command)
+*(.text.cdrom_mode_sense)
+*(.text.blk_phys_contig_segment)
+*(.text.blk_get_queue)
+*(.text.bio_split)
+*(.text.audit_alloc)
+*(.text.anon_pipe_buf_release)
+*(.text.add_wait_queue_exclusive)
+*(.text.add_wait_queue)
+*(.text.acct_process)
+*(.text.account)
+*(.text.zeromap_page_range)
+*(.text.yield)
+*(.text.writeback_acquire)
+*(.text.worker_thread)
+*(.text.wait_on_page_writeback_range)
+*(.text.__wait_on_buffer)
+*(.text.vscnprintf)
+*(.text.vmalloc_to_pfn)
+*(.text.vgacon_save_screen)
+*(.text.vfs_unlink)
+*(.text.vfs_rmdir)
+*(.text.unregister_md_personality)
+*(.text.unlock_new_inode)
+*(.text.unix_stream_sendmsg)
+*(.text.unix_stream_recvmsg)
+*(.text.unhash_process)
+*(.text.udp_v4_lookup_longway)
+*(.text.tty_ldisc_flush)
+*(.text.tty_ldisc_enable)
+*(.text.tty_hung_up_p)
+*(.text.tty_buffer_free_all)
+*(.text.tso_fragment)
+*(.text.try_to_del_timer_sync)
+*(.text.tcp_v4_err)
+*(.text.tcp_unhash)
+*(.text.tcp_seq_next)
+*(.text.tcp_select_initial_window)
+*(.text.tcp_sacktag_write_queue)
+*(.text.tcp_cwnd_validate)
+*(.text.sys_vhangup)
+*(.text.sys_uselib)
+*(.text.sys_symlink)
+*(.text.sys_signal)
+*(.text.sys_poll)
+*(.text.sys_mount)
+*(.text.sys_kill)
+*(.text.sys_ioctl)
+*(.text.sys_inotify_add_watch)
+*(.text.sys_getuid)
+*(.text.sys_getrlimit)
+*(.text.sys_getitimer)
+*(.text.sys_getgroups)
+*(.text.sys_ftruncate)
+*(.text.sysfs_lookup)
+*(.text.sys_exit_group)
+*(.text.stub_fork)
+*(.text.sscanf)
+*(.text.sock_map_fd)
+*(.text.sock_get_timestamp)
+*(.text.__sock_create)
+*(.text.smp_call_function_single)
+*(.text.sk_stop_timer)
+*(.text.skb_copy_and_csum_datagram)
+*(.text.__skb_checksum_complete)
+*(.text.single_next)
+*(.text.sigqueue_alloc)
+*(.text.shrink_dcache_parent)
+*(.text.select_idle_routine)
+*(.text.run_workqueue)
+*(.text.run_local_timers)
+*(.text.remove_inode_hash)
+*(.text.remove_dquot_ref)
+*(.text.register_binfmt)
+*(.text.read_cache_pages)
+*(.text.rb_last)
+*(.text.pty_open)
+*(.text.proc_root_readdir)
+*(.text.proc_pid_flush)
+*(.text.proc_pident_lookup)
+*(.text.proc_fill_super)
+*(.text.proc_exe_link)
+*(.text.posix_locks_deadlock)
+*(.text.pipe_iov_copy_from_user)
+*(.text.opost)
+*(.text.nf_register_hook)
+*(.text.netif_rx_ni)
+*(.text.m_start)
+*(.text.mpage_writepage)
+*(.text.mm_alloc)
+*(.text.memory_open)
+*(.text.mark_buffer_async_write)
+*(.text.lru_add_drain_all)
+*(.text.locks_init_lock)
+*(.text.locks_delete_lock)
+*(.text.lock_hrtimer_base)
+*(.text.load_script)
+*(.text.__kill_fasync)
+*(.text.ip_mc_sf_allow)
+*(.text.__ioremap)
+*(.text.int_with_check)
+*(.text.int_sqrt)
+*(.text.install_thread_keyring)
+*(.text.init_page_buffers)
+*(.text.inet_sock_destruct)
+*(.text.idle_notifier_register)
+*(.text.ide_execute_command)
+*(.text.ide_end_drive_cmd)
+*(.text.__ide_dma_host_on)
+*(.text.hrtimer_run_queues)
+*(.text.hpet_mask_rtc_irq_bit)
+*(.text.__get_zone_counts)
+*(.text.get_zone_counts)
+*(.text.get_write_access)
+*(.text.get_fs_struct)
+*(.text.get_dirty_limits)
+*(.text.generic_readlink)
+*(.text.free_hot_page)
+*(.text.finish_wait)
+*(.text.find_inode)
+*(.text.find_first_bit)
+*(.text.__filemap_fdatawrite_range)
+*(.text.__filemap_copy_from_user_iovec)
+*(.text.exit_aio)
+*(.text.elv_set_request)
+*(.text.elv_former_request)
+*(.text.dup_namespace)
+*(.text.dupfd)
+*(.text.dummy_socket_getsockopt)
+*(.text.dummy_sb_post_mountroot)
+*(.text.dummy_quotactl)
+*(.text.dummy_inode_rename)
+*(.text.__do_SAK)
+*(.text.do_pipe)
+*(.text.do_fsync)
+*(.text.d_instantiate_unique)
+*(.text.d_find_alias)
+*(.text.deny_write_access)
+*(.text.dentry_unhash)
+*(.text.d_delete)
+*(.text.datagram_poll)
+*(.text.cpuset_fork)
+*(.text.cpuid_read)
+*(.text.copy_namespace)
+*(.text.cond_resched)
+*(.text.check_version)
+*(.text.__change_page_attr)
+*(.text.cfq_slab_kill)
+*(.text.cfq_completed_request)
+*(.text.cdrom_pc_intr)
+*(.text.cdrom_decode_status)
+*(.text.cap_capset_check)
+*(.text.blk_put_request)
+*(.text.bio_fs_destructor)
+*(.text.bictcp_min_cwnd)
+*(.text.alloc_chrdev_region)
+*(.text.add_element)
+*(.text.acct_update_integrals)
+*(.text.write_boundary_block)
+*(.text.writeback_release)
+*(.text.writeback_inodes)
+*(.text.wake_up_state)
+*(.text.__wake_up_locked)
+*(.text.wake_futex)
+*(.text.wait_task_inactive)
+*(.text.__wait_on_freeing_inode)
+*(.text.wait_noreap_copyout)
+*(.text.vmstat_start)
+*(.text.vgacon_do_font_op)
+*(.text.vfs_readv)
+*(.text.vfs_quota_sync)
+*(.text.update_queue)
+*(.text.unshare_files)
+*(.text.unmap_vm_area)
+*(.text.unix_socketpair)
+*(.text.unix_release_sock)
+*(.text.unix_detach_fds)
+*(.text.unix_create1)
+*(.text.unix_bind)
+*(.text.udp_sendmsg)
+*(.text.udp_rcv)
+*(.text.udp_queue_rcv_skb)
+*(.text.uart_write)
+*(.text.uart_startup)
+*(.text.uart_open)
+*(.text.tty_vhangup)
+*(.text.tty_termios_baud_rate)
+*(.text.tty_release)
+*(.text.tty_ldisc_ref)
+*(.text.throttle_vm_writeout)
+*(.text.058)
+*(.text.tcp_xmit_probe_skb)
+*(.text.tcp_v4_send_check)
+*(.text.tcp_v4_destroy_sock)
+*(.text.tcp_sync_mss)
+*(.text.tcp_snd_test)
+*(.text.tcp_slow_start)
+*(.text.tcp_send_fin)
+*(.text.tcp_rtt_estimator)
+*(.text.tcp_parse_options)
+*(.text.tcp_ioctl)
+*(.text.tcp_init_tso_segs)
+*(.text.tcp_init_cwnd)
+*(.text.tcp_getsockopt)
+*(.text.tcp_fin)
+*(.text.tcp_connect)
+*(.text.tcp_cong_avoid)
+*(.text.__tcp_checksum_complete_user)
+*(.text.task_dumpable)
+*(.text.sys_wait4)
+*(.text.sys_utimes)
+*(.text.sys_symlinkat)
+*(.text.sys_socketpair)
+*(.text.sys_rmdir)
+*(.text.sys_readahead)
+*(.text.sys_nanosleep)
+*(.text.sys_linkat)
+*(.text.sys_fstat)
+*(.text.sysfs_readdir)
+*(.text.sys_execve)
+*(.text.sysenter_tracesys)
+*(.text.sys_chown)
+*(.text.stub_clone)
+*(.text.strrchr)
+*(.text.strncpy)
+*(.text.stopmachine_set_state)
+*(.text.sock_sendmsg)
+*(.text.sock_release)
+*(.text.sock_fasync)
+*(.text.sock_close)
+*(.text.sk_stream_write_space)
+*(.text.sk_reset_timer)
+*(.text.skb_split)
+*(.text.skb_recv_datagram)
+*(.text.skb_queue_tail)
+*(.text.sk_attach_filter)
+*(.text.si_swapinfo)
+*(.text.simple_strtoll)
+*(.text.set_termios)
+*(.text.set_task_comm)
+*(.text.set_shrinker)
+*(.text.set_normalized_timespec)
+*(.text.set_brk)
+*(.text.serial_in)
+*(.text.seq_printf)
+*(.text.secure_dccp_sequence_number)
+*(.text.rwlock_bug)
+*(.text.rt_hash_code)
+*(.text.__rta_fill)
+*(.text.__request_resource)
+*(.text.relocate_new_kernel)
+*(.text.release_thread)
+*(.text.release_mem)
+*(.text.rb_prev)
+*(.text.rb_first)
+*(.text.random_poll)
+*(.text.__put_super_and_need_restart)
+*(.text.pty_write)
+*(.text.ptrace_stop)
+*(.text.proc_self_readlink)
+*(.text.proc_root_lookup)
+*(.text.proc_root_link)
+*(.text.proc_pid_make_inode)
+*(.text.proc_pid_attr_write)
+*(.text.proc_lookupfd)
+*(.text.proc_delete_inode)
+*(.text.posix_same_owner)
+*(.text.posix_block_lock)
+*(.text.poll_initwait)
+*(.text.pipe_write)
+*(.text.pipe_read_fasync)
+*(.text.pipe_ioctl)
+*(.text.pdflush)
+*(.text.pci_user_read_config_dword)
+*(.text.page_readlink)
+*(.text.null_lseek)
+*(.text.nf_hook_slow)
+*(.text.netlink_sock_destruct)
+*(.text.netlink_broadcast)
+*(.text.neigh_resolve_output)
+*(.text.name_to_int)
+*(.text.mwait_idle)
+*(.text.mutex_trylock)
+*(.text.mutex_debug_check_no_locks_held)
+*(.text.m_stop)
+*(.text.mpage_end_io_write)
+*(.text.mpage_alloc)
+*(.text.move_page_tables)
+*(.text.mounts_open)
+*(.text.__memset)
+*(.text.memcpy_fromiovec)
+*(.text.make_8259A_irq)
+*(.text.lookup_user_key_possessed)
+*(.text.lookup_create)
+*(.text.locks_insert_lock)
+*(.text.locks_alloc_lock)
+*(.text.kthread_should_stop)
+*(.text.kswapd)
+*(.text.kobject_uevent)
+*(.text.kobject_get_path)
+*(.text.kobject_get)
+*(.text.klist_children_put)
+*(.text.__ip_route_output_key)
+*(.text.ip_flush_pending_frames)
+*(.text.ip_compute_csum)
+*(.text.ip_append_data)
+*(.text.ioc_set_batching)
+*(.text.invalidate_inode_pages)
+*(.text.__invalidate_device)
+*(.text.install_arg_page)
+*(.text.in_sched_functions)
+*(.text.inotify_unmount_inodes)
+*(.text.init_once)
+*(.text.init_cdrom_command)
+*(.text.inet_stream_connect)
+*(.text.inet_sk_rebuild_header)
+*(.text.inet_csk_addr2sockaddr)
+*(.text.inet_create)
+*(.text.ifind)
+*(.text.ide_setup_dma)
+*(.text.ide_outsw)
+*(.text.ide_fixstring)
+*(.text.ide_dma_setup)
+*(.text.ide_cdrom_packet)
+*(.text.ide_cd_put)
+*(.text.ide_build_sglist)
+*(.text.i8259A_shutdown)
+*(.text.hung_up_tty_ioctl)
+*(.text.hrtimer_nanosleep)
+*(.text.hrtimer_init)
+*(.text.hrtimer_cancel)
+*(.text.hash_futex)
+*(.text.group_send_sig_info)
+*(.text.grab_cache_page_nowait)
+*(.text.get_wchan)
+*(.text.get_stack)
+*(.text.get_page_state)
+*(.text.getnstimeofday)
+*(.text.get_node)
+*(.text.get_kprobe)
+*(.text.generic_unplug_device)
+*(.text.free_task)
+*(.text.frag_show)
+*(.text.find_next_zero_string)
+*(.text.filp_open)
+*(.text.fillonedir)
+*(.text.exit_io_context)
+*(.text.exit_idle)
+*(.text.exact_lock)
+*(.text.eth_header)
+*(.text.dummy_unregister_security)
+*(.text.dummy_socket_post_create)
+*(.text.dummy_socket_listen)
+*(.text.dummy_quota_on)
+*(.text.dummy_inode_follow_link)
+*(.text.dummy_file_receive)
+*(.text.dummy_file_mprotect)
+*(.text.dummy_file_lock)
+*(.text.dummy_file_ioctl)
+*(.text.dummy_bprm_post_apply_creds)
+*(.text.do_writepages)
+*(.text.__down_interruptible)
+*(.text.do_notify_resume)
+*(.text.do_acct_process)
+*(.text.del_timer_sync)
+*(.text.default_rebuild_header)
+*(.text.d_callback)
+*(.text.dcache_readdir)
+*(.text.ctrl_dumpfamily)
+*(.text.cpuset_rmdir)
+*(.text.copy_strings_kernel)
+*(.text.con_write_room)
+*(.text.complete_all)
+*(.text.collect_sigign_sigcatch)
+*(.text.clear_user)
+*(.text.check_unthrottle)
+*(.text.cdrom_release)
+*(.text.cdrom_newpc_intr)
+*(.text.cdrom_ioctl)
+*(.text.cdrom_check_status)
+*(.text.cdev_put)
+*(.text.cdev_add)
+*(.text.cap_ptrace)
+*(.text.cap_bprm_secureexec)
+*(.text.cache_alloc_refill)
+*(.text.bmap)
+*(.text.blk_run_queue)
+*(.text.blk_queue_dma_alignment)
+*(.text.blk_ordered_req_seq)
+*(.text.blk_backing_dev_unplug)
+*(.text.__bitmap_subset)
+*(.text.__bitmap_and)
+*(.text.bio_unmap_user)
+*(.text.__bforget)
+*(.text.bd_forget)
+*(.text.bad_pipe_w)
+*(.text.bad_get_user)
+*(.text.audit_free)
+*(.text.anon_vma_ctor)
+*(.text.anon_pipe_buf_map)
+*(.text.alloc_sock_iocb)
+*(.text.alloc_fdset)
+*(.text.aio_kick_handler)
+*(.text.__add_entropy_words)
+*(.text.add_disk_randomness)
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 02fc7fa0ea2..6df05e6034f 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -26,6 +26,7 @@
*/
.text
+ .section .bootstrap.text
.code32
.globl startup_32
/* %bx: 1 if coming from smp trampoline on secondary cpu */
@@ -192,7 +193,8 @@ startup_64:
movq initial_code(%rip),%rax
jmp *%rax
- /* SMP bootup changes these two */
+ /* SMP bootup changes these two */
+ .align 8
.globl initial_code
initial_code:
.quad x86_64_start_kernel
@@ -237,7 +239,7 @@ ENTRY(no_long_mode)
.org 0xf00
.globl pGDT32
pGDT32:
- .word gdt_end-cpu_gdt_table
+ .word gdt_end-cpu_gdt_table-1
.long cpu_gdt_table-__START_KERNEL_map
.org 0xf10
@@ -293,8 +295,6 @@ NEXT_PAGE(level2_kernel_pgt)
/* Module mapping starts here */
.fill 492,8,0
-NEXT_PAGE(empty_zero_page)
-
NEXT_PAGE(level3_physmem_pgt)
.quad phys_level2_kernel_pgt | 0x007 /* so that __va works even before pagetable_init */
.fill 511,8,0
@@ -337,7 +337,7 @@ ENTRY(boot_level4_pgt)
.align 16
.globl cpu_gdt_descr
cpu_gdt_descr:
- .word gdt_end-cpu_gdt_table
+ .word gdt_end-cpu_gdt_table-1
gdt:
.quad cpu_gdt_table
#ifdef CONFIG_SMP
@@ -352,7 +352,8 @@ gdt:
* Also sysret mandates a special GDT layout
*/
-.align PAGE_SIZE
+ .section .data.page_aligned, "aw"
+ .align PAGE_SIZE
/* The TLS descriptors are currently at a different place compared to i386.
Hopefully nobody expects them at a fixed place (Wine?) */
@@ -378,9 +379,12 @@ gdt_end:
/* zero the remaining page */
.fill PAGE_SIZE / 8 - GDT_ENTRIES,8,0
-ENTRY(idt_table)
- .rept 256
- .quad 0
- .quad 0
- .endr
+ .section .bss, "aw", @nobits
+ .align L1_CACHE_BYTES
+ENTRY(idt_table)
+ .skip 256 * 16
+ .section .bss.page_aligned, "aw", @nobits
+ .align PAGE_SIZE
+ENTRY(empty_zero_page)
+ .skip PAGE_SIZE
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index ffed464e6b1..77b4c608cca 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -50,7 +50,7 @@ static int no_timer_check;
int disable_timer_pin_1 __initdata;
-int timer_over_8254 __initdata = 1;
+int timer_over_8254 __initdata = 0;
/* Where if anywhere is the i8259 connect in external int mode */
static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
@@ -310,7 +310,7 @@ void __init check_ioapic(void)
force_iommu) &&
!iommu_aperture_allowed) {
printk(KERN_INFO
- "Looks like a VIA chipset. Disabling IOMMU. Overwrite with \"iommu=allowed\"\n");
+ "Looks like a VIA chipset. Disabling IOMMU. Override with \"iommu=allowed\"\n");
iommu_aperture_disabled = 1;
}
#endif
@@ -1848,7 +1848,7 @@ static inline void check_timer(void)
*/
setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
if (timer_irq_works()) {
- printk("works.\n");
+ apic_printk(APIC_VERBOSE," works.\n");
nmi_watchdog_default();
if (nmi_watchdog == NMI_IO_APIC) {
setup_nmi();
@@ -1860,7 +1860,7 @@ static inline void check_timer(void)
*/
clear_IO_APIC_pin(apic2, pin2);
}
- printk(" failed.\n");
+ apic_printk(APIC_VERBOSE," failed.\n");
if (nmi_watchdog == NMI_IO_APIC) {
printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
@@ -1875,7 +1875,7 @@ static inline void check_timer(void)
enable_8259A_irq(0);
if (timer_irq_works()) {
- apic_printk(APIC_QUIET, " works.\n");
+ apic_printk(APIC_VERBOSE," works.\n");
return;
}
apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 14f0ced613b..accbff3fec4 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -37,10 +37,12 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/preempt.h>
+#include <linux/module.h>
#include <asm/cacheflush.h>
#include <asm/pgtable.h>
#include <asm/kdebug.h>
+#include <asm/uaccess.h>
void jprobe_return_end(void);
static void __kprobes arch_copy_kprobe(struct kprobe *p);
@@ -578,16 +580,62 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ const struct exception_table_entry *fixup;
- if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
- return 1;
-
- if (kcb->kprobe_status & KPROBE_HIT_SS) {
- resume_execution(cur, regs, kcb);
+ switch(kcb->kprobe_status) {
+ case KPROBE_HIT_SS:
+ case KPROBE_REENTER:
+ /*
+ * We are here because the instruction being single
+ * stepped caused a page fault. We reset the current
+ * kprobe and the rip points back to the probe address
+ * and allow the page fault handler to continue as a
+ * normal page fault.
+ */
+ regs->rip = (unsigned long)cur->addr;
regs->eflags |= kcb->kprobe_old_rflags;
-
- reset_current_kprobe();
+ if (kcb->kprobe_status == KPROBE_REENTER)
+ restore_previous_kprobe(kcb);
+ else
+ reset_current_kprobe();
preempt_enable_no_resched();
+ break;
+ case KPROBE_HIT_ACTIVE:
+ case KPROBE_HIT_SSDONE:
+ /*
+ * We increment the nmissed count for accounting,
+ * we can also use npre/npostfault count for accouting
+ * these specific fault cases.
+ */
+ kprobes_inc_nmissed_count(cur);
+
+ /*
+ * We come here because instructions in the pre/post
+ * handler caused the page_fault, this could happen
+ * if handler tries to access user space by
+ * copy_from_user(), get_user() etc. Let the
+ * user-specified handler try to fix it first.
+ */
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+ return 1;
+
+ /*
+ * In case the user-specified fault handler returned
+ * zero, try to fix up.
+ */
+ fixup = search_exception_tables(regs->rip);
+ if (fixup) {
+ regs->rip = fixup->fixup;
+ return 1;
+ }
+
+ /*
+ * fixup() could not handle it,
+ * Let do_page_fault() fix it.
+ */
+ break;
+ default:
+ break;
}
return 0;
}
@@ -601,6 +649,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
struct die_args *args = (struct die_args *)data;
int ret = NOTIFY_DONE;
+ if (args->regs && user_mode(args->regs))
+ return ret;
+
switch (val) {
case DIE_INT3:
if (kprobe_handler(args->regs))
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index 9013a90b5c2..b17cf3eba35 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -106,11 +106,11 @@ static int __init mpf_checksum(unsigned char *mp, int len)
return sum & 0xFF;
}
-static void __init MP_processor_info (struct mpc_config_processor *m)
+static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
{
int cpu;
unsigned char ver;
- static int found_bsp=0;
+ cpumask_t tmp_map;
if (!(m->mpc_cpuflag & CPU_ENABLED)) {
disabled_cpus++;
@@ -133,8 +133,10 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
return;
}
- cpu = num_processors++;
-
+ num_processors++;
+ cpus_complement(tmp_map, cpu_present_map);
+ cpu = first_cpu(tmp_map);
+
#if MAX_APICS < 255
if ((int)m->mpc_apicid > MAX_APICS) {
printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
@@ -160,12 +162,7 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
* entry is BSP, and so on.
*/
cpu = 0;
-
- bios_cpu_apicid[0] = m->mpc_apicid;
- x86_cpu_to_apicid[0] = m->mpc_apicid;
- found_bsp = 1;
- } else
- cpu = num_processors - found_bsp;
+ }
bios_cpu_apicid[cpu] = m->mpc_apicid;
x86_cpu_to_apicid[cpu] = m->mpc_apicid;
@@ -691,7 +688,7 @@ void __init mp_register_lapic_address (
}
-void __init mp_register_lapic (
+void __cpuinit mp_register_lapic (
u8 id,
u8 enabled)
{
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 66c009e10ba..d9e4067faf0 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -534,6 +534,7 @@ asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code)
void set_nmi_callback(nmi_callback_t callback)
{
+ vmalloc_sync_all();
rcu_assign_pointer(nmi_callback, callback);
}
diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c
index 4ed391edd47..03c9eeedb0f 100644
--- a/arch/x86_64/kernel/pci-dma.c
+++ b/arch/x86_64/kernel/pci-dma.c
@@ -73,6 +73,9 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
if (dma_mask == 0)
dma_mask = 0xffffffff;
+ /* Don't invoke OOM killer */
+ gfp |= __GFP_NORETRY;
+
/* Kludge to make it bug-to-bug compatible with i386. i386
uses the normal dma_mask for alloc_coherent. */
dma_mask &= *dev->dma_mask;
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index 0c3f052ba6c..a6c01e12126 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -65,9 +65,7 @@ static u32 gart_unmapped_entry;
#define for_all_nb(dev) \
dev = NULL; \
- while ((dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1103, dev))!=NULL)\
- if (dev->bus->number == 0 && \
- (PCI_SLOT(dev->devfn) >= 24) && (PCI_SLOT(dev->devfn) <= 31))
+ while ((dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1103, dev))!=NULL)
static struct pci_dev *northbridges[MAX_NB];
static u32 northbridge_flush_word[MAX_NB];
@@ -148,9 +146,12 @@ static void flush_gart(struct device *dev)
if (!northbridges[i])
continue;
/* Make sure the hardware actually executed the flush. */
- do {
+ for (;;) {
pci_read_config_dword(northbridges[i], 0x9c, &w);
- } while (w & 1);
+ if (!(w & 1))
+ break;
+ cpu_relax();
+ }
}
if (!flushed)
printk("nothing to flush?\n");
diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c
index 5c51d10408a..ee5ee4891f3 100644
--- a/arch/x86_64/kernel/pmtimer.c
+++ b/arch/x86_64/kernel/pmtimer.c
@@ -86,7 +86,7 @@ static unsigned pmtimer_wait_tick(void)
for (a = b = inl(pmtmr_ioport) & ACPI_PM_MASK;
a == b;
b = inl(pmtmr_ioport) & ACPI_PM_MASK)
- ;
+ cpu_relax();
return b;
}
@@ -97,6 +97,7 @@ void pmtimer_wait(unsigned us)
a = pmtimer_wait_tick();
do {
b = inl(pmtmr_ioport);
+ cpu_relax();
} while (cyc2us(b - a) < us);
}
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 80a8f307917..70dd8e5c688 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -35,8 +35,8 @@
#include <linux/ptrace.h>
#include <linux/utsname.h>
#include <linux/random.h>
-#include <linux/kprobes.h>
#include <linux/notifier.h>
+#include <linux/kprobes.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -66,24 +66,17 @@ EXPORT_SYMBOL(boot_option_idle_override);
void (*pm_idle)(void);
static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
-static struct notifier_block *idle_notifier;
-static DEFINE_SPINLOCK(idle_notifier_lock);
+static ATOMIC_NOTIFIER_HEAD(idle_notifier);
void idle_notifier_register(struct notifier_block *n)
{
- unsigned long flags;
- spin_lock_irqsave(&idle_notifier_lock, flags);
- notifier_chain_register(&idle_notifier, n);
- spin_unlock_irqrestore(&idle_notifier_lock, flags);
+ atomic_notifier_chain_register(&idle_notifier, n);
}
EXPORT_SYMBOL_GPL(idle_notifier_register);
void idle_notifier_unregister(struct notifier_block *n)
{
- unsigned long flags;
- spin_lock_irqsave(&idle_notifier_lock, flags);
- notifier_chain_unregister(&idle_notifier, n);
- spin_unlock_irqrestore(&idle_notifier_lock, flags);
+ atomic_notifier_chain_unregister(&idle_notifier, n);
}
EXPORT_SYMBOL(idle_notifier_unregister);
@@ -93,13 +86,13 @@ static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE;
void enter_idle(void)
{
__get_cpu_var(idle_state) = CPU_IDLE;
- notifier_call_chain(&idle_notifier, IDLE_START, NULL);
+ atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
}
static void __exit_idle(void)
{
__get_cpu_var(idle_state) = CPU_NOT_IDLE;
- notifier_call_chain(&idle_notifier, IDLE_END, NULL);
+ atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
}
/* Called from interrupts to signify idle end */
@@ -353,13 +346,6 @@ void exit_thread(void)
struct task_struct *me = current;
struct thread_struct *t = &me->thread;
- /*
- * Remove function-return probe instances associated with this task
- * and put them back on the free list. Do not insert an exit probe for
- * this function, it will be disabled by kprobe_flush_task if you do.
- */
- kprobe_flush_task(me);
-
if (me->thread.io_bitmap_ptr) {
struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
@@ -508,7 +494,7 @@ out:
/*
* This special macro can be used to load a debugging register
*/
-#define loaddebug(thread,r) set_debug(thread->debugreg ## r, r)
+#define loaddebug(thread,r) set_debugreg(thread->debugreg ## r, r)
/*
* switch_to(x,y) should switch tasks from x to y.
@@ -527,8 +513,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
int cpu = smp_processor_id();
struct tss_struct *tss = &per_cpu(init_tss, cpu);
- unlazy_fpu(prev_p);
-
/*
* Reload esp0, LDT and the page table pointer:
*/
@@ -586,11 +570,14 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
}
/*
- * Switch the PDA context.
+ * Switch the PDA and FPU contexts.
*/
prev->userrsp = read_pda(oldrsp);
write_pda(oldrsp, next->userrsp);
write_pda(pcurrent, next_p);
+ /* This must be here to ensure both math_state_restore() and
+ kernel_fpu_begin() work consistently. */
+ unlazy_fpu(prev_p);
write_pda(kernelstack,
task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index 53205622351..d44b2c1e63a 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -420,9 +420,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case offsetof(struct user, u_debugreg[7]):
/* See arch/i386/kernel/ptrace.c for an explanation of
* this awkward check.*/
- data &= ~DR_CONTROL_RESERVED;
- for(i=0; i<4; i++)
- if ((0x5454 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
+ data &= ~DR_CONTROL_RESERVED;
+ for(i=0; i<4; i++)
+ if ((0x5554 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
break;
if (i == 4) {
child->thread.debugreg7 = data;
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index f227d0c23dc..d1f3e9272c0 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -46,6 +46,7 @@
#include <linux/cpufreq.h>
#include <linux/dmi.h>
#include <linux/dma-mapping.h>
+#include <linux/ctype.h>
#include <asm/mtrr.h>
#include <asm/uaccess.h>
@@ -67,6 +68,7 @@
#include <asm/swiotlb.h>
#include <asm/sections.h>
#include <asm/gart-mapping.h>
+#include <asm/dmi.h>
/*
* Machine setup..
@@ -91,6 +93,12 @@ int bootloader_type;
unsigned long saved_video_mode;
+/*
+ * Early DMI memory
+ */
+int dmi_alloc_index;
+char dmi_alloc_data[DMI_MAX_DATA];
+
/*
* Setup options
*/
@@ -270,6 +278,13 @@ static void __init probe_roms(void)
}
}
+/* Check for full argument with no trailing characters */
+static int fullarg(char *p, char *arg)
+{
+ int l = strlen(arg);
+ return !memcmp(p, arg, l) && (p[l] == 0 || isspace(p[l]));
+}
+
static __init void parse_cmdline_early (char ** cmdline_p)
{
char c = ' ', *to = command_line, *from = COMMAND_LINE;
@@ -293,10 +308,10 @@ static __init void parse_cmdline_early (char ** cmdline_p)
#endif
#ifdef CONFIG_ACPI
/* "acpi=off" disables both ACPI table parsing and interpreter init */
- if (!memcmp(from, "acpi=off", 8))
+ if (fullarg(from,"acpi=off"))
disable_acpi();
- if (!memcmp(from, "acpi=force", 10)) {
+ if (fullarg(from, "acpi=force")) {
/* add later when we do DMI horrors: */
acpi_force = 1;
acpi_disabled = 0;
@@ -304,52 +319,47 @@ static __init void parse_cmdline_early (char ** cmdline_p)
/* acpi=ht just means: do ACPI MADT parsing
at bootup, but don't enable the full ACPI interpreter */
- if (!memcmp(from, "acpi=ht", 7)) {
+ if (fullarg(from, "acpi=ht")) {
if (!acpi_force)
disable_acpi();
acpi_ht = 1;
}
- else if (!memcmp(from, "pci=noacpi", 10))
+ else if (fullarg(from, "pci=noacpi"))
acpi_disable_pci();
- else if (!memcmp(from, "acpi=noirq", 10))
+ else if (fullarg(from, "acpi=noirq"))
acpi_noirq_set();
- else if (!memcmp(from, "acpi_sci=edge", 13))
+ else if (fullarg(from, "acpi_sci=edge"))
acpi_sci_flags.trigger = 1;
- else if (!memcmp(from, "acpi_sci=level", 14))
+ else if (fullarg(from, "acpi_sci=level"))
acpi_sci_flags.trigger = 3;
- else if (!memcmp(from, "acpi_sci=high", 13))
+ else if (fullarg(from, "acpi_sci=high"))
acpi_sci_flags.polarity = 1;
- else if (!memcmp(from, "acpi_sci=low", 12))
+ else if (fullarg(from, "acpi_sci=low"))
acpi_sci_flags.polarity = 3;
/* acpi=strict disables out-of-spec workarounds */
- else if (!memcmp(from, "acpi=strict", 11)) {
+ else if (fullarg(from, "acpi=strict")) {
acpi_strict = 1;
}
#ifdef CONFIG_X86_IO_APIC
- else if (!memcmp(from, "acpi_skip_timer_override", 24))
+ else if (fullarg(from, "acpi_skip_timer_override"))
acpi_skip_timer_override = 1;
#endif
#endif
- if (!memcmp(from, "disable_timer_pin_1", 19))
+ if (fullarg(from, "disable_timer_pin_1"))
disable_timer_pin_1 = 1;
- if (!memcmp(from, "enable_timer_pin_1", 18))
+ if (fullarg(from, "enable_timer_pin_1"))
disable_timer_pin_1 = -1;
- if (!memcmp(from, "nolapic", 7) ||
- !memcmp(from, "disableapic", 11))
+ if (fullarg(from, "nolapic") || fullarg(from, "disableapic"))
disable_apic = 1;
- /* Don't confuse with noapictimer */
- if (!memcmp(from, "noapic", 6) &&
- (from[6] == ' ' || from[6] == 0))
+ if (fullarg(from, "noapic"))
skip_ioapic_setup = 1;
- /* Make sure to not confuse with apic= */
- if (!memcmp(from, "apic", 4) &&
- (from[4] == ' ' || from[4] == 0)) {
+ if (fullarg(from,"apic")) {
skip_ioapic_setup = 0;
ioapic_force = 1;
}
@@ -388,7 +398,7 @@ static __init void parse_cmdline_early (char ** cmdline_p)
iommu_setup(from+6);
}
- if (!memcmp(from,"oops=panic", 10))
+ if (fullarg(from,"oops=panic"))
panic_on_oops = 1;
if (!memcmp(from, "noexec=", 7))
@@ -611,11 +621,14 @@ void __init setup_arch(char **cmdline_p)
* we are rounding upwards:
*/
end_pfn = e820_end_of_ram();
+ num_physpages = end_pfn; /* for pfn_valid */
check_efer();
init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
+ dmi_scan_machine();
+
zap_low_mappings(0);
#ifdef CONFIG_ACPI
@@ -708,6 +721,12 @@ void __init setup_arch(char **cmdline_p)
check_ioapic();
+ /*
+ * set this early, so we dont allocate cpu0
+ * if MADT list doesnt list BSP first
+ * mpparse.c/MP_processor_info() allocates logical cpu numbers.
+ */
+ cpu_set(0, cpu_present_map);
#ifdef CONFIG_ACPI
/*
* Read APIC and some other early information from ACPI tables.
@@ -836,7 +855,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
unsigned bits;
#ifdef CONFIG_NUMA
int node = 0;
- unsigned apicid = phys_proc_id[cpu];
+ unsigned apicid = hard_smp_processor_id();
#endif
bits = 0;
@@ -846,7 +865,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
/* Low order bits define the core id (index of core in socket) */
cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1);
/* Convert the APIC ID into the socket ID */
- phys_proc_id[cpu] >>= bits;
+ phys_proc_id[cpu] = phys_pkg_id(bits);
#ifdef CONFIG_NUMA
node = phys_proc_id[cpu];
@@ -872,8 +891,8 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
}
numa_set_node(cpu, node);
- printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
- cpu, c->x86_max_cores, node, cpu_core_id[cpu]);
+ printk(KERN_INFO "CPU %d/%x(%d) -> Node %d -> Core %d\n",
+ cpu, apicid, c->x86_max_cores, node, cpu_core_id[cpu]);
#endif
#endif
}
@@ -927,8 +946,6 @@ static int __init init_amd(struct cpuinfo_x86 *c)
if (c->extended_cpuid_level >= 0x80000008) {
c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
- if (c->x86_max_cores & (c->x86_max_cores - 1))
- c->x86_max_cores = 1;
amd_detect_cmp(c);
}
@@ -945,7 +962,6 @@ static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
cpuid(1, &eax, &ebx, &ecx, &edx);
- c->apicid = phys_pkg_id(0);
if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
return;
@@ -1154,6 +1170,8 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
c->x86_capability[2] = cpuid_edx(0x80860001);
}
+ c->apicid = phys_pkg_id(0);
+
/*
* Vendor-specific initialization. In this section we
* canonicalize the feature flags, meaning if there are
@@ -1261,7 +1279,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* Intel-defined (#2) */
- "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", NULL, "est",
+ "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
"tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -1402,10 +1420,3 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo,
};
-static int __init run_dmi_scan(void)
-{
- dmi_scan_machine();
- return 0;
-}
-core_initcall(run_dmi_scan);
-
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 70f1bb808a2..eabdb63fec3 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -33,7 +33,7 @@ cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
struct x8664_pda *_cpu_pda[NR_CPUS] __read_mostly;
struct x8664_pda boot_cpu_pda[NR_CPUS] __cacheline_aligned;
-struct desc_ptr idt_descr = { 256 * 16, (unsigned long) idt_table };
+struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned")));
@@ -59,7 +59,7 @@ int __init nonx_setup(char *str)
}
__setup("noexec=", nonx_setup); /* parsed early actually */
-int force_personality32 = READ_IMPLIES_EXEC;
+int force_personality32 = 0;
/* noexec32=on|off
Control non executable heap for 32bit processes.
@@ -248,7 +248,7 @@ void __cpuinit cpu_init (void)
switch (v + 1) {
#if DEBUG_STKSZ > EXCEPTION_STKSZ
case DEBUG_STACK:
- cpu_pda[cpu].debugstack = (unsigned long)estacks;
+ cpu_pda(cpu)->debugstack = (unsigned long)estacks;
estacks += DEBUG_STKSZ;
break;
#endif
@@ -281,12 +281,12 @@ void __cpuinit cpu_init (void)
* Clear all 6 debug registers:
*/
- set_debug(0UL, 0);
- set_debug(0UL, 1);
- set_debug(0UL, 2);
- set_debug(0UL, 3);
- set_debug(0UL, 6);
- set_debug(0UL, 7);
+ set_debugreg(0UL, 0);
+ set_debugreg(0UL, 1);
+ set_debugreg(0UL, 2);
+ set_debugreg(0UL, 3);
+ set_debugreg(0UL, 6);
+ set_debugreg(0UL, 7);
fpu_init();
}
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index 19ef012b1f1..4a6628b14d9 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -75,7 +75,7 @@ static inline void leave_mm(int cpu)
{
if (read_pda(mmu_state) == TLBSTATE_OK)
BUG();
- clear_bit(cpu, &read_pda(active_mm)->cpu_vm_mask);
+ cpu_clear(cpu, read_pda(active_mm)->cpu_vm_mask);
load_cr3(swapper_pg_dir);
}
@@ -85,7 +85,7 @@ static inline void leave_mm(int cpu)
* [cpu0: the cpu that switches]
* 1) switch_mm() either 1a) or 1b)
* 1a) thread switch to a different mm
- * 1a1) clear_bit(cpu, &old_mm->cpu_vm_mask);
+ * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
* Stop ipi delivery for the old mm. This is not synchronized with
* the other cpus, but smp_invalidate_interrupt ignore flush ipis
* for the wrong mm, and in the worst case we perform a superfluous
@@ -95,7 +95,7 @@ static inline void leave_mm(int cpu)
* was in lazy tlb mode.
* 1a3) update cpu active_mm
* Now cpu0 accepts tlb flushes for the new mm.
- * 1a4) set_bit(cpu, &new_mm->cpu_vm_mask);
+ * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
* Now the other cpus will send tlb flush ipis.
* 1a4) change cr3.
* 1b) thread switch without mm change
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 66e98659d07..ea48fa63807 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -68,6 +68,9 @@ u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
/* core ID of each logical CPU */
u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
+/* Last level cache ID of each logical CPU */
+u8 cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID};
+
/* Bitmask of currently online CPUs */
cpumask_t cpu_online_map __read_mostly;
@@ -445,6 +448,18 @@ void __cpuinit smp_callin(void)
cpu_set(cpuid, cpu_callin_map);
}
+/* maps the cpu to the sched domain representing multi-core */
+cpumask_t cpu_coregroup_map(int cpu)
+{
+ struct cpuinfo_x86 *c = cpu_data + cpu;
+ /*
+ * For perf, we return last level cache shared map.
+ * TBD: when power saving sched policy is added, we will return
+ * cpu_core_map when power saving policy is enabled
+ */
+ return c->llc_shared_map;
+}
+
/* representing cpus for which sibling maps can be computed */
static cpumask_t cpu_sibling_setup_map;
@@ -463,12 +478,16 @@ static inline void set_cpu_sibling_map(int cpu)
cpu_set(cpu, cpu_sibling_map[i]);
cpu_set(i, cpu_core_map[cpu]);
cpu_set(cpu, cpu_core_map[i]);
+ cpu_set(i, c[cpu].llc_shared_map);
+ cpu_set(cpu, c[i].llc_shared_map);
}
}
} else {
cpu_set(cpu, cpu_sibling_map[cpu]);
}
+ cpu_set(cpu, c[cpu].llc_shared_map);
+
if (current_cpu_data.x86_max_cores == 1) {
cpu_core_map[cpu] = cpu_sibling_map[cpu];
c[cpu].booted_cores = 1;
@@ -476,6 +495,11 @@ static inline void set_cpu_sibling_map(int cpu)
}
for_each_cpu_mask(i, cpu_sibling_setup_map) {
+ if (cpu_llc_id[cpu] != BAD_APICID &&
+ cpu_llc_id[cpu] == cpu_llc_id[i]) {
+ cpu_set(i, c[cpu].llc_shared_map);
+ cpu_set(cpu, c[i].llc_shared_map);
+ }
if (phys_proc_id[cpu] == phys_proc_id[i]) {
cpu_set(i, cpu_core_map[cpu]);
cpu_set(cpu, cpu_core_map[i]);
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index ee5ce3d3cbc..473b514b66e 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -88,7 +88,8 @@ static inline unsigned int do_gettimeoffset_tsc(void)
unsigned long t;
unsigned long x;
t = get_cycles_sync();
- if (t < vxtime.last_tsc) t = vxtime.last_tsc; /* hack */
+ if (t < vxtime.last_tsc)
+ t = vxtime.last_tsc; /* hack */
x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> 32;
return x;
}
@@ -178,8 +179,9 @@ unsigned long profile_pc(struct pt_regs *regs)
{
unsigned long pc = instruction_pointer(regs);
- /* Assume the lock function has either no stack frame or only a single word.
- This checks if the address on the stack looks like a kernel text address.
+ /* Assume the lock function has either no stack frame or only a single
+ word. This checks if the address on the stack looks like a kernel
+ text address.
There is a small window for false hits, but in that case the tick
is just accounted to the spinlock function.
Better would be to write these functions in assembler again
@@ -242,17 +244,10 @@ static void set_rtc_mmss(unsigned long nowtime)
real_minutes += 30; /* correct for half hour time zone */
real_minutes %= 60;
-#if 0
- /* AMD 8111 is a really bad time keeper and hits this regularly.
- It probably was an attempt to avoid screwing up DST, but ignore
- that for now. */
if (abs(real_minutes - cmos_minutes) >= 30) {
printk(KERN_WARNING "time.c: can't update CMOS clock "
"from %d to %d\n", cmos_minutes, real_minutes);
- } else
-#endif
-
- {
+ } else {
BIN_TO_BCD(real_seconds);
BIN_TO_BCD(real_minutes);
CMOS_WRITE(real_seconds, RTC_SECONDS);
@@ -293,8 +288,7 @@ unsigned long long monotonic_clock(void)
this_offset = hpet_readl(HPET_COUNTER);
} while (read_seqretry(&xtime_lock, seq));
offset = (this_offset - last_offset);
- offset *=(NSEC_PER_SEC/HZ)/hpet_tick;
- return base + offset;
+ offset *= (NSEC_PER_SEC/HZ) / hpet_tick;
} else {
do {
seq = read_seqbegin(&xtime_lock);
@@ -303,50 +297,46 @@ unsigned long long monotonic_clock(void)
base = monotonic_base;
} while (read_seqretry(&xtime_lock, seq));
this_offset = get_cycles_sync();
- offset = (this_offset - last_offset)*1000/cpu_khz;
- return base + offset;
+ offset = (this_offset - last_offset)*1000 / cpu_khz;
}
+ return base + offset;
}
EXPORT_SYMBOL(monotonic_clock);
static noinline void handle_lost_ticks(int lost, struct pt_regs *regs)
{
- static long lost_count;
- static int warned;
-
- if (report_lost_ticks) {
- printk(KERN_WARNING "time.c: Lost %d timer "
- "tick(s)! ", lost);
- print_symbol("rip %s)\n", regs->rip);
- }
-
- if (lost_count == 1000 && !warned) {
- printk(KERN_WARNING
- "warning: many lost ticks.\n"
- KERN_WARNING "Your time source seems to be instable or "
+ static long lost_count;
+ static int warned;
+ if (report_lost_ticks) {
+ printk(KERN_WARNING "time.c: Lost %d timer tick(s)! ", lost);
+ print_symbol("rip %s)\n", regs->rip);
+ }
+
+ if (lost_count == 1000 && !warned) {
+ printk(KERN_WARNING "warning: many lost ticks.\n"
+ KERN_WARNING "Your time source seems to be instable or "
"some driver is hogging interupts\n");
- print_symbol("rip %s\n", regs->rip);
- if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) {
- printk(KERN_WARNING "Falling back to HPET\n");
- if (hpet_use_timer)
- vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
- else
- vxtime.last = hpet_readl(HPET_COUNTER);
- vxtime.mode = VXTIME_HPET;
- do_gettimeoffset = do_gettimeoffset_hpet;
- }
- /* else should fall back to PIT, but code missing. */
- warned = 1;
- } else
- lost_count++;
+ print_symbol("rip %s\n", regs->rip);
+ if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) {
+ printk(KERN_WARNING "Falling back to HPET\n");
+ if (hpet_use_timer)
+ vxtime.last = hpet_readl(HPET_T0_CMP) -
+ hpet_tick;
+ else
+ vxtime.last = hpet_readl(HPET_COUNTER);
+ vxtime.mode = VXTIME_HPET;
+ do_gettimeoffset = do_gettimeoffset_hpet;
+ }
+ /* else should fall back to PIT, but code missing. */
+ warned = 1;
+ } else
+ lost_count++;
#ifdef CONFIG_CPU_FREQ
- /* In some cases the CPU can change frequency without us noticing
- (like going into thermal throttle)
- Give cpufreq a change to catch up. */
- if ((lost_count+1) % 25 == 0) {
- cpufreq_delayed_get();
- }
+ /* In some cases the CPU can change frequency without us noticing
+ Give cpufreq a change to catch up. */
+ if ((lost_count+1) % 25 == 0)
+ cpufreq_delayed_get();
#endif
}
@@ -354,7 +344,7 @@ void main_timer_handler(struct pt_regs *regs)
{
static unsigned long rtc_update = 0;
unsigned long tsc;
- int delay, offset = 0, lost = 0;
+ int delay = 0, offset = 0, lost = 0;
/*
* Here we are in the timer irq handler. We have irqs locally disabled (so we
@@ -375,7 +365,7 @@ void main_timer_handler(struct pt_regs *regs)
*/
offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
delay = hpet_readl(HPET_COUNTER) - offset;
- } else {
+ } else if (!pmtmr_ioport) {
spin_lock(&i8253_lock);
outb_p(0x00, 0x43);
delay = inb_p(0x40);
@@ -514,43 +504,32 @@ unsigned long long sched_clock(void)
static unsigned long get_cmos_time(void)
{
- unsigned int timeout = 1000000, year, mon, day, hour, min, sec;
- unsigned char uip = 0, this = 0;
+ unsigned int year, mon, day, hour, min, sec;
unsigned long flags;
-
-/*
- * The Linux interpretation of the CMOS clock register contents: When the
- * Update-In-Progress (UIP) flag goes from 1 to 0, the RTC registers show the
- * second which has precisely just started. Waiting for this can take up to 1
- * second, we timeout approximately after 2.4 seconds on a machine with
- * standard 8.3 MHz ISA bus.
- */
+ unsigned extyear = 0;
spin_lock_irqsave(&rtc_lock, flags);
- while (timeout && (!uip || this)) {
- uip |= this;
- this = CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP;
- timeout--;
- }
-
- /*
- * Here we are safe to assume the registers won't change for a whole
- * second, so we just go ahead and read them.
- */
- sec = CMOS_READ(RTC_SECONDS);
- min = CMOS_READ(RTC_MINUTES);
- hour = CMOS_READ(RTC_HOURS);
- day = CMOS_READ(RTC_DAY_OF_MONTH);
- mon = CMOS_READ(RTC_MONTH);
- year = CMOS_READ(RTC_YEAR);
+ do {
+ sec = CMOS_READ(RTC_SECONDS);
+ min = CMOS_READ(RTC_MINUTES);
+ hour = CMOS_READ(RTC_HOURS);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
+ mon = CMOS_READ(RTC_MONTH);
+ year = CMOS_READ(RTC_YEAR);
+#ifdef CONFIG_ACPI
+ if (acpi_fadt.revision >= FADT2_REVISION_ID &&
+ acpi_fadt.century)
+ extyear = CMOS_READ(acpi_fadt.century);
+#endif
+ } while (sec != CMOS_READ(RTC_SECONDS));
spin_unlock_irqrestore(&rtc_lock, flags);
/*
* We know that x86-64 always uses BCD format, no need to check the
* config register.
- */
+ */
BCD_TO_BIN(sec);
BCD_TO_BIN(min);
@@ -559,11 +538,17 @@ static unsigned long get_cmos_time(void)
BCD_TO_BIN(mon);
BCD_TO_BIN(year);
- /*
- * x86-64 systems only exists since 2002.
- * This will work up to Dec 31, 2100
- */
- year += 2000;
+ if (extyear) {
+ BCD_TO_BIN(extyear);
+ year += extyear;
+ printk(KERN_INFO "Extended CMOS year: %d\n", extyear);
+ } else {
+ /*
+ * x86-64 systems only exists since 2002.
+ * This will work up to Dec 31, 2100
+ */
+ year += 2000;
+ }
return mktime(year, mon, day, hour, min, sec);
}
@@ -606,7 +591,8 @@ static void cpufreq_delayed_get(void)
cpufreq_delayed_issched = 1;
if (!warned) {
warned = 1;
- printk(KERN_DEBUG "Losing some ticks... checking if CPU frequency changed.\n");
+ printk(KERN_DEBUG
+ "Losing some ticks... checking if CPU frequency changed.\n");
}
schedule_work(&cpufreq_delayed_get_work);
}
@@ -629,9 +615,9 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
lpj = &dummy;
if (!(freq->flags & CPUFREQ_CONST_LOOPS))
#ifdef CONFIG_SMP
- lpj = &cpu_data[freq->cpu].loops_per_jiffy;
+ lpj = &cpu_data[freq->cpu].loops_per_jiffy;
#else
- lpj = &boot_cpu_data.loops_per_jiffy;
+ lpj = &boot_cpu_data.loops_per_jiffy;
#endif
if (!ref_freq) {
@@ -768,9 +754,8 @@ static __init int late_hpet_init(void)
int i;
hpet = (struct hpet *) fix_to_virt(FIX_HPET_BASE);
-
- for (i = 2, timer = &hpet->hpet_timers[2]; i < ntimer;
- timer++, i++)
+ timer = &hpet->hpet_timers[2];
+ for (i = 2; i < ntimer; timer++, i++)
hd.hd_irq[i] = (timer->hpet_config &
Tn_INT_ROUTE_CNF_MASK) >>
Tn_INT_ROUTE_CNF_SHIFT;
@@ -927,8 +912,7 @@ void __init time_init(void)
-xtime.tv_sec, -xtime.tv_nsec);
if (!hpet_init())
- vxtime_hz = (1000000000000000L + hpet_period / 2) /
- hpet_period;
+ vxtime_hz = (1000000000000000L + hpet_period / 2) / hpet_period;
else
vxtime.hpet_address = 0;
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 28d50dc540e..edaa9fe654d 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -47,8 +47,6 @@
#include <asm/proto.h>
#include <asm/nmi.h>
-extern struct gate_struct idt_table[256];
-
asmlinkage void divide_error(void);
asmlinkage void debug(void);
asmlinkage void nmi(void);
@@ -71,18 +69,20 @@ asmlinkage void alignment_check(void);
asmlinkage void machine_check(void);
asmlinkage void spurious_interrupt_bug(void);
-struct notifier_block *die_chain;
-static DEFINE_SPINLOCK(die_notifier_lock);
+ATOMIC_NOTIFIER_HEAD(die_chain);
int register_die_notifier(struct notifier_block *nb)
{
- int err = 0;
- unsigned long flags;
- spin_lock_irqsave(&die_notifier_lock, flags);
- err = notifier_chain_register(&die_chain, nb);
- spin_unlock_irqrestore(&die_notifier_lock, flags);
- return err;
+ vmalloc_sync_all();
+ return atomic_notifier_chain_register(&die_chain, nb);
+}
+EXPORT_SYMBOL(register_die_notifier);
+
+int unregister_die_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&die_chain, nb);
}
+EXPORT_SYMBOL(unregister_die_notifier);
static inline void conditional_sti(struct pt_regs *regs)
{
@@ -122,7 +122,7 @@ int printk_address(unsigned long address)
if (!modname)
modname = delim = "";
return printk("<%016lx>{%s%s%s%s%+ld}",
- address,delim,modname,delim,symname,offset);
+ address, delim, modname, delim, symname, offset);
}
#else
int printk_address(unsigned long address)
@@ -334,13 +334,12 @@ void show_registers(struct pt_regs *regs)
show_stack(NULL, (unsigned long*)rsp);
printk("\nCode: ");
- if(regs->rip < PAGE_OFFSET)
+ if (regs->rip < PAGE_OFFSET)
goto bad;
- for(i=0;i<20;i++)
- {
+ for (i=0; i<20; i++) {
unsigned char c;
- if(__get_user(c, &((unsigned char*)regs->rip)[i])) {
+ if (__get_user(c, &((unsigned char*)regs->rip)[i])) {
bad:
printk(" Bad RIP value.");
break;
@@ -479,7 +478,7 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
printk(KERN_INFO
"%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n",
tsk->comm, tsk->pid, str,
- regs->rip,regs->rsp,error_code);
+ regs->rip, regs->rsp, error_code);
if (info)
force_sig_info(signr, info, tsk);
@@ -493,9 +492,9 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
{
const struct exception_table_entry *fixup;
fixup = search_exception_tables(regs->rip);
- if (fixup) {
+ if (fixup)
regs->rip = fixup->fixup;
- } else
+ else
die(str, regs, error_code);
return;
}
@@ -568,7 +567,7 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
printk(KERN_INFO
"%s[%d] general protection rip:%lx rsp:%lx error:%lx\n",
tsk->comm, tsk->pid,
- regs->rip,regs->rsp,error_code);
+ regs->rip, regs->rsp, error_code);
force_sig(SIGSEGV, tsk);
return;
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 74db0062d4a..39ff0708f80 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -20,6 +20,12 @@ SECTIONS
phys_startup_64 = startup_64 - LOAD_OFFSET;
_text = .; /* Text and read-only data */
.text : AT(ADDR(.text) - LOAD_OFFSET) {
+ /* First the code that has to be first for bootstrapping */
+ *(.bootstrap.text)
+ /* Then all the functions that are "hot" in profiles, to group them
+ onto the same hugetlb entry */
+ #include "functionlist"
+ /* Then the rest */
*(.text)
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index c9dc7e46731..d96a9348e5a 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -144,16 +144,12 @@ EXPORT_SYMBOL(rwsem_down_write_failed_thunk);
EXPORT_SYMBOL(empty_zero_page);
EXPORT_SYMBOL(die_chain);
-EXPORT_SYMBOL(register_die_notifier);
#ifdef CONFIG_SMP
EXPORT_SYMBOL(cpu_sibling_map);
EXPORT_SYMBOL(smp_num_siblings);
#endif
-extern void do_softirq_thunk(void);
-EXPORT_SYMBOL(do_softirq_thunk);
-
#ifdef CONFIG_BUG
EXPORT_SYMBOL(out_of_line_bug);
#endif
diff --git a/arch/x86_64/lib/thunk.S b/arch/x86_64/lib/thunk.S
index acc1e2ca7ed..e49af0032e9 100644
--- a/arch/x86_64/lib/thunk.S
+++ b/arch/x86_64/lib/thunk.S
@@ -42,7 +42,6 @@
thunk rwsem_wake_thunk,rwsem_wake
thunk rwsem_downgrade_thunk,rwsem_downgrade_wake
#endif
- thunk do_softirq_thunk,do_softirq
thunk __down_failed,__down
thunk_retrax __down_failed_interruptible,__down_interruptible
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index 2e7c3c8ffe0..316c53de47b 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -264,6 +264,8 @@ static int vmalloc_fault(unsigned long address)
return -1;
if (pgd_none(*pgd))
set_pgd(pgd, *pgd_ref);
+ else
+ BUG_ON(pgd_page(*pgd) != pgd_page(*pgd_ref));
/* Below here mismatches are bugs because these lower tables
are shared */
@@ -312,21 +314,13 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
unsigned long flags;
siginfo_t info;
+ tsk = current;
+ mm = tsk->mm;
+ prefetchw(&mm->mmap_sem);
+
/* get the address */
__asm__("movq %%cr2,%0":"=r" (address));
- if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
- SIGSEGV) == NOTIFY_STOP)
- return;
-
- if (likely(regs->eflags & X86_EFLAGS_IF))
- local_irq_enable();
- if (unlikely(page_fault_trace))
- printk("pagefault rip:%lx rsp:%lx cs:%lu ss:%lu address %lx error %lx\n",
- regs->rip,regs->rsp,regs->cs,regs->ss,address,error_code);
-
- tsk = current;
- mm = tsk->mm;
info.si_code = SEGV_MAPERR;
@@ -351,10 +345,12 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
*/
if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
((address >= VMALLOC_START && address < VMALLOC_END))) {
- if (vmalloc_fault(address) < 0)
- goto bad_area_nosemaphore;
- return;
+ if (vmalloc_fault(address) >= 0)
+ return;
}
+ if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+ SIGSEGV) == NOTIFY_STOP)
+ return;
/*
* Don't take the mm semaphore here. If we fixup a prefetch
* fault we could otherwise deadlock.
@@ -362,6 +358,17 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
goto bad_area_nosemaphore;
}
+ if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+ SIGSEGV) == NOTIFY_STOP)
+ return;
+
+ if (likely(regs->eflags & X86_EFLAGS_IF))
+ local_irq_enable();
+
+ if (unlikely(page_fault_trace))
+ printk("pagefault rip:%lx rsp:%lx cs:%lu ss:%lu address %lx error %lx\n",
+ regs->rip,regs->rsp,regs->cs,regs->ss,address,error_code);
+
if (unlikely(error_code & PF_RSVD))
pgtable_bad(address, regs, error_code);
@@ -571,6 +578,48 @@ do_sigbus:
return;
}
+DEFINE_SPINLOCK(pgd_lock);
+struct page *pgd_list;
+
+void vmalloc_sync_all(void)
+{
+ /* Note that races in the updates of insync and start aren't
+ problematic:
+ insync can only get set bits added, and updates to start are only
+ improving performance (without affecting correctness if undone). */
+ static DECLARE_BITMAP(insync, PTRS_PER_PGD);
+ static unsigned long start = VMALLOC_START & PGDIR_MASK;
+ unsigned long address;
+
+ for (address = start; address <= VMALLOC_END; address += PGDIR_SIZE) {
+ if (!test_bit(pgd_index(address), insync)) {
+ const pgd_t *pgd_ref = pgd_offset_k(address);
+ struct page *page;
+
+ if (pgd_none(*pgd_ref))
+ continue;
+ spin_lock(&pgd_lock);
+ for (page = pgd_list; page;
+ page = (struct page *)page->index) {
+ pgd_t *pgd;
+ pgd = (pgd_t *)page_address(page) + pgd_index(address);
+ if (pgd_none(*pgd))
+ set_pgd(pgd, *pgd_ref);
+ else
+ BUG_ON(pgd_page(*pgd) != pgd_page(*pgd_ref));
+ }
+ spin_unlock(&pgd_lock);
+ set_bit(pgd_index(address), insync);
+ }
+ if (address == start)
+ start = address + PGDIR_SIZE;
+ }
+ /* Check that there is no need to do the same for the modules area. */
+ BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
+ BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) ==
+ (__START_KERNEL & PGDIR_MASK)));
+}
+
static int __init enable_pagefaulttrace(char *str)
{
page_fault_trace = 1;
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index 40ed13d263c..e5f7f1c3446 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -72,7 +72,7 @@ void show_mem(void)
show_free_areas();
printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
for (i = 0; i < pgdat->node_spanned_pages; ++i) {
page = pfn_to_page(pgdat->node_start_pfn + i);
total++;
@@ -94,7 +94,7 @@ void show_mem(void)
int after_bootmem;
-static void *spp_getpage(void)
+static __init void *spp_getpage(void)
{
void *ptr;
if (after_bootmem)
@@ -108,7 +108,7 @@ static void *spp_getpage(void)
return ptr;
}
-static void set_pte_phys(unsigned long vaddr,
+static __init void set_pte_phys(unsigned long vaddr,
unsigned long phys, pgprot_t prot)
{
pgd_t *pgd;
@@ -157,7 +157,8 @@ static void set_pte_phys(unsigned long vaddr,
}
/* NOTE: this is meant to be run only at boot */
-void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
+void __init
+__set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
{
unsigned long address = __fix_to_virt(idx);
@@ -225,6 +226,33 @@ static __meminit void unmap_low_page(int i)
ti->allocated = 0;
}
+/* Must run before zap_low_mappings */
+__init void *early_ioremap(unsigned long addr, unsigned long size)
+{
+ unsigned long map = round_down(addr, LARGE_PAGE_SIZE);
+
+ /* actually usually some more */
+ if (size >= LARGE_PAGE_SIZE) {
+ printk("SMBIOS area too long %lu\n", size);
+ return NULL;
+ }
+ set_pmd(temp_mappings[0].pmd, __pmd(map | _KERNPG_TABLE | _PAGE_PSE));
+ map += LARGE_PAGE_SIZE;
+ set_pmd(temp_mappings[1].pmd, __pmd(map | _KERNPG_TABLE | _PAGE_PSE));
+ __flush_tlb();
+ return temp_mappings[0].address + (addr & (LARGE_PAGE_SIZE-1));
+}
+
+/* To avoid virtual aliases later */
+__init void early_iounmap(void *addr, unsigned long size)
+{
+ if ((void *)round_down((unsigned long)addr, LARGE_PAGE_SIZE) != temp_mappings[0].address)
+ printk("early_iounmap: bad address %p\n", addr);
+ set_pmd(temp_mappings[0].pmd, __pmd(0));
+ set_pmd(temp_mappings[1].pmd, __pmd(0));
+ __flush_tlb();
+}
+
static void __meminit
phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end)
{
@@ -344,7 +372,7 @@ void __meminit init_memory_mapping(unsigned long start, unsigned long end)
pud_t *pud;
if (after_bootmem)
- pud = pud_offset_k(pgd, __PAGE_OFFSET);
+ pud = pud_offset_k(pgd, start & PGDIR_MASK);
else
pud = alloc_low_page(&map, &pud_phys);
diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c
index dd60e71fdba..7c45c2d2b8b 100644
--- a/arch/x86_64/mm/k8topology.c
+++ b/arch/x86_64/mm/k8topology.c
@@ -43,7 +43,7 @@ static __init int find_northbridge(void)
int __init k8_scan_nodes(unsigned long start, unsigned long end)
{
unsigned long prevbase;
- struct node nodes[8];
+ struct bootnode nodes[8];
int nodeid, i, nb;
unsigned char nodeids[8];
int found = 0;
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index 22e51beee8d..4be82d6e2b4 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -25,8 +25,7 @@
struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
bootmem_data_t plat_node_bdata[MAX_NUMNODES];
-int memnode_shift;
-u8 memnodemap[NODEMAPSIZE];
+struct memnode memnode;
unsigned char cpu_to_node[NR_CPUS] __read_mostly = {
[0 ... NR_CPUS-1] = NUMA_NO_NODE
@@ -47,7 +46,7 @@ int numa_off __initdata;
* -1 if node overlap or lost ram (shift too big)
*/
static int __init
-populate_memnodemap(const struct node *nodes, int numnodes, int shift)
+populate_memnodemap(const struct bootnode *nodes, int numnodes, int shift)
{
int i;
int res = -1;
@@ -74,7 +73,7 @@ populate_memnodemap(const struct node *nodes, int numnodes, int shift)
return res;
}
-int __init compute_hash_shift(struct node *nodes, int numnodes)
+int __init compute_hash_shift(struct bootnode *nodes, int numnodes)
{
int shift = 20;
@@ -149,7 +148,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
/* Initialize final allocator for a zone */
void __init setup_node_zones(int nodeid)
{
- unsigned long start_pfn, end_pfn;
+ unsigned long start_pfn, end_pfn, memmapsize, limit;
unsigned long zones[MAX_NR_ZONES];
unsigned long holes[MAX_NR_ZONES];
@@ -159,6 +158,16 @@ void __init setup_node_zones(int nodeid)
Dprintk(KERN_INFO "Setting up node %d %lx-%lx\n",
nodeid, start_pfn, end_pfn);
+ /* Try to allocate mem_map at end to not fill up precious <4GB
+ memory. */
+ memmapsize = sizeof(struct page) * (end_pfn-start_pfn);
+ limit = end_pfn << PAGE_SHIFT;
+ NODE_DATA(nodeid)->node_mem_map =
+ __alloc_bootmem_core(NODE_DATA(nodeid)->bdata,
+ memmapsize, SMP_CACHE_BYTES,
+ round_down(limit - memmapsize, PAGE_SIZE),
+ limit);
+
size_zones(zones, holes, start_pfn, end_pfn);
free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
start_pfn, holes);
@@ -191,7 +200,7 @@ int numa_fake __initdata = 0;
static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
{
int i;
- struct node nodes[MAX_NUMNODES];
+ struct bootnode nodes[MAX_NUMNODES];
unsigned long sz = ((end_pfn - start_pfn)<<PAGE_SHIFT) / numa_fake;
/* Kludge needed for the hash function */
@@ -357,8 +366,7 @@ void __init init_cpu_to_node(void)
EXPORT_SYMBOL(cpu_to_node);
EXPORT_SYMBOL(node_to_cpumask);
-EXPORT_SYMBOL(memnode_shift);
-EXPORT_SYMBOL(memnodemap);
+EXPORT_SYMBOL(memnode);
EXPORT_SYMBOL(node_data);
#ifdef CONFIG_DISCONTIGMEM
@@ -369,21 +377,6 @@ EXPORT_SYMBOL(node_data);
* Should do that.
*/
-/* Requires pfn_valid(pfn) to be true */
-struct page *pfn_to_page(unsigned long pfn)
-{
- int nid = phys_to_nid(((unsigned long)(pfn)) << PAGE_SHIFT);
- return (pfn - node_start_pfn(nid)) + NODE_DATA(nid)->node_mem_map;
-}
-EXPORT_SYMBOL(pfn_to_page);
-
-unsigned long page_to_pfn(struct page *page)
-{
- return (long)(((page) - page_zone(page)->zone_mem_map) +
- page_zone(page)->zone_start_pfn);
-}
-EXPORT_SYMBOL(page_to_pfn);
-
int pfn_valid(unsigned long pfn)
{
unsigned nid;
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 482c2576736..2eb879590dc 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -23,7 +23,7 @@ static struct acpi_table_slit *acpi_slit;
static nodemask_t nodes_parsed __initdata;
static nodemask_t nodes_found __initdata;
-static struct node nodes[MAX_NUMNODES] __initdata;
+static struct bootnode nodes[MAX_NUMNODES] __initdata;
static u8 pxm2node[256] = { [0 ... 255] = 0xff };
/* Too small nodes confuse the VM badly. Usually they result
@@ -57,7 +57,7 @@ static __init int conflicting_nodes(unsigned long start, unsigned long end)
{
int i;
for_each_node_mask(i, nodes_parsed) {
- struct node *nd = &nodes[i];
+ struct bootnode *nd = &nodes[i];
if (nd->start == nd->end)
continue;
if (nd->end > start && nd->start < end)
@@ -70,7 +70,7 @@ static __init int conflicting_nodes(unsigned long start, unsigned long end)
static __init void cutoff_node(int i, unsigned long start, unsigned long end)
{
- struct node *nd = &nodes[i];
+ struct bootnode *nd = &nodes[i];
if (nd->start < start) {
nd->start = start;
if (nd->end < nd->start)
@@ -159,7 +159,7 @@ acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
void __init
acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
{
- struct node *nd;
+ struct bootnode *nd;
unsigned long start, end;
int node, pxm;
int i;
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index e90ef5db891..dbeb3504c3c 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -22,6 +22,14 @@ config RWSEM_XCHGADD_ALGORITHM
bool
default y
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
config GENERIC_HARDIRQS
bool
default y
diff --git a/arch/xtensa/platform-iss/setup.c b/arch/xtensa/platform-iss/setup.c
index 2e6dcbf0cc0..23790a5610e 100644
--- a/arch/xtensa/platform-iss/setup.c
+++ b/arch/xtensa/platform-iss/setup.c
@@ -108,5 +108,5 @@ static struct notifier_block iss_panic_block = {
void __init platform_setup(char **p_cmdline)
{
- notifier_chain_register(&panic_notifier_list, &iss_panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block);
}
diff --git a/block/Kconfig b/block/Kconfig
index 96783645092..5536839886f 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -13,6 +13,7 @@ config LBD
config BLK_DEV_IO_TRACE
bool "Support for tracing block io actions"
+ depends on SYSFS
select RELAY
select DEBUG_FS
help
@@ -23,4 +24,13 @@ config BLK_DEV_IO_TRACE
git://brick.kernel.dk/data/git/blktrace.git
+config LSF
+ bool "Support for Large Single Files"
+ depends on X86 || (MIPS && 32BIT) || PPC32 || ARCH_S390_31 || SUPERH || UML
+ default n
+ help
+ When CONFIG_LBD is disabled, say Y here if you want to
+ handle large file(bigger than 2TB), otherwise say N.
+ When CONFIG_LBD is enabled, Y is set automatically.
+
source block/Kconfig.iosched
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index c4a0d5d8d7f..67d446de022 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -26,18 +26,12 @@ static const int cfq_back_penalty = 2; /* penalty of a backwards seek */
static const int cfq_slice_sync = HZ / 10;
static int cfq_slice_async = HZ / 25;
static const int cfq_slice_async_rq = 2;
-static int cfq_slice_idle = HZ / 100;
+static int cfq_slice_idle = HZ / 70;
#define CFQ_IDLE_GRACE (HZ / 10)
#define CFQ_SLICE_SCALE (5)
#define CFQ_KEY_ASYNC (0)
-#define CFQ_KEY_ANY (0xffff)
-
-/*
- * disable queueing at the driver/hardware level
- */
-static const int cfq_max_depth = 2;
static DEFINE_RWLOCK(cfq_exit_lock);
@@ -102,6 +96,8 @@ static struct completion *ioc_gone;
#define cfq_cfqq_sync(cfqq) \
(cfq_cfqq_class_sync(cfqq) || (cfqq)->on_dispatch[SYNC])
+#define sample_valid(samples) ((samples) > 80)
+
/*
* Per block device queue structure
*/
@@ -170,7 +166,6 @@ struct cfq_data {
unsigned int cfq_slice[2];
unsigned int cfq_slice_async_rq;
unsigned int cfq_slice_idle;
- unsigned int cfq_max_depth;
struct list_head cic_list;
};
@@ -343,17 +338,27 @@ static int cfq_queue_empty(request_queue_t *q)
return !cfqd->busy_queues;
}
+static inline pid_t cfq_queue_pid(struct task_struct *task, int rw)
+{
+ if (rw == READ || process_sync(task))
+ return task->pid;
+
+ return CFQ_KEY_ASYNC;
+}
+
/*
* Lifted from AS - choose which of crq1 and crq2 that is best served now.
* We choose the request that is closest to the head right now. Distance
- * behind the head are penalized and only allowed to a certain extent.
+ * behind the head is penalized and only allowed to a certain extent.
*/
static struct cfq_rq *
cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
{
sector_t last, s1, s2, d1 = 0, d2 = 0;
- int r1_wrap = 0, r2_wrap = 0; /* requests are behind the disk head */
unsigned long back_max;
+#define CFQ_RQ1_WRAP 0x01 /* request 1 wraps */
+#define CFQ_RQ2_WRAP 0x02 /* request 2 wraps */
+ unsigned wrap = 0; /* bit mask: requests behind the disk head? */
if (crq1 == NULL || crq1 == crq2)
return crq2;
@@ -385,35 +390,47 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
else if (s1 + back_max >= last)
d1 = (last - s1) * cfqd->cfq_back_penalty;
else
- r1_wrap = 1;
+ wrap |= CFQ_RQ1_WRAP;
if (s2 >= last)
d2 = s2 - last;
else if (s2 + back_max >= last)
d2 = (last - s2) * cfqd->cfq_back_penalty;
else
- r2_wrap = 1;
+ wrap |= CFQ_RQ2_WRAP;
/* Found required data */
- if (!r1_wrap && r2_wrap)
- return crq1;
- else if (!r2_wrap && r1_wrap)
- return crq2;
- else if (r1_wrap && r2_wrap) {
- /* both behind the head */
- if (s1 <= s2)
+
+ /*
+ * By doing switch() on the bit mask "wrap" we avoid having to
+ * check two variables for all permutations: --> faster!
+ */
+ switch (wrap) {
+ case 0: /* common case for CFQ: crq1 and crq2 not wrapped */
+ if (d1 < d2)
return crq1;
- else
+ else if (d2 < d1)
return crq2;
- }
+ else {
+ if (s1 >= s2)
+ return crq1;
+ else
+ return crq2;
+ }
- /* Both requests in front of the head */
- if (d1 < d2)
+ case CFQ_RQ2_WRAP:
return crq1;
- else if (d2 < d1)
+ case CFQ_RQ1_WRAP:
return crq2;
- else {
- if (s1 >= s2)
+ case (CFQ_RQ1_WRAP|CFQ_RQ2_WRAP): /* both crqs wrapped */
+ default:
+ /*
+ * Since both rqs are wrapped,
+ * start with the one that's further behind head
+ * (--> only *one* back seek required),
+ * since back seek takes more time than forward.
+ */
+ if (s1 <= s2)
return crq1;
else
return crq2;
@@ -612,15 +629,20 @@ cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
cfq_add_crq_rb(crq);
}
-static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector)
-
+static struct request *
+cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio)
{
- struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->pid, CFQ_KEY_ANY);
+ struct task_struct *tsk = current;
+ pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio));
+ struct cfq_queue *cfqq;
struct rb_node *n;
+ sector_t sector;
+ cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio);
if (!cfqq)
goto out;
+ sector = bio->bi_sector + bio_sectors(bio);
n = cfqq->sort_list.rb_node;
while (n) {
struct cfq_rq *crq = rb_entry_crq(n);
@@ -674,7 +696,7 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
goto out;
}
- __rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio));
+ __rq = cfq_find_rq_fmerge(cfqd, bio);
if (__rq && elv_rq_merge_ok(__rq, bio)) {
ret = ELEVATOR_FRONT_MERGE;
goto out;
@@ -877,6 +899,7 @@ static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd)
static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
{
+ struct cfq_io_context *cic;
unsigned long sl;
WARN_ON(!RB_EMPTY(&cfqq->sort_list));
@@ -892,13 +915,23 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
/*
* task has exited, don't wait
*/
- if (cfqd->active_cic && !cfqd->active_cic->ioc->task)
+ cic = cfqd->active_cic;
+ if (!cic || !cic->ioc->task)
return 0;
cfq_mark_cfqq_must_dispatch(cfqq);
cfq_mark_cfqq_wait_request(cfqq);
sl = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle);
+
+ /*
+ * we don't want to idle for seeks, but we do want to allow
+ * fair distribution of slice time for a process doing back-to-back
+ * seeks. so allow a little bit of time for him to submit a new rq
+ */
+ if (sample_valid(cic->seek_samples) && cic->seek_mean > 131072)
+ sl = 2;
+
mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
return 1;
}
@@ -1115,13 +1148,6 @@ cfq_dispatch_requests(request_queue_t *q, int force)
if (cfqq) {
int max_dispatch;
- /*
- * if idle window is disabled, allow queue buildup
- */
- if (!cfq_cfqq_idle_window(cfqq) &&
- cfqd->rq_in_driver >= cfqd->cfq_max_depth)
- return 0;
-
cfq_clear_cfqq_must_dispatch(cfqq);
cfq_clear_cfqq_wait_request(cfqq);
del_timer(&cfqd->idle_slice_timer);
@@ -1171,13 +1197,13 @@ __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio,
const int hashval)
{
struct hlist_head *hash_list = &cfqd->cfq_hash[hashval];
- struct hlist_node *entry, *next;
+ struct hlist_node *entry;
+ struct cfq_queue *__cfqq;
- hlist_for_each_safe(entry, next, hash_list) {
- struct cfq_queue *__cfqq = list_entry_qhash(entry);
+ hlist_for_each_entry(__cfqq, entry, hash_list, cfq_hash) {
const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->org_ioprio_class, __cfqq->org_ioprio);
- if (__cfqq->key == key && (__p == prio || prio == CFQ_KEY_ANY))
+ if (__cfqq->key == key && (__p == prio || !prio))
return __cfqq;
}
@@ -1190,19 +1216,19 @@ cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned short prio)
return __cfq_find_cfq_hash(cfqd, key, prio, hash_long(key, CFQ_QHASH_SHIFT));
}
-static void cfq_free_io_context(struct cfq_io_context *cic)
+static void cfq_free_io_context(struct io_context *ioc)
{
struct cfq_io_context *__cic;
- struct list_head *entry, *next;
- int freed = 1;
+ struct rb_node *n;
+ int freed = 0;
- list_for_each_safe(entry, next, &cic->list) {
- __cic = list_entry(entry, struct cfq_io_context, list);
+ while ((n = rb_first(&ioc->cic_root)) != NULL) {
+ __cic = rb_entry(n, struct cfq_io_context, rb_node);
+ rb_erase(&__cic->rb_node, &ioc->cic_root);
kmem_cache_free(cfq_ioc_pool, __cic);
freed++;
}
- kmem_cache_free(cfq_ioc_pool, cic);
if (atomic_sub_and_test(freed, &ioc_count) && ioc_gone)
complete(ioc_gone);
}
@@ -1210,8 +1236,7 @@ static void cfq_free_io_context(struct cfq_io_context *cic)
static void cfq_trim(struct io_context *ioc)
{
ioc->set_ioprio = NULL;
- if (ioc->cic)
- cfq_free_io_context(ioc->cic);
+ cfq_free_io_context(ioc);
}
/*
@@ -1250,26 +1275,26 @@ static void cfq_exit_single_io_context(struct cfq_io_context *cic)
spin_unlock(q->queue_lock);
}
-static void cfq_exit_io_context(struct cfq_io_context *cic)
+static void cfq_exit_io_context(struct io_context *ioc)
{
struct cfq_io_context *__cic;
- struct list_head *entry;
unsigned long flags;
-
- local_irq_save(flags);
+ struct rb_node *n;
/*
* put the reference this task is holding to the various queues
*/
- read_lock(&cfq_exit_lock);
- list_for_each(entry, &cic->list) {
- __cic = list_entry(entry, struct cfq_io_context, list);
+ read_lock_irqsave(&cfq_exit_lock, flags);
+
+ n = rb_first(&ioc->cic_root);
+ while (n != NULL) {
+ __cic = rb_entry(n, struct cfq_io_context, rb_node);
+
cfq_exit_single_io_context(__cic);
+ n = rb_next(n);
}
- cfq_exit_single_io_context(cic);
- read_unlock(&cfq_exit_lock);
- local_irq_restore(flags);
+ read_unlock_irqrestore(&cfq_exit_lock, flags);
}
static struct cfq_io_context *
@@ -1278,10 +1303,10 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
if (cic) {
- INIT_LIST_HEAD(&cic->list);
+ RB_CLEAR(&cic->rb_node);
+ cic->key = NULL;
cic->cfqq[ASYNC] = NULL;
cic->cfqq[SYNC] = NULL;
- cic->key = NULL;
cic->last_end_request = jiffies;
cic->ttime_total = 0;
cic->ttime_samples = 0;
@@ -1373,15 +1398,17 @@ static inline void changed_ioprio(struct cfq_io_context *cic)
static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
{
struct cfq_io_context *cic;
+ struct rb_node *n;
write_lock(&cfq_exit_lock);
- cic = ioc->cic;
-
- changed_ioprio(cic);
-
- list_for_each_entry(cic, &cic->list, list)
+ n = rb_first(&ioc->cic_root);
+ while (n != NULL) {
+ cic = rb_entry(n, struct cfq_io_context, rb_node);
+
changed_ioprio(cic);
+ n = rb_next(n);
+ }
write_unlock(&cfq_exit_lock);
@@ -1445,14 +1472,67 @@ out:
return cfqq;
}
+static struct cfq_io_context *
+cfq_cic_rb_lookup(struct cfq_data *cfqd, struct io_context *ioc)
+{
+ struct rb_node *n = ioc->cic_root.rb_node;
+ struct cfq_io_context *cic;
+ void *key = cfqd;
+
+ while (n) {
+ cic = rb_entry(n, struct cfq_io_context, rb_node);
+
+ if (key < cic->key)
+ n = n->rb_left;
+ else if (key > cic->key)
+ n = n->rb_right;
+ else
+ return cic;
+ }
+
+ return NULL;
+}
+
+static inline void
+cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
+ struct cfq_io_context *cic)
+{
+ struct rb_node **p = &ioc->cic_root.rb_node;
+ struct rb_node *parent = NULL;
+ struct cfq_io_context *__cic;
+
+ read_lock(&cfq_exit_lock);
+
+ cic->ioc = ioc;
+ cic->key = cfqd;
+
+ ioc->set_ioprio = cfq_ioc_set_ioprio;
+
+ while (*p) {
+ parent = *p;
+ __cic = rb_entry(parent, struct cfq_io_context, rb_node);
+
+ if (cic->key < __cic->key)
+ p = &(*p)->rb_left;
+ else if (cic->key > __cic->key)
+ p = &(*p)->rb_right;
+ else
+ BUG();
+ }
+
+ rb_link_node(&cic->rb_node, parent, p);
+ rb_insert_color(&cic->rb_node, &ioc->cic_root);
+ list_add(&cic->queue_list, &cfqd->cic_list);
+ read_unlock(&cfq_exit_lock);
+}
+
/*
* Setup general io context and cfq io context. There can be several cfq
* io contexts per general io context, if this process is doing io to more
- * than one device managed by cfq. Note that caller is holding a reference to
- * cfqq, so we don't need to worry about it disappearing
+ * than one device managed by cfq.
*/
static struct cfq_io_context *
-cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
+cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
{
struct io_context *ioc = NULL;
struct cfq_io_context *cic;
@@ -1463,88 +1543,15 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
if (!ioc)
return NULL;
-restart:
- if ((cic = ioc->cic) == NULL) {
- cic = cfq_alloc_io_context(cfqd, gfp_mask);
-
- if (cic == NULL)
- goto err;
-
- /*
- * manually increment generic io_context usage count, it
- * cannot go away since we are already holding one ref to it
- */
- cic->ioc = ioc;
- cic->key = cfqd;
- read_lock(&cfq_exit_lock);
- ioc->set_ioprio = cfq_ioc_set_ioprio;
- ioc->cic = cic;
- list_add(&cic->queue_list, &cfqd->cic_list);
- read_unlock(&cfq_exit_lock);
- } else {
- struct cfq_io_context *__cic;
-
- /*
- * the first cic on the list is actually the head itself
- */
- if (cic->key == cfqd)
- goto out;
-
- if (unlikely(!cic->key)) {
- read_lock(&cfq_exit_lock);
- if (list_empty(&cic->list))
- ioc->cic = NULL;
- else
- ioc->cic = list_entry(cic->list.next,
- struct cfq_io_context,
- list);
- read_unlock(&cfq_exit_lock);
- kmem_cache_free(cfq_ioc_pool, cic);
- atomic_dec(&ioc_count);
- goto restart;
- }
-
- /*
- * cic exists, check if we already are there. linear search
- * should be ok here, the list will usually not be more than
- * 1 or a few entries long
- */
- list_for_each_entry(__cic, &cic->list, list) {
- /*
- * this process is already holding a reference to
- * this queue, so no need to get one more
- */
- if (__cic->key == cfqd) {
- cic = __cic;
- goto out;
- }
- if (unlikely(!__cic->key)) {
- read_lock(&cfq_exit_lock);
- list_del(&__cic->list);
- read_unlock(&cfq_exit_lock);
- kmem_cache_free(cfq_ioc_pool, __cic);
- atomic_dec(&ioc_count);
- goto restart;
- }
- }
+ cic = cfq_cic_rb_lookup(cfqd, ioc);
+ if (cic)
+ goto out;
- /*
- * nope, process doesn't have a cic assoicated with this
- * cfqq yet. get a new one and add to list
- */
- __cic = cfq_alloc_io_context(cfqd, gfp_mask);
- if (__cic == NULL)
- goto err;
-
- __cic->ioc = ioc;
- __cic->key = cfqd;
- read_lock(&cfq_exit_lock);
- list_add(&__cic->list, &cic->list);
- list_add(&__cic->queue_list, &cfqd->cic_list);
- read_unlock(&cfq_exit_lock);
- cic = __cic;
- }
+ cic = cfq_alloc_io_context(cfqd, gfp_mask);
+ if (cic == NULL)
+ goto err;
+ cfq_cic_link(cfqd, ioc, cic);
out:
return cic;
err:
@@ -1577,7 +1584,33 @@ cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples;
}
-#define sample_valid(samples) ((samples) > 80)
+static void
+cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic,
+ struct cfq_rq *crq)
+{
+ sector_t sdist;
+ u64 total;
+
+ if (cic->last_request_pos < crq->request->sector)
+ sdist = crq->request->sector - cic->last_request_pos;
+ else
+ sdist = cic->last_request_pos - crq->request->sector;
+
+ /*
+ * Don't allow the seek distance to get too large from the
+ * odd fragment, pagein, etc
+ */
+ if (cic->seek_samples <= 60) /* second&third seek */
+ sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*1024);
+ else
+ sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*64);
+
+ cic->seek_samples = (7*cic->seek_samples + 256) / 8;
+ cic->seek_total = (7*cic->seek_total + (u64)256*sdist) / 8;
+ total = cic->seek_total + (cic->seek_samples/2);
+ do_div(total, cic->seek_samples);
+ cic->seek_mean = (sector_t)total;
+}
/*
* Disable idle window if the process thinks too long or seeks so much that
@@ -1690,9 +1723,11 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
cic = crq->io_context;
cfq_update_io_thinktime(cfqd, cic);
+ cfq_update_io_seektime(cfqd, cic, crq);
cfq_update_idle_window(cfqd, cfqq, cic);
cic->last_queue = jiffies;
+ cic->last_request_pos = crq->request->sector + crq->request->nr_sectors;
if (cfqq == cfqd->active_queue) {
/*
@@ -1825,14 +1860,6 @@ static void cfq_prio_boost(struct cfq_queue *cfqq)
cfq_resort_rr_list(cfqq, 0);
}
-static inline pid_t cfq_queue_pid(struct task_struct *task, int rw)
-{
- if (rw == READ || process_sync(task))
- return task->pid;
-
- return CFQ_KEY_ASYNC;
-}
-
static inline int
__cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq,
struct task_struct *task, int rw)
@@ -1965,7 +1992,7 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
might_sleep_if(gfp_mask & __GFP_WAIT);
- cic = cfq_get_io_context(cfqd, key, gfp_mask);
+ cic = cfq_get_io_context(cfqd, gfp_mask);
spin_lock_irqsave(q->queue_lock, flags);
@@ -2133,11 +2160,14 @@ static void cfq_exit_queue(elevator_t *e)
request_queue_t *q = cfqd->queue;
cfq_shutdown_timer_wq(cfqd);
+
write_lock(&cfq_exit_lock);
spin_lock_irq(q->queue_lock);
+
if (cfqd->active_queue)
__cfq_slice_expired(cfqd, cfqd->active_queue, 0);
- while(!list_empty(&cfqd->cic_list)) {
+
+ while (!list_empty(&cfqd->cic_list)) {
struct cfq_io_context *cic = list_entry(cfqd->cic_list.next,
struct cfq_io_context,
queue_list);
@@ -2152,6 +2182,7 @@ static void cfq_exit_queue(elevator_t *e)
cic->key = NULL;
list_del_init(&cic->queue_list);
}
+
spin_unlock_irq(q->queue_lock);
write_unlock(&cfq_exit_lock);
@@ -2191,7 +2222,7 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
if (!cfqd->cfq_hash)
goto out_cfqhash;
- cfqd->crq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, crq_pool);
+ cfqd->crq_pool = mempool_create_slab_pool(BLKDEV_MIN_RQ, crq_pool);
if (!cfqd->crq_pool)
goto out_crqpool;
@@ -2227,7 +2258,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
cfqd->cfq_slice[1] = cfq_slice_sync;
cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
cfqd->cfq_slice_idle = cfq_slice_idle;
- cfqd->cfq_max_depth = cfq_max_depth;
return 0;
out_crqpool:
@@ -2310,7 +2340,6 @@ SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1);
SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1);
SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1);
SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0);
-SHOW_FUNCTION(cfq_max_depth_show, cfqd->cfq_max_depth, 0);
#undef SHOW_FUNCTION
#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
@@ -2339,7 +2368,6 @@ STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1);
STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1);
STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1);
STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, 0);
-STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0);
#undef STORE_FUNCTION
#define CFQ_ATTR(name) \
@@ -2356,7 +2384,6 @@ static struct elv_fs_entry cfq_attrs[] = {
CFQ_ATTR(slice_async),
CFQ_ATTR(slice_async_rq),
CFQ_ATTR(slice_idle),
- CFQ_ATTR(max_depth),
__ATTR_NULL
};
diff --git a/block/elevator.c b/block/elevator.c
index 5e558c4689a..56c2ed06a9e 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -728,8 +728,7 @@ void elv_unregister_queue(struct request_queue *q)
int elv_register(struct elevator_type *e)
{
spin_lock_irq(&elv_list_lock);
- if (elevator_find(e->elevator_name))
- BUG();
+ BUG_ON(elevator_find(e->elevator_name));
list_add_tail(&e->list, &elv_list);
spin_unlock_irq(&elv_list_lock);
diff --git a/block/genhd.c b/block/genhd.c
index 64510fd8862..db4c60c802d 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -454,8 +454,8 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page)
disk_round_stats(disk);
preempt_enable();
return sprintf(page,
- "%8u %8u %8llu %8u "
- "%8u %8u %8llu %8u "
+ "%8lu %8lu %8llu %8u "
+ "%8lu %8lu %8llu %8u "
"%8u %8u %8u"
"\n",
disk_stat_read(disk, ios[READ]),
@@ -649,7 +649,7 @@ static int diskstats_show(struct seq_file *s, void *v)
preempt_disable();
disk_round_stats(gp);
preempt_enable();
- seq_printf(s, "%4d %4d %s %u %u %llu %u %u %u %llu %u %u %u %u\n",
+ seq_printf(s, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n",
gp->major, n + gp->first_minor, disk_name(gp, n, buf),
disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]),
(unsigned long long)disk_stat_read(gp, sectors[0]),
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 062067fa7ea..5b26af8597f 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -785,6 +785,8 @@ void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b)
t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments);
t->max_segment_size = min(t->max_segment_size,b->max_segment_size);
t->hardsect_size = max(t->hardsect_size,b->hardsect_size);
+ if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags))
+ clear_bit(QUEUE_FLAG_CLUSTER, &t->queue_flags);
}
EXPORT_SYMBOL(blk_queue_stack_limits);
@@ -906,17 +908,15 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
__FUNCTION__, depth);
}
- tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC);
+ tag_index = kzalloc(depth * sizeof(struct request *), GFP_ATOMIC);
if (!tag_index)
goto fail;
nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG;
- tag_map = kmalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC);
+ tag_map = kzalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC);
if (!tag_map)
goto fail;
- memset(tag_index, 0, depth * sizeof(struct request *));
- memset(tag_map, 0, nr_ulongs * sizeof(unsigned long));
tags->real_max_depth = depth;
tags->max_depth = depth;
tags->tag_index = tag_index;
@@ -2479,10 +2479,12 @@ void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk,
rq->rq_disk = bd_disk;
rq->flags |= REQ_NOMERGE;
rq->end_io = done;
- elv_add_request(q, rq, where, 1);
- generic_unplug_device(q);
+ WARN_ON(irqs_disabled());
+ spin_lock_irq(q->queue_lock);
+ __elv_add_request(q, rq, where, 1);
+ __generic_unplug_device(q);
+ spin_unlock_irq(q->queue_lock);
}
-
EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
/**
@@ -3512,7 +3514,7 @@ int __init blk_dev_init(void)
iocontext_cachep = kmem_cache_create("blkdev_ioc",
sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL);
- for_each_cpu(i)
+ for_each_possible_cpu(i)
INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i));
open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL);
@@ -3537,11 +3539,17 @@ void put_io_context(struct io_context *ioc)
BUG_ON(atomic_read(&ioc->refcount) == 0);
if (atomic_dec_and_test(&ioc->refcount)) {
+ struct cfq_io_context *cic;
+
rcu_read_lock();
if (ioc->aic && ioc->aic->dtor)
ioc->aic->dtor(ioc->aic);
- if (ioc->cic && ioc->cic->dtor)
- ioc->cic->dtor(ioc->cic);
+ if (ioc->cic_root.rb_node != NULL) {
+ struct rb_node *n = rb_first(&ioc->cic_root);
+
+ cic = rb_entry(n, struct cfq_io_context, rb_node);
+ cic->dtor(ioc);
+ }
rcu_read_unlock();
kmem_cache_free(iocontext_cachep, ioc);
@@ -3554,6 +3562,7 @@ void exit_io_context(void)
{
unsigned long flags;
struct io_context *ioc;
+ struct cfq_io_context *cic;
local_irq_save(flags);
task_lock(current);
@@ -3565,9 +3574,11 @@ void exit_io_context(void)
if (ioc->aic && ioc->aic->exit)
ioc->aic->exit(ioc->aic);
- if (ioc->cic && ioc->cic->exit)
- ioc->cic->exit(ioc->cic);
-
+ if (ioc->cic_root.rb_node != NULL) {
+ cic = rb_entry(rb_first(&ioc->cic_root), struct cfq_io_context, rb_node);
+ cic->exit(ioc);
+ }
+
put_io_context(ioc);
}
@@ -3596,7 +3607,7 @@ struct io_context *current_io_context(gfp_t gfp_flags)
ret->last_waited = jiffies; /* doesn't matter... */
ret->nr_batch_requests = 0; /* because this is 0 */
ret->aic = NULL;
- ret->cic = NULL;
+ ret->cic_root.rb_node = NULL;
tsk->io_context = ret;
}
diff --git a/drivers/Kconfig b/drivers/Kconfig
index bddf431bbb7..9f5c0da57c9 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -70,4 +70,6 @@ source "drivers/sn/Kconfig"
source "drivers/edac/Kconfig"
+source "drivers/rtc/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 5c69b86db62..424955274e6 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_USB_GADGET) += usb/gadget/
obj-$(CONFIG_GAMEPORT) += input/gameport/
obj-$(CONFIG_INPUT) += input/
obj-$(CONFIG_I2O) += message/
+obj-$(CONFIG_RTC_LIB) += rtc/
obj-$(CONFIG_I2C) += i2c/
obj-$(CONFIG_W1) += w1/
obj-$(CONFIG_HWMON) += hwmon/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 82710ae3922..5cb96300eb0 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -256,7 +256,8 @@ config ACPI_CUSTOM_DSDT_FILE
depends on ACPI_CUSTOM_DSDT
default ""
help
- Enter the full path name to the file wich includes the AmlCode declaration.
+ Enter the full path name to the file which includes the AmlCode
+ declaration.
config ACPI_BLACKLIST_YEAR
int "Disable ACPI for systems before Jan 1st this year" if X86_32
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 9824f679a91..f9c972b26f4 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -77,28 +77,13 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = {
static int __init blacklist_by_year(void)
{
- int year;
- char *s = dmi_get_system_info(DMI_BIOS_DATE);
-
- if (!s)
- return 0;
- if (!*s)
- return 0;
-
- s = strrchr(s, '/');
- if (!s)
+ int year = dmi_get_year(DMI_BIOS_DATE);
+ /* Doesn't exist? Likely an old system */
+ if (year == -1)
+ return 1;
+ /* 0? Likely a buggy new BIOS */
+ if (year == 0)
return 0;
-
- s += 1;
-
- year = simple_strtoul(s, NULL, 0);
-
- if (year < 100) { /* 2-digit year */
- year += 1900;
- if (year < 1996) /* no dates < spec 1.0 */
- year += 100;
- }
-
if (year < CONFIG_ACPI_BLACKLIST_YEAR) {
printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), "
"acpi=force is required to enable ACPI\n",
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index ac5bbaedac1..13b5fd5854a 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -156,12 +156,10 @@ acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
{
if (efi_enabled) {
addr->pointer_type = ACPI_PHYSICAL_POINTER;
- if (efi.acpi20)
- addr->pointer.physical =
- (acpi_physical_address) virt_to_phys(efi.acpi20);
- else if (efi.acpi)
- addr->pointer.physical =
- (acpi_physical_address) virt_to_phys(efi.acpi);
+ if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
+ addr->pointer.physical = efi.acpi20;
+ else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
+ addr->pointer.physical = efi.acpi;
else {
printk(KERN_ERR PREFIX
"System description tables not found\n");
@@ -182,22 +180,14 @@ acpi_status
acpi_os_map_memory(acpi_physical_address phys, acpi_size size,
void __iomem ** virt)
{
- if (efi_enabled) {
- if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
- *virt = (void __iomem *)phys_to_virt(phys);
- } else {
- *virt = ioremap(phys, size);
- }
- } else {
- if (phys > ULONG_MAX) {
- printk(KERN_ERR PREFIX "Cannot map memory that high\n");
- return AE_BAD_PARAMETER;
- }
- /*
- * ioremap checks to ensure this is in reserved space
- */
- *virt = ioremap((unsigned long)phys, size);
+ if (phys > ULONG_MAX) {
+ printk(KERN_ERR PREFIX "Cannot map memory that high\n");
+ return AE_BAD_PARAMETER;
}
+ /*
+ * ioremap checks to ensure this is in reserved space
+ */
+ *virt = ioremap((unsigned long)phys, size);
if (!*virt)
return AE_NO_MEMORY;
@@ -409,18 +399,8 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
{
u32 dummy;
void __iomem *virt_addr;
- int iomem = 0;
- if (efi_enabled) {
- if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
- /* HACK ALERT! We can use readb/w/l on real memory too.. */
- virt_addr = (void __iomem *)phys_to_virt(phys_addr);
- } else {
- iomem = 1;
- virt_addr = ioremap(phys_addr, width);
- }
- } else
- virt_addr = (void __iomem *)phys_to_virt(phys_addr);
+ virt_addr = ioremap(phys_addr, width);
if (!value)
value = &dummy;
@@ -438,10 +418,7 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
BUG();
}
- if (efi_enabled) {
- if (iomem)
- iounmap(virt_addr);
- }
+ iounmap(virt_addr);
return AE_OK;
}
@@ -450,18 +427,8 @@ acpi_status
acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
{
void __iomem *virt_addr;
- int iomem = 0;
- if (efi_enabled) {
- if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
- /* HACK ALERT! We can use writeb/w/l on real memory too */
- virt_addr = (void __iomem *)phys_to_virt(phys_addr);
- } else {
- iomem = 1;
- virt_addr = ioremap(phys_addr, width);
- }
- } else
- virt_addr = (void __iomem *)phys_to_virt(phys_addr);
+ virt_addr = ioremap(phys_addr, width);
switch (width) {
case 8:
@@ -477,8 +444,7 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
BUG();
}
- if (iomem)
- iounmap(virt_addr);
+ iounmap(virt_addr);
return AE_OK;
}
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 99a3a28594d..713b763884a 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -246,7 +246,7 @@ static int acpi_processor_errata(struct acpi_processor *pr)
}
/* --------------------------------------------------------------------------
- Common ACPI processor fucntions
+ Common ACPI processor functions
-------------------------------------------------------------------------- */
/*
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index eb730a80952..80fa43471f4 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -878,12 +878,9 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
unsigned int working = 0;
#ifdef ARCH_APICTIMER_STOPS_ON_C3
- struct cpuinfo_x86 *c = cpu_data + pr->id;
+ int timer_broadcast = 0;
cpumask_t mask = cpumask_of_cpu(pr->id);
-
- if (c->x86_vendor == X86_VENDOR_INTEL) {
- on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
- }
+ on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
#endif
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
@@ -896,15 +893,20 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
case ACPI_STATE_C2:
acpi_processor_power_verify_c2(cx);
+#ifdef ARCH_APICTIMER_STOPS_ON_C3
+ /* Some AMD systems fake C3 as C2, but still
+ have timer troubles */
+ if (cx->valid &&
+ boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+ timer_broadcast++;
+#endif
break;
case ACPI_STATE_C3:
acpi_processor_power_verify_c3(pr, cx);
#ifdef ARCH_APICTIMER_STOPS_ON_C3
- if (cx->valid && c->x86_vendor == X86_VENDOR_INTEL) {
- on_each_cpu(switch_APIC_timer_to_ipi,
- &mask, 1, 1);
- }
+ if (cx->valid)
+ timer_broadcast++;
#endif
break;
}
@@ -913,6 +915,11 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
working++;
}
+#ifdef ARCH_APICTIMER_STOPS_ON_C3
+ if (timer_broadcast)
+ on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1);
+#endif
+
return (working);
}
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 31d4f3ffc26..7f37c7cc5ef 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -587,7 +587,8 @@ int __init acpi_table_init(void)
return -ENODEV;
}
- rsdp = (struct acpi_table_rsdp *)__va(rsdp_phys);
+ rsdp = (struct acpi_table_rsdp *)__acpi_map_table(rsdp_phys,
+ sizeof(struct acpi_table_rsdp));
if (!rsdp) {
printk(KERN_WARNING PREFIX "Unable to map RSDP\n");
return -ENODEV;
diff --git a/drivers/atm/.gitignore b/drivers/atm/.gitignore
new file mode 100644
index 00000000000..a165b716771
--- /dev/null
+++ b/drivers/atm/.gitignore
@@ -0,0 +1,5 @@
+# Ignore generated files
+fore200e_mkfirm
+fore200e_pca_fw.c
+pca200e.bin
+
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index 69f4c7ce9a6..cac09e353be 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -1972,7 +1972,7 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai)
"(itf %d): No suitable DMA available.\n", lanai->number);
return -EBUSY;
}
- if (pci_set_consistent_dma_mask(pci, 0xFFFFFFFF) != 0) {
+ if (pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) != 0) {
printk(KERN_WARNING DEV_LABEL
"(itf %d): No suitable DMA available.\n", lanai->number);
return -EBUSY;
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 29f3d7504da..dd712b24ec9 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -19,11 +19,6 @@ EXPORT_SYMBOL(cpu_sysdev_class);
static struct sys_device *cpu_sys_devices[NR_CPUS];
#ifdef CONFIG_HOTPLUG_CPU
-int __attribute__((weak)) smp_prepare_cpu (int cpu)
-{
- return 0;
-}
-
static ssize_t show_online(struct sys_device *dev, char *buf)
{
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
@@ -44,9 +39,7 @@ static ssize_t store_online(struct sys_device *dev, const char *buf,
kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
break;
case '1':
- ret = smp_prepare_cpu(cpu->sysdev.id);
- if (!ret)
- ret = cpu_up(cpu->sysdev.id);
+ ret = cpu_up(cpu->sysdev.id);
if (!ret)
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
break;
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 105a0d61eb1..dd547af4681 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -47,16 +47,16 @@ static struct kset_uevent_ops memory_uevent_ops = {
.uevent = memory_uevent,
};
-static struct notifier_block *memory_chain;
+static BLOCKING_NOTIFIER_HEAD(memory_chain);
int register_memory_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&memory_chain, nb);
+ return blocking_notifier_chain_register(&memory_chain, nb);
}
void unregister_memory_notifier(struct notifier_block *nb)
{
- notifier_chain_unregister(&memory_chain, nb);
+ blocking_notifier_chain_unregister(&memory_chain, nb);
}
/*
@@ -140,7 +140,7 @@ static ssize_t show_mem_state(struct sys_device *dev, char *buf)
static inline int memory_notify(unsigned long val, void *v)
{
- return notifier_call_chain(&memory_chain, val, v);
+ return blocking_notifier_call_chain(&memory_chain, val, v);
}
/*
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 37b8cda3e8b..45bcda54488 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -41,6 +41,7 @@
#include <linux/timer.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
#include <linux/random.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -228,8 +229,7 @@ static void *slice_dma_loaf(struct dma_loaf *loaf, size_t len,
void *cpu_end = loaf->cpu_free + len;
void *cpu_addr = loaf->cpu_free;
- if (cpu_end > loaf->cpu_base + loaf->length)
- BUG();
+ BUG_ON(cpu_end > loaf->cpu_base + loaf->length);
*dma_handle = loaf->dma_free;
loaf->cpu_free = cpu_end;
loaf->dma_free += len;
@@ -312,11 +312,10 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
CommandsRemaining = CommandAllocationGroupSize;
CommandGroupByteCount =
CommandsRemaining * CommandAllocationLength;
- AllocationPointer = kmalloc(CommandGroupByteCount, GFP_ATOMIC);
+ AllocationPointer = kzalloc(CommandGroupByteCount, GFP_ATOMIC);
if (AllocationPointer == NULL)
return DAC960_Failure(Controller,
"AUXILIARY STRUCTURE CREATION");
- memset(AllocationPointer, 0, CommandGroupByteCount);
}
Command = (DAC960_Command_T *) AllocationPointer;
AllocationPointer += CommandAllocationLength;
@@ -2710,14 +2709,12 @@ DAC960_DetectController(struct pci_dev *PCI_Device,
void __iomem *BaseAddress;
int i;
- Controller = (DAC960_Controller_T *)
- kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
+ Controller = kzalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
if (Controller == NULL) {
DAC960_Error("Unable to allocate Controller structure for "
"Controller at\n", NULL);
return NULL;
}
- memset(Controller, 0, sizeof(DAC960_Controller_T));
Controller->ControllerNumber = DAC960_ControllerCount;
DAC960_Controllers[DAC960_ControllerCount++] = Controller;
Controller->Bus = PCI_Device->bus->number;
@@ -3658,8 +3655,8 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
(NewEnquiry->EventLogSequenceNumber !=
OldEnquiry->EventLogSequenceNumber) ||
Controller->MonitoringTimerCount == 0 ||
- (jiffies - Controller->SecondaryMonitoringTime
- >= DAC960_SecondaryMonitoringInterval))
+ time_after_eq(jiffies, Controller->SecondaryMonitoringTime
+ + DAC960_SecondaryMonitoringInterval))
{
Controller->V1.NeedLogicalDriveInformation = true;
Controller->V1.NewEventLogSequenceNumber =
@@ -5644,8 +5641,8 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
unsigned int StatusChangeCounter =
Controller->V2.HealthStatusBuffer->StatusChangeCounter;
boolean ForceMonitoringCommand = false;
- if (jiffies - Controller->SecondaryMonitoringTime
- > DAC960_SecondaryMonitoringInterval)
+ if (time_after(jiffies, Controller->SecondaryMonitoringTime
+ + DAC960_SecondaryMonitoringInterval))
{
int LogicalDriveNumber;
for (LogicalDriveNumber = 0;
@@ -5673,8 +5670,8 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
ControllerInfo->ConsistencyChecksActive +
ControllerInfo->RebuildsActive +
ControllerInfo->OnlineExpansionsActive == 0 ||
- jiffies - Controller->PrimaryMonitoringTime
- < DAC960_MonitoringTimerInterval) &&
+ time_before(jiffies, Controller->PrimaryMonitoringTime
+ + DAC960_MonitoringTimerInterval)) &&
!ForceMonitoringCommand)
{
Controller->MonitoringTimer.expires =
@@ -5811,8 +5808,8 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel,
Controller->ProgressBufferLength = Length;
if (Controller->EphemeralProgressMessage)
{
- if (jiffies - Controller->LastProgressReportTime
- >= DAC960_ProgressReportingInterval)
+ if (time_after_eq(jiffies, Controller->LastProgressReportTime
+ + DAC960_ProgressReportingInterval))
{
printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
Controller->ControllerNumber, Buffer);
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 8b133167740..ae0949b3394 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -383,8 +383,9 @@ config BLK_DEV_RAM
thus say N here.
config BLK_DEV_RAM_COUNT
- int "Default number of RAM disks" if BLK_DEV_RAM
+ int "Default number of RAM disks"
default "16"
+ depends on BLK_DEV_RAM
help
The default value is 16 RAM disks. Change this if you know what
are doing. If you boot from a filesystem that needs to be extracted
@@ -400,14 +401,16 @@ config BLK_DEV_RAM_SIZE
8192.
config BLK_DEV_INITRD
- bool "Initial RAM disk (initrd) support"
- depends on BLK_DEV_RAM=y
+ bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support"
help
- The initial RAM disk is a RAM disk that is loaded by the boot loader
- (loadlin or lilo) and that is mounted as root before the normal boot
- procedure. It is typically used to load modules needed to mount the
- "real" root file system, etc. See <file:Documentation/initrd.txt>
- for details.
+ The initial RAM filesystem is a ramfs which is loaded by the
+ boot loader (loadlin or lilo) and that is mounted as root
+ before the normal boot procedure. It is typically used to
+ load modules needed to mount the "real" root file system,
+ etc. See <file:Documentation/initrd.txt> for details.
+
+ If RAM disk support (BLK_DEV_RAM) is also included, this
+ also enables initial RAM disk (initrd) support.
config CDROM_PKTCDVD
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index a5c1c8e871e..4cb9c133628 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -369,8 +369,6 @@ static ssize_t slm_read( struct file *file, char *buf, size_t count,
int length;
int end;
- if (count < 0)
- return( -EINVAL );
if (!(page = __get_free_page( GFP_KERNEL )))
return( -ENOMEM );
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index 881c48d941b..6eebcb7be97 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,5 +1,5 @@
/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
-#define VERSION "14"
+#define VERSION "22"
#define AOE_MAJOR 152
#define DEVICE_NAME "aoe"
@@ -75,8 +75,9 @@ enum {
DEVFL_TKILL = (1<<1), /* flag for timer to know when to kill self */
DEVFL_EXT = (1<<2), /* device accepts lba48 commands */
DEVFL_CLOSEWAIT = (1<<3), /* device is waiting for all closes to revalidate */
- DEVFL_WC_UPDATE = (1<<4), /* this device needs to update write cache status */
- DEVFL_WORKON = (1<<4),
+ DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */
+ DEVFL_PAUSE = (1<<5),
+ DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */
BUFFL_FAIL = 1,
};
@@ -152,16 +153,17 @@ void aoechr_exit(void);
void aoechr_error(char *);
void aoecmd_work(struct aoedev *d);
-void aoecmd_cfg(ushort, unsigned char);
+void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor);
void aoecmd_ata_rsp(struct sk_buff *);
void aoecmd_cfg_rsp(struct sk_buff *);
+void aoecmd_sleepwork(void *vp);
int aoedev_init(void);
void aoedev_exit(void);
struct aoedev *aoedev_by_aoeaddr(int maj, int min);
+struct aoedev *aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt);
void aoedev_downdev(struct aoedev *d);
-struct aoedev *aoedev_set(ulong, unsigned char *, struct net_device *, ulong);
-int aoedev_busy(void);
+int aoedev_isbusy(struct aoedev *d);
int aoenet_init(void);
void aoenet_exit(void);
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index c05ee8bffd9..393b86a3dbf 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -22,7 +22,9 @@ static ssize_t aoedisk_show_state(struct gendisk * disk, char *page)
return snprintf(page, PAGE_SIZE,
"%s%s\n",
(d->flags & DEVFL_UP) ? "up" : "down",
- (d->flags & DEVFL_CLOSEWAIT) ? ",closewait" : "");
+ (d->flags & DEVFL_PAUSE) ? ",paused" :
+ (d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : "");
+ /* I'd rather see nopen exported so we can ditch closewait */
}
static ssize_t aoedisk_show_mac(struct gendisk * disk, char *page)
{
@@ -107,8 +109,7 @@ aoeblk_release(struct inode *inode, struct file *filp)
spin_lock_irqsave(&d->lock, flags);
- if (--d->nopen == 0 && (d->flags & DEVFL_CLOSEWAIT)) {
- d->flags &= ~DEVFL_CLOSEWAIT;
+ if (--d->nopen == 0) {
spin_unlock_irqrestore(&d->lock, flags);
aoecmd_cfg(d->aoemajor, d->aoeminor);
return 0;
@@ -158,14 +159,14 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio)
}
list_add_tail(&buf->bufs, &d->bufq);
- aoecmd_work(d);
+ aoecmd_work(d);
sl = d->sendq_hd;
d->sendq_hd = d->sendq_tl = NULL;
spin_unlock_irqrestore(&d->lock, flags);
-
aoenet_xmit(sl);
+
return 0;
}
@@ -205,20 +206,18 @@ aoeblk_gdalloc(void *vp)
printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate disk "
"structure for %ld.%ld\n", d->aoemajor, d->aoeminor);
spin_lock_irqsave(&d->lock, flags);
- d->flags &= ~DEVFL_WORKON;
+ d->flags &= ~DEVFL_GDALLOC;
spin_unlock_irqrestore(&d->lock, flags);
return;
}
- d->bufpool = mempool_create(MIN_BUFS,
- mempool_alloc_slab, mempool_free_slab,
- buf_pool_cache);
+ d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache);
if (d->bufpool == NULL) {
printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate bufpool "
"for %ld.%ld\n", d->aoemajor, d->aoeminor);
put_disk(gd);
spin_lock_irqsave(&d->lock, flags);
- d->flags &= ~DEVFL_WORKON;
+ d->flags &= ~DEVFL_GDALLOC;
spin_unlock_irqrestore(&d->lock, flags);
return;
}
@@ -235,18 +234,13 @@ aoeblk_gdalloc(void *vp)
gd->queue = &d->blkq;
d->gd = gd;
- d->flags &= ~DEVFL_WORKON;
+ d->flags &= ~DEVFL_GDALLOC;
d->flags |= DEVFL_UP;
spin_unlock_irqrestore(&d->lock, flags);
add_disk(gd);
aoedisk_add_sysfs(d);
-
- printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu "
- "sectors\n", (unsigned long long)mac_addr(d->addr),
- d->aoemajor, d->aoeminor,
- d->fw_ver, (long long)d->ssize);
}
void
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 41ae0ede619..5327f553b4f 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -13,6 +13,7 @@ enum {
MINOR_ERR = 2,
MINOR_DISCOVER,
MINOR_INTERFACES,
+ MINOR_REVALIDATE,
MSGSZ = 2048,
NARGS = 10,
NMSG = 100, /* message backlog to retain */
@@ -41,6 +42,7 @@ static struct aoe_chardev chardevs[] = {
{ MINOR_ERR, "err" },
{ MINOR_DISCOVER, "discover" },
{ MINOR_INTERFACES, "interfaces" },
+ { MINOR_REVALIDATE, "revalidate" },
};
static int
@@ -62,6 +64,39 @@ interfaces(const char __user *str, size_t size)
return 0;
}
+static int
+revalidate(const char __user *str, size_t size)
+{
+ int major, minor, n;
+ ulong flags;
+ struct aoedev *d;
+ char buf[16];
+
+ if (size >= sizeof buf)
+ return -EINVAL;
+ buf[sizeof buf - 1] = '\0';
+ if (copy_from_user(buf, str, size))
+ return -EFAULT;
+
+ /* should be e%d.%d format */
+ n = sscanf(buf, "e%d.%d", &major, &minor);
+ if (n != 2) {
+ printk(KERN_ERR "aoe: %s: invalid device specification\n",
+ __FUNCTION__);
+ return -EINVAL;
+ }
+ d = aoedev_by_aoeaddr(major, minor);
+ if (!d)
+ return -EINVAL;
+
+ spin_lock_irqsave(&d->lock, flags);
+ d->flags |= DEVFL_PAUSE;
+ spin_unlock_irqrestore(&d->lock, flags);
+ aoecmd_cfg(major, minor);
+
+ return 0;
+}
+
void
aoechr_error(char *msg)
{
@@ -114,6 +149,8 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp
case MINOR_INTERFACES:
ret = interfaces(buf, cnt);
break;
+ case MINOR_REVALIDATE:
+ ret = revalidate(buf, cnt);
}
if (ret == 0)
ret = cnt;
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 326ca3876b6..39da28d344f 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -8,6 +8,7 @@
#include <linux/blkdev.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
+#include <linux/genhd.h>
#include <asm/unaligned.h>
#include "aoe.h"
@@ -28,6 +29,7 @@ new_skb(struct net_device *if_dev, ulong len)
skb->protocol = __constant_htons(ETH_P_AOE);
skb->priority = 0;
skb_put(skb, len);
+ memset(skb->head, 0, len);
skb->next = skb->prev = NULL;
/* tell the network layer not to perform IP checksums
@@ -188,12 +190,67 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
}
}
+/* some callers cannot sleep, and they can call this function,
+ * transmitting the packets later, when interrupts are on
+ */
+static struct sk_buff *
+aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
+{
+ struct aoe_hdr *h;
+ struct aoe_cfghdr *ch;
+ struct sk_buff *skb, *sl, *sl_tail;
+ struct net_device *ifp;
+
+ sl = sl_tail = NULL;
+
+ read_lock(&dev_base_lock);
+ for (ifp = dev_base; ifp; dev_put(ifp), ifp = ifp->next) {
+ dev_hold(ifp);
+ if (!is_aoe_netif(ifp))
+ continue;
+
+ skb = new_skb(ifp, sizeof *h + sizeof *ch);
+ if (skb == NULL) {
+ printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n");
+ continue;
+ }
+ if (sl_tail == NULL)
+ sl_tail = skb;
+ h = (struct aoe_hdr *) skb->mac.raw;
+ memset(h, 0, sizeof *h + sizeof *ch);
+
+ memset(h->dst, 0xff, sizeof h->dst);
+ memcpy(h->src, ifp->dev_addr, sizeof h->src);
+ h->type = __constant_cpu_to_be16(ETH_P_AOE);
+ h->verfl = AOE_HVER;
+ h->major = cpu_to_be16(aoemajor);
+ h->minor = aoeminor;
+ h->cmd = AOECMD_CFG;
+
+ skb->next = sl;
+ sl = skb;
+ }
+ read_unlock(&dev_base_lock);
+
+ if (tail != NULL)
+ *tail = sl_tail;
+ return sl;
+}
+
/* enters with d->lock held */
void
aoecmd_work(struct aoedev *d)
{
struct frame *f;
struct buf *buf;
+
+ if (d->flags & DEVFL_PAUSE) {
+ if (!aoedev_isbusy(d))
+ d->sendq_hd = aoecmd_cfg_pkts(d->aoemajor,
+ d->aoeminor, &d->sendq_tl);
+ return;
+ }
+
loop:
f = getframe(d, FREETAG);
if (f == NULL)
@@ -229,6 +286,8 @@ rexmit(struct aoedev *d, struct frame *f)
h = (struct aoe_hdr *) f->data;
f->tag = n;
h->tag = cpu_to_be32(n);
+ memcpy(h->dst, d->addr, sizeof h->dst);
+ memcpy(h->src, d->ifp->dev_addr, sizeof h->src);
skb = skb_prepare(d, f);
if (skb) {
@@ -272,7 +331,7 @@ rexmit_timer(ulong vp)
spin_lock_irqsave(&d->lock, flags);
if (d->flags & DEVFL_TKILL) {
-tdie: spin_unlock_irqrestore(&d->lock, flags);
+ spin_unlock_irqrestore(&d->lock, flags);
return;
}
f = d->frames;
@@ -283,7 +342,7 @@ tdie: spin_unlock_irqrestore(&d->lock, flags);
n /= HZ;
if (n > MAXWAIT) { /* waited too long. device failure. */
aoedev_downdev(d);
- goto tdie;
+ break;
}
rexmit(d, f);
}
@@ -305,6 +364,37 @@ tdie: spin_unlock_irqrestore(&d->lock, flags);
aoenet_xmit(sl);
}
+/* this function performs work that has been deferred until sleeping is OK
+ */
+void
+aoecmd_sleepwork(void *vp)
+{
+ struct aoedev *d = (struct aoedev *) vp;
+
+ if (d->flags & DEVFL_GDALLOC)
+ aoeblk_gdalloc(d);
+
+ if (d->flags & DEVFL_NEWSIZE) {
+ struct block_device *bd;
+ unsigned long flags;
+ u64 ssize;
+
+ ssize = d->gd->capacity;
+ bd = bdget_disk(d->gd, 0);
+
+ if (bd) {
+ mutex_lock(&bd->bd_inode->i_mutex);
+ i_size_write(bd->bd_inode, (loff_t)ssize<<9);
+ mutex_unlock(&bd->bd_inode->i_mutex);
+ bdput(bd);
+ }
+ spin_lock_irqsave(&d->lock, flags);
+ d->flags |= DEVFL_UP;
+ d->flags &= ~DEVFL_NEWSIZE;
+ spin_unlock_irqrestore(&d->lock, flags);
+ }
+}
+
static void
ataid_complete(struct aoedev *d, unsigned char *id)
{
@@ -339,21 +429,29 @@ ataid_complete(struct aoedev *d, unsigned char *id)
d->geo.heads = le16_to_cpu(get_unaligned((__le16 *) &id[55<<1]));
d->geo.sectors = le16_to_cpu(get_unaligned((__le16 *) &id[56<<1]));
}
+
+ if (d->ssize != ssize)
+ printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu "
+ "sectors\n", (unsigned long long)mac_addr(d->addr),
+ d->aoemajor, d->aoeminor,
+ d->fw_ver, (long long)ssize);
d->ssize = ssize;
d->geo.start = 0;
if (d->gd != NULL) {
d->gd->capacity = ssize;
- d->flags |= DEVFL_UP;
- return;
- }
- if (d->flags & DEVFL_WORKON) {
- printk(KERN_INFO "aoe: ataid_complete: can't schedule work, it's already on! "
- "(This really shouldn't happen).\n");
- return;
+ d->flags |= DEVFL_NEWSIZE;
+ } else {
+ if (d->flags & DEVFL_GDALLOC) {
+ printk(KERN_INFO "aoe: %s: %s e%lu.%lu, %s\n",
+ __FUNCTION__,
+ "can't schedule work for",
+ d->aoemajor, d->aoeminor,
+ "it's already on! (This really shouldn't happen).\n");
+ return;
+ }
+ d->flags |= DEVFL_GDALLOC;
}
- INIT_WORK(&d->work, aoeblk_gdalloc, d);
schedule_work(&d->work);
- d->flags |= DEVFL_WORKON;
}
static void
@@ -419,6 +517,8 @@ aoecmd_ata_rsp(struct sk_buff *skb)
ahout = (struct aoe_atahdr *) (f->data + sizeof(struct aoe_hdr));
buf = f->buf;
+ if (ahout->cmdstat == WIN_IDENTIFY)
+ d->flags &= ~DEVFL_PAUSE;
if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */
printk(KERN_CRIT "aoe: aoecmd_ata_rsp: ata error cmd=%2.2Xh "
"stat=%2.2Xh from e%ld.%ld\n",
@@ -451,7 +551,6 @@ aoecmd_ata_rsp(struct sk_buff *skb)
return;
}
ataid_complete(d, (char *) (ahin+1));
- /* d->flags |= DEVFL_WC_UPDATE; */
break;
default:
printk(KERN_INFO "aoe: aoecmd_ata_rsp: unrecognized "
@@ -484,51 +583,19 @@ aoecmd_ata_rsp(struct sk_buff *skb)
f->tag = FREETAG;
aoecmd_work(d);
-
sl = d->sendq_hd;
d->sendq_hd = d->sendq_tl = NULL;
spin_unlock_irqrestore(&d->lock, flags);
-
aoenet_xmit(sl);
}
void
aoecmd_cfg(ushort aoemajor, unsigned char aoeminor)
{
- struct aoe_hdr *h;
- struct aoe_cfghdr *ch;
- struct sk_buff *skb, *sl;
- struct net_device *ifp;
-
- sl = NULL;
-
- read_lock(&dev_base_lock);
- for (ifp = dev_base; ifp; dev_put(ifp), ifp = ifp->next) {
- dev_hold(ifp);
- if (!is_aoe_netif(ifp))
- continue;
-
- skb = new_skb(ifp, sizeof *h + sizeof *ch);
- if (skb == NULL) {
- printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n");
- continue;
- }
- h = (struct aoe_hdr *) skb->mac.raw;
- memset(h, 0, sizeof *h + sizeof *ch);
-
- memset(h->dst, 0xff, sizeof h->dst);
- memcpy(h->src, ifp->dev_addr, sizeof h->src);
- h->type = __constant_cpu_to_be16(ETH_P_AOE);
- h->verfl = AOE_HVER;
- h->major = cpu_to_be16(aoemajor);
- h->minor = aoeminor;
- h->cmd = AOECMD_CFG;
+ struct sk_buff *sl;
- skb->next = sl;
- sl = skb;
- }
- read_unlock(&dev_base_lock);
+ sl = aoecmd_cfg_pkts(aoemajor, aoeminor, NULL);
aoenet_xmit(sl);
}
@@ -561,9 +628,6 @@ aoecmd_ata_id(struct aoedev *d)
f->waited = 0;
f->writedatalen = 0;
- /* this message initializes the device, so we reset the rttavg */
- d->rttavg = MAXTIMER;
-
/* set up ata header */
ah->scnt = 1;
ah->cmdstat = WIN_IDENTIFY;
@@ -571,12 +635,8 @@ aoecmd_ata_id(struct aoedev *d)
skb = skb_prepare(d, f);
- /* we now want to start the rexmit tracking */
- d->flags &= ~DEVFL_TKILL;
- d->timer.data = (ulong) d;
+ d->rttavg = MAXTIMER;
d->timer.function = rexmit_timer;
- d->timer.expires = jiffies + TIMERTICK;
- add_timer(&d->timer);
return skb;
}
@@ -590,7 +650,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
ulong flags, sysminor, aoemajor;
u16 bufcnt;
struct sk_buff *sl;
- enum { MAXFRAMES = 8 };
+ enum { MAXFRAMES = 16 };
h = (struct aoe_hdr *) skb->mac.raw;
ch = (struct aoe_cfghdr *) (h+1);
@@ -618,23 +678,28 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
if (bufcnt > MAXFRAMES) /* keep it reasonable */
bufcnt = MAXFRAMES;
- d = aoedev_set(sysminor, h->src, skb->dev, bufcnt);
+ d = aoedev_by_sysminor_m(sysminor, bufcnt);
if (d == NULL) {
- printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device set failure\n");
+ printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n");
return;
}
spin_lock_irqsave(&d->lock, flags);
- if (d->flags & (DEVFL_UP | DEVFL_CLOSEWAIT)) {
+ /* permit device to migrate mac and network interface */
+ d->ifp = skb->dev;
+ memcpy(d->addr, h->src, sizeof d->addr);
+
+ /* don't change users' perspective */
+ if (d->nopen && !(d->flags & DEVFL_PAUSE)) {
spin_unlock_irqrestore(&d->lock, flags);
return;
}
-
+ d->flags |= DEVFL_PAUSE; /* force pause */
d->fw_ver = be16_to_cpu(ch->fwver);
- /* we get here only if the device is new */
- sl = aoecmd_ata_id(d);
+ /* check for already outstanding ataid */
+ sl = aoedev_isbusy(d) == 0 ? aoecmd_ata_id(d) : NULL;
spin_unlock_irqrestore(&d->lock, flags);
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index ded33ba31ac..ed4258a62df 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -12,6 +12,24 @@
static struct aoedev *devlist;
static spinlock_t devlist_lock;
+int
+aoedev_isbusy(struct aoedev *d)
+{
+ struct frame *f, *e;
+
+ f = d->frames;
+ e = f + d->nframes;
+ do {
+ if (f->tag != FREETAG) {
+ printk(KERN_DEBUG "aoe: %ld.%ld isbusy\n",
+ d->aoemajor, d->aoeminor);
+ return 1;
+ }
+ } while (++f < e);
+
+ return 0;
+}
+
struct aoedev *
aoedev_by_aoeaddr(int maj, int min)
{
@@ -28,6 +46,18 @@ aoedev_by_aoeaddr(int maj, int min)
return d;
}
+static void
+dummy_timer(ulong vp)
+{
+ struct aoedev *d;
+
+ d = (struct aoedev *)vp;
+ if (d->flags & DEVFL_TKILL)
+ return;
+ d->timer.expires = jiffies + HZ;
+ add_timer(&d->timer);
+}
+
/* called with devlist lock held */
static struct aoedev *
aoedev_newdev(ulong nframes)
@@ -44,6 +74,8 @@ aoedev_newdev(ulong nframes)
return NULL;
}
+ INIT_WORK(&d->work, aoecmd_sleepwork, d);
+
d->nframes = nframes;
d->frames = f;
e = f + nframes;
@@ -52,6 +84,10 @@ aoedev_newdev(ulong nframes)
spin_lock_init(&d->lock);
init_timer(&d->timer);
+ d->timer.data = (ulong) d;
+ d->timer.function = dummy_timer;
+ d->timer.expires = jiffies + HZ;
+ add_timer(&d->timer);
d->bufpool = NULL; /* defer to aoeblk_gdalloc */
INIT_LIST_HEAD(&d->bufq);
d->next = devlist;
@@ -67,9 +103,6 @@ aoedev_downdev(struct aoedev *d)
struct buf *buf;
struct bio *bio;
- d->flags |= DEVFL_TKILL;
- del_timer(&d->timer);
-
f = d->frames;
e = f + d->nframes;
for (; f<e; f->tag = FREETAG, f->buf = NULL, f++) {
@@ -92,16 +125,15 @@ aoedev_downdev(struct aoedev *d)
bio_endio(bio, bio->bi_size, -EIO);
}
- if (d->nopen)
- d->flags |= DEVFL_CLOSEWAIT;
if (d->gd)
d->gd->capacity = 0;
- d->flags &= ~DEVFL_UP;
+ d->flags &= ~(DEVFL_UP | DEVFL_PAUSE);
}
+/* find it or malloc it */
struct aoedev *
-aoedev_set(ulong sysminor, unsigned char *addr, struct net_device *ifp, ulong bufcnt)
+aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt)
{
struct aoedev *d;
ulong flags;
@@ -112,25 +144,19 @@ aoedev_set(ulong sysminor, unsigned char *addr, struct net_device *ifp, ulong bu
if (d->sysminor == sysminor)
break;
- if (d == NULL && (d = aoedev_newdev(bufcnt)) == NULL) {
- spin_unlock_irqrestore(&devlist_lock, flags);
- printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n");
- return NULL;
- } /* if newdev, (d->flags & DEVFL_UP) == 0 for below */
-
- spin_unlock_irqrestore(&devlist_lock, flags);
- spin_lock_irqsave(&d->lock, flags);
-
- d->ifp = ifp;
- memcpy(d->addr, addr, sizeof d->addr);
- if ((d->flags & DEVFL_UP) == 0) {
- aoedev_downdev(d); /* flushes outstanding frames */
+ if (d == NULL) {
+ d = aoedev_newdev(bufcnt);
+ if (d == NULL) {
+ spin_unlock_irqrestore(&devlist_lock, flags);
+ printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n");
+ return NULL;
+ }
d->sysminor = sysminor;
d->aoemajor = AOEMAJOR(sysminor);
d->aoeminor = AOEMINOR(sysminor);
}
- spin_unlock_irqrestore(&d->lock, flags);
+ spin_unlock_irqrestore(&devlist_lock, flags);
return d;
}
@@ -161,6 +187,7 @@ aoedev_exit(void)
spin_lock_irqsave(&d->lock, flags);
aoedev_downdev(d);
+ d->flags |= DEVFL_TKILL;
spin_unlock_irqrestore(&d->lock, flags);
del_timer_sync(&d->timer);
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c
index 387588a3f4b..de08491ebe6 100644
--- a/drivers/block/aoe/aoemain.c
+++ b/drivers/block/aoe/aoemain.c
@@ -11,7 +11,7 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sam Hopkins <sah@coraid.com>");
-MODULE_DESCRIPTION("AoE block/char driver for 2.6.[0-9]+");
+MODULE_DESCRIPTION("AoE block/char driver for 2.6.2 and newer 2.6 kernels");
MODULE_VERSION(VERSION);
enum { TINIT, TRUN, TKILL };
@@ -89,7 +89,7 @@ aoe_init(void)
}
printk(KERN_INFO
- "aoe: aoe_init: AoE v2.6-%s initialised.\n",
+ "aoe: aoe_init: AoE v%s initialised.\n",
VERSION);
discover_timer(TINIT);
return 0;
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index 4be976940f6..fdff774b8ab 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -92,18 +92,6 @@ mac_addr(char addr[6])
return __be64_to_cpu(n);
}
-static struct sk_buff *
-skb_check(struct sk_buff *skb)
-{
- if (skb_is_nonlinear(skb))
- if ((skb = skb_share_check(skb, GFP_ATOMIC)))
- if (skb_linearize(skb, GFP_ATOMIC) < 0) {
- dev_kfree_skb(skb);
- return NULL;
- }
- return skb;
-}
-
void
aoenet_xmit(struct sk_buff *sl)
{
@@ -125,14 +113,14 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
struct aoe_hdr *h;
u32 n;
- skb = skb_check(skb);
- if (!skb)
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (skb == NULL)
return 0;
-
+ if (skb_is_nonlinear(skb))
+ if (skb_linearize(skb, GFP_ATOMIC) < 0)
+ goto exit;
if (!is_aoe_netif(ifp))
goto exit;
-
- //skb->len += ETH_HLEN; /* (1) */
skb_push(skb, ETH_HLEN); /* (1) */
h = (struct aoe_hdr *) skb->mac.raw;
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index f8ce235ccfc..c39650920bd 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -271,7 +271,7 @@ unsigned char *DMABuffer; /* buffer for writes */
static unsigned long PhysDMABuffer; /* physical address */
static int UseTrackbuffer = -1; /* Do track buffering? */
-MODULE_PARM(UseTrackbuffer, "i");
+module_param(UseTrackbuffer, int, 0);
unsigned char *TrackBuffer; /* buffer for reads */
static unsigned long PhysTrackBuffer; /* physical address */
@@ -296,7 +296,7 @@ static int MotorOn = 0, MotorOffTrys;
static int IsFormatting = 0, FormatError;
static int UserSteprate[FD_MAX_UNITS] = { -1, -1 };
-MODULE_PARM(UserSteprate, "1-" __MODULE_STRING(FD_MAX_UNITS) "i");
+module_param_array(UserSteprate, int, NULL, 0);
/* Synchronization of FDC access. */
static volatile int fdc_busy = 0;
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 1f2890989b5..1b0fd31c57c 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -996,13 +996,11 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
status = -EINVAL;
goto cleanup1;
}
- buff = (unsigned char **) kmalloc(MAXSGENTRIES *
- sizeof(char *), GFP_KERNEL);
+ buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
if (!buff) {
status = -ENOMEM;
goto cleanup1;
}
- memset(buff, 0, MAXSGENTRIES);
buff_size = (int *) kmalloc(MAXSGENTRIES * sizeof(int),
GFP_KERNEL);
if (!buff_size) {
@@ -2361,8 +2359,7 @@ queue:
if (!creq)
goto startio;
- if (creq->nr_phys_segments > MAXSGENTRIES)
- BUG();
+ BUG_ON(creq->nr_phys_segments > MAXSGENTRIES);
if (( c = cmd_alloc(h, 1)) == NULL)
goto full;
@@ -2730,9 +2727,9 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *c, struct pci_dev *pdev,
return;
}
}
+default_int_mode:
#endif /* CONFIG_PCI_MSI */
/* if we get here we're going to use the default interrupt mode */
-default_int_mode:
c->intr[SIMPLE_MODE_INT] = pdev->irq;
return;
}
@@ -2941,13 +2938,12 @@ static void cciss_getgeometry(int cntl_num)
int block_size;
int total_size;
- ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
+ ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
if (ld_buff == NULL)
{
printk(KERN_ERR "cciss: out of memory\n");
return;
}
- memset(ld_buff, 0, sizeof(ReportLunData_struct));
size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
if (size_buff == NULL)
{
@@ -3061,10 +3057,9 @@ static int alloc_cciss_hba(void)
for(i=0; i< MAX_CTLR; i++) {
if (!hba[i]) {
ctlr_info_t *p;
- p = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
+ p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL);
if (!p)
goto Enomem;
- memset(p, 0, sizeof(ctlr_info_t));
for (n = 0; n < NWD; n++)
p->gendisk[n] = disk[n];
hba[i] = p;
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 9e35de05d5c..597c007fe81 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -1027,12 +1027,11 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
int i;
c = (ctlr_info_t *) hba[cntl_num];
- ld_buff = kmalloc(reportlunsize, GFP_KERNEL);
+ ld_buff = kzalloc(reportlunsize, GFP_KERNEL);
if (ld_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
return;
}
- memset(ld_buff, 0, reportlunsize);
inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
if (inq_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
@@ -1316,7 +1315,7 @@ cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd
cp->Request.Timeout = 0;
memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB));
- if (cmd->cmd_len > sizeof(cp->Request.CDB)) BUG();
+ BUG_ON(cmd->cmd_len > sizeof(cp->Request.CDB));
cp->Request.CDBLen = cmd->cmd_len;
memcpy(cp->Request.CDB, cmd->cmnd, cmd->cmd_len);
cp->Request.Type.Type = TYPE_CMD;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 862b9abac0a..b6ea2f0c727 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -906,8 +906,7 @@ queue_next:
if (!creq)
goto startio;
- if (creq->nr_phys_segments > SG_MAX)
- BUG();
+ BUG_ON(creq->nr_phys_segments > SG_MAX);
if ((c = cmd_alloc(h,1)) == NULL)
goto startio;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index fb2d0be7cde..bedb689b051 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -170,6 +170,7 @@ static int print_unex = 1;
#include <linux/mm.h>
#include <linux/bio.h>
#include <linux/string.h>
+#include <linux/jiffies.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/mc146818rtc.h> /* CMOS defines */
@@ -250,6 +251,18 @@ static int irqdma_allocated;
#include <linux/cdrom.h> /* for the compatibility eject ioctl */
#include <linux/completion.h>
+/*
+ * Interrupt freeing also means /proc VFS work - dont do it
+ * from interrupt context. We push this work into keventd:
+ */
+static void fd_free_irq_fn(void *data)
+{
+ fd_free_irq();
+}
+
+static DECLARE_WORK(fd_free_irq_work, fd_free_irq_fn, NULL);
+
+
static struct request *current_req;
static struct request_queue *floppy_queue;
static void do_fd_request(request_queue_t * q);
@@ -735,7 +748,7 @@ static int disk_change(int drive)
{
int fdc = FDC(drive);
#ifdef FLOPPY_SANITY_CHECK
- if (jiffies - UDRS->select_date < UDP->select_delay)
+ if (time_before(jiffies, UDRS->select_date + UDP->select_delay))
DPRINT("WARNING disk change called early\n");
if (!(FDCS->dor & (0x10 << UNIT(drive))) ||
(FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) {
@@ -1063,7 +1076,7 @@ static int fd_wait_for_completion(unsigned long delay, timeout_fn function)
return 1;
}
- if ((signed)(jiffies - delay) < 0) {
+ if (time_before(jiffies, delay)) {
del_timer(&fd_timer);
fd_timer.function = function;
fd_timer.expires = delay;
@@ -1523,7 +1536,7 @@ static void setup_rw_floppy(void)
* again just before spinup completion. Beware that
* after scandrives, we must again wait for selection.
*/
- if ((signed)(ready_date - jiffies) > DP->select_delay) {
+ if (time_after(ready_date, jiffies + DP->select_delay)) {
ready_date -= DP->select_delay;
function = (timeout_fn) floppy_start;
} else
@@ -3811,7 +3824,7 @@ static int check_floppy_change(struct gendisk *disk)
if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
return 1;
- if (UDP->checkfreq < (int)(jiffies - UDRS->last_checked)) {
+ if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
if (floppy_grab_irq_and_dma()) {
return 1;
}
@@ -4433,6 +4446,13 @@ static int floppy_grab_irq_and_dma(void)
return 0;
}
spin_unlock_irqrestore(&floppy_usage_lock, flags);
+
+ /*
+ * We might have scheduled a free_irq(), wait it to
+ * drain first:
+ */
+ flush_scheduled_work();
+
if (fd_request_irq()) {
DPRINT("Unable to grab IRQ%d for the floppy driver\n",
FLOPPY_IRQ);
@@ -4522,7 +4542,7 @@ static void floppy_release_irq_and_dma(void)
if (irqdma_allocated) {
fd_disable_dma();
fd_free_dma();
- fd_free_irq();
+ schedule_work(&fd_free_irq_work);
irqdma_allocated = 0;
}
set_dor(0, ~0, 8);
@@ -4594,7 +4614,7 @@ static void __init parse_floppy_cfg_string(char *cfg)
}
}
-int init_module(void)
+int __init init_module(void)
{
if (floppy)
parse_floppy_cfg_string(floppy);
@@ -4633,6 +4653,8 @@ void cleanup_module(void)
/* eject disk, if any */
fd_eject(0);
+ flush_scheduled_work(); /* fd_free_irq() might be pending */
+
wait_for_completion(&device_release);
}
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 74bf0255e98..9c3b94e8f03 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -839,7 +839,9 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
set_blocksize(bdev, lo_blocksize);
- kernel_thread(loop_thread, lo, CLONE_KERNEL);
+ error = kernel_thread(loop_thread, lo, CLONE_KERNEL);
+ if (error < 0)
+ goto out_putf;
wait_for_completion(&lo->lo_done);
return 0;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index a9bde30dada..8bca4905d7f 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -639,10 +639,7 @@ static int __init nbd_init(void)
int err = -ENOMEM;
int i;
- if (sizeof(struct nbd_request) != 28) {
- printk(KERN_CRIT "nbd: sizeof nbd_request needs to be 28 in order to work!\n" );
- return -EIO;
- }
+ BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
if (nbds_max > MAX_NBD) {
printk(KERN_CRIT "nbd: cannot allocate more than %u nbds; %u requested.\n", MAX_NBD,
diff --git a/drivers/block/paride/bpck6.c b/drivers/block/paride/bpck6.c
index 08d858ad64d..41a237c5957 100644
--- a/drivers/block/paride/bpck6.c
+++ b/drivers/block/paride/bpck6.c
@@ -224,10 +224,9 @@ static void bpck6_log_adapter( PIA *pi, char * scratch, int verbose )
static int bpck6_init_proto(PIA *pi)
{
- Interface *p = kmalloc(sizeof(Interface), GFP_KERNEL);
+ Interface *p = kzalloc(sizeof(Interface), GFP_KERNEL);
if (p) {
- memset(p, 0, sizeof(Interface));
pi->private = (unsigned long)p;
return 0;
}
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 62d2464c12f..2403721f9db 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -151,6 +151,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV};
#include <linux/cdrom.h> /* for the eject ioctl */
#include <linux/blkdev.h>
#include <linux/blkpg.h>
+#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <linux/sched.h>
#include <linux/workqueue.h>
@@ -275,7 +276,7 @@ static void pd_print_error(struct pd_unit *disk, char *msg, int status)
int i;
printk("%s: %s: status = 0x%x =", disk->name, msg, status);
- for (i = 0; i < 18; i++)
+ for (i = 0; i < ARRAY_SIZE(pd_errs); i++)
if (status & (1 << i))
printk(" %s", pd_errs[i]);
printk("\n");
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 6f5df0fad70..79b86825403 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -643,7 +643,8 @@ static ssize_t pg_read(struct file *filp, char __user *buf, size_t count, loff_t
static int __init pg_init(void)
{
- int unit, err = 0;
+ int unit;
+ int err;
if (disable){
err = -1;
@@ -657,16 +658,17 @@ static int __init pg_init(void)
goto out;
}
- if (register_chrdev(major, name, &pg_fops)) {
+ err = register_chrdev(major, name, &pg_fops);
+ if (err < 0) {
printk("pg_init: unable to get major number %d\n", major);
for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit];
if (dev->present)
pi_release(dev->pi);
}
- err = -1;
goto out;
}
+ major = err; /* In case the user specified `major=0' (dynamic) */
pg_class = class_create(THIS_MODULE, "pg");
if (IS_ERR(pg_class)) {
err = PTR_ERR(pg_class);
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 715ae5dc88f..d2013d36240 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -943,7 +943,8 @@ static ssize_t pt_write(struct file *filp, const char __user *buf, size_t count,
static int __init pt_init(void)
{
- int unit, err = 0;
+ int unit;
+ int err;
if (disable) {
err = -1;
@@ -955,14 +956,15 @@ static int __init pt_init(void)
goto out;
}
- if (register_chrdev(major, name, &pt_fops)) {
+ err = register_chrdev(major, name, &pt_fops);
+ if (err < 0) {
printk("pt_init: unable to get major number %d\n", major);
for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present)
pi_release(pt[unit].pi);
- err = -1;
goto out;
}
+ major = err;
pt_class = class_create(THIS_MODULE, "pt");
if (IS_ERR(pt_class)) {
err = PTR_ERR(pt_class);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 1d261f985f3..a04f60693c3 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -230,16 +230,6 @@ static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets)
return 1;
}
-static void *pkt_rb_alloc(gfp_t gfp_mask, void *data)
-{
- return kmalloc(sizeof(struct pkt_rb_node), gfp_mask);
-}
-
-static void pkt_rb_free(void *ptr, void *data)
-{
- kfree(ptr);
-}
-
static inline struct pkt_rb_node *pkt_rbtree_next(struct pkt_rb_node *node)
{
struct rb_node *n = rb_next(&node->rb_node);
@@ -2073,16 +2063,6 @@ static int pkt_close(struct inode *inode, struct file *file)
}
-static void *psd_pool_alloc(gfp_t gfp_mask, void *data)
-{
- return kmalloc(sizeof(struct packet_stacked_data), gfp_mask);
-}
-
-static void psd_pool_free(void *ptr, void *data)
-{
- kfree(ptr);
-}
-
static int pkt_end_io_read_cloned(struct bio *bio, unsigned int bytes_done, int err)
{
struct packet_stacked_data *psd = bio->bi_private;
@@ -2475,7 +2455,8 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
if (!pd)
return ret;
- pd->rb_pool = mempool_create(PKT_RB_POOL_SIZE, pkt_rb_alloc, pkt_rb_free, NULL);
+ pd->rb_pool = mempool_create_kmalloc_pool(PKT_RB_POOL_SIZE,
+ sizeof(struct pkt_rb_node));
if (!pd->rb_pool)
goto out_mem;
@@ -2639,7 +2620,8 @@ static int __init pkt_init(void)
{
int ret;
- psd_pool = mempool_create(PSD_POOL_SIZE, psd_pool_alloc, psd_pool_free, NULL);
+ psd_pool = mempool_create_kmalloc_pool(PSD_POOL_SIZE,
+ sizeof(struct packet_stacked_data));
if (!psd_pool)
return -ENOMEM;
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index c16e66b9c7a..f7d4c65a7b8 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -50,6 +50,7 @@
#include <linux/timer.h>
#include <linux/pci.h>
#include <linux/slab.h>
+#include <linux/dma-mapping.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/hdreg.h> /* HDIO_GETGEO */
@@ -881,8 +882,8 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
printk(KERN_INFO "Micro Memory(tm) controller #%d found at %02x:%02x (PCI Mem Module (Battery Backup))\n",
card->card_number, dev->bus->number, dev->devfn);
- if (pci_set_dma_mask(dev, 0xffffffffffffffffLL) &&
- pci_set_dma_mask(dev, 0xffffffffLL)) {
+ if (pci_set_dma_mask(dev, DMA_64BIT_MASK) &&
+ pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "MM%d: NO suitable DMA found\n",num_cards);
return -ENOMEM;
}
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index fad27a87ce3..f43a988dd41 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -218,12 +218,12 @@ static int cm206_base = CM206_BASE;
static int cm206_irq = CM206_IRQ;
#ifdef MODULE
static int cm206[2] = { 0, 0 }; /* for compatible `insmod' parameter passing */
+module_param_array(cm206, int, NULL, 0); /* base,irq or irq,base */
#endif
-MODULE_PARM(cm206_base, "i"); /* base */
-MODULE_PARM(cm206_irq, "i"); /* irq */
-MODULE_PARM(cm206, "1-2i"); /* base,irq or irq,base */
-MODULE_PARM(auto_probe, "i"); /* auto probe base and irq */
+module_param(cm206_base, int, 0); /* base */
+module_param(cm206_irq, int, 0); /* irq */
+module_param(auto_probe, bool, 0); /* auto probe base and irq */
MODULE_LICENSE("GPL");
#define POLLOOP 100 /* milliseconds */
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index 4760f515f59..05c9e865eca 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -464,8 +464,13 @@ static int sbpcd[] =
static __cacheline_aligned DEFINE_SPINLOCK(sbpcd_lock);
static struct request_queue *sbpcd_queue;
-MODULE_PARM(sbpcd, "2i");
-MODULE_PARM(max_drives, "i");
+/* You can only set the first pair, from old MODULE_PARM code. */
+static int sbpcd_set(const char *val, struct kernel_param *kp)
+{
+ get_options((char *)val, 2, (int *)sbpcd);
+ return 0;
+}
+module_param_call(sbpcd, sbpcd_set, NULL, NULL, 0);
#define NUM_PROBE (sizeof(sbpcd) / sizeof(int))
@@ -553,6 +558,7 @@ static unsigned char msgnum;
static char msgbuf[80];
static int max_drives = MAX_DRIVES;
+module_param(max_drives, int, 0);
#ifndef MODULE
static unsigned char setup_done;
static const char *str_sb_l = "soundblaster";
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 5980f3e886f..889cad07774 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -187,6 +187,7 @@ config MOXA_SMARTIO
config ISI
tristate "Multi-Tech multiport card support (EXPERIMENTAL)"
depends on SERIAL_NONSTANDARD
+ select FW_LOADER
help
This is a driver for the Multi-Tech cards which provide several
serial ports. The driver is experimental and can currently only be
@@ -560,14 +561,31 @@ config TIPAR
If unsure, say N.
+config HVC_DRIVER
+ bool
+ help
+ Users of pSeries machines that want to utilize the hvc console front-end
+ module for their backend console driver should select this option.
+ It will automatically be selected if one of the back-end console drivers
+ is selected.
+
+
config HVC_CONSOLE
bool "pSeries Hypervisor Virtual Console support"
depends on PPC_PSERIES
+ select HVC_DRIVER
help
pSeries machines when partitioned support a hypervisor virtual
console. This driver allows each pSeries partition to have a console
which is accessed via the HMC.
+config HVC_RTAS
+ bool "IBM RTAS Console support"
+ depends on PPC_RTAS
+ select HVC_DRIVER
+ help
+ IBM Console device driver which makes use of RTAS
+
config HVCS
tristate "IBM Hypervisor Virtual Console Server support"
depends on PPC_PSERIES
@@ -695,7 +713,7 @@ config NVRAM
config RTC
tristate "Enhanced Real Time Clock Support"
- depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV
+ depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 090d154098b..a73cb495692 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -41,60 +41,63 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
obj-$(CONFIG_SX) += sx.o generic_serial.o
obj-$(CONFIG_RIO) += rio/ generic_serial.o
-obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvc_vio.o hvsi.o
+obj-$(CONFIG_HVC_DRIVER) += hvc_console.o
+obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o
+obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o
obj-$(CONFIG_RAW_DRIVER) += raw.o
obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
obj-$(CONFIG_MMTIMER) += mmtimer.o
-obj-$(CONFIG_VIOCONS) += viocons.o
+obj-$(CONFIG_VIOCONS) += viocons.o
obj-$(CONFIG_VIOTAPE) += viotape.o
obj-$(CONFIG_HVCS) += hvcs.o
obj-$(CONFIG_SGI_MBCS) += mbcs.o
-obj-$(CONFIG_PRINTER) += lp.o
-obj-$(CONFIG_TIPAR) += tipar.o
-
-obj-$(CONFIG_DTLK) += dtlk.o
-obj-$(CONFIG_R3964) += n_r3964.o
-obj-$(CONFIG_APPLICOM) += applicom.o
-obj-$(CONFIG_SONYPI) += sonypi.o
-obj-$(CONFIG_RTC) += rtc.o
-obj-$(CONFIG_HPET) += hpet.o
-obj-$(CONFIG_GEN_RTC) += genrtc.o
-obj-$(CONFIG_EFI_RTC) += efirtc.o
-obj-$(CONFIG_SGI_DS1286) += ds1286.o
-obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
-obj-$(CONFIG_DS1302) += ds1302.o
-obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o
-obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o
+obj-$(CONFIG_PRINTER) += lp.o
+obj-$(CONFIG_TIPAR) += tipar.o
+
+obj-$(CONFIG_DTLK) += dtlk.o
+obj-$(CONFIG_R3964) += n_r3964.o
+obj-$(CONFIG_APPLICOM) += applicom.o
+obj-$(CONFIG_SONYPI) += sonypi.o
+obj-$(CONFIG_RTC) += rtc.o
+obj-$(CONFIG_HPET) += hpet.o
+obj-$(CONFIG_GEN_RTC) += genrtc.o
+obj-$(CONFIG_EFI_RTC) += efirtc.o
+obj-$(CONFIG_SGI_DS1286) += ds1286.o
+obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
+obj-$(CONFIG_DS1302) += ds1302.o
+obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o
+obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o
ifeq ($(CONFIG_GENERIC_NVRAM),y)
- obj-$(CONFIG_NVRAM) += generic_nvram.o
+ obj-$(CONFIG_NVRAM) += generic_nvram.o
else
- obj-$(CONFIG_NVRAM) += nvram.o
+ obj-$(CONFIG_NVRAM) += nvram.o
endif
-obj-$(CONFIG_TOSHIBA) += toshiba.o
-obj-$(CONFIG_I8K) += i8k.o
-obj-$(CONFIG_DS1620) += ds1620.o
-obj-$(CONFIG_HW_RANDOM) += hw_random.o
-obj-$(CONFIG_FTAPE) += ftape/
-obj-$(CONFIG_COBALT_LCD) += lcd.o
-obj-$(CONFIG_PPDEV) += ppdev.o
-obj-$(CONFIG_NWBUTTON) += nwbutton.o
-obj-$(CONFIG_NWFLASH) += nwflash.o
-obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
-obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o
-obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
-obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
-obj-$(CONFIG_TELCLOCK) += tlclk.o
-
-obj-$(CONFIG_WATCHDOG) += watchdog/
-obj-$(CONFIG_MWAVE) += mwave/
-obj-$(CONFIG_AGP) += agp/
-obj-$(CONFIG_DRM) += drm/
-obj-$(CONFIG_PCMCIA) += pcmcia/
-obj-$(CONFIG_IPMI_HANDLER) += ipmi/
-
-obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
-obj-$(CONFIG_TCG_TPM) += tpm/
+obj-$(CONFIG_TOSHIBA) += toshiba.o
+obj-$(CONFIG_I8K) += i8k.o
+obj-$(CONFIG_DS1620) += ds1620.o
+obj-$(CONFIG_HW_RANDOM) += hw_random.o
+obj-$(CONFIG_FTAPE) += ftape/
+obj-$(CONFIG_COBALT_LCD) += lcd.o
+obj-$(CONFIG_PPDEV) += ppdev.o
+obj-$(CONFIG_NWBUTTON) += nwbutton.o
+obj-$(CONFIG_NWFLASH) += nwflash.o
+obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
+obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o
+obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
+obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
+obj-$(CONFIG_TELCLOCK) += tlclk.o
+
+obj-$(CONFIG_WATCHDOG) += watchdog/
+obj-$(CONFIG_MWAVE) += mwave/
+obj-$(CONFIG_AGP) += agp/
+obj-$(CONFIG_DRM) += drm/
+obj-$(CONFIG_PCMCIA) += pcmcia/
+obj-$(CONFIG_IPMI_HANDLER) += ipmi/
+
+obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
+obj-$(CONFIG_TCG_TPM) += tpm/
+
# Files generated that shall be removed upon make clean
clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index a4d425d2dce..0b9cf9c59a2 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -98,12 +98,12 @@ config AGP_SWORKS
tristate "Serverworks LE/HE chipset support"
depends on AGP && X86_32
help
- Say Y here to support the Serverworks AGP card. See
+ Say Y here to support the Serverworks AGP card. See
<http://www.serverworks.com/> for product descriptions and images.
config AGP_VIA
tristate "VIA chipset support"
- depends on AGP && X86_32
+ depends on AGP
help
This option gives you AGP support for the GLX component of
X on VIA MVP3/Apollo Pro chipsets.
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index b4af87c6f9c..3c623b67ea1 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -19,9 +19,9 @@
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
@@ -53,7 +53,7 @@ enum aper_size_type {
struct gatt_mask {
unsigned long mask;
u32 type;
- /* totally device specific, for integrated chipsets that
+ /* totally device specific, for integrated chipsets that
* might have different types of memory masks. For other
* devices this will probably be ignored */
};
@@ -104,8 +104,7 @@ struct agp_bridge_driver {
void (*agp_enable)(struct agp_bridge_data *, u32);
void (*cleanup)(void);
void (*tlb_flush)(struct agp_memory *);
- unsigned long (*mask_memory)(struct agp_bridge_data *,
- unsigned long, int);
+ unsigned long (*mask_memory)(struct agp_bridge_data *, unsigned long, int);
void (*cache_flush)(void);
int (*create_gatt_table)(struct agp_bridge_data *);
int (*free_gatt_table)(struct agp_bridge_data *);
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index b02fc226715..5a31ec7c62f 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -147,7 +147,7 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge)
if (!addr)
return NULL;
-
+
pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c
index a072d32005a..2b5838e6475 100644
--- a/drivers/char/agp/alpha-agp.c
+++ b/drivers/char/agp/alpha-agp.c
@@ -23,8 +23,9 @@ static struct page *alpha_core_agp_vm_nopage(struct vm_area_struct *vma,
dma_addr = address - vma->vm_start + agp->aperture.bus_base;
pa = agp->ops->translate(agp, dma_addr);
- if (pa == (unsigned long)-EINVAL) return NULL; /* no translation */
-
+ if (pa == (unsigned long)-EINVAL)
+ return NULL; /* no translation */
+
/*
* Get the page, inc the use count, and return it
*/
@@ -89,7 +90,7 @@ static void alpha_core_agp_enable(struct agp_bridge_data *bridge, u32 mode)
agp_device_command(agp->mode.lw, 0);
}
-static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start,
+static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start,
int type)
{
alpha_agp_info *agp = agp_bridge->dev_private_data;
@@ -98,7 +99,8 @@ static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start,
temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;
- if ((pg_start + mem->page_count) > num_entries) return -EINVAL;
+ if ((pg_start + mem->page_count) > num_entries)
+ return -EINVAL;
status = agp->ops->bind(agp, pg_start, mem);
mb();
@@ -107,7 +109,7 @@ static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start,
return status;
}
-static int alpha_core_agp_remove_memory(struct agp_memory *mem, off_t pg_start,
+static int alpha_core_agp_remove_memory(struct agp_memory *mem, off_t pg_start,
int type)
{
alpha_agp_info *agp = agp_bridge->dev_private_data;
@@ -125,7 +127,7 @@ struct agp_bridge_driver alpha_core_agp_driver = {
.size_type = FIXED_APER_SIZE,
.cant_use_aperture = 1,
.masks = NULL,
-
+
.fetch_size = alpha_core_agp_fetch_size,
.configure = alpha_core_agp_configure,
.agp_enable = alpha_core_agp_enable,
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 1251b2515bb..36517d4d1ad 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -216,7 +216,7 @@ static struct aper_size_info_32 amd_8151_sizes[7] =
{256, 65536, 6, 0x00000700 }, /* 1 1 1 0 0 0 */
{128, 32768, 5, 0x00000720 }, /* 1 1 1 1 0 0 */
{64, 16384, 4, 0x00000730 }, /* 1 1 1 1 1 0 */
- {32, 8192, 3, 0x00000738 } /* 1 1 1 1 1 1 */
+ {32, 8192, 3, 0x00000738 } /* 1 1 1 1 1 1 */
};
static int amd_8151_configure(void)
@@ -725,7 +725,7 @@ static struct pci_device_id agp_amd64_pci_table[] = {
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_AL,
- .device = 0x1689,
+ .device = 0x1695,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index 5b74c36c116..06fd10ba0c5 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -74,7 +74,7 @@ static int ati_create_page_map(ati_page_map *page_map)
/*CACHE_FLUSH();*/
global_cache_flush();
- for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
+ for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
writel(agp_bridge->scratch_page, page_map->remapped+i);
readl(page_map->remapped+i); /* PCI Posting. */
}
@@ -99,7 +99,7 @@ static void ati_free_gatt_pages(void)
ati_page_map *entry;
tables = ati_generic_private.gatt_pages;
- for(i = 0; i < ati_generic_private.num_tables; i++) {
+ for (i = 0; i < ati_generic_private.num_tables; i++) {
entry = tables[i];
if (entry != NULL) {
if (entry->real != NULL)
@@ -387,7 +387,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge)
agp_bridge->gart_bus_addr = addr;
/* Calculate the agp offset */
- for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
+ for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1,
page_dir.remapped+GET_PAGE_DIR_OFF(addr));
readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */
@@ -466,6 +466,10 @@ static struct agp_device_ids ati_agp_device_ids[] __devinitdata =
.device_id = PCI_DEVICE_ID_ATI_RS300_200,
.chipset_name = "IGP9100/M",
},
+ {
+ .device_id = PCI_DEVICE_ID_ATI_RS350_200,
+ .chipset_name = "IGP9100/M",
+ },
{ }, /* dummy final entry, always present */
};
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 80ee17a8fc2..509adc40325 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -228,7 +228,7 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
struct agp_bridge_data *agp_alloc_bridge(void)
{
struct agp_bridge_data *bridge;
-
+
bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
if (!bridge)
return NULL;
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index e7aea77a60f..fed0a87448d 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -1,6 +1,6 @@
/*
* Transmeta's Efficeon AGPGART driver.
- *
+ *
* Based upon a diff by Linus around November '02.
*
* Ported to the 2.6 kernel by Carlos Puchol <cpglinux@puchol.com>
@@ -9,7 +9,7 @@
/*
* NOTE-cpg-040217:
- *
+ *
* - when compiled as a module, after loading the module,
* it will refuse to unload, indicating it is in use,
* when it is not.
@@ -45,7 +45,7 @@
* 8: Present
* 7:6: reserved, write as zero
* 5:0: GATT directory index: which 1st-level entry
- *
+ *
* The Efficeon AGP spec requires pages to be WB-cacheable
* but to be explicitly CLFLUSH'd after any changes.
*/
@@ -125,7 +125,7 @@ static int efficeon_configure(void)
struct aper_size_info_lvl2 *current_size;
printk(KERN_DEBUG PFX "efficeon_configure()\n");
-
+
current_size = A_SIZE_LVL2(agp_bridge->current_size);
/* aperture size */
@@ -190,7 +190,7 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
const int present = EFFICEON_PRESENT;
const int clflush_chunk = ((cpuid_ebx(1) >> 8) & 0xff) << 3;
int num_entries, l1_pages;
-
+
num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
printk(KERN_DEBUG PFX "efficeon_create_gatt_table(%d)\n", num_entries);
@@ -257,12 +257,12 @@ static int efficeon_insert_memory(struct agp_memory * mem, off_t pg_start, int t
if (!page)
continue;
-
+
page += (index & 0x3ff);
*page = insert;
/* clflush is slow, so don't clflush until we have to */
- if ( last_page &&
+ if ( last_page &&
((unsigned long)page^(unsigned long)last_page) & clflush_mask )
asm volatile("clflush %0" : : "m" (*last_page));
@@ -373,7 +373,7 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
*/
r = &pdev->resource[0];
if (!r->start && r->end) {
- if(pci_assign_resource(pdev, 0)) {
+ if (pci_assign_resource(pdev, 0)) {
printk(KERN_ERR PFX "could not assign resource 0\n");
return -ENODEV;
}
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index 97eeb2345b1..ffcf15c30e9 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -781,7 +781,7 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv)
if (agp_fe.current_controller != NULL)
return -EBUSY;
- if(!agp_bridge)
+ if (!agp_bridge)
return -ENODEV;
if (atomic_read(&agp_bridge->agp_in_use))
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 5567ce8d72b..4e1891e2c03 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -299,7 +299,7 @@ EXPORT_SYMBOL_GPL(agp_num_entries);
/**
* agp_copy_info - copy bridge state information
*
- * @info: agp_kern_info pointer. The caller should insure that this pointer is valid.
+ * @info: agp_kern_info pointer. The caller should insure that this pointer is valid.
*
* This function copies information about the agp bridge device and the state of
* the agp backend into an agp_kern_info pointer.
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index de5d6d21267..8c4c6ef748e 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -85,8 +85,8 @@ static int __init hp_zx1_ioc_shared(void)
/*
* IOC already configured by sba_iommu module; just use
* its setup. We assume:
- * - IOVA space is 1Gb in size
- * - first 512Mb is IOMMU, second 512Mb is GART
+ * - IOVA space is 1Gb in size
+ * - first 512Mb is IOMMU, second 512Mb is GART
*/
hp->io_tlb_ps = readq(hp->ioc_regs+HP_ZX1_TCNFG);
switch (hp->io_tlb_ps) {
@@ -115,7 +115,7 @@ static int __init hp_zx1_ioc_shared(void)
if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
/* Normal case when no AGP device in system */
- hp->gatt = NULL;
+ hp->gatt = NULL;
hp->gatt_entries = 0;
printk(KERN_ERR PFX "No reserved IO PDIR entry found; "
"GART disabled\n");
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index 8ee19a4a6bc..91769443d8f 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -400,10 +400,10 @@ static int i460_insert_memory_large_io_page (struct agp_memory *mem,
num_entries = A_SIZE_8(temp)->num_entries;
/* Figure out what pg_start means in terms of our large GART pages */
- start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
- end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
- start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
- end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;
+ start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
+ end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
+ start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
+ end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;
if (end > i460.lp_desc + num_entries) {
printk(KERN_ERR PFX "Looks like we're out of AGP memory\n");
@@ -458,10 +458,10 @@ static int i460_remove_memory_large_io_page (struct agp_memory *mem,
num_entries = A_SIZE_8(temp)->num_entries;
/* Figure out what pg_start means in terms of our large GART pages */
- start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
- end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
- start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
- end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;
+ start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
+ end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
+ start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
+ end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;
for (i = 0, lp = start; lp <= end; ++lp) {
for (idx = ((lp == start) ? start_offset : 0);
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 631531fd97a..bddcae54b16 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -201,9 +201,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;
- if ((pg_start + mem->page_count) > num_entries) {
+ if ((pg_start + mem->page_count) > num_entries)
return -EINVAL;
- }
+
for (j = pg_start; j < (pg_start + mem->page_count); j++) {
if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
return -EBUSY;
@@ -221,7 +221,7 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
agp_bridge->driver->tlb_flush(mem);
return 0;
}
- if((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY))
+ if ((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY))
goto insert;
return -EINVAL;
}
@@ -328,7 +328,7 @@ static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
static void intel_i810_free_by_type(struct agp_memory *curr)
{
agp_free_key(curr->key);
- if(curr->type == AGP_PHYS_MEMORY) {
+ if (curr->type == AGP_PHYS_MEMORY) {
if (curr->page_count == 4)
i8xx_destroy_pages(gart_to_virt(curr->memory[0]));
else {
@@ -1603,11 +1603,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
name = "i820";
break;
case PCI_DEVICE_ID_INTEL_82830_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC)) {
+ if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC))
bridge->driver = &intel_830_driver;
- } else {
+ else
bridge->driver = &intel_830mp_driver;
- }
name = "830M";
break;
case PCI_DEVICE_ID_INTEL_82840_HB:
@@ -1619,11 +1618,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
name = "i845";
break;
case PCI_DEVICE_ID_INTEL_82845G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG)) {
+ if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG))
bridge->driver = &intel_830_driver;
- } else {
+ else
bridge->driver = &intel_845_driver;
- }
name = "845G";
break;
case PCI_DEVICE_ID_INTEL_82850_HB:
@@ -1648,11 +1646,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
name = "i860";
break;
case PCI_DEVICE_ID_INTEL_82865_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) {
+ if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG))
bridge->driver = &intel_830_driver;
- } else {
+ else
bridge->driver = &intel_845_driver;
- }
name = "865";
break;
case PCI_DEVICE_ID_INTEL_82875_HB:
@@ -1660,35 +1657,31 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
name = "i875";
break;
case PCI_DEVICE_ID_INTEL_82915G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG)) {
+ if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG))
bridge->driver = &intel_915_driver;
- } else {
+ else
bridge->driver = &intel_845_driver;
- }
name = "915G";
break;
case PCI_DEVICE_ID_INTEL_82915GM_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82915GM_IG)) {
+ if (find_i830(PCI_DEVICE_ID_INTEL_82915GM_IG))
bridge->driver = &intel_915_driver;
- } else {
+ else
bridge->driver = &intel_845_driver;
- }
name = "915GM";
break;
case PCI_DEVICE_ID_INTEL_82945G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG)) {
+ if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG))
bridge->driver = &intel_915_driver;
- } else {
+ else
bridge->driver = &intel_845_driver;
- }
name = "945G";
break;
case PCI_DEVICE_ID_INTEL_82945GM_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG)) {
+ if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG))
bridge->driver = &intel_915_driver;
- } else {
+ else
bridge->driver = &intel_845_driver;
- }
name = "945GM";
break;
case PCI_DEVICE_ID_INTEL_7505_0:
@@ -1724,7 +1717,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
*/
r = &pdev->resource[0];
if (!r->start && r->end) {
- if(pci_assign_resource(pdev, 0)) {
+ if (pci_assign_resource(pdev, 0)) {
printk(KERN_ERR PFX "could not assign resource 0\n");
agp_put_bridge(bridge);
return -ENODEV;
diff --git a/drivers/char/agp/isoch.c b/drivers/char/agp/isoch.c
index 7c14a096b85..3f9ccde6237 100644
--- a/drivers/char/agp/isoch.c
+++ b/drivers/char/agp/isoch.c
@@ -26,7 +26,7 @@ static void agp_3_5_dev_list_insert(struct list_head *head, struct list_head *ne
list_for_each(pos, head) {
cur = list_entry(pos, struct agp_3_5_dev, list);
- if(cur->maxbw > n->maxbw)
+ if (cur->maxbw > n->maxbw)
break;
}
list_add_tail(new, pos);
@@ -54,9 +54,9 @@ static void agp_3_5_dev_list_sort(struct agp_3_5_dev *list, unsigned int ndevs)
}
}
-/*
- * Initialize all isochronous transfer parameters for an AGP 3.0
- * node (i.e. a host bridge in combination with the adapters
+/*
+ * Initialize all isochronous transfer parameters for an AGP 3.0
+ * node (i.e. a host bridge in combination with the adapters
* lying behind it...)
*/
@@ -200,7 +200,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge,
* this to the hungriest device (as per the spec) */
rem = target.n - tot_n;
- /*
+ /*
* Calculate the minimum isochronous RQ depth needed by each master.
* Along the way, distribute the extra ISOCH_N capability calculated
* above.
@@ -214,7 +214,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge,
* many writes on the AGP bus).
*/
master[cdev].rq = master[cdev].n;
- if(master[cdev].y > 0x1)
+ if (master[cdev].y > 0x1)
master[cdev].rq *= (1 << (master[cdev].y - 1));
tot_rq += master[cdev].rq;
@@ -334,9 +334,9 @@ int agp_3_5_enable(struct agp_bridge_data *bridge)
arqsz = (tstatus >> 13) & 0x7;
- /*
+ /*
* Allocate a head for our AGP 3.5 device list
- * (multiple AGP v3 devices are allowed behind a single bridge).
+ * (multiple AGP v3 devices are allowed behind a single bridge).
*/
if ((dev_list = kmalloc(sizeof(*dev_list), GFP_KERNEL)) == NULL) {
ret = -ENOMEM;
@@ -366,7 +366,7 @@ int agp_3_5_enable(struct agp_bridge_data *bridge)
case 0x0300: /* Display controller */
case 0x0400: /* Multimedia controller */
- if((cur = kmalloc(sizeof(*cur), GFP_KERNEL)) == NULL) {
+ if ((cur = kmalloc(sizeof(*cur), GFP_KERNEL)) == NULL) {
ret = -ENOMEM;
goto free_and_exit;
}
@@ -391,7 +391,7 @@ int agp_3_5_enable(struct agp_bridge_data *bridge)
list_for_each(pos, head) {
cur = list_entry(pos, struct agp_3_5_dev, list);
dev = cur->dev;
-
+
pci_read_config_word(dev, PCI_STATUS, &mpstat);
if ((mpstat & PCI_STATUS_CAP_LIST) == 0)
continue;
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index 80dafa3030b..4c67135c12d 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -11,6 +11,7 @@
#include <linux/gfp.h>
#include <linux/page-flags.h>
#include <linux/mm.h>
+#include <linux/jiffies.h>
#include "agp.h"
/* NVIDIA registers */
@@ -72,7 +73,7 @@ static int nvidia_init_iorr(u32 base, u32 size)
/* Find the iorr that is already used for the base */
/* If not found, determine the uppermost available iorr */
free_iorr_addr = AMD_K7_NUM_IORR;
- for(iorr_addr = 0; iorr_addr < AMD_K7_NUM_IORR; iorr_addr++) {
+ for (iorr_addr = 0; iorr_addr < AMD_K7_NUM_IORR; iorr_addr++) {
rdmsr(IORR_BASE0 + 2 * iorr_addr, base_lo, base_hi);
rdmsr(IORR_MASK0 + 2 * iorr_addr, mask_lo, mask_hi);
@@ -82,7 +83,7 @@ static int nvidia_init_iorr(u32 base, u32 size)
if ((mask_lo & 0x00000800) == 0)
free_iorr_addr = iorr_addr;
}
-
+
if (iorr_addr >= AMD_K7_NUM_IORR) {
iorr_addr = free_iorr_addr;
if (iorr_addr >= AMD_K7_NUM_IORR)
@@ -139,7 +140,7 @@ static int nvidia_configure(void)
}
/* attbase */
- for(i = 0; i < 8; i++) {
+ for (i = 0; i < 8; i++) {
pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_ATTBASE(i),
(agp_bridge->gatt_bus_addr + (i % num_dirs) * 64 * 1024) | 1);
}
@@ -197,15 +198,15 @@ extern int agp_memory_reserved;
static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
{
int i, j;
-
+
if ((type != 0) || (mem->type != 0))
return -EINVAL;
-
+
if ((pg_start + mem->page_count) >
(nvidia_private.num_active_entries - agp_memory_reserved/PAGE_SIZE))
return -EINVAL;
-
- for(j = pg_start; j < (pg_start + mem->page_count); j++) {
+
+ for (j = pg_start; j < (pg_start + mem->page_count); j++) {
if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j)))
return -EBUSY;
}
@@ -256,7 +257,7 @@ static void nvidia_tlbflush(struct agp_memory *mem)
do {
pci_read_config_dword(nvidia_private.dev_1,
NVIDIA_1_WBC, &wbc_reg);
- if ((signed)(end - jiffies) <= 0) {
+ if (time_before_eq(end, jiffies)) {
printk(KERN_ERR PFX
"TLB flush took more than 3 seconds.\n");
}
@@ -264,9 +265,9 @@ static void nvidia_tlbflush(struct agp_memory *mem)
}
/* flush TLB entries */
- for(i = 0; i < 32 + 1; i++)
+ for (i = 0; i < 32 + 1; i++)
temp = readl(nvidia_private.aperture+(i * PAGE_SIZE / sizeof(u32)));
- for(i = 0; i < 32 + 1; i++)
+ for (i = 0; i < 32 + 1; i++)
temp = readl(nvidia_private.aperture+(i * PAGE_SIZE / sizeof(u32)));
}
@@ -323,7 +324,7 @@ static int __devinit agp_nvidia_probe(struct pci_dev *pdev,
pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2));
nvidia_private.dev_3 =
pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0));
-
+
if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) {
printk(KERN_INFO PFX "Detected an NVIDIA nForce/nForce2 "
"chipset, but could not find the secondary devices.\n");
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 4df7734b51c..cfa7922cb43 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -329,7 +329,7 @@ static int __devinit agp_sgi_init(void)
static void __devexit agp_sgi_cleanup(void)
{
- if(sgi_tioca_agp_bridges)
+ if (sgi_tioca_agp_bridges)
kfree(sgi_tioca_agp_bridges);
sgi_tioca_agp_bridges=NULL;
}
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index ebc05554045..a00fd48a6f0 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -121,7 +121,7 @@ static struct aper_size_info_8 sis_generic_sizes[7] =
static struct agp_bridge_driver sis_driver = {
.owner = THIS_MODULE,
- .aperture_sizes = sis_generic_sizes,
+ .aperture_sizes = sis_generic_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 7,
.configure = sis_configure,
@@ -243,11 +243,11 @@ static void __devinit sis_get_driver(struct agp_bridge_data *bridge)
{
int i;
- for(i=0; sis_broken_chipsets[i]!=0; ++i)
- if(bridge->dev->device==sis_broken_chipsets[i])
+ for (i=0; sis_broken_chipsets[i]!=0; ++i)
+ if (bridge->dev->device==sis_broken_chipsets[i])
break;
- if(sis_broken_chipsets[i] || agp_sis_force_delay)
+ if (sis_broken_chipsets[i] || agp_sis_force_delay)
sis_driver.agp_enable=sis_delayed_enable;
// sis chipsets that indicate less than agp3.5
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index efef9999f1c..4f2d7d99902 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -64,7 +64,7 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map)
}
global_cache_flush();
- for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++)
+ for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++)
writel(agp_bridge->scratch_page, page_map->remapped+i);
return 0;
@@ -84,7 +84,7 @@ static void serverworks_free_gatt_pages(void)
struct serverworks_page_map *entry;
tables = serverworks_private.gatt_pages;
- for(i = 0; i < serverworks_private.num_tables; i++) {
+ for (i = 0; i < serverworks_private.num_tables; i++) {
entry = tables[i];
if (entry != NULL) {
if (entry->real != NULL) {
@@ -103,7 +103,7 @@ static int serverworks_create_gatt_pages(int nr_tables)
int retval = 0;
int i;
- tables = kzalloc((nr_tables + 1) * sizeof(struct serverworks_page_map *),
+ tables = kzalloc((nr_tables + 1) * sizeof(struct serverworks_page_map *),
GFP_KERNEL);
if (tables == NULL)
return -ENOMEM;
@@ -161,7 +161,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
return retval;
}
/* Create a fake scratch directory */
- for(i = 0; i < 1024; i++) {
+ for (i = 0; i < 1024; i++) {
writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i);
writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
}
@@ -185,9 +185,8 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
pci_read_config_dword(agp_bridge->dev,serverworks_private.gart_addr_ofs,&temp);
agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
- /* Calculate the agp offset */
-
- for(i = 0; i < value->num_entries / 1024; i++)
+ /* Calculate the agp offset */
+ for (i = 0; i < value->num_entries / 1024; i++)
writel(virt_to_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
return 0;
@@ -196,7 +195,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
static int serverworks_free_gatt_table(struct agp_bridge_data *bridge)
{
struct serverworks_page_map page_dir;
-
+
page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index 50947e38501..9846defbddb 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -95,12 +95,12 @@ static void uninorth_cleanup(void)
static int uninorth_configure(void)
{
struct aper_size_info_32 *current_size;
-
+
current_size = A_SIZE_32(agp_bridge->current_size);
printk(KERN_INFO PFX "configuring for size idx: %d\n",
current_size->size_value);
-
+
/* aperture size and gatt addr */
pci_write_config_dword(agp_bridge->dev,
UNI_N_CFG_GART_BASE,
@@ -127,7 +127,7 @@ static int uninorth_configure(void)
UNI_N_CFG_GART_DUMMY_PAGE,
agp_bridge->scratch_page_real >> 12);
}
-
+
return 0;
}
@@ -162,7 +162,7 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start,
}
(void)in_le32((volatile u32*)&agp_bridge->gatt_table[pg_start]);
mb();
- flush_dcache_range((unsigned long)&agp_bridge->gatt_table[pg_start],
+ flush_dcache_range((unsigned long)&agp_bridge->gatt_table[pg_start],
(unsigned long)&agp_bridge->gatt_table[pg_start + mem->page_count]);
uninorth_tlbflush(mem);
@@ -235,7 +235,7 @@ static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode)
command = agp_collect_device_status(bridge, mode, status);
command |= PCI_AGP_COMMAND_AGP;
-
+
if (uninorth_rev == 0x21) {
/*
* Darwin disable AGP 4x on this revision, thus we
@@ -456,7 +456,7 @@ static struct aper_size_info_32 uninorth_sizes[7] =
{256, 65536, 6, 64},
{128, 32768, 5, 32},
{64, 16384, 4, 16},
-#endif
+#endif
{32, 8192, 3, 8},
{16, 4096, 2, 4},
{8, 2048, 1, 2},
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index 641f7633878..b7f7951c458 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -175,7 +175,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
drm_device_t *dev = NULL;
int minor = iminor(inode);
int err = -ENODEV;
- struct file_operations *old_fops;
+ const struct file_operations *old_fops;
DRM_DEBUG("\n");
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index ae0aa6d7e0b..c658dde3633 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -126,7 +126,7 @@ static int i810_map_buffer(drm_buf_t * buf, struct file *filp)
drm_device_t *dev = priv->head->dev;
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
drm_i810_private_t *dev_priv = dev->dev_private;
- struct file_operations *old_fops;
+ const struct file_operations *old_fops;
int retcode = 0;
if (buf_priv->currently_mapped == I810_BUF_MAPPED)
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 163f2cbfe60..b0f815d8cea 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -128,7 +128,7 @@ static int i830_map_buffer(drm_buf_t * buf, struct file *filp)
drm_device_t *dev = priv->head->dev;
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
drm_i830_private_t *dev_priv = dev->dev_private;
- struct file_operations *old_fops;
+ const struct file_operations *old_fops;
unsigned long virtual;
int retcode = 0;
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 765c5c108bf..9cad8501d62 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -486,8 +486,7 @@ static void pc_close(struct tty_struct * tty, struct file * filp)
} /* End channel is open more than once */
/* Port open only once go ahead with shutdown & reset */
- if (ch->count < 0)
- BUG();
+ BUG_ON(ch->count < 0);
/* ---------------------------------------------------------------
Let the rest of the driver know the channel is being closed.
diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c
index b2e0928e842..093fdf98b19 100644
--- a/drivers/char/ftape/lowlevel/fdc-io.c
+++ b/drivers/char/ftape/lowlevel/fdc-io.c
@@ -607,7 +607,7 @@ void fdc_reset(void)
fdc_mode = fdc_idle;
- /* maybe the cli()/sti() pair is not necessary, BUT:
+ /* maybe the spin_lock_irq* pair is not necessary, BUT:
* the following line MUST be here. Otherwise fdc_interrupt_wait()
* won't wait. Note that fdc_reset() is called from
* ftape_dumb_stop() when the fdc is busy transferring data. In this
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
index 1b5e01e6e12..43ff5981651 100644
--- a/drivers/char/generic_nvram.c
+++ b/drivers/char/generic_nvram.c
@@ -22,6 +22,9 @@
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/nvram.h>
+#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
+#endif
#define NVRAM_SIZE 8192
@@ -92,7 +95,7 @@ static int nvram_ioctl(struct inode *inode, struct file *file,
case IOC_NVRAM_GET_OFFSET: {
int part, offset;
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return -EINVAL;
if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0)
return -EFAULT;
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index f65b2e14a48..2b6a56b2bf3 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -39,8 +39,10 @@
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
+
#include <asm/uaccess.h>
-#include <asm/hvconsole.h>
+
+#include "hvc_console.h"
#define HVC_MAJOR 229
#define HVC_MINOR 0
@@ -54,17 +56,14 @@
#define HVC_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
/*
- * The Linux TTY code does not support dynamic addition of tty derived devices
- * so we need to know how many tty devices we might need when space is allocated
- * for the tty device. Since this driver supports hotplug of vty adapters we
- * need to make sure we have enough allocated.
+ * These sizes are most efficient for vio, because they are the
+ * native transfer size. We could make them selectable in the
+ * future to better deal with backends that want other buffer sizes.
*/
-#define HVC_ALLOC_TTY_ADAPTERS 8
-
#define N_OUTBUF 16
#define N_INBUF 16
-#define __ALIGNED__ __attribute__((__aligned__(8)))
+#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
static struct tty_driver *hvc_driver;
static struct task_struct *hvc_task;
@@ -154,7 +153,7 @@ static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =
void hvc_console_print(struct console *co, const char *b, unsigned count)
{
- char c[16] __ALIGNED__;
+ char c[N_OUTBUF] __ALIGNED__;
unsigned i = 0, n = 0;
int r, donecr = 0, index = co->index;
@@ -473,8 +472,10 @@ static void hvc_push(struct hvc_struct *hp)
n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
if (n <= 0) {
- if (n == 0)
+ if (n == 0) {
+ hp->do_wakeup = 1;
return;
+ }
/* throw away output on error; this happens when
there is no session connected to the vterm. */
hp->n_outbuf = 0;
@@ -486,12 +487,19 @@ static void hvc_push(struct hvc_struct *hp)
hp->do_wakeup = 1;
}
-static inline int __hvc_write_kernel(struct hvc_struct *hp,
- const unsigned char *buf, int count)
+static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
+ struct hvc_struct *hp = tty->driver_data;
unsigned long flags;
int rsize, written = 0;
+ /* This write was probably executed during a tty close. */
+ if (!hp)
+ return -EPIPE;
+
+ if (hp->count <= 0)
+ return -EIO;
+
spin_lock_irqsave(&hp->lock, flags);
/* Push pending writes */
@@ -510,26 +518,8 @@ static inline int __hvc_write_kernel(struct hvc_struct *hp,
}
spin_unlock_irqrestore(&hp->lock, flags);
- return written;
-}
-static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
- struct hvc_struct *hp = tty->driver_data;
- int written;
-
- /* This write was probably executed during a tty close. */
- if (!hp)
- return -EPIPE;
-
- if (hp->count <= 0)
- return -EIO;
-
- written = __hvc_write_kernel(hp, buf, count);
-
/*
* Racy, but harmless, kick thread if there is still pending data.
- * There really is nothing wrong with kicking the thread, even if there
- * is no buffered data.
*/
if (hp->n_outbuf)
hvc_kick();
@@ -614,6 +604,13 @@ static int hvc_poll(struct hvc_struct *hp)
spin_unlock_irqrestore(&hp->lock, flags);
tty_hangup(tty);
spin_lock_irqsave(&hp->lock, flags);
+ } else if ( n == -EAGAIN ) {
+ /*
+ * Some back-ends can only ensure a certain min
+ * num of bytes read, which may be > 'count'.
+ * Let the tty clear the flip buff to make room.
+ */
+ poll_mask |= HVC_POLL_READ;
}
break;
}
@@ -635,16 +632,7 @@ static int hvc_poll(struct hvc_struct *hp)
tty_insert_flip_char(tty, buf[i], 0);
}
- /*
- * Account for the total amount read in one loop, and if above
- * 64 bytes, we do a quick schedule loop to let the tty grok
- * the data and eventually throttle us.
- */
read_total += n;
- if (read_total >= 64) {
- poll_mask |= HVC_POLL_QUICK;
- break;
- }
}
throttled:
/* Wakeup write queue if necessary */
@@ -767,7 +755,8 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
* see if this vterm id matches one registered for console.
*/
for (i=0; i < MAX_NR_HVC_CONSOLES; i++)
- if (vtermnos[i] == hp->vtermno)
+ if (vtermnos[i] == hp->vtermno &&
+ cons_ops[i] == hp->ops)
break;
/* no matching slot, just use a counter */
@@ -823,34 +812,38 @@ EXPORT_SYMBOL(hvc_remove);
* interfaces start to become available. */
int __init hvc_init(void)
{
+ struct tty_driver *drv;
+
/* We need more than hvc_count adapters due to hotplug additions. */
- hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
- if (!hvc_driver)
+ drv = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
+ if (!drv)
return -ENOMEM;
- hvc_driver->owner = THIS_MODULE;
- hvc_driver->devfs_name = "hvc/";
- hvc_driver->driver_name = "hvc";
- hvc_driver->name = "hvc";
- hvc_driver->major = HVC_MAJOR;
- hvc_driver->minor_start = HVC_MINOR;
- hvc_driver->type = TTY_DRIVER_TYPE_SYSTEM;
- hvc_driver->init_termios = tty_std_termios;
- hvc_driver->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(hvc_driver, &hvc_ops);
+ drv->owner = THIS_MODULE;
+ drv->devfs_name = "hvc/";
+ drv->driver_name = "hvc";
+ drv->name = "hvc";
+ drv->major = HVC_MAJOR;
+ drv->minor_start = HVC_MINOR;
+ drv->type = TTY_DRIVER_TYPE_SYSTEM;
+ drv->init_termios = tty_std_termios;
+ drv->flags = TTY_DRIVER_REAL_RAW;
+ tty_set_operations(drv, &hvc_ops);
/* Always start the kthread because there can be hotplug vty adapters
* added later. */
hvc_task = kthread_run(khvcd, NULL, "khvcd");
if (IS_ERR(hvc_task)) {
panic("Couldn't create kthread for console.\n");
- put_tty_driver(hvc_driver);
+ put_tty_driver(drv);
return -EIO;
}
- if (tty_register_driver(hvc_driver))
+ if (tty_register_driver(drv))
panic("Couldn't register hvc console driver\n");
+ mb();
+ hvc_driver = drv;
return 0;
}
module_init(hvc_init);
diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h
new file mode 100644
index 00000000000..96b7401319c
--- /dev/null
+++ b/drivers/char/hvc_console.h
@@ -0,0 +1,63 @@
+/*
+ * hvc_console.h
+ * Copyright (C) 2005 IBM Corporation
+ *
+ * Author(s):
+ * Ryan S. Arnold <rsa@us.ibm.com>
+ *
+ * hvc_console header information:
+ * moved here from include/asm-powerpc/hvconsole.h
+ * and drivers/char/hvc_console.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef HVC_CONSOLE_H
+#define HVC_CONSOLE_H
+
+/*
+ * This is the max number of console adapters that can/will be found as
+ * console devices on first stage console init. Any number beyond this range
+ * can't be used as a console device but is still a valid tty device.
+ */
+#define MAX_NR_HVC_CONSOLES 16
+
+/*
+ * The Linux TTY code does not support dynamic addition of tty derived devices
+ * so we need to know how many tty devices we might need when space is allocated
+ * for the tty device. Since this driver supports hotplug of vty adapters we
+ * need to make sure we have enough allocated.
+ */
+#define HVC_ALLOC_TTY_ADAPTERS 8
+
+
+/* implemented by a low level driver */
+struct hv_ops {
+ int (*get_chars)(uint32_t vtermno, char *buf, int count);
+ int (*put_chars)(uint32_t vtermno, const char *buf, int count);
+};
+
+struct hvc_struct;
+
+/* Register a vterm and a slot index for use as a console (console_init) */
+extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops);
+
+/* register a vterm for hvc tty operation (module_init or hotplug add) */
+extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq,
+ struct hv_ops *ops);
+/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */
+extern int __devexit hvc_remove(struct hvc_struct *hp);
+
+#endif // HVC_CONSOLE_H
diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c
new file mode 100644
index 00000000000..83364ea63cb
--- /dev/null
+++ b/drivers/char/hvc_rtas.c
@@ -0,0 +1,138 @@
+/*
+ * IBM RTAS driver interface to hvc_console.c
+ *
+ * (C) Copyright IBM Corporation 2001-2005
+ * (C) Copyright Red Hat, Inc. 2005
+ *
+ * Author(s): Maximino Augilar <IBM STI Design Center>
+ * : Ryan S. Arnold <rsa@us.ibm.com>
+ * : Utz Bacher <utz.bacher@de.ibm.com>
+ * : David Woodhouse <dwmw2@infradead.org>
+ *
+ * inspired by drivers/char/hvc_console.c
+ * written by Anton Blanchard and 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+
+#include <asm/irq.h>
+#include <asm/rtas.h>
+#include "hvc_console.h"
+
+#define hvc_rtas_cookie 0x67781e15
+struct hvc_struct *hvc_rtas_dev;
+
+#define RTASCONS_PUT_ATTEMPTS 16
+
+static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE;
+static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE;
+static int rtascons_put_delay = 100;
+module_param_named(put_delay, rtascons_put_delay, int, 0644);
+
+static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, int count)
+{
+ int done;
+
+ /* if there is more than one character to be displayed, wait a bit */
+ for (done = 0; done < count; done++) {
+ int result;
+ result = rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[done]);
+ if (result)
+ break;
+ }
+ /* the calling routine expects to receive the number of bytes sent */
+ return done;
+}
+
+static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ int c, err;
+
+ err = rtas_call(rtascons_get_char_token, 0, 2, &c);
+ if (err)
+ break;
+
+ buf[i] = c;
+ }
+
+ return i;
+}
+
+static struct hv_ops hvc_rtas_get_put_ops = {
+ .get_chars = hvc_rtas_read_console,
+ .put_chars = hvc_rtas_write_console,
+};
+
+static int hvc_rtas_init(void)
+{
+ struct hvc_struct *hp;
+
+ if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
+ rtascons_put_char_token = rtas_token("put-term-char");
+ if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
+ return -EIO;
+
+ if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
+ rtascons_get_char_token = rtas_token("get-term-char");
+ if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
+ return -EIO;
+
+ BUG_ON(hvc_rtas_dev);
+
+ /* Allocate an hvc_struct for the console device we instantiated
+ * earlier. Save off hp so that we can return it on exit */
+ hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops);
+ if (IS_ERR(hp))
+ return PTR_ERR(hp);
+ hvc_rtas_dev = hp;
+ return 0;
+}
+module_init(hvc_rtas_init);
+
+/* This will tear down the tty portion of the driver */
+static void __exit hvc_rtas_exit(void)
+{
+ /* Really the fun isn't over until the worker thread breaks down and the
+ * tty cleans up */
+ if (hvc_rtas_dev)
+ hvc_remove(hvc_rtas_dev);
+}
+module_exit(hvc_rtas_exit);
+
+/* This will happen prior to module init. There is no tty at this time? */
+static int hvc_rtas_console_init(void)
+{
+ rtascons_put_char_token = rtas_token("put-term-char");
+ if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
+ return -EIO;
+ rtascons_get_char_token = rtas_token("get-term-char");
+ if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
+ return -EIO;
+
+ hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops );
+ add_preferred_console("hvc", 0, NULL);
+ return 0;
+}
+console_initcall(hvc_rtas_console_init);
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c
index f5212eb2b41..9add81ceb44 100644
--- a/drivers/char/hvc_vio.c
+++ b/drivers/char/hvc_vio.c
@@ -31,10 +31,13 @@
#include <linux/types.h>
#include <linux/init.h>
+
#include <asm/hvconsole.h>
#include <asm/vio.h>
#include <asm/prom.h>
+#include "hvc_console.h"
+
char hvc_driver_name[] = "hvc_console";
static struct vio_device_id hvc_driver_table[] __devinitdata = {
@@ -48,6 +51,14 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
unsigned long got;
int i;
+ /*
+ * Vio firmware will read up to SIZE_VIO_GET_CHARS at its own discretion
+ * so we play safe and avoid the situation where got > count which could
+ * overload the flip buffer.
+ */
+ if (count < SIZE_VIO_GET_CHARS)
+ return -EAGAIN;
+
got = hvc_get_chars(vtermno, buf, count);
/*
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index f7ac3185657..327b00c3c45 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -439,7 +439,6 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
char buf[HVCS_BUFF_LEN] __ALIGNED__;
unsigned long flags;
int got = 0;
- int i;
spin_lock_irqsave(&hvcsd->lock, flags);
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 7c0684deea0..932feedda26 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -90,7 +90,7 @@ static unsigned int ipmi_poll(struct file *file, poll_table *wait)
spin_lock_irqsave(&priv->recv_msg_lock, flags);
- if (! list_empty(&(priv->recv_msgs)))
+ if (!list_empty(&(priv->recv_msgs)))
mask |= (POLLIN | POLLRDNORM);
spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
@@ -789,21 +789,53 @@ MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By"
" interface. Other values will set the major device number"
" to that value.");
+/* Keep track of the devices that are registered. */
+struct ipmi_reg_list {
+ dev_t dev;
+ struct list_head link;
+};
+static LIST_HEAD(reg_list);
+static DEFINE_MUTEX(reg_list_mutex);
+
static struct class *ipmi_class;
-static void ipmi_new_smi(int if_num)
+static void ipmi_new_smi(int if_num, struct device *device)
{
dev_t dev = MKDEV(ipmi_major, if_num);
+ struct ipmi_reg_list *entry;
devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
"ipmidev/%d", if_num);
- class_device_create(ipmi_class, NULL, dev, NULL, "ipmi%d", if_num);
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry) {
+ printk(KERN_ERR "ipmi_devintf: Unable to create the"
+ " ipmi class device link\n");
+ return;
+ }
+ entry->dev = dev;
+
+ mutex_lock(&reg_list_mutex);
+ class_device_create(ipmi_class, NULL, dev, device, "ipmi%d", if_num);
+ list_add(&entry->link, &reg_list);
+ mutex_unlock(&reg_list_mutex);
}
static void ipmi_smi_gone(int if_num)
{
- class_device_destroy(ipmi_class, MKDEV(ipmi_major, if_num));
+ dev_t dev = MKDEV(ipmi_major, if_num);
+ struct ipmi_reg_list *entry;
+
+ mutex_lock(&reg_list_mutex);
+ list_for_each_entry(entry, &reg_list, link) {
+ if (entry->dev == dev) {
+ list_del(&entry->link);
+ kfree(entry);
+ break;
+ }
+ }
+ class_device_destroy(ipmi_class, dev);
+ mutex_unlock(&reg_list_mutex);
devfs_remove("ipmidev/%d", if_num);
}
@@ -856,6 +888,14 @@ module_init(init_ipmi_devintf);
static __exit void cleanup_ipmi(void)
{
+ struct ipmi_reg_list *entry, *entry2;
+ mutex_lock(&reg_list_mutex);
+ list_for_each_entry_safe(entry, entry2, &reg_list, link) {
+ list_del(&entry->link);
+ class_device_destroy(ipmi_class, entry->dev);
+ kfree(entry);
+ }
+ mutex_unlock(&reg_list_mutex);
class_destroy(ipmi_class);
ipmi_smi_watcher_unregister(&smi_watcher);
devfs_remove(DEVICE_NAME);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index d745004281d..40eb005b9d7 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -48,7 +48,7 @@
#define PFX "IPMI message handler: "
-#define IPMI_DRIVER_VERSION "38.0"
+#define IPMI_DRIVER_VERSION "39.0"
static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
static int ipmi_init_msghandler(void);
@@ -162,6 +162,28 @@ struct ipmi_proc_entry
};
#endif
+struct bmc_device
+{
+ struct platform_device *dev;
+ struct ipmi_device_id id;
+ unsigned char guid[16];
+ int guid_set;
+
+ struct kref refcount;
+
+ /* bmc device attributes */
+ struct device_attribute device_id_attr;
+ struct device_attribute provides_dev_sdrs_attr;
+ struct device_attribute revision_attr;
+ struct device_attribute firmware_rev_attr;
+ struct device_attribute version_attr;
+ struct device_attribute add_dev_support_attr;
+ struct device_attribute manufacturer_id_attr;
+ struct device_attribute product_id_attr;
+ struct device_attribute guid_attr;
+ struct device_attribute aux_firmware_rev_attr;
+};
+
#define IPMI_IPMB_NUM_SEQ 64
#define IPMI_MAX_CHANNELS 16
struct ipmi_smi
@@ -178,9 +200,8 @@ struct ipmi_smi
/* Used for wake ups at startup. */
wait_queue_head_t waitq;
- /* The IPMI version of the BMC on the other end. */
- unsigned char version_major;
- unsigned char version_minor;
+ struct bmc_device *bmc;
+ char *my_dev_name;
/* This is the lower-layer's sender routine. */
struct ipmi_smi_handlers *handlers;
@@ -194,6 +215,9 @@ struct ipmi_smi
struct ipmi_proc_entry *proc_entries;
#endif
+ /* Driver-model device for the system interface. */
+ struct device *si_dev;
+
/* A table of sequence numbers for this interface. We use the
sequence numbers for IPMB messages that go out of the
interface to match them up with their responses. A routine
@@ -312,6 +336,7 @@ struct ipmi_smi
/* Events that were received with the proper format. */
unsigned int events;
};
+#define to_si_intf_from_dev(device) container_of(device, struct ipmi_smi, dev)
/* Used to mark an interface entry that cannot be used but is not a
* free entry, either, primarily used at creation and deletion time so
@@ -320,6 +345,15 @@ struct ipmi_smi
#define IPMI_INVALID_INTERFACE(i) (((i) == NULL) \
|| (i == IPMI_INVALID_INTERFACE_ENTRY))
+/**
+ * The driver model view of the IPMI messaging driver.
+ */
+static struct device_driver ipmidriver = {
+ .name = "ipmi",
+ .bus = &platform_bus_type
+};
+static DEFINE_MUTEX(ipmidriver_mutex);
+
#define MAX_IPMI_INTERFACES 4
static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES];
@@ -393,7 +427,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
if (IPMI_INVALID_INTERFACE(intf))
continue;
spin_unlock_irqrestore(&interfaces_lock, flags);
- watcher->new_smi(i);
+ watcher->new_smi(i, intf->si_dev);
spin_lock_irqsave(&interfaces_lock, flags);
}
spin_unlock_irqrestore(&interfaces_lock, flags);
@@ -409,14 +443,14 @@ int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher)
}
static void
-call_smi_watchers(int i)
+call_smi_watchers(int i, struct device *dev)
{
struct ipmi_smi_watcher *w;
down_read(&smi_watchers_sem);
list_for_each_entry(w, &smi_watchers, link) {
if (try_module_get(w->owner)) {
- w->new_smi(i);
+ w->new_smi(i, dev);
module_put(w->owner);
}
}
@@ -736,7 +770,8 @@ int ipmi_create_user(unsigned int if_num,
intf = ipmi_interfaces[if_num];
if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) {
spin_unlock_irqrestore(&interfaces_lock, flags);
- return -EINVAL;
+ rv = -EINVAL;
+ goto out_kfree;
}
/* Note that each existing user holds a refcount to the interface. */
@@ -751,14 +786,14 @@ int ipmi_create_user(unsigned int if_num,
if (!try_module_get(intf->handlers->owner)) {
rv = -ENODEV;
- goto out_err;
+ goto out_kref;
}
if (intf->handlers->inc_usecount) {
rv = intf->handlers->inc_usecount(intf->send_info);
if (rv) {
module_put(intf->handlers->owner);
- goto out_err;
+ goto out_kref;
}
}
@@ -769,9 +804,10 @@ int ipmi_create_user(unsigned int if_num,
*user = new_user;
return 0;
- out_err:
- kfree(new_user);
+out_kref:
kref_put(&intf->refcount, intf_free);
+out_kfree:
+ kfree(new_user);
return rv;
}
@@ -842,8 +878,8 @@ void ipmi_get_version(ipmi_user_t user,
unsigned char *major,
unsigned char *minor)
{
- *major = user->intf->version_major;
- *minor = user->intf->version_minor;
+ *major = ipmi_version_major(&user->intf->bmc->id);
+ *minor = ipmi_version_minor(&user->intf->bmc->id);
}
int ipmi_set_my_address(ipmi_user_t user,
@@ -1551,7 +1587,8 @@ static int version_file_read_proc(char *page, char **start, off_t off,
ipmi_smi_t intf = data;
return sprintf(out, "%d.%d\n",
- intf->version_major, intf->version_minor);
+ ipmi_version_major(&intf->bmc->id),
+ ipmi_version_minor(&intf->bmc->id));
}
static int stat_file_read_proc(char *page, char **start, off_t off,
@@ -1710,6 +1747,470 @@ static void remove_proc_entries(ipmi_smi_t smi)
#endif /* CONFIG_PROC_FS */
}
+static int __find_bmc_guid(struct device *dev, void *data)
+{
+ unsigned char *id = data;
+ struct bmc_device *bmc = dev_get_drvdata(dev);
+ return memcmp(bmc->guid, id, 16) == 0;
+}
+
+static struct bmc_device *ipmi_find_bmc_guid(struct device_driver *drv,
+ unsigned char *guid)
+{
+ struct device *dev;
+
+ dev = driver_find_device(drv, NULL, guid, __find_bmc_guid);
+ if (dev)
+ return dev_get_drvdata(dev);
+ else
+ return NULL;
+}
+
+struct prod_dev_id {
+ unsigned int product_id;
+ unsigned char device_id;
+};
+
+static int __find_bmc_prod_dev_id(struct device *dev, void *data)
+{
+ struct prod_dev_id *id = data;
+ struct bmc_device *bmc = dev_get_drvdata(dev);
+
+ return (bmc->id.product_id == id->product_id
+ && bmc->id.product_id == id->product_id
+ && bmc->id.device_id == id->device_id);
+}
+
+static struct bmc_device *ipmi_find_bmc_prod_dev_id(
+ struct device_driver *drv,
+ unsigned char product_id, unsigned char device_id)
+{
+ struct prod_dev_id id = {
+ .product_id = product_id,
+ .device_id = device_id,
+ };
+ struct device *dev;
+
+ dev = driver_find_device(drv, NULL, &id, __find_bmc_prod_dev_id);
+ if (dev)
+ return dev_get_drvdata(dev);
+ else
+ return NULL;
+}
+
+static ssize_t device_id_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bmc_device *bmc = dev_get_drvdata(dev);
+
+ return snprintf(buf, 10, "%u\n", bmc->id.device_id);
+}
+
+static ssize_t provides_dev_sdrs_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bmc_device *bmc = dev_get_drvdata(dev);
+
+ return snprintf(buf, 10, "%u\n",
+ bmc->id.device_revision && 0x80 >> 7);
+}
+
+static ssize_t revision_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct bmc_device *bmc = dev_get_drvdata(dev);
+
+ return snprintf(buf, 20, "%u\n",
+ bmc->id.device_revision && 0x0F);
+}
+
+static ssize_t firmware_rev_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bmc_device *bmc = dev_get_drvdata(dev);
+
+ return snprintf(buf, 20, "%u.%x\n", bmc->id.firmware_revision_1,
+ bmc->id.firmware_revision_2);
+}
+
+static ssize_t ipmi_version_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bmc_device *bmc = dev_get_drvdata(dev);
+
+ return snprintf(buf, 20, "%u.%u\n",
+ ipmi_version_major(&bmc->id),
+ ipmi_version_minor(&bmc->id));
+}
+
+static ssize_t add_dev_support_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bmc_device *bmc = dev_get_drvdata(dev);
+
+ return snprintf(buf, 10, "0x%02x\n",
+ bmc->id.additional_device_support);
+}
+
+static ssize_t manufacturer_id_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bmc_device *bmc = dev_get_drvdata(dev);
+
+ return snprintf(buf, 20, "0x%6.6x\n", bmc->id.manufacturer_id);
+}
+
+static ssize_t product_id_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bmc_device *bmc = dev_get_drvdata(dev);
+
+ return snprintf(buf, 10, "0x%4.4x\n", bmc->id.product_id);
+}
+
+static ssize_t aux_firmware_rev_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bmc_device *bmc = dev_get_drvdata(dev);
+
+ return snprintf(buf, 21, "0x%02x 0x%02x 0x%02x 0x%02x\n",
+ bmc->id.aux_firmware_revision[3],
+ bmc->id.aux_firmware_revision[2],
+ bmc->id.aux_firmware_revision[1],
+ bmc->id.aux_firmware_revision[0]);
+}
+
+static ssize_t guid_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct bmc_device *bmc = dev_get_drvdata(dev);
+
+ return snprintf(buf, 100, "%Lx%Lx\n",
+ (long long) bmc->guid[0],
+ (long long) bmc->guid[8]);
+}
+
+static void
+cleanup_bmc_device(struct kref *ref)
+{
+ struct bmc_device *bmc;
+
+ bmc = container_of(ref, struct bmc_device, refcount);
+
+ device_remove_file(&bmc->dev->dev,
+ &bmc->device_id_attr);
+ device_remove_file(&bmc->dev->dev,
+ &bmc->provides_dev_sdrs_attr);
+ device_remove_file(&bmc->dev->dev,
+ &bmc->revision_attr);
+ device_remove_file(&bmc->dev->dev,
+ &bmc->firmware_rev_attr);
+ device_remove_file(&bmc->dev->dev,
+ &bmc->version_attr);
+ device_remove_file(&bmc->dev->dev,
+ &bmc->add_dev_support_attr);
+ device_remove_file(&bmc->dev->dev,
+ &bmc->manufacturer_id_attr);
+ device_remove_file(&bmc->dev->dev,
+ &bmc->product_id_attr);
+ if (bmc->id.aux_firmware_revision_set)
+ device_remove_file(&bmc->dev->dev,
+ &bmc->aux_firmware_rev_attr);
+ if (bmc->guid_set)
+ device_remove_file(&bmc->dev->dev,
+ &bmc->guid_attr);
+ platform_device_unregister(bmc->dev);
+ kfree(bmc);
+}
+
+static void ipmi_bmc_unregister(ipmi_smi_t intf)
+{
+ struct bmc_device *bmc = intf->bmc;
+
+ sysfs_remove_link(&intf->si_dev->kobj, "bmc");
+ if (intf->my_dev_name) {
+ sysfs_remove_link(&bmc->dev->dev.kobj, intf->my_dev_name);
+ kfree(intf->my_dev_name);
+ intf->my_dev_name = NULL;
+ }
+
+ mutex_lock(&ipmidriver_mutex);
+ kref_put(&bmc->refcount, cleanup_bmc_device);
+ mutex_unlock(&ipmidriver_mutex);
+}
+
+static int ipmi_bmc_register(ipmi_smi_t intf)
+{
+ int rv;
+ struct bmc_device *bmc = intf->bmc;
+ struct bmc_device *old_bmc;
+ int size;
+ char dummy[1];
+
+ mutex_lock(&ipmidriver_mutex);
+
+ /*
+ * Try to find if there is an bmc_device struct
+ * representing the interfaced BMC already
+ */
+ if (bmc->guid_set)
+ old_bmc = ipmi_find_bmc_guid(&ipmidriver, bmc->guid);
+ else
+ old_bmc = ipmi_find_bmc_prod_dev_id(&ipmidriver,
+ bmc->id.product_id,
+ bmc->id.device_id);
+
+ /*
+ * If there is already an bmc_device, free the new one,
+ * otherwise register the new BMC device
+ */
+ if (old_bmc) {
+ kfree(bmc);
+ intf->bmc = old_bmc;
+ bmc = old_bmc;
+
+ kref_get(&bmc->refcount);
+ mutex_unlock(&ipmidriver_mutex);
+
+ printk(KERN_INFO
+ "ipmi: interfacing existing BMC (man_id: 0x%6.6x,"
+ " prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n",
+ bmc->id.manufacturer_id,
+ bmc->id.product_id,
+ bmc->id.device_id);
+ } else {
+ bmc->dev = platform_device_alloc("ipmi_bmc",
+ bmc->id.device_id);
+ if (! bmc->dev) {
+ printk(KERN_ERR
+ "ipmi_msghandler:"
+ " Unable to allocate platform device\n");
+ return -ENOMEM;
+ }
+ bmc->dev->dev.driver = &ipmidriver;
+ dev_set_drvdata(&bmc->dev->dev, bmc);
+ kref_init(&bmc->refcount);
+
+ rv = platform_device_register(bmc->dev);
+ mutex_unlock(&ipmidriver_mutex);
+ if (rv) {
+ printk(KERN_ERR
+ "ipmi_msghandler:"
+ " Unable to register bmc device: %d\n",
+ rv);
+ /* Don't go to out_err, you can only do that if
+ the device is registered already. */
+ return rv;
+ }
+
+ bmc->device_id_attr.attr.name = "device_id";
+ bmc->device_id_attr.attr.owner = THIS_MODULE;
+ bmc->device_id_attr.attr.mode = S_IRUGO;
+ bmc->device_id_attr.show = device_id_show;
+
+ bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs";
+ bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE;
+ bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO;
+ bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show;
+
+
+ bmc->revision_attr.attr.name = "revision";
+ bmc->revision_attr.attr.owner = THIS_MODULE;
+ bmc->revision_attr.attr.mode = S_IRUGO;
+ bmc->revision_attr.show = revision_show;
+
+ bmc->firmware_rev_attr.attr.name = "firmware_revision";
+ bmc->firmware_rev_attr.attr.owner = THIS_MODULE;
+ bmc->firmware_rev_attr.attr.mode = S_IRUGO;
+ bmc->firmware_rev_attr.show = firmware_rev_show;
+
+ bmc->version_attr.attr.name = "ipmi_version";
+ bmc->version_attr.attr.owner = THIS_MODULE;
+ bmc->version_attr.attr.mode = S_IRUGO;
+ bmc->version_attr.show = ipmi_version_show;
+
+ bmc->add_dev_support_attr.attr.name
+ = "additional_device_support";
+ bmc->add_dev_support_attr.attr.owner = THIS_MODULE;
+ bmc->add_dev_support_attr.attr.mode = S_IRUGO;
+ bmc->add_dev_support_attr.show = add_dev_support_show;
+
+ bmc->manufacturer_id_attr.attr.name = "manufacturer_id";
+ bmc->manufacturer_id_attr.attr.owner = THIS_MODULE;
+ bmc->manufacturer_id_attr.attr.mode = S_IRUGO;
+ bmc->manufacturer_id_attr.show = manufacturer_id_show;
+
+ bmc->product_id_attr.attr.name = "product_id";
+ bmc->product_id_attr.attr.owner = THIS_MODULE;
+ bmc->product_id_attr.attr.mode = S_IRUGO;
+ bmc->product_id_attr.show = product_id_show;
+
+ bmc->guid_attr.attr.name = "guid";
+ bmc->guid_attr.attr.owner = THIS_MODULE;
+ bmc->guid_attr.attr.mode = S_IRUGO;
+ bmc->guid_attr.show = guid_show;
+
+ bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision";
+ bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE;
+ bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO;
+ bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show;
+
+ device_create_file(&bmc->dev->dev,
+ &bmc->device_id_attr);
+ device_create_file(&bmc->dev->dev,
+ &bmc->provides_dev_sdrs_attr);
+ device_create_file(&bmc->dev->dev,
+ &bmc->revision_attr);
+ device_create_file(&bmc->dev->dev,
+ &bmc->firmware_rev_attr);
+ device_create_file(&bmc->dev->dev,
+ &bmc->version_attr);
+ device_create_file(&bmc->dev->dev,
+ &bmc->add_dev_support_attr);
+ device_create_file(&bmc->dev->dev,
+ &bmc->manufacturer_id_attr);
+ device_create_file(&bmc->dev->dev,
+ &bmc->product_id_attr);
+ if (bmc->id.aux_firmware_revision_set)
+ device_create_file(&bmc->dev->dev,
+ &bmc->aux_firmware_rev_attr);
+ if (bmc->guid_set)
+ device_create_file(&bmc->dev->dev,
+ &bmc->guid_attr);
+
+ printk(KERN_INFO
+ "ipmi: Found new BMC (man_id: 0x%6.6x, "
+ " prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n",
+ bmc->id.manufacturer_id,
+ bmc->id.product_id,
+ bmc->id.device_id);
+ }
+
+ /*
+ * create symlink from system interface device to bmc device
+ * and back.
+ */
+ rv = sysfs_create_link(&intf->si_dev->kobj,
+ &bmc->dev->dev.kobj, "bmc");
+ if (rv) {
+ printk(KERN_ERR
+ "ipmi_msghandler: Unable to create bmc symlink: %d\n",
+ rv);
+ goto out_err;
+ }
+
+ size = snprintf(dummy, 0, "ipmi%d", intf->intf_num);
+ intf->my_dev_name = kmalloc(size+1, GFP_KERNEL);
+ if (!intf->my_dev_name) {
+ rv = -ENOMEM;
+ printk(KERN_ERR
+ "ipmi_msghandler: allocate link from BMC: %d\n",
+ rv);
+ goto out_err;
+ }
+ snprintf(intf->my_dev_name, size+1, "ipmi%d", intf->intf_num);
+
+ rv = sysfs_create_link(&bmc->dev->dev.kobj, &intf->si_dev->kobj,
+ intf->my_dev_name);
+ if (rv) {
+ kfree(intf->my_dev_name);
+ intf->my_dev_name = NULL;
+ printk(KERN_ERR
+ "ipmi_msghandler:"
+ " Unable to create symlink to bmc: %d\n",
+ rv);
+ goto out_err;
+ }
+
+ return 0;
+
+out_err:
+ ipmi_bmc_unregister(intf);
+ return rv;
+}
+
+static int
+send_guid_cmd(ipmi_smi_t intf, int chan)
+{
+ struct kernel_ipmi_msg msg;
+ struct ipmi_system_interface_addr si;
+
+ si.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+ si.channel = IPMI_BMC_CHANNEL;
+ si.lun = 0;
+
+ msg.netfn = IPMI_NETFN_APP_REQUEST;
+ msg.cmd = IPMI_GET_DEVICE_GUID_CMD;
+ msg.data = NULL;
+ msg.data_len = 0;
+ return i_ipmi_request(NULL,
+ intf,
+ (struct ipmi_addr *) &si,
+ 0,
+ &msg,
+ intf,
+ NULL,
+ NULL,
+ 0,
+ intf->channels[0].address,
+ intf->channels[0].lun,
+ -1, 0);
+}
+
+static void
+guid_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
+{
+ if ((msg->addr.addr_type != IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+ || (msg->msg.netfn != IPMI_NETFN_APP_RESPONSE)
+ || (msg->msg.cmd != IPMI_GET_DEVICE_GUID_CMD))
+ /* Not for me */
+ return;
+
+ if (msg->msg.data[0] != 0) {
+ /* Error from getting the GUID, the BMC doesn't have one. */
+ intf->bmc->guid_set = 0;
+ goto out;
+ }
+
+ if (msg->msg.data_len < 17) {
+ intf->bmc->guid_set = 0;
+ printk(KERN_WARNING PFX
+ "guid_handler: The GUID response from the BMC was too"
+ " short, it was %d but should have been 17. Assuming"
+ " GUID is not available.\n",
+ msg->msg.data_len);
+ goto out;
+ }
+
+ memcpy(intf->bmc->guid, msg->msg.data, 16);
+ intf->bmc->guid_set = 1;
+ out:
+ wake_up(&intf->waitq);
+}
+
+static void
+get_guid(ipmi_smi_t intf)
+{
+ int rv;
+
+ intf->bmc->guid_set = 0x2;
+ intf->null_user_handler = guid_handler;
+ rv = send_guid_cmd(intf, 0);
+ if (rv)
+ /* Send failed, no GUID available. */
+ intf->bmc->guid_set = 0;
+ wait_event(intf->waitq, intf->bmc->guid_set != 2);
+ intf->null_user_handler = NULL;
+}
+
static int
send_channel_info_cmd(ipmi_smi_t intf, int chan)
{
@@ -1802,8 +2303,8 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
void *send_info,
- unsigned char version_major,
- unsigned char version_minor,
+ struct ipmi_device_id *device_id,
+ struct device *si_dev,
unsigned char slave_addr,
ipmi_smi_t *new_intf)
{
@@ -1811,7 +2312,11 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
int rv;
ipmi_smi_t intf;
unsigned long flags;
+ int version_major;
+ int version_minor;
+ version_major = ipmi_version_major(device_id);
+ version_minor = ipmi_version_minor(device_id);
/* Make sure the driver is actually initialized, this handles
problems with initialization order. */
@@ -1829,10 +2334,15 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
if (!intf)
return -ENOMEM;
memset(intf, 0, sizeof(*intf));
+ intf->bmc = kzalloc(sizeof(*intf->bmc), GFP_KERNEL);
+ if (!intf->bmc) {
+ kfree(intf);
+ return -ENOMEM;
+ }
intf->intf_num = -1;
kref_init(&intf->refcount);
- intf->version_major = version_major;
- intf->version_minor = version_minor;
+ intf->bmc->id = *device_id;
+ intf->si_dev = si_dev;
for (j = 0; j < IPMI_MAX_CHANNELS; j++) {
intf->channels[j].address = IPMI_BMC_SLAVE_ADDR;
intf->channels[j].lun = 2;
@@ -1882,6 +2392,8 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
caller before sending any messages with it. */
*new_intf = intf;
+ get_guid(intf);
+
if ((version_major > 1)
|| ((version_major == 1) && (version_minor >= 5)))
{
@@ -1896,6 +2408,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
/* Wait for the channel info to be read. */
wait_event(intf->waitq,
intf->curr_channel >= IPMI_MAX_CHANNELS);
+ intf->null_user_handler = NULL;
} else {
/* Assume a single IPMB channel at zero. */
intf->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB;
@@ -1905,6 +2418,8 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
if (rv == 0)
rv = add_proc_entries(intf, i);
+ rv = ipmi_bmc_register(intf);
+
out:
if (rv) {
if (intf->proc_dir)
@@ -1919,7 +2434,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
spin_lock_irqsave(&interfaces_lock, flags);
ipmi_interfaces[i] = intf;
spin_unlock_irqrestore(&interfaces_lock, flags);
- call_smi_watchers(i);
+ call_smi_watchers(i, intf->si_dev);
}
return rv;
@@ -1931,6 +2446,8 @@ int ipmi_unregister_smi(ipmi_smi_t intf)
struct ipmi_smi_watcher *w;
unsigned long flags;
+ ipmi_bmc_unregister(intf);
+
spin_lock_irqsave(&interfaces_lock, flags);
for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
if (ipmi_interfaces[i] == intf) {
@@ -3194,10 +3711,17 @@ static struct notifier_block panic_block = {
static int ipmi_init_msghandler(void)
{
int i;
+ int rv;
if (initialized)
return 0;
+ rv = driver_register(&ipmidriver);
+ if (rv) {
+ printk(KERN_ERR PFX "Could not register IPMI driver\n");
+ return rv;
+ }
+
printk(KERN_INFO "ipmi message handler version "
IPMI_DRIVER_VERSION "\n");
@@ -3220,7 +3744,7 @@ static int ipmi_init_msghandler(void)
ipmi_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES;
add_timer(&ipmi_timer);
- notifier_chain_register(&panic_notifier_list, &panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
initialized = 1;
@@ -3240,7 +3764,7 @@ static __exit void cleanup_ipmi(void)
if (!initialized)
return;
- notifier_chain_unregister(&panic_notifier_list, &panic_block);
+ atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block);
/* This can't be called if any interfaces exist, so no worry about
shutting down the interfaces. */
@@ -3254,6 +3778,8 @@ static __exit void cleanup_ipmi(void)
remove_proc_entry(proc_ipmi_root->name, &proc_root);
#endif /* CONFIG_PROC_FS */
+ driver_unregister(&ipmidriver);
+
initialized = 0;
/* Check for buffer leaks. */
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index e8ed26b77d4..786a2802ca3 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -464,7 +464,7 @@ static void ipmi_poweroff_function (void)
/* Wait for an IPMI interface to be installed, the first one installed
will be grabbed by this code and used to perform the powerdown. */
-static void ipmi_po_new_smi(int if_num)
+static void ipmi_po_new_smi(int if_num, struct device *device)
{
struct ipmi_system_interface_addr smi_addr;
struct kernel_ipmi_msg send_msg;
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index e59b638766e..35fbd4d8ed4 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -52,6 +52,7 @@
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/notifier.h>
+#include <linux/mutex.h>
#include <linux/kthread.h>
#include <asm/irq.h>
#ifdef CONFIG_HIGH_RES_TIMERS
@@ -109,21 +110,15 @@ enum si_intf_state {
enum si_type {
SI_KCS, SI_SMIC, SI_BT
};
+static char *si_to_str[] = { "KCS", "SMIC", "BT" };
-struct ipmi_device_id {
- unsigned char device_id;
- unsigned char device_revision;
- unsigned char firmware_revision_1;
- unsigned char firmware_revision_2;
- unsigned char ipmi_version;
- unsigned char additional_device_support;
- unsigned char manufacturer_id[3];
- unsigned char product_id[2];
- unsigned char aux_firmware_revision[4];
-} __attribute__((packed));
-
-#define ipmi_version_major(v) ((v)->ipmi_version & 0xf)
-#define ipmi_version_minor(v) ((v)->ipmi_version >> 4)
+#define DEVICE_NAME "ipmi_si"
+
+static struct device_driver ipmi_driver =
+{
+ .name = DEVICE_NAME,
+ .bus = &platform_bus_type
+};
struct smi_info
{
@@ -147,6 +142,9 @@ struct smi_info
int (*irq_setup)(struct smi_info *info);
void (*irq_cleanup)(struct smi_info *info);
unsigned int io_size;
+ char *addr_source; /* ACPI, PCI, SMBIOS, hardcode, default. */
+ void (*addr_source_cleanup)(struct smi_info *info);
+ void *addr_source_data;
/* Per-OEM handler, called from handle_flags().
Returns 1 when handle_flags() needs to be re-run
@@ -203,8 +201,17 @@ struct smi_info
interrupts. */
int interrupt_disabled;
+ /* From the get device id response... */
struct ipmi_device_id device_id;
+ /* Driver model stuff. */
+ struct device *dev;
+ struct platform_device *pdev;
+
+ /* True if we allocated the device, false if it came from
+ * someplace else (like PCI). */
+ int dev_registered;
+
/* Slave address, could be reported from DMI. */
unsigned char slave_addr;
@@ -224,12 +231,16 @@ struct smi_info
unsigned long incoming_messages;
struct task_struct *thread;
+
+ struct list_head link;
};
-static struct notifier_block *xaction_notifier_list;
+static int try_smi_init(struct smi_info *smi);
+
+static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list);
static int register_xaction_notifier(struct notifier_block * nb)
{
- return notifier_chain_register(&xaction_notifier_list, nb);
+ return atomic_notifier_chain_register(&xaction_notifier_list, nb);
}
static void si_restart_short_timer(struct smi_info *smi_info);
@@ -271,13 +282,13 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
spin_lock(&(smi_info->msg_lock));
/* Pick the high priority queue first. */
- if (! list_empty(&(smi_info->hp_xmit_msgs))) {
+ if (!list_empty(&(smi_info->hp_xmit_msgs))) {
entry = smi_info->hp_xmit_msgs.next;
- } else if (! list_empty(&(smi_info->xmit_msgs))) {
+ } else if (!list_empty(&(smi_info->xmit_msgs))) {
entry = smi_info->xmit_msgs.next;
}
- if (! entry) {
+ if (!entry) {
smi_info->curr_msg = NULL;
rv = SI_SM_IDLE;
} else {
@@ -291,7 +302,8 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
do_gettimeofday(&t);
printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
#endif
- err = notifier_call_chain(&xaction_notifier_list, 0, smi_info);
+ err = atomic_notifier_call_chain(&xaction_notifier_list,
+ 0, smi_info);
if (err & NOTIFY_STOP_MASK) {
rv = SI_SM_CALL_WITHOUT_DELAY;
goto out;
@@ -344,7 +356,7 @@ static void start_clear_flags(struct smi_info *smi_info)
memory, we will re-enable the interrupt. */
static inline void disable_si_irq(struct smi_info *smi_info)
{
- if ((smi_info->irq) && (! smi_info->interrupt_disabled)) {
+ if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
disable_irq_nosync(smi_info->irq);
smi_info->interrupt_disabled = 1;
}
@@ -375,7 +387,7 @@ static void handle_flags(struct smi_info *smi_info)
} else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) {
/* Messages available. */
smi_info->curr_msg = ipmi_alloc_smi_msg();
- if (! smi_info->curr_msg) {
+ if (!smi_info->curr_msg) {
disable_si_irq(smi_info);
smi_info->si_state = SI_NORMAL;
return;
@@ -394,7 +406,7 @@ static void handle_flags(struct smi_info *smi_info)
} else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) {
/* Events available. */
smi_info->curr_msg = ipmi_alloc_smi_msg();
- if (! smi_info->curr_msg) {
+ if (!smi_info->curr_msg) {
disable_si_irq(smi_info);
smi_info->si_state = SI_NORMAL;
return;
@@ -430,7 +442,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
#endif
switch (smi_info->si_state) {
case SI_NORMAL:
- if (! smi_info->curr_msg)
+ if (!smi_info->curr_msg)
break;
smi_info->curr_msg->rsp_size
@@ -880,7 +892,7 @@ static void smi_timeout(unsigned long data)
smi_info->last_timeout_jiffies = jiffies_now;
- if ((smi_info->irq) && (! smi_info->interrupt_disabled)) {
+ if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
/* Running with interrupts, only do long timeouts. */
smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
spin_lock_irqsave(&smi_info->count_lock, flags);
@@ -974,15 +986,10 @@ static struct ipmi_smi_handlers handlers =
a default IO port, and 1 ACPI/SPMI address. That sets SI_MAX_DRIVERS */
#define SI_MAX_PARMS 4
-#define SI_MAX_DRIVERS ((SI_MAX_PARMS * 2) + 2)
-static struct smi_info *smi_infos[SI_MAX_DRIVERS] =
-{ NULL, NULL, NULL, NULL };
+static LIST_HEAD(smi_infos);
+static DECLARE_MUTEX(smi_infos_lock);
+static int smi_num; /* Used to sequence the SMIs */
-#define DEVICE_NAME "ipmi_si"
-
-#define DEFAULT_KCS_IO_PORT 0xca2
-#define DEFAULT_SMIC_IO_PORT 0xca9
-#define DEFAULT_BT_IO_PORT 0xe4
#define DEFAULT_REGSPACING 1
static int si_trydefaults = 1;
@@ -1053,38 +1060,23 @@ MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave address for"
" by interface number.");
+#define IPMI_IO_ADDR_SPACE 0
#define IPMI_MEM_ADDR_SPACE 1
-#define IPMI_IO_ADDR_SPACE 2
+static char *addr_space_to_str[] = { "I/O", "memory" };
-#if defined(CONFIG_ACPI) || defined(CONFIG_DMI) || defined(CONFIG_PCI)
-static int is_new_interface(int intf, u8 addr_space, unsigned long base_addr)
+static void std_irq_cleanup(struct smi_info *info)
{
- int i;
-
- for (i = 0; i < SI_MAX_PARMS; ++i) {
- /* Don't check our address. */
- if (i == intf)
- continue;
- if (si_type[i] != NULL) {
- if ((addr_space == IPMI_MEM_ADDR_SPACE &&
- base_addr == addrs[i]) ||
- (addr_space == IPMI_IO_ADDR_SPACE &&
- base_addr == ports[i]))
- return 0;
- }
- else
- break;
- }
-
- return 1;
+ if (info->si_type == SI_BT)
+ /* Disable the interrupt in the BT interface. */
+ info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, 0);
+ free_irq(info->irq, info);
}
-#endif
static int std_irq_setup(struct smi_info *info)
{
int rv;
- if (! info->irq)
+ if (!info->irq)
return 0;
if (info->si_type == SI_BT) {
@@ -1093,7 +1085,7 @@ static int std_irq_setup(struct smi_info *info)
SA_INTERRUPT,
DEVICE_NAME,
info);
- if (! rv)
+ if (!rv)
/* Enable the interrupt in the BT interface. */
info->io.outputb(&info->io, IPMI_BT_INTMASK_REG,
IPMI_BT_INTMASK_ENABLE_IRQ_BIT);
@@ -1110,88 +1102,77 @@ static int std_irq_setup(struct smi_info *info)
DEVICE_NAME, info->irq);
info->irq = 0;
} else {
+ info->irq_cleanup = std_irq_cleanup;
printk(" Using irq %d\n", info->irq);
}
return rv;
}
-static void std_irq_cleanup(struct smi_info *info)
-{
- if (! info->irq)
- return;
-
- if (info->si_type == SI_BT)
- /* Disable the interrupt in the BT interface. */
- info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, 0);
- free_irq(info->irq, info);
-}
-
static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)
{
- unsigned int *addr = io->info;
+ unsigned int addr = io->addr_data;
- return inb((*addr)+(offset*io->regspacing));
+ return inb(addr + (offset * io->regspacing));
}
static void port_outb(struct si_sm_io *io, unsigned int offset,
unsigned char b)
{
- unsigned int *addr = io->info;
+ unsigned int addr = io->addr_data;
- outb(b, (*addr)+(offset * io->regspacing));
+ outb(b, addr + (offset * io->regspacing));
}
static unsigned char port_inw(struct si_sm_io *io, unsigned int offset)
{
- unsigned int *addr = io->info;
+ unsigned int addr = io->addr_data;
- return (inw((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff;
+ return (inw(addr + (offset * io->regspacing)) >> io->regshift) & 0xff;
}
static void port_outw(struct si_sm_io *io, unsigned int offset,
unsigned char b)
{
- unsigned int *addr = io->info;
+ unsigned int addr = io->addr_data;
- outw(b << io->regshift, (*addr)+(offset * io->regspacing));
+ outw(b << io->regshift, addr + (offset * io->regspacing));
}
static unsigned char port_inl(struct si_sm_io *io, unsigned int offset)
{
- unsigned int *addr = io->info;
+ unsigned int addr = io->addr_data;
- return (inl((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff;
+ return (inl(addr + (offset * io->regspacing)) >> io->regshift) & 0xff;
}
static void port_outl(struct si_sm_io *io, unsigned int offset,
unsigned char b)
{
- unsigned int *addr = io->info;
+ unsigned int addr = io->addr_data;
- outl(b << io->regshift, (*addr)+(offset * io->regspacing));
+ outl(b << io->regshift, addr+(offset * io->regspacing));
}
static void port_cleanup(struct smi_info *info)
{
- unsigned int *addr = info->io.info;
- int mapsize;
+ unsigned int addr = info->io.addr_data;
+ int mapsize;
- if (addr && (*addr)) {
+ if (addr) {
mapsize = ((info->io_size * info->io.regspacing)
- (info->io.regspacing - info->io.regsize));
- release_region (*addr, mapsize);
+ release_region (addr, mapsize);
}
- kfree(info);
}
static int port_setup(struct smi_info *info)
{
- unsigned int *addr = info->io.info;
- int mapsize;
+ unsigned int addr = info->io.addr_data;
+ int mapsize;
- if (! addr || (! *addr))
+ if (!addr)
return -ENODEV;
info->io_cleanup = port_cleanup;
@@ -1225,51 +1206,11 @@ static int port_setup(struct smi_info *info)
mapsize = ((info->io_size * info->io.regspacing)
- (info->io.regspacing - info->io.regsize));
- if (request_region(*addr, mapsize, DEVICE_NAME) == NULL)
+ if (request_region(addr, mapsize, DEVICE_NAME) == NULL)
return -EIO;
return 0;
}
-static int try_init_port(int intf_num, struct smi_info **new_info)
-{
- struct smi_info *info;
-
- if (! ports[intf_num])
- return -ENODEV;
-
- if (! is_new_interface(intf_num, IPMI_IO_ADDR_SPACE,
- ports[intf_num]))
- return -ENODEV;
-
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (! info) {
- printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n");
- return -ENOMEM;
- }
- memset(info, 0, sizeof(*info));
-
- info->io_setup = port_setup;
- info->io.info = &(ports[intf_num]);
- info->io.addr = NULL;
- info->io.regspacing = regspacings[intf_num];
- if (! info->io.regspacing)
- info->io.regspacing = DEFAULT_REGSPACING;
- info->io.regsize = regsizes[intf_num];
- if (! info->io.regsize)
- info->io.regsize = DEFAULT_REGSPACING;
- info->io.regshift = regshifts[intf_num];
- info->irq = 0;
- info->irq_setup = NULL;
- *new_info = info;
-
- if (si_type[intf_num] == NULL)
- si_type[intf_num] = "kcs";
-
- printk("ipmi_si: Trying \"%s\" at I/O port 0x%x\n",
- si_type[intf_num], ports[intf_num]);
- return 0;
-}
-
static unsigned char intf_mem_inb(struct si_sm_io *io, unsigned int offset)
{
return readb((io->addr)+(offset * io->regspacing));
@@ -1321,7 +1262,7 @@ static void mem_outq(struct si_sm_io *io, unsigned int offset,
static void mem_cleanup(struct smi_info *info)
{
- unsigned long *addr = info->io.info;
+ unsigned long addr = info->io.addr_data;
int mapsize;
if (info->io.addr) {
@@ -1330,17 +1271,16 @@ static void mem_cleanup(struct smi_info *info)
mapsize = ((info->io_size * info->io.regspacing)
- (info->io.regspacing - info->io.regsize));
- release_mem_region(*addr, mapsize);
+ release_mem_region(addr, mapsize);
}
- kfree(info);
}
static int mem_setup(struct smi_info *info)
{
- unsigned long *addr = info->io.info;
+ unsigned long addr = info->io.addr_data;
int mapsize;
- if (! addr || (! *addr))
+ if (!addr)
return -ENODEV;
info->io_cleanup = mem_cleanup;
@@ -1380,57 +1320,83 @@ static int mem_setup(struct smi_info *info)
mapsize = ((info->io_size * info->io.regspacing)
- (info->io.regspacing - info->io.regsize));
- if (request_mem_region(*addr, mapsize, DEVICE_NAME) == NULL)
+ if (request_mem_region(addr, mapsize, DEVICE_NAME) == NULL)
return -EIO;
- info->io.addr = ioremap(*addr, mapsize);
+ info->io.addr = ioremap(addr, mapsize);
if (info->io.addr == NULL) {
- release_mem_region(*addr, mapsize);
+ release_mem_region(addr, mapsize);
return -EIO;
}
return 0;
}
-static int try_init_mem(int intf_num, struct smi_info **new_info)
+
+static __devinit void hardcode_find_bmc(void)
{
+ int i;
struct smi_info *info;
- if (! addrs[intf_num])
- return -ENODEV;
+ for (i = 0; i < SI_MAX_PARMS; i++) {
+ if (!ports[i] && !addrs[i])
+ continue;
- if (! is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE,
- addrs[intf_num]))
- return -ENODEV;
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return;
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (! info) {
- printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n");
- return -ENOMEM;
- }
- memset(info, 0, sizeof(*info));
+ info->addr_source = "hardcoded";
- info->io_setup = mem_setup;
- info->io.info = &addrs[intf_num];
- info->io.addr = NULL;
- info->io.regspacing = regspacings[intf_num];
- if (! info->io.regspacing)
- info->io.regspacing = DEFAULT_REGSPACING;
- info->io.regsize = regsizes[intf_num];
- if (! info->io.regsize)
- info->io.regsize = DEFAULT_REGSPACING;
- info->io.regshift = regshifts[intf_num];
- info->irq = 0;
- info->irq_setup = NULL;
- *new_info = info;
+ if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) {
+ info->si_type = SI_KCS;
+ } else if (strcmp(si_type[i], "smic") == 0) {
+ info->si_type = SI_SMIC;
+ } else if (strcmp(si_type[i], "bt") == 0) {
+ info->si_type = SI_BT;
+ } else {
+ printk(KERN_WARNING
+ "ipmi_si: Interface type specified "
+ "for interface %d, was invalid: %s\n",
+ i, si_type[i]);
+ kfree(info);
+ continue;
+ }
- if (si_type[intf_num] == NULL)
- si_type[intf_num] = "kcs";
+ if (ports[i]) {
+ /* An I/O port */
+ info->io_setup = port_setup;
+ info->io.addr_data = ports[i];
+ info->io.addr_type = IPMI_IO_ADDR_SPACE;
+ } else if (addrs[i]) {
+ /* A memory port */
+ info->io_setup = mem_setup;
+ info->io.addr_data = addrs[i];
+ info->io.addr_type = IPMI_MEM_ADDR_SPACE;
+ } else {
+ printk(KERN_WARNING
+ "ipmi_si: Interface type specified "
+ "for interface %d, "
+ "but port and address were not set or "
+ "set to zero.\n", i);
+ kfree(info);
+ continue;
+ }
- printk("ipmi_si: Trying \"%s\" at memory address 0x%lx\n",
- si_type[intf_num], addrs[intf_num]);
- return 0;
-}
+ info->io.addr = NULL;
+ info->io.regspacing = regspacings[i];
+ if (!info->io.regspacing)
+ info->io.regspacing = DEFAULT_REGSPACING;
+ info->io.regsize = regsizes[i];
+ if (!info->io.regsize)
+ info->io.regsize = DEFAULT_REGSPACING;
+ info->io.regshift = regshifts[i];
+ info->irq = irqs[i];
+ if (info->irq)
+ info->irq_setup = std_irq_setup;
+ try_smi_init(info);
+ }
+}
#ifdef CONFIG_ACPI
@@ -1470,11 +1436,19 @@ static u32 ipmi_acpi_gpe(void *context)
return ACPI_INTERRUPT_HANDLED;
}
+static void acpi_gpe_irq_cleanup(struct smi_info *info)
+{
+ if (!info->irq)
+ return;
+
+ acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe);
+}
+
static int acpi_gpe_irq_setup(struct smi_info *info)
{
acpi_status status;
- if (! info->irq)
+ if (!info->irq)
return 0;
/* FIXME - is level triggered right? */
@@ -1491,19 +1465,12 @@ static int acpi_gpe_irq_setup(struct smi_info *info)
info->irq = 0;
return -EINVAL;
} else {
+ info->irq_cleanup = acpi_gpe_irq_cleanup;
printk(" Using ACPI GPE %d\n", info->irq);
return 0;
}
}
-static void acpi_gpe_irq_cleanup(struct smi_info *info)
-{
- if (! info->irq)
- return;
-
- acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe);
-}
-
/*
* Defined at
* http://h21007.www2.hp.com/dspp/files/unprotected/devresource/Docs/TechPapers/IA64/hpspmi.pdf
@@ -1546,28 +1513,12 @@ struct SPMITable {
s8 spmi_id[1]; /* A '\0' terminated array starts here. */
};
-static int try_init_acpi(int intf_num, struct smi_info **new_info)
+static __devinit int try_init_acpi(struct SPMITable *spmi)
{
struct smi_info *info;
- acpi_status status;
- struct SPMITable *spmi;
char *io_type;
u8 addr_space;
- if (acpi_disabled)
- return -ENODEV;
-
- if (acpi_failure)
- return -ENODEV;
-
- status = acpi_get_firmware_table("SPMI", intf_num+1,
- ACPI_LOGICAL_ADDRESSING,
- (struct acpi_table_header **) &spmi);
- if (status != AE_OK) {
- acpi_failure = 1;
- return -ENODEV;
- }
-
if (spmi->IPMIlegacy != 1) {
printk(KERN_INFO "IPMI: Bad SPMI legacy %d\n", spmi->IPMIlegacy);
return -ENODEV;
@@ -1577,47 +1528,42 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
addr_space = IPMI_MEM_ADDR_SPACE;
else
addr_space = IPMI_IO_ADDR_SPACE;
- if (! is_new_interface(-1, addr_space, spmi->addr.address))
- return -ENODEV;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n");
+ return -ENOMEM;
+ }
+
+ info->addr_source = "ACPI";
/* Figure out the interface type. */
switch (spmi->InterfaceType)
{
case 1: /* KCS */
- si_type[intf_num] = "kcs";
+ info->si_type = SI_KCS;
break;
-
case 2: /* SMIC */
- si_type[intf_num] = "smic";
+ info->si_type = SI_SMIC;
break;
-
case 3: /* BT */
- si_type[intf_num] = "bt";
+ info->si_type = SI_BT;
break;
-
default:
printk(KERN_INFO "ipmi_si: Unknown ACPI/SPMI SI type %d\n",
spmi->InterfaceType);
+ kfree(info);
return -EIO;
}
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (! info) {
- printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n");
- return -ENOMEM;
- }
- memset(info, 0, sizeof(*info));
-
if (spmi->InterruptType & 1) {
/* We've got a GPE interrupt. */
info->irq = spmi->GPE;
info->irq_setup = acpi_gpe_irq_setup;
- info->irq_cleanup = acpi_gpe_irq_cleanup;
} else if (spmi->InterruptType & 2) {
/* We've got an APIC/SAPIC interrupt. */
info->irq = spmi->GlobalSystemInterrupt;
info->irq_setup = std_irq_setup;
- info->irq_cleanup = std_irq_cleanup;
} else {
/* Use the default interrupt setting. */
info->irq = 0;
@@ -1626,43 +1572,60 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
if (spmi->addr.register_bit_width) {
/* A (hopefully) properly formed register bit width. */
- regspacings[intf_num] = spmi->addr.register_bit_width / 8;
info->io.regspacing = spmi->addr.register_bit_width / 8;
} else {
- regspacings[intf_num] = DEFAULT_REGSPACING;
info->io.regspacing = DEFAULT_REGSPACING;
}
- regsizes[intf_num] = regspacings[intf_num];
- info->io.regsize = regsizes[intf_num];
- regshifts[intf_num] = spmi->addr.register_bit_offset;
- info->io.regshift = regshifts[intf_num];
+ info->io.regsize = info->io.regspacing;
+ info->io.regshift = spmi->addr.register_bit_offset;
if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
io_type = "memory";
info->io_setup = mem_setup;
- addrs[intf_num] = spmi->addr.address;
- info->io.info = &(addrs[intf_num]);
+ info->io.addr_type = IPMI_IO_ADDR_SPACE;
} else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
io_type = "I/O";
info->io_setup = port_setup;
- ports[intf_num] = spmi->addr.address;
- info->io.info = &(ports[intf_num]);
+ info->io.addr_type = IPMI_MEM_ADDR_SPACE;
} else {
kfree(info);
printk("ipmi_si: Unknown ACPI I/O Address type\n");
return -EIO;
}
+ info->io.addr_data = spmi->addr.address;
- *new_info = info;
+ try_smi_init(info);
- printk("ipmi_si: ACPI/SPMI specifies \"%s\" %s SI @ 0x%lx\n",
- si_type[intf_num], io_type, (unsigned long) spmi->addr.address);
return 0;
}
+
+static __devinit void acpi_find_bmc(void)
+{
+ acpi_status status;
+ struct SPMITable *spmi;
+ int i;
+
+ if (acpi_disabled)
+ return;
+
+ if (acpi_failure)
+ return;
+
+ for (i = 0; ; i++) {
+ status = acpi_get_firmware_table("SPMI", i+1,
+ ACPI_LOGICAL_ADDRESSING,
+ (struct acpi_table_header **)
+ &spmi);
+ if (status != AE_OK)
+ return;
+
+ try_init_acpi(spmi);
+ }
+}
#endif
#ifdef CONFIG_DMI
-typedef struct dmi_ipmi_data
+struct dmi_ipmi_data
{
u8 type;
u8 addr_space;
@@ -1670,49 +1633,46 @@ typedef struct dmi_ipmi_data
u8 irq;
u8 offset;
u8 slave_addr;
-} dmi_ipmi_data_t;
-
-static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS];
-static int dmi_data_entries;
+};
-static int __init decode_dmi(struct dmi_header *dm, int intf_num)
+static int __devinit decode_dmi(struct dmi_header *dm,
+ struct dmi_ipmi_data *dmi)
{
u8 *data = (u8 *)dm;
unsigned long base_addr;
u8 reg_spacing;
u8 len = dm->length;
- dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
- ipmi_data->type = data[4];
+ dmi->type = data[4];
memcpy(&base_addr, data+8, sizeof(unsigned long));
if (len >= 0x11) {
if (base_addr & 1) {
/* I/O */
base_addr &= 0xFFFE;
- ipmi_data->addr_space = IPMI_IO_ADDR_SPACE;
+ dmi->addr_space = IPMI_IO_ADDR_SPACE;
}
else {
/* Memory */
- ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE;
+ dmi->addr_space = IPMI_MEM_ADDR_SPACE;
}
/* If bit 4 of byte 0x10 is set, then the lsb for the address
is odd. */
- ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
+ dmi->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
- ipmi_data->irq = data[0x11];
+ dmi->irq = data[0x11];
/* The top two bits of byte 0x10 hold the register spacing. */
reg_spacing = (data[0x10] & 0xC0) >> 6;
switch(reg_spacing){
case 0x00: /* Byte boundaries */
- ipmi_data->offset = 1;
+ dmi->offset = 1;
break;
case 0x01: /* 32-bit boundaries */
- ipmi_data->offset = 4;
+ dmi->offset = 4;
break;
case 0x02: /* 16-byte boundaries */
- ipmi_data->offset = 16;
+ dmi->offset = 16;
break;
default:
/* Some other interface, just ignore it. */
@@ -1726,217 +1686,227 @@ static int __init decode_dmi(struct dmi_header *dm, int intf_num)
* wrong (and all that I have seen are I/O) so we just
* ignore that bit and assume I/O. Systems that use
* memory should use the newer spec, anyway. */
- ipmi_data->base_addr = base_addr & 0xfffe;
- ipmi_data->addr_space = IPMI_IO_ADDR_SPACE;
- ipmi_data->offset = 1;
- }
-
- ipmi_data->slave_addr = data[6];
-
- if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) {
- dmi_data_entries++;
- return 0;
+ dmi->base_addr = base_addr & 0xfffe;
+ dmi->addr_space = IPMI_IO_ADDR_SPACE;
+ dmi->offset = 1;
}
- memset(ipmi_data, 0, sizeof(dmi_ipmi_data_t));
+ dmi->slave_addr = data[6];
- return -1;
+ return 0;
}
-static void __init dmi_find_bmc(void)
+static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
{
- struct dmi_device *dev = NULL;
- int intf_num = 0;
-
- while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) {
- if (intf_num >= SI_MAX_DRIVERS)
- break;
+ struct smi_info *info;
- decode_dmi((struct dmi_header *) dev->device_data, intf_num++);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ printk(KERN_ERR
+ "ipmi_si: Could not allocate SI data\n");
+ return;
}
-}
-
-static int try_init_smbios(int intf_num, struct smi_info **new_info)
-{
- struct smi_info *info;
- dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
- char *io_type;
- if (intf_num >= dmi_data_entries)
- return -ENODEV;
+ info->addr_source = "SMBIOS";
switch (ipmi_data->type) {
- case 0x01: /* KCS */
- si_type[intf_num] = "kcs";
- break;
- case 0x02: /* SMIC */
- si_type[intf_num] = "smic";
- break;
- case 0x03: /* BT */
- si_type[intf_num] = "bt";
- break;
- default:
- return -EIO;
- }
-
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (! info) {
- printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n");
- return -ENOMEM;
+ case 0x01: /* KCS */
+ info->si_type = SI_KCS;
+ break;
+ case 0x02: /* SMIC */
+ info->si_type = SI_SMIC;
+ break;
+ case 0x03: /* BT */
+ info->si_type = SI_BT;
+ break;
+ default:
+ return;
}
- memset(info, 0, sizeof(*info));
- if (ipmi_data->addr_space == 1) {
- io_type = "memory";
+ switch (ipmi_data->addr_space) {
+ case IPMI_MEM_ADDR_SPACE:
info->io_setup = mem_setup;
- addrs[intf_num] = ipmi_data->base_addr;
- info->io.info = &(addrs[intf_num]);
- } else if (ipmi_data->addr_space == 2) {
- io_type = "I/O";
+ info->io.addr_type = IPMI_MEM_ADDR_SPACE;
+ break;
+
+ case IPMI_IO_ADDR_SPACE:
info->io_setup = port_setup;
- ports[intf_num] = ipmi_data->base_addr;
- info->io.info = &(ports[intf_num]);
- } else {
+ info->io.addr_type = IPMI_IO_ADDR_SPACE;
+ break;
+
+ default:
kfree(info);
- printk("ipmi_si: Unknown SMBIOS I/O Address type.\n");
- return -EIO;
+ printk(KERN_WARNING
+ "ipmi_si: Unknown SMBIOS I/O Address type: %d.\n",
+ ipmi_data->addr_space);
+ return;
}
+ info->io.addr_data = ipmi_data->base_addr;
- regspacings[intf_num] = ipmi_data->offset;
- info->io.regspacing = regspacings[intf_num];
- if (! info->io.regspacing)
+ info->io.regspacing = ipmi_data->offset;
+ if (!info->io.regspacing)
info->io.regspacing = DEFAULT_REGSPACING;
info->io.regsize = DEFAULT_REGSPACING;
- info->io.regshift = regshifts[intf_num];
+ info->io.regshift = 0;
info->slave_addr = ipmi_data->slave_addr;
- irqs[intf_num] = ipmi_data->irq;
+ info->irq = ipmi_data->irq;
+ if (info->irq)
+ info->irq_setup = std_irq_setup;
- *new_info = info;
+ try_smi_init(info);
+}
- printk("ipmi_si: Found SMBIOS-specified state machine at %s"
- " address 0x%lx, slave address 0x%x\n",
- io_type, (unsigned long)ipmi_data->base_addr,
- ipmi_data->slave_addr);
- return 0;
+static void __devinit dmi_find_bmc(void)
+{
+ struct dmi_device *dev = NULL;
+ struct dmi_ipmi_data data;
+ int rv;
+
+ while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) {
+ rv = decode_dmi((struct dmi_header *) dev->device_data, &data);
+ if (!rv)
+ try_init_dmi(&data);
+ }
}
#endif /* CONFIG_DMI */
#ifdef CONFIG_PCI
-#define PCI_ERMC_CLASSCODE 0x0C0700
+#define PCI_ERMC_CLASSCODE 0x0C0700
+#define PCI_ERMC_CLASSCODE_MASK 0xffffff00
+#define PCI_ERMC_CLASSCODE_TYPE_MASK 0xff
+#define PCI_ERMC_CLASSCODE_TYPE_SMIC 0x00
+#define PCI_ERMC_CLASSCODE_TYPE_KCS 0x01
+#define PCI_ERMC_CLASSCODE_TYPE_BT 0x02
+
#define PCI_HP_VENDOR_ID 0x103C
#define PCI_MMC_DEVICE_ID 0x121A
#define PCI_MMC_ADDR_CW 0x10
-/* Avoid more than one attempt to probe pci smic. */
-static int pci_smic_checked = 0;
+static void ipmi_pci_cleanup(struct smi_info *info)
+{
+ struct pci_dev *pdev = info->addr_source_data;
+
+ pci_disable_device(pdev);
+}
-static int find_pci_smic(int intf_num, struct smi_info **new_info)
+static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
- struct smi_info *info;
- int error;
- struct pci_dev *pci_dev = NULL;
- u16 base_addr;
- int fe_rmc = 0;
+ int rv;
+ int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK;
+ struct smi_info *info;
+ int first_reg_offset = 0;
- if (pci_smic_checked)
- return -ENODEV;
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return ENOMEM;
- pci_smic_checked = 1;
+ info->addr_source = "PCI";
- pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, NULL);
- if (! pci_dev) {
- pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL);
- if (pci_dev && (pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID))
- fe_rmc = 1;
- else
- return -ENODEV;
- }
+ switch (class_type) {
+ case PCI_ERMC_CLASSCODE_TYPE_SMIC:
+ info->si_type = SI_SMIC;
+ break;
- error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr);
- if (error)
- {
- pci_dev_put(pci_dev);
- printk(KERN_ERR
- "ipmi_si: pci_read_config_word() failed (%d).\n",
- error);
- return -ENODEV;
+ case PCI_ERMC_CLASSCODE_TYPE_KCS:
+ info->si_type = SI_KCS;
+ break;
+
+ case PCI_ERMC_CLASSCODE_TYPE_BT:
+ info->si_type = SI_BT;
+ break;
+
+ default:
+ kfree(info);
+ printk(KERN_INFO "ipmi_si: %s: Unknown IPMI type: %d\n",
+ pci_name(pdev), class_type);
+ return ENOMEM;
}
- /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */
- if (! (base_addr & 0x0001))
- {
- pci_dev_put(pci_dev);
- printk(KERN_ERR
- "ipmi_si: memory mapped I/O not supported for PCI"
- " smic.\n");
- return -ENODEV;
+ rv = pci_enable_device(pdev);
+ if (rv) {
+ printk(KERN_ERR "ipmi_si: %s: couldn't enable PCI device\n",
+ pci_name(pdev));
+ kfree(info);
+ return rv;
}
- base_addr &= 0xFFFE;
- if (! fe_rmc)
- /* Data register starts at base address + 1 in eRMC */
- ++base_addr;
+ info->addr_source_cleanup = ipmi_pci_cleanup;
+ info->addr_source_data = pdev;
- if (! is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) {
- pci_dev_put(pci_dev);
- return -ENODEV;
- }
+ if (pdev->subsystem_vendor == PCI_HP_VENDOR_ID)
+ first_reg_offset = 1;
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (! info) {
- pci_dev_put(pci_dev);
- printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n");
- return -ENOMEM;
+ if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
+ info->io_setup = port_setup;
+ info->io.addr_type = IPMI_IO_ADDR_SPACE;
+ } else {
+ info->io_setup = mem_setup;
+ info->io.addr_type = IPMI_MEM_ADDR_SPACE;
}
- memset(info, 0, sizeof(*info));
+ info->io.addr_data = pci_resource_start(pdev, 0);
- info->io_setup = port_setup;
- ports[intf_num] = base_addr;
- info->io.info = &(ports[intf_num]);
- info->io.regspacing = regspacings[intf_num];
- if (! info->io.regspacing)
- info->io.regspacing = DEFAULT_REGSPACING;
+ info->io.regspacing = DEFAULT_REGSPACING;
info->io.regsize = DEFAULT_REGSPACING;
- info->io.regshift = regshifts[intf_num];
+ info->io.regshift = 0;
- *new_info = info;
+ info->irq = pdev->irq;
+ if (info->irq)
+ info->irq_setup = std_irq_setup;
- irqs[intf_num] = pci_dev->irq;
- si_type[intf_num] = "smic";
+ info->dev = &pdev->dev;
- printk("ipmi_si: Found PCI SMIC at I/O address 0x%lx\n",
- (long unsigned int) base_addr);
+ return try_smi_init(info);
+}
- pci_dev_put(pci_dev);
+static void __devexit ipmi_pci_remove(struct pci_dev *pdev)
+{
+}
+
+#ifdef CONFIG_PM
+static int ipmi_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
return 0;
}
-#endif /* CONFIG_PCI */
-static int try_init_plug_and_play(int intf_num, struct smi_info **new_info)
+static int ipmi_pci_resume(struct pci_dev *pdev)
{
-#ifdef CONFIG_PCI
- if (find_pci_smic(intf_num, new_info) == 0)
- return 0;
+ return 0;
+}
#endif
- /* Include other methods here. */
- return -ENODEV;
-}
+static struct pci_device_id ipmi_pci_devices[] = {
+ { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) },
+ { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE) }
+};
+MODULE_DEVICE_TABLE(pci, ipmi_pci_devices);
+
+static struct pci_driver ipmi_pci_driver = {
+ .name = DEVICE_NAME,
+ .id_table = ipmi_pci_devices,
+ .probe = ipmi_pci_probe,
+ .remove = __devexit_p(ipmi_pci_remove),
+#ifdef CONFIG_PM
+ .suspend = ipmi_pci_suspend,
+ .resume = ipmi_pci_resume,
+#endif
+};
+#endif /* CONFIG_PCI */
static int try_get_dev_id(struct smi_info *smi_info)
{
- unsigned char msg[2];
- unsigned char *resp;
- unsigned long resp_len;
- enum si_sm_result smi_result;
- int rv = 0;
+ unsigned char msg[2];
+ unsigned char *resp;
+ unsigned long resp_len;
+ enum si_sm_result smi_result;
+ int rv = 0;
resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
- if (! resp)
+ if (!resp)
return -ENOMEM;
/* Do a Get Device ID command, since it comes back with some
@@ -1972,7 +1942,7 @@ static int try_get_dev_id(struct smi_info *smi_info)
/* Otherwise, we got some data. */
resp_len = smi_info->handlers->get_result(smi_info->si_sm,
resp, IPMI_MAX_MSG_LENGTH);
- if (resp_len < 6) {
+ if (resp_len < 14) {
/* That's odd, it should be longer. */
rv = -EINVAL;
goto out;
@@ -1985,8 +1955,7 @@ static int try_get_dev_id(struct smi_info *smi_info)
}
/* Record info from the get device id, in case we need it. */
- memcpy(&smi_info->device_id, &resp[3],
- min_t(unsigned long, resp_len-3, sizeof(smi_info->device_id)));
+ ipmi_demangle_device_id(resp+3, resp_len-3, &smi_info->device_id);
out:
kfree(resp);
@@ -2018,7 +1987,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
struct smi_info *smi = data;
out += sprintf(out, "interrupts_enabled: %d\n",
- smi->irq && ! smi->interrupt_disabled);
+ smi->irq && !smi->interrupt_disabled);
out += sprintf(out, "short_timeouts: %ld\n",
smi->short_timeouts);
out += sprintf(out, "long_timeouts: %ld\n",
@@ -2089,15 +2058,14 @@ static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info)
#define DELL_POWEREDGE_8G_BMC_DEVICE_ID 0x20
#define DELL_POWEREDGE_8G_BMC_DEVICE_REV 0x80
#define DELL_POWEREDGE_8G_BMC_IPMI_VERSION 0x51
-#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00}
+#define DELL_IANA_MFR_ID 0x0002a2
static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info)
{
struct ipmi_device_id *id = &smi_info->device_id;
- const char mfr[3]=DELL_IANA_MFR_ID;
- if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr))) {
+ if (id->manufacturer_id == DELL_IANA_MFR_ID) {
if (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID &&
id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV &&
- id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) {
+ id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) {
smi_info->oem_data_avail_handler =
oem_data_avail_to_receive_msg_avail;
}
@@ -2169,8 +2137,7 @@ static void
setup_dell_poweredge_bt_xaction_handler(struct smi_info *smi_info)
{
struct ipmi_device_id *id = &smi_info->device_id;
- const char mfr[3]=DELL_IANA_MFR_ID;
- if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr)) &&
+ if (id->manufacturer_id == DELL_IANA_MFR_ID &&
smi_info->si_type == SI_BT)
register_xaction_notifier(&dell_poweredge_bt_xaction_notifier);
}
@@ -2200,62 +2167,110 @@ static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
del_timer_sync(&smi_info->si_timer);
}
-/* Returns 0 if initialized, or negative on an error. */
-static int init_one_smi(int intf_num, struct smi_info **smi)
+static struct ipmi_default_vals
{
- int rv;
- struct smi_info *new_smi;
+ int type;
+ int port;
+} __devinit ipmi_defaults[] =
+{
+ { .type = SI_KCS, .port = 0xca2 },
+ { .type = SI_SMIC, .port = 0xca9 },
+ { .type = SI_BT, .port = 0xe4 },
+ { .port = 0 }
+};
+static __devinit void default_find_bmc(void)
+{
+ struct smi_info *info;
+ int i;
- rv = try_init_mem(intf_num, &new_smi);
- if (rv)
- rv = try_init_port(intf_num, &new_smi);
-#ifdef CONFIG_ACPI
- if (rv && si_trydefaults)
- rv = try_init_acpi(intf_num, &new_smi);
-#endif
-#ifdef CONFIG_DMI
- if (rv && si_trydefaults)
- rv = try_init_smbios(intf_num, &new_smi);
-#endif
- if (rv && si_trydefaults)
- rv = try_init_plug_and_play(intf_num, &new_smi);
+ for (i = 0; ; i++) {
+ if (!ipmi_defaults[i].port)
+ break;
- if (rv)
- return rv;
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return;
- /* So we know not to free it unless we have allocated one. */
- new_smi->intf = NULL;
- new_smi->si_sm = NULL;
- new_smi->handlers = NULL;
+ info->addr_source = NULL;
- if (! new_smi->irq_setup) {
- new_smi->irq = irqs[intf_num];
- new_smi->irq_setup = std_irq_setup;
- new_smi->irq_cleanup = std_irq_cleanup;
- }
+ info->si_type = ipmi_defaults[i].type;
+ info->io_setup = port_setup;
+ info->io.addr_data = ipmi_defaults[i].port;
+ info->io.addr_type = IPMI_IO_ADDR_SPACE;
- /* Default to KCS if no type is specified. */
- if (si_type[intf_num] == NULL) {
- if (si_trydefaults)
- si_type[intf_num] = "kcs";
- else {
- rv = -EINVAL;
- goto out_err;
+ info->io.addr = NULL;
+ info->io.regspacing = DEFAULT_REGSPACING;
+ info->io.regsize = DEFAULT_REGSPACING;
+ info->io.regshift = 0;
+
+ if (try_smi_init(info) == 0) {
+ /* Found one... */
+ printk(KERN_INFO "ipmi_si: Found default %s state"
+ " machine at %s address 0x%lx\n",
+ si_to_str[info->si_type],
+ addr_space_to_str[info->io.addr_type],
+ info->io.addr_data);
+ return;
}
}
+}
+
+static int is_new_interface(struct smi_info *info)
+{
+ struct smi_info *e;
+
+ list_for_each_entry(e, &smi_infos, link) {
+ if (e->io.addr_type != info->io.addr_type)
+ continue;
+ if (e->io.addr_data == info->io.addr_data)
+ return 0;
+ }
+
+ return 1;
+}
+
+static int try_smi_init(struct smi_info *new_smi)
+{
+ int rv;
+
+ if (new_smi->addr_source) {
+ printk(KERN_INFO "ipmi_si: Trying %s-specified %s state"
+ " machine at %s address 0x%lx, slave address 0x%x,"
+ " irq %d\n",
+ new_smi->addr_source,
+ si_to_str[new_smi->si_type],
+ addr_space_to_str[new_smi->io.addr_type],
+ new_smi->io.addr_data,
+ new_smi->slave_addr, new_smi->irq);
+ }
+
+ down(&smi_infos_lock);
+ if (!is_new_interface(new_smi)) {
+ printk(KERN_WARNING "ipmi_si: duplicate interface\n");
+ rv = -EBUSY;
+ goto out_err;
+ }
- /* Set up the state machine to use. */
- if (strcmp(si_type[intf_num], "kcs") == 0) {
+ /* So we know not to free it unless we have allocated one. */
+ new_smi->intf = NULL;
+ new_smi->si_sm = NULL;
+ new_smi->handlers = NULL;
+
+ switch (new_smi->si_type) {
+ case SI_KCS:
new_smi->handlers = &kcs_smi_handlers;
- new_smi->si_type = SI_KCS;
- } else if (strcmp(si_type[intf_num], "smic") == 0) {
+ break;
+
+ case SI_SMIC:
new_smi->handlers = &smic_smi_handlers;
- new_smi->si_type = SI_SMIC;
- } else if (strcmp(si_type[intf_num], "bt") == 0) {
+ break;
+
+ case SI_BT:
new_smi->handlers = &bt_smi_handlers;
- new_smi->si_type = SI_BT;
- } else {
+ break;
+
+ default:
/* No support for anything else yet. */
rv = -EIO;
goto out_err;
@@ -2263,7 +2278,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
/* Allocate the state machine's data and initialize it. */
new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL);
- if (! new_smi->si_sm) {
+ if (!new_smi->si_sm) {
printk(" Could not allocate state machine memory\n");
rv = -ENOMEM;
goto out_err;
@@ -2284,21 +2299,29 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
/* Do low-level detection first. */
if (new_smi->handlers->detect(new_smi->si_sm)) {
+ if (new_smi->addr_source)
+ printk(KERN_INFO "ipmi_si: Interface detection"
+ " failed\n");
rv = -ENODEV;
goto out_err;
}
/* Attempt a get device id command. If it fails, we probably
- don't have a SMI here. */
+ don't have a BMC here. */
rv = try_get_dev_id(new_smi);
- if (rv)
+ if (rv) {
+ if (new_smi->addr_source)
+ printk(KERN_INFO "ipmi_si: There appears to be no BMC"
+ " at this location\n");
goto out_err;
+ }
setup_oem_data_handler(new_smi);
setup_xaction_handlers(new_smi);
/* Try to claim any interrupts. */
- new_smi->irq_setup(new_smi);
+ if (new_smi->irq_setup)
+ new_smi->irq_setup(new_smi);
INIT_LIST_HEAD(&(new_smi->xmit_msgs));
INIT_LIST_HEAD(&(new_smi->hp_xmit_msgs));
@@ -2308,7 +2331,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
new_smi->interrupt_disabled = 0;
atomic_set(&new_smi->stop_operation, 0);
- new_smi->intf_num = intf_num;
+ new_smi->intf_num = smi_num;
+ smi_num++;
/* Start clearing the flags before we enable interrupts or the
timer to avoid racing with the timer. */
@@ -2332,10 +2356,36 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
new_smi->thread = kthread_run(ipmi_thread, new_smi,
"kipmi%d", new_smi->intf_num);
+ if (!new_smi->dev) {
+ /* If we don't already have a device from something
+ * else (like PCI), then register a new one. */
+ new_smi->pdev = platform_device_alloc("ipmi_si",
+ new_smi->intf_num);
+ if (rv) {
+ printk(KERN_ERR
+ "ipmi_si_intf:"
+ " Unable to allocate platform device\n");
+ goto out_err_stop_timer;
+ }
+ new_smi->dev = &new_smi->pdev->dev;
+ new_smi->dev->driver = &ipmi_driver;
+
+ rv = platform_device_register(new_smi->pdev);
+ if (rv) {
+ printk(KERN_ERR
+ "ipmi_si_intf:"
+ " Unable to register system interface device:"
+ " %d\n",
+ rv);
+ goto out_err_stop_timer;
+ }
+ new_smi->dev_registered = 1;
+ }
+
rv = ipmi_register_smi(&handlers,
new_smi,
- ipmi_version_major(&new_smi->device_id),
- ipmi_version_minor(&new_smi->device_id),
+ &new_smi->device_id,
+ new_smi->dev,
new_smi->slave_addr,
&(new_smi->intf));
if (rv) {
@@ -2365,9 +2415,11 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
goto out_err_stop_timer;
}
- *smi = new_smi;
+ list_add_tail(&new_smi->link, &smi_infos);
+
+ up(&smi_infos_lock);
- printk(" IPMI %s interface initialized\n", si_type[intf_num]);
+ printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
return 0;
@@ -2379,7 +2431,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
if (new_smi->intf)
ipmi_unregister_smi(new_smi->intf);
- new_smi->irq_cleanup(new_smi);
+ if (new_smi->irq_cleanup)
+ new_smi->irq_cleanup(new_smi);
/* Wait until we know that we are out of any interrupt
handlers might have been running before we freed the
@@ -2391,23 +2444,41 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
new_smi->handlers->cleanup(new_smi->si_sm);
kfree(new_smi->si_sm);
}
+ if (new_smi->addr_source_cleanup)
+ new_smi->addr_source_cleanup(new_smi);
if (new_smi->io_cleanup)
new_smi->io_cleanup(new_smi);
+ if (new_smi->dev_registered)
+ platform_device_unregister(new_smi->pdev);
+
+ kfree(new_smi);
+
+ up(&smi_infos_lock);
+
return rv;
}
-static __init int init_ipmi_si(void)
+static __devinit int init_ipmi_si(void)
{
- int rv = 0;
- int pos = 0;
int i;
char *str;
+ int rv;
if (initialized)
return 0;
initialized = 1;
+ /* Register the device drivers. */
+ rv = driver_register(&ipmi_driver);
+ if (rv) {
+ printk(KERN_ERR
+ "init_ipmi_si: Unable to register driver: %d\n",
+ rv);
+ return rv;
+ }
+
+
/* Parse out the si_type string into its components. */
str = si_type_str;
if (*str != '\0') {
@@ -2425,63 +2496,66 @@ static __init int init_ipmi_si(void)
printk(KERN_INFO "IPMI System Interface driver.\n");
+ hardcode_find_bmc();
+
#ifdef CONFIG_DMI
dmi_find_bmc();
#endif
- rv = init_one_smi(0, &(smi_infos[pos]));
- if (rv && ! ports[0] && si_trydefaults) {
- /* If we are trying defaults and the initial port is
- not set, then set it. */
- si_type[0] = "kcs";
- ports[0] = DEFAULT_KCS_IO_PORT;
- rv = init_one_smi(0, &(smi_infos[pos]));
- if (rv) {
- /* No KCS - try SMIC */
- si_type[0] = "smic";
- ports[0] = DEFAULT_SMIC_IO_PORT;
- rv = init_one_smi(0, &(smi_infos[pos]));
- }
- if (rv) {
- /* No SMIC - try BT */
- si_type[0] = "bt";
- ports[0] = DEFAULT_BT_IO_PORT;
- rv = init_one_smi(0, &(smi_infos[pos]));
- }
- }
- if (rv == 0)
- pos++;
+#ifdef CONFIG_ACPI
+ if (si_trydefaults)
+ acpi_find_bmc();
+#endif
- for (i = 1; i < SI_MAX_PARMS; i++) {
- rv = init_one_smi(i, &(smi_infos[pos]));
- if (rv == 0)
- pos++;
+#ifdef CONFIG_PCI
+ pci_module_init(&ipmi_pci_driver);
+#endif
+
+ if (si_trydefaults) {
+ down(&smi_infos_lock);
+ if (list_empty(&smi_infos)) {
+ /* No BMC was found, try defaults. */
+ up(&smi_infos_lock);
+ default_find_bmc();
+ } else {
+ up(&smi_infos_lock);
+ }
}
- if (smi_infos[0] == NULL) {
+ down(&smi_infos_lock);
+ if (list_empty(&smi_infos)) {
+ up(&smi_infos_lock);
+#ifdef CONFIG_PCI
+ pci_unregister_driver(&ipmi_pci_driver);
+#endif
printk("ipmi_si: Unable to find any System Interface(s)\n");
return -ENODEV;
+ } else {
+ up(&smi_infos_lock);
+ return 0;
}
-
- return 0;
}
module_init(init_ipmi_si);
-static void __exit cleanup_one_si(struct smi_info *to_clean)
+static void __devexit cleanup_one_si(struct smi_info *to_clean)
{
int rv;
unsigned long flags;
- if (! to_clean)
+ if (!to_clean)
return;
+ list_del(&to_clean->link);
+
/* Tell the timer and interrupt handlers that we are shutting
down. */
spin_lock_irqsave(&(to_clean->si_lock), flags);
spin_lock(&(to_clean->msg_lock));
atomic_inc(&to_clean->stop_operation);
- to_clean->irq_cleanup(to_clean);
+
+ if (to_clean->irq_cleanup)
+ to_clean->irq_cleanup(to_clean);
spin_unlock(&(to_clean->msg_lock));
spin_unlock_irqrestore(&(to_clean->si_lock), flags);
@@ -2511,20 +2585,34 @@ static void __exit cleanup_one_si(struct smi_info *to_clean)
kfree(to_clean->si_sm);
+ if (to_clean->addr_source_cleanup)
+ to_clean->addr_source_cleanup(to_clean);
if (to_clean->io_cleanup)
to_clean->io_cleanup(to_clean);
+
+ if (to_clean->dev_registered)
+ platform_device_unregister(to_clean->pdev);
+
+ kfree(to_clean);
}
static __exit void cleanup_ipmi_si(void)
{
- int i;
+ struct smi_info *e, *tmp_e;
- if (! initialized)
+ if (!initialized)
return;
- for (i = 0; i < SI_MAX_DRIVERS; i++) {
- cleanup_one_si(smi_infos[i]);
- }
+#ifdef CONFIG_PCI
+ pci_unregister_driver(&ipmi_pci_driver);
+#endif
+
+ down(&smi_infos_lock);
+ list_for_each_entry_safe(e, tmp_e, &smi_infos, link)
+ cleanup_one_si(e);
+ up(&smi_infos_lock);
+
+ driver_unregister(&ipmi_driver);
}
module_exit(cleanup_ipmi_si);
diff --git a/drivers/char/ipmi/ipmi_si_sm.h b/drivers/char/ipmi/ipmi_si_sm.h
index bf3d4962d6a..4b731b24dc1 100644
--- a/drivers/char/ipmi/ipmi_si_sm.h
+++ b/drivers/char/ipmi/ipmi_si_sm.h
@@ -50,11 +50,12 @@ struct si_sm_io
/* Generic info used by the actual handling routines, the
state machine shouldn't touch these. */
- void *info;
void __iomem *addr;
int regspacing;
int regsize;
int regshift;
+ int addr_type;
+ long addr_data;
};
/* Results of SMI events. */
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 1f3159eb1ed..7ece9f3c8f7 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -996,7 +996,7 @@ static struct notifier_block wdog_panic_notifier = {
};
-static void ipmi_new_smi(int if_num)
+static void ipmi_new_smi(int if_num, struct device *device)
{
ipmi_register_watchdog(if_num);
}
@@ -1158,7 +1158,8 @@ static int __init ipmi_wdog_init(void)
}
register_reboot_notifier(&wdog_reboot_notifier);
- notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &wdog_panic_notifier);
printk(KERN_INFO PFX "driver initialized\n");
@@ -1176,7 +1177,8 @@ static __exit void ipmi_unregister_watchdog(void)
release_nmi(&ipmi_nmi_handler);
#endif
- notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier);
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &wdog_panic_notifier);
unregister_reboot_notifier(&wdog_reboot_notifier);
if (! watchdog_user)
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index ede128356af..e5247f85a44 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -378,13 +378,13 @@ MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver");
MODULE_LICENSE("GPL");
-MODULE_PARM(board0, "1-3s");
+module_param_array(board0, charp, NULL, 0);
MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]");
-MODULE_PARM(board1, "1-3s");
+module_param_array(board1, charp, NULL, 0);
MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]");
-MODULE_PARM(board2, "1-3s");
+module_param_array(board2, charp, NULL, 0);
MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]");
-MODULE_PARM(board3, "1-3s");
+module_param_array(board3, charp, NULL, 0);
MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]");
#endif
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 29c41f4418c..66719f9d294 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -88,21 +88,15 @@ static inline int uncached_access(struct file *file, unsigned long addr)
}
#ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE
-static inline int valid_phys_addr_range(unsigned long addr, size_t *count)
+static inline int valid_phys_addr_range(unsigned long addr, size_t count)
{
- unsigned long end_mem;
-
- end_mem = __pa(high_memory);
- if (addr >= end_mem)
+ if (addr + count > __pa(high_memory))
return 0;
- if (*count > end_mem - addr)
- *count = end_mem - addr;
-
return 1;
}
-static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t *size)
+static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t size)
{
return 1;
}
@@ -119,7 +113,7 @@ static ssize_t read_mem(struct file * file, char __user * buf,
ssize_t read, sz;
char *ptr;
- if (!valid_phys_addr_range(p, &count))
+ if (!valid_phys_addr_range(p, count))
return -EFAULT;
read = 0;
#ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
@@ -177,7 +171,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
unsigned long copied;
void *ptr;
- if (!valid_phys_addr_range(p, &count))
+ if (!valid_phys_addr_range(p, count))
return -EFAULT;
written = 0;
@@ -216,11 +210,9 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
copied = copy_from_user(ptr, buf, sz);
if (copied) {
- ssize_t ret;
-
- ret = written + (sz - copied);
- if (ret)
- return ret;
+ written += sz - copied;
+ if (written)
+ break;
return -EFAULT;
}
buf += sz;
@@ -251,7 +243,7 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
{
size_t size = vma->vm_end - vma->vm_start;
- if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, &size))
+ if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, size))
return -EINVAL;
vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
@@ -456,11 +448,9 @@ do_write_kmem(void *p, unsigned long realp, const char __user * buf,
copied = copy_from_user(ptr, buf, sz);
if (copied) {
- ssize_t ret;
-
- ret = written + (sz - copied);
- if (ret)
- return ret;
+ written += sz - copied;
+ if (written)
+ break;
return -EFAULT;
}
buf += sz;
@@ -514,11 +504,10 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
if (len) {
written = copy_from_user(kbuf, buf, len);
if (written) {
- ssize_t ret;
-
+ if (wrote + virtr)
+ break;
free_page((unsigned long)kbuf);
- ret = wrote + virtr + (len - written);
- return ret ? ret : -EFAULT;
+ return -EFAULT;
}
}
len = vwrite(kbuf, (char *)p, len);
@@ -563,8 +552,11 @@ static ssize_t write_port(struct file * file, const char __user * buf,
return -EFAULT;
while (count-- > 0 && i < 65536) {
char c;
- if (__get_user(c, tmp))
+ if (__get_user(c, tmp)) {
+ if (tmp > buf)
+ break;
return -EFAULT;
+ }
outb(c,i);
i++;
tmp++;
@@ -907,7 +899,7 @@ static const struct {
unsigned int minor;
char *name;
umode_t mode;
- struct file_operations *fops;
+ const struct file_operations *fops;
} devlist[] = { /* list of minor devices */
{1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
{2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 3e4c0414a01..96eb2a709e2 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -129,7 +129,7 @@ static int misc_open(struct inode * inode, struct file * file)
int minor = iminor(inode);
struct miscdevice *c;
int err = -ENODEV;
- struct file_operations *old_fops, *new_fops = NULL;
+ const struct file_operations *old_fops, *new_fops = NULL;
down(&misc_sem);
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index ea725a9964e..0fb2fb9fb02 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -243,10 +243,10 @@ static int verbose = 0;
MODULE_AUTHOR("Casper Yang");
MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver");
-MODULE_PARM(ioaddr, "1-4i");
-MODULE_PARM(ttymajor, "i");
-MODULE_PARM(calloutmajor, "i");
-MODULE_PARM(verbose, "i");
+module_param_array(ioaddr, int, NULL, 0);
+module_param(ttymajor, int, 0);
+module_param(calloutmajor, int, 0);
+module_param(verbose, bool, 0);
MODULE_LICENSE("GPL");
struct mxser_log {
diff --git a/drivers/char/mxser.h b/drivers/char/mxser.h
index e7fd0b08e0b..7e188a4d602 100644
--- a/drivers/char/mxser.h
+++ b/drivers/char/mxser.h
@@ -118,7 +118,7 @@
// enable CTS interrupt
#define MOXA_MUST_IER_ECTSI 0x80
-// eanble RTS interrupt
+// enable RTS interrupt
#define MOXA_MUST_IER_ERTSI 0x40
// enable Xon/Xoff interrupt
#define MOXA_MUST_IER_XINT 0x20
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 306ee0f091a..bee6c47b45b 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -65,10 +65,11 @@
#include <linux/parport.h>
#include <linux/ctype.h>
#include <linux/poll.h>
-#include <asm/uaccess.h>
+#include <linux/major.h>
#include <linux/ppdev.h>
#include <linux/smp_lock.h>
#include <linux/device.h>
+#include <asm/uaccess.h>
#define PP_VERSION "ppdev: user-space parallel port driver"
#define CHRDEV "ppdev"
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 119e629656b..657c0d88f48 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -1743,10 +1743,10 @@ static int iobase;
static int iobase1;
static int iobase2;
static int iobase3;
-MODULE_PARM(iobase, "i");
-MODULE_PARM(iobase1, "i");
-MODULE_PARM(iobase2, "i");
-MODULE_PARM(iobase3, "i");
+module_param(iobase, int, 0);
+module_param(iobase1, int, 0);
+module_param(iobase2, int, 0);
+module_param(iobase3, int, 0);
MODULE_LICENSE("GPL");
#endif /* MODULE */
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index d68be61f0a4..fee2aca3f6a 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -941,17 +941,6 @@ static void* mgsl_get_text_ptr(void)
return mgsl_get_text_ptr;
}
-/*
- * tmp_buf is used as a temporary buffer by mgsl_write. We need to
- * lock it in case the COPY_FROM_USER blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ioports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char *tmp_buf;
-
static inline int mgsl_paranoia_check(struct mgsl_struct *info,
char *name, const char *routine)
{
@@ -2150,7 +2139,7 @@ static int mgsl_write(struct tty_struct * tty,
if (mgsl_paranoia_check(info, tty->name, "mgsl_write"))
goto cleanup;
- if (!tty || !info->xmit_buf || !tmp_buf)
+ if (!tty || !info->xmit_buf)
goto cleanup;
if ( info->params.mode == MGSL_MODE_HDLC ||
@@ -3438,7 +3427,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
{
struct mgsl_struct *info;
int retval, line;
- unsigned long page;
unsigned long flags;
/* verify range of specified line number */
@@ -3472,18 +3460,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
goto cleanup;
}
- if (!tmp_buf) {
- page = get_zeroed_page(GFP_KERNEL);
- if (!page) {
- retval = -ENOMEM;
- goto cleanup;
- }
- if (tmp_buf)
- free_page(page);
- else
- tmp_buf = (unsigned char *) page;
- }
-
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
spin_lock_irqsave(&info->netlock, flags);
@@ -4502,11 +4478,6 @@ static void synclink_cleanup(void)
kfree(tmp);
}
- if (tmp_buf) {
- free_page((unsigned long) tmp_buf);
- tmp_buf = NULL;
- }
-
if (pci_registered)
pci_unregister_driver(&synclink_pci_driver);
}
@@ -6025,7 +5996,7 @@ static void usc_set_async_mode( struct mgsl_struct *info )
* <15..8> ? RxFIFO IRQ Request Level
*
* Note: For async mode the receive FIFO level must be set
- * to 0 to aviod the situation where the FIFO contains fewer bytes
+ * to 0 to avoid the situation where the FIFO contains fewer bytes
* than the trigger level and no more data is expected.
*
* <7> 0 Exited Hunt IA (Interrupt Arm)
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 738ec2f4e56..b4d1f4eea43 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1,5 +1,5 @@
/*
- * $Id: synclink_gt.c,v 4.22 2006/01/09 20:16:06 paulkf Exp $
+ * $Id: synclink_gt.c,v 4.25 2006/02/06 21:20:33 paulkf Exp $
*
* Device driver for Microgate SyncLink GT serial adapters.
*
@@ -92,7 +92,7 @@
* module identification
*/
static char *driver_name = "SyncLink GT";
-static char *driver_version = "$Revision: 4.22 $";
+static char *driver_version = "$Revision: 4.25 $";
static char *tty_driver_name = "synclink_gt";
static char *tty_dev_prefix = "ttySLG";
MODULE_LICENSE("GPL");
@@ -188,6 +188,20 @@ static void hdlcdev_exit(struct slgt_info *info);
#define SLGT_REG_SIZE 256
/*
+ * conditional wait facility
+ */
+struct cond_wait {
+ struct cond_wait *next;
+ wait_queue_head_t q;
+ wait_queue_t wait;
+ unsigned int data;
+};
+static void init_cond_wait(struct cond_wait *w, unsigned int data);
+static void add_cond_wait(struct cond_wait **head, struct cond_wait *w);
+static void remove_cond_wait(struct cond_wait **head, struct cond_wait *w);
+static void flush_cond_wait(struct cond_wait **head);
+
+/*
* DMA buffer descriptor and access macros
*/
struct slgt_desc
@@ -269,6 +283,9 @@ struct slgt_info {
struct timer_list tx_timer;
struct timer_list rx_timer;
+ unsigned int gpio_present;
+ struct cond_wait *gpio_wait_q;
+
spinlock_t lock; /* spinlock for synchronizing with ISR */
struct work_struct task;
@@ -379,6 +396,11 @@ static MGSL_PARAMS default_params = {
#define MASK_OVERRUN BIT4
#define GSR 0x00 /* global status */
+#define JCR 0x04 /* JTAG control */
+#define IODR 0x08 /* GPIO direction */
+#define IOER 0x0c /* GPIO interrupt enable */
+#define IOVR 0x10 /* GPIO value */
+#define IOSR 0x14 /* GPIO interrupt status */
#define TDR 0x80 /* tx data */
#define RDR 0x80 /* rx data */
#define TCR 0x82 /* tx control */
@@ -503,6 +525,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
static void set_break(struct tty_struct *tty, int break_state);
static int get_interface(struct slgt_info *info, int __user *if_mode);
static int set_interface(struct slgt_info *info, int if_mode);
+static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
+static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
+static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
/*
* driver functions
@@ -1112,6 +1137,12 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return get_interface(info, argp);
case MGSL_IOCSIF:
return set_interface(info,(int)arg);
+ case MGSL_IOCSGPIO:
+ return set_gpio(info, argp);
+ case MGSL_IOCGGPIO:
+ return get_gpio(info, argp);
+ case MGSL_IOCWAITGPIO:
+ return wait_gpio(info, argp);
case TIOCGICOUNT:
spin_lock_irqsave(&info->lock,flags);
cnow = info->icount;
@@ -1762,10 +1793,6 @@ static void rx_async(struct slgt_info *info)
DBGDATA(info, p, count, "rx");
for(i=0 ; i < count; i+=2, p+=2) {
- if (tty && chars) {
- tty_flip_buffer_push(tty);
- chars = 0;
- }
ch = *p;
icount->rx++;
@@ -2158,6 +2185,24 @@ static void isr_txeom(struct slgt_info *info, unsigned short status)
}
}
+static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int state)
+{
+ struct cond_wait *w, *prev;
+
+ /* wake processes waiting for specific transitions */
+ for (w = info->gpio_wait_q, prev = NULL ; w != NULL ; w = w->next) {
+ if (w->data & changed) {
+ w->data = state;
+ wake_up_interruptible(&w->q);
+ if (prev != NULL)
+ prev->next = w->next;
+ else
+ info->gpio_wait_q = w->next;
+ } else
+ prev = w;
+ }
+}
+
/* interrupt service routine
*
* irq interrupt number
@@ -2193,6 +2238,22 @@ static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs)
}
}
+ if (info->gpio_present) {
+ unsigned int state;
+ unsigned int changed;
+ while ((changed = rd_reg32(info, IOSR)) != 0) {
+ DBGISR(("%s iosr=%08x\n", info->device_name, changed));
+ /* read latched state of GPIO signals */
+ state = rd_reg32(info, IOVR);
+ /* clear pending GPIO interrupt bits */
+ wr_reg32(info, IOSR, changed);
+ for (i=0 ; i < info->port_count ; i++) {
+ if (info->port_array[i] != NULL)
+ isr_gpio(info->port_array[i], changed, state);
+ }
+ }
+ }
+
for(i=0; i < info->port_count ; i++) {
struct slgt_info *port = info->port_array[i];
@@ -2276,6 +2337,8 @@ static void shutdown(struct slgt_info *info)
set_signals(info);
}
+ flush_cond_wait(&info->gpio_wait_q);
+
spin_unlock_irqrestore(&info->lock,flags);
if (info->tty)
@@ -2650,6 +2713,175 @@ static int set_interface(struct slgt_info *info, int if_mode)
return 0;
}
+/*
+ * set general purpose IO pin state and direction
+ *
+ * user_gpio fields:
+ * state each bit indicates a pin state
+ * smask set bit indicates pin state to set
+ * dir each bit indicates a pin direction (0=input, 1=output)
+ * dmask set bit indicates pin direction to set
+ */
+static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
+{
+ unsigned long flags;
+ struct gpio_desc gpio;
+ __u32 data;
+
+ if (!info->gpio_present)
+ return -EINVAL;
+ if (copy_from_user(&gpio, user_gpio, sizeof(gpio)))
+ return -EFAULT;
+ DBGINFO(("%s set_gpio state=%08x smask=%08x dir=%08x dmask=%08x\n",
+ info->device_name, gpio.state, gpio.smask,
+ gpio.dir, gpio.dmask));
+
+ spin_lock_irqsave(&info->lock,flags);
+ if (gpio.dmask) {
+ data = rd_reg32(info, IODR);
+ data |= gpio.dmask & gpio.dir;
+ data &= ~(gpio.dmask & ~gpio.dir);
+ wr_reg32(info, IODR, data);
+ }
+ if (gpio.smask) {
+ data = rd_reg32(info, IOVR);
+ data |= gpio.smask & gpio.state;
+ data &= ~(gpio.smask & ~gpio.state);
+ wr_reg32(info, IOVR, data);
+ }
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ return 0;
+}
+
+/*
+ * get general purpose IO pin state and direction
+ */
+static int get_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
+{
+ struct gpio_desc gpio;
+ if (!info->gpio_present)
+ return -EINVAL;
+ gpio.state = rd_reg32(info, IOVR);
+ gpio.smask = 0xffffffff;
+ gpio.dir = rd_reg32(info, IODR);
+ gpio.dmask = 0xffffffff;
+ if (copy_to_user(user_gpio, &gpio, sizeof(gpio)))
+ return -EFAULT;
+ DBGINFO(("%s get_gpio state=%08x dir=%08x\n",
+ info->device_name, gpio.state, gpio.dir));
+ return 0;
+}
+
+/*
+ * conditional wait facility
+ */
+static void init_cond_wait(struct cond_wait *w, unsigned int data)
+{
+ init_waitqueue_head(&w->q);
+ init_waitqueue_entry(&w->wait, current);
+ w->data = data;
+}
+
+static void add_cond_wait(struct cond_wait **head, struct cond_wait *w)
+{
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&w->q, &w->wait);
+ w->next = *head;
+ *head = w;
+}
+
+static void remove_cond_wait(struct cond_wait **head, struct cond_wait *cw)
+{
+ struct cond_wait *w, *prev;
+ remove_wait_queue(&cw->q, &cw->wait);
+ set_current_state(TASK_RUNNING);
+ for (w = *head, prev = NULL ; w != NULL ; prev = w, w = w->next) {
+ if (w == cw) {
+ if (prev != NULL)
+ prev->next = w->next;
+ else
+ *head = w->next;
+ break;
+ }
+ }
+}
+
+static void flush_cond_wait(struct cond_wait **head)
+{
+ while (*head != NULL) {
+ wake_up_interruptible(&(*head)->q);
+ *head = (*head)->next;
+ }
+}
+
+/*
+ * wait for general purpose I/O pin(s) to enter specified state
+ *
+ * user_gpio fields:
+ * state - bit indicates target pin state
+ * smask - set bit indicates watched pin
+ *
+ * The wait ends when at least one watched pin enters the specified
+ * state. When 0 (no error) is returned, user_gpio->state is set to the
+ * state of all GPIO pins when the wait ends.
+ *
+ * Note: Each pin may be a dedicated input, dedicated output, or
+ * configurable input/output. The number and configuration of pins
+ * varies with the specific adapter model. Only input pins (dedicated
+ * or configured) can be monitored with this function.
+ */
+static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
+{
+ unsigned long flags;
+ int rc = 0;
+ struct gpio_desc gpio;
+ struct cond_wait wait;
+ u32 state;
+
+ if (!info->gpio_present)
+ return -EINVAL;
+ if (copy_from_user(&gpio, user_gpio, sizeof(gpio)))
+ return -EFAULT;
+ DBGINFO(("%s wait_gpio() state=%08x smask=%08x\n",
+ info->device_name, gpio.state, gpio.smask));
+ /* ignore output pins identified by set IODR bit */
+ if ((gpio.smask &= ~rd_reg32(info, IODR)) == 0)
+ return -EINVAL;
+ init_cond_wait(&wait, gpio.smask);
+
+ spin_lock_irqsave(&info->lock, flags);
+ /* enable interrupts for watched pins */
+ wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask);
+ /* get current pin states */
+ state = rd_reg32(info, IOVR);
+
+ if (gpio.smask & ~(state ^ gpio.state)) {
+ /* already in target state */
+ gpio.state = state;
+ } else {
+ /* wait for target state */
+ add_cond_wait(&info->gpio_wait_q, &wait);
+ spin_unlock_irqrestore(&info->lock, flags);
+ schedule();
+ if (signal_pending(current))
+ rc = -ERESTARTSYS;
+ else
+ gpio.state = wait.data;
+ spin_lock_irqsave(&info->lock, flags);
+ remove_cond_wait(&info->gpio_wait_q, &wait);
+ }
+
+ /* disable all GPIO interrupts if no waiting processes */
+ if (info->gpio_wait_q == NULL)
+ wr_reg32(info, IOER, 0);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio)))
+ rc = -EFAULT;
+ return rc;
+}
+
static int modem_input_wait(struct slgt_info *info,int arg)
{
unsigned long flags;
@@ -3166,8 +3398,10 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
} else {
port_array[0]->irq_requested = 1;
adapter_test(port_array[0]);
- for (i=1 ; i < port_count ; i++)
+ for (i=1 ; i < port_count ; i++) {
port_array[i]->init_error = port_array[0]->init_error;
+ port_array[i]->gpio_present = port_array[0]->gpio_present;
+ }
}
}
}
@@ -4301,7 +4535,7 @@ static int register_test(struct slgt_info *info)
break;
}
}
-
+ info->gpio_present = (rd_reg32(info, JCR) & BIT5) ? 1 : 0;
info->init_error = rc ? 0 : DiagStatus_AddressFailure;
return rc;
}
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index d58f8231885..35082dc12ea 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -42,16 +42,15 @@
/* Whether we react on sysrq keys or just ignore them */
int sysrq_enabled = 1;
-/* Loglevel sysrq handler */
static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
int i;
i = key - '0';
console_loglevel = 7;
printk("Loglevel set to %d\n", i);
console_loglevel = i;
-}
+}
static struct sysrq_key_op sysrq_loglevel_op = {
.handler = sysrq_handle_loglevel,
.help_msg = "loglevel0-8",
@@ -59,11 +58,9 @@ static struct sysrq_key_op sysrq_loglevel_op = {
.enable_mask = SYSRQ_ENABLE_LOG,
};
-
-/* SAK sysrq handler */
#ifdef CONFIG_VT
static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
if (tty)
do_SAK(tty);
@@ -75,12 +72,13 @@ static struct sysrq_key_op sysrq_SAK_op = {
.action_msg = "SAK",
.enable_mask = SYSRQ_ENABLE_KEYBOARD,
};
+#else
+#define sysrq_SAK_op (*(struct sysrq_key_op *)0)
#endif
#ifdef CONFIG_VT
-/* unraw sysrq handler */
static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
struct kbd_struct *kbd = &kbd_table[fg_console];
@@ -93,10 +91,11 @@ static struct sysrq_key_op sysrq_unraw_op = {
.action_msg = "Keyboard mode set to XLATE",
.enable_mask = SYSRQ_ENABLE_KEYBOARD,
};
+#else
+#define sysrq_unraw_op (*(struct sysrq_key_op *)0)
#endif /* CONFIG_VT */
#ifdef CONFIG_KEXEC
-/* crashdump sysrq handler */
static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{
@@ -108,16 +107,16 @@ static struct sysrq_key_op sysrq_crashdump_op = {
.action_msg = "Trigger a crashdump",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
+#else
+#define sysrq_crashdump_op (*(struct sysrq_key_op *)0)
#endif
-/* reboot sysrq handler */
static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
local_irq_enable();
emergency_restart();
}
-
static struct sysrq_key_op sysrq_reboot_op = {
.handler = sysrq_handle_reboot,
.help_msg = "reBoot",
@@ -126,11 +125,10 @@ static struct sysrq_key_op sysrq_reboot_op = {
};
static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
emergency_sync();
}
-
static struct sysrq_key_op sysrq_sync_op = {
.handler = sysrq_handle_sync,
.help_msg = "Sync",
@@ -139,11 +137,10 @@ static struct sysrq_key_op sysrq_sync_op = {
};
static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
emergency_remount();
}
-
static struct sysrq_key_op sysrq_mountro_op = {
.handler = sysrq_handle_mountro,
.help_msg = "Unmount",
@@ -151,28 +148,23 @@ static struct sysrq_key_op sysrq_mountro_op = {
.enable_mask = SYSRQ_ENABLE_REMOUNT,
};
-/* END SYNC SYSRQ HANDLERS BLOCK */
-
#ifdef CONFIG_DEBUG_MUTEXES
-
-static void
-sysrq_handle_showlocks(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
+static void sysrq_handle_showlocks(int key, struct pt_regs *pt_regs,
+ struct tty_struct *tty)
{
mutex_debug_show_all_locks();
}
-
static struct sysrq_key_op sysrq_showlocks_op = {
.handler = sysrq_handle_showlocks,
.help_msg = "show-all-locks(D)",
.action_msg = "Show Locks Held",
};
-
+#else
+#define sysrq_showlocks_op (*(struct sysrq_key_op *)0)
#endif
-/* SHOW SYSRQ HANDLERS BLOCK */
-
static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
if (pt_regs)
show_regs(pt_regs);
@@ -184,9 +176,8 @@ static struct sysrq_key_op sysrq_showregs_op = {
.enable_mask = SYSRQ_ENABLE_DUMP,
};
-
static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
show_state();
}
@@ -197,9 +188,8 @@ static struct sysrq_key_op sysrq_showstate_op = {
.enable_mask = SYSRQ_ENABLE_DUMP,
};
-
static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
show_mem();
}
@@ -210,13 +200,9 @@ static struct sysrq_key_op sysrq_showmem_op = {
.enable_mask = SYSRQ_ENABLE_DUMP,
};
-/* SHOW SYSRQ HANDLERS BLOCK */
-
-
-/* SIGNAL SYSRQ HANDLERS BLOCK */
-
-/* signal sysrq helper function
- * Sends a signal to all user processes */
+/*
+ * Signal sysrq helper function. Sends a signal to all user processes.
+ */
static void send_sig_all(int sig)
{
struct task_struct *p;
@@ -229,7 +215,7 @@ static void send_sig_all(int sig)
}
static void sysrq_handle_term(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
send_sig_all(SIGTERM);
console_loglevel = 8;
@@ -243,7 +229,8 @@ static struct sysrq_key_op sysrq_term_op = {
static void moom_callback(void *ignored)
{
- out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], GFP_KERNEL, 0);
+ out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL],
+ GFP_KERNEL, 0);
}
static DECLARE_WORK(moom_work, moom_callback, NULL);
@@ -260,7 +247,7 @@ static struct sysrq_key_op sysrq_moom_op = {
};
static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+ struct tty_struct *tty)
{
send_sig_all(SIGKILL);
console_loglevel = 8;
@@ -272,8 +259,6 @@ static struct sysrq_key_op sysrq_kill_op = {
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
-/* END SIGNAL SYSRQ HANDLERS BLOCK */
-
static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{
@@ -288,110 +273,99 @@ static struct sysrq_key_op sysrq_unrt_op = {
/* Key Operations table and lock */
static DEFINE_SPINLOCK(sysrq_key_table_lock);
-#define SYSRQ_KEY_TABLE_LENGTH 36
-static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
-/* 0 */ &sysrq_loglevel_op,
-/* 1 */ &sysrq_loglevel_op,
-/* 2 */ &sysrq_loglevel_op,
-/* 3 */ &sysrq_loglevel_op,
-/* 4 */ &sysrq_loglevel_op,
-/* 5 */ &sysrq_loglevel_op,
-/* 6 */ &sysrq_loglevel_op,
-/* 7 */ &sysrq_loglevel_op,
-/* 8 */ &sysrq_loglevel_op,
-/* 9 */ &sysrq_loglevel_op,
-/* a */ NULL, /* Don't use for system provided sysrqs,
- it is handled specially on the sparc
- and will never arrive */
-/* b */ &sysrq_reboot_op,
-#ifdef CONFIG_KEXEC
-/* c */ &sysrq_crashdump_op,
-#else
-/* c */ NULL,
-#endif
-#ifdef CONFIG_DEBUG_MUTEXES
-/* d */ &sysrq_showlocks_op,
-#else
-/* d */ NULL,
-#endif
-/* e */ &sysrq_term_op,
-/* f */ &sysrq_moom_op,
-/* g */ NULL,
-/* h */ NULL,
-/* i */ &sysrq_kill_op,
-/* j */ NULL,
-#ifdef CONFIG_VT
-/* k */ &sysrq_SAK_op,
-#else
-/* k */ NULL,
-#endif
-/* l */ NULL,
-/* m */ &sysrq_showmem_op,
-/* n */ &sysrq_unrt_op,
-/* o */ NULL, /* This will often be registered
- as 'Off' at init time */
-/* p */ &sysrq_showregs_op,
-/* q */ NULL,
-#ifdef CONFIG_VT
-/* r */ &sysrq_unraw_op,
-#else
-/* r */ NULL,
-#endif
-/* s */ &sysrq_sync_op,
-/* t */ &sysrq_showstate_op,
-/* u */ &sysrq_mountro_op,
-/* v */ NULL, /* May be assigned at init time by SMP VOYAGER */
-/* w */ NULL,
-/* x */ NULL,
-/* y */ NULL,
-/* z */ NULL
+
+static struct sysrq_key_op *sysrq_key_table[36] = {
+ &sysrq_loglevel_op, /* 0 */
+ &sysrq_loglevel_op, /* 1 */
+ &sysrq_loglevel_op, /* 2 */
+ &sysrq_loglevel_op, /* 3 */
+ &sysrq_loglevel_op, /* 4 */
+ &sysrq_loglevel_op, /* 5 */
+ &sysrq_loglevel_op, /* 6 */
+ &sysrq_loglevel_op, /* 7 */
+ &sysrq_loglevel_op, /* 8 */
+ &sysrq_loglevel_op, /* 9 */
+
+ /*
+ * Don't use for system provided sysrqs, it is handled specially on
+ * sparc and will never arrive
+ */
+ NULL, /* a */
+ &sysrq_reboot_op, /* b */
+ &sysrq_crashdump_op, /* c */
+ &sysrq_showlocks_op, /* d */
+ &sysrq_term_op, /* e */
+ &sysrq_moom_op, /* f */
+ NULL, /* g */
+ NULL, /* h */
+ &sysrq_kill_op, /* i */
+ NULL, /* j */
+ &sysrq_SAK_op, /* k */
+ NULL, /* l */
+ &sysrq_showmem_op, /* m */
+ &sysrq_unrt_op, /* n */
+ /* This will often be registered as 'Off' at init time */
+ NULL, /* o */
+ &sysrq_showregs_op, /* p */
+ NULL, /* q */
+ &sysrq_unraw_op, /* r */
+ &sysrq_sync_op, /* s */
+ &sysrq_showstate_op, /* t */
+ &sysrq_mountro_op, /* u */
+ /* May be assigned at init time by SMP VOYAGER */
+ NULL, /* v */
+ NULL, /* w */
+ NULL, /* x */
+ NULL, /* y */
+ NULL /* z */
};
/* key2index calculation, -1 on invalid index */
-static int sysrq_key_table_key2index(int key) {
+static int sysrq_key_table_key2index(int key)
+{
int retval;
- if ((key >= '0') && (key <= '9')) {
+
+ if ((key >= '0') && (key <= '9'))
retval = key - '0';
- } else if ((key >= 'a') && (key <= 'z')) {
+ else if ((key >= 'a') && (key <= 'z'))
retval = key + 10 - 'a';
- } else {
+ else
retval = -1;
- }
return retval;
}
/*
* get and put functions for the table, exposed to modules.
*/
-
-struct sysrq_key_op *__sysrq_get_key_op (int key) {
- struct sysrq_key_op *op_p;
+struct sysrq_key_op *__sysrq_get_key_op(int key)
+{
+ struct sysrq_key_op *op_p = NULL;
int i;
-
+
i = sysrq_key_table_key2index(key);
- op_p = (i == -1) ? NULL : sysrq_key_table[i];
+ if (i != -1)
+ op_p = sysrq_key_table[i];
return op_p;
}
-static void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) {
- int i;
+static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
+{
+ int i = sysrq_key_table_key2index(key);
- i = sysrq_key_table_key2index(key);
if (i != -1)
sysrq_key_table[i] = op_p;
}
/*
- * This is the non-locking version of handle_sysrq
- * It must/can only be called by sysrq key handlers,
- * as they are inside of the lock
+ * This is the non-locking version of handle_sysrq. It must/can only be called
+ * by sysrq key handlers, as they are inside of the lock
*/
-
-void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, int check_mask)
+void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty,
+ int check_mask)
{
struct sysrq_key_op *op_p;
int orig_log_level;
- int i, j;
+ int i;
unsigned long flags;
spin_lock_irqsave(&sysrq_key_table_lock, flags);
@@ -401,26 +375,34 @@ void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, in
op_p = __sysrq_get_key_op(key);
if (op_p) {
- /* Should we check for enabled operations (/proc/sysrq-trigger should not)
- * and is the invoked operation enabled? */
+ /*
+ * Should we check for enabled operations (/proc/sysrq-trigger
+ * should not) and is the invoked operation enabled?
+ */
if (!check_mask || sysrq_enabled == 1 ||
(sysrq_enabled & op_p->enable_mask)) {
- printk ("%s\n", op_p->action_msg);
+ printk("%s\n", op_p->action_msg);
console_loglevel = orig_log_level;
op_p->handler(key, pt_regs, tty);
- }
- else
+ } else {
printk("This sysrq operation is disabled.\n");
+ }
} else {
printk("HELP : ");
/* Only print the help msg once per handler */
- for (i=0; i<SYSRQ_KEY_TABLE_LENGTH; i++)
- if (sysrq_key_table[i]) {
- for (j=0; sysrq_key_table[i] != sysrq_key_table[j]; j++);
- if (j == i)
- printk ("%s ", sysrq_key_table[i]->help_msg);
+ for (i = 0; i < ARRAY_SIZE(sysrq_key_table); i++) {
+ if (sysrq_key_table[i]) {
+ int j;
+
+ for (j = 0; sysrq_key_table[i] !=
+ sysrq_key_table[j]; j++)
+ ;
+ if (j != i)
+ continue;
+ printk("%s ", sysrq_key_table[i]->help_msg);
+ }
}
- printk ("\n");
+ printk("\n");
console_loglevel = orig_log_level;
}
spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
@@ -430,16 +412,17 @@ void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, in
* This function is called by the keyboard handler when SysRq is pressed
* and any other keycode arrives.
*/
-
void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
{
if (!sysrq_enabled)
return;
__handle_sysrq(key, pt_regs, tty, 1);
}
+EXPORT_SYMBOL(handle_sysrq);
static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
- struct sysrq_key_op *remove_op_p) {
+ struct sysrq_key_op *remove_op_p)
+{
int retval;
unsigned long flags;
@@ -452,7 +435,6 @@ static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
retval = -1;
}
spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
-
return retval;
}
@@ -460,12 +442,10 @@ int register_sysrq_key(int key, struct sysrq_key_op *op_p)
{
return __sysrq_swap_key_ops(key, op_p, NULL);
}
+EXPORT_SYMBOL(register_sysrq_key);
int unregister_sysrq_key(int key, struct sysrq_key_op *op_p)
{
return __sysrq_swap_key_ops(key, NULL, op_p);
}
-
-EXPORT_SYMBOL(handle_sysrq);
-EXPORT_SYMBOL(register_sysrq_key);
EXPORT_SYMBOL(unregister_sysrq_key);
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 4c272189cd4..2546637a55c 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -767,6 +767,7 @@ static int __init tlclk_init(void)
printk(KERN_ERR "tlclk: can't get major %d.\n", tlclk_major);
return ret;
}
+ tlclk_major = ret;
alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
if (!alarm_events)
goto out1;
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index fd3a4beaa53..dec0224b447 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -24,6 +24,7 @@
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
+#include <linux/io.h>
enum tpm_timeout {
TPM_TIMEOUT = 5, /* msecs */
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 76592ee1fb3..0bfd1b63662 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -354,7 +354,7 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size)
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
-int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t size)
+int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size)
{
int copied = 0;
do {
@@ -378,7 +378,7 @@ int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t
EXPORT_SYMBOL_GPL(tty_insert_flip_string);
-int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *chars, char *flags, size_t size)
+int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size)
{
int copied = 0;
do {
@@ -543,14 +543,12 @@ void tty_ldisc_put(int disc)
struct tty_ldisc *ld;
unsigned long flags;
- if (disc < N_TTY || disc >= NR_LDISCS)
- BUG();
+ BUG_ON(disc < N_TTY || disc >= NR_LDISCS);
spin_lock_irqsave(&tty_ldisc_lock, flags);
ld = &tty_ldiscs[disc];
- if(ld->refcount == 0)
- BUG();
- ld->refcount --;
+ BUG_ON(ld->refcount == 0);
+ ld->refcount--;
module_put(ld->owner);
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
}
@@ -645,8 +643,7 @@ void tty_ldisc_deref(struct tty_ldisc *ld)
{
unsigned long flags;
- if(ld == NULL)
- BUG();
+ BUG_ON(ld == NULL);
spin_lock_irqsave(&tty_ldisc_lock, flags);
if(ld->refcount == 0)
@@ -1097,8 +1094,8 @@ static void do_tty_hangup(void *data)
p->signal->tty = NULL;
if (!p->signal->leader)
continue;
- send_group_sig_info(SIGHUP, SEND_SIG_PRIV, p);
- send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p);
+ group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
+ group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
if (tty->pgrp > 0)
p->signal->tty_old_pgrp = tty->pgrp;
} while_each_task_pid(tty->session, PIDTYPE_SID, p);
@@ -2675,7 +2672,7 @@ static void __do_SAK(void *arg)
tty_hangup(tty);
#else
struct tty_struct *tty = arg;
- struct task_struct *p;
+ struct task_struct *g, *p;
int session;
int i;
struct file *filp;
@@ -2696,8 +2693,18 @@ static void __do_SAK(void *arg)
tty->driver->flush_buffer(tty);
read_lock(&tasklist_lock);
+ /* Kill the entire session */
do_each_task_pid(session, PIDTYPE_SID, p) {
- if (p->signal->tty == tty || session > 0) {
+ printk(KERN_NOTICE "SAK: killed process %d"
+ " (%s): p->signal->session==tty->session\n",
+ p->pid, p->comm);
+ send_sig(SIGKILL, p, 1);
+ } while_each_task_pid(session, PIDTYPE_SID, p);
+ /* Now kill any processes that happen to have the
+ * tty open.
+ */
+ do_each_thread(g, p) {
+ if (p->signal->tty == tty) {
printk(KERN_NOTICE "SAK: killed process %d"
" (%s): p->signal->session==tty->session\n",
p->pid, p->comm);
@@ -2724,7 +2731,7 @@ static void __do_SAK(void *arg)
rcu_read_unlock();
}
task_unlock(p);
- } while_each_task_pid(session, PIDTYPE_SID, p);
+ } while_each_thread(g, p);
read_unlock(&tasklist_lock);
#endif
}
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index c0dfcf273f0..16e99db2e12 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -148,6 +148,16 @@ config MPCORE_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called mpcore_wdt.
+config EP93XX_WATCHDOG
+ tristate "EP93xx Watchdog"
+ depends on WATCHDOG && ARCH_EP93XX
+ help
+ Say Y here if to include support for the watchdog timer
+ embedded in the Cirrus Logic EP93xx family of devices.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ep93xx_wdt.
+
# X86 (i386 + ia64 + x86_64) Architecture
config ACQUIRE_WDT
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index 36c0b282b8b..d6f27fde990 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
+obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
# X86 (i386 + ia64 + x86_64) Architecture
obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
diff --git a/drivers/char/watchdog/ep93xx_wdt.c b/drivers/char/watchdog/ep93xx_wdt.c
new file mode 100644
index 00000000000..9021dbb7829
--- /dev/null
+++ b/drivers/char/watchdog/ep93xx_wdt.c
@@ -0,0 +1,257 @@
+/*
+ * Watchdog driver for Cirrus Logic EP93xx family of devices.
+ *
+ * Copyright (c) 2004 Ray Lehtiniemi
+ * Copyright (c) 2006 Tower Technologies
+ * Based on ep93xx driver, bits from alim7101_wdt.c
+ *
+ * Authors: Ray Lehtiniemi <rayl@mail.com>,
+ * Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * This watchdog fires after 250msec, which is a too short interval
+ * for us to rely on the user space daemon alone. So we ping the
+ * wdt each ~200msec and eventually stop doing it if the user space
+ * daemon dies.
+ *
+ * TODO:
+ *
+ * - Test last reset from watchdog status
+ * - Add a few missing ioctls
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/timer.h>
+
+#include <asm/hardware.h>
+#include <asm/uaccess.h>
+
+#define WDT_VERSION "0.3"
+#define PFX "ep93xx_wdt: "
+
+/* default timeout (secs) */
+#define WDT_TIMEOUT 30
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+static int timeout = WDT_TIMEOUT;
+
+static struct timer_list timer;
+static unsigned long next_heartbeat;
+static unsigned long wdt_status;
+static unsigned long boot_status;
+
+#define WDT_IN_USE 0
+#define WDT_OK_TO_CLOSE 1
+
+#define EP93XX_WDT_REG(x) (EP93XX_WATCHDOG_BASE + (x))
+#define EP93XX_WDT_WATCHDOG EP93XX_WDT_REG(0x00)
+#define EP93XX_WDT_WDSTATUS EP93XX_WDT_REG(0x04)
+
+/* reset the wdt every ~200ms */
+#define WDT_INTERVAL (HZ/5)
+
+static void wdt_enable(void)
+{
+ __raw_writew(0xaaaa, EP93XX_WDT_WATCHDOG);
+}
+
+static void wdt_disable(void)
+{
+ __raw_writew(0xaa55, EP93XX_WDT_WATCHDOG);
+}
+
+static inline void wdt_ping(void)
+{
+ __raw_writew(0x5555, EP93XX_WDT_WATCHDOG);
+}
+
+static void wdt_startup(void)
+{
+ next_heartbeat = jiffies + (timeout * HZ);
+
+ wdt_enable();
+ mod_timer(&timer, jiffies + WDT_INTERVAL);
+}
+
+static void wdt_shutdown(void)
+{
+ del_timer_sync(&timer);
+ wdt_disable();
+}
+
+static void wdt_keepalive(void)
+{
+ /* user land ping */
+ next_heartbeat = jiffies + (timeout * HZ);
+}
+
+static int ep93xx_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(WDT_IN_USE, &wdt_status))
+ return -EBUSY;
+
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+ wdt_startup();
+
+ return nonseekable_open(inode, file);
+}
+
+static ssize_t
+ep93xx_wdt_write(struct file *file, const char __user *data, size_t len,
+ loff_t *ppos)
+{
+ /* Can't seek (pwrite) on this device */
+ if (*ppos != file->f_pos)
+ return -ESPIPE;
+
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+ for (i = 0; i != len; i++) {
+ char c;
+
+ if (get_user(c, data + i))
+ return -EFAULT;
+
+ if (c == 'V')
+ set_bit(WDT_OK_TO_CLOSE, &wdt_status);
+ else
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+ }
+ }
+ wdt_keepalive();
+ }
+
+ return len;
+}
+
+static struct watchdog_info ident = {
+ .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE,
+ .identity = "EP93xx Watchdog",
+};
+
+static int
+ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = -ENOIOCTLCMD;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
+ sizeof(ident)) ? -EFAULT : 0;
+ break;
+
+ case WDIOC_GETSTATUS:
+ ret = put_user(0, (int __user *)arg);
+ break;
+
+ case WDIOC_GETBOOTSTATUS:
+ ret = put_user(boot_status, (int __user *)arg);
+ break;
+
+ case WDIOC_GETTIMEOUT:
+ /* actually, it is 0.250 seconds.... */
+ ret = put_user(1, (int __user *)arg);
+ break;
+
+ case WDIOC_KEEPALIVE:
+ wdt_keepalive();
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static int ep93xx_wdt_release(struct inode *inode, struct file *file)
+{
+ if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
+ wdt_shutdown();
+ else
+ printk(KERN_CRIT PFX "Device closed unexpectedly - "
+ "timer will not stop\n");
+
+ clear_bit(WDT_IN_USE, &wdt_status);
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+ return 0;
+}
+
+static struct file_operations ep93xx_wdt_fops = {
+ .owner = THIS_MODULE,
+ .write = ep93xx_wdt_write,
+ .ioctl = ep93xx_wdt_ioctl,
+ .open = ep93xx_wdt_open,
+ .release = ep93xx_wdt_release,
+};
+
+static struct miscdevice ep93xx_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &ep93xx_wdt_fops,
+};
+
+static void ep93xx_timer_ping(unsigned long data)
+{
+ if (time_before(jiffies, next_heartbeat))
+ wdt_ping();
+
+ /* Re-set the timer interval */
+ mod_timer(&timer, jiffies + WDT_INTERVAL);
+}
+
+static int __init ep93xx_wdt_init(void)
+{
+ int err;
+
+ err = misc_register(&ep93xx_wdt_miscdev);
+
+ boot_status = __raw_readl(EP93XX_WDT_WATCHDOG) & 0x01 ? 1 : 0;
+
+ printk(KERN_INFO PFX "EP93XX watchdog, driver version "
+ WDT_VERSION "%s\n",
+ (__raw_readl(EP93XX_WDT_WATCHDOG) & 0x08)
+ ? " (nCS1 disable detected)" : "");
+
+ if (timeout < 1 || timeout > 3600) {
+ timeout = WDT_TIMEOUT;
+ printk(KERN_INFO PFX
+ "timeout value must be 1<=x<=3600, using %d\n",
+ timeout);
+ }
+
+ setup_timer(&timer, ep93xx_timer_ping, 1);
+ return err;
+}
+
+static void __exit ep93xx_wdt_exit(void)
+{
+ wdt_shutdown();
+ misc_deregister(&ep93xx_wdt_miscdev);
+}
+
+module_init(ep93xx_wdt_init);
+module_exit(ep93xx_wdt_exit);
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>,"
+ "Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("EP93xx Watchdog");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(WDT_VERSION);
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 9582de1c9ca..9b6ae7dc8b8 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -5,7 +5,9 @@
* (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
*
* Oct 2005 - Ashok Raj <ashok.raj@intel.com>
- * Added handling for CPU hotplug
+ * Added handling for CPU hotplug
+ * Feb 2006 - Jacob Shin <jacob.shin@amd.com>
+ * Fix handling for CPU hotplug -- affected CPUs
*
* 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
@@ -44,15 +46,14 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
static void handle_update(void *data);
/**
- * Two notifier lists: the "policy" list is involved in the
- * validation process for a new CPU frequency policy; the
+ * Two notifier lists: the "policy" list is involved in the
+ * validation process for a new CPU frequency policy; the
* "transition" list for kernel code that needs to handle
* changes to devices when the CPU clock speed changes.
* The mutex locks both lists.
*/
-static struct notifier_block *cpufreq_policy_notifier_list;
-static struct notifier_block *cpufreq_transition_notifier_list;
-static DECLARE_RWSEM (cpufreq_notifier_rwsem);
+static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
+static BLOCKING_NOTIFIER_HEAD(cpufreq_transition_notifier_list);
static LIST_HEAD(cpufreq_governor_list);
@@ -151,7 +152,7 @@ void cpufreq_debug_printk(unsigned int type, const char *prefix, const char *fmt
va_list args;
unsigned int len;
unsigned long flags;
-
+
WARN_ON(!prefix);
if (type & debug) {
spin_lock_irqsave(&disable_ratelimit_lock, flags);
@@ -198,7 +199,7 @@ static inline void cpufreq_debug_disable_ratelimit(void) { return; }
*
* This function alters the system "loops_per_jiffy" for the clock
* speed change. Note that loops_per_jiffy cannot be updated on SMP
- * systems as each CPU might be scaled differently. So, use the arch
+ * systems as each CPU might be scaled differently. So, use the arch
* per-CPU loops_per_jiffy value wherever possible.
*/
#ifndef CONFIG_SMP
@@ -233,7 +234,7 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) {
*
* This function calls the transition notifiers and the "adjust_jiffies"
* function. It is called twice on all CPU frequency changes that have
- * external effects.
+ * external effects.
*/
void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
{
@@ -245,13 +246,11 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
dprintk("notification %u of frequency transition to %u kHz\n",
state, freqs->new);
- down_read(&cpufreq_notifier_rwsem);
-
policy = cpufreq_cpu_data[freqs->cpu];
switch (state) {
case CPUFREQ_PRECHANGE:
- /* detect if the driver reported a value as "old frequency"
+ /* detect if the driver reported a value as "old frequency"
* which is not equal to what the cpufreq core thinks is
* "old frequency".
*/
@@ -264,20 +263,19 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
freqs->old = policy->cur;
}
}
- notifier_call_chain(&cpufreq_transition_notifier_list,
- CPUFREQ_PRECHANGE, freqs);
+ blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
+ CPUFREQ_PRECHANGE, freqs);
adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
break;
case CPUFREQ_POSTCHANGE:
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
- notifier_call_chain(&cpufreq_transition_notifier_list,
- CPUFREQ_POSTCHANGE, freqs);
+ blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
+ CPUFREQ_POSTCHANGE, freqs);
if (likely(policy) && likely(policy->cpu == freqs->cpu))
policy->cur = freqs->new;
break;
}
- up_read(&cpufreq_notifier_rwsem);
}
EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
@@ -335,11 +333,11 @@ extern struct sysdev_class cpu_sysdev_class;
* "unsigned int".
*/
-#define show_one(file_name, object) \
-static ssize_t show_##file_name \
-(struct cpufreq_policy * policy, char *buf) \
-{ \
- return sprintf (buf, "%u\n", policy->object); \
+#define show_one(file_name, object) \
+static ssize_t show_##file_name \
+(struct cpufreq_policy * policy, char *buf) \
+{ \
+ return sprintf (buf, "%u\n", policy->object); \
}
show_one(cpuinfo_min_freq, cpuinfo.min_freq);
@@ -404,8 +402,8 @@ static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf)
/**
* store_scaling_governor - store policy for the specified CPU
*/
-static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
- const char *buf, size_t count)
+static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
+ const char *buf, size_t count)
{
unsigned int ret = -EINVAL;
char str_governor[16];
@@ -528,7 +526,7 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf)
return ret;
}
-static ssize_t store(struct kobject * kobj, struct attribute * attr,
+static ssize_t store(struct kobject * kobj, struct attribute * attr,
const char * buf, size_t count)
{
struct cpufreq_policy * policy = to_policy(kobj);
@@ -564,7 +562,7 @@ static struct kobj_type ktype_cpufreq = {
/**
* cpufreq_add_dev - add a CPU device
*
- * Adds the cpufreq interface for a CPU device.
+ * Adds the cpufreq interface for a CPU device.
*/
static int cpufreq_add_dev (struct sys_device * sys_dev)
{
@@ -573,8 +571,12 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
struct cpufreq_policy new_policy;
struct cpufreq_policy *policy;
struct freq_attr **drv_attr;
+ struct sys_device *cpu_sys_dev;
unsigned long flags;
unsigned int j;
+#ifdef CONFIG_SMP
+ struct cpufreq_policy *managed_policy;
+#endif
if (cpu_is_offline(cpu))
return 0;
@@ -587,8 +589,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
* CPU because it is in the same boat. */
policy = cpufreq_cpu_get(cpu);
if (unlikely(policy)) {
- dprintk("CPU already managed, adding link\n");
- sysfs_create_link(&sys_dev->kobj, &policy->kobj, "cpufreq");
+ cpufreq_cpu_put(policy);
cpufreq_debug_enable_ratelimit();
return 0;
}
@@ -623,6 +624,32 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
goto err_out;
}
+#ifdef CONFIG_SMP
+ for_each_cpu_mask(j, policy->cpus) {
+ if (cpu == j)
+ continue;
+
+ /* check for existing affected CPUs. They may not be aware
+ * of it due to CPU Hotplug.
+ */
+ managed_policy = cpufreq_cpu_get(j);
+ if (unlikely(managed_policy)) {
+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
+ managed_policy->cpus = policy->cpus;
+ cpufreq_cpu_data[cpu] = managed_policy;
+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+
+ dprintk("CPU already managed, adding link\n");
+ sysfs_create_link(&sys_dev->kobj,
+ &managed_policy->kobj, "cpufreq");
+
+ cpufreq_debug_enable_ratelimit();
+ mutex_unlock(&policy->lock);
+ ret = 0;
+ goto err_out_driver_exit; /* call driver->exit() */
+ }
+ }
+#endif
memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
/* prepare interface data */
@@ -650,6 +677,21 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
for_each_cpu_mask(j, policy->cpus)
cpufreq_cpu_data[j] = policy;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+
+ /* symlink affected CPUs */
+ for_each_cpu_mask(j, policy->cpus) {
+ if (j == cpu)
+ continue;
+ if (!cpu_online(j))
+ continue;
+
+ dprintk("CPU already managed, adding link\n");
+ cpufreq_cpu_get(cpu);
+ cpu_sys_dev = get_cpu_sysdev(j);
+ sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
+ "cpufreq");
+ }
+
policy->governor = NULL; /* to assure that the starting sequence is
* run in cpufreq_set_policy */
mutex_unlock(&policy->lock);
@@ -724,10 +766,11 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
#ifdef CONFIG_SMP
/* if this isn't the CPU which is the parent of the kobj, we
- * only need to unlink, put and exit
+ * only need to unlink, put and exit
*/
if (unlikely(cpu != data->cpu)) {
dprintk("removing link\n");
+ cpu_clear(cpu, data->cpus);
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
sysfs_remove_link(&sys_dev->kobj, "cpufreq");
cpufreq_cpu_put(data);
@@ -740,7 +783,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
if (!kobject_get(&data->kobj)) {
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
cpufreq_debug_enable_ratelimit();
- return -EFAULT;
+ return -EFAULT;
}
#ifdef CONFIG_SMP
@@ -783,7 +826,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
kobject_put(&data->kobj);
/* we need to make sure that the underlying kobj is actually
- * not referenced anymore by anybody before we proceed with
+ * not referenced anymore by anybody before we proceed with
* unloading.
*/
dprintk("waiting for dropping of refcount\n");
@@ -831,7 +874,7 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne
}
-/**
+/**
* cpufreq_quick_get - get the CPU frequency (in kHz) frpm policy->cur
* @cpu: CPU number
*
@@ -855,7 +898,7 @@ unsigned int cpufreq_quick_get(unsigned int cpu)
EXPORT_SYMBOL(cpufreq_quick_get);
-/**
+/**
* cpufreq_get - get the current CPU frequency (in kHz)
* @cpu: CPU number
*
@@ -960,7 +1003,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
freqs.old = cpu_policy->cur;
freqs.new = cur_freq;
- notifier_call_chain(&cpufreq_transition_notifier_list,
+ blocking_notifier_call_chain(&cpufreq_transition_notifier_list,
CPUFREQ_SUSPENDCHANGE, &freqs);
adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs);
@@ -1041,7 +1084,8 @@ static int cpufreq_resume(struct sys_device * sysdev)
freqs.old = cpu_policy->cur;
freqs.new = cur_freq;
- notifier_call_chain(&cpufreq_transition_notifier_list,
+ blocking_notifier_call_chain(
+ &cpufreq_transition_notifier_list,
CPUFREQ_RESUMECHANGE, &freqs);
adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs);
@@ -1072,30 +1116,30 @@ static struct sysdev_driver cpufreq_sysdev_driver = {
* @nb: notifier function to register
* @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
*
- * Add a driver to one of two lists: either a list of drivers that
+ * Add a driver to one of two lists: either a list of drivers that
* are notified about clock rate changes (once before and once after
* the transition), or a list of drivers that are notified about
* changes in cpufreq policy.
*
* This function may sleep, and has the same return conditions as
- * notifier_chain_register.
+ * blocking_notifier_chain_register.
*/
int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
{
int ret;
- down_write(&cpufreq_notifier_rwsem);
switch (list) {
case CPUFREQ_TRANSITION_NOTIFIER:
- ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb);
+ ret = blocking_notifier_chain_register(
+ &cpufreq_transition_notifier_list, nb);
break;
case CPUFREQ_POLICY_NOTIFIER:
- ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb);
+ ret = blocking_notifier_chain_register(
+ &cpufreq_policy_notifier_list, nb);
break;
default:
ret = -EINVAL;
}
- up_write(&cpufreq_notifier_rwsem);
return ret;
}
@@ -1110,24 +1154,24 @@ EXPORT_SYMBOL(cpufreq_register_notifier);
* Remove a driver from the CPU frequency notifier list.
*
* This function may sleep, and has the same return conditions as
- * notifier_chain_unregister.
+ * blocking_notifier_chain_unregister.
*/
int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
{
int ret;
- down_write(&cpufreq_notifier_rwsem);
switch (list) {
case CPUFREQ_TRANSITION_NOTIFIER:
- ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb);
+ ret = blocking_notifier_chain_unregister(
+ &cpufreq_transition_notifier_list, nb);
break;
case CPUFREQ_POLICY_NOTIFIER:
- ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb);
+ ret = blocking_notifier_chain_unregister(
+ &cpufreq_policy_notifier_list, nb);
break;
default:
ret = -EINVAL;
}
- up_write(&cpufreq_notifier_rwsem);
return ret;
}
@@ -1225,7 +1269,7 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
return -EINVAL;
mutex_lock(&cpufreq_governor_mutex);
-
+
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
mutex_unlock(&cpufreq_governor_mutex);
@@ -1234,7 +1278,7 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
}
list_add(&governor->governor_list, &cpufreq_governor_list);
- mutex_unlock(&cpufreq_governor_mutex);
+ mutex_unlock(&cpufreq_governor_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_register_governor);
@@ -1299,29 +1343,23 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
if (ret)
goto error_out;
- down_read(&cpufreq_notifier_rwsem);
-
/* adjust if necessary - all reasons */
- notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST,
- policy);
+ blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+ CPUFREQ_ADJUST, policy);
/* adjust if necessary - hardware incompatibility*/
- notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE,
- policy);
+ blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+ CPUFREQ_INCOMPATIBLE, policy);
/* verify the cpu speed can be set within this limit,
which might be different to the first one */
ret = cpufreq_driver->verify(policy);
- if (ret) {
- up_read(&cpufreq_notifier_rwsem);
+ if (ret)
goto error_out;
- }
/* notification of the new policy */
- notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY,
- policy);
-
- up_read(&cpufreq_notifier_rwsem);
+ blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+ CPUFREQ_NOTIFY, policy);
data->min = policy->min;
data->max = policy->max;
@@ -1497,9 +1535,9 @@ static struct notifier_block cpufreq_cpu_notifier =
* @driver_data: A struct cpufreq_driver containing the values#
* submitted by the CPU Frequency driver.
*
- * Registers a CPU Frequency driver to this core code. This code
+ * Registers a CPU Frequency driver to this core code. This code
* returns zero on success, -EBUSY when another driver got here first
- * (and isn't unregistered in the meantime).
+ * (and isn't unregistered in the meantime).
*
*/
int cpufreq_register_driver(struct cpufreq_driver *driver_data)
@@ -1560,7 +1598,7 @@ EXPORT_SYMBOL_GPL(cpufreq_register_driver);
/**
* cpufreq_unregister_driver - unregister the current CPUFreq driver
*
- * Unregister the current CPUFreq driver. Only call this if you have
+ * Unregister the current CPUFreq driver. Only call this if you have
* the right to do so, i.e. if you have succeeded in initialising before!
* Returns zero if successful, and -EINVAL if the cpufreq_driver is
* currently not initialised.
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index ac38766b258..037f6bf4543 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -35,12 +35,7 @@
*/
#define DEF_FREQUENCY_UP_THRESHOLD (80)
-#define MIN_FREQUENCY_UP_THRESHOLD (0)
-#define MAX_FREQUENCY_UP_THRESHOLD (100)
-
#define DEF_FREQUENCY_DOWN_THRESHOLD (20)
-#define MIN_FREQUENCY_DOWN_THRESHOLD (0)
-#define MAX_FREQUENCY_DOWN_THRESHOLD (100)
/*
* The polling frequency of this governor depends on the capability of
@@ -53,10 +48,14 @@
* All times here are in uS.
*/
static unsigned int def_sampling_rate;
-#define MIN_SAMPLING_RATE (def_sampling_rate / 2)
+#define MIN_SAMPLING_RATE_RATIO (2)
+/* for correct statistics, we need at least 10 ticks between each measure */
+#define MIN_STAT_SAMPLING_RATE (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
+#define MIN_SAMPLING_RATE (def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
#define MAX_SAMPLING_RATE (500 * def_sampling_rate)
-#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (100000)
-#define DEF_SAMPLING_DOWN_FACTOR (5)
+#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000)
+#define DEF_SAMPLING_DOWN_FACTOR (1)
+#define MAX_SAMPLING_DOWN_FACTOR (10)
#define TRANSITION_LATENCY_LIMIT (10 * 1000)
static void do_dbs_timer(void *data);
@@ -66,6 +65,8 @@ struct cpu_dbs_info_s {
unsigned int prev_cpu_idle_up;
unsigned int prev_cpu_idle_down;
unsigned int enable;
+ unsigned int down_skip;
+ unsigned int requested_freq;
};
static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
@@ -87,6 +88,8 @@ static struct dbs_tuners dbs_tuners_ins = {
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
.down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
+ .ignore_nice = 0,
+ .freq_step = 5,
};
static inline unsigned int get_cpu_idle_time(unsigned int cpu)
@@ -136,7 +139,7 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
unsigned int input;
int ret;
ret = sscanf (buf, "%u", &input);
- if (ret != 1 )
+ if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
return -EINVAL;
mutex_lock(&dbs_mutex);
@@ -173,8 +176,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
ret = sscanf (buf, "%u", &input);
mutex_lock(&dbs_mutex);
- if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
- input < MIN_FREQUENCY_UP_THRESHOLD ||
+ if (ret != 1 || input > 100 || input < 0 ||
input <= dbs_tuners_ins.down_threshold) {
mutex_unlock(&dbs_mutex);
return -EINVAL;
@@ -194,8 +196,7 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused,
ret = sscanf (buf, "%u", &input);
mutex_lock(&dbs_mutex);
- if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD ||
- input < MIN_FREQUENCY_DOWN_THRESHOLD ||
+ if (ret != 1 || input > 100 || input < 0 ||
input >= dbs_tuners_ins.up_threshold) {
mutex_unlock(&dbs_mutex);
return -EINVAL;
@@ -297,31 +298,17 @@ static struct attribute_group dbs_attr_group = {
static void dbs_check_cpu(int cpu)
{
unsigned int idle_ticks, up_idle_ticks, down_idle_ticks;
+ unsigned int tmp_idle_ticks, total_idle_ticks;
unsigned int freq_step;
unsigned int freq_down_sampling_rate;
- static int down_skip[NR_CPUS];
- static int requested_freq[NR_CPUS];
- static unsigned short init_flag = 0;
- struct cpu_dbs_info_s *this_dbs_info;
- struct cpu_dbs_info_s *dbs_info;
-
+ struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
struct cpufreq_policy *policy;
- unsigned int j;
- this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
if (!this_dbs_info->enable)
return;
policy = this_dbs_info->cur_policy;
- if ( init_flag == 0 ) {
- for_each_online_cpu(j) {
- dbs_info = &per_cpu(cpu_dbs_info, j);
- requested_freq[j] = dbs_info->cur_policy->cur;
- }
- init_flag = 1;
- }
-
/*
* The default safe range is 20% to 80%
* Every sampling_rate, we check
@@ -337,39 +324,29 @@ static void dbs_check_cpu(int cpu)
*/
/* Check for frequency increase */
-
idle_ticks = UINT_MAX;
- for_each_cpu_mask(j, policy->cpus) {
- unsigned int tmp_idle_ticks, total_idle_ticks;
- struct cpu_dbs_info_s *j_dbs_info;
- j_dbs_info = &per_cpu(cpu_dbs_info, j);
- /* Check for frequency increase */
- total_idle_ticks = get_cpu_idle_time(j);
- tmp_idle_ticks = total_idle_ticks -
- j_dbs_info->prev_cpu_idle_up;
- j_dbs_info->prev_cpu_idle_up = total_idle_ticks;
-
- if (tmp_idle_ticks < idle_ticks)
- idle_ticks = tmp_idle_ticks;
- }
+ /* Check for frequency increase */
+ total_idle_ticks = get_cpu_idle_time(cpu);
+ tmp_idle_ticks = total_idle_ticks -
+ this_dbs_info->prev_cpu_idle_up;
+ this_dbs_info->prev_cpu_idle_up = total_idle_ticks;
+
+ if (tmp_idle_ticks < idle_ticks)
+ idle_ticks = tmp_idle_ticks;
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks *= 100;
up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) *
- usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+ usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
if (idle_ticks < up_idle_ticks) {
- down_skip[cpu] = 0;
- for_each_cpu_mask(j, policy->cpus) {
- struct cpu_dbs_info_s *j_dbs_info;
+ this_dbs_info->down_skip = 0;
+ this_dbs_info->prev_cpu_idle_down =
+ this_dbs_info->prev_cpu_idle_up;
- j_dbs_info = &per_cpu(cpu_dbs_info, j);
- j_dbs_info->prev_cpu_idle_down =
- j_dbs_info->prev_cpu_idle_up;
- }
/* if we are already at full speed then break out early */
- if (requested_freq[cpu] == policy->max)
+ if (this_dbs_info->requested_freq == policy->max)
return;
freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100;
@@ -378,49 +355,45 @@ static void dbs_check_cpu(int cpu)
if (unlikely(freq_step == 0))
freq_step = 5;
- requested_freq[cpu] += freq_step;
- if (requested_freq[cpu] > policy->max)
- requested_freq[cpu] = policy->max;
+ this_dbs_info->requested_freq += freq_step;
+ if (this_dbs_info->requested_freq > policy->max)
+ this_dbs_info->requested_freq = policy->max;
- __cpufreq_driver_target(policy, requested_freq[cpu],
+ __cpufreq_driver_target(policy, this_dbs_info->requested_freq,
CPUFREQ_RELATION_H);
return;
}
/* Check for frequency decrease */
- down_skip[cpu]++;
- if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor)
+ this_dbs_info->down_skip++;
+ if (this_dbs_info->down_skip < dbs_tuners_ins.sampling_down_factor)
return;
- idle_ticks = UINT_MAX;
- for_each_cpu_mask(j, policy->cpus) {
- unsigned int tmp_idle_ticks, total_idle_ticks;
- struct cpu_dbs_info_s *j_dbs_info;
+ /* Check for frequency decrease */
+ total_idle_ticks = this_dbs_info->prev_cpu_idle_up;
+ tmp_idle_ticks = total_idle_ticks -
+ this_dbs_info->prev_cpu_idle_down;
+ this_dbs_info->prev_cpu_idle_down = total_idle_ticks;
- j_dbs_info = &per_cpu(cpu_dbs_info, j);
- total_idle_ticks = j_dbs_info->prev_cpu_idle_up;
- tmp_idle_ticks = total_idle_ticks -
- j_dbs_info->prev_cpu_idle_down;
- j_dbs_info->prev_cpu_idle_down = total_idle_ticks;
-
- if (tmp_idle_ticks < idle_ticks)
- idle_ticks = tmp_idle_ticks;
- }
+ if (tmp_idle_ticks < idle_ticks)
+ idle_ticks = tmp_idle_ticks;
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks *= 100;
- down_skip[cpu] = 0;
+ this_dbs_info->down_skip = 0;
freq_down_sampling_rate = dbs_tuners_ins.sampling_rate *
dbs_tuners_ins.sampling_down_factor;
down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) *
- usecs_to_jiffies(freq_down_sampling_rate);
+ usecs_to_jiffies(freq_down_sampling_rate);
if (idle_ticks > down_idle_ticks) {
- /* if we are already at the lowest speed then break out early
+ /*
+ * if we are already at the lowest speed then break out early
* or if we 'cannot' reduce the speed as the user might want
- * freq_step to be zero */
- if (requested_freq[cpu] == policy->min
+ * freq_step to be zero
+ */
+ if (this_dbs_info->requested_freq == policy->min
|| dbs_tuners_ins.freq_step == 0)
return;
@@ -430,13 +403,12 @@ static void dbs_check_cpu(int cpu)
if (unlikely(freq_step == 0))
freq_step = 5;
- requested_freq[cpu] -= freq_step;
- if (requested_freq[cpu] < policy->min)
- requested_freq[cpu] = policy->min;
+ this_dbs_info->requested_freq -= freq_step;
+ if (this_dbs_info->requested_freq < policy->min)
+ this_dbs_info->requested_freq = policy->min;
- __cpufreq_driver_target(policy,
- requested_freq[cpu],
- CPUFREQ_RELATION_H);
+ __cpufreq_driver_target(policy, this_dbs_info->requested_freq,
+ CPUFREQ_RELATION_H);
return;
}
}
@@ -493,11 +465,13 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;
- j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
+ j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(cpu);
j_dbs_info->prev_cpu_idle_down
= j_dbs_info->prev_cpu_idle_up;
}
this_dbs_info->enable = 1;
+ this_dbs_info->down_skip = 0;
+ this_dbs_info->requested_freq = policy->cur;
sysfs_create_group(&policy->kobj, &dbs_attr_group);
dbs_enable++;
/*
@@ -507,16 +481,17 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
if (dbs_enable == 1) {
unsigned int latency;
/* policy latency is in nS. Convert it to uS first */
+ latency = policy->cpuinfo.transition_latency / 1000;
+ if (latency == 0)
+ latency = 1;
- latency = policy->cpuinfo.transition_latency;
- if (latency < 1000)
- latency = 1000;
-
- def_sampling_rate = (latency / 1000) *
+ def_sampling_rate = 10 * latency *
DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
+
+ if (def_sampling_rate < MIN_STAT_SAMPLING_RATE)
+ def_sampling_rate = MIN_STAT_SAMPLING_RATE;
+
dbs_tuners_ins.sampling_rate = def_sampling_rate;
- dbs_tuners_ins.ignore_nice = 0;
- dbs_tuners_ins.freq_step = 5;
dbs_timer_init();
}
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 9ee9411f186..956d121cb16 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -38,17 +38,17 @@
#define MIN_FREQUENCY_UP_THRESHOLD (11)
#define MAX_FREQUENCY_UP_THRESHOLD (100)
-/*
- * The polling frequency of this governor depends on the capability of
+/*
+ * The polling frequency of this governor depends on the capability of
* the processor. Default polling frequency is 1000 times the transition
- * latency of the processor. The governor will work on any processor with
- * transition latency <= 10mS, using appropriate sampling
+ * latency of the processor. The governor will work on any processor with
+ * transition latency <= 10mS, using appropriate sampling
* rate.
* For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
* this governor will not work.
* All times here are in uS.
*/
-static unsigned int def_sampling_rate;
+static unsigned int def_sampling_rate;
#define MIN_SAMPLING_RATE_RATIO (2)
/* for correct statistics, we need at least 10 ticks between each measure */
#define MIN_STAT_SAMPLING_RATE (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10))
@@ -62,28 +62,29 @@ static unsigned int def_sampling_rate;
static void do_dbs_timer(void *data);
struct cpu_dbs_info_s {
- struct cpufreq_policy *cur_policy;
- unsigned int prev_cpu_idle_up;
- unsigned int prev_cpu_idle_down;
- unsigned int enable;
+ struct cpufreq_policy *cur_policy;
+ unsigned int prev_cpu_idle_up;
+ unsigned int prev_cpu_idle_down;
+ unsigned int enable;
};
static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
static unsigned int dbs_enable; /* number of CPUs using this policy */
-static DEFINE_MUTEX (dbs_mutex);
+static DEFINE_MUTEX (dbs_mutex);
static DECLARE_WORK (dbs_work, do_dbs_timer, NULL);
struct dbs_tuners {
- unsigned int sampling_rate;
- unsigned int sampling_down_factor;
- unsigned int up_threshold;
- unsigned int ignore_nice;
+ unsigned int sampling_rate;
+ unsigned int sampling_down_factor;
+ unsigned int up_threshold;
+ unsigned int ignore_nice;
};
static struct dbs_tuners dbs_tuners_ins = {
- .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
- .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
+ .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
+ .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
+ .ignore_nice = 0,
};
static inline unsigned int get_cpu_idle_time(unsigned int cpu)
@@ -106,8 +107,8 @@ static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf)
return sprintf (buf, "%u\n", MIN_SAMPLING_RATE);
}
-#define define_one_ro(_name) \
-static struct freq_attr _name = \
+#define define_one_ro(_name) \
+static struct freq_attr _name = \
__ATTR(_name, 0444, show_##_name, NULL)
define_one_ro(sampling_rate_max);
@@ -125,7 +126,7 @@ show_one(sampling_down_factor, sampling_down_factor);
show_one(up_threshold, up_threshold);
show_one(ignore_nice_load, ignore_nice);
-static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
+static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
const char *buf, size_t count)
{
unsigned int input;
@@ -144,7 +145,7 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
return count;
}
-static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
+static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
const char *buf, size_t count)
{
unsigned int input;
@@ -163,7 +164,7 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
return count;
}
-static ssize_t store_up_threshold(struct cpufreq_policy *unused,
+static ssize_t store_up_threshold(struct cpufreq_policy *unused,
const char *buf, size_t count)
{
unsigned int input;
@@ -171,7 +172,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
ret = sscanf (buf, "%u", &input);
mutex_lock(&dbs_mutex);
- if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
+ if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
input < MIN_FREQUENCY_UP_THRESHOLD) {
mutex_unlock(&dbs_mutex);
return -EINVAL;
@@ -190,14 +191,14 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
int ret;
unsigned int j;
-
+
ret = sscanf (buf, "%u", &input);
if ( ret != 1 )
return -EINVAL;
if ( input > 1 )
input = 1;
-
+
mutex_lock(&dbs_mutex);
if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */
mutex_unlock(&dbs_mutex);
@@ -259,16 +260,16 @@ static void dbs_check_cpu(int cpu)
return;
policy = this_dbs_info->cur_policy;
- /*
+ /*
* Every sampling_rate, we check, if current idle time is less
* than 20% (default), then we try to increase frequency
* Every sampling_rate*sampling_down_factor, we look for a the lowest
* frequency which can sustain the load while keeping idle time over
* 30%. If such a frequency exist, we try to decrease to this frequency.
*
- * Any frequency increase takes it to the maximum frequency.
- * Frequency reduction happens at minimum steps of
- * 5% (default) of current frequency
+ * Any frequency increase takes it to the maximum frequency.
+ * Frequency reduction happens at minimum steps of
+ * 5% (default) of current frequency
*/
/* Check for frequency increase */
@@ -298,14 +299,14 @@ static void dbs_check_cpu(int cpu)
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
- j_dbs_info->prev_cpu_idle_down =
+ j_dbs_info->prev_cpu_idle_down =
j_dbs_info->prev_cpu_idle_up;
}
/* if we are already at full speed then break out early */
if (policy->cur == policy->max)
return;
-
- __cpufreq_driver_target(policy, policy->max,
+
+ __cpufreq_driver_target(policy, policy->max,
CPUFREQ_RELATION_H);
return;
}
@@ -347,23 +348,26 @@ static void dbs_check_cpu(int cpu)
* policy. To be safe, we focus 10 points under the threshold.
*/
freq_next = ((total_ticks - idle_ticks) * 100) / total_ticks;
- freq_next = (freq_next * policy->cur) /
+ freq_next = (freq_next * policy->cur) /
(dbs_tuners_ins.up_threshold - 10);
+ if (freq_next < policy->min)
+ freq_next = policy->min;
+
if (freq_next <= ((policy->cur * 95) / 100))
__cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L);
}
static void do_dbs_timer(void *data)
-{
+{
int i;
mutex_lock(&dbs_mutex);
for_each_online_cpu(i)
dbs_check_cpu(i);
- schedule_delayed_work(&dbs_work,
+ schedule_delayed_work(&dbs_work,
usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
mutex_unlock(&dbs_mutex);
-}
+}
static inline void dbs_timer_init(void)
{
@@ -390,22 +394,25 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
switch (event) {
case CPUFREQ_GOV_START:
- if ((!cpu_online(cpu)) ||
+ if ((!cpu_online(cpu)) ||
(!policy->cur))
return -EINVAL;
if (policy->cpuinfo.transition_latency >
- (TRANSITION_LATENCY_LIMIT * 1000))
+ (TRANSITION_LATENCY_LIMIT * 1000)) {
+ printk(KERN_WARNING "ondemand governor failed to load "
+ "due to too long transition latency\n");
return -EINVAL;
+ }
if (this_dbs_info->enable) /* Already enabled */
break;
-
+
mutex_lock(&dbs_mutex);
for_each_cpu_mask(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;
-
+
j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
j_dbs_info->prev_cpu_idle_down
= j_dbs_info->prev_cpu_idle_up;
@@ -431,11 +438,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
def_sampling_rate = MIN_STAT_SAMPLING_RATE;
dbs_tuners_ins.sampling_rate = def_sampling_rate;
- dbs_tuners_ins.ignore_nice = 0;
-
dbs_timer_init();
}
-
+
mutex_unlock(&dbs_mutex);
break;
@@ -448,9 +453,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
* Stop the timerschedule work, when this governor
* is used for first time
*/
- if (dbs_enable == 0)
+ if (dbs_enable == 0)
dbs_timer_exit();
-
+
mutex_unlock(&dbs_mutex);
break;
@@ -460,11 +465,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
if (policy->max < this_dbs_info->cur_policy->cur)
__cpufreq_driver_target(
this_dbs_info->cur_policy,
- policy->max, CPUFREQ_RELATION_H);
+ policy->max, CPUFREQ_RELATION_H);
else if (policy->min > this_dbs_info->cur_policy->cur)
__cpufreq_driver_target(
this_dbs_info->cur_policy,
- policy->min, CPUFREQ_RELATION_L);
+ policy->min, CPUFREQ_RELATION_L);
mutex_unlock(&dbs_mutex);
break;
}
diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c
index 8d536b40deb..de91e3371ef 100644
--- a/drivers/cpufreq/cpufreq_performance.c
+++ b/drivers/cpufreq/cpufreq_performance.c
@@ -32,7 +32,7 @@ static int cpufreq_governor_performance(struct cpufreq_policy *policy,
}
return 0;
}
-
+
struct cpufreq_governor cpufreq_gov_performance = {
.name = "performance",
.governor = cpufreq_governor_performance,
diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c
index c85edda7feb..0a2596044e6 100644
--- a/drivers/cpufreq/cpufreq_powersave.c
+++ b/drivers/cpufreq/cpufreq_powersave.c
@@ -31,7 +31,7 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
}
return 0;
}
-
+
static struct cpufreq_governor cpufreq_gov_powersave = {
.name = "powersave",
.governor = cpufreq_governor_powersave,
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 0bddb8e694d..9694b6ed326 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -2,7 +2,7 @@
* drivers/cpufreq/cpufreq_stats.c
*
* Copyright (C) 2003-2004 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
- * (C) 2004 Zou Nan hai <nanhai.zou@intel.com>.
+ * (C) 2004 Zou Nan hai <nanhai.zou@intel.com>.
*
* 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
@@ -90,7 +90,7 @@ show_time_in_state(struct cpufreq_policy *policy, char *buf)
return 0;
cpufreq_stats_update(stat->cpu);
for (i = 0; i < stat->state_num; i++) {
- len += sprintf(buf + len, "%u %llu\n", stat->freq_table[i],
+ len += sprintf(buf + len, "%u %llu\n", stat->freq_table[i],
(unsigned long long)cputime64_to_clock_t(stat->time_in_state[i]));
}
return len;
@@ -171,7 +171,7 @@ cpufreq_stats_free_table (unsigned int cpu)
{
struct cpufreq_stats *stat = cpufreq_stats_table[cpu];
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
- if (policy && policy->cpu == cpu)
+ if (policy && policy->cpu == cpu)
sysfs_remove_group(&policy->kobj, &stats_attr_group);
if (stat) {
kfree(stat->time_in_state);
@@ -303,7 +303,7 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val,
return 0;
}
-static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
+static int cpufreq_stat_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index 92a0be22a2a..071ee4f1bbf 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -41,7 +41,7 @@ static DEFINE_MUTEX (userspace_mutex);
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
/* keep track of frequency transitions */
-static int
+static int
userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
@@ -58,7 +58,7 @@ static struct notifier_block userspace_cpufreq_notifier_block = {
};
-/**
+/**
* cpufreq_set - set the CPU frequency
* @freq: target frequency in kHz
* @cpu: CPU for which the frequency is to be set
@@ -103,8 +103,8 @@ static ssize_t show_speed (struct cpufreq_policy *policy, char *buf)
return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]);
}
-static ssize_t
-store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
+static ssize_t
+store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
{
unsigned int freq = 0;
unsigned int ret;
@@ -118,7 +118,7 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
return count;
}
-static struct freq_attr freq_attr_scaling_setspeed =
+static struct freq_attr freq_attr_scaling_setspeed =
{
.attr = { .name = "scaling_setspeed", .mode = 0644, .owner = THIS_MODULE },
.show = show_speed,
@@ -135,7 +135,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
return -EINVAL;
BUG_ON(!policy->cur);
mutex_lock(&userspace_mutex);
- cpu_is_managed[cpu] = 1;
+ cpu_is_managed[cpu] = 1;
cpu_min_freq[cpu] = policy->min;
cpu_max_freq[cpu] = policy->max;
cpu_cur_freq[cpu] = policy->cur;
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index ba460bdea60..a4818ce8891 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -59,9 +59,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
if (!cpu_online(policy->cpu))
return -EINVAL;
- cpufreq_verify_within_limits(policy,
- policy->cpuinfo.min_freq,
- policy->cpuinfo.max_freq);
+ cpufreq_verify_within_limits(policy,
+ policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
unsigned int freq = table[i].frequency;
@@ -76,9 +75,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
if (!count)
policy->max = next_larger;
- cpufreq_verify_within_limits(policy,
- policy->cpuinfo.min_freq,
- policy->cpuinfo.max_freq);
+ cpufreq_verify_within_limits(policy,
+ policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
dprintk("verification lead to (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu);
@@ -199,7 +197,7 @@ EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
* if you use these, you must assure that the frequency table is valid
* all the time between get_attr and put_attr!
*/
-void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
+void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu)
{
dprintk("setting show_table for cpu %u to %p\n", cpu, table);
diff --git a/drivers/dio/dio-driver.c b/drivers/dio/dio-driver.c
index ca8e69d2f64..e4c48e32936 100644
--- a/drivers/dio/dio-driver.c
+++ b/drivers/dio/dio-driver.c
@@ -71,22 +71,17 @@ static int dio_device_probe(struct device *dev)
* @drv: the driver structure to register
*
* Adds the driver structure to the list of registered drivers
- * Returns the number of DIO devices which were claimed by the driver
- * during registration. The driver remains registered even if the
- * return value is zero.
+ * Returns zero or a negative error value.
*/
int dio_register_driver(struct dio_driver *drv)
{
- int count = 0;
-
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &dio_bus_type;
/* register with core */
- count = driver_register(&drv->driver);
- return count ? count : 1;
+ return driver_register(&drv->driver);
}
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 52f3eb45d2b..b582d0cdc24 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -64,35 +64,35 @@ config EDAC_AMD76X
config EDAC_E7XXX
tristate "Intel e7xxx (e7205, e7500, e7501, e7505)"
- depends on EDAC_MM_EDAC && PCI
+ depends on EDAC_MM_EDAC && PCI && X86_32
help
Support for error detection and correction on the Intel
E7205, E7500, E7501 and E7505 server chipsets.
config EDAC_E752X
tristate "Intel e752x (e7520, e7525, e7320)"
- depends on EDAC_MM_EDAC && PCI
+ depends on EDAC_MM_EDAC && PCI && X86
help
Support for error detection and correction on the Intel
E7520, E7525, E7320 server chipsets.
config EDAC_I82875P
tristate "Intel 82875p (D82875P, E7210)"
- depends on EDAC_MM_EDAC && PCI
+ depends on EDAC_MM_EDAC && PCI && X86_32
help
Support for error detection and correction on the Intel
DP82785P and E7210 server chipsets.
config EDAC_I82860
tristate "Intel 82860"
- depends on EDAC_MM_EDAC && PCI
+ depends on EDAC_MM_EDAC && PCI && X86_32
help
Support for error detection and correction on the Intel
82860 chipset.
config EDAC_R82600
tristate "Radisys 82600 embedded chipset"
- depends on EDAC_MM_EDAC
+ depends on EDAC_MM_EDAC && PCI && X86_32
help
Support for error detection and correction on the Radisys
82600 embedded chipset.
diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c
index 2fcc8120b53..53423ad6d4a 100644
--- a/drivers/edac/amd76x_edac.c
+++ b/drivers/edac/amd76x_edac.c
@@ -12,25 +12,26 @@
*
*/
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
-
#include <linux/pci.h>
#include <linux/pci_ids.h>
-
#include <linux/slab.h>
-
#include "edac_mc.h"
+#define amd76x_printk(level, fmt, arg...) \
+ edac_printk(level, "amd76x", fmt, ##arg)
+
+#define amd76x_mc_printk(mci, level, fmt, arg...) \
+ edac_mc_chipset_printk(mci, level, "amd76x", fmt, ##arg)
#define AMD76X_NR_CSROWS 8
#define AMD76X_NR_CHANS 1
#define AMD76X_NR_DIMMS 4
-
/* AMD 76x register addresses - device 0 function 0 - PCI bridge */
+
#define AMD76X_ECC_MODE_STATUS 0x48 /* Mode and status of ECC (32b)
*
* 31:16 reserved
@@ -42,6 +43,7 @@
* 7:4 UE cs row
* 3:0 CE cs row
*/
+
#define AMD76X_DRAM_MODE_STATUS 0x58 /* DRAM Mode and status (32b)
*
* 31:26 clock disable 5 - 0
@@ -56,6 +58,7 @@
* 15:8 reserved
* 7:0 x4 mode enable 7 - 0
*/
+
#define AMD76X_MEM_BASE_ADDR 0xC0 /* Memory base address (8 x 32b)
*
* 31:23 chip-select base
@@ -66,29 +69,28 @@
* 0 chip-select enable
*/
-
struct amd76x_error_info {
u32 ecc_mode_status;
};
-
enum amd76x_chips {
AMD761 = 0,
AMD762
};
-
struct amd76x_dev_info {
const char *ctl_name;
};
-
static const struct amd76x_dev_info amd76x_devs[] = {
- [AMD761] = {.ctl_name = "AMD761"},
- [AMD762] = {.ctl_name = "AMD762"},
+ [AMD761] = {
+ .ctl_name = "AMD761"
+ },
+ [AMD762] = {
+ .ctl_name = "AMD762"
+ },
};
-
/**
* amd76x_get_error_info - fetch error information
* @mci: Memory controller
@@ -97,23 +99,21 @@ static const struct amd76x_dev_info amd76x_devs[] = {
* Fetch and store the AMD76x ECC status. Clear pending status
* on the chip so that further errors will be reported
*/
-
-static void amd76x_get_error_info (struct mem_ctl_info *mci,
- struct amd76x_error_info *info)
+static void amd76x_get_error_info(struct mem_ctl_info *mci,
+ struct amd76x_error_info *info)
{
pci_read_config_dword(mci->pdev, AMD76X_ECC_MODE_STATUS,
&info->ecc_mode_status);
if (info->ecc_mode_status & BIT(8))
pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
- (u32) BIT(8), (u32) BIT(8));
+ (u32) BIT(8), (u32) BIT(8));
if (info->ecc_mode_status & BIT(9))
pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
- (u32) BIT(9), (u32) BIT(9));
+ (u32) BIT(9), (u32) BIT(9));
}
-
/**
* amd76x_process_error_info - Error check
* @mci: Memory controller
@@ -124,8 +124,7 @@ static void amd76x_get_error_info (struct mem_ctl_info *mci,
* A return of 1 indicates an error. Also if handle_errors is true
* then attempt to handle and clean up after the error
*/
-
-static int amd76x_process_error_info (struct mem_ctl_info *mci,
+static int amd76x_process_error_info(struct mem_ctl_info *mci,
struct amd76x_error_info *info, int handle_errors)
{
int error_found;
@@ -141,9 +140,8 @@ static int amd76x_process_error_info (struct mem_ctl_info *mci,
if (handle_errors) {
row = (info->ecc_mode_status >> 4) & 0xf;
- edac_mc_handle_ue(mci,
- mci->csrows[row].first_page, 0, row,
- mci->ctl_name);
+ edac_mc_handle_ue(mci, mci->csrows[row].first_page, 0,
+ row, mci->ctl_name);
}
}
@@ -155,11 +153,11 @@ static int amd76x_process_error_info (struct mem_ctl_info *mci,
if (handle_errors) {
row = info->ecc_mode_status & 0xf;
- edac_mc_handle_ce(mci,
- mci->csrows[row].first_page, 0, 0, row, 0,
- mci->ctl_name);
+ edac_mc_handle_ce(mci, mci->csrows[row].first_page, 0,
+ 0, row, 0, mci->ctl_name);
}
}
+
return error_found;
}
@@ -170,16 +168,14 @@ static int amd76x_process_error_info (struct mem_ctl_info *mci,
* Called by the poll handlers this function reads the status
* from the controller and checks for errors.
*/
-
static void amd76x_check(struct mem_ctl_info *mci)
{
struct amd76x_error_info info;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
amd76x_get_error_info(mci, &info);
amd76x_process_error_info(mci, &info, 1);
}
-
/**
* amd76x_probe1 - Perform set up for detected device
* @pdev; PCI device detected
@@ -189,7 +185,6 @@ static void amd76x_check(struct mem_ctl_info *mci)
* controller status reporting. We configure and set up the
* memory controller reporting and claim the device.
*/
-
static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
{
int rc = -ENODEV;
@@ -203,12 +198,11 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
};
u32 ems;
u32 ems_mode;
+ struct amd76x_error_info discard;
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
-
+ debugf0("%s()\n", __func__);
pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems);
ems_mode = (ems >> 10) & 0x3;
-
mci = edac_mc_alloc(0, AMD76X_NR_CSROWS, AMD76X_NR_CHANS);
if (mci == NULL) {
@@ -216,16 +210,13 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
goto fail;
}
- debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
-
- mci->pdev = pci_dev_get(pdev);
+ debugf0("%s(): mci = %p\n", __func__, mci);
+ mci->pdev = pdev;
mci->mtype_cap = MEM_FLAG_RDDR;
-
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
mci->edac_cap = ems_mode ?
- (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE;
-
- mci->mod_name = BS_MOD_STR;
+ (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE;
+ mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = "$Revision: 1.4.2.5 $";
mci->ctl_name = amd76x_devs[dev_idx].ctl_name;
mci->edac_check = amd76x_check;
@@ -240,18 +231,15 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
/* find the DRAM Chip Select Base address and mask */
pci_read_config_dword(mci->pdev,
- AMD76X_MEM_BASE_ADDR + (index * 4),
- &mba);
+ AMD76X_MEM_BASE_ADDR + (index * 4), &mba);
if (!(mba & BIT(0)))
continue;
mba_base = mba & 0xff800000UL;
mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL;
-
pci_read_config_dword(mci->pdev, AMD76X_DRAM_MODE_STATUS,
- &dms);
-
+ &dms);
csrow->first_page = mba_base >> PAGE_SHIFT;
csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
@@ -262,40 +250,33 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
csrow->edac_mode = ems_modes[ems_mode];
}
- /* clear counters */
- pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, (u32) (0x3 << 8),
- (u32) (0x3 << 8));
+ amd76x_get_error_info(mci, &discard); /* clear counters */
if (edac_mc_add_mc(mci)) {
- debugf3("MC: " __FILE__
- ": %s(): failed edac_mc_add_mc()\n", __func__);
+ debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
goto fail;
}
/* get this far and it's successful */
- debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ debugf3("%s(): success\n", __func__);
return 0;
fail:
- if (mci) {
- if(mci->pdev)
- pci_dev_put(mci->pdev);
+ if (mci != NULL)
edac_mc_free(mci);
- }
return rc;
}
/* returns count (>= 0), or negative on error */
static int __devinit amd76x_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *ent)
{
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
+ debugf0("%s()\n", __func__);
/* don't need to call pci_device_enable() */
return amd76x_probe1(pdev, ent->driver_data);
}
-
/**
* amd76x_remove_one - driver shutdown
* @pdev: PCI device being handed back
@@ -304,35 +285,36 @@ static int __devinit amd76x_init_one(struct pci_dev *pdev,
* structure for the device then delete the mci and free the
* resources.
*/
-
static void __devexit amd76x_remove_one(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
- debugf0(__FILE__ ": %s()\n", __func__);
+ debugf0("%s()\n", __func__);
- if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+ if ((mci = edac_mc_del_mc(pdev)) == NULL)
return;
- if (edac_mc_del_mc(mci))
- return;
- pci_dev_put(mci->pdev);
+
edac_mc_free(mci);
}
-
static const struct pci_device_id amd76x_pci_tbl[] __devinitdata = {
- {PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- AMD762},
- {PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- AMD761},
- {0,} /* 0 terminated list. */
+ {
+ PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ AMD762
+ },
+ {
+ PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ AMD761
+ },
+ {
+ 0,
+ } /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl);
-
static struct pci_driver amd76x_driver = {
- .name = BS_MOD_STR,
+ .name = EDAC_MOD_STR,
.probe = amd76x_init_one,
.remove = __devexit_p(amd76x_remove_one),
.id_table = amd76x_pci_tbl,
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index c454ded2b06..66572c5323a 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -17,18 +17,19 @@
*
*/
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
-
#include <linux/pci.h>
#include <linux/pci_ids.h>
-
#include <linux/slab.h>
-
#include "edac_mc.h"
+#define e752x_printk(level, fmt, arg...) \
+ edac_printk(level, "e752x", fmt, ##arg)
+
+#define e752x_mc_printk(mci, level, fmt, arg...) \
+ edac_mc_chipset_printk(mci, level, "e752x", fmt, ##arg)
#ifndef PCI_DEVICE_ID_INTEL_7520_0
#define PCI_DEVICE_ID_INTEL_7520_0 0x3590
@@ -56,7 +57,6 @@
#define E752X_NR_CSROWS 8 /* number of csrows */
-
/* E752X register addresses - device 0 function 0 */
#define E752X_DRB 0x60 /* DRAM row boundary register (8b) */
#define E752X_DRA 0x70 /* DRAM row attribute register (8b) */
@@ -156,7 +156,6 @@ enum e752x_chips {
E7320 = 2
};
-
struct e752x_pvt {
struct pci_dev *bridge_ck;
struct pci_dev *dev_d0f0;
@@ -170,9 +169,9 @@ struct e752x_pvt {
const struct e752x_dev_info *dev_info;
};
-
struct e752x_dev_info {
u16 err_dev;
+ u16 ctl_dev;
const char *ctl_name;
};
@@ -198,38 +197,47 @@ struct e752x_error_info {
static const struct e752x_dev_info e752x_devs[] = {
[E7520] = {
- .err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR,
- .ctl_name = "E7520"},
+ .err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR,
+ .ctl_dev = PCI_DEVICE_ID_INTEL_7520_0,
+ .ctl_name = "E7520"
+ },
[E7525] = {
- .err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR,
- .ctl_name = "E7525"},
+ .err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR,
+ .ctl_dev = PCI_DEVICE_ID_INTEL_7525_0,
+ .ctl_name = "E7525"
+ },
[E7320] = {
- .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR,
- .ctl_name = "E7320"},
+ .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR,
+ .ctl_dev = PCI_DEVICE_ID_INTEL_7320_0,
+ .ctl_name = "E7320"
+ },
};
-
static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
- unsigned long page)
+ unsigned long page)
{
u32 remap;
struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
if (page < pvt->tolm)
return page;
+
if ((page >= 0x100000) && (page < pvt->remapbase))
return page;
+
remap = (page - pvt->tolm) + pvt->remapbase;
+
if (remap < pvt->remaplimit)
return remap;
- printk(KERN_ERR "Invalid page %lx - out of range\n", page);
+
+ e752x_printk(KERN_ERR, "Invalid page %lx - out of range\n", page);
return pvt->tolm - 1;
}
static void do_process_ce(struct mem_ctl_info *mci, u16 error_one,
- u32 sec1_add, u16 sec1_syndrome)
+ u32 sec1_add, u16 sec1_syndrome)
{
u32 page;
int row;
@@ -237,7 +245,7 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one,
int i;
struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
/* convert the addr to 4k page */
page = sec1_add >> (PAGE_SHIFT - 4);
@@ -246,36 +254,37 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one,
if (pvt->mc_symmetric) {
/* chip select are bits 14 & 13 */
row = ((page >> 1) & 3);
- printk(KERN_WARNING
- "Test row %d Table %d %d %d %d %d %d %d %d\n",
- row, pvt->map[0], pvt->map[1], pvt->map[2],
- pvt->map[3], pvt->map[4], pvt->map[5],
- pvt->map[6], pvt->map[7]);
+ e752x_printk(KERN_WARNING,
+ "Test row %d Table %d %d %d %d %d %d %d %d\n", row,
+ pvt->map[0], pvt->map[1], pvt->map[2], pvt->map[3],
+ pvt->map[4], pvt->map[5], pvt->map[6], pvt->map[7]);
/* test for channel remapping */
for (i = 0; i < 8; i++) {
if (pvt->map[i] == row)
break;
}
- printk(KERN_WARNING "Test computed row %d\n", i);
+
+ e752x_printk(KERN_WARNING, "Test computed row %d\n", i);
+
if (i < 8)
row = i;
else
- printk(KERN_WARNING
- "MC%d: row %d not found in remap table\n",
- mci->mc_idx, row);
+ e752x_mc_printk(mci, KERN_WARNING,
+ "row %d not found in remap table\n", row);
} else
row = edac_mc_find_csrow_by_page(mci, page);
+
/* 0 = channel A, 1 = channel B */
channel = !(error_one & 1);
if (!pvt->map_type)
row = 7 - row;
+
edac_mc_handle_ce(mci, page, 0, sec1_syndrome, row, channel,
- "e752x CE");
+ "e752x CE");
}
-
static inline void process_ce(struct mem_ctl_info *mci, u16 error_one,
u32 sec1_add, u16 sec1_syndrome, int *error_found,
int handle_error)
@@ -286,36 +295,42 @@ static inline void process_ce(struct mem_ctl_info *mci, u16 error_one,
do_process_ce(mci, error_one, sec1_add, sec1_syndrome);
}
-static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, u32 ded_add,
- u32 scrb_add)
+static void do_process_ue(struct mem_ctl_info *mci, u16 error_one,
+ u32 ded_add, u32 scrb_add)
{
u32 error_2b, block_page;
int row;
struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
if (error_one & 0x0202) {
error_2b = ded_add;
+
/* convert to 4k address */
block_page = error_2b >> (PAGE_SHIFT - 4);
+
row = pvt->mc_symmetric ?
- /* chip select are bits 14 & 13 */
- ((block_page >> 1) & 3) :
- edac_mc_find_csrow_by_page(mci, block_page);
+ /* chip select are bits 14 & 13 */
+ ((block_page >> 1) & 3) :
+ edac_mc_find_csrow_by_page(mci, block_page);
+
edac_mc_handle_ue(mci, block_page, 0, row,
- "e752x UE from Read");
+ "e752x UE from Read");
}
if (error_one & 0x0404) {
error_2b = scrb_add;
+
/* convert to 4k address */
block_page = error_2b >> (PAGE_SHIFT - 4);
+
row = pvt->mc_symmetric ?
- /* chip select are bits 14 & 13 */
- ((block_page >> 1) & 3) :
- edac_mc_find_csrow_by_page(mci, block_page);
+ /* chip select are bits 14 & 13 */
+ ((block_page >> 1) & 3) :
+ edac_mc_find_csrow_by_page(mci, block_page);
+
edac_mc_handle_ue(mci, block_page, 0, row,
- "e752x UE from Scruber");
+ "e752x UE from Scruber");
}
}
@@ -336,7 +351,7 @@ static inline void process_ue_no_info_wr(struct mem_ctl_info *mci,
if (!handle_error)
return;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
edac_mc_handle_ue_no_info(mci, "e752x UE log memory write");
}
@@ -348,13 +363,13 @@ static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error,
struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
error_1b = retry_add;
- page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */
+ page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */
row = pvt->mc_symmetric ?
- ((page >> 1) & 3) : /* chip select are bits 14 & 13 */
- edac_mc_find_csrow_by_page(mci, page);
- printk(KERN_WARNING
- "MC%d: CE page 0x%lx, row %d : Memory read retry\n",
- mci->mc_idx, (long unsigned int) page, row);
+ ((page >> 1) & 3) : /* chip select are bits 14 & 13 */
+ edac_mc_find_csrow_by_page(mci, page);
+ e752x_mc_printk(mci, KERN_WARNING,
+ "CE page 0x%lx, row %d : Memory read retry\n",
+ (long unsigned int) page, row);
}
static inline void process_ded_retry(struct mem_ctl_info *mci, u16 error,
@@ -372,8 +387,7 @@ static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error,
*error_found = 1;
if (handle_error)
- printk(KERN_WARNING "MC%d: Memory threshold CE\n",
- mci->mc_idx);
+ e752x_mc_printk(mci, KERN_WARNING, "Memory threshold CE\n");
}
static char *global_message[11] = {
@@ -391,8 +405,8 @@ static void do_global_error(int fatal, u32 errors)
for (i = 0; i < 11; i++) {
if (errors & (1 << i))
- printk(KERN_WARNING "%sError %s\n",
- fatal_message[fatal], global_message[i]);
+ e752x_printk(KERN_WARNING, "%sError %s\n",
+ fatal_message[fatal], global_message[i]);
}
}
@@ -418,8 +432,8 @@ static void do_hub_error(int fatal, u8 errors)
for (i = 0; i < 7; i++) {
if (errors & (1 << i))
- printk(KERN_WARNING "%sError %s\n",
- fatal_message[fatal], hub_message[i]);
+ e752x_printk(KERN_WARNING, "%sError %s\n",
+ fatal_message[fatal], hub_message[i]);
}
}
@@ -445,8 +459,8 @@ static void do_membuf_error(u8 errors)
for (i = 0; i < 4; i++) {
if (errors & (1 << i))
- printk(KERN_WARNING "Non-Fatal Error %s\n",
- membuf_message[i]);
+ e752x_printk(KERN_WARNING, "Non-Fatal Error %s\n",
+ membuf_message[i]);
}
}
@@ -458,8 +472,7 @@ static inline void membuf_error(u8 errors, int *error_found, int handle_error)
do_membuf_error(errors);
}
-#if 0
-char *sysbus_message[10] = {
+static char *sysbus_message[10] = {
"Addr or Request Parity",
"Data Strobe Glitch",
"Addr Strobe Glitch",
@@ -470,7 +483,6 @@ char *sysbus_message[10] = {
"Memory Parity",
"IO Subsystem Parity"
};
-#endif /* 0 */
static void do_sysbus_error(int fatal, u32 errors)
{
@@ -478,8 +490,8 @@ static void do_sysbus_error(int fatal, u32 errors)
for (i = 0; i < 10; i++) {
if (errors & (1 << i))
- printk(KERN_WARNING "%sError System Bus %s\n",
- fatal_message[fatal], global_message[i]);
+ e752x_printk(KERN_WARNING, "%sError System Bus %s\n",
+ fatal_message[fatal], sysbus_message[i]);
}
}
@@ -492,33 +504,42 @@ static inline void sysbus_error(int fatal, u32 errors, int *error_found,
do_sysbus_error(fatal, errors);
}
-static void e752x_check_hub_interface (struct e752x_error_info *info,
+static void e752x_check_hub_interface(struct e752x_error_info *info,
int *error_found, int handle_error)
{
u8 stat8;
//pci_read_config_byte(dev,E752X_HI_FERR,&stat8);
+
stat8 = info->hi_ferr;
+
if(stat8 & 0x7f) { /* Error, so process */
stat8 &= 0x7f;
+
if(stat8 & 0x2b)
hub_error(1, stat8 & 0x2b, error_found, handle_error);
+
if(stat8 & 0x54)
hub_error(0, stat8 & 0x54, error_found, handle_error);
}
+
//pci_read_config_byte(dev,E752X_HI_NERR,&stat8);
+
stat8 = info->hi_nerr;
+
if(stat8 & 0x7f) { /* Error, so process */
stat8 &= 0x7f;
+
if (stat8 & 0x2b)
hub_error(1, stat8 & 0x2b, error_found, handle_error);
+
if(stat8 & 0x54)
hub_error(0, stat8 & 0x54, error_found, handle_error);
}
}
-static void e752x_check_sysbus (struct e752x_error_info *info, int *error_found,
- int handle_error)
+static void e752x_check_sysbus(struct e752x_error_info *info,
+ int *error_found, int handle_error)
{
u32 stat32, error32;
@@ -530,27 +551,34 @@ static void e752x_check_sysbus (struct e752x_error_info *info, int *error_found,
error32 = (stat32 >> 16) & 0x3ff;
stat32 = stat32 & 0x3ff;
+
if(stat32 & 0x083)
sysbus_error(1, stat32 & 0x083, error_found, handle_error);
+
if(stat32 & 0x37c)
sysbus_error(0, stat32 & 0x37c, error_found, handle_error);
+
if(error32 & 0x083)
sysbus_error(1, error32 & 0x083, error_found, handle_error);
+
if(error32 & 0x37c)
sysbus_error(0, error32 & 0x37c, error_found, handle_error);
}
-static void e752x_check_membuf (struct e752x_error_info *info, int *error_found,
- int handle_error)
+static void e752x_check_membuf (struct e752x_error_info *info,
+ int *error_found, int handle_error)
{
u8 stat8;
stat8 = info->buf_ferr;
+
if (stat8 & 0x0f) { /* Error, so process */
stat8 &= 0x0f;
membuf_error(stat8, error_found, handle_error);
}
+
stat8 = info->buf_nerr;
+
if (stat8 & 0x0f) { /* Error, so process */
stat8 &= 0x0f;
membuf_error(stat8, error_found, handle_error);
@@ -558,7 +586,8 @@ static void e752x_check_membuf (struct e752x_error_info *info, int *error_found,
}
static void e752x_check_dram (struct mem_ctl_info *mci,
- struct e752x_error_info *info, int *error_found, int handle_error)
+ struct e752x_error_info *info, int *error_found,
+ int handle_error)
{
u16 error_one, error_next;
@@ -608,7 +637,7 @@ static void e752x_check_dram (struct mem_ctl_info *mci,
}
static void e752x_get_error_info (struct mem_ctl_info *mci,
- struct e752x_error_info *info)
+ struct e752x_error_info *info)
{
struct pci_dev *dev;
struct e752x_pvt *pvt;
@@ -616,7 +645,6 @@ static void e752x_get_error_info (struct mem_ctl_info *mci,
memset(info, 0, sizeof(*info));
pvt = (struct e752x_pvt *) mci->pvt_info;
dev = pvt->dev_d0f1;
-
pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global);
if (info->ferr_global) {
@@ -727,7 +755,8 @@ static int e752x_process_error_info (struct mem_ctl_info *mci,
static void e752x_check(struct mem_ctl_info *mci)
{
struct e752x_error_info info;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ debugf3("%s()\n", __func__);
e752x_get_error_info(mci, &info);
e752x_process_error_info(mci, &info, 1);
}
@@ -736,23 +765,21 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
{
int rc = -ENODEV;
int index;
- u16 pci_data, stat;
- u32 stat32;
- u16 stat16;
+ u16 pci_data;
u8 stat8;
struct mem_ctl_info *mci = NULL;
struct e752x_pvt *pvt = NULL;
u16 ddrcsr;
u32 drc;
- int drc_chan; /* Number of channels 0=1chan,1=2chan */
- int drc_drbg; /* DRB granularity 0=64mb,1=128mb */
- int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+ int drc_chan; /* Number of channels 0=1chan,1=2chan */
+ int drc_drbg; /* DRB granularity 0=64mb, 1=128mb */
+ int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
u32 dra;
unsigned long last_cumul_size;
- struct pci_dev *pres_dev;
struct pci_dev *dev = NULL;
+ struct e752x_error_info discard;
- debugf0("MC: " __FILE__ ": %s(): mci\n", __func__);
+ debugf0("%s(): mci\n", __func__);
debugf0("Starting Probe1\n");
/* enable device 0 function 1 */
@@ -776,34 +803,35 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
goto fail;
}
- debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
-
+ debugf3("%s(): init mci\n", __func__);
mci->mtype_cap = MEM_FLAG_RDDR;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED |
EDAC_FLAG_S4ECD4ED;
/* FIXME - what if different memory types are in different csrows? */
- mci->mod_name = BS_MOD_STR;
+ mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = "$Revision: 1.5.2.11 $";
mci->pdev = pdev;
- debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+ debugf3("%s(): init pvt\n", __func__);
pvt = (struct e752x_pvt *) mci->pvt_info;
pvt->dev_info = &e752x_devs[dev_idx];
pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
- pvt->dev_info->err_dev,
- pvt->bridge_ck);
+ pvt->dev_info->err_dev,
+ pvt->bridge_ck);
+
if (pvt->bridge_ck == NULL)
pvt->bridge_ck = pci_scan_single_device(pdev->bus,
- PCI_DEVFN(0, 1));
+ PCI_DEVFN(0, 1));
+
if (pvt->bridge_ck == NULL) {
- printk(KERN_ERR "MC: error reporting device not found:"
- "vendor %x device 0x%x (broken BIOS?)\n",
- PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev);
+ e752x_printk(KERN_ERR, "error reporting device not found:"
+ "vendor %x device 0x%x (broken BIOS?)\n",
+ PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev);
goto fail;
}
- pvt->mc_symmetric = ((ddrcsr & 0x10) != 0);
- debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__);
+ pvt->mc_symmetric = ((ddrcsr & 0x10) != 0);
+ debugf3("%s(): more mci init\n", __func__);
mci->ctl_name = pvt->dev_info->ctl_name;
mci->edac_check = e752x_check;
mci->ctl_page_to_phys = ctl_page_to_phys;
@@ -820,6 +848,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
u8 value;
u32 cumul_size;
+
/* mem_dev 0=x8, 1=x4 */
int mem_dev = (dra >> (index * 4 + 2)) & 0x3;
struct csrow_info *csrow = &mci->csrows[index];
@@ -828,17 +857,18 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
pci_read_config_byte(mci->pdev, E752X_DRB + index, &value);
/* convert a 128 or 64 MiB DRB to a page size. */
cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
- debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
- __func__, index, cumul_size);
+ debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
+ cumul_size);
+
if (cumul_size == last_cumul_size)
- continue; /* not populated */
+ continue; /* not populated */
csrow->first_page = last_cumul_size;
csrow->last_page = cumul_size - 1;
csrow->nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;
- csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
- csrow->mtype = MEM_RDDR; /* only one type supported */
+ csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
+ csrow->mtype = MEM_RDDR; /* only one type supported */
csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
/*
@@ -862,29 +892,32 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
u8 value;
u8 last = 0;
u8 row = 0;
- for (index = 0; index < 8; index += 2) {
+ for (index = 0; index < 8; index += 2) {
pci_read_config_byte(mci->pdev, E752X_DRB + index,
- &value);
+ &value);
+
/* test if there is a dimm in this slot */
if (value == last) {
/* no dimm in the slot, so flag it as empty */
pvt->map[index] = 0xff;
pvt->map[index + 1] = 0xff;
- } else { /* there is a dimm in the slot */
+ } else { /* there is a dimm in the slot */
pvt->map[index] = row;
row++;
last = value;
/* test the next value to see if the dimm is
double sided */
pci_read_config_byte(mci->pdev,
- E752X_DRB + index + 1,
- &value);
+ E752X_DRB + index + 1,
+ &value);
pvt->map[index + 1] = (value == last) ?
- 0xff : /* the dimm is single sided,
- so flag as empty */
- row; /* this is a double sided dimm
- to save the next row # */
+ 0xff : /* the dimm is single sided,
+ * so flag as empty
+ */
+ row; /* this is a double sided dimm
+ * to save the next row #
+ */
row++;
last = value;
}
@@ -896,9 +929,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f));
mci->edac_cap |= EDAC_FLAG_NONE;
+ debugf3("%s(): tolm, remapbase, remaplimit\n", __func__);
- debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n",
- __func__);
/* load the top of low memory, remap base, and remap limit vars */
pci_read_config_word(mci->pdev, E752X_TOLM, &pci_data);
pvt->tolm = ((u32) pci_data) << 4;
@@ -906,43 +938,18 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
pvt->remapbase = ((u32) pci_data) << 14;
pci_read_config_word(mci->pdev, E752X_REMAPLIMIT, &pci_data);
pvt->remaplimit = ((u32) pci_data) << 14;
- printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
- pvt->remapbase, pvt->remaplimit);
+ e752x_printk(KERN_INFO,
+ "tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
+ pvt->remapbase, pvt->remaplimit);
if (edac_mc_add_mc(mci)) {
- debugf3("MC: " __FILE__
- ": %s(): failed edac_mc_add_mc()\n",
- __func__);
+ debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
goto fail;
}
- /* Walk through the PCI table and clear errors */
- switch (dev_idx) {
- case E7520:
- dev = pci_get_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_7520_0, NULL);
- break;
- case E7525:
- dev = pci_get_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_7525_0, NULL);
- break;
- case E7320:
- dev = pci_get_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_7320_0, NULL);
- break;
- }
-
-
+ dev = pci_get_device(PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].ctl_dev,
+ NULL);
pvt->dev_d0f0 = dev;
- for (pres_dev = dev;
- ((struct pci_dev *) pres_dev->global_list.next != dev);
- pres_dev = (struct pci_dev *) pres_dev->global_list.next) {
- pci_read_config_dword(pres_dev, PCI_COMMAND, &stat32);
- stat = (u16) (stat32 >> 16);
- /* clear any error bits */
- if (stat32 & ((1 << 6) + (1 << 8)))
- pci_write_config_word(pres_dev, PCI_STATUS, stat);
- }
/* find the error reporting device and clear errors */
dev = pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck);
/* Turn off error disable & SMI in case the BIOS turned it on */
@@ -954,67 +961,51 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00);
pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00);
pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00);
- /* clear other MCH errors */
- pci_read_config_dword(dev, E752X_FERR_GLOBAL, &stat32);
- pci_write_config_dword(dev, E752X_FERR_GLOBAL, stat32);
- pci_read_config_dword(dev, E752X_NERR_GLOBAL, &stat32);
- pci_write_config_dword(dev, E752X_NERR_GLOBAL, stat32);
- pci_read_config_byte(dev, E752X_HI_FERR, &stat8);
- pci_write_config_byte(dev, E752X_HI_FERR, stat8);
- pci_read_config_byte(dev, E752X_HI_NERR, &stat8);
- pci_write_config_byte(dev, E752X_HI_NERR, stat8);
- pci_read_config_dword(dev, E752X_SYSBUS_FERR, &stat32);
- pci_write_config_dword(dev, E752X_SYSBUS_FERR, stat32);
- pci_read_config_byte(dev, E752X_BUF_FERR, &stat8);
- pci_write_config_byte(dev, E752X_BUF_FERR, stat8);
- pci_read_config_byte(dev, E752X_BUF_NERR, &stat8);
- pci_write_config_byte(dev, E752X_BUF_NERR, stat8);
- pci_read_config_word(dev, E752X_DRAM_FERR, &stat16);
- pci_write_config_word(dev, E752X_DRAM_FERR, stat16);
- pci_read_config_word(dev, E752X_DRAM_NERR, &stat16);
- pci_write_config_word(dev, E752X_DRAM_NERR, stat16);
+
+ e752x_get_error_info(mci, &discard); /* clear other MCH errors */
/* get this far and it's successful */
- debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ debugf3("%s(): success\n", __func__);
return 0;
fail:
if (mci) {
if (pvt->dev_d0f0)
pci_dev_put(pvt->dev_d0f0);
+
if (pvt->dev_d0f1)
pci_dev_put(pvt->dev_d0f1);
+
if (pvt->bridge_ck)
pci_dev_put(pvt->bridge_ck);
+
edac_mc_free(mci);
}
+
return rc;
}
/* returns count (>= 0), or negative on error */
static int __devinit e752x_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *ent)
{
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
+ debugf0("%s()\n", __func__);
/* wake up and enable device */
if(pci_enable_device(pdev) < 0)
return -EIO;
+
return e752x_probe1(pdev, ent->driver_data);
}
-
static void __devexit e752x_remove_one(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
struct e752x_pvt *pvt;
- debugf0(__FILE__ ": %s()\n", __func__);
-
- if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
- return;
+ debugf0("%s()\n", __func__);
- if (edac_mc_del_mc(mci))
+ if ((mci = edac_mc_del_mc(pdev)) == NULL)
return;
pvt = (struct e752x_pvt *) mci->pvt_info;
@@ -1024,45 +1015,48 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev)
edac_mc_free(mci);
}
-
static const struct pci_device_id e752x_pci_tbl[] __devinitdata = {
- {PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- E7520},
- {PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- E7525},
- {PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- E7320},
- {0,} /* 0 terminated list. */
+ {
+ PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7520
+ },
+ {
+ PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7525
+ },
+ {
+ PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7320
+ },
+ {
+ 0,
+ } /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, e752x_pci_tbl);
-
static struct pci_driver e752x_driver = {
- .name = BS_MOD_STR,
+ .name = EDAC_MOD_STR,
.probe = e752x_init_one,
.remove = __devexit_p(e752x_remove_one),
.id_table = e752x_pci_tbl,
};
-
static int __init e752x_init(void)
{
int pci_rc;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
pci_rc = pci_register_driver(&e752x_driver);
return (pci_rc < 0) ? pci_rc : 0;
}
-
static void __exit e752x_exit(void)
{
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
pci_unregister_driver(&e752x_driver);
}
-
module_init(e752x_init);
module_exit(e752x_exit);
diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c
index d5e320dfc66..a9518d3e4be 100644
--- a/drivers/edac/e7xxx_edac.c
+++ b/drivers/edac/e7xxx_edac.c
@@ -11,9 +11,9 @@
* http://www.anime.net/~goemon/linux-ecc/
*
* Contributors:
- * Eric Biederman (Linux Networx)
- * Tom Zimmerman (Linux Networx)
- * Jim Garlick (Lawrence Livermore National Labs)
+ * Eric Biederman (Linux Networx)
+ * Tom Zimmerman (Linux Networx)
+ * Jim Garlick (Lawrence Livermore National Labs)
* Dave Peterson (Lawrence Livermore National Labs)
* That One Guy (Some other place)
* Wang Zhenyu (intel.com)
@@ -22,7 +22,6 @@
*
*/
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -31,6 +30,11 @@
#include <linux/slab.h>
#include "edac_mc.h"
+#define e7xxx_printk(level, fmt, arg...) \
+ edac_printk(level, "e7xxx", fmt, ##arg)
+
+#define e7xxx_mc_printk(mci, level, fmt, arg...) \
+ edac_mc_chipset_printk(mci, level, "e7xxx", fmt, ##arg)
#ifndef PCI_DEVICE_ID_INTEL_7205_0
#define PCI_DEVICE_ID_INTEL_7205_0 0x255d
@@ -64,11 +68,9 @@
#define PCI_DEVICE_ID_INTEL_7505_1_ERR 0x2551
#endif /* PCI_DEVICE_ID_INTEL_7505_1_ERR */
-
#define E7XXX_NR_CSROWS 8 /* number of csrows */
#define E7XXX_NR_DIMMS 8 /* FIXME - is this correct? */
-
/* E7XXX register addresses - device 0 function 0 */
#define E7XXX_DRB 0x60 /* DRAM row boundary register (8b) */
#define E7XXX_DRA 0x70 /* DRAM row attribute register (8b) */
@@ -118,7 +120,6 @@ enum e7xxx_chips {
E7205,
};
-
struct e7xxx_pvt {
struct pci_dev *bridge_ck;
u32 tolm;
@@ -127,13 +128,11 @@ struct e7xxx_pvt {
const struct e7xxx_dev_info *dev_info;
};
-
struct e7xxx_dev_info {
u16 err_dev;
const char *ctl_name;
};
-
struct e7xxx_error_info {
u8 dram_ferr;
u8 dram_nerr;
@@ -144,108 +143,110 @@ struct e7xxx_error_info {
static const struct e7xxx_dev_info e7xxx_devs[] = {
[E7500] = {
- .err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR,
- .ctl_name = "E7500"},
+ .err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR,
+ .ctl_name = "E7500"
+ },
[E7501] = {
- .err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR,
- .ctl_name = "E7501"},
+ .err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR,
+ .ctl_name = "E7501"
+ },
[E7505] = {
- .err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR,
- .ctl_name = "E7505"},
+ .err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR,
+ .ctl_name = "E7505"
+ },
[E7205] = {
- .err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR,
- .ctl_name = "E7205"},
+ .err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR,
+ .ctl_name = "E7205"
+ },
};
-
/* FIXME - is this valid for both SECDED and S4ECD4ED? */
static inline int e7xxx_find_channel(u16 syndrome)
{
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
if ((syndrome & 0xff00) == 0)
return 0;
+
if ((syndrome & 0x00ff) == 0)
return 1;
+
if ((syndrome & 0xf000) == 0 || (syndrome & 0x0f00) == 0)
return 0;
+
return 1;
}
-
-static unsigned long
-ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page)
+static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
+ unsigned long page)
{
u32 remap;
struct e7xxx_pvt *pvt = (struct e7xxx_pvt *) mci->pvt_info;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
if ((page < pvt->tolm) ||
- ((page >= 0x100000) && (page < pvt->remapbase)))
+ ((page >= 0x100000) && (page < pvt->remapbase)))
return page;
+
remap = (page - pvt->tolm) + pvt->remapbase;
+
if (remap < pvt->remaplimit)
return remap;
- printk(KERN_ERR "Invalid page %lx - out of range\n", page);
+
+ e7xxx_printk(KERN_ERR, "Invalid page %lx - out of range\n", page);
return pvt->tolm - 1;
}
-
-static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
+static void process_ce(struct mem_ctl_info *mci,
+ struct e7xxx_error_info *info)
{
u32 error_1b, page;
u16 syndrome;
int row;
int channel;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
-
+ debugf3("%s()\n", __func__);
/* read the error address */
error_1b = info->dram_celog_add;
/* FIXME - should use PAGE_SHIFT */
- page = error_1b >> 6; /* convert the address to 4k page */
+ page = error_1b >> 6; /* convert the address to 4k page */
/* read the syndrome */
syndrome = info->dram_celog_syndrome;
/* FIXME - check for -1 */
row = edac_mc_find_csrow_by_page(mci, page);
/* convert syndrome to channel */
channel = e7xxx_find_channel(syndrome);
- edac_mc_handle_ce(mci, page, 0, syndrome, row, channel,
- "e7xxx CE");
+ edac_mc_handle_ce(mci, page, 0, syndrome, row, channel, "e7xxx CE");
}
-
static void process_ce_no_info(struct mem_ctl_info *mci)
{
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
edac_mc_handle_ce_no_info(mci, "e7xxx CE log register overflow");
}
-
-static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
+static void process_ue(struct mem_ctl_info *mci,
+ struct e7xxx_error_info *info)
{
u32 error_2b, block_page;
int row;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
-
+ debugf3("%s()\n", __func__);
/* read the error address */
error_2b = info->dram_uelog_add;
/* FIXME - should use PAGE_SHIFT */
- block_page = error_2b >> 6; /* convert to 4k address */
+ block_page = error_2b >> 6; /* convert to 4k address */
row = edac_mc_find_csrow_by_page(mci, block_page);
edac_mc_handle_ue(mci, block_page, 0, row, "e7xxx UE");
}
-
static void process_ue_no_info(struct mem_ctl_info *mci)
{
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
edac_mc_handle_ue_no_info(mci, "e7xxx UE log register overflow");
}
-
static void e7xxx_get_error_info (struct mem_ctl_info *mci,
struct e7xxx_error_info *info)
{
@@ -253,31 +254,29 @@ static void e7xxx_get_error_info (struct mem_ctl_info *mci,
pvt = (struct e7xxx_pvt *) mci->pvt_info;
pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_FERR,
- &info->dram_ferr);
+ &info->dram_ferr);
pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_NERR,
- &info->dram_nerr);
+ &info->dram_nerr);
if ((info->dram_ferr & 1) || (info->dram_nerr & 1)) {
pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_CELOG_ADD,
- &info->dram_celog_add);
+ &info->dram_celog_add);
pci_read_config_word(pvt->bridge_ck,
- E7XXX_DRAM_CELOG_SYNDROME, &info->dram_celog_syndrome);
+ E7XXX_DRAM_CELOG_SYNDROME,
+ &info->dram_celog_syndrome);
}
if ((info->dram_ferr & 2) || (info->dram_nerr & 2))
pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_UELOG_ADD,
- &info->dram_uelog_add);
+ &info->dram_uelog_add);
if (info->dram_ferr & 3)
- pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03,
- 0x03);
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03);
if (info->dram_nerr & 3)
- pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03,
- 0x03);
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03);
}
-
static int e7xxx_process_error_info (struct mem_ctl_info *mci,
struct e7xxx_error_info *info, int handle_errors)
{
@@ -325,17 +324,15 @@ static int e7xxx_process_error_info (struct mem_ctl_info *mci,
return error_found;
}
-
static void e7xxx_check(struct mem_ctl_info *mci)
{
struct e7xxx_error_info info;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
e7xxx_get_error_info(mci, &info);
e7xxx_process_error_info(mci, &info, 1);
}
-
static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
{
int rc = -ENODEV;
@@ -349,19 +346,20 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
u32 dra;
unsigned long last_cumul_size;
+ struct e7xxx_error_info discard;
-
- debugf0("MC: " __FILE__ ": %s(): mci\n", __func__);
+ debugf0("%s(): mci\n", __func__);
/* need to find out the number of channels */
pci_read_config_dword(pdev, E7XXX_DRC, &drc);
+
/* only e7501 can be single channel */
if (dev_idx == E7501) {
drc_chan = ((drc >> 22) & 0x1);
drc_drbg = (drc >> 18) & 0x3;
}
- drc_ddim = (drc >> 20) & 0x3;
+ drc_ddim = (drc >> 20) & 0x3;
mci = edac_mc_alloc(sizeof(*pvt), E7XXX_NR_CSROWS, drc_chan + 1);
if (mci == NULL) {
@@ -369,33 +367,31 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
goto fail;
}
- debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
-
+ debugf3("%s(): init mci\n", __func__);
mci->mtype_cap = MEM_FLAG_RDDR;
- mci->edac_ctl_cap =
- EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED;
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED |
+ EDAC_FLAG_S4ECD4ED;
/* FIXME - what if different memory types are in different csrows? */
- mci->mod_name = BS_MOD_STR;
+ mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = "$Revision: 1.5.2.9 $";
mci->pdev = pdev;
- debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+ debugf3("%s(): init pvt\n", __func__);
pvt = (struct e7xxx_pvt *) mci->pvt_info;
pvt->dev_info = &e7xxx_devs[dev_idx];
pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
- pvt->dev_info->err_dev,
- pvt->bridge_ck);
+ pvt->dev_info->err_dev,
+ pvt->bridge_ck);
+
if (!pvt->bridge_ck) {
- printk(KERN_ERR
- "MC: error reporting device not found:"
- "vendor %x device 0x%x (broken BIOS?)\n",
- PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev);
+ e7xxx_printk(KERN_ERR, "error reporting device not found:"
+ "vendor %x device 0x%x (broken BIOS?)\n",
+ PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev);
goto fail;
}
- debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__);
+ debugf3("%s(): more mci init\n", __func__);
mci->ctl_name = pvt->dev_info->ctl_name;
-
mci->edac_check = e7xxx_check;
mci->ctl_page_to_phys = ctl_page_to_phys;
@@ -418,17 +414,18 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
pci_read_config_byte(mci->pdev, E7XXX_DRB + index, &value);
/* convert a 64 or 32 MiB DRB to a page size. */
cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
- debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
- __func__, index, cumul_size);
+ debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
+ cumul_size);
+
if (cumul_size == last_cumul_size)
- continue; /* not populated */
+ continue; /* not populated */
csrow->first_page = last_cumul_size;
csrow->last_page = cumul_size - 1;
csrow->nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;
- csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
- csrow->mtype = MEM_RDDR; /* only one type supported */
+ csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
+ csrow->mtype = MEM_RDDR; /* only one type supported */
csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
/*
@@ -449,8 +446,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
mci->edac_cap |= EDAC_FLAG_NONE;
- debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n",
- __func__);
+ debugf3("%s(): tolm, remapbase, remaplimit\n", __func__);
/* load the top of low memory, remap base, and remap limit vars */
pci_read_config_word(mci->pdev, E7XXX_TOLM, &pci_data);
pvt->tolm = ((u32) pci_data) << 4;
@@ -458,22 +454,20 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
pvt->remapbase = ((u32) pci_data) << 14;
pci_read_config_word(mci->pdev, E7XXX_REMAPLIMIT, &pci_data);
pvt->remaplimit = ((u32) pci_data) << 14;
- printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
- pvt->remapbase, pvt->remaplimit);
+ e7xxx_printk(KERN_INFO,
+ "tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
+ pvt->remapbase, pvt->remaplimit);
/* clear any pending errors, or initial state bits */
- pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03);
- pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03);
+ e7xxx_get_error_info(mci, &discard);
if (edac_mc_add_mc(mci) != 0) {
- debugf3("MC: " __FILE__
- ": %s(): failed edac_mc_add_mc()\n",
- __func__);
+ debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
goto fail;
}
/* get this far and it's successful */
- debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ debugf3("%s(): success\n", __func__);
return 0;
fail:
@@ -487,62 +481,67 @@ fail:
}
/* returns count (>= 0), or negative on error */
-static int __devinit
-e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int __devinit e7xxx_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
+ debugf0("%s()\n", __func__);
/* wake up and enable device */
return pci_enable_device(pdev) ?
- -EIO : e7xxx_probe1(pdev, ent->driver_data);
+ -EIO : e7xxx_probe1(pdev, ent->driver_data);
}
-
static void __devexit e7xxx_remove_one(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
struct e7xxx_pvt *pvt;
- debugf0(__FILE__ ": %s()\n", __func__);
+ debugf0("%s()\n", __func__);
- if (((mci = edac_mc_find_mci_by_pdev(pdev)) != 0) &&
- edac_mc_del_mc(mci)) {
- pvt = (struct e7xxx_pvt *) mci->pvt_info;
- pci_dev_put(pvt->bridge_ck);
- edac_mc_free(mci);
- }
-}
+ if ((mci = edac_mc_del_mc(pdev)) == NULL)
+ return;
+ pvt = (struct e7xxx_pvt *) mci->pvt_info;
+ pci_dev_put(pvt->bridge_ck);
+ edac_mc_free(mci);
+}
static const struct pci_device_id e7xxx_pci_tbl[] __devinitdata = {
- {PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- E7205},
- {PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- E7500},
- {PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- E7501},
- {PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- E7505},
- {0,} /* 0 terminated list. */
+ {
+ PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7205
+ },
+ {
+ PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7500
+ },
+ {
+ PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7501
+ },
+ {
+ PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7505
+ },
+ {
+ 0,
+ } /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl);
-
static struct pci_driver e7xxx_driver = {
- .name = BS_MOD_STR,
+ .name = EDAC_MOD_STR,
.probe = e7xxx_init_one,
.remove = __devexit_p(e7xxx_remove_one),
.id_table = e7xxx_pci_tbl,
};
-
static int __init e7xxx_init(void)
{
return pci_register_driver(&e7xxx_driver);
}
-
static void __exit e7xxx_exit(void)
{
pci_unregister_driver(&e7xxx_driver);
@@ -551,8 +550,7 @@ static void __exit e7xxx_exit(void)
module_init(e7xxx_init);
module_exit(e7xxx_exit);
-
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
- "Based on.work by Dan Hollis et al");
+ "Based on.work by Dan Hollis et al");
MODULE_DESCRIPTION("MC support for Intel e7xxx memory controllers");
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 9c205274c1c..ea06e3a4dc3 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -12,7 +12,6 @@
*
*/
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
@@ -29,14 +28,13 @@
#include <linux/list.h>
#include <linux/sysdev.h>
#include <linux/ctype.h>
-
+#include <linux/kthread.h>
#include <asm/uaccess.h>
#include <asm/page.h>
#include <asm/edac.h>
-
#include "edac_mc.h"
-#define EDAC_MC_VERSION "edac_mc Ver: 2.0.0 " __DATE__
+#define EDAC_MC_VERSION "Ver: 2.0.0 " __DATE__
/* For now, disable the EDAC sysfs code. The sysfs interface that EDAC
* presents to user space needs more thought, and is likely to change
@@ -47,7 +45,7 @@
#ifdef CONFIG_EDAC_DEBUG
/* Values of 0 to 4 will generate output */
int edac_debug_level = 1;
-EXPORT_SYMBOL(edac_debug_level);
+EXPORT_SYMBOL_GPL(edac_debug_level);
#endif
/* EDAC Controls, setable by module parameter, and sysfs */
@@ -64,13 +62,14 @@ static atomic_t pci_parity_count = ATOMIC_INIT(0);
static DECLARE_MUTEX(mem_ctls_mutex);
static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices);
+static struct task_struct *edac_thread;
+
/* Structure of the whitelist and blacklist arrays */
struct edac_pci_device_list {
unsigned int vendor; /* Vendor ID */
unsigned int device; /* Deviice ID */
};
-
#define MAX_LISTED_PCI_DEVICES 32
/* List of PCI devices (vendor-id:device-id) that should be skipped */
@@ -123,7 +122,6 @@ static const char *edac_caps[] = {
[EDAC_S16ECD16ED] = "S16ECD16ED"
};
-
/* sysfs object: /sys/devices/system/edac */
static struct sysdev_class edac_class = {
set_kset_name("edac"),
@@ -136,9 +134,15 @@ static struct sysdev_class edac_class = {
static struct kobject edac_memctrl_kobj;
static struct kobject edac_pci_kobj;
+/* We use these to wait for the reference counts on edac_memctrl_kobj and
+ * edac_pci_kobj to reach 0.
+ */
+static struct completion edac_memctrl_kobj_complete;
+static struct completion edac_pci_kobj_complete;
+
/*
* /sys/devices/system/edac/mc;
- * data structures and methods
+ * data structures and methods
*/
#if 0
static ssize_t memctrl_string_show(void *ptr, char *buffer)
@@ -165,33 +169,34 @@ static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
}
struct memctrl_dev_attribute {
- struct attribute attr;
- void *value;
+ struct attribute attr;
+ void *value;
ssize_t (*show)(void *,char *);
ssize_t (*store)(void *, const char *, size_t);
};
/* Set of show/store abstract level functions for memory control object */
-static ssize_t
-memctrl_dev_show(struct kobject *kobj, struct attribute *attr, char *buffer)
+static ssize_t memctrl_dev_show(struct kobject *kobj,
+ struct attribute *attr, char *buffer)
{
struct memctrl_dev_attribute *memctrl_dev;
memctrl_dev = (struct memctrl_dev_attribute*)attr;
if (memctrl_dev->show)
return memctrl_dev->show(memctrl_dev->value, buffer);
+
return -EIO;
}
-static ssize_t
-memctrl_dev_store(struct kobject *kobj, struct attribute *attr,
- const char *buffer, size_t count)
+static ssize_t memctrl_dev_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
{
struct memctrl_dev_attribute *memctrl_dev;
memctrl_dev = (struct memctrl_dev_attribute*)attr;
if (memctrl_dev->store)
return memctrl_dev->store(memctrl_dev->value, buffer, count);
+
return -EIO;
}
@@ -227,7 +232,6 @@ MEMCTRL_ATTR(log_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
MEMCTRL_ATTR(log_ce,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
MEMCTRL_ATTR(poll_msec,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
-
/* Base Attributes of the memory ECC object */
static struct memctrl_dev_attribute *memctrl_attr[] = {
&attr_panic_on_ue,
@@ -240,13 +244,14 @@ static struct memctrl_dev_attribute *memctrl_attr[] = {
/* Main MC kobject release() function */
static void edac_memctrl_master_release(struct kobject *kobj)
{
- debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__);
+ debugf1("%s()\n", __func__);
+ complete(&edac_memctrl_kobj_complete);
}
static struct kobj_type ktype_memctrl = {
- .release = edac_memctrl_master_release,
- .sysfs_ops = &memctrlfs_ops,
- .default_attrs = (struct attribute **) memctrl_attr,
+ .release = edac_memctrl_master_release,
+ .sysfs_ops = &memctrlfs_ops,
+ .default_attrs = (struct attribute **) memctrl_attr,
};
#endif /* DISABLE_EDAC_SYSFS */
@@ -268,32 +273,31 @@ static int edac_sysfs_memctrl_setup(void)
{
int err=0;
- debugf1("MC: " __FILE__ ": %s()\n", __func__);
+ debugf1("%s()\n", __func__);
/* create the /sys/devices/system/edac directory */
err = sysdev_class_register(&edac_class);
+
if (!err) {
/* Init the MC's kobject */
memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj));
- kobject_init(&edac_memctrl_kobj);
-
edac_memctrl_kobj.parent = &edac_class.kset.kobj;
edac_memctrl_kobj.ktype = &ktype_memctrl;
/* generate sysfs "..../edac/mc" */
err = kobject_set_name(&edac_memctrl_kobj,"mc");
+
if (!err) {
/* FIXME: maybe new sysdev_create_subdir() */
err = kobject_register(&edac_memctrl_kobj);
- if (err) {
+
+ if (err)
debugf1("Failed to register '.../edac/mc'\n");
- } else {
+ else
debugf1("Registered '.../edac/mc' kobject\n");
- }
}
- } else {
- debugf1(KERN_WARNING "__FILE__ %s() error=%d\n", __func__,err);
- }
+ } else
+ debugf1("%s() error=%d\n", __func__, err);
return err;
}
@@ -308,11 +312,12 @@ static void edac_sysfs_memctrl_teardown(void)
#ifndef DISABLE_EDAC_SYSFS
debugf0("MC: " __FILE__ ": %s()\n", __func__);
- /* Unregister the MC's kobject */
+ /* Unregister the MC's kobject and wait for reference count to reach
+ * 0.
+ */
+ init_completion(&edac_memctrl_kobj_complete);
kobject_unregister(&edac_memctrl_kobj);
-
- /* release the master edac mc kobject */
- kobject_put(&edac_memctrl_kobj);
+ wait_for_completion(&edac_memctrl_kobj_complete);
/* Unregister the 'edac' object */
sysdev_class_unregister(&edac_class);
@@ -331,7 +336,6 @@ struct list_control {
int *count;
};
-
#if 0
/* Output the list as: vendor_id:device:id<,vendor_id:device_id> */
static ssize_t edac_pci_list_string_show(void *ptr, char *buffer)
@@ -356,7 +360,6 @@ static ssize_t edac_pci_list_string_show(void *ptr, char *buffer)
}
len += snprintf(p + len,(PAGE_SIZE-len), "\n");
-
return (ssize_t) len;
}
@@ -378,7 +381,7 @@ static int parse_one_device(const char **s,const char **e,
/* if null byte, we are done */
if (!**s) {
- (*s)++; /* keep *s moving */
+ (*s)++; /* keep *s moving */
return 0;
}
@@ -395,6 +398,7 @@ static int parse_one_device(const char **s,const char **e,
/* parse vendor_id */
runner = *s;
+
while (runner < *e) {
/* scan for vendor:device delimiter */
if (*runner == ':') {
@@ -402,6 +406,7 @@ static int parse_one_device(const char **s,const char **e,
runner = p + 1;
break;
}
+
runner++;
}
@@ -417,12 +422,11 @@ static int parse_one_device(const char **s,const char **e,
}
*s = runner;
-
return 1;
}
static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer,
- size_t count)
+ size_t count)
{
struct list_control *listctl;
struct edac_pci_device_list *list;
@@ -432,14 +436,12 @@ static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer,
s = (char*)buffer;
e = s + count;
-
listctl = ptr;
list = listctl->list;
index = listctl->count;
-
*index = 0;
- while (*index < MAX_LISTED_PCI_DEVICES) {
+ while (*index < MAX_LISTED_PCI_DEVICES) {
if (parse_one_device(&s,&e,&vendor_id,&device_id)) {
list[ *index ].vendor = vendor_id;
list[ *index ].device = device_id;
@@ -472,15 +474,15 @@ static ssize_t edac_pci_int_store(void *ptr, const char *buffer, size_t count)
}
struct edac_pci_dev_attribute {
- struct attribute attr;
- void *value;
+ struct attribute attr;
+ void *value;
ssize_t (*show)(void *,char *);
ssize_t (*store)(void *, const char *,size_t);
};
/* Set of show/store abstract level functions for PCI Parity object */
static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr,
- char *buffer)
+ char *buffer)
{
struct edac_pci_dev_attribute *edac_pci_dev;
edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
@@ -490,8 +492,8 @@ static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr,
return -EIO;
}
-static ssize_t edac_pci_dev_store(struct kobject *kobj, struct attribute *attr,
- const char *buffer, size_t count)
+static ssize_t edac_pci_dev_store(struct kobject *kobj,
+ struct attribute *attr, const char *buffer, size_t count)
{
struct edac_pci_dev_attribute *edac_pci_dev;
edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
@@ -506,7 +508,6 @@ static struct sysfs_ops edac_pci_sysfs_ops = {
.store = edac_pci_dev_store
};
-
#define EDAC_PCI_ATTR(_name,_mode,_show,_store) \
struct edac_pci_dev_attribute edac_pci_attr_##_name = { \
.attr = {.name = __stringify(_name), .mode = _mode }, \
@@ -549,9 +550,11 @@ EDAC_PCI_STRING_ATTR(pci_parity_blacklist,
#endif
/* PCI Parity control files */
-EDAC_PCI_ATTR(check_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
-EDAC_PCI_ATTR(panic_on_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
-EDAC_PCI_ATTR(pci_parity_count,S_IRUGO,edac_pci_int_show,NULL);
+EDAC_PCI_ATTR(check_pci_parity, S_IRUGO|S_IWUSR, edac_pci_int_show,
+ edac_pci_int_store);
+EDAC_PCI_ATTR(panic_on_pci_parity, S_IRUGO|S_IWUSR, edac_pci_int_show,
+ edac_pci_int_store);
+EDAC_PCI_ATTR(pci_parity_count, S_IRUGO, edac_pci_int_show, NULL);
/* Base Attributes of the memory ECC object */
static struct edac_pci_dev_attribute *edac_pci_attr[] = {
@@ -564,13 +567,14 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = {
/* No memory to release */
static void edac_pci_release(struct kobject *kobj)
{
- debugf1("EDAC PCI: " __FILE__ ": %s()\n", __func__);
+ debugf1("%s()\n", __func__);
+ complete(&edac_pci_kobj_complete);
}
static struct kobj_type ktype_edac_pci = {
- .release = edac_pci_release,
- .sysfs_ops = &edac_pci_sysfs_ops,
- .default_attrs = (struct attribute **) edac_pci_attr,
+ .release = edac_pci_release,
+ .sysfs_ops = &edac_pci_sysfs_ops,
+ .default_attrs = (struct attribute **) edac_pci_attr,
};
#endif /* DISABLE_EDAC_SYSFS */
@@ -588,24 +592,24 @@ static int edac_sysfs_pci_setup(void)
{
int err;
- debugf1("MC: " __FILE__ ": %s()\n", __func__);
+ debugf1("%s()\n", __func__);
memset(&edac_pci_kobj, 0, sizeof(edac_pci_kobj));
-
- kobject_init(&edac_pci_kobj);
edac_pci_kobj.parent = &edac_class.kset.kobj;
edac_pci_kobj.ktype = &ktype_edac_pci;
-
err = kobject_set_name(&edac_pci_kobj, "pci");
+
if (!err) {
/* Instanstiate the csrow object */
/* FIXME: maybe new sysdev_create_subdir() */
err = kobject_register(&edac_pci_kobj);
+
if (err)
debugf1("Failed to register '.../edac/pci'\n");
else
debugf1("Registered '.../edac/pci' kobject\n");
}
+
return err;
}
#endif /* DISABLE_EDAC_SYSFS */
@@ -613,10 +617,10 @@ static int edac_sysfs_pci_setup(void)
static void edac_sysfs_pci_teardown(void)
{
#ifndef DISABLE_EDAC_SYSFS
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
-
+ debugf0("%s()\n", __func__);
+ init_completion(&edac_pci_kobj_complete);
kobject_unregister(&edac_pci_kobj);
- kobject_put(&edac_pci_kobj);
+ wait_for_completion(&edac_pci_kobj_complete);
#endif
}
@@ -633,6 +637,7 @@ static ssize_t csrow_ch0_dimm_label_show(struct csrow_info *csrow, char *data)
size = snprintf(data, EDAC_MC_LABEL_LEN,"%s\n",
csrow->channels[0].label);
}
+
return size;
}
@@ -644,11 +649,12 @@ static ssize_t csrow_ch1_dimm_label_show(struct csrow_info *csrow, char *data)
size = snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
csrow->channels[1].label);
}
+
return size;
}
static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow,
- const char *data, size_t size)
+ const char *data, size_t size)
{
ssize_t max_size = 0;
@@ -657,11 +663,12 @@ static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow,
strncpy(csrow->channels[0].label, data, max_size);
csrow->channels[0].label[max_size] = '\0';
}
+
return size;
}
static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow,
- const char *data, size_t size)
+ const char *data, size_t size)
{
ssize_t max_size = 0;
@@ -670,6 +677,7 @@ static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow,
strncpy(csrow->channels[1].label, data, max_size);
csrow->channels[1].label[max_size] = '\0';
}
+
return max_size;
}
@@ -690,6 +698,7 @@ static ssize_t csrow_ch0_ce_count_show(struct csrow_info *csrow, char *data)
if (csrow->nr_channels > 0) {
size = sprintf(data,"%u\n", csrow->channels[0].ce_count);
}
+
return size;
}
@@ -700,6 +709,7 @@ static ssize_t csrow_ch1_ce_count_show(struct csrow_info *csrow, char *data)
if (csrow->nr_channels > 1) {
size = sprintf(data,"%u\n", csrow->channels[1].ce_count);
}
+
return size;
}
@@ -724,7 +734,7 @@ static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data)
}
struct csrowdev_attribute {
- struct attribute attr;
+ struct attribute attr;
ssize_t (*show)(struct csrow_info *,char *);
ssize_t (*store)(struct csrow_info *, const char *,size_t);
};
@@ -734,24 +744,26 @@ struct csrowdev_attribute {
/* Set of show/store higher level functions for csrow objects */
static ssize_t csrowdev_show(struct kobject *kobj, struct attribute *attr,
- char *buffer)
+ char *buffer)
{
struct csrow_info *csrow = to_csrow(kobj);
struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
if (csrowdev_attr->show)
return csrowdev_attr->show(csrow, buffer);
+
return -EIO;
}
static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr,
- const char *buffer, size_t count)
+ const char *buffer, size_t count)
{
struct csrow_info *csrow = to_csrow(kobj);
struct csrowdev_attribute * csrowdev_attr = to_csrowdev_attr(attr);
if (csrowdev_attr->store)
return csrowdev_attr->store(csrow, buffer, count);
+
return -EIO;
}
@@ -785,7 +797,6 @@ CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR,
csrow_ch1_dimm_label_show,
csrow_ch1_dimm_label_store);
-
/* Attributes of the CSROW<id> object */
static struct csrowdev_attribute *csrow_attr[] = {
&attr_dev_type,
@@ -801,40 +812,43 @@ static struct csrowdev_attribute *csrow_attr[] = {
NULL,
};
-
/* No memory to release */
static void edac_csrow_instance_release(struct kobject *kobj)
{
- debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__);
+ struct csrow_info *cs;
+
+ debugf1("%s()\n", __func__);
+ cs = container_of(kobj, struct csrow_info, kobj);
+ complete(&cs->kobj_complete);
}
static struct kobj_type ktype_csrow = {
- .release = edac_csrow_instance_release,
- .sysfs_ops = &csrowfs_ops,
- .default_attrs = (struct attribute **) csrow_attr,
+ .release = edac_csrow_instance_release,
+ .sysfs_ops = &csrowfs_ops,
+ .default_attrs = (struct attribute **) csrow_attr,
};
/* Create a CSROW object under specifed edac_mc_device */
static int edac_create_csrow_object(struct kobject *edac_mci_kobj,
- struct csrow_info *csrow, int index )
+ struct csrow_info *csrow, int index)
{
int err = 0;
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
-
+ debugf0("%s()\n", __func__);
memset(&csrow->kobj, 0, sizeof(csrow->kobj));
/* generate ..../edac/mc/mc<id>/csrow<index> */
- kobject_init(&csrow->kobj);
csrow->kobj.parent = edac_mci_kobj;
csrow->kobj.ktype = &ktype_csrow;
/* name this instance of csrow<id> */
err = kobject_set_name(&csrow->kobj,"csrow%d",index);
+
if (!err) {
/* Instanstiate the csrow object */
err = kobject_register(&csrow->kobj);
+
if (err)
debugf0("Failed to register CSROW%d\n",index);
else
@@ -846,8 +860,8 @@ static int edac_create_csrow_object(struct kobject *edac_mci_kobj,
/* sysfs data structures and methods for the MCI kobjects */
-static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
- const char *data, size_t count )
+static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
+ const char *data, size_t count)
{
int row, chan;
@@ -855,16 +869,18 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
mci->ce_noinfo_count = 0;
mci->ue_count = 0;
mci->ce_count = 0;
+
for (row = 0; row < mci->nr_csrows; row++) {
struct csrow_info *ri = &mci->csrows[row];
ri->ue_count = 0;
ri->ce_count = 0;
+
for (chan = 0; chan < ri->nr_channels; chan++)
ri->channels[chan].ce_count = 0;
}
- mci->start_time = jiffies;
+ mci->start_time = jiffies;
return count;
}
@@ -922,18 +938,16 @@ static ssize_t mci_edac_capability_show(struct mem_ctl_info *mci, char *data)
p += mci_output_edac_cap(p,mci->edac_ctl_cap);
p += sprintf(p, "\n");
-
return p - data;
}
static ssize_t mci_edac_current_capability_show(struct mem_ctl_info *mci,
- char *data)
+ char *data)
{
char *p = data;
p += mci_output_edac_cap(p,mci->edac_cap);
p += sprintf(p, "\n");
-
return p - data;
}
@@ -950,13 +964,13 @@ static int mci_output_mtype_cap(char *buf, unsigned long mtype_cap)
return p - buf;
}
-static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci, char *data)
+static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci,
+ char *data)
{
char *p = data;
p += mci_output_mtype_cap(p,mci->mtype_cap);
p += sprintf(p, "\n");
-
return p - data;
}
@@ -970,6 +984,7 @@ static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
if (!csrow->nr_pages)
continue;
+
total_pages += csrow->nr_pages;
}
@@ -977,7 +992,7 @@ static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
}
struct mcidev_attribute {
- struct attribute attr;
+ struct attribute attr;
ssize_t (*show)(struct mem_ctl_info *,char *);
ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
};
@@ -986,30 +1001,32 @@ struct mcidev_attribute {
#define to_mcidev_attr(a) container_of(a, struct mcidev_attribute, attr)
static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
- char *buffer)
+ char *buffer)
{
struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
if (mcidev_attr->show)
return mcidev_attr->show(mem_ctl_info, buffer);
+
return -EIO;
}
static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
- const char *buffer, size_t count)
+ const char *buffer, size_t count)
{
struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
if (mcidev_attr->store)
return mcidev_attr->store(mem_ctl_info, buffer, count);
+
return -EIO;
}
static struct sysfs_ops mci_ops = {
- .show = mcidev_show,
- .store = mcidev_store
+ .show = mcidev_show,
+ .store = mcidev_store
};
#define MCIDEV_ATTR(_name,_mode,_show,_store) \
@@ -1037,7 +1054,6 @@ MCIDEV_ATTR(edac_current_capability,S_IRUGO,
MCIDEV_ATTR(supported_mem_type,S_IRUGO,
mci_supported_mem_type_show,NULL);
-
static struct mcidev_attribute *mci_attr[] = {
&mci_attr_reset_counters,
&mci_attr_module_name,
@@ -1054,25 +1070,22 @@ static struct mcidev_attribute *mci_attr[] = {
NULL
};
-
/*
* Release of a MC controlling instance
*/
static void edac_mci_instance_release(struct kobject *kobj)
{
struct mem_ctl_info *mci;
- mci = container_of(kobj,struct mem_ctl_info,edac_mci_kobj);
- debugf0("MC: " __FILE__ ": %s() idx=%d calling kfree\n",
- __func__, mci->mc_idx);
-
- kfree(mci);
+ mci = to_mci(kobj);
+ debugf0("%s() idx=%d\n", __func__, mci->mc_idx);
+ complete(&mci->kobj_complete);
}
static struct kobj_type ktype_mci = {
- .release = edac_mci_instance_release,
- .sysfs_ops = &mci_ops,
- .default_attrs = (struct attribute **) mci_attr,
+ .release = edac_mci_instance_release,
+ .sysfs_ops = &mci_ops,
+ .default_attrs = (struct attribute **) mci_attr,
};
#endif /* DISABLE_EDAC_SYSFS */
@@ -1099,13 +1112,12 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
struct csrow_info *csrow;
struct kobject *edac_mci_kobj=&mci->edac_mci_kobj;
- debugf0("MC: " __FILE__ ": %s() idx=%d\n", __func__, mci->mc_idx);
-
+ debugf0("%s() idx=%d\n", __func__, mci->mc_idx);
memset(edac_mci_kobj, 0, sizeof(*edac_mci_kobj));
- kobject_init(edac_mci_kobj);
/* set the name of the mc<id> object */
err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx);
+
if (err)
return err;
@@ -1115,50 +1127,48 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
/* register the mc<id> kobject */
err = kobject_register(edac_mci_kobj);
+
if (err)
return err;
/* create a symlink for the device */
err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj,
EDAC_DEVICE_SYMLINK);
- if (err) {
- kobject_unregister(edac_mci_kobj);
- return err;
- }
+
+ if (err)
+ goto fail0;
/* Make directories for each CSROW object
* under the mc<id> kobject
*/
for (i = 0; i < mci->nr_csrows; i++) {
-
csrow = &mci->csrows[i];
/* Only expose populated CSROWs */
if (csrow->nr_pages > 0) {
err = edac_create_csrow_object(edac_mci_kobj,csrow,i);
+
if (err)
- goto fail;
+ goto fail1;
}
}
- /* Mark this MCI instance as having sysfs entries */
- mci->sysfs_active = MCI_SYSFS_ACTIVE;
-
return 0;
-
/* CSROW error: backout what has already been registered, */
-fail:
+fail1:
for ( i--; i >= 0; i--) {
if (csrow->nr_pages > 0) {
+ init_completion(&csrow->kobj_complete);
kobject_unregister(&mci->csrows[i].kobj);
- kobject_put(&mci->csrows[i].kobj);
+ wait_for_completion(&csrow->kobj_complete);
}
}
+fail0:
+ init_completion(&mci->kobj_complete);
kobject_unregister(edac_mci_kobj);
- kobject_put(edac_mci_kobj);
-
+ wait_for_completion(&mci->kobj_complete);
return err;
}
#endif /* DISABLE_EDAC_SYSFS */
@@ -1171,20 +1181,21 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
#ifndef DISABLE_EDAC_SYSFS
int i;
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
+ debugf0("%s()\n", __func__);
/* remove all csrow kobjects */
for (i = 0; i < mci->nr_csrows; i++) {
- if (mci->csrows[i].nr_pages > 0) {
+ if (mci->csrows[i].nr_pages > 0) {
+ init_completion(&mci->csrows[i].kobj_complete);
kobject_unregister(&mci->csrows[i].kobj);
- kobject_put(&mci->csrows[i].kobj);
+ wait_for_completion(&mci->csrows[i].kobj_complete);
}
}
sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
-
+ init_completion(&mci->kobj_complete);
kobject_unregister(&mci->edac_mci_kobj);
- kobject_put(&mci->edac_mci_kobj);
+ wait_for_completion(&mci->kobj_complete);
#endif /* DISABLE_EDAC_SYSFS */
}
@@ -1192,8 +1203,6 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
#ifdef CONFIG_EDAC_DEBUG
-EXPORT_SYMBOL(edac_mc_dump_channel);
-
void edac_mc_dump_channel(struct channel_info *chan)
{
debugf4("\tchannel = %p\n", chan);
@@ -1202,9 +1211,7 @@ void edac_mc_dump_channel(struct channel_info *chan)
debugf4("\tchannel->label = '%s'\n", chan->label);
debugf4("\tchannel->csrow = %p\n\n", chan->csrow);
}
-
-
-EXPORT_SYMBOL(edac_mc_dump_csrow);
+EXPORT_SYMBOL_GPL(edac_mc_dump_channel);
void edac_mc_dump_csrow(struct csrow_info *csrow)
{
@@ -1220,9 +1227,7 @@ void edac_mc_dump_csrow(struct csrow_info *csrow)
debugf4("\tcsrow->channels = %p\n", csrow->channels);
debugf4("\tcsrow->mci = %p\n\n", csrow->mci);
}
-
-
-EXPORT_SYMBOL(edac_mc_dump_mci);
+EXPORT_SYMBOL_GPL(edac_mc_dump_csrow);
void edac_mc_dump_mci(struct mem_ctl_info *mci)
{
@@ -1238,9 +1243,9 @@ void edac_mc_dump_mci(struct mem_ctl_info *mci)
mci->mod_name, mci->ctl_name);
debugf3("\tpvt_info = %p\n\n", mci->pvt_info);
}
+EXPORT_SYMBOL_GPL(edac_mc_dump_mci);
-
-#endif /* CONFIG_EDAC_DEBUG */
+#endif /* CONFIG_EDAC_DEBUG */
/* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'.
* Adjust 'ptr' so that its alignment is at least as stringent as what the
@@ -1249,7 +1254,7 @@ void edac_mc_dump_mci(struct mem_ctl_info *mci)
* If 'size' is a constant, the compiler will optimize this whole function
* down to either a no-op or the addition of a constant to the value of 'ptr'.
*/
-static inline char * align_ptr (void *ptr, unsigned size)
+static inline char * align_ptr(void *ptr, unsigned size)
{
unsigned align, r;
@@ -1276,9 +1281,6 @@ static inline char * align_ptr (void *ptr, unsigned size)
return (char *) (((unsigned long) ptr) + align - r);
}
-
-EXPORT_SYMBOL(edac_mc_alloc);
-
/**
* edac_mc_alloc: Allocate a struct mem_ctl_info structure
* @size_pvt: size of private storage needed
@@ -1296,7 +1298,7 @@ EXPORT_SYMBOL(edac_mc_alloc);
* struct mem_ctl_info pointer
*/
struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
- unsigned nr_chans)
+ unsigned nr_chans)
{
struct mem_ctl_info *mci;
struct csrow_info *csi, *csrow;
@@ -1327,8 +1329,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
chi = (struct channel_info *) (((char *) mci) + ((unsigned long) chi));
pvt = sz_pvt ? (((char *) mci) + ((unsigned long) pvt)) : NULL;
- memset(mci, 0, size); /* clear all fields */
-
+ memset(mci, 0, size); /* clear all fields */
mci->csrows = csi;
mci->pvt_info = pvt;
mci->nr_csrows = nr_csrows;
@@ -1350,50 +1351,24 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
return mci;
}
-
-
-EXPORT_SYMBOL(edac_mc_free);
+EXPORT_SYMBOL_GPL(edac_mc_alloc);
/**
* edac_mc_free: Free a previously allocated 'mci' structure
* @mci: pointer to a struct mem_ctl_info structure
- *
- * Free up a previously allocated mci structure
- * A MCI structure can be in 2 states after being allocated
- * by edac_mc_alloc().
- * 1) Allocated in a MC driver's probe, but not yet committed
- * 2) Allocated and committed, by a call to edac_mc_add_mc()
- * edac_mc_add_mc() is the function that adds the sysfs entries
- * thus, this free function must determine which state the 'mci'
- * structure is in, then either free it directly or
- * perform kobject cleanup by calling edac_remove_sysfs_mci_device().
- *
- * VOID Return
*/
void edac_mc_free(struct mem_ctl_info *mci)
{
- /* only if sysfs entries for this mci instance exist
- * do we remove them and defer the actual kfree via
- * the kobject 'release()' callback.
- *
- * Otherwise, do a straight kfree now.
- */
- if (mci->sysfs_active == MCI_SYSFS_ACTIVE)
- edac_remove_sysfs_mci_device(mci);
- else
- kfree(mci);
+ kfree(mci);
}
+EXPORT_SYMBOL_GPL(edac_mc_free);
-
-
-EXPORT_SYMBOL(edac_mc_find_mci_by_pdev);
-
-struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev *pdev)
+static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
struct list_head *item;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
list_for_each(item, &mc_devices) {
mci = list_entry(item, struct mem_ctl_info, link);
@@ -1405,7 +1380,7 @@ struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev *pdev)
return NULL;
}
-static int add_mc_to_global_list (struct mem_ctl_info *mci)
+static int add_mc_to_global_list(struct mem_ctl_info *mci)
{
struct list_head *item, *insert_before;
struct mem_ctl_info *p;
@@ -1415,11 +1390,12 @@ static int add_mc_to_global_list (struct mem_ctl_info *mci)
mci->mc_idx = 0;
insert_before = &mc_devices;
} else {
- if (edac_mc_find_mci_by_pdev(mci->pdev)) {
- printk(KERN_WARNING
- "EDAC MC: %s (%s) %s %s already assigned %d\n",
- mci->pdev->dev.bus_id, pci_name(mci->pdev),
- mci->mod_name, mci->ctl_name, mci->mc_idx);
+ if (find_mci_by_pdev(mci->pdev)) {
+ edac_printk(KERN_WARNING, EDAC_MC,
+ "%s (%s) %s %s already assigned %d\n",
+ mci->pdev->dev.bus_id,
+ pci_name(mci->pdev), mci->mod_name,
+ mci->ctl_name, mci->mc_idx);
return 1;
}
@@ -1447,12 +1423,26 @@ static int add_mc_to_global_list (struct mem_ctl_info *mci)
return 0;
}
+static void complete_mc_list_del(struct rcu_head *head)
+{
+ struct mem_ctl_info *mci;
+ mci = container_of(head, struct mem_ctl_info, rcu);
+ INIT_LIST_HEAD(&mci->link);
+ complete(&mci->complete);
+}
-EXPORT_SYMBOL(edac_mc_add_mc);
+static void del_mc_from_global_list(struct mem_ctl_info *mci)
+{
+ list_del_rcu(&mci->link);
+ init_completion(&mci->complete);
+ call_rcu(&mci->rcu, complete_mc_list_del);
+ wait_for_completion(&mci->complete);
+}
/**
- * edac_mc_add_mc: Insert the 'mci' structure into the mci global list
+ * edac_mc_add_mc: Insert the 'mci' structure into the mci global list and
+ * create sysfs entries associated with mci structure
* @mci: pointer to the mci structure to be added to the list
*
* Return:
@@ -1463,111 +1453,90 @@ EXPORT_SYMBOL(edac_mc_add_mc);
/* FIXME - should a warning be printed if no error detection? correction? */
int edac_mc_add_mc(struct mem_ctl_info *mci)
{
- int rc = 1;
-
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
+ debugf0("%s()\n", __func__);
#ifdef CONFIG_EDAC_DEBUG
if (edac_debug_level >= 3)
edac_mc_dump_mci(mci);
+
if (edac_debug_level >= 4) {
int i;
for (i = 0; i < mci->nr_csrows; i++) {
int j;
+
edac_mc_dump_csrow(&mci->csrows[i]);
for (j = 0; j < mci->csrows[i].nr_channels; j++)
- edac_mc_dump_channel(&mci->csrows[i].
- channels[j]);
+ edac_mc_dump_channel(
+ &mci->csrows[i].channels[j]);
}
}
#endif
down(&mem_ctls_mutex);
if (add_mc_to_global_list(mci))
- goto finish;
+ goto fail0;
/* set load time so that error rate can be tracked */
mci->start_time = jiffies;
if (edac_create_sysfs_mci_device(mci)) {
- printk(KERN_WARNING
- "EDAC MC%d: failed to create sysfs device\n",
- mci->mc_idx);
- /* FIXME - should there be an error code and unwind? */
- goto finish;
+ edac_mc_printk(mci, KERN_WARNING,
+ "failed to create sysfs device\n");
+ goto fail1;
}
/* Report action taken */
- printk(KERN_INFO
- "EDAC MC%d: Giving out device to %s %s: PCI %s\n",
- mci->mc_idx, mci->mod_name, mci->ctl_name,
- pci_name(mci->pdev));
+ edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: PCI %s\n",
+ mci->mod_name, mci->ctl_name, pci_name(mci->pdev));
-
- rc = 0;
-
-finish:
up(&mem_ctls_mutex);
- return rc;
-}
-
-
-
-static void complete_mc_list_del (struct rcu_head *head)
-{
- struct mem_ctl_info *mci;
+ return 0;
- mci = container_of(head, struct mem_ctl_info, rcu);
- INIT_LIST_HEAD(&mci->link);
- complete(&mci->complete);
-}
+fail1:
+ del_mc_from_global_list(mci);
-static void del_mc_from_global_list (struct mem_ctl_info *mci)
-{
- list_del_rcu(&mci->link);
- init_completion(&mci->complete);
- call_rcu(&mci->rcu, complete_mc_list_del);
- wait_for_completion(&mci->complete);
+fail0:
+ up(&mem_ctls_mutex);
+ return 1;
}
-
-EXPORT_SYMBOL(edac_mc_del_mc);
+EXPORT_SYMBOL_GPL(edac_mc_add_mc);
/**
- * edac_mc_del_mc: Remove the specified mci structure from global list
- * @mci: Pointer to struct mem_ctl_info structure
+ * edac_mc_del_mc: Remove sysfs entries for specified mci structure and
+ * remove mci structure from global list
+ * @pdev: Pointer to 'struct pci_dev' representing mci structure to remove.
*
- * Returns:
- * 0 Success
- * 1 Failure
+ * Return pointer to removed mci structure, or NULL if device not found.
*/
-int edac_mc_del_mc(struct mem_ctl_info *mci)
+struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev)
{
- int rc = 1;
+ struct mem_ctl_info *mci;
- debugf0("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ debugf0("MC: %s()\n", __func__);
down(&mem_ctls_mutex);
+
+ if ((mci = find_mci_by_pdev(pdev)) == NULL) {
+ up(&mem_ctls_mutex);
+ return NULL;
+ }
+
+ edac_remove_sysfs_mci_device(mci);
del_mc_from_global_list(mci);
- printk(KERN_INFO
- "EDAC MC%d: Removed device %d for %s %s: PCI %s\n",
- mci->mc_idx, mci->mc_idx, mci->mod_name, mci->ctl_name,
- pci_name(mci->pdev));
- rc = 0;
up(&mem_ctls_mutex);
-
- return rc;
+ edac_printk(KERN_INFO, EDAC_MC,
+ "Removed device %d for %s %s: PCI %s\n", mci->mc_idx,
+ mci->mod_name, mci->ctl_name, pci_name(mci->pdev));
+ return mci;
}
+EXPORT_SYMBOL_GPL(edac_mc_del_mc);
-
-EXPORT_SYMBOL(edac_mc_scrub_block);
-
-void edac_mc_scrub_block(unsigned long page, unsigned long offset,
- u32 size)
+void edac_mc_scrub_block(unsigned long page, unsigned long offset, u32 size)
{
struct page *pg;
void *virt_addr;
unsigned long flags = 0;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
/* ECC error page was not in our memory. Ignore it. */
if(!pfn_valid(page))
@@ -1590,19 +1559,15 @@ void edac_mc_scrub_block(unsigned long page, unsigned long offset,
if (PageHighMem(pg))
local_irq_restore(flags);
}
-
+EXPORT_SYMBOL_GPL(edac_mc_scrub_block);
/* FIXME - should return -1 */
-EXPORT_SYMBOL(edac_mc_find_csrow_by_page);
-
-int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
- unsigned long page)
+int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page)
{
struct csrow_info *csrows = mci->csrows;
int row, i;
- debugf1("MC%d: " __FILE__ ": %s(): 0x%lx\n", mci->mc_idx, __func__,
- page);
+ debugf1("MC%d: %s(): 0x%lx\n", mci->mc_idx, __func__, page);
row = -1;
for (i = 0; i < mci->nr_csrows; i++) {
@@ -1611,11 +1576,10 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
if (csrow->nr_pages == 0)
continue;
- debugf3("MC%d: " __FILE__
- ": %s(): first(0x%lx) page(0x%lx)"
- " last(0x%lx) mask(0x%lx)\n", mci->mc_idx,
- __func__, csrow->first_page, page,
- csrow->last_page, csrow->page_mask);
+ debugf3("MC%d: %s(): first(0x%lx) page(0x%lx) last(0x%lx) "
+ "mask(0x%lx)\n", mci->mc_idx, __func__,
+ csrow->first_page, page, csrow->last_page,
+ csrow->page_mask);
if ((page >= csrow->first_page) &&
(page <= csrow->last_page) &&
@@ -1627,56 +1591,52 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
}
if (row == -1)
- printk(KERN_ERR
- "EDAC MC%d: could not look up page error address %lx\n",
- mci->mc_idx, (unsigned long) page);
+ edac_mc_printk(mci, KERN_ERR,
+ "could not look up page error address %lx\n",
+ (unsigned long) page);
return row;
}
-
-
-EXPORT_SYMBOL(edac_mc_handle_ce);
+EXPORT_SYMBOL_GPL(edac_mc_find_csrow_by_page);
/* FIXME - setable log (warning/emerg) levels */
/* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */
void edac_mc_handle_ce(struct mem_ctl_info *mci,
- unsigned long page_frame_number,
- unsigned long offset_in_page,
- unsigned long syndrome, int row, int channel,
- const char *msg)
+ unsigned long page_frame_number, unsigned long offset_in_page,
+ unsigned long syndrome, int row, int channel, const char *msg)
{
unsigned long remapped_page;
- debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
/* FIXME - maybe make panic on INTERNAL ERROR an option */
if (row >= mci->nr_csrows || row < 0) {
/* something is wrong */
- printk(KERN_ERR
- "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n",
- mci->mc_idx, row, mci->nr_csrows);
+ edac_mc_printk(mci, KERN_ERR,
+ "INTERNAL ERROR: row out of range "
+ "(%d >= %d)\n", row, mci->nr_csrows);
edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
return;
}
+
if (channel >= mci->csrows[row].nr_channels || channel < 0) {
/* something is wrong */
- printk(KERN_ERR
- "EDAC MC%d: INTERNAL ERROR: channel out of range "
- "(%d >= %d)\n",
- mci->mc_idx, channel, mci->csrows[row].nr_channels);
+ edac_mc_printk(mci, KERN_ERR,
+ "INTERNAL ERROR: channel out of range "
+ "(%d >= %d)\n", channel,
+ mci->csrows[row].nr_channels);
edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
return;
}
if (log_ce)
/* FIXME - put in DIMM location */
- printk(KERN_WARNING
- "EDAC MC%d: CE page 0x%lx, offset 0x%lx,"
- " grain %d, syndrome 0x%lx, row %d, channel %d,"
- " label \"%s\": %s\n", mci->mc_idx,
- page_frame_number, offset_in_page,
- mci->csrows[row].grain, syndrome, row, channel,
- mci->csrows[row].channels[channel].label, msg);
+ edac_mc_printk(mci, KERN_WARNING,
+ "CE page 0x%lx, offset 0x%lx, grain %d, syndrome "
+ "0x%lx, row %d, channel %d, label \"%s\": %s\n",
+ page_frame_number, offset_in_page,
+ mci->csrows[row].grain, syndrome, row, channel,
+ mci->csrows[row].channels[channel].label, msg);
mci->ce_count++;
mci->csrows[row].ce_count++;
@@ -1697,31 +1657,25 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
page_frame_number;
edac_mc_scrub_block(remapped_page, offset_in_page,
- mci->csrows[row].grain);
+ mci->csrows[row].grain);
}
}
+EXPORT_SYMBOL_GPL(edac_mc_handle_ce);
-
-EXPORT_SYMBOL(edac_mc_handle_ce_no_info);
-
-void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci,
- const char *msg)
+void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg)
{
if (log_ce)
- printk(KERN_WARNING
- "EDAC MC%d: CE - no information available: %s\n",
- mci->mc_idx, msg);
+ edac_mc_printk(mci, KERN_WARNING,
+ "CE - no information available: %s\n", msg);
+
mci->ce_noinfo_count++;
mci->ce_count++;
}
-
-
-EXPORT_SYMBOL(edac_mc_handle_ue);
+EXPORT_SYMBOL_GPL(edac_mc_handle_ce_no_info);
void edac_mc_handle_ue(struct mem_ctl_info *mci,
- unsigned long page_frame_number,
- unsigned long offset_in_page, int row,
- const char *msg)
+ unsigned long page_frame_number, unsigned long offset_in_page,
+ int row, const char *msg)
{
int len = EDAC_MC_LABEL_LEN * 4;
char labels[len + 1];
@@ -1729,65 +1683,61 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
int chan;
int chars;
- debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
/* FIXME - maybe make panic on INTERNAL ERROR an option */
if (row >= mci->nr_csrows || row < 0) {
/* something is wrong */
- printk(KERN_ERR
- "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n",
- mci->mc_idx, row, mci->nr_csrows);
+ edac_mc_printk(mci, KERN_ERR,
+ "INTERNAL ERROR: row out of range "
+ "(%d >= %d)\n", row, mci->nr_csrows);
edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
return;
}
chars = snprintf(pos, len + 1, "%s",
- mci->csrows[row].channels[0].label);
+ mci->csrows[row].channels[0].label);
len -= chars;
pos += chars;
+
for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0);
chan++) {
chars = snprintf(pos, len + 1, ":%s",
- mci->csrows[row].channels[chan].label);
+ mci->csrows[row].channels[chan].label);
len -= chars;
pos += chars;
}
if (log_ue)
- printk(KERN_EMERG
- "EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d,"
- " labels \"%s\": %s\n", mci->mc_idx,
- page_frame_number, offset_in_page,
- mci->csrows[row].grain, row, labels, msg);
+ edac_mc_printk(mci, KERN_EMERG,
+ "UE page 0x%lx, offset 0x%lx, grain %d, row %d, "
+ "labels \"%s\": %s\n", page_frame_number,
+ offset_in_page, mci->csrows[row].grain, row, labels,
+ msg);
if (panic_on_ue)
- panic
- ("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d,"
- " labels \"%s\": %s\n", mci->mc_idx,
- page_frame_number, offset_in_page,
- mci->csrows[row].grain, row, labels, msg);
+ panic("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, "
+ "row %d, labels \"%s\": %s\n", mci->mc_idx,
+ page_frame_number, offset_in_page,
+ mci->csrows[row].grain, row, labels, msg);
mci->ue_count++;
mci->csrows[row].ue_count++;
}
+EXPORT_SYMBOL_GPL(edac_mc_handle_ue);
-
-EXPORT_SYMBOL(edac_mc_handle_ue_no_info);
-
-void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
- const char *msg)
+void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg)
{
if (panic_on_ue)
panic("EDAC MC%d: Uncorrected Error", mci->mc_idx);
if (log_ue)
- printk(KERN_WARNING
- "EDAC MC%d: UE - no information available: %s\n",
- mci->mc_idx, msg);
+ edac_mc_printk(mci, KERN_WARNING,
+ "UE - no information available: %s\n", msg);
mci->ue_noinfo_count++;
mci->ue_count++;
}
-
+EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info);
#ifdef CONFIG_PCI
@@ -1799,18 +1749,22 @@ static u16 get_pci_parity_status(struct pci_dev *dev, int secondary)
where = secondary ? PCI_SEC_STATUS : PCI_STATUS;
pci_read_config_word(dev, where, &status);
- /* If we get back 0xFFFF then we must suspect that the card has been pulled but
- the Linux PCI layer has not yet finished cleaning up. We don't want to report
- on such devices */
+ /* If we get back 0xFFFF then we must suspect that the card has been
+ * pulled but the Linux PCI layer has not yet finished cleaning up.
+ * We don't want to report on such devices
+ */
if (status == 0xFFFF) {
u32 sanity;
+
pci_read_config_dword(dev, 0, &sanity);
+
if (sanity == 0xFFFFFFFF)
return 0;
}
+
status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR |
- PCI_STATUS_PARITY;
+ PCI_STATUS_PARITY;
if (status)
/* reset only the bits we are interested in */
@@ -1822,7 +1776,7 @@ static u16 get_pci_parity_status(struct pci_dev *dev, int secondary)
typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev);
/* Clear any PCI parity errors logged by this device. */
-static void edac_pci_dev_parity_clear( struct pci_dev *dev )
+static void edac_pci_dev_parity_clear(struct pci_dev *dev)
{
u8 header_type;
@@ -1853,25 +1807,22 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
/* check the status reg for errors */
if (status) {
if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
- printk(KERN_CRIT
- "EDAC PCI- "
+ edac_printk(KERN_CRIT, EDAC_PCI,
"Signaled System Error on %s\n",
- pci_name (dev));
+ pci_name(dev));
if (status & (PCI_STATUS_PARITY)) {
- printk(KERN_CRIT
- "EDAC PCI- "
+ edac_printk(KERN_CRIT, EDAC_PCI,
"Master Data Parity Error on %s\n",
- pci_name (dev));
+ pci_name(dev));
atomic_inc(&pci_parity_count);
}
if (status & (PCI_STATUS_DETECTED_PARITY)) {
- printk(KERN_CRIT
- "EDAC PCI- "
+ edac_printk(KERN_CRIT, EDAC_PCI,
"Detected Parity Error on %s\n",
- pci_name (dev));
+ pci_name(dev));
atomic_inc(&pci_parity_count);
}
@@ -1892,25 +1843,22 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
/* check the secondary status reg for errors */
if (status) {
if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
- printk(KERN_CRIT
- "EDAC PCI-Bridge- "
+ edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
"Signaled System Error on %s\n",
- pci_name (dev));
+ pci_name(dev));
if (status & (PCI_STATUS_PARITY)) {
- printk(KERN_CRIT
- "EDAC PCI-Bridge- "
- "Master Data Parity Error on %s\n",
- pci_name (dev));
+ edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
+ "Master Data Parity Error on "
+ "%s\n", pci_name(dev));
atomic_inc(&pci_parity_count);
}
if (status & (PCI_STATUS_DETECTED_PARITY)) {
- printk(KERN_CRIT
- "EDAC PCI-Bridge- "
+ edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
"Detected Parity Error on %s\n",
- pci_name (dev));
+ pci_name(dev));
atomic_inc(&pci_parity_count);
}
@@ -1929,58 +1877,55 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
* Returns: 0 not found
* 1 found on list
*/
-static int check_dev_on_list(struct edac_pci_device_list *list, int free_index,
- struct pci_dev *dev)
-{
- int i;
- int rc = 0; /* Assume not found */
- unsigned short vendor=dev->vendor;
- unsigned short device=dev->device;
-
- /* Scan the list, looking for a vendor/device match
- */
- for (i = 0; i < free_index; i++, list++ ) {
- if ( (list->vendor == vendor ) &&
- (list->device == device )) {
- rc = 1;
- break;
- }
- }
+static int check_dev_on_list(struct edac_pci_device_list *list,
+ int free_index, struct pci_dev *dev)
+{
+ int i;
+ int rc = 0; /* Assume not found */
+ unsigned short vendor=dev->vendor;
+ unsigned short device=dev->device;
+
+ /* Scan the list, looking for a vendor/device match */
+ for (i = 0; i < free_index; i++, list++ ) {
+ if ((list->vendor == vendor ) && (list->device == device )) {
+ rc = 1;
+ break;
+ }
+ }
- return rc;
+ return rc;
}
/*
* pci_dev parity list iterator
- * Scan the PCI device list for one iteration, looking for SERRORs
+ * Scan the PCI device list for one iteration, looking for SERRORs
* Master Parity ERRORS or Parity ERRORs on primary or secondary devices
*/
static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn)
{
- struct pci_dev *dev=NULL;
+ struct pci_dev *dev = NULL;
/* request for kernel access to the next PCI device, if any,
* and while we are looking at it have its reference count
* bumped until we are done with it
*/
while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-
- /* if whitelist exists then it has priority, so only scan those
- * devices on the whitelist
- */
- if (pci_whitelist_count > 0 ) {
- if (check_dev_on_list(pci_whitelist,
+ /* if whitelist exists then it has priority, so only scan
+ * those devices on the whitelist
+ */
+ if (pci_whitelist_count > 0 ) {
+ if (check_dev_on_list(pci_whitelist,
pci_whitelist_count, dev))
fn(dev);
- } else {
+ } else {
/*
* if no whitelist, then check if this devices is
* blacklisted
*/
- if (!check_dev_on_list(pci_blacklist,
+ if (!check_dev_on_list(pci_blacklist,
pci_blacklist_count, dev))
fn(dev);
- }
+ }
}
}
@@ -1989,7 +1934,7 @@ static void do_pci_parity_check(void)
unsigned long flags;
int before_count;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
if (!check_pci_parity)
return;
@@ -2011,7 +1956,6 @@ static void do_pci_parity_check(void)
}
}
-
static inline void clear_pci_parity_errors(void)
{
/* Clear any PCI bus parity errors that devices initially have logged
@@ -2020,37 +1964,30 @@ static inline void clear_pci_parity_errors(void)
edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear);
}
-
#else /* CONFIG_PCI */
-
static inline void do_pci_parity_check(void)
{
/* no-op */
}
-
static inline void clear_pci_parity_errors(void)
{
/* no-op */
}
-
#endif /* CONFIG_PCI */
/*
* Iterate over all MC instances and check for ECC, et al, errors
*/
-static inline void check_mc_devices (void)
+static inline void check_mc_devices(void)
{
- unsigned long flags;
struct list_head *item;
struct mem_ctl_info *mci;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
-
- /* during poll, have interrupts off */
- local_irq_save(flags);
+ debugf3("%s()\n", __func__);
+ down(&mem_ctls_mutex);
list_for_each(item, &mc_devices) {
mci = list_entry(item, struct mem_ctl_info, link);
@@ -2059,10 +1996,9 @@ static inline void check_mc_devices (void)
mci->edac_check(mci);
}
- local_irq_restore(flags);
+ up(&mem_ctls_mutex);
}
-
/*
* Check MC status every poll_msec.
* Check PCI status every poll_msec as well.
@@ -2073,70 +2009,21 @@ static inline void check_mc_devices (void)
*/
static void do_edac_check(void)
{
-
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
-
+ debugf3("%s()\n", __func__);
check_mc_devices();
-
do_pci_parity_check();
}
-
-/*
- * EDAC thread state information
- */
-struct bs_thread_info
-{
- struct task_struct *task;
- struct completion *event;
- char *name;
- void (*run)(void);
-};
-
-static struct bs_thread_info bs_thread;
-
-/*
- * edac_kernel_thread
- * This the kernel thread that processes edac operations
- * in a normal thread environment
- */
static int edac_kernel_thread(void *arg)
{
- struct bs_thread_info *thread = (struct bs_thread_info *) arg;
-
- /* detach thread */
- daemonize(thread->name);
-
- current->exit_signal = SIGCHLD;
- allow_signal(SIGKILL);
- thread->task = current;
-
- /* indicate to starting task we have started */
- complete(thread->event);
-
- /* loop forever, until we are told to stop */
- while(thread->run != NULL) {
- void (*run)(void);
-
- /* call the function to check the memory controllers */
- run = thread->run;
- if (run)
- run();
-
- if (signal_pending(current))
- flush_signals(current);
-
- /* ensure we are interruptable */
- set_current_state(TASK_INTERRUPTIBLE);
+ while (!kthread_should_stop()) {
+ do_edac_check();
/* goto sleep for the interval */
- schedule_timeout((HZ * poll_msec) / 1000);
+ schedule_timeout_interruptible((HZ * poll_msec) / 1000);
try_to_freeze();
}
- /* notify waiter that we are exiting */
- complete(thread->event);
-
return 0;
}
@@ -2146,10 +2033,7 @@ static int edac_kernel_thread(void *arg)
*/
static int __init edac_mc_init(void)
{
- int ret;
- struct completion event;
-
- printk(KERN_INFO "MC: " __FILE__ " version " EDAC_MC_VERSION "\n");
+ edac_printk(KERN_INFO, EDAC_MC, EDAC_MC_VERSION "\n");
/*
* Harvest and clear any boot/initialization PCI parity errors
@@ -2160,80 +2044,54 @@ static int __init edac_mc_init(void)
*/
clear_pci_parity_errors();
- /* perform check for first time to harvest boot leftovers */
- do_edac_check();
-
- /* Create the MC sysfs entires */
+ /* Create the MC sysfs entries */
if (edac_sysfs_memctrl_setup()) {
- printk(KERN_ERR "EDAC MC: Error initializing sysfs code\n");
+ edac_printk(KERN_ERR, EDAC_MC,
+ "Error initializing sysfs code\n");
return -ENODEV;
}
/* Create the PCI parity sysfs entries */
if (edac_sysfs_pci_setup()) {
edac_sysfs_memctrl_teardown();
- printk(KERN_ERR "EDAC PCI: Error initializing sysfs code\n");
+ edac_printk(KERN_ERR, EDAC_MC,
+ "EDAC PCI: Error initializing sysfs code\n");
return -ENODEV;
}
- /* Create our kernel thread */
- init_completion(&event);
- bs_thread.event = &event;
- bs_thread.name = "kedac";
- bs_thread.run = do_edac_check;
-
/* create our kernel thread */
- ret = kernel_thread(edac_kernel_thread, &bs_thread, CLONE_KERNEL);
- if (ret < 0) {
+ edac_thread = kthread_run(edac_kernel_thread, NULL, "kedac");
+
+ if (IS_ERR(edac_thread)) {
/* remove the sysfs entries */
edac_sysfs_memctrl_teardown();
edac_sysfs_pci_teardown();
- return -ENOMEM;
+ return PTR_ERR(edac_thread);
}
- /* wait for our kernel theard ack that it is up and running */
- wait_for_completion(&event);
-
return 0;
}
-
/*
* edac_mc_exit()
* module exit/termination functioni
*/
static void __exit edac_mc_exit(void)
{
- struct completion event;
-
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
-
- init_completion(&event);
- bs_thread.event = &event;
-
- /* As soon as ->run is set to NULL, the task could disappear,
- * so we need to hold tasklist_lock until we have sent the signal
- */
- read_lock(&tasklist_lock);
- bs_thread.run = NULL;
- send_sig(SIGKILL, bs_thread.task, 1);
- read_unlock(&tasklist_lock);
- wait_for_completion(&event);
+ debugf0("%s()\n", __func__);
+ kthread_stop(edac_thread);
/* tear down the sysfs device */
edac_sysfs_memctrl_teardown();
edac_sysfs_pci_teardown();
}
-
-
-
module_init(edac_mc_init);
module_exit(edac_mc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
- "Based on.work by Dan Hollis et al");
+ "Based on work by Dan Hollis et al");
MODULE_DESCRIPTION("Core library routines for MC reporting");
module_param(panic_on_ue, int, 0644);
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
index 75ecf484a43..8d9e83909b9 100644
--- a/drivers/edac/edac_mc.h
+++ b/drivers/edac/edac_mc.h
@@ -15,11 +15,9 @@
*
*/
-
#ifndef _EDAC_MC_H_
#define _EDAC_MC_H_
-
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -33,7 +31,6 @@
#include <linux/completion.h>
#include <linux/kobject.h>
-
#define EDAC_MC_LABEL_LEN 31
#define MC_PROC_NAME_MAX_LEN 7
@@ -43,31 +40,53 @@
#define PAGES_TO_MiB( pages ) ( ( pages ) << ( PAGE_SHIFT - 20 ) )
#endif
+#define edac_printk(level, prefix, fmt, arg...) \
+ printk(level "EDAC " prefix ": " fmt, ##arg)
+
+#define edac_mc_printk(mci, level, fmt, arg...) \
+ printk(level "EDAC MC%d: " fmt, mci->mc_idx, ##arg)
+
+#define edac_mc_chipset_printk(mci, level, prefix, fmt, arg...) \
+ printk(level "EDAC " prefix " MC%d: " fmt, mci->mc_idx, ##arg)
+
+/* prefixes for edac_printk() and edac_mc_printk() */
+#define EDAC_MC "MC"
+#define EDAC_PCI "PCI"
+#define EDAC_DEBUG "DEBUG"
+
#ifdef CONFIG_EDAC_DEBUG
extern int edac_debug_level;
-#define edac_debug_printk(level, fmt, args...) \
-do { if (level <= edac_debug_level) printk(KERN_DEBUG fmt, ##args); } while(0)
+
+#define edac_debug_printk(level, fmt, arg...) \
+ do { \
+ if (level <= edac_debug_level) \
+ edac_printk(KERN_DEBUG, EDAC_DEBUG, fmt, ##arg); \
+ } while(0)
+
#define debugf0( ... ) edac_debug_printk(0, __VA_ARGS__ )
#define debugf1( ... ) edac_debug_printk(1, __VA_ARGS__ )
#define debugf2( ... ) edac_debug_printk(2, __VA_ARGS__ )
#define debugf3( ... ) edac_debug_printk(3, __VA_ARGS__ )
#define debugf4( ... ) edac_debug_printk(4, __VA_ARGS__ )
-#else /* !CONFIG_EDAC_DEBUG */
+
+#else /* !CONFIG_EDAC_DEBUG */
+
#define debugf0( ... )
#define debugf1( ... )
#define debugf2( ... )
#define debugf3( ... )
#define debugf4( ... )
-#endif /* !CONFIG_EDAC_DEBUG */
+#endif /* !CONFIG_EDAC_DEBUG */
-#define bs_xstr(s) bs_str(s)
-#define bs_str(s) #s
-#define BS_MOD_STR bs_xstr(KBUILD_BASENAME)
+#define edac_xstr(s) edac_str(s)
+#define edac_str(s) #s
+#define EDAC_MOD_STR edac_xstr(KBUILD_BASENAME)
#define BIT(x) (1 << (x))
-#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, PCI_DEVICE_ID_ ## vend ## _ ## dev
+#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \
+ PCI_DEVICE_ID_ ## vend ## _ ## dev
/* memory devices */
enum dev_type {
@@ -117,7 +136,6 @@ enum mem_type {
#define MEM_FLAG_RDDR BIT(MEM_RDDR)
#define MEM_FLAG_RMBS BIT(MEM_RMBS)
-
/* chipset Error Detection and Correction capabilities and mode */
enum edac_type {
EDAC_UNKNOWN = 0, /* Unknown if ECC is available */
@@ -142,7 +160,6 @@ enum edac_type {
#define EDAC_FLAG_S8ECD8ED BIT(EDAC_S8ECD8ED)
#define EDAC_FLAG_S16ECD16ED BIT(EDAC_S16ECD16ED)
-
/* scrubbing capabilities */
enum scrub_type {
SCRUB_UNKNOWN = 0, /* Unknown if scrubber is available */
@@ -166,11 +183,6 @@ enum scrub_type {
#define SCRUB_FLAG_HW_PROG_SRC BIT(SCRUB_HW_PROG_SRC_CORR)
#define SCRUB_FLAG_HW_TUN BIT(SCRUB_HW_TUNABLE)
-enum mci_sysfs_status {
- MCI_SYSFS_INACTIVE = 0, /* sysfs entries NOT registered */
- MCI_SYSFS_ACTIVE /* sysfs entries ARE registered */
-};
-
/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */
/*
@@ -255,20 +267,19 @@ enum mci_sysfs_status {
* PS - I enjoyed writing all that about as much as you enjoyed reading it.
*/
-
struct channel_info {
int chan_idx; /* channel index */
u32 ce_count; /* Correctable Errors for this CHANNEL */
- char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */
+ char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */
struct csrow_info *csrow; /* the parent */
};
-
struct csrow_info {
unsigned long first_page; /* first page number in dimm */
unsigned long last_page; /* last page number in dimm */
unsigned long page_mask; /* used for interleaving -
- 0UL for non intlv */
+ * 0UL for non intlv
+ */
u32 nr_pages; /* number of pages in csrow */
u32 grain; /* granularity of reported error in bytes */
int csrow_idx; /* the chip-select row */
@@ -280,29 +291,28 @@ struct csrow_info {
struct mem_ctl_info *mci; /* the parent */
struct kobject kobj; /* sysfs kobject for this csrow */
+ struct completion kobj_complete;
/* FIXME the number of CHANNELs might need to become dynamic */
u32 nr_channels;
struct channel_info *channels;
};
-
struct mem_ctl_info {
struct list_head link; /* for global list of mem_ctl_info structs */
unsigned long mtype_cap; /* memory types supported by mc */
unsigned long edac_ctl_cap; /* Mem controller EDAC capabilities */
unsigned long edac_cap; /* configuration capabilities - this is
- closely related to edac_ctl_cap. The
- difference is that the controller
- may be capable of s4ecd4ed which would
- be listed in edac_ctl_cap, but if
- channels aren't capable of s4ecd4ed then the
- edac_cap would not have that capability. */
+ * closely related to edac_ctl_cap. The
+ * difference is that the controller may be
+ * capable of s4ecd4ed which would be listed
+ * in edac_ctl_cap, but if channels aren't
+ * capable of s4ecd4ed then the edac_cap would
+ * not have that capability.
+ */
unsigned long scrub_cap; /* chipset scrub capabilities */
enum scrub_type scrub_mode; /* current scrub mode */
- enum mci_sysfs_status sysfs_active; /* status of sysfs */
-
/* pointer to edac checking routine */
void (*edac_check) (struct mem_ctl_info * mci);
/*
@@ -311,7 +321,7 @@ struct mem_ctl_info {
*/
/* FIXME - why not send the phys page to begin with? */
unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci,
- unsigned long page);
+ unsigned long page);
int mc_idx;
int nr_csrows;
struct csrow_info *csrows;
@@ -340,72 +350,69 @@ struct mem_ctl_info {
/* edac sysfs device control */
struct kobject edac_mci_kobj;
+ struct completion kobj_complete;
};
-
-
/* write all or some bits in a byte-register*/
-static inline void pci_write_bits8(struct pci_dev *pdev, int offset,
- u8 value, u8 mask)
+static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value,
+ u8 mask)
{
if (mask != 0xff) {
u8 buf;
+
pci_read_config_byte(pdev, offset, &buf);
value &= mask;
buf &= ~mask;
value |= buf;
}
+
pci_write_config_byte(pdev, offset, value);
}
-
/* write all or some bits in a word-register*/
static inline void pci_write_bits16(struct pci_dev *pdev, int offset,
- u16 value, u16 mask)
+ u16 value, u16 mask)
{
if (mask != 0xffff) {
u16 buf;
+
pci_read_config_word(pdev, offset, &buf);
value &= mask;
buf &= ~mask;
value |= buf;
}
+
pci_write_config_word(pdev, offset, value);
}
-
/* write all or some bits in a dword-register*/
static inline void pci_write_bits32(struct pci_dev *pdev, int offset,
- u32 value, u32 mask)
+ u32 value, u32 mask)
{
if (mask != 0xffff) {
u32 buf;
+
pci_read_config_dword(pdev, offset, &buf);
value &= mask;
buf &= ~mask;
value |= buf;
}
+
pci_write_config_dword(pdev, offset, value);
}
-
#ifdef CONFIG_EDAC_DEBUG
void edac_mc_dump_channel(struct channel_info *chan);
void edac_mc_dump_mci(struct mem_ctl_info *mci);
void edac_mc_dump_csrow(struct csrow_info *csrow);
-#endif /* CONFIG_EDAC_DEBUG */
+#endif /* CONFIG_EDAC_DEBUG */
extern int edac_mc_add_mc(struct mem_ctl_info *mci);
-extern int edac_mc_del_mc(struct mem_ctl_info *mci);
-
+extern struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev);
extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
- unsigned long page);
-
-extern struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev
- *pdev);
-
-extern void edac_mc_scrub_block(unsigned long page,
- unsigned long offset, u32 size);
+ unsigned long page);
+extern void edac_mc_scrub_block(unsigned long page, unsigned long offset,
+ u32 size);
/*
* The no info errors are used when error overflows are reported.
@@ -418,31 +425,25 @@ extern void edac_mc_scrub_block(unsigned long page,
* statement clutter and extra function arguments.
*/
extern void edac_mc_handle_ce(struct mem_ctl_info *mci,
- unsigned long page_frame_number,
- unsigned long offset_in_page,
- unsigned long syndrome,
- int row, int channel, const char *msg);
-
+ unsigned long page_frame_number, unsigned long offset_in_page,
+ unsigned long syndrome, int row, int channel,
+ const char *msg);
extern void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci,
- const char *msg);
-
+ const char *msg);
extern void edac_mc_handle_ue(struct mem_ctl_info *mci,
- unsigned long page_frame_number,
- unsigned long offset_in_page,
- int row, const char *msg);
-
+ unsigned long page_frame_number, unsigned long offset_in_page,
+ int row, const char *msg);
extern void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
- const char *msg);
+ const char *msg);
/*
* This kmalloc's and initializes all the structures.
* Can't be used if all structures don't have the same lifetime.
*/
-extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt,
- unsigned nr_csrows, unsigned nr_chans);
+extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
+ unsigned nr_chans);
/* Free an mc previously allocated by edac_mc_alloc() */
extern void edac_mc_free(struct mem_ctl_info *mci);
-
#endif /* _EDAC_MC_H_ */
diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c
index 52596e75f9c..fd342163cf9 100644
--- a/drivers/edac/i82860_edac.c
+++ b/drivers/edac/i82860_edac.c
@@ -9,7 +9,6 @@
* by Thayne Harbaugh of Linux Networx. (http://lnxi.com)
*/
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -18,6 +17,11 @@
#include <linux/slab.h>
#include "edac_mc.h"
+#define i82860_printk(level, fmt, arg...) \
+ edac_printk(level, "i82860", fmt, ##arg)
+
+#define i82860_mc_printk(mci, level, fmt, arg...) \
+ edac_mc_chipset_printk(mci, level, "i82860", fmt, ##arg)
#ifndef PCI_DEVICE_ID_INTEL_82860_0
#define PCI_DEVICE_ID_INTEL_82860_0 0x2531
@@ -48,15 +52,15 @@ struct i82860_error_info {
static const struct i82860_dev_info i82860_devs[] = {
[I82860] = {
- .ctl_name = "i82860"},
+ .ctl_name = "i82860"
+ },
};
static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code
- has already registered driver */
+ * has already registered driver
+ */
-static int i82860_registered = 1;
-
-static void i82860_get_error_info (struct mem_ctl_info *mci,
+static void i82860_get_error_info(struct mem_ctl_info *mci,
struct i82860_error_info *info)
{
/*
@@ -78,14 +82,15 @@ static void i82860_get_error_info (struct mem_ctl_info *mci,
*/
if (!(info->errsts2 & 0x0003))
return;
+
if ((info->errsts ^ info->errsts2) & 0x0003) {
pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap);
pci_read_config_word(mci->pdev, I82860_DERRCTL_STS,
- &info->derrsyn);
+ &info->derrsyn);
}
}
-static int i82860_process_error_info (struct mem_ctl_info *mci,
+static int i82860_process_error_info(struct mem_ctl_info *mci,
struct i82860_error_info *info, int handle_errors)
{
int row;
@@ -107,8 +112,8 @@ static int i82860_process_error_info (struct mem_ctl_info *mci,
if (info->errsts & 0x0002)
edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE");
else
- edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
- 0, "i82860 UE");
+ edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, 0,
+ "i82860 UE");
return 1;
}
@@ -117,7 +122,7 @@ static void i82860_check(struct mem_ctl_info *mci)
{
struct i82860_error_info info;
- debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ debugf1("MC%d: %s()\n", mci->mc_idx, __func__);
i82860_get_error_info(mci, &info);
i82860_process_error_info(mci, &info, 1);
}
@@ -128,6 +133,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
int index;
struct mem_ctl_info *mci = NULL;
unsigned long last_cumul_size;
+ struct i82860_error_info discard;
u16 mchcfg_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
@@ -140,21 +146,20 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
going to make 1 channel for group.
*/
mci = edac_mc_alloc(0, 16, 1);
+
if (!mci)
return -ENOMEM;
- debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
-
+ debugf3("%s(): init mci\n", __func__);
mci->pdev = pdev;
mci->mtype_cap = MEM_FLAG_DDR;
-
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
/* I"m not sure about this but I think that all RDRAM is SECDED */
mci->edac_cap = EDAC_FLAG_SECDED;
/* adjust FLAGS */
- mci->mod_name = BS_MOD_STR;
+ mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = "$Revision: 1.1.2.6 $";
mci->ctl_name = i82860_devs[dev_idx].ctl_name;
mci->edac_check = i82860_check;
@@ -175,12 +180,13 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
struct csrow_info *csrow = &mci->csrows[index];
pci_read_config_word(mci->pdev, I82860_GBA + index * 2,
- &value);
+ &value);
cumul_size = (value & I82860_GBA_MASK) <<
(I82860_GBA_SHIFT - PAGE_SHIFT);
- debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
- __func__, index, cumul_size);
+ debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
+ cumul_size);
+
if (cumul_size == last_cumul_size)
continue; /* not populated */
@@ -188,42 +194,43 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
csrow->last_page = cumul_size - 1;
csrow->nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;
- csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
+ csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
csrow->mtype = MEM_RMBS;
csrow->dtype = DEV_UNKNOWN;
csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
}
- /* clear counters */
- pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003);
+ i82860_get_error_info(mci, &discard); /* clear counters */
if (edac_mc_add_mc(mci)) {
- debugf3("MC: " __FILE__
- ": %s(): failed edac_mc_add_mc()\n",
- __func__);
+ debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
edac_mc_free(mci);
} else {
/* get this far and it's successful */
- debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ debugf3("%s(): success\n", __func__);
rc = 0;
}
+
return rc;
}
/* returns count (>= 0), or negative on error */
static int __devinit i82860_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *ent)
{
int rc;
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
+ debugf0("%s()\n", __func__);
+ i82860_printk(KERN_INFO, "i82860 init one\n");
- printk(KERN_INFO "i82860 init one\n");
- if(pci_enable_device(pdev) < 0)
+ if (pci_enable_device(pdev) < 0)
return -EIO;
+
rc = i82860_probe1(pdev, ent->driver_data);
- if(rc == 0)
+
+ if (rc == 0)
mci_pdev = pci_dev_get(pdev);
+
return rc;
}
@@ -231,23 +238,28 @@ static void __devexit i82860_remove_one(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
- debugf0(__FILE__ ": %s()\n", __func__);
+ debugf0("%s()\n", __func__);
- mci = edac_mc_find_mci_by_pdev(pdev);
- if ((mci != NULL) && (edac_mc_del_mc(mci) == 0))
- edac_mc_free(mci);
+ if ((mci = edac_mc_del_mc(pdev)) == NULL)
+ return;
+
+ edac_mc_free(mci);
}
static const struct pci_device_id i82860_pci_tbl[] __devinitdata = {
- {PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- I82860},
- {0,} /* 0 terminated list. */
+ {
+ PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ I82860
+ },
+ {
+ 0,
+ } /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, i82860_pci_tbl);
static struct pci_driver i82860_driver = {
- .name = BS_MOD_STR,
+ .name = EDAC_MOD_STR,
.probe = i82860_init_one,
.remove = __devexit_p(i82860_remove_one),
.id_table = i82860_pci_tbl,
@@ -257,43 +269,56 @@ static int __init i82860_init(void)
{
int pci_rc;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
+
if ((pci_rc = pci_register_driver(&i82860_driver)) < 0)
- return pci_rc;
+ goto fail0;
if (!mci_pdev) {
- i82860_registered = 0;
mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82860_0, NULL);
+ PCI_DEVICE_ID_INTEL_82860_0, NULL);
+
if (mci_pdev == NULL) {
debugf0("860 pci_get_device fail\n");
- return -ENODEV;
+ pci_rc = -ENODEV;
+ goto fail1;
}
+
pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl);
+
if (pci_rc < 0) {
debugf0("860 init fail\n");
- pci_dev_put(mci_pdev);
- return -ENODEV;
+ pci_rc = -ENODEV;
+ goto fail1;
}
}
+
return 0;
+
+fail1:
+ pci_unregister_driver(&i82860_driver);
+
+fail0:
+ if (mci_pdev != NULL)
+ pci_dev_put(mci_pdev);
+
+ return pci_rc;
}
static void __exit i82860_exit(void)
{
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
pci_unregister_driver(&i82860_driver);
- if (!i82860_registered) {
- i82860_remove_one(mci_pdev);
+
+ if (mci_pdev != NULL)
pci_dev_put(mci_pdev);
- }
}
module_init(i82860_init);
module_exit(i82860_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR
- ("Red Hat Inc. (http://www.redhat.com.com) Ben Woodard <woodard@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) "
+ "Ben Woodard <woodard@redhat.com>");
MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
index 1991f94af75..0aec92698f1 100644
--- a/drivers/edac/i82875p_edac.c
+++ b/drivers/edac/i82875p_edac.c
@@ -13,18 +13,19 @@
* Note: E7210 appears same as D82875P - zhenyu.z.wang at intel.com
*/
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
-
#include <linux/pci.h>
#include <linux/pci_ids.h>
-
#include <linux/slab.h>
-
#include "edac_mc.h"
+#define i82875p_printk(level, fmt, arg...) \
+ edac_printk(level, "i82875p", fmt, ##arg)
+
+#define i82875p_mc_printk(mci, level, fmt, arg...) \
+ edac_mc_chipset_printk(mci, level, "i82875p", fmt, ##arg)
#ifndef PCI_DEVICE_ID_INTEL_82875_0
#define PCI_DEVICE_ID_INTEL_82875_0 0x2578
@@ -34,11 +35,9 @@
#define PCI_DEVICE_ID_INTEL_82875_6 0x257e
#endif /* PCI_DEVICE_ID_INTEL_82875_6 */
-
/* four csrows in dual channel, eight in single channel */
#define I82875P_NR_CSROWS(nr_chans) (8/(nr_chans))
-
/* Intel 82875p register addresses - device 0 function 0 - DRAM Controller */
#define I82875P_EAP 0x58 /* Error Address Pointer (32b)
*
@@ -87,7 +86,6 @@
* 0 reserved
*/
-
/* Intel 82875p register addresses - device 6 function 0 - DRAM Controller */
#define I82875P_PCICMD6 0x04 /* PCI Command Register (16b)
*
@@ -151,23 +149,19 @@
* 1:0 DRAM type 01=DDR
*/
-
enum i82875p_chips {
I82875P = 0,
};
-
struct i82875p_pvt {
struct pci_dev *ovrfl_pdev;
void __iomem *ovrfl_window;
};
-
struct i82875p_dev_info {
const char *ctl_name;
};
-
struct i82875p_error_info {
u16 errsts;
u32 eap;
@@ -176,17 +170,19 @@ struct i82875p_error_info {
u16 errsts2;
};
-
static const struct i82875p_dev_info i82875p_devs[] = {
[I82875P] = {
- .ctl_name = "i82875p"},
+ .ctl_name = "i82875p"
+ },
};
-static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code
- has already registered driver */
+static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code has
+ * already registered driver
+ */
+
static int i82875p_registered = 1;
-static void i82875p_get_error_info (struct mem_ctl_info *mci,
+static void i82875p_get_error_info(struct mem_ctl_info *mci,
struct i82875p_error_info *info)
{
/*
@@ -210,15 +206,16 @@ static void i82875p_get_error_info (struct mem_ctl_info *mci,
*/
if (!(info->errsts2 & 0x0081))
return;
+
if ((info->errsts ^ info->errsts2) & 0x0081) {
pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap);
pci_read_config_byte(mci->pdev, I82875P_DES, &info->des);
pci_read_config_byte(mci->pdev, I82875P_DERRSYN,
- &info->derrsyn);
+ &info->derrsyn);
}
}
-static int i82875p_process_error_info (struct mem_ctl_info *mci,
+static int i82875p_process_error_info(struct mem_ctl_info *mci,
struct i82875p_error_info *info, int handle_errors)
{
int row, multi_chan;
@@ -243,23 +240,21 @@ static int i82875p_process_error_info (struct mem_ctl_info *mci,
edac_mc_handle_ue(mci, info->eap, 0, row, "i82875p UE");
else
edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
- multi_chan ? (info->des & 0x1) : 0,
- "i82875p CE");
+ multi_chan ? (info->des & 0x1) : 0,
+ "i82875p CE");
return 1;
}
-
static void i82875p_check(struct mem_ctl_info *mci)
{
struct i82875p_error_info info;
- debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ debugf1("MC%d: %s()\n", mci->mc_idx, __func__);
i82875p_get_error_info(mci, &info);
i82875p_process_error_info(mci, &info, 1);
}
-
#ifdef CONFIG_PROC_FS
extern int pci_proc_attach_device(struct pci_dev *);
#endif
@@ -273,15 +268,14 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
unsigned long last_cumul_size;
struct pci_dev *ovrfl_pdev;
void __iomem *ovrfl_window = NULL;
-
u32 drc;
u32 drc_chan; /* Number of channels 0=1chan,1=2chan */
u32 nr_chans;
u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+ struct i82875p_error_info discard;
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
-
- ovrfl_pdev = pci_find_device(PCI_VEND_DEV(INTEL, 82875_6), NULL);
+ debugf0("%s()\n", __func__);
+ ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL);
if (!ovrfl_pdev) {
/*
@@ -292,71 +286,69 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
*/
pci_write_bits8(pdev, 0xf4, 0x2, 0x2);
ovrfl_pdev =
- pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0));
+ pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0));
+
if (!ovrfl_pdev)
- goto fail;
+ return -ENODEV;
}
+
#ifdef CONFIG_PROC_FS
if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) {
- printk(KERN_ERR "MC: " __FILE__
- ": %s(): Failed to attach overflow device\n",
- __func__);
- goto fail;
+ i82875p_printk(KERN_ERR,
+ "%s(): Failed to attach overflow device\n", __func__);
+ return -ENODEV;
}
-#endif /* CONFIG_PROC_FS */
+#endif
+ /* CONFIG_PROC_FS */
if (pci_enable_device(ovrfl_pdev)) {
- printk(KERN_ERR "MC: " __FILE__
- ": %s(): Failed to enable overflow device\n",
- __func__);
- goto fail;
+ i82875p_printk(KERN_ERR,
+ "%s(): Failed to enable overflow device\n", __func__);
+ return -ENODEV;
}
if (pci_request_regions(ovrfl_pdev, pci_name(ovrfl_pdev))) {
#ifdef CORRECT_BIOS
- goto fail;
+ goto fail0;
#endif
}
+
/* cache is irrelevant for PCI bus reads/writes */
ovrfl_window = ioremap_nocache(pci_resource_start(ovrfl_pdev, 0),
- pci_resource_len(ovrfl_pdev, 0));
+ pci_resource_len(ovrfl_pdev, 0));
if (!ovrfl_window) {
- printk(KERN_ERR "MC: " __FILE__
- ": %s(): Failed to ioremap bar6\n", __func__);
- goto fail;
+ i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n",
+ __func__);
+ goto fail1;
}
/* need to find out the number of channels */
drc = readl(ovrfl_window + I82875P_DRC);
drc_chan = ((drc >> 21) & 0x1);
nr_chans = drc_chan + 1;
- drc_ddim = (drc >> 18) & 0x1;
+ drc_ddim = (drc >> 18) & 0x1;
mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans),
- nr_chans);
+ nr_chans);
if (!mci) {
rc = -ENOMEM;
- goto fail;
+ goto fail2;
}
- debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
-
+ debugf3("%s(): init mci\n", __func__);
mci->pdev = pdev;
mci->mtype_cap = MEM_FLAG_DDR;
-
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
mci->edac_cap = EDAC_FLAG_UNKNOWN;
/* adjust FLAGS */
- mci->mod_name = BS_MOD_STR;
+ mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = "$Revision: 1.5.2.11 $";
mci->ctl_name = i82875p_devs[dev_idx].ctl_name;
mci->edac_check = i82875p_check;
mci->ctl_page_to_phys = NULL;
-
- debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
-
+ debugf3("%s(): init pvt\n", __func__);
pvt = (struct i82875p_pvt *) mci->pvt_info;
pvt->ovrfl_pdev = ovrfl_pdev;
pvt->ovrfl_window = ovrfl_window;
@@ -374,8 +366,9 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
value = readb(ovrfl_window + I82875P_DRB + index);
cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT);
- debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
- __func__, index, cumul_size);
+ debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
+ cumul_size);
+
if (cumul_size == last_cumul_size)
continue; /* not populated */
@@ -383,71 +376,72 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
csrow->last_page = cumul_size - 1;
csrow->nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;
- csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */
+ csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */
csrow->mtype = MEM_DDR;
csrow->dtype = DEV_UNKNOWN;
csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE;
}
- /* clear counters */
- pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081);
+ i82875p_get_error_info(mci, &discard); /* clear counters */
if (edac_mc_add_mc(mci)) {
- debugf3("MC: " __FILE__
- ": %s(): failed edac_mc_add_mc()\n", __func__);
- goto fail;
+ debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
+ goto fail3;
}
/* get this far and it's successful */
- debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ debugf3("%s(): success\n", __func__);
return 0;
- fail:
- if (mci)
- edac_mc_free(mci);
+fail3:
+ edac_mc_free(mci);
- if (ovrfl_window)
- iounmap(ovrfl_window);
+fail2:
+ iounmap(ovrfl_window);
- if (ovrfl_pdev) {
- pci_release_regions(ovrfl_pdev);
- pci_disable_device(ovrfl_pdev);
- }
+fail1:
+ pci_release_regions(ovrfl_pdev);
+#ifdef CORRECT_BIOS
+fail0:
+#endif
+ pci_disable_device(ovrfl_pdev);
/* NOTE: the ovrfl proc entry and pci_dev are intentionally left */
return rc;
}
-
/* returns count (>= 0), or negative on error */
static int __devinit i82875p_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *ent)
{
int rc;
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
+ debugf0("%s()\n", __func__);
+ i82875p_printk(KERN_INFO, "i82875p init one\n");
- printk(KERN_INFO "i82875p init one\n");
- if(pci_enable_device(pdev) < 0)
+ if (pci_enable_device(pdev) < 0)
return -EIO;
+
rc = i82875p_probe1(pdev, ent->driver_data);
+
if (mci_pdev == NULL)
mci_pdev = pci_dev_get(pdev);
+
return rc;
}
-
static void __devexit i82875p_remove_one(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
struct i82875p_pvt *pvt = NULL;
- debugf0(__FILE__ ": %s()\n", __func__);
+ debugf0("%s()\n", __func__);
- if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+ if ((mci = edac_mc_del_mc(pdev)) == NULL)
return;
pvt = (struct i82875p_pvt *) mci->pvt_info;
+
if (pvt->ovrfl_window)
iounmap(pvt->ovrfl_window);
@@ -459,74 +453,84 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev)
pci_dev_put(pvt->ovrfl_pdev);
}
- if (edac_mc_del_mc(mci))
- return;
-
edac_mc_free(mci);
}
-
static const struct pci_device_id i82875p_pci_tbl[] __devinitdata = {
- {PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- I82875P},
- {0,} /* 0 terminated list. */
+ {
+ PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ I82875P
+ },
+ {
+ 0,
+ } /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl);
-
static struct pci_driver i82875p_driver = {
- .name = BS_MOD_STR,
+ .name = EDAC_MOD_STR,
.probe = i82875p_init_one,
.remove = __devexit_p(i82875p_remove_one),
.id_table = i82875p_pci_tbl,
};
-
static int __init i82875p_init(void)
{
int pci_rc;
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
pci_rc = pci_register_driver(&i82875p_driver);
+
if (pci_rc < 0)
- return pci_rc;
+ goto fail0;
+
if (mci_pdev == NULL) {
- i82875p_registered = 0;
- mci_pdev =
- pci_get_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82875_0, NULL);
+ mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82875_0, NULL);
+
if (!mci_pdev) {
debugf0("875p pci_get_device fail\n");
- return -ENODEV;
+ pci_rc = -ENODEV;
+ goto fail1;
}
+
pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl);
+
if (pci_rc < 0) {
debugf0("875p init fail\n");
- pci_dev_put(mci_pdev);
- return -ENODEV;
+ pci_rc = -ENODEV;
+ goto fail1;
}
}
+
return 0;
-}
+fail1:
+ pci_unregister_driver(&i82875p_driver);
+
+fail0:
+ if (mci_pdev != NULL)
+ pci_dev_put(mci_pdev);
+
+ return pci_rc;
+}
static void __exit i82875p_exit(void)
{
- debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ debugf3("%s()\n", __func__);
pci_unregister_driver(&i82875p_driver);
+
if (!i82875p_registered) {
i82875p_remove_one(mci_pdev);
pci_dev_put(mci_pdev);
}
}
-
module_init(i82875p_init);
module_exit(i82875p_exit);
-
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
MODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers");
diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c
index e90892831b9..2c29fafe67c 100644
--- a/drivers/edac/r82600_edac.c
+++ b/drivers/edac/r82600_edac.c
@@ -18,14 +18,17 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
-
#include <linux/pci.h>
#include <linux/pci_ids.h>
-
#include <linux/slab.h>
-
#include "edac_mc.h"
+#define r82600_printk(level, fmt, arg...) \
+ edac_printk(level, "r82600", fmt, ##arg)
+
+#define r82600_mc_printk(mci, level, fmt, arg...) \
+ edac_mc_chipset_printk(mci, level, "r82600", fmt, ##arg)
+
/* Radisys say "The 82600 integrates a main memory SDRAM controller that
* supports up to four banks of memory. The four banks can support a mix of
* sizes of 64 bit wide (72 bits with ECC) Synchronous DRAM (SDRAM) DIMMs,
@@ -126,10 +129,8 @@ struct r82600_error_info {
u32 eapr;
};
-
static unsigned int disable_hardware_scrub = 0;
-
static void r82600_get_error_info (struct mem_ctl_info *mci,
struct r82600_error_info *info)
{
@@ -138,17 +139,16 @@ static void r82600_get_error_info (struct mem_ctl_info *mci,
if (info->eapr & BIT(0))
/* Clear error to allow next error to be reported [p.62] */
pci_write_bits32(mci->pdev, R82600_EAP,
- ((u32) BIT(0) & (u32) BIT(1)),
- ((u32) BIT(0) & (u32) BIT(1)));
+ ((u32) BIT(0) & (u32) BIT(1)),
+ ((u32) BIT(0) & (u32) BIT(1)));
if (info->eapr & BIT(1))
/* Clear error to allow next error to be reported [p.62] */
pci_write_bits32(mci->pdev, R82600_EAP,
- ((u32) BIT(0) & (u32) BIT(1)),
- ((u32) BIT(0) & (u32) BIT(1)));
+ ((u32) BIT(0) & (u32) BIT(1)),
+ ((u32) BIT(0) & (u32) BIT(1)));
}
-
static int r82600_process_error_info (struct mem_ctl_info *mci,
struct r82600_error_info *info, int handle_errors)
{
@@ -167,26 +167,25 @@ static int r82600_process_error_info (struct mem_ctl_info *mci,
* granularity (upper 19 bits only) */
page = eapaddr >> PAGE_SHIFT;
- if (info->eapr & BIT(0)) { /* CE? */
+ if (info->eapr & BIT(0)) { /* CE? */
error_found = 1;
if (handle_errors)
- edac_mc_handle_ce(
- mci, page, 0, /* not avail */
- syndrome,
- edac_mc_find_csrow_by_page(mci, page),
- 0, /* channel */
- mci->ctl_name);
+ edac_mc_handle_ce(mci, page, 0, /* not avail */
+ syndrome,
+ edac_mc_find_csrow_by_page(mci, page),
+ 0, /* channel */
+ mci->ctl_name);
}
- if (info->eapr & BIT(1)) { /* UE? */
+ if (info->eapr & BIT(1)) { /* UE? */
error_found = 1;
if (handle_errors)
/* 82600 doesn't give enough info */
edac_mc_handle_ue(mci, page, 0,
- edac_mc_find_csrow_by_page(mci, page),
- mci->ctl_name);
+ edac_mc_find_csrow_by_page(mci, page),
+ mci->ctl_name);
}
return error_found;
@@ -196,7 +195,7 @@ static void r82600_check(struct mem_ctl_info *mci)
{
struct r82600_error_info info;
- debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ debugf1("MC%d: %s()\n", mci->mc_idx, __func__);
r82600_get_error_info(mci, &info);
r82600_process_error_info(mci, &info, 1);
}
@@ -213,25 +212,18 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
u32 scrub_disabled;
u32 sdram_refresh_rate;
u32 row_high_limit_last = 0;
- u32 eap_init_bits;
-
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
-
+ struct r82600_error_info discard;
+ debugf0("%s()\n", __func__);
pci_read_config_byte(pdev, R82600_DRAMC, &dramcr);
pci_read_config_dword(pdev, R82600_EAP, &eapr);
-
ecc_on = dramcr & BIT(5);
reg_sdram = dramcr & BIT(4);
scrub_disabled = eapr & BIT(31);
sdram_refresh_rate = dramcr & (BIT(0) | BIT(1));
-
- debugf2("MC: " __FILE__ ": %s(): sdram refresh rate = %#0x\n",
- __func__, sdram_refresh_rate);
-
- debugf2("MC: " __FILE__ ": %s(): DRAMC register = %#0x\n", __func__,
- dramcr);
-
+ debugf2("%s(): sdram refresh rate = %#0x\n", __func__,
+ sdram_refresh_rate);
+ debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr);
mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS);
if (mci == NULL) {
@@ -239,29 +231,28 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
goto fail;
}
- debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
-
+ debugf0("%s(): mci = %p\n", __func__, mci);
mci->pdev = pdev;
mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
-
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
- /* FIXME try to work out if the chip leads have been *
- * used for COM2 instead on this board? [MA6?] MAYBE: */
+ /* FIXME try to work out if the chip leads have been used for COM2
+ * instead on this board? [MA6?] MAYBE:
+ */
/* On the R82600, the pins for memory bits 72:65 - i.e. the *
* EC bits are shared with the pins for COM2 (!), so if COM2 *
* is enabled, we assume COM2 is wired up, and thus no EDAC *
* is possible. */
mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+
if (ecc_on) {
if (scrub_disabled)
- debugf3("MC: " __FILE__ ": %s(): mci = %p - "
- "Scrubbing disabled! EAP: %#0x\n", __func__,
- mci, eapr);
+ debugf3("%s(): mci = %p - Scrubbing disabled! EAP: "
+ "%#0x\n", __func__, mci, eapr);
} else
mci->edac_cap = EDAC_FLAG_NONE;
- mci->mod_name = BS_MOD_STR;
+ mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = "$Revision: 1.1.2.6 $";
mci->ctl_name = "R82600";
mci->edac_check = r82600_check;
@@ -276,23 +267,21 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
/* find the DRAM Chip Select Base address and mask */
pci_read_config_byte(mci->pdev, R82600_DRBA + index, &drbar);
- debugf1("MC%d: " __FILE__ ": %s() Row=%d DRBA = %#0x\n",
- mci->mc_idx, __func__, index, drbar);
+ debugf1("MC%d: %s() Row=%d DRBA = %#0x\n", mci->mc_idx,
+ __func__, index, drbar);
row_high_limit = ((u32) drbar << 24);
/* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */
- debugf1("MC%d: " __FILE__ ": %s() Row=%d, "
- "Boundry Address=%#0x, Last = %#0x \n",
- mci->mc_idx, __func__, index, row_high_limit,
- row_high_limit_last);
+ debugf1("MC%d: %s() Row=%d, Boundry Address=%#0x, Last = "
+ "%#0x \n", mci->mc_idx, __func__, index,
+ row_high_limit, row_high_limit_last);
/* Empty row [p.57] */
if (row_high_limit == row_high_limit_last)
continue;
row_base = row_high_limit_last;
-
csrow->first_page = row_base >> PAGE_SHIFT;
csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;
csrow->nr_pages = csrow->last_page - csrow->first_page + 1;
@@ -308,31 +297,22 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
row_high_limit_last = row_high_limit;
}
- /* clear counters */
- /* FIXME should we? */
+ r82600_get_error_info(mci, &discard); /* clear counters */
if (edac_mc_add_mc(mci)) {
- debugf3("MC: " __FILE__
- ": %s(): failed edac_mc_add_mc()\n", __func__);
+ debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
goto fail;
}
/* get this far and it's successful */
- /* Clear error flags to allow next error to be reported [p.62] */
- /* Test systems seem to always have the UE flag raised on boot */
-
- eap_init_bits = BIT(0) & BIT(1);
if (disable_hardware_scrub) {
- eap_init_bits |= BIT(31);
- debugf3("MC: " __FILE__ ": %s(): Disabling Hardware Scrub "
- "(scrub on error)\n", __func__);
+ debugf3("%s(): Disabling Hardware Scrub (scrub on error)\n",
+ __func__);
+ pci_write_bits32(mci->pdev, R82600_EAP, BIT(31), BIT(31));
}
- pci_write_bits32(mci->pdev, R82600_EAP, eap_init_bits,
- eap_init_bits);
-
- debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ debugf3("%s(): success\n", __func__);
return 0;
fail:
@@ -344,62 +324,60 @@ fail:
/* returns count (>= 0), or negative on error */
static int __devinit r82600_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *ent)
{
- debugf0("MC: " __FILE__ ": %s()\n", __func__);
+ debugf0("%s()\n", __func__);
/* don't need to call pci_device_enable() */
return r82600_probe1(pdev, ent->driver_data);
}
-
static void __devexit r82600_remove_one(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
- debugf0(__FILE__ ": %s()\n", __func__);
+ debugf0("%s()\n", __func__);
- if (((mci = edac_mc_find_mci_by_pdev(pdev)) != NULL) &&
- !edac_mc_del_mc(mci))
- edac_mc_free(mci);
-}
+ if ((mci = edac_mc_del_mc(pdev)) == NULL)
+ return;
+ edac_mc_free(mci);
+}
static const struct pci_device_id r82600_pci_tbl[] __devinitdata = {
- {PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)},
- {0,} /* 0 terminated list. */
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)
+ },
+ {
+ 0,
+ } /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, r82600_pci_tbl);
-
static struct pci_driver r82600_driver = {
- .name = BS_MOD_STR,
+ .name = EDAC_MOD_STR,
.probe = r82600_init_one,
.remove = __devexit_p(r82600_remove_one),
.id_table = r82600_pci_tbl,
};
-
static int __init r82600_init(void)
{
return pci_register_driver(&r82600_driver);
}
-
static void __exit r82600_exit(void)
{
pci_unregister_driver(&r82600_driver);
}
-
module_init(r82600_init);
module_exit(r82600_exit);
-
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. "
- "on behalf of EADS Astrium");
+ "on behalf of EADS Astrium");
MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers");
module_param(disable_hardware_scrub, bool, 0644);
diff --git a/drivers/eisa/.gitignore b/drivers/eisa/.gitignore
new file mode 100644
index 00000000000..4b335c0aedb
--- /dev/null
+++ b/drivers/eisa/.gitignore
@@ -0,0 +1 @@
+devlist.h
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index 4196137e66d..6078e2f5881 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -135,13 +135,8 @@ struct bus_type eisa_bus_type = {
int eisa_driver_register (struct eisa_driver *edrv)
{
- int r;
-
edrv->driver.bus = &eisa_bus_type;
- if ((r = driver_register (&edrv->driver)) < 0)
- return r;
-
- return 0;
+ return driver_register (&edrv->driver);
}
void eisa_driver_unregister (struct eisa_driver *edrv)
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index d6543fc4a92..339f405ff70 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -484,26 +484,15 @@ static void dcdbas_host_control(void)
static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
void *unused)
{
- static unsigned int notify_cnt = 0;
-
switch (code) {
case SYS_DOWN:
case SYS_HALT:
case SYS_POWER_OFF:
if (host_control_on_shutdown) {
/* firmware is going to perform host control action */
- if (++notify_cnt == 2) {
- printk(KERN_WARNING
- "Please wait for shutdown "
- "action to complete...\n");
- dcdbas_host_control();
- }
- /*
- * register again and initiate the host control
- * action on the second notification to allow
- * everyone that registered to be notified
- */
- register_reboot_notifier(nb);
+ printk(KERN_WARNING "Please wait for shutdown "
+ "action to complete...\n");
+ dcdbas_host_control();
}
break;
}
@@ -514,7 +503,7 @@ static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
static struct notifier_block dcdbas_reboot_nb = {
.notifier_call = dcdbas_reboot_notify,
.next = NULL,
- .priority = 0
+ .priority = INT_MIN
};
static DCDBAS_BIN_ATTR_RW(smi_data);
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 343379f23a5..9b7e4d52ffd 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -568,20 +568,20 @@ systab_read(struct subsystem *entry, char *buf)
if (!entry || !buf)
return -EINVAL;
- if (efi.mps)
- str += sprintf(str, "MPS=0x%lx\n", __pa(efi.mps));
- if (efi.acpi20)
- str += sprintf(str, "ACPI20=0x%lx\n", __pa(efi.acpi20));
- if (efi.acpi)
- str += sprintf(str, "ACPI=0x%lx\n", __pa(efi.acpi));
- if (efi.smbios)
- str += sprintf(str, "SMBIOS=0x%lx\n", __pa(efi.smbios));
- if (efi.hcdp)
- str += sprintf(str, "HCDP=0x%lx\n", __pa(efi.hcdp));
- if (efi.boot_info)
- str += sprintf(str, "BOOTINFO=0x%lx\n", __pa(efi.boot_info));
- if (efi.uga)
- str += sprintf(str, "UGA=0x%lx\n", __pa(efi.uga));
+ if (efi.mps != EFI_INVALID_TABLE_ADDR)
+ str += sprintf(str, "MPS=0x%lx\n", efi.mps);
+ if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
+ str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
+ if (efi.acpi != EFI_INVALID_TABLE_ADDR)
+ str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
+ if (efi.smbios != EFI_INVALID_TABLE_ADDR)
+ str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
+ if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
+ str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
+ if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
+ str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
+ if (efi.uga != EFI_INVALID_TABLE_ADDR)
+ str += sprintf(str, "UGA=0x%lx\n", efi.uga);
return str - buf;
}
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
index ae1fb45dbb4..c37baf9448b 100644
--- a/drivers/firmware/pcdp.c
+++ b/drivers/firmware/pcdp.c
@@ -89,19 +89,20 @@ efi_setup_pcdp_console(char *cmdline)
struct pcdp_uart *uart;
struct pcdp_device *dev, *end;
int i, serial = 0;
+ int rc = -ENODEV;
- pcdp = efi.hcdp;
- if (!pcdp)
+ if (efi.hcdp == EFI_INVALID_TABLE_ADDR)
return -ENODEV;
- printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, __pa(pcdp));
+ pcdp = ioremap(efi.hcdp, 4096);
+ printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, efi.hcdp);
if (strstr(cmdline, "console=hcdp")) {
if (pcdp->rev < 3)
serial = 1;
} else if (strstr(cmdline, "console=")) {
printk(KERN_INFO "Explicit \"console=\"; ignoring PCDP\n");
- return -ENODEV;
+ goto out;
}
if (pcdp->rev < 3 && efi_uart_console_only())
@@ -110,7 +111,8 @@ efi_setup_pcdp_console(char *cmdline)
for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) {
if (uart->flags & PCDP_UART_PRIMARY_CONSOLE || serial) {
if (uart->type == PCDP_CONSOLE_UART) {
- return setup_serial_console(uart);
+ rc = setup_serial_console(uart);
+ goto out;
}
}
}
@@ -121,10 +123,13 @@ efi_setup_pcdp_console(char *cmdline)
dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) {
if (dev->flags & PCDP_PRIMARY_CONSOLE) {
if (dev->type == PCDP_CONSOLE_VGA) {
- return setup_vga_console(dev);
+ rc = setup_vga_console(dev);
+ goto out;
}
}
}
- return -ENODEV;
+out:
+ iounmap(pcdp);
+ return rc;
}
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index f9fae28f561..7aa5c38f085 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -65,15 +65,6 @@ config SENSORS_PCF8591
This driver can also be built as a module. If so, the module
will be called pcf8591.
-config SENSORS_RTC8564
- tristate "Epson 8564 RTC chip"
- depends on I2C && EXPERIMENTAL
- help
- If you say yes here you get support for the Epson 8564 RTC chip.
-
- This driver can also be built as a module. If so, the module
- will be called i2c-rtc8564.
-
config ISP1301_OMAP
tristate "Philips ISP1301 with OMAP OTG"
depends on I2C && ARCH_OMAP_OTG
@@ -126,13 +117,4 @@ config SENSORS_MAX6875
This driver can also be built as a module. If so, the module
will be called max6875.
-config RTC_X1205_I2C
- tristate "Xicor X1205 RTC chip"
- depends on I2C && EXPERIMENTAL
- help
- If you say yes here you get support for the Xicor X1205 RTC chip.
-
- This driver can also be built as a module. If so, the module
- will be called x1205.
-
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 46178b57b1f..779868ef2e2 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -10,10 +10,8 @@ obj-$(CONFIG_SENSORS_M41T00) += m41t00.o
obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o
obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
-obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TPS65010) += tps65010.o
-obj-$(CONFIG_RTC_X1205_I2C) += x1205.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
deleted file mode 100644
index 0d8699b3f48..00000000000
--- a/drivers/i2c/chips/rtc8564.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * linux/drivers/i2c/chips/rtc8564.c
- *
- * Copyright (C) 2002-2004 Stefan Eletzhofer
- *
- * based on linux/drivers/acron/char/pcf8583.c
- * Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Driver for system3's EPSON RTC 8564 chip
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/bcd.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/rtc.h> /* get the user-level API */
-#include <linux/init.h>
-
-#include "rtc8564.h"
-
-#ifdef DEBUG
-# define _DBG(x, fmt, args...) do{ if (debug>=x) printk(KERN_DEBUG"%s: " fmt "\n", __FUNCTION__, ##args); } while(0);
-#else
-# define _DBG(x, fmt, args...) do { } while(0);
-#endif
-
-#define _DBGRTCTM(x, rtctm) if (debug>=x) printk("%s: secs=%d, mins=%d, hours=%d, mday=%d, " \
- "mon=%d, year=%d, wday=%d VL=%d\n", __FUNCTION__, \
- (rtctm).secs, (rtctm).mins, (rtctm).hours, (rtctm).mday, \
- (rtctm).mon, (rtctm).year, (rtctm).wday, (rtctm).vl);
-
-struct rtc8564_data {
- struct i2c_client client;
- u16 ctrl;
-};
-
-static inline u8 _rtc8564_ctrl1(struct i2c_client *client)
-{
- struct rtc8564_data *data = i2c_get_clientdata(client);
- return data->ctrl & 0xff;
-}
-static inline u8 _rtc8564_ctrl2(struct i2c_client *client)
-{
- struct rtc8564_data *data = i2c_get_clientdata(client);
- return (data->ctrl & 0xff00) >> 8;
-}
-
-#define CTRL1(c) _rtc8564_ctrl1(c)
-#define CTRL2(c) _rtc8564_ctrl2(c)
-
-static int debug;
-module_param(debug, int, S_IRUGO | S_IWUSR);
-
-static struct i2c_driver rtc8564_driver;
-
-static unsigned short ignore[] = { I2C_CLIENT_END };
-static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END };
-
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_addr,
- .probe = ignore,
- .ignore = ignore,
-};
-
-static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem);
-static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem);
-
-static int rtc8564_read(struct i2c_client *client, unsigned char adr,
- unsigned char *buf, unsigned char len)
-{
- int ret = -EIO;
- unsigned char addr[1] = { adr };
- struct i2c_msg msgs[2] = {
- {client->addr, 0, 1, addr},
- {client->addr, I2C_M_RD, len, buf}
- };
-
- _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len);
-
- if (!buf) {
- ret = -EINVAL;
- goto done;
- }
-
- ret = i2c_transfer(client->adapter, msgs, 2);
- if (ret == 2) {
- ret = 0;
- }
-
-done:
- return ret;
-}
-
-static int rtc8564_write(struct i2c_client *client, unsigned char adr,
- unsigned char *data, unsigned char len)
-{
- int ret = 0;
- unsigned char _data[16];
- struct i2c_msg wr;
- int i;
-
- if (!data || len > 15) {
- ret = -EINVAL;
- goto done;
- }
-
- _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, data, len);
-
- _data[0] = adr;
- for (i = 0; i < len; i++) {
- _data[i + 1] = data[i];
- _DBG(5, "data[%d] = 0x%02x (%d)", i, data[i], data[i]);
- }
-
- wr.addr = client->addr;
- wr.flags = 0;
- wr.len = len + 1;
- wr.buf = _data;
-
- ret = i2c_transfer(client->adapter, &wr, 1);
- if (ret == 1) {
- ret = 0;
- }
-
-done:
- return ret;
-}
-
-static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind)
-{
- int ret;
- struct i2c_client *new_client;
- struct rtc8564_data *d;
- unsigned char data[10];
- unsigned char ad[1] = { 0 };
- struct i2c_msg ctrl_wr[1] = {
- {addr, 0, 2, data}
- };
- struct i2c_msg ctrl_rd[2] = {
- {addr, 0, 1, ad},
- {addr, I2C_M_RD, 2, data}
- };
-
- d = kzalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
- if (!d) {
- ret = -ENOMEM;
- goto done;
- }
- new_client = &d->client;
-
- strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
- i2c_set_clientdata(new_client, d);
- new_client->addr = addr;
- new_client->adapter = adap;
- new_client->driver = &rtc8564_driver;
-
- _DBG(1, "client=%p", new_client);
-
- /* init ctrl1 reg */
- data[0] = 0;
- data[1] = 0;
- ret = i2c_transfer(new_client->adapter, ctrl_wr, 1);
- if (ret != 1) {
- printk(KERN_INFO "rtc8564: cant init ctrl1\n");
- ret = -ENODEV;
- goto done;
- }
-
- /* read back ctrl1 and ctrl2 */
- ret = i2c_transfer(new_client->adapter, ctrl_rd, 2);
- if (ret != 2) {
- printk(KERN_INFO "rtc8564: cant read ctrl\n");
- ret = -ENODEV;
- goto done;
- }
-
- d->ctrl = data[0] | (data[1] << 8);
-
- _DBG(1, "RTC8564_REG_CTRL1=%02x, RTC8564_REG_CTRL2=%02x",
- data[0], data[1]);
-
- ret = i2c_attach_client(new_client);
-done:
- if (ret) {
- kfree(d);
- }
- return ret;
-}
-
-static int rtc8564_probe(struct i2c_adapter *adap)
-{
- return i2c_probe(adap, &addr_data, rtc8564_attach);
-}
-
-static int rtc8564_detach(struct i2c_client *client)
-{
- i2c_detach_client(client);
- kfree(i2c_get_clientdata(client));
- return 0;
-}
-
-static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
-{
- int ret = -EIO;
- unsigned char buf[15];
-
- _DBG(1, "client=%p, dt=%p", client, dt);
-
- if (!dt)
- return -EINVAL;
-
- memset(buf, 0, sizeof(buf));
-
- ret = rtc8564_read(client, 0, buf, 15);
- if (ret)
- return ret;
-
- /* century stored in minute alarm reg */
- dt->year = BCD2BIN(buf[RTC8564_REG_YEAR]);
- dt->year += 100 * BCD2BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
- dt->mday = BCD2BIN(buf[RTC8564_REG_DAY] & 0x3f);
- dt->wday = BCD2BIN(buf[RTC8564_REG_WDAY] & 7);
- dt->mon = BCD2BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
-
- dt->secs = BCD2BIN(buf[RTC8564_REG_SEC] & 0x7f);
- dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80;
- dt->mins = BCD2BIN(buf[RTC8564_REG_MIN] & 0x7f);
- dt->hours = BCD2BIN(buf[RTC8564_REG_HR] & 0x3f);
-
- _DBGRTCTM(2, *dt);
-
- return 0;
-}
-
-static int
-rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
-{
- int ret, len = 5;
- unsigned char buf[15];
-
- _DBG(1, "client=%p, dt=%p", client, dt);
-
- if (!dt)
- return -EINVAL;
-
- _DBGRTCTM(2, *dt);
-
- buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP;
- buf[RTC8564_REG_CTRL2] = CTRL2(client);
- buf[RTC8564_REG_SEC] = BIN2BCD(dt->secs);
- buf[RTC8564_REG_MIN] = BIN2BCD(dt->mins);
- buf[RTC8564_REG_HR] = BIN2BCD(dt->hours);
-
- if (datetoo) {
- len += 5;
- buf[RTC8564_REG_DAY] = BIN2BCD(dt->mday);
- buf[RTC8564_REG_WDAY] = BIN2BCD(dt->wday);
- buf[RTC8564_REG_MON_CENT] = BIN2BCD(dt->mon) & 0x1f;
- /* century stored in minute alarm reg */
- buf[RTC8564_REG_YEAR] = BIN2BCD(dt->year % 100);
- buf[RTC8564_REG_AL_MIN] = BIN2BCD(dt->year / 100);
- }
-
- ret = rtc8564_write(client, 0, buf, len);
- if (ret) {
- _DBG(1, "error writing data! %d", ret);
- }
-
- buf[RTC8564_REG_CTRL1] = CTRL1(client);
- ret = rtc8564_write(client, 0, buf, 1);
- if (ret) {
- _DBG(1, "error writing data! %d", ret);
- }
-
- return ret;
-}
-
-static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl)
-{
- struct rtc8564_data *data = i2c_get_clientdata(client);
-
- if (!ctrl)
- return -1;
-
- *ctrl = data->ctrl;
- return 0;
-}
-
-static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl)
-{
- struct rtc8564_data *data = i2c_get_clientdata(client);
- unsigned char buf[2];
-
- if (!ctrl)
- return -1;
-
- buf[0] = *ctrl & 0xff;
- buf[1] = (*ctrl & 0xff00) >> 8;
- data->ctrl = *ctrl;
-
- return rtc8564_write(client, 0, buf, 2);
-}
-
-static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem)
-{
-
- if (!mem)
- return -EINVAL;
-
- return rtc8564_read(client, mem->loc, mem->data, mem->nr);
-}
-
-static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem)
-{
-
- if (!mem)
- return -EINVAL;
-
- return rtc8564_write(client, mem->loc, mem->data, mem->nr);
-}
-
-static int
-rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
-
- _DBG(1, "cmd=%d", cmd);
-
- switch (cmd) {
- case RTC_GETDATETIME:
- return rtc8564_get_datetime(client, arg);
-
- case RTC_SETTIME:
- return rtc8564_set_datetime(client, arg, 0);
-
- case RTC_SETDATETIME:
- return rtc8564_set_datetime(client, arg, 1);
-
- case RTC_GETCTRL:
- return rtc8564_get_ctrl(client, arg);
-
- case RTC_SETCTRL:
- return rtc8564_set_ctrl(client, arg);
-
- case MEM_READ:
- return rtc8564_read_mem(client, arg);
-
- case MEM_WRITE:
- return rtc8564_write_mem(client, arg);
-
- default:
- return -EINVAL;
- }
-}
-
-static struct i2c_driver rtc8564_driver = {
- .driver = {
- .name = "RTC8564",
- },
- .id = I2C_DRIVERID_RTC8564,
- .attach_adapter = rtc8564_probe,
- .detach_client = rtc8564_detach,
- .command = rtc8564_command
-};
-
-static __init int rtc8564_init(void)
-{
- return i2c_add_driver(&rtc8564_driver);
-}
-
-static __exit void rtc8564_exit(void)
-{
- i2c_del_driver(&rtc8564_driver);
-}
-
-MODULE_AUTHOR("Stefan Eletzhofer <Stefan.Eletzhofer@eletztrick.de>");
-MODULE_DESCRIPTION("EPSON RTC8564 Driver");
-MODULE_LICENSE("GPL");
-
-module_init(rtc8564_init);
-module_exit(rtc8564_exit);
diff --git a/drivers/i2c/chips/rtc8564.h b/drivers/i2c/chips/rtc8564.h
deleted file mode 100644
index e5342d10b8f..00000000000
--- a/drivers/i2c/chips/rtc8564.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * linux/drivers/i2c/chips/rtc8564.h
- *
- * Copyright (C) 2002-2004 Stefan Eletzhofer
- *
- * based on linux/drivers/acron/char/pcf8583.h
- * Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-struct rtc_tm {
- unsigned char secs;
- unsigned char mins;
- unsigned char hours;
- unsigned char mday;
- unsigned char mon;
- unsigned short year; /* xxxx 4 digits :) */
- unsigned char wday;
- unsigned char vl;
-};
-
-struct mem {
- unsigned int loc;
- unsigned int nr;
- unsigned char *data;
-};
-
-#define RTC_GETDATETIME 0
-#define RTC_SETTIME 1
-#define RTC_SETDATETIME 2
-#define RTC_GETCTRL 3
-#define RTC_SETCTRL 4
-#define MEM_READ 5
-#define MEM_WRITE 6
-
-#define RTC8564_REG_CTRL1 0x0 /* T 0 S 0 | T 0 0 0 */
-#define RTC8564_REG_CTRL2 0x1 /* 0 0 0 TI/TP | AF TF AIE TIE */
-#define RTC8564_REG_SEC 0x2 /* VL 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_MIN 0x3 /* x 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_HR 0x4 /* x x 2 1 | 8 4 2 1 */
-#define RTC8564_REG_DAY 0x5 /* x x 2 1 | 8 4 2 1 */
-#define RTC8564_REG_WDAY 0x6 /* x x x x | x 4 2 1 */
-#define RTC8564_REG_MON_CENT 0x7 /* C x x 1 | 8 4 2 1 */
-#define RTC8564_REG_YEAR 0x8 /* 8 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_AL_MIN 0x9 /* AE 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_AL_HR 0xa /* AE 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_AL_DAY 0xb /* AE x 2 1 | 8 4 2 1 */
-#define RTC8564_REG_AL_WDAY 0xc /* AE x x x | x 4 2 1 */
-#define RTC8564_REG_CLKOUT 0xd /* FE x x x | x x FD1 FD0 */
-#define RTC8564_REG_TCTL 0xe /* TE x x x | x x FD1 FD0 */
-#define RTC8564_REG_TIMER 0xf /* 8 bit binary */
-
-/* Control reg */
-#define RTC8564_CTRL1_TEST1 (1<<3)
-#define RTC8564_CTRL1_STOP (1<<5)
-#define RTC8564_CTRL1_TEST2 (1<<7)
-
-#define RTC8564_CTRL2_TIE (1<<0)
-#define RTC8564_CTRL2_AIE (1<<1)
-#define RTC8564_CTRL2_TF (1<<2)
-#define RTC8564_CTRL2_AF (1<<3)
-#define RTC8564_CTRL2_TI_TP (1<<4)
-
-/* CLKOUT frequencies */
-#define RTC8564_FD_32768HZ (0x0)
-#define RTC8564_FD_1024HZ (0x1)
-#define RTC8564_FD_32 (0x2)
-#define RTC8564_FD_1HZ (0x3)
-
-/* Timer CTRL */
-#define RTC8564_TD_4096HZ (0x0)
-#define RTC8564_TD_64HZ (0x1)
-#define RTC8564_TD_1HZ (0x2)
-#define RTC8564_TD_1_60HZ (0x3)
-
-#define I2C_DRIVERID_RTC8564 0xf000
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index c7671e18801..b4a41d6d071 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -2143,6 +2143,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
req.data = (char *)&capbuf;
req.data_len = sizeof(capbuf);
+ req.flags |= REQ_QUIET;
stat = cdrom_queue_packet_command(drive, &req);
if (stat == 0) {
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index ebc59064b47..f04791a58df 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -433,6 +433,7 @@
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
+#include <linux/jiffies.h>
#include <linux/major.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/errno.h>
@@ -2336,7 +2337,7 @@ static ide_startstop_t idetape_rw_callback (ide_drive_t *drive)
}
if (time_after(jiffies, tape->insert_time))
tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
- if (jiffies - tape->avg_time >= HZ) {
+ if (time_after_eq(jiffies, tape->avg_time + HZ)) {
tape->avg_speed = tape->avg_size * HZ / (jiffies - tape->avg_time) / 1024;
tape->avg_size = 0;
tape->avg_time = jiffies;
@@ -2497,7 +2498,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
} else {
return ide_do_reset(drive);
}
- } else if (jiffies - tape->dsc_polling_start > IDETAPE_DSC_MA_THRESHOLD)
+ } else if (time_after(jiffies, tape->dsc_polling_start + IDETAPE_DSC_MA_THRESHOLD))
tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW;
idetape_postpone_request(drive);
return ide_stopped;
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index b2cc43702f6..3fdab563fec 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -2058,7 +2058,7 @@ static void __init parse_options (char *line)
}
}
-int init_module (void)
+int __init init_module (void)
{
parse_options(options);
return ide_init();
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 21965e5ef25..b22ee546231 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -347,10 +347,8 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
break;
case AMD_UDMA_66:
- pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
- for (i = 24; i >= 0; i -= 8)
- if ((u >> i) & 4)
- amd_80w |= (1 << (1 - (i >> 4)));
+ /* no host side cable detection */
+ amd_80w = 0x03;
break;
}
@@ -386,8 +384,6 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
if (amd_clock < 20000 || amd_clock > 50000) {
printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n",
amd_chipset->name, amd_clock);
- printk(KERN_WARNING "%s: Use ide0=ata66 if you want to assume 80-wire cable\n",
- amd_chipset->name);
amd_clock = 33333;
}
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index 6e3ab0c38c4..f82e8210972 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -41,14 +41,15 @@
static int ide_generic_all; /* Set to claim all devices */
+#ifndef MODULE
static int __init ide_generic_all_on(char *unused)
{
ide_generic_all = 1;
printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers.\n");
return 1;
}
-
__setup("all-generic-ide", ide_generic_all_on);
+#endif
static void __devinit init_hwif_generic (ide_hwif_t *hwif)
{
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 75a2253a3e6..8e9d87701ce 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -112,6 +112,7 @@ static const struct {
{ "SiS5596", PCI_DEVICE_ID_SI_5596, ATA_16 },
{ "SiS5571", PCI_DEVICE_ID_SI_5571, ATA_16 },
+ { "SiS5517", PCI_DEVICE_ID_SI_5517, ATA_16 },
{ "SiS551x", PCI_DEVICE_ID_SI_5511, ATA_16 },
};
@@ -524,6 +525,7 @@ static void config_art_rwp_pio (ide_drive_t *drive, u8 pio)
case 3: test1 = 0x30|0x03; break;
case 2: test1 = 0x40|0x04; break;
case 1: test1 = 0x60|0x07; break;
+ case 0: test1 = 0x00; break;
default: break;
}
pci_write_config_byte(dev, drive_pci, test1);
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index c85b87cb59d..3e677c4f8c2 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -440,7 +440,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
#if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32)
- if(_machine == _MACH_chrp && _chrp_type == _CHRP_Pegasos) {
+ if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) {
hwif->irq = hwif->channel ? 15 : 14;
}
#endif
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 5013b1285e2..78e30f80367 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1677,7 +1677,7 @@ MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match);
void __init
pmac_ide_probe(void)
{
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return;
#ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index efeaa944bd0..85c2d4ca0de 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -73,7 +73,7 @@
- fix all XXX showstoppers
- disable IR/IT DMA interrupts on shutdown
- flush pci writes to the card by issuing a read
- - devfs and character device dispatching (* needs testing with Linux 2.2.x)
+ - character device dispatching
- switch over to the new kernel DMA API (pci_map_*()) (* needs testing on platforms with IOMMU!)
- keep all video_cards in a list (for open() via chardev), set file->private_data = video
- dv1394_poll should indicate POLLIN when receiving buffers are available
@@ -1096,7 +1096,6 @@ static int do_dv1394_init_default(struct video_card *video)
init.api_version = DV1394_API_VERSION;
init.n_frames = DV1394_MAX_FRAMES / 4;
- /* the following are now set via devfs */
init.channel = video->channel;
init.format = video->pal_or_ntsc;
init.cip_n = video->cip_n;
@@ -1791,8 +1790,6 @@ static int dv1394_open(struct inode *inode, struct file *file)
{
struct video_card *video = NULL;
- /* if the device was opened through devfs, then file->private_data
- has already been set to video by devfs */
if (file->private_data) {
video = (struct video_card*) file->private_data;
@@ -2211,7 +2208,7 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes
video = kzalloc(sizeof(*video), GFP_KERNEL);
if (!video) {
printk(KERN_ERR "dv1394: cannot allocate video_card\n");
- goto err;
+ return -1;
}
video->ohci = ohci;
@@ -2266,37 +2263,14 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes
list_add_tail(&video->list, &dv1394_cards);
spin_unlock_irqrestore(&dv1394_cards_lock, flags);
- if (devfs_mk_cdev(MKDEV(IEEE1394_MAJOR,
- IEEE1394_MINOR_BLOCK_DV1394*16 + video->id),
- S_IFCHR|S_IRUGO|S_IWUGO,
- "ieee1394/dv/host%d/%s/%s",
- (video->id>>2),
- (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
- (video->mode == MODE_RECEIVE ? "in" : "out")) < 0)
- goto err_free;
-
debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id);
-
return 0;
-
- err_free:
- kfree(video);
- err:
- return -1;
}
static void dv1394_un_init(struct video_card *video)
{
- char buf[32];
-
/* obviously nobody has the driver open at this point */
do_dv1394_shutdown(video, 1);
- snprintf(buf, sizeof(buf), "dv/host%d/%s/%s", (video->id >> 2),
- (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
- (video->mode == MODE_RECEIVE ? "in" : "out")
- );
-
- devfs_remove("ieee1394/%s", buf);
kfree(video);
}
@@ -2333,9 +2307,6 @@ static void dv1394_remove_host (struct hpsb_host *host)
class_device_destroy(hpsb_protocol_class,
MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)));
- devfs_remove("ieee1394/dv/host%d/NTSC", id);
- devfs_remove("ieee1394/dv/host%d/PAL", id);
- devfs_remove("ieee1394/dv/host%d", id);
}
static void dv1394_add_host (struct hpsb_host *host)
@@ -2352,9 +2323,6 @@ static void dv1394_add_host (struct hpsb_host *host)
class_device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
NULL, "dv1394-%d", id);
- devfs_mk_dir("ieee1394/dv/host%d", id);
- devfs_mk_dir("ieee1394/dv/host%d/NTSC", id);
- devfs_mk_dir("ieee1394/dv/host%d/PAL", id);
dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
@@ -2611,10 +2579,8 @@ MODULE_LICENSE("GPL");
static void __exit dv1394_exit_module(void)
{
hpsb_unregister_protocol(&dv1394_driver);
-
hpsb_unregister_highlevel(&dv1394_highlevel);
cdev_del(&dv1394_cdev);
- devfs_remove("ieee1394/dv");
}
static int __init dv1394_init_module(void)
@@ -2630,15 +2596,12 @@ static int __init dv1394_init_module(void)
return ret;
}
- devfs_mk_dir("ieee1394/dv");
-
hpsb_register_highlevel(&dv1394_highlevel);
ret = hpsb_register_protocol(&dv1394_driver);
if (ret) {
printk(KERN_ERR "dv1394: failed to register protocol\n");
hpsb_unregister_highlevel(&dv1394_highlevel);
- devfs_remove("ieee1394/dv");
cdev_del(&dv1394_cdev);
return ret;
}
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 734b121a055..491e6032bde 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -306,8 +306,7 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
u64 align_mask = ~(alignment - 1);
if ((alignment & 3) || (alignment > 0x800000000000ULL) ||
- ((hweight32(alignment >> 32) +
- hweight32(alignment & 0xffffffff) != 1))) {
+ (hweight64(alignment) != 1)) {
HPSB_ERR("%s called with invalid alignment: 0x%048llx",
__FUNCTION__, (unsigned long long)alignment);
return retval;
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 25ef5a86f5f..be6854e25ad 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -58,7 +58,7 @@ MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
/* Disable Isochronous Resource Manager functionality */
int hpsb_disable_irm = 0;
-module_param_named(disable_irm, hpsb_disable_irm, bool, 0);
+module_param_named(disable_irm, hpsb_disable_irm, bool, 0444);
MODULE_PARM_DESC(disable_irm,
"Disable Isochronous Resource Manager functionality.");
@@ -1078,17 +1078,10 @@ static int __init ieee1394_init(void)
goto exit_release_kernel_thread;
}
- /* actually this is a non-fatal error */
- ret = devfs_mk_dir("ieee1394");
- if (ret < 0) {
- HPSB_ERR("unable to make devfs dir for device major %d!\n", IEEE1394_MAJOR);
- goto release_chrdev;
- }
-
ret = bus_register(&ieee1394_bus_type);
if (ret < 0) {
HPSB_INFO("bus register failed");
- goto release_devfs;
+ goto release_chrdev;
}
for (i = 0; fw_bus_attrs[i]; i++) {
@@ -1099,7 +1092,7 @@ static int __init ieee1394_init(void)
fw_bus_attrs[i--]);
}
bus_unregister(&ieee1394_bus_type);
- goto release_devfs;
+ goto release_chrdev;
}
}
@@ -1152,8 +1145,6 @@ release_all_bus:
for (i = 0; fw_bus_attrs[i]; i++)
bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
bus_unregister(&ieee1394_bus_type);
-release_devfs:
- devfs_remove("ieee1394");
release_chrdev:
unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
exit_release_kernel_thread:
@@ -1191,7 +1182,6 @@ static void __exit ieee1394_cleanup(void)
hpsb_cleanup_config_roms();
unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
- devfs_remove("ieee1394");
}
module_init(ieee1394_init);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index b35466023f0..e7b55e895f5 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -3,7 +3,6 @@
#define _IEEE1394_CORE_H
#include <linux/slab.h>
-#include <linux/devfs_fs_kernel.h>
#include <asm/atomic.h>
#include <asm/semaphore.h>
#include "hosts.h"
@@ -202,14 +201,12 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
#define IEEE1394_MINOR_BLOCK_RAW1394 0
#define IEEE1394_MINOR_BLOCK_VIDEO1394 1
#define IEEE1394_MINOR_BLOCK_DV1394 2
-#define IEEE1394_MINOR_BLOCK_AMDTP 3
#define IEEE1394_MINOR_BLOCK_EXPERIMENTAL 15
#define IEEE1394_CORE_DEV MKDEV(IEEE1394_MAJOR, 0)
#define IEEE1394_RAW1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16)
#define IEEE1394_VIDEO1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16)
#define IEEE1394_DV1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16)
-#define IEEE1394_AMDTP_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_AMDTP * 16)
#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
/* return the index (within a minor number block) of a file */
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index b6b96fa04d6..19222878aae 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -544,12 +544,19 @@ static void ohci_initialize(struct ti_ohci *ohci)
/* Initialize IR Legacy DMA channel mask */
ohci->ir_legacy_channels = 0;
- /*
- * Accept AT requests from all nodes. This probably
- * will have to be controlled from the subsystem
- * on a per node basis.
- */
- reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0x80000000);
+ /* Accept AR requests from all nodes */
+ reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
+
+ /* Set the address range of the physical response unit.
+ * Most controllers do not implement it as a writable register though.
+ * They will keep a hardwired offset of 0x00010000 and show 0x0 as
+ * register content.
+ * To actually enable physical responses is the job of our interrupt
+ * handler which programs the physical request filter. */
+ reg_write(ohci, OHCI1394_PhyUpperBound, 0xffff0000);
+
+ DBGMSG("physUpperBoundOffset=%08x",
+ reg_read(ohci, OHCI1394_PhyUpperBound));
/* Specify AT retries */
reg_write(ohci, OHCI1394_ATRetries,
@@ -572,6 +579,7 @@ static void ohci_initialize(struct ti_ohci *ohci)
OHCI1394_reqTxComplete |
OHCI1394_isochRx |
OHCI1394_isochTx |
+ OHCI1394_postedWriteErr |
OHCI1394_cycleInconsistent);
/* Enable link */
@@ -2374,7 +2382,10 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
event &= ~OHCI1394_unrecoverableError;
}
-
+ if (event & OHCI1394_postedWriteErr) {
+ PRINT(KERN_ERR, "physical posted write error");
+ /* no recovery strategy yet, had to involve protocol drivers */
+ }
if (event & OHCI1394_cycleInconsistent) {
/* We subscribe to the cycleInconsistent event only to
* clear the corresponding event bit... otherwise,
@@ -2382,7 +2393,6 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
DBGMSG("OHCI1394_cycleInconsistent");
event &= ~OHCI1394_cycleInconsistent;
}
-
if (event & OHCI1394_busReset) {
/* The busReset event bit can't be cleared during the
* selfID phase, so we disable busReset interrupts, to
@@ -2426,7 +2436,6 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
}
event &= ~OHCI1394_busReset;
}
-
if (event & OHCI1394_reqTxComplete) {
struct dma_trm_ctx *d = &ohci->at_req_context;
DBGMSG("Got reqTxComplete interrupt "
@@ -2514,26 +2523,20 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
spin_unlock_irqrestore(&ohci->event_lock, flags);
- /* Accept Physical requests from all nodes. */
- reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0xffffffff);
- reg_write(ohci,OHCI1394_AsReqFilterLoSet, 0xffffffff);
-
/* Turn on phys dma reception.
*
* TODO: Enable some sort of filtering management.
*/
if (phys_dma) {
- reg_write(ohci,OHCI1394_PhyReqFilterHiSet, 0xffffffff);
- reg_write(ohci,OHCI1394_PhyReqFilterLoSet, 0xffffffff);
- reg_write(ohci,OHCI1394_PhyUpperBound, 0xffff0000);
- } else {
- reg_write(ohci,OHCI1394_PhyReqFilterHiSet, 0x00000000);
- reg_write(ohci,OHCI1394_PhyReqFilterLoSet, 0x00000000);
+ reg_write(ohci, OHCI1394_PhyReqFilterHiSet,
+ 0xffffffff);
+ reg_write(ohci, OHCI1394_PhyReqFilterLoSet,
+ 0xffffffff);
}
DBGMSG("PhyReqFilter=%08x%08x",
- reg_read(ohci,OHCI1394_PhyReqFilterHiSet),
- reg_read(ohci,OHCI1394_PhyReqFilterLoSet));
+ reg_read(ohci, OHCI1394_PhyReqFilterHiSet),
+ reg_read(ohci, OHCI1394_PhyReqFilterLoSet));
hpsb_selfid_complete(host, phyid, isroot);
} else
@@ -3259,8 +3262,8 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
* fail to report the right length. Anyway, the ohci spec
* clearly says it's 2kb, so this shouldn't be a problem. */
ohci_base = pci_resource_start(dev, 0);
- if (pci_resource_len(dev, 0) != OHCI1394_REGISTER_SIZE)
- PRINT(KERN_WARNING, "Unexpected PCI resource length of %lx!",
+ if (pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE)
+ PRINT(KERN_WARNING, "PCI resource length of %lx too small!",
pci_resource_len(dev, 0));
/* Seems PCMCIA handles this internally. Not sure why. Seems
@@ -3526,7 +3529,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
static int ohci1394_pci_resume (struct pci_dev *pdev)
{
#ifdef CONFIG_PPC_PMAC
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
struct device_node *of_node;
/* Re-enable 1394 */
@@ -3545,7 +3548,7 @@ static int ohci1394_pci_resume (struct pci_dev *pdev)
static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
{
#ifdef CONFIG_PPC_PMAC
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
struct device_node *of_node;
/* Disable 1394 */
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index b0523563991..f7de546f2ed 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -41,7 +41,7 @@
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
-#include <linux/devfs_fs_kernel.h>
+#include <linux/compat.h>
#include "csr1212.h"
#include "ieee1394.h"
@@ -406,6 +406,65 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
queue_complete_req(req);
}
+#ifdef CONFIG_COMPAT
+struct compat_raw1394_req {
+ __u32 type;
+ __s32 error;
+ __u32 misc;
+
+ __u32 generation;
+ __u32 length;
+
+ __u64 address;
+
+ __u64 tag;
+
+ __u64 sendb;
+ __u64 recvb;
+} __attribute__((packed));
+
+static const char __user *raw1394_compat_write(const char __user *buf)
+{
+ struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
+ struct raw1394_request __user *r;
+ r = compat_alloc_user_space(sizeof(struct raw1394_request));
+
+#define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x))
+
+ if (copy_in_user(r, cr, sizeof(struct compat_raw1394_req)) ||
+ C(address) ||
+ C(tag) ||
+ C(sendb) ||
+ C(recvb))
+ return ERR_PTR(-EFAULT);
+ return (const char __user *)r;
+}
+#undef C
+
+#define P(x) __put_user(r->x, &cr->x)
+
+static int
+raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
+{
+ struct compat_raw1394_req __user *cr = (typeof(cr)) r;
+ if (!access_ok(VERIFY_WRITE,cr,sizeof(struct compat_raw1394_req)) ||
+ P(type) ||
+ P(error) ||
+ P(misc) ||
+ P(generation) ||
+ P(length) ||
+ P(address) ||
+ P(tag) ||
+ P(sendb) ||
+ P(recvb))
+ return -EFAULT;
+ return sizeof(struct compat_raw1394_req);
+}
+#undef P
+
+#endif
+
+
static ssize_t raw1394_read(struct file *file, char __user * buffer,
size_t count, loff_t * offset_is_ignored)
{
@@ -415,6 +474,11 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer,
struct pending_request *req;
ssize_t ret;
+#ifdef CONFIG_COMPAT
+ if (count == sizeof(struct compat_raw1394_req)) {
+ /* ok */
+ } else
+#endif
if (count != sizeof(struct raw1394_request)) {
return -EINVAL;
}
@@ -446,12 +510,22 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer,
req->req.error = RAW1394_ERROR_MEMFAULT;
}
}
- if (copy_to_user(buffer, &req->req, sizeof(req->req))) {
- ret = -EFAULT;
- goto out;
- }
- ret = (ssize_t) sizeof(struct raw1394_request);
+#ifdef CONFIG_COMPAT
+ if (count == sizeof(struct compat_raw1394_req) &&
+ sizeof(struct compat_raw1394_req) !=
+ sizeof(struct raw1394_request)) {
+ ret = raw1394_compat_read(buffer, &req->req);
+
+ } else
+#endif
+ {
+ if (copy_to_user(buffer, &req->req, sizeof(req->req))) {
+ ret = -EFAULT;
+ goto out;
+ }
+ ret = (ssize_t) sizeof(struct raw1394_request);
+ }
out:
free_pending_request(req);
return ret;
@@ -2274,6 +2348,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
return handle_async_request(fi, req, node);
}
+
static ssize_t raw1394_write(struct file *file, const char __user * buffer,
size_t count, loff_t * offset_is_ignored)
{
@@ -2281,6 +2356,15 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
struct pending_request *req;
ssize_t retval = 0;
+#ifdef CONFIG_COMPAT
+ if (count == sizeof(struct compat_raw1394_req) &&
+ sizeof(struct compat_raw1394_req) !=
+ sizeof(struct raw1394_request)) {
+ buffer = raw1394_compat_write(buffer);
+ if (IS_ERR(buffer))
+ return PTR_ERR(buffer);
+ } else
+#endif
if (count != sizeof(struct raw1394_request)) {
return -EINVAL;
}
@@ -2893,6 +2977,7 @@ static struct file_operations raw1394_fops = {
.write = raw1394_write,
.mmap = raw1394_mmap,
.ioctl = raw1394_ioctl,
+ // .compat_ioctl = ... someone needs to do this
.poll = raw1394_poll,
.open = raw1394_open,
.release = raw1394_release,
@@ -2913,9 +2998,6 @@ static int __init init_raw1394(void)
goto out_unreg;
}
- devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
- S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
-
cdev_init(&raw1394_cdev, &raw1394_fops);
raw1394_cdev.owner = THIS_MODULE;
kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME);
@@ -2937,7 +3019,6 @@ static int __init init_raw1394(void)
goto out;
out_dev:
- devfs_remove(RAW1394_DEVICE_NAME);
class_device_destroy(hpsb_protocol_class,
MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_RAW1394 * 16));
@@ -2953,7 +3034,6 @@ static void __exit cleanup_raw1394(void)
MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_RAW1394 * 16));
cdev_del(&raw1394_cdev);
- devfs_remove(RAW1394_DEVICE_NAME);
hpsb_unregister_highlevel(&raw1394_highlevel);
hpsb_unregister_protocol(&raw1394_driver);
}
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index eca92eb475a..2c765ca5aa5 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -214,6 +214,7 @@ static u32 global_outstanding_dmas = 0;
#endif
#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
+#define SBP2_DEBUG_ENTER() SBP2_DEBUG("%s", __FUNCTION__)
/*
* Globals
@@ -535,7 +536,7 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
command->Current_SCpnt = Current_SCpnt;
list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse);
} else {
- SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!");
+ SBP2_ERR("%s: no orbs available", __FUNCTION__);
}
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
return command;
@@ -549,7 +550,7 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command)
struct hpsb_host *host;
if (!scsi_id) {
- printk(KERN_ERR "%s: scsi_id == NULL\n", __FUNCTION__);
+ SBP2_ERR("%s: scsi_id == NULL", __FUNCTION__);
return;
}
@@ -610,7 +611,7 @@ static int sbp2_probe(struct device *dev)
struct unit_directory *ud;
struct scsi_id_instance_data *scsi_id;
- SBP2_DEBUG("sbp2_probe");
+ SBP2_DEBUG_ENTER();
ud = container_of(dev, struct unit_directory, device);
@@ -635,7 +636,7 @@ static int sbp2_remove(struct device *dev)
struct scsi_id_instance_data *scsi_id;
struct scsi_device *sdev;
- SBP2_DEBUG("sbp2_remove");
+ SBP2_DEBUG_ENTER();
ud = container_of(dev, struct unit_directory, device);
scsi_id = ud->device.driver_data;
@@ -667,7 +668,7 @@ static int sbp2_update(struct unit_directory *ud)
{
struct scsi_id_instance_data *scsi_id = ud->device.driver_data;
- SBP2_DEBUG("sbp2_update");
+ SBP2_DEBUG_ENTER();
if (sbp2_reconnect_device(scsi_id)) {
@@ -715,7 +716,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
struct Scsi_Host *scsi_host = NULL;
struct scsi_id_instance_data *scsi_id = NULL;
- SBP2_DEBUG("sbp2_alloc_device");
+ SBP2_DEBUG_ENTER();
scsi_id = kzalloc(sizeof(*scsi_id), GFP_KERNEL);
if (!scsi_id) {
@@ -749,12 +750,22 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
/* Handle data movement if physical dma is not
- * enabled/supportedon host controller */
- hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_physdma_ops,
- 0x0ULL, 0xfffffffcULL);
+ * enabled or not supported on host controller */
+ if (!hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host,
+ &sbp2_physdma_ops,
+ 0x0ULL, 0xfffffffcULL)) {
+ SBP2_ERR("failed to register lower 4GB address range");
+ goto failed_alloc;
+ }
#endif
}
+ /* Prevent unloading of the 1394 host */
+ if (!try_module_get(hi->host->driver->owner)) {
+ SBP2_ERR("failed to get a reference on 1394 host driver");
+ goto failed_alloc;
+ }
+
scsi_id->hi = hi;
list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);
@@ -816,7 +827,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
struct sbp2scsi_host_info *hi = scsi_id->hi;
int error;
- SBP2_DEBUG("sbp2_start_device");
+ SBP2_DEBUG_ENTER();
/* Login FIFO DMA */
scsi_id->login_response =
@@ -891,7 +902,6 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
* allows someone else to login instead. One second makes sense. */
msleep_interruptible(1000);
if (signal_pending(current)) {
- SBP2_WARN("aborting sbp2_start_device due to event");
sbp2_remove_device(scsi_id);
return -EINTR;
}
@@ -944,7 +954,7 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
{
struct sbp2scsi_host_info *hi;
- SBP2_DEBUG("sbp2_remove_device");
+ SBP2_DEBUG_ENTER();
if (!scsi_id)
return;
@@ -1015,6 +1025,9 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
scsi_id->ud->device.driver_data = NULL;
+ if (hi)
+ module_put(hi->host->driver->owner);
+
SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id);
kfree(scsi_id);
@@ -1073,23 +1086,20 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
int max_logins;
int active_logins;
- SBP2_DEBUG("sbp2_query_logins");
+ SBP2_DEBUG_ENTER();
scsi_id->query_logins_orb->reserved1 = 0x0;
scsi_id->query_logins_orb->reserved2 = 0x0;
scsi_id->query_logins_orb->query_response_lo = scsi_id->query_logins_response_dma;
scsi_id->query_logins_orb->query_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
- SBP2_DEBUG("sbp2_query_logins: query_response_hi/lo initialized");
scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST);
scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);
scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
- SBP2_DEBUG("sbp2_query_logins: lun_misc initialized");
scsi_id->query_logins_orb->reserved_resp_length =
ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response));
- SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized");
scsi_id->query_logins_orb->status_fifo_hi =
ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
@@ -1098,25 +1108,19 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb));
- SBP2_DEBUG("sbp2_query_logins: orb byte-swapped");
-
sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb),
"sbp2 query logins orb", scsi_id->query_logins_orb_dma);
memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response));
memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
- SBP2_DEBUG("sbp2_query_logins: query_logins_response/status FIFO memset");
-
data[0] = ORB_SET_NODE_ID(hi->host->node_id);
data[1] = scsi_id->query_logins_orb_dma;
sbp2util_cpu_to_be32_buffer(data, 8);
atomic_set(&scsi_id->sbp2_login_complete, 0);
- SBP2_DEBUG("sbp2_query_logins: prepared to write");
hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
- SBP2_DEBUG("sbp2_query_logins: written");
if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) {
SBP2_INFO("Error querying logins to SBP-2 device - timed out");
@@ -1165,10 +1169,10 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
struct sbp2scsi_host_info *hi = scsi_id->hi;
quadlet_t data[2];
- SBP2_DEBUG("sbp2_login_device");
+ SBP2_DEBUG_ENTER();
if (!scsi_id->login_orb) {
- SBP2_DEBUG("sbp2_login_device: login_orb not alloc'd!");
+ SBP2_DEBUG("%s: login_orb not alloc'd!", __FUNCTION__);
return -EIO;
}
@@ -1182,59 +1186,39 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
/* Set-up login ORB, assume no password */
scsi_id->login_orb->password_hi = 0;
scsi_id->login_orb->password_lo = 0;
- SBP2_DEBUG("sbp2_login_device: password_hi/lo initialized");
scsi_id->login_orb->login_response_lo = scsi_id->login_response_dma;
scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
- SBP2_DEBUG("sbp2_login_device: login_response_hi/lo initialized");
scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST);
scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0); /* One second reconnect time */
scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(exclusive_login); /* Exclusive access to device */
scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1); /* Notify us of login complete */
scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
- SBP2_DEBUG("sbp2_login_device: lun_misc initialized");
scsi_id->login_orb->passwd_resp_lengths =
ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
- SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized");
scsi_id->login_orb->status_fifo_hi =
ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);
scsi_id->login_orb->status_fifo_lo =
ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);
- /*
- * Byte swap ORB if necessary
- */
sbp2util_cpu_to_be32_buffer(scsi_id->login_orb, sizeof(struct sbp2_login_orb));
- SBP2_DEBUG("sbp2_login_device: orb byte-swapped");
-
sbp2util_packet_dump(scsi_id->login_orb, sizeof(struct sbp2_login_orb),
"sbp2 login orb", scsi_id->login_orb_dma);
- /*
- * Initialize login response and status fifo
- */
memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response));
memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
- SBP2_DEBUG("sbp2_login_device: login_response/status FIFO memset");
-
- /*
- * Ok, let's write to the target's management agent register
- */
data[0] = ORB_SET_NODE_ID(hi->host->node_id);
data[1] = scsi_id->login_orb_dma;
sbp2util_cpu_to_be32_buffer(data, 8);
atomic_set(&scsi_id->sbp2_login_complete, 0);
- SBP2_DEBUG("sbp2_login_device: prepared to write to %08x",
- (unsigned int)scsi_id->sbp2_management_agent_addr);
hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
- SBP2_DEBUG("sbp2_login_device: written");
/*
* Wait for login status (up to 20 seconds)...
@@ -1298,7 +1282,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
quadlet_t data[2];
int error;
- SBP2_DEBUG("sbp2_logout_device");
+ SBP2_DEBUG_ENTER();
/*
* Set-up logout ORB
@@ -1362,7 +1346,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
quadlet_t data[2];
int error;
- SBP2_DEBUG("sbp2_reconnect_device");
+ SBP2_DEBUG_ENTER();
/*
* Set-up reconnect ORB
@@ -1453,17 +1437,11 @@ static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id)
{
quadlet_t data;
- SBP2_DEBUG("sbp2_set_busy_timeout");
+ SBP2_DEBUG_ENTER();
- /*
- * Ok, let's write to the target's busy timeout register
- */
data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);
-
- if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) {
- SBP2_ERR("sbp2_set_busy_timeout error");
- }
-
+ if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4))
+ SBP2_ERR("%s error", __FUNCTION__);
return 0;
}
@@ -1482,7 +1460,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
firmware_revision, workarounds;
int i;
- SBP2_DEBUG("sbp2_parse_unit_directory");
+ SBP2_DEBUG_ENTER();
management_agent_addr = 0x0;
command_set_spec_id = 0x0;
@@ -1615,7 +1593,7 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
{
struct sbp2scsi_host_info *hi = scsi_id->hi;
- SBP2_DEBUG("sbp2_max_speed_and_size");
+ SBP2_DEBUG_ENTER();
/* Initial setting comes from the hosts speed map */
scsi_id->speed_code =
@@ -1652,11 +1630,8 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
u64 addr;
int retval;
- SBP2_DEBUG("sbp2_agent_reset");
+ SBP2_DEBUG_ENTER();
- /*
- * Ok, let's write to the target's management agent register
- */
data = ntohl(SBP2_AGENT_RESET_DATA);
addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET;
@@ -2004,11 +1979,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
unsigned int request_bufflen = SCpnt->request_bufflen;
struct sbp2_command_info *command;
- SBP2_DEBUG("sbp2_send_command");
-#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP)
- printk("[scsi command]\n ");
- scsi_print_command(SCpnt);
-#endif
+ SBP2_DEBUG_ENTER();
SBP2_DEBUG("SCSI transfer size = %x", request_bufflen);
SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
@@ -2048,7 +2019,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
*/
static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data)
{
- SBP2_DEBUG("sbp2_status_to_sense_data");
+ SBP2_DEBUG_ENTER();
/*
* Ok, it's pretty ugly... ;-)
@@ -2082,7 +2053,7 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
{
u8 *scsi_buf = SCpnt->request_buffer;
- SBP2_DEBUG("sbp2_check_sbp2_response");
+ SBP2_DEBUG_ENTER();
if (SCpnt->cmnd[0] == INQUIRY && (SCpnt->cmnd[1] & 3) == 0) {
/*
@@ -2113,7 +2084,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
struct sbp2_command_info *command;
unsigned long flags;
- SBP2_DEBUG("sbp2_handle_status_write");
+ SBP2_DEBUG_ENTER();
sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr);
@@ -2260,7 +2231,10 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
struct sbp2scsi_host_info *hi;
int result = DID_NO_CONNECT << 16;
- SBP2_DEBUG("sbp2scsi_queuecommand");
+ SBP2_DEBUG_ENTER();
+#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP)
+ scsi_print_command(SCpnt);
+#endif
if (!sbp2util_node_is_available(scsi_id))
goto done;
@@ -2338,7 +2312,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
struct sbp2_command_info *command;
unsigned long flags;
- SBP2_DEBUG("sbp2scsi_complete_all_commands");
+ SBP2_DEBUG_ENTER();
spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
@@ -2371,7 +2345,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
u32 scsi_status, struct scsi_cmnd *SCpnt,
void (*done)(struct scsi_cmnd *))
{
- SBP2_DEBUG("sbp2scsi_complete_command");
+ SBP2_DEBUG_ENTER();
/*
* Sanity
@@ -2397,7 +2371,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
*/
switch (scsi_status) {
case SBP2_SCSI_STATUS_GOOD:
- SCpnt->result = DID_OK;
+ SCpnt->result = DID_OK << 16;
break;
case SBP2_SCSI_STATUS_BUSY:
@@ -2407,16 +2381,11 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
case SBP2_SCSI_STATUS_CHECK_CONDITION:
SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION");
- SCpnt->result = CHECK_CONDITION << 1;
-
- /*
- * Debug stuff
- */
+ SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16;
#if CONFIG_IEEE1394_SBP2_DEBUG >= 1
scsi_print_command(SCpnt);
- scsi_print_sense("bh", SCpnt);
+ scsi_print_sense(SBP2_DEVICE_NAME, SCpnt);
#endif
-
break;
case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
@@ -2441,7 +2410,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
/*
* Take care of any sbp2 response data mucking here (RBC stuff, etc.)
*/
- if (SCpnt->result == DID_OK) {
+ if (SCpnt->result == DID_OK << 16) {
sbp2_check_sbp2_response(scsi_id, SCpnt);
}
@@ -2459,6 +2428,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
* If a unit attention occurs, return busy status so it gets
* retried... it could have happened because of a 1394 bus reset
* or hot-plug...
+ * XXX DID_BUS_BUSY is actually a bad idea because it will defy
+ * the scsi layer's retry logic.
*/
#if 0
if ((scsi_status == SBP2_SCSI_STATUS_CHECK_CONDITION) &&
@@ -2624,7 +2595,7 @@ static int sbp2_module_init(void)
{
int ret;
- SBP2_DEBUG("sbp2_module_init");
+ SBP2_DEBUG_ENTER();
/* Module load debug option to force one command at a time (serializing I/O) */
if (serialize_io) {
@@ -2652,7 +2623,7 @@ static int sbp2_module_init(void)
static void __exit sbp2_module_exit(void)
{
- SBP2_DEBUG("sbp2_module_exit");
+ SBP2_DEBUG_ENTER();
hpsb_unregister_protocol(&sbp2_driver);
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 216dbbf1dc8..4e3bd62c458 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -42,7 +42,6 @@
#include <linux/poll.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
-#include <linux/devfs_fs_kernel.h>
#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/vmalloc.h>
@@ -1322,9 +1321,6 @@ static void video1394_add_host (struct hpsb_host *host)
class_device_create(hpsb_protocol_class, NULL, MKDEV(
IEEE1394_MAJOR, minor),
NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
- devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
- S_IFCHR | S_IRUSR | S_IWUSR,
- "%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
}
@@ -1332,12 +1328,9 @@ static void video1394_remove_host (struct hpsb_host *host)
{
struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
- if (ohci) {
+ if (ohci)
class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
- devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
- }
-
return;
}
@@ -1478,12 +1471,8 @@ static long video1394_compat_ioctl(struct file *f, unsigned cmd, unsigned long a
static void __exit video1394_exit_module (void)
{
hpsb_unregister_protocol(&video1394_driver);
-
hpsb_unregister_highlevel(&video1394_highlevel);
-
- devfs_remove(VIDEO1394_DRIVER_NAME);
cdev_del(&video1394_cdev);
-
PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module");
}
@@ -1500,15 +1489,12 @@ static int __init video1394_init_module (void)
return ret;
}
- devfs_mk_dir(VIDEO1394_DRIVER_NAME);
-
hpsb_register_highlevel(&video1394_highlevel);
ret = hpsb_register_protocol(&video1394_driver);
if (ret) {
PRINT_G(KERN_ERR, "video1394: failed to register protocol");
hpsb_unregister_highlevel(&video1394_highlevel);
- devfs_remove(VIDEO1394_DRIVER_NAME);
cdev_del(&video1394_cdev);
return ret;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index f673c461e30..1bc2678c2fa 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -483,13 +483,20 @@ out:
return err;
}
-static void mthca_path_set(struct ib_ah_attr *ah, struct mthca_qp_path *path)
+static int mthca_path_set(struct mthca_dev *dev, struct ib_ah_attr *ah,
+ struct mthca_qp_path *path)
{
path->g_mylmc = ah->src_path_bits & 0x7f;
path->rlid = cpu_to_be16(ah->dlid);
path->static_rate = !!ah->static_rate;
if (ah->ah_flags & IB_AH_GRH) {
+ if (ah->grh.sgid_index >= dev->limits.gid_table_len) {
+ mthca_dbg(dev, "sgid_index (%u) too large. max is %d\n",
+ ah->grh.sgid_index, dev->limits.gid_table_len-1);
+ return -1;
+ }
+
path->g_mylmc |= 1 << 7;
path->mgid_index = ah->grh.sgid_index;
path->hop_limit = ah->grh.hop_limit;
@@ -500,6 +507,8 @@ static void mthca_path_set(struct ib_ah_attr *ah, struct mthca_qp_path *path)
memcpy(path->rgid, ah->grh.dgid.raw, 16);
} else
path->sl_tclass_flowlabel = cpu_to_be32(ah->sl << 28);
+
+ return 0;
}
int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
@@ -592,8 +601,14 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
if (qp->transport == MLX || qp->transport == UD)
qp_context->mtu_msgmax = (IB_MTU_2048 << 5) | 11;
- else if (attr_mask & IB_QP_PATH_MTU)
+ else if (attr_mask & IB_QP_PATH_MTU) {
+ if (attr->path_mtu < IB_MTU_256 || attr->path_mtu > IB_MTU_2048) {
+ mthca_dbg(dev, "path MTU (%u) is invalid\n",
+ attr->path_mtu);
+ return -EINVAL;
+ }
qp_context->mtu_msgmax = (attr->path_mtu << 5) | 31;
+ }
if (mthca_is_memfree(dev)) {
if (qp->rq.max)
@@ -642,7 +657,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
}
if (attr_mask & IB_QP_AV) {
- mthca_path_set(&attr->ah_attr, &qp_context->pri_path);
+ if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path))
+ return -EINVAL;
+
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH);
}
@@ -664,7 +681,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
return -EINVAL;
}
- mthca_path_set(&attr->alt_ah_attr, &qp_context->alt_path);
+ if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path))
+ return -EINVAL;
+
qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index |
attr->alt_port_num << 24);
qp_context->alt_path.ackto = attr->alt_timeout << 3;
@@ -758,21 +777,20 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
err = mthca_MODIFY_QP(dev, cur_state, new_state, qp->qpn, 0,
mailbox, sqd_event, &status);
+ if (err)
+ goto out;
if (status) {
mthca_warn(dev, "modify QP %d->%d returned status %02x.\n",
cur_state, new_state, status);
err = -EINVAL;
+ goto out;
}
- if (!err) {
- qp->state = new_state;
- if (attr_mask & IB_QP_ACCESS_FLAGS)
- qp->atomic_rd_en = attr->qp_access_flags;
- if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
- qp->resp_depth = attr->max_dest_rd_atomic;
- }
-
- mthca_free_mailbox(dev, mailbox);
+ qp->state = new_state;
+ if (attr_mask & IB_QP_ACCESS_FLAGS)
+ qp->atomic_rd_en = attr->qp_access_flags;
+ if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
+ qp->resp_depth = attr->max_dest_rd_atomic;
if (is_sqp(dev, qp))
store_attrs(to_msqp(qp), attr, attr_mask);
@@ -797,7 +815,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
* If we moved a kernel QP to RESET, clean up all old CQ
* entries and reinitialize the QP.
*/
- if (!err && new_state == IB_QPS_RESET && !qp->ibqp.uobject) {
+ if (new_state == IB_QPS_RESET && !qp->ibqp.uobject) {
mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn,
qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
@@ -816,6 +834,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
}
}
+out:
+ mthca_free_mailbox(dev, mailbox);
return err;
}
@@ -1177,10 +1197,6 @@ int mthca_alloc_qp(struct mthca_dev *dev,
{
int err;
- err = mthca_set_qp_size(dev, cap, pd, qp);
- if (err)
- return err;
-
switch (type) {
case IB_QPT_RC: qp->transport = RC; break;
case IB_QPT_UC: qp->transport = UC; break;
@@ -1188,6 +1204,10 @@ int mthca_alloc_qp(struct mthca_dev *dev,
default: return -EINVAL;
}
+ err = mthca_set_qp_size(dev, cap, pd, qp);
+ if (err)
+ return err;
+
qp->qpn = mthca_alloc(&dev->qp_table.alloc);
if (qp->qpn == -1)
return -ENOMEM;
@@ -1220,6 +1240,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1;
int err;
+ sqp->qp.transport = MLX;
err = mthca_set_qp_size(dev, cap, pd, &sqp->qp);
if (err)
return err;
@@ -1980,8 +2001,8 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
wmb();
((struct mthca_next_seg *) prev_wqe)->ee_nds =
cpu_to_be32(MTHCA_NEXT_DBD | size |
- ((wr->send_flags & IB_SEND_FENCE) ?
- MTHCA_NEXT_FENCE : 0));
+ ((wr->send_flags & IB_SEND_FENCE) ?
+ MTHCA_NEXT_FENCE : 0));
if (!size0) {
size0 = size;
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 47a6a754a59..0cfd1580221 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -205,6 +205,10 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
ds = max(64UL,
roundup_pow_of_two(sizeof (struct mthca_next_seg) +
srq->max_gs * sizeof (struct mthca_data_seg)));
+
+ if (ds > dev->limits.max_desc_sz)
+ return -EINVAL;
+
srq->wqe_shift = long_log2(ds);
srq->srqn = mthca_alloc(&dev->srq_table.alloc);
@@ -354,6 +358,8 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
return -EINVAL;
if (attr_mask & IB_SRQ_LIMIT) {
+ if (attr->srq_limit > srq->max)
+ return -EINVAL;
ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit, &status);
if (ret)
return ret;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 1251f86ec85..b640107fb73 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -72,13 +72,14 @@ enum {
IPOIB_MAX_MCAST_QUEUE = 3,
IPOIB_FLAG_OPER_UP = 0,
- IPOIB_FLAG_ADMIN_UP = 1,
- IPOIB_PKEY_ASSIGNED = 2,
- IPOIB_PKEY_STOP = 3,
- IPOIB_FLAG_SUBINTERFACE = 4,
- IPOIB_MCAST_RUN = 5,
- IPOIB_STOP_REAPER = 6,
- IPOIB_MCAST_STARTED = 7,
+ IPOIB_FLAG_INITIALIZED = 1,
+ IPOIB_FLAG_ADMIN_UP = 2,
+ IPOIB_PKEY_ASSIGNED = 3,
+ IPOIB_PKEY_STOP = 4,
+ IPOIB_FLAG_SUBINTERFACE = 5,
+ IPOIB_MCAST_RUN = 6,
+ IPOIB_STOP_REAPER = 7,
+ IPOIB_MCAST_STARTED = 8,
IPOIB_MAX_BACKOFF_SECONDS = 16,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index a1f5a05f2f3..ed65202878d 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -423,13 +423,33 @@ int ipoib_ib_dev_open(struct net_device *dev)
clear_bit(IPOIB_STOP_REAPER, &priv->flags);
queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, HZ);
+ set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
+
return 0;
}
+static void ipoib_pkey_dev_check_presence(struct net_device *dev)
+{
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ u16 pkey_index = 0;
+
+ if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index))
+ clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+ else
+ set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+}
+
int ipoib_ib_dev_up(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
+ ipoib_pkey_dev_check_presence(dev);
+
+ if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
+ ipoib_dbg(priv, "PKEY is not assigned.\n");
+ return 0;
+ }
+
set_bit(IPOIB_FLAG_OPER_UP, &priv->flags);
return ipoib_mcast_start_thread(dev);
@@ -483,6 +503,8 @@ int ipoib_ib_dev_stop(struct net_device *dev)
struct ipoib_tx_buf *tx_req;
int i;
+ clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
+
/*
* Move our QP to the error state and then reinitialize in
* when all work requests have completed or have been flushed.
@@ -587,8 +609,15 @@ void ipoib_ib_dev_flush(void *_dev)
struct net_device *dev = (struct net_device *)_dev;
struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv;
- if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
+ if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags) ) {
+ ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n");
+ return;
+ }
+
+ if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) {
+ ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_ADMIN_UP not set.\n");
return;
+ }
ipoib_dbg(priv, "flushing\n");
@@ -605,7 +634,7 @@ void ipoib_ib_dev_flush(void *_dev)
/* Flush any child interfaces too */
list_for_each_entry(cpriv, &priv->child_intfs, list)
- ipoib_ib_dev_flush(&cpriv->dev);
+ ipoib_ib_dev_flush(cpriv->dev);
mutex_unlock(&priv->vlan_mutex);
}
@@ -632,17 +661,6 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
* change async notification is available.
*/
-static void ipoib_pkey_dev_check_presence(struct net_device *dev)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- u16 pkey_index = 0;
-
- if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index))
- clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
- else
- set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
-}
-
void ipoib_pkey_poll(void *dev_ptr)
{
struct net_device *dev = dev_ptr;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 37da8d3dc38..53a32f65788 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -736,6 +736,11 @@ static void ipoib_set_mcast_list(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
+ if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) {
+ ipoib_dbg(priv, "IPOIB_FLAG_OPER_UP not set");
+ return;
+ }
+
queue_work(ipoib_workqueue, &priv->restart_task);
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 18d2f53ec34..5f0388027b2 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -251,10 +251,12 @@ void ipoib_event(struct ib_event_handler *handler,
struct ipoib_dev_priv *priv =
container_of(handler, struct ipoib_dev_priv, event_handler);
- if (record->event == IB_EVENT_PORT_ACTIVE ||
+ if (record->event == IB_EVENT_PORT_ERR ||
+ record->event == IB_EVENT_PKEY_CHANGE ||
+ record->event == IB_EVENT_PORT_ACTIVE ||
record->event == IB_EVENT_LID_CHANGE ||
record->event == IB_EVENT_SM_CHANGE) {
- ipoib_dbg(priv, "Port active event\n");
+ ipoib_dbg(priv, "Port state change event\n");
queue_work(ipoib_workqueue, &priv->flush_task);
}
}
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index a13dcdf90a4..61924cc30e5 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -503,8 +503,10 @@ err:
static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
struct srp_request *req)
{
+ struct scatterlist *scat;
struct srp_cmd *cmd = req->cmd->buf;
- int len;
+ int len, nents, count;
+ int i;
u8 fmt;
if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE)
@@ -517,82 +519,66 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
return -EINVAL;
}
- if (scmnd->use_sg) {
- struct scatterlist *scat = scmnd->request_buffer;
- int n;
- int i;
-
- n = dma_map_sg(target->srp_host->dev->dma_device,
- scat, scmnd->use_sg, scmnd->sc_data_direction);
+ /*
+ * This handling of non-SG commands can be killed when the
+ * SCSI midlayer no longer generates non-SG commands.
+ */
+ if (likely(scmnd->use_sg)) {
+ nents = scmnd->use_sg;
+ scat = scmnd->request_buffer;
+ } else {
+ nents = 1;
+ scat = &req->fake_sg;
+ sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen);
+ }
- if (n == 1) {
- struct srp_direct_buf *buf = (void *) cmd->add_data;
+ count = dma_map_sg(target->srp_host->dev->dma_device, scat, nents,
+ scmnd->sc_data_direction);
- fmt = SRP_DATA_DESC_DIRECT;
+ if (count == 1) {
+ struct srp_direct_buf *buf = (void *) cmd->add_data;
- buf->va = cpu_to_be64(sg_dma_address(scat));
- buf->key = cpu_to_be32(target->srp_host->mr->rkey);
- buf->len = cpu_to_be32(sg_dma_len(scat));
+ fmt = SRP_DATA_DESC_DIRECT;
- len = sizeof (struct srp_cmd) +
- sizeof (struct srp_direct_buf);
- } else {
- struct srp_indirect_buf *buf = (void *) cmd->add_data;
- u32 datalen = 0;
+ buf->va = cpu_to_be64(sg_dma_address(scat));
+ buf->key = cpu_to_be32(target->srp_host->mr->rkey);
+ buf->len = cpu_to_be32(sg_dma_len(scat));
- fmt = SRP_DATA_DESC_INDIRECT;
+ len = sizeof (struct srp_cmd) +
+ sizeof (struct srp_direct_buf);
+ } else {
+ struct srp_indirect_buf *buf = (void *) cmd->add_data;
+ u32 datalen = 0;
- if (scmnd->sc_data_direction == DMA_TO_DEVICE)
- cmd->data_out_desc_cnt = n;
- else
- cmd->data_in_desc_cnt = n;
+ fmt = SRP_DATA_DESC_INDIRECT;
- buf->table_desc.va = cpu_to_be64(req->cmd->dma +
- sizeof *cmd +
- sizeof *buf);
- buf->table_desc.key =
+ if (scmnd->sc_data_direction == DMA_TO_DEVICE)
+ cmd->data_out_desc_cnt = count;
+ else
+ cmd->data_in_desc_cnt = count;
+
+ buf->table_desc.va = cpu_to_be64(req->cmd->dma +
+ sizeof *cmd +
+ sizeof *buf);
+ buf->table_desc.key =
+ cpu_to_be32(target->srp_host->mr->rkey);
+ buf->table_desc.len =
+ cpu_to_be32(count * sizeof (struct srp_direct_buf));
+
+ for (i = 0; i < count; ++i) {
+ buf->desc_list[i].va = cpu_to_be64(sg_dma_address(&scat[i]));
+ buf->desc_list[i].key =
cpu_to_be32(target->srp_host->mr->rkey);
- buf->table_desc.len =
- cpu_to_be32(n * sizeof (struct srp_direct_buf));
-
- for (i = 0; i < n; ++i) {
- buf->desc_list[i].va = cpu_to_be64(sg_dma_address(&scat[i]));
- buf->desc_list[i].key =
- cpu_to_be32(target->srp_host->mr->rkey);
- buf->desc_list[i].len = cpu_to_be32(sg_dma_len(&scat[i]));
-
- datalen += sg_dma_len(&scat[i]);
- }
+ buf->desc_list[i].len = cpu_to_be32(sg_dma_len(&scat[i]));
- buf->len = cpu_to_be32(datalen);
-
- len = sizeof (struct srp_cmd) +
- sizeof (struct srp_indirect_buf) +
- n * sizeof (struct srp_direct_buf);
- }
- } else {
- struct srp_direct_buf *buf = (void *) cmd->add_data;
- dma_addr_t dma;
-
- dma = dma_map_single(target->srp_host->dev->dma_device,
- scmnd->request_buffer, scmnd->request_bufflen,
- scmnd->sc_data_direction);
- if (dma_mapping_error(dma)) {
- printk(KERN_WARNING PFX "unable to map %p/%d (dir %d)\n",
- scmnd->request_buffer, (int) scmnd->request_bufflen,
- scmnd->sc_data_direction);
- return -EINVAL;
+ datalen += sg_dma_len(&scat[i]);
}
- pci_unmap_addr_set(req, direct_mapping, dma);
+ buf->len = cpu_to_be32(datalen);
- buf->va = cpu_to_be64(dma);
- buf->key = cpu_to_be32(target->srp_host->mr->rkey);
- buf->len = cpu_to_be32(scmnd->request_bufflen);
-
- fmt = SRP_DATA_DESC_DIRECT;
-
- len = sizeof (struct srp_cmd) + sizeof (struct srp_direct_buf);
+ len = sizeof (struct srp_cmd) +
+ sizeof (struct srp_indirect_buf) +
+ count * sizeof (struct srp_direct_buf);
}
if (scmnd->sc_data_direction == DMA_TO_DEVICE)
@@ -600,7 +586,6 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
else
cmd->buf_fmt = fmt;
-
return len;
}
@@ -608,20 +593,28 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
struct srp_target_port *target,
struct srp_request *req)
{
+ struct scatterlist *scat;
+ int nents;
+
if (!scmnd->request_buffer ||
(scmnd->sc_data_direction != DMA_TO_DEVICE &&
scmnd->sc_data_direction != DMA_FROM_DEVICE))
- return;
+ return;
- if (scmnd->use_sg)
- dma_unmap_sg(target->srp_host->dev->dma_device,
- (struct scatterlist *) scmnd->request_buffer,
- scmnd->use_sg, scmnd->sc_data_direction);
- else
- dma_unmap_single(target->srp_host->dev->dma_device,
- pci_unmap_addr(req, direct_mapping),
- scmnd->request_bufflen,
- scmnd->sc_data_direction);
+ /*
+ * This handling of non-SG commands can be killed when the
+ * SCSI midlayer no longer generates non-SG commands.
+ */
+ if (likely(scmnd->use_sg)) {
+ nents = scmnd->use_sg;
+ scat = (struct scatterlist *) scmnd->request_buffer;
+ } else {
+ nents = 1;
+ scat = (struct scatterlist *) scmnd->request_buffer;
+ }
+
+ dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents,
+ scmnd->sc_data_direction);
}
static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index 4e7727df32f..bd7f7c3115d 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -38,6 +38,7 @@
#include <linux/types.h>
#include <linux/list.h>
#include <linux/mutex.h>
+#include <linux/scatterlist.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
@@ -94,7 +95,11 @@ struct srp_request {
struct scsi_cmnd *scmnd;
struct srp_iu *cmd;
struct srp_iu *tsk_mgmt;
- DECLARE_PCI_UNMAP_ADDR(direct_mapping)
+ /*
+ * Fake scatterlist used when scmnd->use_sg==0. Can be killed
+ * when the SCSI midlayer no longer generates non-SG commands.
+ */
+ struct scatterlist fake_sg;
struct completion done;
short next;
u8 cmd_done;
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 4fe3da3c667..f8af0945964 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -923,7 +923,7 @@ void input_unregister_handler(struct input_handler *handler)
static int input_open_file(struct inode *inode, struct file *file)
{
struct input_handler *handler = input_table[iminor(inode) >> 5];
- struct file_operations *old_fops, *new_fops = NULL;
+ const struct file_operations *old_fops, *new_fops = NULL;
int err;
/* No load-on-demand here? */
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 5704204964a..ea499783fb1 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -556,7 +556,7 @@ static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) {
do_gettimeofday(&(mlc->instart));
mlc->icount = 15;
memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));
- if (down_trylock(&(mlc->isem))) BUG();
+ BUG_ON(down_trylock(&(mlc->isem)));
return;
}
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
index 1c9426fd520..aa4a8a4ccfd 100644
--- a/drivers/input/serio/hp_sdc_mlc.c
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -270,9 +270,10 @@ static void hp_sdc_mlc_out (hil_mlc *mlc) {
do_control:
priv->emtestmode = mlc->opacket & HIL_CTRL_TEST;
- if ((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE) {
- BUG(); /* we cannot emulate this, it should not be used. */
- }
+
+ /* we cannot emulate this, it should not be used. */
+ BUG_ON((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE);
+
if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only;
if (mlc->opacket & HIL_CTRL_APE) {
BUG(); /* Should not send command/data after engaging APE */
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 8c12a974b41..46d1fec2cfd 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
+#include <asm/irq.h>
#ifdef CONFIG_ARM
#include <asm/mach-types.h>
diff --git a/drivers/isdn/Makefile b/drivers/isdn/Makefile
index 03d8ccd5195..988142c30a6 100644
--- a/drivers/isdn/Makefile
+++ b/drivers/isdn/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_ISDN_DRV_SC) += sc/
obj-$(CONFIG_ISDN_DRV_LOOP) += isdnloop/
obj-$(CONFIG_ISDN_DRV_ACT2000) += act2000/
obj-$(CONFIG_HYSDN) += hysdn/
+obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset/
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 623adbb0d13..9b493f0becc 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1485,6 +1485,7 @@ static int __init capi_init(void)
{
char *p;
char *compileinfo;
+ int major_ret;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strlcpy(rev, p + 2, sizeof(rev));
@@ -1493,11 +1494,12 @@ static int __init capi_init(void)
} else
strcpy(rev, "1.0");
- if (register_chrdev(capi_major, "capi20", &capi_fops)) {
+ major_ret = register_chrdev(capi_major, "capi20", &capi_fops);
+ if (major_ret < 0) {
printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
- return -EIO;
+ return major_ret;
}
-
+ capi_major = major_ret;
capi_class = class_create(THIS_MODULE, "capi");
if (IS_ERR(capi_class)) {
unregister_chrdev(capi_major, "capi20");
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
index 2cc8b27e4c3..ca9dc00a45c 100644
--- a/drivers/isdn/capi/kcapi_proc.c
+++ b/drivers/isdn/capi/kcapi_proc.c
@@ -233,7 +233,7 @@ static struct file_operations proc_applstats_ops = {
};
static void
-create_seq_entry(char *name, mode_t mode, struct file_operations *f)
+create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
{
struct proc_dir_entry *entry;
entry = create_proc_entry(name, mode, NULL);
diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig
new file mode 100644
index 00000000000..53c4fb62ed8
--- /dev/null
+++ b/drivers/isdn/gigaset/Kconfig
@@ -0,0 +1,42 @@
+menu "Siemens Gigaset"
+ depends on ISDN_I4L
+
+config ISDN_DRV_GIGASET
+ tristate "Siemens Gigaset support (isdn)"
+ depends on ISDN_I4L && m
+# depends on ISDN_I4L && MODULES
+ help
+ Say m here if you have a Gigaset or Sinus isdn device.
+
+if ISDN_DRV_GIGASET!=n
+
+config GIGASET_BASE
+ tristate "Gigaset base station support"
+ depends on ISDN_DRV_GIGASET && USB
+ help
+ Say m here if you need to communicate with the base
+ directly via USB.
+
+config GIGASET_M105
+ tristate "Gigaset M105 support"
+ depends on ISDN_DRV_GIGASET && USB
+ help
+ Say m here if you need the driver for the Gigaset M105 device.
+
+config GIGASET_DEBUG
+ bool "Gigaset debugging"
+ help
+ This enables debugging code in the Gigaset drivers.
+ If in doubt, say yes.
+
+config GIGASET_UNDOCREQ
+ bool "Support for undocumented USB requests"
+ help
+ This enables support for USB requests we only know from
+ reverse engineering (currently M105 only). If you need
+ features like configuration mode of M105, say yes. If you
+ care about your device, say no.
+
+endif
+
+endmenu
diff --git a/drivers/isdn/gigaset/Makefile b/drivers/isdn/gigaset/Makefile
new file mode 100644
index 00000000000..9b9acf1a21a
--- /dev/null
+++ b/drivers/isdn/gigaset/Makefile
@@ -0,0 +1,6 @@
+gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o
+usb_gigaset-y := usb-gigaset.o asyncdata.o
+bas_gigaset-y := bas-gigaset.o isocdata.o
+
+obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o gigaset.o
+obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o gigaset.o
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
new file mode 100644
index 00000000000..171f8b703d6
--- /dev/null
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -0,0 +1,597 @@
+/*
+ * Common data handling layer for ser_gigaset and usb_gigaset
+ *
+ * Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>,
+ * Hansjoerg Lipp <hjlipp@web.de>,
+ * Stefan Eilers <Eilers.Stefan@epost.de>.
+ *
+ * =====================================================================
+ * 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.
+ * =====================================================================
+ * ToDo: ...
+ * =====================================================================
+ * Version: $Id: asyncdata.c,v 1.2.2.7 2005/11/13 23:05:18 hjlipp Exp $
+ * =====================================================================
+ */
+
+#include "gigaset.h"
+#include <linux/crc-ccitt.h>
+
+//#define GIG_M10x_STUFF_VOICE_DATA
+
+/* check if byte must be stuffed/escaped
+ * I'm not sure which data should be encoded.
+ * Therefore I will go the hard way and decode every value
+ * less than 0x20, the flag sequence and the control escape char.
+ */
+static inline int muststuff(unsigned char c)
+{
+ if (c < PPP_TRANS) return 1;
+ if (c == PPP_FLAG) return 1;
+ if (c == PPP_ESCAPE) return 1;
+ /* other possible candidates: */
+ /* 0x91: XON with parity set */
+ /* 0x93: XOFF with parity set */
+ return 0;
+}
+
+/* == data input =========================================================== */
+
+/* process a block of received bytes in command mode (modem response)
+ * Return value:
+ * number of processed bytes
+ */
+static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
+ struct inbuf_t *inbuf)
+{
+ struct cardstate *cs = inbuf->cs;
+ unsigned cbytes = cs->cbytes;
+ int inputstate = inbuf->inputstate;
+ int startbytes = numbytes;
+
+ for (;;) {
+ cs->respdata[cbytes] = c;
+ if (c == 10 || c == 13) {
+ dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
+ __func__, cbytes);
+ cs->cbytes = cbytes;
+ gigaset_handle_modem_response(cs); /* can change cs->dle */
+ cbytes = 0;
+
+ if (cs->dle &&
+ !(inputstate & INS_DLE_command)) {
+ inputstate &= ~INS_command;
+ break;
+ }
+ } else {
+ /* advance in line buffer, checking for overflow */
+ if (cbytes < MAX_RESP_SIZE - 1)
+ cbytes++;
+ else
+ warn("response too large");
+ }
+
+ if (!numbytes)
+ break;
+ c = *src++;
+ --numbytes;
+ if (c == DLE_FLAG &&
+ (cs->dle || inputstate & INS_DLE_command)) {
+ inputstate |= INS_DLE_char;
+ break;
+ }
+ }
+
+ cs->cbytes = cbytes;
+ inbuf->inputstate = inputstate;
+
+ return startbytes - numbytes;
+}
+
+/* process a block of received bytes in lock mode (tty i/f)
+ * Return value:
+ * number of processed bytes
+ */
+static inline int lock_loop(unsigned char *src, int numbytes,
+ struct inbuf_t *inbuf)
+{
+ struct cardstate *cs = inbuf->cs;
+
+ gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src, 0);
+ gigaset_if_receive(cs, src, numbytes);
+
+ return numbytes;
+}
+
+/* process a block of received bytes in HDLC data mode
+ * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
+ * When a frame is complete, check the FCS and pass valid frames to the LL.
+ * If DLE is encountered, return immediately to let the caller handle it.
+ * Return value:
+ * number of processed bytes
+ * numbytes (all bytes processed) on error --FIXME
+ */
+static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
+ struct inbuf_t *inbuf)
+{
+ struct cardstate *cs = inbuf->cs;
+ struct bc_state *bcs = inbuf->bcs;
+ int inputstate;
+ __u16 fcs;
+ struct sk_buff *skb;
+ unsigned char error;
+ struct sk_buff *compskb;
+ int startbytes = numbytes;
+ int l;
+
+ IFNULLRETVAL(bcs, numbytes);
+ inputstate = bcs->inputstate;
+ fcs = bcs->fcs;
+ skb = bcs->skb;
+ IFNULLRETVAL(skb, numbytes);
+
+ if (unlikely(inputstate & INS_byte_stuff)) {
+ inputstate &= ~INS_byte_stuff;
+ goto byte_stuff;
+ }
+ for (;;) {
+ if (unlikely(c == PPP_ESCAPE)) {
+ if (unlikely(!numbytes)) {
+ inputstate |= INS_byte_stuff;
+ break;
+ }
+ c = *src++;
+ --numbytes;
+ if (unlikely(c == DLE_FLAG &&
+ (cs->dle ||
+ inbuf->inputstate & INS_DLE_command))) {
+ inbuf->inputstate |= INS_DLE_char;
+ inputstate |= INS_byte_stuff;
+ break;
+ }
+byte_stuff:
+ c ^= PPP_TRANS;
+#ifdef CONFIG_GIGASET_DEBUG
+ if (unlikely(!muststuff(c)))
+ dbg(DEBUG_HDLC,
+ "byte stuffed: 0x%02x", c);
+#endif
+ } else if (unlikely(c == PPP_FLAG)) {
+ if (unlikely(inputstate & INS_skip_frame)) {
+ if (!(inputstate & INS_have_data)) { /* 7E 7E */
+ //dbg(DEBUG_HDLC, "(7e)7e------------------------");
+#ifdef CONFIG_GIGASET_DEBUG
+ ++bcs->emptycount;
+#endif
+ } else
+ dbg(DEBUG_HDLC,
+ "7e----------------------------");
+
+ /* end of frame */
+ error = 1;
+ gigaset_rcv_error(NULL, cs, bcs);
+ } else if (!(inputstate & INS_have_data)) { /* 7E 7E */
+ //dbg(DEBUG_HDLC, "(7e)7e------------------------");
+#ifdef CONFIG_GIGASET_DEBUG
+ ++bcs->emptycount;
+#endif
+ break;
+ } else {
+ dbg(DEBUG_HDLC,
+ "7e----------------------------");
+
+ /* end of frame */
+ error = 0;
+
+ if (unlikely(fcs != PPP_GOODFCS)) {
+ err("Packet checksum at %lu failed, "
+ "packet is corrupted (%u bytes)!",
+ bcs->rcvbytes, skb->len);
+ compskb = NULL;
+ gigaset_rcv_error(compskb, cs, bcs);
+ error = 1;
+ } else {
+ if (likely((l = skb->len) > 2)) {
+ skb->tail -= 2;
+ skb->len -= 2;
+ } else {
+ dev_kfree_skb(skb);
+ skb = NULL;
+ inputstate |= INS_skip_frame;
+ if (l == 1) {
+ err("invalid packet size (1)!");
+ error = 1;
+ gigaset_rcv_error(NULL, cs, bcs);
+ }
+ }
+ if (likely(!(error ||
+ (inputstate &
+ INS_skip_frame)))) {
+ gigaset_rcv_skb(skb, cs, bcs);
+ }
+ }
+ }
+
+ if (unlikely(error))
+ if (skb)
+ dev_kfree_skb(skb);
+
+ fcs = PPP_INITFCS;
+ inputstate &= ~(INS_have_data | INS_skip_frame);
+ if (unlikely(bcs->ignore)) {
+ inputstate |= INS_skip_frame;
+ skb = NULL;
+ } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) {
+ skb_reserve(skb, HW_HDR_LEN);
+ } else {
+ warn("could not allocate new skb");
+ inputstate |= INS_skip_frame;
+ }
+
+ break;
+#ifdef CONFIG_GIGASET_DEBUG
+ } else if (unlikely(muststuff(c))) {
+ /* Should not happen. Possible after ZDLE=1<CR><LF>. */
+ dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
+#endif
+ }
+
+ /* add character */
+
+#ifdef CONFIG_GIGASET_DEBUG
+ if (unlikely(!(inputstate & INS_have_data))) {
+ dbg(DEBUG_HDLC,
+ "7e (%d x) ================", bcs->emptycount);
+ bcs->emptycount = 0;
+ }
+#endif
+
+ inputstate |= INS_have_data;
+
+ if (likely(!(inputstate & INS_skip_frame))) {
+ if (unlikely(skb->len == SBUFSIZE)) {
+ warn("received packet too long");
+ dev_kfree_skb_any(skb);
+ skb = NULL;
+ inputstate |= INS_skip_frame;
+ break;
+ }
+ *gigaset_skb_put_quick(skb, 1) = c;
+ /* *__skb_put (skb, 1) = c; */
+ fcs = crc_ccitt_byte(fcs, c);
+ }
+
+ if (unlikely(!numbytes))
+ break;
+ c = *src++;
+ --numbytes;
+ if (unlikely(c == DLE_FLAG &&
+ (cs->dle ||
+ inbuf->inputstate & INS_DLE_command))) {
+ inbuf->inputstate |= INS_DLE_char;
+ break;
+ }
+ }
+ bcs->inputstate = inputstate;
+ bcs->fcs = fcs;
+ bcs->skb = skb;
+ return startbytes - numbytes;
+}
+
+/* process a block of received bytes in transparent data mode
+ * Invert bytes, undoing byte stuffing and watching for DLE escapes.
+ * If DLE is encountered, return immediately to let the caller handle it.
+ * Return value:
+ * number of processed bytes
+ * numbytes (all bytes processed) on error --FIXME
+ */
+static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
+ struct inbuf_t *inbuf)
+{
+ struct cardstate *cs = inbuf->cs;
+ struct bc_state *bcs = inbuf->bcs;
+ int inputstate;
+ struct sk_buff *skb;
+ int startbytes = numbytes;
+
+ IFNULLRETVAL(bcs, numbytes);
+ inputstate = bcs->inputstate;
+ skb = bcs->skb;
+ IFNULLRETVAL(skb, numbytes);
+
+ for (;;) {
+ /* add character */
+ inputstate |= INS_have_data;
+
+ if (likely(!(inputstate & INS_skip_frame))) {
+ if (unlikely(skb->len == SBUFSIZE)) {
+ //FIXME just pass skb up and allocate a new one
+ warn("received packet too long");
+ dev_kfree_skb_any(skb);
+ skb = NULL;
+ inputstate |= INS_skip_frame;
+ break;
+ }
+ *gigaset_skb_put_quick(skb, 1) = gigaset_invtab[c];
+ }
+
+ if (unlikely(!numbytes))
+ break;
+ c = *src++;
+ --numbytes;
+ if (unlikely(c == DLE_FLAG &&
+ (cs->dle ||
+ inbuf->inputstate & INS_DLE_command))) {
+ inbuf->inputstate |= INS_DLE_char;
+ break;
+ }
+ }
+
+ /* pass data up */
+ if (likely(inputstate & INS_have_data)) {
+ if (likely(!(inputstate & INS_skip_frame))) {
+ gigaset_rcv_skb(skb, cs, bcs);
+ }
+ inputstate &= ~(INS_have_data | INS_skip_frame);
+ if (unlikely(bcs->ignore)) {
+ inputstate |= INS_skip_frame;
+ skb = NULL;
+ } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN))
+ != NULL)) {
+ skb_reserve(skb, HW_HDR_LEN);
+ } else {
+ warn("could not allocate new skb");
+ inputstate |= INS_skip_frame;
+ }
+ }
+
+ bcs->inputstate = inputstate;
+ bcs->skb = skb;
+ return startbytes - numbytes;
+}
+
+/* process a block of data received from the device
+ */
+void gigaset_m10x_input(struct inbuf_t *inbuf)
+{
+ struct cardstate *cs;
+ unsigned tail, head, numbytes;
+ unsigned char *src, c;
+ int procbytes;
+
+ head = atomic_read(&inbuf->head);
+ tail = atomic_read(&inbuf->tail);
+ dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
+
+ if (head != tail) {
+ cs = inbuf->cs;
+ src = inbuf->data + head;
+ numbytes = (head > tail ? RBUFSIZE : tail) - head;
+ dbg(DEBUG_INTR, "processing %u bytes", numbytes);
+
+ while (numbytes) {
+ if (atomic_read(&cs->mstate) == MS_LOCKED) {
+ procbytes = lock_loop(src, numbytes, inbuf);
+ src += procbytes;
+ numbytes -= procbytes;
+ } else {
+ c = *src++;
+ --numbytes;
+ if (c == DLE_FLAG && (cs->dle ||
+ inbuf->inputstate & INS_DLE_command)) {
+ if (!(inbuf->inputstate & INS_DLE_char)) {
+ inbuf->inputstate |= INS_DLE_char;
+ goto nextbyte;
+ }
+ /* <DLE> <DLE> => <DLE> in data stream */
+ inbuf->inputstate &= ~INS_DLE_char;
+ }
+
+ if (!(inbuf->inputstate & INS_DLE_char)) {
+
+ /* FIXME Einfach je nach Modus Funktionszeiger in cs setzen [hier+hdlc_loop]? */
+ /* FIXME Spart folgendes "if" und ermoeglicht andere Protokolle */
+ if (inbuf->inputstate & INS_command)
+ procbytes = cmd_loop(c, src, numbytes, inbuf);
+ else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC)
+ procbytes = hdlc_loop(c, src, numbytes, inbuf);
+ else
+ procbytes = iraw_loop(c, src, numbytes, inbuf);
+
+ src += procbytes;
+ numbytes -= procbytes;
+ } else { /* DLE-char */
+ inbuf->inputstate &= ~INS_DLE_char;
+ switch (c) {
+ case 'X': /*begin of command*/
+#ifdef CONFIG_GIGASET_DEBUG
+ if (inbuf->inputstate & INS_command)
+ err("received <DLE> 'X' in command mode");
+#endif
+ inbuf->inputstate |=
+ INS_command | INS_DLE_command;
+ break;
+ case '.': /*end of command*/
+#ifdef CONFIG_GIGASET_DEBUG
+ if (!(inbuf->inputstate & INS_command))
+ err("received <DLE> '.' in hdlc mode");
+#endif
+ inbuf->inputstate &= cs->dle ?
+ ~(INS_DLE_command|INS_command)
+ : ~INS_DLE_command;
+ break;
+ //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
+ default:
+ err("received 0x10 0x%02x!", (int) c);
+ /* FIXME: reset driver?? */
+ }
+ }
+ }
+nextbyte:
+ if (!numbytes) {
+ /* end of buffer, check for wrap */
+ if (head > tail) {
+ head = 0;
+ src = inbuf->data;
+ numbytes = tail;
+ } else {
+ head = tail;
+ break;
+ }
+ }
+ }
+
+ dbg(DEBUG_INTR, "setting head to %u", head);
+ atomic_set(&inbuf->head, head);
+ }
+}
+
+
+/* == data output ========================================================== */
+
+/* Encoding of a PPP packet into an octet stuffed HDLC frame
+ * with FCS, opening and closing flags.
+ * parameters:
+ * skb skb containing original packet (freed upon return)
+ * head number of headroom bytes to allocate in result skb
+ * tail number of tailroom bytes to allocate in result skb
+ * Return value:
+ * pointer to newly allocated skb containing the result frame
+ */
+static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
+{
+ struct sk_buff *hdlc_skb;
+ __u16 fcs;
+ unsigned char c;
+ unsigned char *cp;
+ int len;
+ unsigned int stuf_cnt;
+
+ stuf_cnt = 0;
+ fcs = PPP_INITFCS;
+ cp = skb->data;
+ len = skb->len;
+ while (len--) {
+ if (muststuff(*cp))
+ stuf_cnt++;
+ fcs = crc_ccitt_byte(fcs, *cp++);
+ }
+ fcs ^= 0xffff; /* complement */
+
+ /* size of new buffer: original size + number of stuffing bytes
+ * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
+ */
+ hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head);
+ if (!hdlc_skb) {
+ err("unable to allocate memory for HDLC encoding!");
+ dev_kfree_skb(skb);
+ return NULL;
+ }
+ skb_reserve(hdlc_skb, head);
+
+ /* Copy acknowledge request into new skb */
+ memcpy(hdlc_skb->head, skb->head, 2);
+
+ /* Add flag sequence in front of everything.. */
+ *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
+
+ /* Perform byte stuffing while copying data. */
+ while (skb->len--) {
+ if (muststuff(*skb->data)) {
+ *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
+ *(skb_put(hdlc_skb, 1)) = (*skb->data++) ^ PPP_TRANS;
+ } else
+ *(skb_put(hdlc_skb, 1)) = *skb->data++;
+ }
+
+ /* Finally add FCS (byte stuffed) and flag sequence */
+ c = (fcs & 0x00ff); /* least significant byte first */
+ if (muststuff(c)) {
+ *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
+ c ^= PPP_TRANS;
+ }
+ *(skb_put(hdlc_skb, 1)) = c;
+
+ c = ((fcs >> 8) & 0x00ff);
+ if (muststuff(c)) {
+ *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
+ c ^= PPP_TRANS;
+ }
+ *(skb_put(hdlc_skb, 1)) = c;
+
+ *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
+
+ dev_kfree_skb(skb);
+ return hdlc_skb;
+}
+
+/* Encoding of a raw packet into an octet stuffed bit inverted frame
+ * parameters:
+ * skb skb containing original packet (freed upon return)
+ * head number of headroom bytes to allocate in result skb
+ * tail number of tailroom bytes to allocate in result skb
+ * Return value:
+ * pointer to newly allocated skb containing the result frame
+ */
+static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
+{
+ struct sk_buff *iraw_skb;
+ unsigned char c;
+ unsigned char *cp;
+ int len;
+
+ /* worst case: every byte must be stuffed */
+ iraw_skb = dev_alloc_skb(2*skb->len + tail + head);
+ if (!iraw_skb) {
+ err("unable to allocate memory for HDLC encoding!");
+ dev_kfree_skb(skb);
+ return NULL;
+ }
+ skb_reserve(iraw_skb, head);
+
+ cp = skb->data;
+ len = skb->len;
+ while (len--) {
+ c = gigaset_invtab[*cp++];
+ if (c == DLE_FLAG)
+ *(skb_put(iraw_skb, 1)) = c;
+ *(skb_put(iraw_skb, 1)) = c;
+ }
+ dev_kfree_skb(skb);
+ return iraw_skb;
+}
+
+/* gigaset_send_skb
+ * called by common.c to queue an skb for sending
+ * and start transmission if necessary
+ * parameters:
+ * B Channel control structure
+ * skb
+ * Return value:
+ * number of bytes accepted for sending
+ * (skb->len if ok, 0 if out of buffer space)
+ * or error code (< 0, eg. -EINVAL)
+ */
+int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
+{
+ unsigned len;
+
+ IFNULLRETVAL(bcs, -EFAULT);
+ IFNULLRETVAL(skb, -EFAULT);
+ len = skb->len;
+
+ if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
+ skb = HDLC_Encode(skb, HW_HDR_LEN, 0);
+ else
+ skb = iraw_encode(skb, HW_HDR_LEN, 0);
+ if (!skb)
+ return -ENOMEM;
+
+ skb_queue_tail(&bcs->squeue, skb);
+ tasklet_schedule(&bcs->cs->write_tasklet);
+
+ return len; /* ok so far */
+}
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
new file mode 100644
index 00000000000..31f0f07832b
--- /dev/null
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -0,0 +1,2365 @@
+/*
+ * USB driver for Gigaset 307x base via direct USB connection.
+ *
+ * Copyright (c) 2001 by Hansjoerg Lipp <hjlipp@web.de>,
+ * Tilman Schmidt <tilman@imap.cc>,
+ * Stefan Eilers <Eilers.Stefan@epost.de>.
+ *
+ * Based on usb-gigaset.c.
+ *
+ * =====================================================================
+ * 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.
+ * =====================================================================
+ * ToDo: ...
+ * =====================================================================
+ * Version: $Id: bas-gigaset.c,v 1.52.4.19 2006/02/04 18:28:16 hjlipp Exp $
+ * =====================================================================
+ */
+
+#include "gigaset.h"
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/usb.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+/* Version Information */
+#define DRIVER_AUTHOR "Tilman Schmidt <tilman@imap.cc>, Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_DESC "USB Driver for Gigaset 307x"
+
+
+/* Module parameters */
+
+static int startmode = SM_ISDN;
+static int cidmode = 1;
+
+module_param(startmode, int, S_IRUGO);
+module_param(cidmode, int, S_IRUGO);
+MODULE_PARM_DESC(startmode, "start in isdn4linux mode");
+MODULE_PARM_DESC(cidmode, "Call-ID mode");
+
+#define GIGASET_MINORS 1
+#define GIGASET_MINOR 16
+#define GIGASET_MODULENAME "bas_gigaset"
+#define GIGASET_DEVFSNAME "gig/bas/"
+#define GIGASET_DEVNAME "ttyGB"
+
+#define IF_WRITEBUF 256 //FIXME
+
+/* Values for the Gigaset 307x */
+#define USB_GIGA_VENDOR_ID 0x0681
+#define USB_GIGA_PRODUCT_ID 0x0001
+#define USB_4175_PRODUCT_ID 0x0002
+#define USB_SX303_PRODUCT_ID 0x0021
+#define USB_SX353_PRODUCT_ID 0x0022
+
+/* table of devices that work with this driver */
+static struct usb_device_id gigaset_table [] = {
+ { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_GIGA_PRODUCT_ID) },
+ { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_4175_PRODUCT_ID) },
+ { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) },
+ { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX353_PRODUCT_ID) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, gigaset_table);
+
+/* Get a minor range for your devices from the usb maintainer */
+#define USB_SKEL_MINOR_BASE 200
+
+/*======================= local function prototypes =============================*/
+
+/* This function is called if a new device is connected to the USB port. It
+ * checks whether this new device belongs to this driver.
+ */
+static int gigaset_probe(struct usb_interface *interface,
+ const struct usb_device_id *id);
+
+/* Function will be called if the device is unplugged */
+static void gigaset_disconnect(struct usb_interface *interface);
+
+
+/*==============================================================================*/
+
+struct bas_cardstate {
+ struct usb_device *udev; /* USB device pointer */
+ struct usb_interface *interface; /* interface for this device */
+ unsigned char minor; /* starting minor number */
+
+ struct urb *urb_ctrl; /* control pipe default URB */
+ struct usb_ctrlrequest dr_ctrl;
+ struct timer_list timer_ctrl; /* control request timeout */
+
+ struct timer_list timer_atrdy; /* AT command ready timeout */
+ struct urb *urb_cmd_out; /* for sending AT commands */
+ struct usb_ctrlrequest dr_cmd_out;
+ int retry_cmd_out;
+
+ struct urb *urb_cmd_in; /* for receiving AT replies */
+ struct usb_ctrlrequest dr_cmd_in;
+ struct timer_list timer_cmd_in; /* receive request timeout */
+ unsigned char *rcvbuf; /* AT reply receive buffer */
+
+ struct urb *urb_int_in; /* URB for interrupt pipe */
+ unsigned char int_in_buf[3];
+
+ spinlock_t lock; /* locks all following */
+ atomic_t basstate; /* bitmap (BS_*) */
+ int pending; /* uncompleted base request */
+ int rcvbuf_size; /* size of AT receive buffer */
+ /* 0: no receive in progress */
+ int retry_cmd_in; /* receive req retry count */
+};
+
+/* status of direct USB connection to 307x base (bits in basstate) */
+#define BS_ATOPEN 0x001
+#define BS_B1OPEN 0x002
+#define BS_B2OPEN 0x004
+#define BS_ATREADY 0x008
+#define BS_INIT 0x010
+#define BS_ATTIMER 0x020
+
+
+static struct gigaset_driver *driver = NULL;
+static struct cardstate *cardstate = NULL;
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver gigaset_usb_driver = {
+ .name = GIGASET_MODULENAME,
+ .probe = gigaset_probe,
+ .disconnect = gigaset_disconnect,
+ .id_table = gigaset_table,
+};
+
+/* get message text for USB status code
+ */
+static char *get_usb_statmsg(int status)
+{
+ static char unkmsg[28];
+
+ switch (status) {
+ case 0:
+ return "success";
+ case -ENOENT:
+ return "canceled";
+ case -ECONNRESET:
+ return "canceled (async)";
+ case -EINPROGRESS:
+ return "pending";
+ case -EPROTO:
+ return "bit stuffing or unknown USB error";
+ case -EILSEQ:
+ return "Illegal byte sequence (CRC mismatch)";
+ case -EPIPE:
+ return "babble detect or endpoint stalled";
+ case -ENOSR:
+ return "buffer error";
+ case -ETIMEDOUT:
+ return "timed out";
+ case -ENODEV:
+ return "device not present";
+ case -EREMOTEIO:
+ return "short packet detected";
+ case -EXDEV:
+ return "partial isochronous transfer";
+ case -EINVAL:
+ return "invalid argument";
+ case -ENXIO:
+ return "URB already queued";
+ case -EAGAIN:
+ return "isochronous start frame too early or too much scheduled";
+ case -EFBIG:
+ return "too many isochronous frames requested";
+ case -EMSGSIZE:
+ return "endpoint message size zero";
+ case -ESHUTDOWN:
+ return "endpoint shutdown";
+ case -EBUSY:
+ return "another request pending";
+ default:
+ snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", status);
+ return unkmsg;
+ }
+}
+
+/* usb_pipetype_str
+ * retrieve string representation of USB pipe type
+ */
+static inline char *usb_pipetype_str(int pipe)
+{
+ if (usb_pipeisoc(pipe))
+ return "Isoc";
+ if (usb_pipeint(pipe))
+ return "Int";
+ if (usb_pipecontrol(pipe))
+ return "Ctrl";
+ if (usb_pipebulk(pipe))
+ return "Bulk";
+ return "?";
+}
+
+/* dump_urb
+ * write content of URB to syslog for debugging
+ */
+static inline void dump_urb(enum debuglevel level, const char *tag,
+ struct urb *urb)
+{
+#ifdef CONFIG_GIGASET_DEBUG
+ int i;
+ IFNULLRET(tag);
+ dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb);
+ if (urb) {
+ dbg(level,
+ " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, "
+ "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,",
+ (unsigned long) urb->dev,
+ usb_pipetype_str(urb->pipe),
+ usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe),
+ usb_pipein(urb->pipe) ? "in" : "out",
+ urb->status, (unsigned long) urb->hcpriv,
+ urb->transfer_flags);
+ dbg(level,
+ " transfer_buffer=0x%08lx[%d], actual_length=%d, "
+ "bandwidth=%d, setup_packet=0x%08lx,",
+ (unsigned long) urb->transfer_buffer,
+ urb->transfer_buffer_length, urb->actual_length,
+ urb->bandwidth, (unsigned long) urb->setup_packet);
+ dbg(level,
+ " start_frame=%d, number_of_packets=%d, interval=%d, "
+ "error_count=%d,",
+ urb->start_frame, urb->number_of_packets, urb->interval,
+ urb->error_count);
+ dbg(level,
+ " context=0x%08lx, complete=0x%08lx, iso_frame_desc[]={",
+ (unsigned long) urb->context,
+ (unsigned long) urb->complete);
+ for (i = 0; i < urb->number_of_packets; i++) {
+ struct usb_iso_packet_descriptor *pifd = &urb->iso_frame_desc[i];
+ dbg(level,
+ " {offset=%u, length=%u, actual_length=%u, "
+ "status=%u}",
+ pifd->offset, pifd->length, pifd->actual_length,
+ pifd->status);
+ }
+ }
+ dbg(level, "}}");
+#endif
+}
+
+/* read/set modem control bits etc. (m10x only) */
+static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
+ unsigned new_state)
+{
+ return -EINVAL;
+}
+
+static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
+{
+ return -EINVAL;
+}
+
+static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
+{
+ return -EINVAL;
+}
+
+/* error_hangup
+ * hang up any existing connection because of an unrecoverable error
+ * This function may be called from any context and takes care of scheduling
+ * the necessary actions for execution outside of interrupt context.
+ * argument:
+ * B channel control structure
+ */
+static inline void error_hangup(struct bc_state *bcs)
+{
+ struct cardstate *cs = bcs->cs;
+
+ dbg(DEBUG_ANY,
+ "%s: scheduling HUP for channel %d", __func__, bcs->channel);
+
+ if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) {
+ //FIXME what should we do?
+ return;
+ }
+
+ gigaset_schedule_event(cs);
+}
+
+/* error_reset
+ * reset Gigaset device because of an unrecoverable error
+ * This function may be called from any context and takes care of scheduling
+ * the necessary actions for execution outside of interrupt context.
+ * argument:
+ * controller state structure
+ */
+static inline void error_reset(struct cardstate *cs)
+{
+ //FIXME try to recover without bothering the user
+ err("unrecoverable error - please disconnect the Gigaset base to reset");
+}
+
+/* check_pending
+ * check for completion of pending control request
+ * parameter:
+ * urb USB request block of completed request
+ * urb->context = hardware specific controller state structure
+ */
+static void check_pending(struct bas_cardstate *ucs)
+{
+ unsigned long flags;
+
+ IFNULLRET(ucs);
+ IFNULLRET(cardstate);
+
+ spin_lock_irqsave(&ucs->lock, flags);
+ switch (ucs->pending) {
+ case 0:
+ break;
+ case HD_OPEN_ATCHANNEL:
+ if (atomic_read(&ucs->basstate) & BS_ATOPEN)
+ ucs->pending = 0;
+ break;
+ case HD_OPEN_B1CHANNEL:
+ if (atomic_read(&ucs->basstate) & BS_B1OPEN)
+ ucs->pending = 0;
+ break;
+ case HD_OPEN_B2CHANNEL:
+ if (atomic_read(&ucs->basstate) & BS_B2OPEN)
+ ucs->pending = 0;
+ break;
+ case HD_CLOSE_ATCHANNEL:
+ if (!(atomic_read(&ucs->basstate) & BS_ATOPEN))
+ ucs->pending = 0;
+ //wake_up_interruptible(cs->initwait);
+ //FIXME need own wait queue?
+ break;
+ case HD_CLOSE_B1CHANNEL:
+ if (!(atomic_read(&ucs->basstate) & BS_B1OPEN))
+ ucs->pending = 0;
+ break;
+ case HD_CLOSE_B2CHANNEL:
+ if (!(atomic_read(&ucs->basstate) & BS_B2OPEN))
+ ucs->pending = 0;
+ break;
+ case HD_DEVICE_INIT_ACK: /* no reply expected */
+ ucs->pending = 0;
+ break;
+ /* HD_READ_ATMESSAGE, HD_WRITE_ATMESSAGE, HD_RESET_INTERRUPTPIPE
+ * are handled separately and should never end up here
+ */
+ default:
+ warn("unknown pending request 0x%02x cleared", ucs->pending);
+ ucs->pending = 0;
+ }
+
+ if (!ucs->pending)
+ del_timer(&ucs->timer_ctrl);
+
+ spin_unlock_irqrestore(&ucs->lock, flags);
+}
+
+/* cmd_in_timeout
+ * timeout routine for command input request
+ * argument:
+ * controller state structure
+ */
+static void cmd_in_timeout(unsigned long data)
+{
+ struct cardstate *cs = (struct cardstate *) data;
+ struct bas_cardstate *ucs;
+ unsigned long flags;
+
+ IFNULLRET(cs);
+ ucs = cs->hw.bas;
+ IFNULLRET(ucs);
+
+ spin_lock_irqsave(&cs->lock, flags);
+ if (!atomic_read(&cs->connected)) {
+ dbg(DEBUG_USBREQ, "%s: disconnected", __func__);
+ spin_unlock_irqrestore(&cs->lock, flags);
+ return;
+ }
+ if (!ucs->rcvbuf_size) {
+ dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__);
+ spin_unlock_irqrestore(&cs->lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&cs->lock, flags);
+
+ err("timeout reading AT response");
+ error_reset(cs); //FIXME retry?
+}
+
+
+static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs);
+
+/* atread_submit
+ * submit an HD_READ_ATMESSAGE command URB
+ * parameters:
+ * cs controller state structure
+ * timeout timeout in 1/10 sec., 0: none
+ * return value:
+ * 0 on success
+ * -EINVAL if a NULL pointer is encountered somewhere
+ * -EBUSY if another request is pending
+ * any URB submission error code
+ */
+static int atread_submit(struct cardstate *cs, int timeout)
+{
+ struct bas_cardstate *ucs;
+ int ret;
+
+ IFNULLRETVAL(cs, -EINVAL);
+ ucs = cs->hw.bas;
+ IFNULLRETVAL(ucs, -EINVAL);
+ IFNULLRETVAL(ucs->urb_cmd_in, -EINVAL);
+
+ dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", ucs->rcvbuf_size);
+
+ if (ucs->urb_cmd_in->status == -EINPROGRESS) {
+ err("could not submit HD_READ_ATMESSAGE: URB busy");
+ return -EBUSY;
+ }
+
+ ucs->dr_cmd_in.bRequestType = IN_VENDOR_REQ;
+ ucs->dr_cmd_in.bRequest = HD_READ_ATMESSAGE;
+ ucs->dr_cmd_in.wValue = 0;
+ ucs->dr_cmd_in.wIndex = 0;
+ ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size);
+ usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev,
+ usb_rcvctrlpipe(ucs->udev, 0),
+ (unsigned char*) & ucs->dr_cmd_in,
+ ucs->rcvbuf, ucs->rcvbuf_size,
+ read_ctrl_callback, cs->inbuf);
+
+ if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) {
+ err("could not submit HD_READ_ATMESSAGE: %s",
+ get_usb_statmsg(ret));
+ return ret;
+ }
+
+ if (timeout > 0) {
+ dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
+ ucs->timer_cmd_in.expires = jiffies + timeout * HZ / 10;
+ ucs->timer_cmd_in.data = (unsigned long) cs;
+ ucs->timer_cmd_in.function = cmd_in_timeout;
+ add_timer(&ucs->timer_cmd_in);
+ }
+ return 0;
+}
+
+static void stopurbs(struct bas_bc_state *);
+static int start_cbsend(struct cardstate *);
+
+/* set/clear bits in base connection state
+ */
+inline static void update_basstate(struct bas_cardstate *ucs,
+ int set, int clear)
+{
+ unsigned long flags;
+ int state;
+
+ spin_lock_irqsave(&ucs->lock, flags);
+ state = atomic_read(&ucs->basstate);
+ state &= ~clear;
+ state |= set;
+ atomic_set(&ucs->basstate, state);
+ spin_unlock_irqrestore(&ucs->lock, flags);
+}
+
+
+/* read_int_callback
+ * USB completion handler for interrupt pipe input
+ * called by the USB subsystem in interrupt context
+ * parameter:
+ * urb USB request block
+ * urb->context = controller state structure
+ */
+static void read_int_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct cardstate *cs;
+ struct bas_cardstate *ucs;
+ struct bc_state *bcs;
+ unsigned long flags;
+ int status;
+ unsigned l;
+ int channel;
+
+ IFNULLRET(urb);
+ cs = (struct cardstate *) urb->context;
+ IFNULLRET(cs);
+ ucs = cs->hw.bas;
+ IFNULLRET(ucs);
+
+ if (unlikely(!atomic_read(&cs->connected))) {
+ warn("%s: disconnected", __func__);
+ return;
+ }
+
+ switch (urb->status) {
+ case 0: /* success */
+ break;
+ case -ENOENT: /* canceled */
+ case -ECONNRESET: /* canceled (async) */
+ case -EINPROGRESS: /* pending */
+ /* ignore silently */
+ dbg(DEBUG_USBREQ,
+ "%s: %s", __func__, get_usb_statmsg(urb->status));
+ return;
+ default: /* severe trouble */
+ warn("interrupt read: %s", get_usb_statmsg(urb->status));
+ //FIXME corrective action? resubmission always ok?
+ goto resubmit;
+ }
+
+ l = (unsigned) ucs->int_in_buf[1] +
+ (((unsigned) ucs->int_in_buf[2]) << 8);
+
+ dbg(DEBUG_USBREQ,
+ "<-------%d: 0x%02x (%u [0x%02x 0x%02x])", urb->actual_length,
+ (int)ucs->int_in_buf[0], l,
+ (int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]);
+
+ channel = 0;
+
+ switch (ucs->int_in_buf[0]) {
+ case HD_DEVICE_INIT_OK:
+ update_basstate(ucs, BS_INIT, 0);
+ break;
+
+ case HD_READY_SEND_ATDATA:
+ del_timer(&ucs->timer_atrdy);
+ update_basstate(ucs, BS_ATREADY, BS_ATTIMER);
+ start_cbsend(cs);
+ break;
+
+ case HD_OPEN_B2CHANNEL_ACK:
+ ++channel;
+ case HD_OPEN_B1CHANNEL_ACK:
+ bcs = cs->bcs + channel;
+ update_basstate(ucs, BS_B1OPEN << channel, 0);
+ gigaset_bchannel_up(bcs);
+ break;
+
+ case HD_OPEN_ATCHANNEL_ACK:
+ update_basstate(ucs, BS_ATOPEN, 0);
+ start_cbsend(cs);
+ break;
+
+ case HD_CLOSE_B2CHANNEL_ACK:
+ ++channel;
+ case HD_CLOSE_B1CHANNEL_ACK:
+ bcs = cs->bcs + channel;
+ update_basstate(ucs, 0, BS_B1OPEN << channel);
+ stopurbs(bcs->hw.bas);
+ gigaset_bchannel_down(bcs);
+ break;
+
+ case HD_CLOSE_ATCHANNEL_ACK:
+ update_basstate(ucs, 0, BS_ATOPEN);
+ break;
+
+ case HD_B2_FLOW_CONTROL:
+ ++channel;
+ case HD_B1_FLOW_CONTROL:
+ bcs = cs->bcs + channel;
+ atomic_add((l - BAS_NORMFRAME) * BAS_CORRFRAMES,
+ &bcs->hw.bas->corrbytes);
+ dbg(DEBUG_ISO,
+ "Flow control (channel %d, sub %d): 0x%02x => %d",
+ channel, bcs->hw.bas->numsub, l,
+ atomic_read(&bcs->hw.bas->corrbytes));
+ break;
+
+ case HD_RECEIVEATDATA_ACK: /* AT response ready to be received */
+ if (!l) {
+ warn("HD_RECEIVEATDATA_ACK with length 0 ignored");
+ break;
+ }
+ spin_lock_irqsave(&cs->lock, flags);
+ if (ucs->rcvbuf_size) {
+ spin_unlock_irqrestore(&cs->lock, flags);
+ err("receive AT data overrun, %d bytes lost", l);
+ error_reset(cs); //FIXME reschedule
+ break;
+ }
+ if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) {
+ spin_unlock_irqrestore(&cs->lock, flags);
+ err("%s: out of memory, %d bytes lost", __func__, l);
+ error_reset(cs); //FIXME reschedule
+ break;
+ }
+ ucs->rcvbuf_size = l;
+ ucs->retry_cmd_in = 0;
+ if ((status = atread_submit(cs, BAS_TIMEOUT)) < 0) {
+ kfree(ucs->rcvbuf);
+ ucs->rcvbuf = NULL;
+ ucs->rcvbuf_size = 0;
+ error_reset(cs); //FIXME reschedule
+ }
+ spin_unlock_irqrestore(&cs->lock, flags);
+ break;
+
+ case HD_RESET_INTERRUPT_PIPE_ACK:
+ dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK");
+ break;
+
+ case HD_SUSPEND_END:
+ dbg(DEBUG_USBREQ, "HD_SUSPEND_END");
+ break;
+
+ default:
+ warn("unknown Gigaset signal 0x%02x (%u) ignored",
+ (int) ucs->int_in_buf[0], l);
+ }
+
+ check_pending(ucs);
+
+resubmit:
+ status = usb_submit_urb(urb, SLAB_ATOMIC);
+ if (unlikely(status)) {
+ err("could not resubmit interrupt URB: %s",
+ get_usb_statmsg(status));
+ error_reset(cs);
+ }
+}
+
+/* read_ctrl_callback
+ * USB completion handler for control pipe input
+ * called by the USB subsystem in interrupt context
+ * parameter:
+ * urb USB request block
+ * urb->context = inbuf structure for controller state
+ */
+static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct cardstate *cs;
+ struct bas_cardstate *ucs;
+ unsigned numbytes;
+ unsigned long flags;
+ struct inbuf_t *inbuf;
+ int have_data = 0;
+
+ IFNULLRET(urb);
+ inbuf = (struct inbuf_t *) urb->context;
+ IFNULLRET(inbuf);
+ cs = inbuf->cs;
+ IFNULLRET(cs);
+ ucs = cs->hw.bas;
+ IFNULLRET(ucs);
+
+ spin_lock_irqsave(&cs->lock, flags);
+ if (!atomic_read(&cs->connected)) {
+ warn("%s: disconnected", __func__);
+ spin_unlock_irqrestore(&cs->lock, flags);
+ return;
+ }
+
+ if (!ucs->rcvbuf_size) {
+ warn("%s: no receive in progress", __func__);
+ spin_unlock_irqrestore(&cs->lock, flags);
+ return;
+ }
+
+ del_timer(&ucs->timer_cmd_in);
+
+ switch (urb->status) {
+ case 0: /* normal completion */
+ numbytes = urb->actual_length;
+ if (unlikely(numbytes == 0)) {
+ warn("control read: empty block received");
+ goto retry;
+ }
+ if (unlikely(numbytes != ucs->rcvbuf_size)) {
+ warn("control read: received %d chars, expected %d",
+ numbytes, ucs->rcvbuf_size);
+ if (numbytes > ucs->rcvbuf_size)
+ numbytes = ucs->rcvbuf_size;
+ }
+
+ /* copy received bytes to inbuf */
+ have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes);
+
+ if (unlikely(numbytes < ucs->rcvbuf_size)) {
+ /* incomplete - resubmit for remaining bytes */
+ ucs->rcvbuf_size -= numbytes;
+ ucs->retry_cmd_in = 0;
+ goto retry;
+ }
+ break;
+
+ case -ENOENT: /* canceled */
+ case -ECONNRESET: /* canceled (async) */
+ case -EINPROGRESS: /* pending */
+ /* no action necessary */
+ dbg(DEBUG_USBREQ,
+ "%s: %s", __func__, get_usb_statmsg(urb->status));
+ break;
+
+ default: /* severe trouble */
+ warn("control read: %s", get_usb_statmsg(urb->status));
+ retry:
+ if (ucs->retry_cmd_in++ < BAS_RETRY) {
+ notice("control read: retry %d", ucs->retry_cmd_in);
+ if (atread_submit(cs, BAS_TIMEOUT) >= 0) {
+ /* resubmitted - bypass regular exit block */
+ spin_unlock_irqrestore(&cs->lock, flags);
+ return;
+ }
+ } else {
+ err("control read: giving up after %d tries",
+ ucs->retry_cmd_in);
+ }
+ error_reset(cs);
+ }
+
+ kfree(ucs->rcvbuf);
+ ucs->rcvbuf = NULL;
+ ucs->rcvbuf_size = 0;
+ spin_unlock_irqrestore(&cs->lock, flags);
+ if (have_data) {
+ dbg(DEBUG_INTR, "%s-->BH", __func__);
+ gigaset_schedule_event(cs);
+ }
+}
+
+/* read_iso_callback
+ * USB completion handler for B channel isochronous input
+ * called by the USB subsystem in interrupt context
+ * parameter:
+ * urb USB request block of completed request
+ * urb->context = bc_state structure
+ */
+static void read_iso_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct bc_state *bcs;
+ struct bas_bc_state *ubc;
+ unsigned long flags;
+ int i, rc;
+
+ IFNULLRET(urb);
+ IFNULLRET(urb->context);
+ IFNULLRET(cardstate);
+
+ /* status codes not worth bothering the tasklet with */
+ if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
+ urb->status == -EINPROGRESS)) {
+ dbg(DEBUG_ISO,
+ "%s: %s", __func__, get_usb_statmsg(urb->status));
+ return;
+ }
+
+ bcs = (struct bc_state *) urb->context;
+ ubc = bcs->hw.bas;
+ IFNULLRET(ubc);
+
+ spin_lock_irqsave(&ubc->isoinlock, flags);
+ if (likely(ubc->isoindone == NULL)) {
+ /* pass URB to tasklet */
+ ubc->isoindone = urb;
+ tasklet_schedule(&ubc->rcvd_tasklet);
+ } else {
+ /* tasklet still busy, drop data and resubmit URB */
+ ubc->loststatus = urb->status;
+ for (i = 0; i < BAS_NUMFRAMES; i++) {
+ ubc->isoinlost += urb->iso_frame_desc[i].actual_length;
+ if (unlikely(urb->iso_frame_desc[i].status != 0 &&
+ urb->iso_frame_desc[i].status != -EINPROGRESS)) {
+ ubc->loststatus = urb->iso_frame_desc[i].status;
+ }
+ urb->iso_frame_desc[i].status = 0;
+ urb->iso_frame_desc[i].actual_length = 0;
+ }
+ if (likely(atomic_read(&ubc->running))) {
+ urb->dev = bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->number_of_packets = BAS_NUMFRAMES;
+ dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", __func__);
+ rc = usb_submit_urb(urb, SLAB_ATOMIC);
+ if (unlikely(rc != 0)) {
+ err("could not resubmit isochronous read URB: %s",
+ get_usb_statmsg(rc));
+ dump_urb(DEBUG_ISO, "isoc read", urb);
+ error_hangup(bcs);
+ }
+ }
+ }
+ spin_unlock_irqrestore(&ubc->isoinlock, flags);
+}
+
+/* write_iso_callback
+ * USB completion handler for B channel isochronous output
+ * called by the USB subsystem in interrupt context
+ * parameter:
+ * urb USB request block of completed request
+ * urb->context = isow_urbctx_t structure
+ */
+static void write_iso_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct isow_urbctx_t *ucx;
+ struct bas_bc_state *ubc;
+ unsigned long flags;
+
+ IFNULLRET(urb);
+ IFNULLRET(urb->context);
+ IFNULLRET(cardstate);
+
+ /* status codes not worth bothering the tasklet with */
+ if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
+ urb->status == -EINPROGRESS)) {
+ dbg(DEBUG_ISO,
+ "%s: %s", __func__, get_usb_statmsg(urb->status));
+ return;
+ }
+
+ /* pass URB context to tasklet */
+ ucx = (struct isow_urbctx_t *) urb->context;
+ IFNULLRET(ucx->bcs);
+ ubc = ucx->bcs->hw.bas;
+ IFNULLRET(ubc);
+
+ spin_lock_irqsave(&ubc->isooutlock, flags);
+ ubc->isooutovfl = ubc->isooutdone;
+ ubc->isooutdone = ucx;
+ spin_unlock_irqrestore(&ubc->isooutlock, flags);
+ tasklet_schedule(&ubc->sent_tasklet);
+}
+
+/* starturbs
+ * prepare and submit USB request blocks for isochronous input and output
+ * argument:
+ * B channel control structure
+ * return value:
+ * 0 on success
+ * < 0 on error (no URBs submitted)
+ */
+static int starturbs(struct bc_state *bcs)
+{
+ struct urb *urb;
+ struct bas_bc_state *ubc;
+ int j, k;
+ int rc;
+
+ IFNULLRETVAL(bcs, -EFAULT);
+ ubc = bcs->hw.bas;
+ IFNULLRETVAL(ubc, -EFAULT);
+
+ /* initialize L2 reception */
+ if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
+ bcs->inputstate |= INS_flag_hunt;
+
+ /* submit all isochronous input URBs */
+ atomic_set(&ubc->running, 1);
+ for (k = 0; k < BAS_INURBS; k++) {
+ urb = ubc->isoinurbs[k];
+ if (!urb) {
+ err("isoinurbs[%d]==NULL", k);
+ rc = -EFAULT;
+ goto error;
+ }
+
+ urb->dev = bcs->cs->hw.bas->udev;
+ urb->pipe = usb_rcvisocpipe(urb->dev, 3 + 2 * bcs->channel);
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->transfer_buffer = ubc->isoinbuf + k * BAS_INBUFSIZE;
+ urb->transfer_buffer_length = BAS_INBUFSIZE;
+ urb->number_of_packets = BAS_NUMFRAMES;
+ urb->interval = BAS_FRAMETIME;
+ urb->complete = read_iso_callback;
+ urb->context = bcs;
+ for (j = 0; j < BAS_NUMFRAMES; j++) {
+ urb->iso_frame_desc[j].offset = j * BAS_MAXFRAME;
+ urb->iso_frame_desc[j].length = BAS_MAXFRAME;
+ urb->iso_frame_desc[j].status = 0;
+ urb->iso_frame_desc[j].actual_length = 0;
+ }
+
+ dump_urb(DEBUG_ISO, "Initial isoc read", urb);
+ if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
+ err("could not submit isochronous read URB %d: %s",
+ k, get_usb_statmsg(rc));
+ goto error;
+ }
+ }
+
+ /* initialize L2 transmission */
+ gigaset_isowbuf_init(ubc->isooutbuf, PPP_FLAG);
+
+ /* set up isochronous output URBs for flag idling */
+ for (k = 0; k < BAS_OUTURBS; ++k) {
+ urb = ubc->isoouturbs[k].urb;
+ if (!urb) {
+ err("isoouturbs[%d].urb==NULL", k);
+ rc = -EFAULT;
+ goto error;
+ }
+ urb->dev = bcs->cs->hw.bas->udev;
+ urb->pipe = usb_sndisocpipe(urb->dev, 4 + 2 * bcs->channel);
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->transfer_buffer = ubc->isooutbuf->data;
+ urb->transfer_buffer_length = sizeof(ubc->isooutbuf->data);
+ urb->number_of_packets = BAS_NUMFRAMES;
+ urb->interval = BAS_FRAMETIME;
+ urb->complete = write_iso_callback;
+ urb->context = &ubc->isoouturbs[k];
+ for (j = 0; j < BAS_NUMFRAMES; ++j) {
+ urb->iso_frame_desc[j].offset = BAS_OUTBUFSIZE;
+ urb->iso_frame_desc[j].length = BAS_NORMFRAME;
+ urb->iso_frame_desc[j].status = 0;
+ urb->iso_frame_desc[j].actual_length = 0;
+ }
+ ubc->isoouturbs[k].limit = -1;
+ }
+
+ /* submit two URBs, keep third one */
+ for (k = 0; k < 2; ++k) {
+ dump_urb(DEBUG_ISO, "Initial isoc write", urb);
+ rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC);
+ if (rc != 0) {
+ err("could not submit isochronous write URB %d: %s",
+ k, get_usb_statmsg(rc));
+ goto error;
+ }
+ }
+ dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb);
+ ubc->isooutfree = &ubc->isoouturbs[2];
+ ubc->isooutdone = ubc->isooutovfl = NULL;
+ return 0;
+ error:
+ stopurbs(ubc);
+ return rc;
+}
+
+/* stopurbs
+ * cancel the USB request blocks for isochronous input and output
+ * errors are silently ignored
+ * argument:
+ * B channel control structure
+ */
+static void stopurbs(struct bas_bc_state *ubc)
+{
+ int k, rc;
+
+ IFNULLRET(ubc);
+
+ atomic_set(&ubc->running, 0);
+
+ for (k = 0; k < BAS_INURBS; ++k) {
+ rc = usb_unlink_urb(ubc->isoinurbs[k]);
+ dbg(DEBUG_ISO, "%s: isoc input URB %d unlinked, result = %d",
+ __func__, k, rc);
+ }
+
+ for (k = 0; k < BAS_OUTURBS; ++k) {
+ rc = usb_unlink_urb(ubc->isoouturbs[k].urb);
+ dbg(DEBUG_ISO, "%s: isoc output URB %d unlinked, result = %d",
+ __func__, k, rc);
+ }
+}
+
+/* Isochronous Write - Bottom Half */
+/* =============================== */
+
+/* submit_iso_write_urb
+ * fill and submit the next isochronous write URB
+ * parameters:
+ * bcs B channel state structure
+ * return value:
+ * number of frames submitted in URB
+ * 0 if URB not submitted because no data available (isooutbuf busy)
+ * error code < 0 on error
+ */
+static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
+{
+ struct urb *urb;
+ struct bas_bc_state *ubc;
+ struct usb_iso_packet_descriptor *ifd;
+ int corrbytes, nframe, rc;
+
+ IFNULLRETVAL(ucx, -EFAULT);
+ urb = ucx->urb;
+ IFNULLRETVAL(urb, -EFAULT);
+ IFNULLRETVAL(ucx->bcs, -EFAULT);
+ ubc = ucx->bcs->hw.bas;
+ IFNULLRETVAL(ubc, -EFAULT);
+
+ urb->dev = ucx->bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->transfer_buffer = ubc->isooutbuf->data;
+ urb->transfer_buffer_length = sizeof(ubc->isooutbuf->data);
+
+ for (nframe = 0; nframe < BAS_NUMFRAMES; nframe++) {
+ ifd = &urb->iso_frame_desc[nframe];
+
+ /* compute frame length according to flow control */
+ ifd->length = BAS_NORMFRAME;
+ if ((corrbytes = atomic_read(&ubc->corrbytes)) != 0) {
+ dbg(DEBUG_ISO, "%s: corrbytes=%d", __func__, corrbytes);
+ if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME)
+ corrbytes = BAS_HIGHFRAME - BAS_NORMFRAME;
+ else if (corrbytes < BAS_LOWFRAME - BAS_NORMFRAME)
+ corrbytes = BAS_LOWFRAME - BAS_NORMFRAME;
+ ifd->length += corrbytes;
+ atomic_add(-corrbytes, &ubc->corrbytes);
+ }
+ //dbg(DEBUG_ISO, "%s: frame %d length=%d", __func__, nframe, ifd->length);
+
+ /* retrieve block of data to send */
+ ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf, ifd->length);
+ if (ifd->offset < 0) {
+ if (ifd->offset == -EBUSY) {
+ dbg(DEBUG_ISO, "%s: buffer busy at frame %d",
+ __func__, nframe);
+ /* tasklet will be restarted from gigaset_send_skb() */
+ } else {
+ err("%s: buffer error %d at frame %d",
+ __func__, ifd->offset, nframe);
+ return ifd->offset;
+ }
+ break;
+ }
+ ucx->limit = atomic_read(&ubc->isooutbuf->nextread);
+ ifd->status = 0;
+ ifd->actual_length = 0;
+ }
+ if ((urb->number_of_packets = nframe) > 0) {
+ if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
+ err("could not submit isochronous write URB: %s",
+ get_usb_statmsg(rc));
+ dump_urb(DEBUG_ISO, "isoc write", urb);
+ return rc;
+ }
+ ++ubc->numsub;
+ }
+ return nframe;
+}
+
+/* write_iso_tasklet
+ * tasklet scheduled when an isochronous output URB from the Gigaset device
+ * has completed
+ * parameter:
+ * data B channel state structure
+ */
+static void write_iso_tasklet(unsigned long data)
+{
+ struct bc_state *bcs;
+ struct bas_bc_state *ubc;
+ struct cardstate *cs;
+ struct isow_urbctx_t *done, *next, *ovfl;
+ struct urb *urb;
+ struct usb_iso_packet_descriptor *ifd;
+ int offset;
+ unsigned long flags;
+ int i;
+ struct sk_buff *skb;
+ int len;
+
+ bcs = (struct bc_state *) data;
+ IFNULLRET(bcs);
+ ubc = bcs->hw.bas;
+ IFNULLRET(ubc);
+ cs = bcs->cs;
+ IFNULLRET(cs);
+
+ /* loop while completed URBs arrive in time */
+ for (;;) {
+ if (unlikely(!atomic_read(&cs->connected))) {
+ warn("%s: disconnected", __func__);
+ return;
+ }
+
+ if (unlikely(!(atomic_read(&ubc->running)))) {
+ dbg(DEBUG_ISO, "%s: not running", __func__);
+ return;
+ }
+
+ /* retrieve completed URBs */
+ spin_lock_irqsave(&ubc->isooutlock, flags);
+ done = ubc->isooutdone;
+ ubc->isooutdone = NULL;
+ ovfl = ubc->isooutovfl;
+ ubc->isooutovfl = NULL;
+ spin_unlock_irqrestore(&ubc->isooutlock, flags);
+ if (ovfl) {
+ err("isochronous write buffer underrun - buy a faster machine :-)");
+ error_hangup(bcs);
+ break;
+ }
+ if (!done)
+ break;
+
+ /* submit free URB if available */
+ spin_lock_irqsave(&ubc->isooutlock, flags);
+ next = ubc->isooutfree;
+ ubc->isooutfree = NULL;
+ spin_unlock_irqrestore(&ubc->isooutlock, flags);
+ if (next) {
+ if (submit_iso_write_urb(next) <= 0) {
+ /* could not submit URB, put it back */
+ spin_lock_irqsave(&ubc->isooutlock, flags);
+ if (ubc->isooutfree == NULL) {
+ ubc->isooutfree = next;
+ next = NULL;
+ }
+ spin_unlock_irqrestore(&ubc->isooutlock, flags);
+ if (next) {
+ /* couldn't put it back */
+ err("losing isochronous write URB");
+ error_hangup(bcs);
+ }
+ }
+ }
+
+ /* process completed URB */
+ urb = done->urb;
+ switch (urb->status) {
+ case 0: /* normal completion */
+ break;
+ case -EXDEV: /* inspect individual frames */
+ /* assumptions (for lack of documentation):
+ * - actual_length bytes of the frame in error are successfully sent
+ * - all following frames are not sent at all
+ */
+ dbg(DEBUG_ISO, "%s: URB partially completed", __func__);
+ offset = done->limit; /* just in case */
+ for (i = 0; i < BAS_NUMFRAMES; i++) {
+ ifd = &urb->iso_frame_desc[i];
+ if (ifd->status ||
+ ifd->actual_length != ifd->length) {
+ warn("isochronous write: frame %d: %s, "
+ "only %d of %d bytes sent",
+ i, get_usb_statmsg(ifd->status),
+ ifd->actual_length, ifd->length);
+ offset = (ifd->offset +
+ ifd->actual_length)
+ % BAS_OUTBUFSIZE;
+ break;
+ }
+ }
+#ifdef CONFIG_GIGASET_DEBUG
+ /* check assumption on remaining frames */
+ for (; i < BAS_NUMFRAMES; i++) {
+ ifd = &urb->iso_frame_desc[i];
+ if (ifd->status != -EINPROGRESS
+ || ifd->actual_length != 0) {
+ warn("isochronous write: frame %d: %s, "
+ "%d of %d bytes sent",
+ i, get_usb_statmsg(ifd->status),
+ ifd->actual_length, ifd->length);
+ offset = (ifd->offset +
+ ifd->actual_length)
+ % BAS_OUTBUFSIZE;
+ break;
+ }
+ }
+#endif
+ break;
+ case -EPIPE: //FIXME is this the code for "underrun"?
+ err("isochronous write stalled");
+ error_hangup(bcs);
+ break;
+ default: /* severe trouble */
+ warn("isochronous write: %s",
+ get_usb_statmsg(urb->status));
+ }
+
+ /* mark the write buffer area covered by this URB as free */
+ if (done->limit >= 0)
+ atomic_set(&ubc->isooutbuf->read, done->limit);
+
+ /* mark URB as free */
+ spin_lock_irqsave(&ubc->isooutlock, flags);
+ next = ubc->isooutfree;
+ ubc->isooutfree = done;
+ spin_unlock_irqrestore(&ubc->isooutlock, flags);
+ if (next) {
+ /* only one URB still active - resubmit one */
+ if (submit_iso_write_urb(next) <= 0) {
+ /* couldn't submit */
+ error_hangup(bcs);
+ }
+ }
+ }
+
+ /* process queued SKBs */
+ while ((skb = skb_dequeue(&bcs->squeue))) {
+ /* copy to output buffer, doing L2 encapsulation */
+ len = skb->len;
+ if (gigaset_isoc_buildframe(bcs, skb->data, len) == -EAGAIN) {
+ /* insufficient buffer space, push back onto queue */
+ skb_queue_head(&bcs->squeue, skb);
+ dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d",
+ __func__, skb_queue_len(&bcs->squeue));
+ break;
+ }
+ skb_pull(skb, len);
+ gigaset_skb_sent(bcs, skb);
+ dev_kfree_skb_any(skb);
+ }
+}
+
+/* Isochronous Read - Bottom Half */
+/* ============================== */
+
+/* read_iso_tasklet
+ * tasklet scheduled when an isochronous input URB from the Gigaset device
+ * has completed
+ * parameter:
+ * data B channel state structure
+ */
+static void read_iso_tasklet(unsigned long data)
+{
+ struct bc_state *bcs;
+ struct bas_bc_state *ubc;
+ struct cardstate *cs;
+ struct urb *urb;
+ char *rcvbuf;
+ unsigned long flags;
+ int totleft, numbytes, offset, frame, rc;
+
+ bcs = (struct bc_state *) data;
+ IFNULLRET(bcs);
+ ubc = bcs->hw.bas;
+ IFNULLRET(ubc);
+ cs = bcs->cs;
+ IFNULLRET(cs);
+
+ /* loop while more completed URBs arrive in the meantime */
+ for (;;) {
+ if (!atomic_read(&cs->connected)) {
+ warn("%s: disconnected", __func__);
+ return;
+ }
+
+ /* retrieve URB */
+ spin_lock_irqsave(&ubc->isoinlock, flags);
+ if (!(urb = ubc->isoindone)) {
+ spin_unlock_irqrestore(&ubc->isoinlock, flags);
+ return;
+ }
+ ubc->isoindone = NULL;
+ if (unlikely(ubc->loststatus != -EINPROGRESS)) {
+ warn("isochronous read overrun, dropped URB with status: %s, %d bytes lost",
+ get_usb_statmsg(ubc->loststatus), ubc->isoinlost);
+ ubc->loststatus = -EINPROGRESS;
+ }
+ spin_unlock_irqrestore(&ubc->isoinlock, flags);
+
+ if (unlikely(!(atomic_read(&ubc->running)))) {
+ dbg(DEBUG_ISO, "%s: channel not running, dropped URB with status: %s",
+ __func__, get_usb_statmsg(urb->status));
+ return;
+ }
+
+ switch (urb->status) {
+ case 0: /* normal completion */
+ break;
+ case -EXDEV: /* inspect individual frames (we do that anyway) */
+ dbg(DEBUG_ISO, "%s: URB partially completed", __func__);
+ break;
+ case -ENOENT:
+ case -ECONNRESET:
+ dbg(DEBUG_ISO, "%s: URB canceled", __func__);
+ continue; /* -> skip */
+ case -EINPROGRESS: /* huh? */
+ dbg(DEBUG_ISO, "%s: URB still pending", __func__);
+ continue; /* -> skip */
+ case -EPIPE:
+ err("isochronous read stalled");
+ error_hangup(bcs);
+ continue; /* -> skip */
+ default: /* severe trouble */
+ warn("isochronous read: %s",
+ get_usb_statmsg(urb->status));
+ goto error;
+ }
+
+ rcvbuf = urb->transfer_buffer;
+ totleft = urb->actual_length;
+ for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) {
+ if (unlikely(urb->iso_frame_desc[frame].status)) {
+ warn("isochronous read: frame %d: %s",
+ frame, get_usb_statmsg(urb->iso_frame_desc[frame].status));
+ break;
+ }
+ numbytes = urb->iso_frame_desc[frame].actual_length;
+ if (unlikely(numbytes > BAS_MAXFRAME)) {
+ warn("isochronous read: frame %d: numbytes (%d) > BAS_MAXFRAME",
+ frame, numbytes);
+ break;
+ }
+ if (unlikely(numbytes > totleft)) {
+ warn("isochronous read: frame %d: numbytes (%d) > totleft (%d)",
+ frame, numbytes, totleft);
+ break;
+ }
+ offset = urb->iso_frame_desc[frame].offset;
+ if (unlikely(offset + numbytes > BAS_INBUFSIZE)) {
+ warn("isochronous read: frame %d: offset (%d) + numbytes (%d) > BAS_INBUFSIZE",
+ frame, offset, numbytes);
+ break;
+ }
+ gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs);
+ totleft -= numbytes;
+ }
+ if (unlikely(totleft > 0))
+ warn("isochronous read: %d data bytes missing",
+ totleft);
+
+ error:
+ /* URB processed, resubmit */
+ for (frame = 0; frame < BAS_NUMFRAMES; frame++) {
+ urb->iso_frame_desc[frame].status = 0;
+ urb->iso_frame_desc[frame].actual_length = 0;
+ }
+ urb->dev = bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->number_of_packets = BAS_NUMFRAMES;
+ if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
+ err("could not resubmit isochronous read URB: %s",
+ get_usb_statmsg(rc));
+ dump_urb(DEBUG_ISO, "resubmit iso read", urb);
+ error_hangup(bcs);
+ }
+ }
+}
+
+/* Channel Operations */
+/* ================== */
+
+/* req_timeout
+ * timeout routine for control output request
+ * argument:
+ * B channel control structure
+ */
+static void req_timeout(unsigned long data)
+{
+ struct bc_state *bcs = (struct bc_state *) data;
+ struct bas_cardstate *ucs;
+ int pending;
+ unsigned long flags;
+
+ IFNULLRET(bcs);
+ IFNULLRET(bcs->cs);
+ ucs = bcs->cs->hw.bas;
+ IFNULLRET(ucs);
+
+ check_pending(ucs);
+
+ spin_lock_irqsave(&ucs->lock, flags);
+ pending = ucs->pending;
+ ucs->pending = 0;
+ spin_unlock_irqrestore(&ucs->lock, flags);
+
+ switch (pending) {
+ case 0: /* no pending request */
+ dbg(DEBUG_USBREQ, "%s: no request pending", __func__);
+ break;
+
+ case HD_OPEN_ATCHANNEL:
+ err("timeout opening AT channel");
+ error_reset(bcs->cs);
+ break;
+
+ case HD_OPEN_B2CHANNEL:
+ case HD_OPEN_B1CHANNEL:
+ err("timeout opening channel %d", bcs->channel + 1);
+ error_hangup(bcs);
+ break;
+
+ case HD_CLOSE_ATCHANNEL:
+ err("timeout closing AT channel");
+ //wake_up_interruptible(cs->initwait);
+ //FIXME need own wait queue?
+ break;
+
+ case HD_CLOSE_B2CHANNEL:
+ case HD_CLOSE_B1CHANNEL:
+ err("timeout closing channel %d", bcs->channel + 1);
+ break;
+
+ default:
+ warn("request 0x%02x timed out, clearing", pending);
+ }
+}
+
+/* write_ctrl_callback
+ * USB completion handler for control pipe output
+ * called by the USB subsystem in interrupt context
+ * parameter:
+ * urb USB request block of completed request
+ * urb->context = hardware specific controller state structure
+ */
+static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct bas_cardstate *ucs;
+ unsigned long flags;
+
+ IFNULLRET(urb);
+ IFNULLRET(urb->context);
+ IFNULLRET(cardstate);
+
+ ucs = (struct bas_cardstate *) urb->context;
+ spin_lock_irqsave(&ucs->lock, flags);
+ if (urb->status && ucs->pending) {
+ err("control request 0x%02x failed: %s",
+ ucs->pending, get_usb_statmsg(urb->status));
+ del_timer(&ucs->timer_ctrl);
+ ucs->pending = 0;
+ }
+ /* individual handling of specific request types */
+ switch (ucs->pending) {
+ case HD_DEVICE_INIT_ACK: /* no reply expected */
+ ucs->pending = 0;
+ break;
+ }
+ spin_unlock_irqrestore(&ucs->lock, flags);
+}
+
+/* req_submit
+ * submit a control output request without message buffer to the Gigaset base
+ * and optionally start a timeout
+ * parameters:
+ * bcs B channel control structure
+ * req control request code (HD_*)
+ * val control request parameter value (set to 0 if unused)
+ * timeout timeout in seconds (0: no timeout)
+ * return value:
+ * 0 on success
+ * -EINVAL if a NULL pointer is encountered somewhere
+ * -EBUSY if another request is pending
+ * any URB submission error code
+ */
+static int req_submit(struct bc_state *bcs, int req, int val, int timeout)
+{
+ struct bas_cardstate *ucs;
+ int ret;
+ unsigned long flags;
+
+ IFNULLRETVAL(bcs, -EINVAL);
+ IFNULLRETVAL(bcs->cs, -EINVAL);
+ ucs = bcs->cs->hw.bas;
+ IFNULLRETVAL(ucs, -EINVAL);
+ IFNULLRETVAL(ucs->urb_ctrl, -EINVAL);
+
+ dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val);
+
+ spin_lock_irqsave(&ucs->lock, flags);
+ if (ucs->pending) {
+ spin_unlock_irqrestore(&ucs->lock, flags);
+ err("submission of request 0x%02x failed: request 0x%02x still pending",
+ req, ucs->pending);
+ return -EBUSY;
+ }
+ if (ucs->urb_ctrl->status == -EINPROGRESS) {
+ spin_unlock_irqrestore(&ucs->lock, flags);
+ err("could not submit request 0x%02x: URB busy", req);
+ return -EBUSY;
+ }
+
+ ucs->dr_ctrl.bRequestType = OUT_VENDOR_REQ;
+ ucs->dr_ctrl.bRequest = req;
+ ucs->dr_ctrl.wValue = cpu_to_le16(val);
+ ucs->dr_ctrl.wIndex = 0;
+ ucs->dr_ctrl.wLength = 0;
+ usb_fill_control_urb(ucs->urb_ctrl, ucs->udev,
+ usb_sndctrlpipe(ucs->udev, 0),
+ (unsigned char*) &ucs->dr_ctrl, NULL, 0,
+ write_ctrl_callback, ucs);
+ if ((ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC)) != 0) {
+ err("could not submit request 0x%02x: %s",
+ req, get_usb_statmsg(ret));
+ spin_unlock_irqrestore(&ucs->lock, flags);
+ return ret;
+ }
+ ucs->pending = req;
+
+ if (timeout > 0) {
+ dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
+ ucs->timer_ctrl.expires = jiffies + timeout * HZ / 10;
+ ucs->timer_ctrl.data = (unsigned long) bcs;
+ ucs->timer_ctrl.function = req_timeout;
+ add_timer(&ucs->timer_ctrl);
+ }
+
+ spin_unlock_irqrestore(&ucs->lock, flags);
+ return 0;
+}
+
+/* gigaset_init_bchannel
+ * called by common.c to connect a B channel
+ * initialize isochronous I/O and tell the Gigaset base to open the channel
+ * argument:
+ * B channel control structure
+ * return value:
+ * 0 on success, error code < 0 on error
+ */
+static int gigaset_init_bchannel(struct bc_state *bcs)
+{
+ int req, ret;
+
+ IFNULLRETVAL(bcs, -EINVAL);
+
+ if ((ret = starturbs(bcs)) < 0) {
+ err("could not start isochronous I/O for channel %d",
+ bcs->channel + 1);
+ error_hangup(bcs);
+ return ret;
+ }
+
+ req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL;
+ if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) {
+ err("could not open channel %d: %s",
+ bcs->channel + 1, get_usb_statmsg(ret));
+ stopurbs(bcs->hw.bas);
+ error_hangup(bcs);
+ }
+ return ret;
+}
+
+/* gigaset_close_bchannel
+ * called by common.c to disconnect a B channel
+ * tell the Gigaset base to close the channel
+ * stopping isochronous I/O and LL notification will be done when the
+ * acknowledgement for the close arrives
+ * argument:
+ * B channel control structure
+ * return value:
+ * 0 on success, error code < 0 on error
+ */
+static int gigaset_close_bchannel(struct bc_state *bcs)
+{
+ int req, ret;
+
+ IFNULLRETVAL(bcs, -EINVAL);
+
+ if (!(atomic_read(&bcs->cs->hw.bas->basstate) &
+ (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) {
+ /* channel not running: just signal common.c */
+ gigaset_bchannel_down(bcs);
+ return 0;
+ }
+
+ req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL;
+ if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0)
+ err("could not submit HD_CLOSE_BxCHANNEL request: %s",
+ get_usb_statmsg(ret));
+ return ret;
+}
+
+/* Device Operations */
+/* ================= */
+
+/* complete_cb
+ * unqueue first command buffer from queue, waking any sleepers
+ * must be called with cs->cmdlock held
+ * parameter:
+ * cs controller state structure
+ */
+static void complete_cb(struct cardstate *cs)
+{
+ struct cmdbuf_t *cb;
+
+ IFNULLRET(cs);
+ cb = cs->cmdbuf;
+ IFNULLRET(cb);
+
+ /* unqueue completed buffer */
+ cs->cmdbytes -= cs->curlen;
+ dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD,
+ "write_command: sent %u bytes, %u left",
+ cs->curlen, cs->cmdbytes);
+ if ((cs->cmdbuf = cb->next) != NULL) {
+ cs->cmdbuf->prev = NULL;
+ cs->curlen = cs->cmdbuf->len;
+ } else {
+ cs->lastcmdbuf = NULL;
+ cs->curlen = 0;
+ }
+
+ if (cb->wake_tasklet)
+ tasklet_schedule(cb->wake_tasklet);
+
+ kfree(cb);
+}
+
+static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len);
+
+/* write_command_callback
+ * USB completion handler for AT command transmission
+ * called by the USB subsystem in interrupt context
+ * parameter:
+ * urb USB request block of completed request
+ * urb->context = controller state structure
+ */
+static void write_command_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct cardstate *cs;
+ unsigned long flags;
+ struct bas_cardstate *ucs;
+
+ IFNULLRET(urb);
+ cs = (struct cardstate *) urb->context;
+ IFNULLRET(cs);
+ ucs = cs->hw.bas;
+ IFNULLRET(ucs);
+
+ /* check status */
+ switch (urb->status) {
+ case 0: /* normal completion */
+ break;
+ case -ENOENT: /* canceled */
+ case -ECONNRESET: /* canceled (async) */
+ case -EINPROGRESS: /* pending */
+ /* ignore silently */
+ dbg(DEBUG_USBREQ,
+ "%s: %s", __func__, get_usb_statmsg(urb->status));
+ return;
+ default: /* any failure */
+ if (++ucs->retry_cmd_out > BAS_RETRY) {
+ warn("command write: %s, giving up after %d retries",
+ get_usb_statmsg(urb->status), ucs->retry_cmd_out);
+ break;
+ }
+ if (cs->cmdbuf == NULL) {
+ warn("command write: %s, cannot retry - cmdbuf gone",
+ get_usb_statmsg(urb->status));
+ break;
+ }
+ notice("command write: %s, retry %d",
+ get_usb_statmsg(urb->status), ucs->retry_cmd_out);
+ if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0)
+ /* resubmitted - bypass regular exit block */
+ return;
+ /* command send failed, assume base still waiting */
+ update_basstate(ucs, BS_ATREADY, 0);
+ }
+
+ spin_lock_irqsave(&cs->cmdlock, flags);
+ if (cs->cmdbuf != NULL)
+ complete_cb(cs);
+ spin_unlock_irqrestore(&cs->cmdlock, flags);
+}
+
+/* atrdy_timeout
+ * timeout routine for AT command transmission
+ * argument:
+ * controller state structure
+ */
+static void atrdy_timeout(unsigned long data)
+{
+ struct cardstate *cs = (struct cardstate *) data;
+ struct bas_cardstate *ucs;
+
+ IFNULLRET(cs);
+ ucs = cs->hw.bas;
+ IFNULLRET(ucs);
+
+ warn("timeout waiting for HD_READY_SEND_ATDATA");
+
+ /* fake the missing signal - what else can I do? */
+ update_basstate(ucs, BS_ATREADY, BS_ATTIMER);
+ start_cbsend(cs);
+}
+
+/* atwrite_submit
+ * submit an HD_WRITE_ATMESSAGE command URB
+ * parameters:
+ * cs controller state structure
+ * buf buffer containing command to send
+ * len length of command to send
+ * return value:
+ * 0 on success
+ * -EFAULT if a NULL pointer is encountered somewhere
+ * -EBUSY if another request is pending
+ * any URB submission error code
+ */
+static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
+{
+ struct bas_cardstate *ucs;
+ int ret;
+
+ IFNULLRETVAL(cs, -EFAULT);
+ ucs = cs->hw.bas;
+ IFNULLRETVAL(ucs, -EFAULT);
+ IFNULLRETVAL(ucs->urb_cmd_out, -EFAULT);
+
+ dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len);
+
+ if (ucs->urb_cmd_out->status == -EINPROGRESS) {
+ err("could not submit HD_WRITE_ATMESSAGE: URB busy");
+ return -EBUSY;
+ }
+
+ ucs->dr_cmd_out.bRequestType = OUT_VENDOR_REQ;
+ ucs->dr_cmd_out.bRequest = HD_WRITE_ATMESSAGE;
+ ucs->dr_cmd_out.wValue = 0;
+ ucs->dr_cmd_out.wIndex = 0;
+ ucs->dr_cmd_out.wLength = cpu_to_le16(len);
+ usb_fill_control_urb(ucs->urb_cmd_out, ucs->udev,
+ usb_sndctrlpipe(ucs->udev, 0),
+ (unsigned char*) &ucs->dr_cmd_out, buf, len,
+ write_command_callback, cs);
+
+ if ((ret = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC)) != 0) {
+ err("could not submit HD_WRITE_ATMESSAGE: %s",
+ get_usb_statmsg(ret));
+ return ret;
+ }
+
+ /* submitted successfully */
+ update_basstate(ucs, 0, BS_ATREADY);
+
+ /* start timeout if necessary */
+ if (!(atomic_read(&ucs->basstate) & BS_ATTIMER)) {
+ dbg(DEBUG_OUTPUT,
+ "setting ATREADY timeout of %d/10 secs", ATRDY_TIMEOUT);
+ ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10;
+ ucs->timer_atrdy.data = (unsigned long) cs;
+ ucs->timer_atrdy.function = atrdy_timeout;
+ add_timer(&ucs->timer_atrdy);
+ update_basstate(ucs, BS_ATTIMER, 0);
+ }
+ return 0;
+}
+
+/* start_cbsend
+ * start transmission of AT command queue if necessary
+ * parameter:
+ * cs controller state structure
+ * return value:
+ * 0 on success
+ * error code < 0 on error
+ */
+static int start_cbsend(struct cardstate *cs)
+{
+ struct cmdbuf_t *cb;
+ struct bas_cardstate *ucs;
+ unsigned long flags;
+ int rc;
+ int retval = 0;
+
+ IFNULLRETVAL(cs, -EFAULT);
+ ucs = cs->hw.bas;
+ IFNULLRETVAL(ucs, -EFAULT);
+
+ /* check if AT channel is open */
+ if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) {
+ dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD, "AT channel not open");
+ rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT);
+ if (rc < 0) {
+ err("could not open AT channel");
+ /* flush command queue */
+ spin_lock_irqsave(&cs->cmdlock, flags);
+ while (cs->cmdbuf != NULL)
+ complete_cb(cs);
+ spin_unlock_irqrestore(&cs->cmdlock, flags);
+ }
+ return rc;
+ }
+
+ /* try to send first command in queue */
+ spin_lock_irqsave(&cs->cmdlock, flags);
+
+ while ((cb = cs->cmdbuf) != NULL &&
+ atomic_read(&ucs->basstate) & BS_ATREADY) {
+ ucs->retry_cmd_out = 0;
+ rc = atwrite_submit(cs, cb->buf, cb->len);
+ if (unlikely(rc)) {
+ retval = rc;
+ complete_cb(cs);
+ }
+ }
+
+ spin_unlock_irqrestore(&cs->cmdlock, flags);
+ return retval;
+}
+
+/* gigaset_write_cmd
+ * This function is called by the device independent part of the driver
+ * to transmit an AT command string to the Gigaset device.
+ * It encapsulates the device specific method for transmission over the
+ * direct USB connection to the base.
+ * The command string is added to the queue of commands to send, and
+ * USB transmission is started if necessary.
+ * parameters:
+ * cs controller state structure
+ * buf command string to send
+ * len number of bytes to send (max. IF_WRITEBUF)
+ * wake_tasklet tasklet to run when transmission is completed (NULL if none)
+ * return value:
+ * number of bytes queued on success
+ * error code < 0 on error
+ */
+static int gigaset_write_cmd(struct cardstate *cs,
+ const unsigned char *buf, int len,
+ struct tasklet_struct *wake_tasklet)
+{
+ struct cmdbuf_t *cb;
+ unsigned long flags;
+ int status;
+
+ gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
+ DEBUG_TRANSCMD : DEBUG_LOCKCMD,
+ "CMD Transmit", len, buf, 0);
+
+ if (!atomic_read(&cs->connected)) {
+ err("%s: not connected", __func__);
+ return -ENODEV;
+ }
+
+ if (len <= 0)
+ return 0; /* nothing to do */
+
+ if (len > IF_WRITEBUF)
+ len = IF_WRITEBUF;
+ if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
+ err("%s: out of memory", __func__);
+ return -ENOMEM;
+ }
+
+ memcpy(cb->buf, buf, len);
+ cb->len = len;
+ cb->offset = 0;
+ cb->next = NULL;
+ cb->wake_tasklet = wake_tasklet;
+
+ spin_lock_irqsave(&cs->cmdlock, flags);
+ cb->prev = cs->lastcmdbuf;
+ if (cs->lastcmdbuf)
+ cs->lastcmdbuf->next = cb;
+ else {
+ cs->cmdbuf = cb;
+ cs->curlen = len;
+ }
+ cs->cmdbytes += len;
+ cs->lastcmdbuf = cb;
+ spin_unlock_irqrestore(&cs->cmdlock, flags);
+
+ status = start_cbsend(cs);
+
+ return status < 0 ? status : len;
+}
+
+/* gigaset_write_room
+ * tty_driver.write_room interface routine
+ * return number of characters the driver will accept to be written via gigaset_write_cmd
+ * parameter:
+ * controller state structure
+ * return value:
+ * number of characters
+ */
+static int gigaset_write_room(struct cardstate *cs)
+{
+ return IF_WRITEBUF;
+}
+
+/* gigaset_chars_in_buffer
+ * tty_driver.chars_in_buffer interface routine
+ * return number of characters waiting to be sent
+ * parameter:
+ * controller state structure
+ * return value:
+ * number of characters
+ */
+static int gigaset_chars_in_buffer(struct cardstate *cs)
+{
+ unsigned long flags;
+ unsigned bytes;
+
+ spin_lock_irqsave(&cs->cmdlock, flags);
+ bytes = cs->cmdbytes;
+ spin_unlock_irqrestore(&cs->cmdlock, flags);
+
+ return bytes;
+}
+
+/* gigaset_brkchars
+ * implementation of ioctl(GIGASET_BRKCHARS)
+ * parameter:
+ * controller state structure
+ * return value:
+ * -EINVAL (unimplemented function)
+ */
+static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
+{
+ return -EINVAL;
+}
+
+
+/* Device Initialization/Shutdown */
+/* ============================== */
+
+/* Free hardware dependent part of the B channel structure
+ * parameter:
+ * bcs B channel structure
+ * return value:
+ * !=0 on success
+ */
+static int gigaset_freebcshw(struct bc_state *bcs)
+{
+ if (!bcs->hw.bas)
+ return 0;
+
+ if (bcs->hw.bas->isooutbuf)
+ kfree(bcs->hw.bas->isooutbuf);
+ kfree(bcs->hw.bas);
+ bcs->hw.bas = NULL;
+ return 1;
+}
+
+/* Initialize hardware dependent part of the B channel structure
+ * parameter:
+ * bcs B channel structure
+ * return value:
+ * !=0 on success
+ */
+static int gigaset_initbcshw(struct bc_state *bcs)
+{
+ int i;
+ struct bas_bc_state *ubc;
+
+ bcs->hw.bas = ubc = kmalloc(sizeof(struct bas_bc_state), GFP_KERNEL);
+ if (!ubc) {
+ err("could not allocate bas_bc_state");
+ return 0;
+ }
+
+ atomic_set(&ubc->running, 0);
+ atomic_set(&ubc->corrbytes, 0);
+ spin_lock_init(&ubc->isooutlock);
+ for (i = 0; i < BAS_OUTURBS; ++i) {
+ ubc->isoouturbs[i].urb = NULL;
+ ubc->isoouturbs[i].bcs = bcs;
+ }
+ ubc->isooutdone = ubc->isooutfree = ubc->isooutovfl = NULL;
+ ubc->numsub = 0;
+ if (!(ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL))) {
+ err("could not allocate isochronous output buffer");
+ kfree(ubc);
+ bcs->hw.bas = NULL;
+ return 0;
+ }
+ tasklet_init(&ubc->sent_tasklet,
+ &write_iso_tasklet, (unsigned long) bcs);
+
+ spin_lock_init(&ubc->isoinlock);
+ for (i = 0; i < BAS_INURBS; ++i)
+ ubc->isoinurbs[i] = NULL;
+ ubc->isoindone = NULL;
+ ubc->loststatus = -EINPROGRESS;
+ ubc->isoinlost = 0;
+ ubc->seqlen = 0;
+ ubc->inbyte = 0;
+ ubc->inbits = 0;
+ ubc->goodbytes = 0;
+ ubc->alignerrs = 0;
+ ubc->fcserrs = 0;
+ ubc->frameerrs = 0;
+ ubc->giants = 0;
+ ubc->runts = 0;
+ ubc->aborts = 0;
+ ubc->shared0s = 0;
+ ubc->stolen0s = 0;
+ tasklet_init(&ubc->rcvd_tasklet,
+ &read_iso_tasklet, (unsigned long) bcs);
+ return 1;
+}
+
+static void gigaset_reinitbcshw(struct bc_state *bcs)
+{
+ struct bas_bc_state *ubc = bcs->hw.bas;
+
+ atomic_set(&bcs->hw.bas->running, 0);
+ atomic_set(&bcs->hw.bas->corrbytes, 0);
+ bcs->hw.bas->numsub = 0;
+ spin_lock_init(&ubc->isooutlock);
+ spin_lock_init(&ubc->isoinlock);
+ ubc->loststatus = -EINPROGRESS;
+}
+
+static void gigaset_freecshw(struct cardstate *cs)
+{
+ struct bas_cardstate *ucs = cs->hw.bas;
+
+ del_timer(&ucs->timer_ctrl);
+ del_timer(&ucs->timer_atrdy);
+ del_timer(&ucs->timer_cmd_in);
+
+ kfree(cs->hw.bas);
+}
+
+static int gigaset_initcshw(struct cardstate *cs)
+{
+ struct bas_cardstate *ucs;
+
+ cs->hw.bas = ucs = kmalloc(sizeof *ucs, GFP_KERNEL);
+ if (!ucs)
+ return 0;
+
+ ucs->urb_cmd_in = NULL;
+ ucs->urb_cmd_out = NULL;
+ ucs->rcvbuf = NULL;
+ ucs->rcvbuf_size = 0;
+
+ spin_lock_init(&ucs->lock);
+ ucs->pending = 0;
+
+ atomic_set(&ucs->basstate, 0);
+ init_timer(&ucs->timer_ctrl);
+ init_timer(&ucs->timer_atrdy);
+ init_timer(&ucs->timer_cmd_in);
+
+ return 1;
+}
+
+/* freeurbs
+ * unlink and deallocate all URBs unconditionally
+ * caller must make sure that no commands are still in progress
+ * parameter:
+ * cs controller state structure
+ */
+static void freeurbs(struct cardstate *cs)
+{
+ struct bas_cardstate *ucs;
+ struct bas_bc_state *ubc;
+ int i, j;
+
+ IFNULLRET(cs);
+ ucs = cs->hw.bas;
+ IFNULLRET(ucs);
+
+ for (j = 0; j < 2; ++j) {
+ ubc = cs->bcs[j].hw.bas;
+ IFNULLCONT(ubc);
+ for (i = 0; i < BAS_OUTURBS; ++i)
+ if (ubc->isoouturbs[i].urb) {
+ usb_kill_urb(ubc->isoouturbs[i].urb);
+ dbg(DEBUG_INIT,
+ "%s: isoc output URB %d/%d unlinked",
+ __func__, j, i);
+ usb_free_urb(ubc->isoouturbs[i].urb);
+ ubc->isoouturbs[i].urb = NULL;
+ }
+ for (i = 0; i < BAS_INURBS; ++i)
+ if (ubc->isoinurbs[i]) {
+ usb_kill_urb(ubc->isoinurbs[i]);
+ dbg(DEBUG_INIT,
+ "%s: isoc input URB %d/%d unlinked",
+ __func__, j, i);
+ usb_free_urb(ubc->isoinurbs[i]);
+ ubc->isoinurbs[i] = NULL;
+ }
+ }
+ if (ucs->urb_int_in) {
+ usb_kill_urb(ucs->urb_int_in);
+ dbg(DEBUG_INIT, "%s: interrupt input URB unlinked", __func__);
+ usb_free_urb(ucs->urb_int_in);
+ ucs->urb_int_in = NULL;
+ }
+ if (ucs->urb_cmd_out) {
+ usb_kill_urb(ucs->urb_cmd_out);
+ dbg(DEBUG_INIT, "%s: command output URB unlinked", __func__);
+ usb_free_urb(ucs->urb_cmd_out);
+ ucs->urb_cmd_out = NULL;
+ }
+ if (ucs->urb_cmd_in) {
+ usb_kill_urb(ucs->urb_cmd_in);
+ dbg(DEBUG_INIT, "%s: command input URB unlinked", __func__);
+ usb_free_urb(ucs->urb_cmd_in);
+ ucs->urb_cmd_in = NULL;
+ }
+ if (ucs->urb_ctrl) {
+ usb_kill_urb(ucs->urb_ctrl);
+ dbg(DEBUG_INIT, "%s: control output URB unlinked", __func__);
+ usb_free_urb(ucs->urb_ctrl);
+ ucs->urb_ctrl = NULL;
+ }
+}
+
+/* gigaset_probe
+ * This function is called when a new USB device is connected.
+ * It checks whether the new device is handled by this driver.
+ */
+static int gigaset_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct usb_host_interface *hostif;
+ struct usb_device *udev = interface_to_usbdev(interface);
+ struct cardstate *cs = NULL;
+ struct bas_cardstate *ucs = NULL;
+ struct bas_bc_state *ubc;
+ struct usb_endpoint_descriptor *endpoint;
+ int i, j;
+ int ret;
+
+ IFNULLRETVAL(udev, -ENODEV);
+
+ dbg(DEBUG_ANY,
+ "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
+ __func__, le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+
+ /* See if the device offered us matches what we can accept */
+ if ((le16_to_cpu(udev->descriptor.idVendor) != USB_GIGA_VENDOR_ID) ||
+ (le16_to_cpu(udev->descriptor.idProduct) != USB_GIGA_PRODUCT_ID &&
+ le16_to_cpu(udev->descriptor.idProduct) != USB_4175_PRODUCT_ID &&
+ le16_to_cpu(udev->descriptor.idProduct) != USB_SX303_PRODUCT_ID &&
+ le16_to_cpu(udev->descriptor.idProduct) != USB_SX353_PRODUCT_ID)) {
+ dbg(DEBUG_ANY, "%s: unmatched ID - exiting", __func__);
+ return -ENODEV;
+ }
+
+ /* set required alternate setting */
+ hostif = interface->cur_altsetting;
+ if (hostif->desc.bAlternateSetting != 3) {
+ dbg(DEBUG_ANY,
+ "%s: wrong alternate setting %d - trying to switch",
+ __func__, hostif->desc.bAlternateSetting);
+ if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) < 0) {
+ warn("usb_set_interface failed, device %d interface %d altsetting %d",
+ udev->devnum, hostif->desc.bInterfaceNumber,
+ hostif->desc.bAlternateSetting);
+ return -ENODEV;
+ }
+ hostif = interface->cur_altsetting;
+ }
+
+ /* Reject application specific interfaces
+ */
+ if (hostif->desc.bInterfaceClass != 255) {
+ warn("%s: bInterfaceClass == %d",
+ __func__, hostif->desc.bInterfaceClass);
+ return -ENODEV;
+ }
+
+ info("%s: Device matched (Vendor: 0x%x, Product: 0x%x)",
+ __func__, le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+
+ cs = gigaset_getunassignedcs(driver);
+ if (!cs) {
+ err("%s: no free cardstate", __func__);
+ return -ENODEV;
+ }
+ ucs = cs->hw.bas;
+ ucs->udev = udev;
+ ucs->interface = interface;
+
+ /* allocate URBs:
+ * - one for the interrupt pipe
+ * - three for the different uses of the default control pipe
+ * - three for each isochronous pipe
+ */
+ ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL);
+ if (!ucs->urb_int_in) {
+ err("No free urbs available");
+ goto error;
+ }
+ ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL);
+ if (!ucs->urb_cmd_in) {
+ err("No free urbs available");
+ goto error;
+ }
+ ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL);
+ if (!ucs->urb_cmd_out) {
+ err("No free urbs available");
+ goto error;
+ }
+ ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL);
+ if (!ucs->urb_ctrl) {
+ err("No free urbs available");
+ goto error;
+ }
+
+ for (j = 0; j < 2; ++j) {
+ ubc = cs->bcs[j].hw.bas;
+ for (i = 0; i < BAS_OUTURBS; ++i) {
+ ubc->isoouturbs[i].urb =
+ usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL);
+ if (!ubc->isoouturbs[i].urb) {
+ err("No free urbs available");
+ goto error;
+ }
+ }
+ for (i = 0; i < BAS_INURBS; ++i) {
+ ubc->isoinurbs[i] =
+ usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL);
+ if (!ubc->isoinurbs[i]) {
+ err("No free urbs available");
+ goto error;
+ }
+ }
+ }
+
+ ucs->rcvbuf = NULL;
+ ucs->rcvbuf_size = 0;
+
+ /* Fill the interrupt urb and send it to the core */
+ endpoint = &hostif->endpoint[0].desc;
+ usb_fill_int_urb(ucs->urb_int_in, udev,
+ usb_rcvintpipe(udev,
+ (endpoint->bEndpointAddress) & 0x0f),
+ ucs->int_in_buf, 3, read_int_callback, cs,
+ endpoint->bInterval);
+ ret = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL);
+ if (ret) {
+ err("could not submit interrupt URB: %s", get_usb_statmsg(ret));
+ goto error;
+ }
+
+ /* tell the device that the driver is ready */
+ if ((ret = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0)
+ goto error;
+
+ /* tell common part that the device is ready */
+ if (startmode == SM_LOCKED)
+ atomic_set(&cs->mstate, MS_LOCKED);
+ if (!gigaset_start(cs))
+ goto error;
+
+ /* save address of controller structure */
+ usb_set_intfdata(interface, cs);
+
+ /* set up device sysfs */
+ gigaset_init_dev_sysfs(interface);
+ return 0;
+
+error:
+ freeurbs(cs);
+ gigaset_unassign(cs);
+ return -ENODEV;
+}
+
+/* gigaset_disconnect
+ * This function is called when the Gigaset base is unplugged.
+ */
+static void gigaset_disconnect(struct usb_interface *interface)
+{
+ struct cardstate *cs;
+ struct bas_cardstate *ucs;
+
+ /* clear device sysfs */
+ gigaset_free_dev_sysfs(interface);
+
+ cs = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
+
+ IFNULLRET(cs);
+ ucs = cs->hw.bas;
+ IFNULLRET(ucs);
+
+ info("disconnecting GigaSet base");
+ gigaset_stop(cs);
+ freeurbs(cs);
+ kfree(ucs->rcvbuf);
+ ucs->rcvbuf = NULL;
+ ucs->rcvbuf_size = 0;
+ atomic_set(&ucs->basstate, 0);
+ gigaset_unassign(cs);
+}
+
+static struct gigaset_ops gigops = {
+ gigaset_write_cmd,
+ gigaset_write_room,
+ gigaset_chars_in_buffer,
+ gigaset_brkchars,
+ gigaset_init_bchannel,
+ gigaset_close_bchannel,
+ gigaset_initbcshw,
+ gigaset_freebcshw,
+ gigaset_reinitbcshw,
+ gigaset_initcshw,
+ gigaset_freecshw,
+ gigaset_set_modem_ctrl,
+ gigaset_baud_rate,
+ gigaset_set_line_ctrl,
+ gigaset_isoc_send_skb,
+ gigaset_isoc_input,
+};
+
+/* bas_gigaset_init
+ * This function is called after the kernel module is loaded.
+ */
+static int __init bas_gigaset_init(void)
+{
+ int result;
+
+ /* allocate memory for our driver state and intialize it */
+ if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
+ GIGASET_MODULENAME, GIGASET_DEVNAME,
+ GIGASET_DEVFSNAME, &gigops,
+ THIS_MODULE)) == NULL)
+ goto error;
+
+ /* allocate memory for our device state and intialize it */
+ cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode, GIGASET_MODULENAME);
+ if (!cardstate)
+ goto error;
+
+ /* register this driver with the USB subsystem */
+ result = usb_register(&gigaset_usb_driver);
+ if (result < 0) {
+ err("usb_register failed (error %d)", -result);
+ goto error;
+ }
+
+ info(DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+ return 0;
+
+error: if (cardstate)
+ gigaset_freecs(cardstate);
+ cardstate = NULL;
+ if (driver)
+ gigaset_freedriver(driver);
+ driver = NULL;
+ return -1;
+}
+
+/* bas_gigaset_exit
+ * This function is called before the kernel module is unloaded.
+ */
+static void __exit bas_gigaset_exit(void)
+{
+ gigaset_blockdriver(driver); /* => probe will fail
+ * => no gigaset_start any more
+ */
+
+ gigaset_shutdown(cardstate);
+ /* from now on, no isdn callback should be possible */
+
+ if (atomic_read(&cardstate->hw.bas->basstate) & BS_ATOPEN) {
+ dbg(DEBUG_ANY, "closing AT channel");
+ if (req_submit(cardstate->bcs,
+ HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT) >= 0) {
+ /* successfully submitted - wait for completion */
+ //wait_event_interruptible(cs->initwait, !cs->hw.bas->pending);
+ //FIXME need own wait queue? wakeup?
+ }
+ }
+
+ /* deregister this driver with the USB subsystem */
+ usb_deregister(&gigaset_usb_driver);
+ /* this will call the disconnect-callback */
+ /* from now on, no disconnect/probe callback should be running */
+
+ gigaset_freecs(cardstate);
+ cardstate = NULL;
+ gigaset_freedriver(driver);
+ driver = NULL;
+}
+
+
+module_init(bas_gigaset_init);
+module_exit(bas_gigaset_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
new file mode 100644
index 00000000000..64371995c1a
--- /dev/null
+++ b/drivers/isdn/gigaset/common.c
@@ -0,0 +1,1203 @@
+/*
+ * Stuff used by all variants of the driver
+ *
+ * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>,
+ * Hansjoerg Lipp <hjlipp@web.de>,
+ * Tilman Schmidt <tilman@imap.cc>.
+ *
+ * =====================================================================
+ * 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.
+ * =====================================================================
+ * ToDo: ...
+ * =====================================================================
+ * Version: $Id: common.c,v 1.104.4.22 2006/02/04 18:28:16 hjlipp Exp $
+ * =====================================================================
+ */
+
+#include "gigaset.h"
+#include <linux/ctype.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+/* Version Information */
+#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_DESC "Driver for Gigaset 307x"
+
+/* Module parameters */
+int gigaset_debuglevel = DEBUG_DEFAULT;
+EXPORT_SYMBOL_GPL(gigaset_debuglevel);
+module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(debug, "debug level");
+
+/*======================================================================
+ Prototypes of internal functions
+ */
+
+//static void gigaset_process_response(int resp_code, int parameter,
+// struct at_state_t *at_state,
+// unsigned char ** pstring);
+static struct cardstate *alloc_cs(struct gigaset_driver *drv);
+static void free_cs(struct cardstate *cs);
+static void make_valid(struct cardstate *cs, unsigned mask);
+static void make_invalid(struct cardstate *cs, unsigned mask);
+
+#define VALID_MINOR 0x01
+#define VALID_ID 0x02
+#define ASSIGNED 0x04
+
+/* bitwise byte inversion table */
+__u8 gigaset_invtab[256] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+EXPORT_SYMBOL_GPL(gigaset_invtab);
+
+void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
+ size_t len, const unsigned char *buf, int from_user)
+{
+ unsigned char outbuf[80];
+ unsigned char inbuf[80 - 1];
+ size_t numin;
+ const unsigned char *in;
+ size_t space = sizeof outbuf - 1;
+ unsigned char *out = outbuf;
+
+ if (!from_user) {
+ in = buf;
+ numin = len;
+ } else {
+ numin = len < sizeof inbuf ? len : sizeof inbuf;
+ in = inbuf;
+ if (copy_from_user(inbuf, (const unsigned char __user *) buf, numin)) {
+ strncpy(inbuf, "<FAULT>", sizeof inbuf);
+ numin = sizeof "<FAULT>" - 1;
+ }
+ }
+
+ for (; numin && space; --numin, ++in) {
+ --space;
+ if (*in >= 32)
+ *out++ = *in;
+ else {
+ *out++ = '^';
+ if (space) {
+ *out++ = '@' + *in;
+ --space;
+ }
+ }
+ }
+ *out = 0;
+
+ dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf);
+}
+EXPORT_SYMBOL_GPL(gigaset_dbg_buffer);
+
+static int setflags(struct cardstate *cs, unsigned flags, unsigned delay)
+{
+ int r;
+
+ r = cs->ops->set_modem_ctrl(cs, cs->control_state, flags);
+ cs->control_state = flags;
+ if (r < 0)
+ return r;
+
+ if (delay) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(delay * HZ / 1000);
+ }
+
+ return 0;
+}
+
+int gigaset_enterconfigmode(struct cardstate *cs)
+{
+ int i, r;
+
+ if (!atomic_read(&cs->connected)) {
+ err("not connected!");
+ return -1;
+ }
+
+ cs->control_state = TIOCM_RTS; //FIXME
+
+ r = setflags(cs, TIOCM_DTR, 200);
+ if (r < 0)
+ goto error;
+ r = setflags(cs, 0, 200);
+ if (r < 0)
+ goto error;
+ for (i = 0; i < 5; ++i) {
+ r = setflags(cs, TIOCM_RTS, 100);
+ if (r < 0)
+ goto error;
+ r = setflags(cs, 0, 100);
+ if (r < 0)
+ goto error;
+ }
+ r = setflags(cs, TIOCM_RTS|TIOCM_DTR, 800);
+ if (r < 0)
+ goto error;
+
+ return 0;
+
+error:
+ err("error %d on setuartbits!\n", -r);
+ cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value?
+ cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR);
+
+ return -1; //r
+}
+
+static int test_timeout(struct at_state_t *at_state)
+{
+ if (!at_state->timer_expires)
+ return 0;
+
+ if (--at_state->timer_expires) {
+ dbg(DEBUG_MCMD, "decreased timer of %p to %lu",
+ at_state, at_state->timer_expires);
+ return 0;
+ }
+
+ if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL,
+ atomic_read(&at_state->timer_index), NULL)) {
+ //FIXME what should we do?
+ }
+
+ return 1;
+}
+
+static void timer_tick(unsigned long data)
+{
+ struct cardstate *cs = (struct cardstate *) data;
+ unsigned long flags;
+ unsigned channel;
+ struct at_state_t *at_state;
+ int timeout = 0;
+
+ spin_lock_irqsave(&cs->lock, flags);
+
+ for (channel = 0; channel < cs->channels; ++channel)
+ if (test_timeout(&cs->bcs[channel].at_state))
+ timeout = 1;
+
+ if (test_timeout(&cs->at_state))
+ timeout = 1;
+
+ list_for_each_entry(at_state, &cs->temp_at_states, list)
+ if (test_timeout(at_state))
+ timeout = 1;
+
+ if (atomic_read(&cs->running)) {
+ mod_timer(&cs->timer, jiffies + GIG_TICK);
+ if (timeout) {
+ dbg(DEBUG_CMD, "scheduling timeout");
+ tasklet_schedule(&cs->event_tasklet);
+ }
+ }
+
+ spin_unlock_irqrestore(&cs->lock, flags);
+}
+
+int gigaset_get_channel(struct bc_state *bcs)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&bcs->cs->lock, flags);
+ if (bcs->use_count) {
+ dbg(DEBUG_ANY, "could not allocate channel %d", bcs->channel);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
+ return 0;
+ }
+ ++bcs->use_count;
+ bcs->busy = 1;
+ dbg(DEBUG_ANY, "allocated channel %d", bcs->channel);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
+ return 1;
+}
+
+void gigaset_free_channel(struct bc_state *bcs)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&bcs->cs->lock, flags);
+ if (!bcs->busy) {
+ dbg(DEBUG_ANY, "could not free channel %d", bcs->channel);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
+ return;
+ }
+ --bcs->use_count;
+ bcs->busy = 0;
+ dbg(DEBUG_ANY, "freed channel %d", bcs->channel);
+ spin_unlock_irqrestore(&bcs->cs->lock, flags);
+}
+
+int gigaset_get_channels(struct cardstate *cs)
+{
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&cs->lock, flags);
+ for (i = 0; i < cs->channels; ++i)
+ if (cs->bcs[i].use_count) {
+ spin_unlock_irqrestore(&cs->lock, flags);
+ dbg(DEBUG_ANY, "could not allocated all channels");
+ return 0;
+ }
+ for (i = 0; i < cs->channels; ++i)
+ ++cs->bcs[i].use_count;
+ spin_unlock_irqrestore(&cs->lock, flags);
+
+ dbg(DEBUG_ANY, "allocated all channels");
+
+ return 1;
+}
+
+void gigaset_free_channels(struct cardstate *cs)
+{
+ unsigned long flags;
+ int i;
+
+ dbg(DEBUG_ANY, "unblocking all channels");
+ spin_lock_irqsave(&cs->lock, flags);
+ for (i = 0; i < cs->channels; ++i)
+ --cs->bcs[i].use_count;
+ spin_unlock_irqrestore(&cs->lock, flags);
+}
+
+void gigaset_block_channels(struct cardstate *cs)
+{
+ unsigned long flags;
+ int i;
+
+ dbg(DEBUG_ANY, "blocking all channels");
+ spin_lock_irqsave(&cs->lock, flags);
+ for (i = 0; i < cs->channels; ++i)
+ ++cs->bcs[i].use_count;
+ spin_unlock_irqrestore(&cs->lock, flags);
+}
+
+static void clear_events(struct cardstate *cs)
+{
+ struct event_t *ev;
+ unsigned head, tail;
+
+ /* no locking needed (no reader/writer allowed) */
+
+ head = atomic_read(&cs->ev_head);
+ tail = atomic_read(&cs->ev_tail);
+
+ while (tail != head) {
+ ev = cs->events + head;
+ kfree(ev->ptr);
+
+ head = (head + 1) % MAX_EVENTS;
+ }
+
+ atomic_set(&cs->ev_head, tail);
+}
+
+struct event_t *gigaset_add_event(struct cardstate *cs,
+ struct at_state_t *at_state, int type,
+ void *ptr, int parameter, void *arg)
+{
+ unsigned long flags;
+ unsigned next, tail;
+ struct event_t *event = NULL;
+
+ spin_lock_irqsave(&cs->ev_lock, flags);
+
+ tail = atomic_read(&cs->ev_tail);
+ next = (tail + 1) % MAX_EVENTS;
+ if (unlikely(next == atomic_read(&cs->ev_head)))
+ err("event queue full");
+ else {
+ event = cs->events + tail;
+ event->type = type;
+ event->at_state = at_state;
+ event->cid = -1;
+ event->ptr = ptr;
+ event->arg = arg;
+ event->parameter = parameter;
+ atomic_set(&cs->ev_tail, next);
+ }
+
+ spin_unlock_irqrestore(&cs->ev_lock, flags);
+
+ return event;
+}
+EXPORT_SYMBOL_GPL(gigaset_add_event);
+
+static void free_strings(struct at_state_t *at_state)
+{
+ int i;
+
+ for (i = 0; i < STR_NUM; ++i) {
+ kfree(at_state->str_var[i]);
+ at_state->str_var[i] = NULL;
+ }
+}
+
+static void clear_at_state(struct at_state_t *at_state)
+{
+ free_strings(at_state);
+}
+
+static void dealloc_at_states(struct cardstate *cs)
+{
+ struct at_state_t *cur, *next;
+
+ list_for_each_entry_safe(cur, next, &cs->temp_at_states, list) {
+ list_del(&cur->list);
+ free_strings(cur);
+ kfree(cur);
+ }
+}
+
+static void gigaset_freebcs(struct bc_state *bcs)
+{
+ int i;
+
+ dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel);
+ if (!bcs->cs->ops->freebcshw(bcs)) {
+ dbg(DEBUG_INIT, "failed");
+ }
+
+ dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
+ clear_at_state(&bcs->at_state);
+ dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
+
+ if (bcs->skb)
+ dev_kfree_skb(bcs->skb);
+ for (i = 0; i < AT_NUM; ++i) {
+ kfree(bcs->commands[i]);
+ bcs->commands[i] = NULL;
+ }
+}
+
+void gigaset_freecs(struct cardstate *cs)
+{
+ int i;
+ unsigned long flags;
+
+ if (!cs)
+ return;
+
+ down(&cs->sem);
+
+ if (!cs->bcs)
+ goto f_cs;
+ if (!cs->inbuf)
+ goto f_bcs;
+
+ spin_lock_irqsave(&cs->lock, flags);
+ atomic_set(&cs->running, 0);
+ spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are not rescheduled below */
+
+ tasklet_kill(&cs->event_tasklet);
+ del_timer_sync(&cs->timer);
+
+ switch (cs->cs_init) {
+ default:
+ gigaset_if_free(cs);
+
+ dbg(DEBUG_INIT, "clearing hw");
+ cs->ops->freecshw(cs);
+
+ //FIXME cmdbuf
+
+ /* fall through */
+ case 2: /* error in initcshw */
+ /* Deregister from LL */
+ make_invalid(cs, VALID_ID);
+ dbg(DEBUG_INIT, "clearing iif");
+ gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
+
+ /* fall through */
+ case 1: /* error when regestering to LL */
+ dbg(DEBUG_INIT, "clearing at_state");
+ clear_at_state(&cs->at_state);
+ dealloc_at_states(cs);
+
+ /* fall through */
+ case 0: /* error in one call to initbcs */
+ for (i = 0; i < cs->channels; ++i) {
+ dbg(DEBUG_INIT, "clearing bcs[%d]", i);
+ gigaset_freebcs(cs->bcs + i);
+ }
+
+ clear_events(cs);
+ dbg(DEBUG_INIT, "freeing inbuf");
+ kfree(cs->inbuf);
+ }
+f_bcs: dbg(DEBUG_INIT, "freeing bcs[]");
+ kfree(cs->bcs);
+f_cs: dbg(DEBUG_INIT, "freeing cs");
+ up(&cs->sem);
+ free_cs(cs);
+}
+EXPORT_SYMBOL_GPL(gigaset_freecs);
+
+void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
+ struct cardstate *cs, int cid)
+{
+ int i;
+
+ INIT_LIST_HEAD(&at_state->list);
+ at_state->waiting = 0;
+ at_state->getstring = 0;
+ at_state->pending_commands = 0;
+ at_state->timer_expires = 0;
+ at_state->timer_active = 0;
+ atomic_set(&at_state->timer_index, 0);
+ atomic_set(&at_state->seq_index, 0);
+ at_state->ConState = 0;
+ for (i = 0; i < STR_NUM; ++i)
+ at_state->str_var[i] = NULL;
+ at_state->int_var[VAR_ZDLE] = 0;
+ at_state->int_var[VAR_ZCTP] = -1;
+ at_state->int_var[VAR_ZSAU] = ZSAU_NULL;
+ at_state->cs = cs;
+ at_state->bcs = bcs;
+ at_state->cid = cid;
+ if (!cid)
+ at_state->replystruct = cs->tabnocid;
+ else
+ at_state->replystruct = cs->tabcid;
+}
+
+
+static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs,
+ struct cardstate *cs, int inputstate)
+/* inbuf->read must be allocated before! */
+{
+ atomic_set(&inbuf->head, 0);
+ atomic_set(&inbuf->tail, 0);
+ inbuf->cs = cs;
+ inbuf->bcs = bcs; /*base driver: NULL*/
+ inbuf->rcvbuf = NULL; //FIXME
+ inbuf->inputstate = inputstate;
+}
+
+/* Initialize the b-channel structure */
+static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
+ struct cardstate *cs, int channel)
+{
+ int i;
+
+ bcs->tx_skb = NULL; //FIXME -> hw part
+
+ skb_queue_head_init(&bcs->squeue);
+
+ bcs->corrupted = 0;
+ bcs->trans_down = 0;
+ bcs->trans_up = 0;
+
+ dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel);
+ gigaset_at_init(&bcs->at_state, bcs, cs, -1);
+
+ bcs->rcvbytes = 0;
+
+#ifdef CONFIG_GIGASET_DEBUG
+ bcs->emptycount = 0;
+#endif
+
+ dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
+ bcs->fcs = PPP_INITFCS;
+ bcs->inputstate = 0;
+ if (cs->ignoreframes) {
+ bcs->inputstate |= INS_skip_frame;
+ bcs->skb = NULL;
+ } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
+ skb_reserve(bcs->skb, HW_HDR_LEN);
+ else {
+ warn("could not allocate skb");
+ bcs->inputstate |= INS_skip_frame;
+ }
+
+ bcs->channel = channel;
+ bcs->cs = cs;
+
+ bcs->chstate = 0;
+ bcs->use_count = 1;
+ bcs->busy = 0;
+ bcs->ignore = cs->ignoreframes;
+
+ for (i = 0; i < AT_NUM; ++i)
+ bcs->commands[i] = NULL;
+
+ dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel);
+ if (cs->ops->initbcshw(bcs))
+ return bcs;
+
+//error:
+ dbg(DEBUG_INIT, " failed");
+
+ dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel);
+ if (bcs->skb)
+ dev_kfree_skb(bcs->skb);
+
+ return NULL;
+}
+
+/* gigaset_initcs
+ * Allocate and initialize cardstate structure for Gigaset driver
+ * Calls hardware dependent gigaset_initcshw() function
+ * Calls B channel initialization function gigaset_initbcs() for each B channel
+ * parameters:
+ * drv hardware driver the device belongs to
+ * channels number of B channels supported by device
+ * onechannel !=0: B channel data and AT commands share one communication channel
+ * ==0: B channels have separate communication channels
+ * ignoreframes number of frames to ignore after setting up B channel
+ * cidmode !=0: start in CallID mode
+ * modulename name of driver module (used for I4L registration)
+ * return value:
+ * pointer to cardstate structure
+ */
+struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
+ int onechannel, int ignoreframes,
+ int cidmode, const char *modulename)
+{
+ struct cardstate *cs = NULL;
+ int i;
+
+ dbg(DEBUG_INIT, "allocating cs");
+ cs = alloc_cs(drv);
+ if (!cs)
+ goto error;
+ dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
+ cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
+ if (!cs->bcs)
+ goto error;
+ dbg(DEBUG_INIT, "allocating inbuf");
+ cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL);
+ if (!cs->inbuf)
+ goto error;
+
+ cs->cs_init = 0;
+ cs->channels = channels;
+ cs->onechannel = onechannel;
+ cs->ignoreframes = ignoreframes;
+ INIT_LIST_HEAD(&cs->temp_at_states);
+ atomic_set(&cs->running, 0);
+ init_timer(&cs->timer); /* clear next & prev */
+ spin_lock_init(&cs->ev_lock);
+ atomic_set(&cs->ev_tail, 0);
+ atomic_set(&cs->ev_head, 0);
+ init_MUTEX_LOCKED(&cs->sem);
+ tasklet_init(&cs->event_tasklet, &gigaset_handle_event, (unsigned long) cs);
+ atomic_set(&cs->commands_pending, 0);
+ cs->cur_at_seq = 0;
+ cs->gotfwver = -1;
+ cs->open_count = 0;
+ cs->tty = NULL;
+ atomic_set(&cs->cidmode, cidmode != 0);
+
+ //if(onechannel) { //FIXME
+ cs->tabnocid = gigaset_tab_nocid_m10x;
+ cs->tabcid = gigaset_tab_cid_m10x;
+ //} else {
+ // cs->tabnocid = gigaset_tab_nocid;
+ // cs->tabcid = gigaset_tab_cid;
+ //}
+
+ init_waitqueue_head(&cs->waitqueue);
+ cs->waiting = 0;
+
+ atomic_set(&cs->mode, M_UNKNOWN);
+ atomic_set(&cs->mstate, MS_UNINITIALIZED);
+
+ for (i = 0; i < channels; ++i) {
+ dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
+ if (!gigaset_initbcs(cs->bcs + i, cs, i))
+ goto error;
+ }
+
+ ++cs->cs_init;
+
+ dbg(DEBUG_INIT, "setting up at_state");
+ spin_lock_init(&cs->lock);
+ gigaset_at_init(&cs->at_state, NULL, cs, 0);
+ cs->dle = 0;
+ cs->cbytes = 0;
+
+ dbg(DEBUG_INIT, "setting up inbuf");
+ if (onechannel) { //FIXME distinction necessary?
+ gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command);
+ } else
+ gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command);
+
+ atomic_set(&cs->connected, 0);
+
+ dbg(DEBUG_INIT, "setting up cmdbuf");
+ cs->cmdbuf = cs->lastcmdbuf = NULL;
+ spin_lock_init(&cs->cmdlock);
+ cs->curlen = 0;
+ cs->cmdbytes = 0;
+
+ /*
+ * Tell the ISDN4Linux subsystem (the LL) that
+ * a driver for a USB-Device is available !
+ * If this is done, "isdnctrl" is able to bind a device for this driver even
+ * if no physical usb-device is currently connected.
+ * But this device will just be accessable if a physical USB device is connected
+ * (via "gigaset_probe") .
+ */
+ dbg(DEBUG_INIT, "setting up iif");
+ if (!gigaset_register_to_LL(cs, modulename)) {
+ err("register_isdn=>error");
+ goto error;
+ }
+
+ make_valid(cs, VALID_ID);
+ ++cs->cs_init;
+ dbg(DEBUG_INIT, "setting up hw");
+ if (!cs->ops->initcshw(cs))
+ goto error;
+
+ ++cs->cs_init;
+
+ gigaset_if_init(cs);
+
+ atomic_set(&cs->running, 1);
+ cs->timer.data = (unsigned long) cs;
+ cs->timer.function = timer_tick;
+ cs->timer.expires = jiffies + GIG_TICK;
+ /* FIXME: can jiffies increase too much until the timer is added?
+ * Same problem(?) with mod_timer() in timer_tick(). */
+ add_timer(&cs->timer);
+
+ dbg(DEBUG_INIT, "cs initialized!");
+ up(&cs->sem);
+ return cs;
+
+error: if (cs)
+ up(&cs->sem);
+ dbg(DEBUG_INIT, "failed");
+ gigaset_freecs(cs);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(gigaset_initcs);
+
+/* ReInitialize the b-channel structure */ /* e.g. called on hangup, disconnect */
+void gigaset_bcs_reinit(struct bc_state *bcs)
+{
+ struct sk_buff *skb;
+ struct cardstate *cs = bcs->cs;
+ unsigned long flags;
+
+ while ((skb = skb_dequeue(&bcs->squeue)) != NULL)
+ dev_kfree_skb(skb);
+
+ spin_lock_irqsave(&cs->lock, flags); //FIXME
+ clear_at_state(&bcs->at_state);
+ bcs->at_state.ConState = 0;
+ bcs->at_state.timer_active = 0;
+ bcs->at_state.timer_expires = 0;
+ bcs->at_state.cid = -1; /* No CID defined */
+ spin_unlock_irqrestore(&cs->lock, flags);
+
+ bcs->inputstate = 0;
+
+#ifdef CONFIG_GIGASET_DEBUG
+ bcs->emptycount = 0;
+#endif
+
+ bcs->fcs = PPP_INITFCS;
+ bcs->chstate = 0;
+
+ bcs->ignore = cs->ignoreframes;
+ if (bcs->ignore)
+ bcs->inputstate |= INS_skip_frame;
+
+
+ cs->ops->reinitbcshw(bcs);
+}
+
+static void cleanup_cs(struct cardstate *cs)
+{
+ struct cmdbuf_t *cb, *tcb;
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cs->lock, flags);
+
+ atomic_set(&cs->mode, M_UNKNOWN);
+ atomic_set(&cs->mstate, MS_UNINITIALIZED);
+
+ clear_at_state(&cs->at_state);
+ dealloc_at_states(cs);
+ free_strings(&cs->at_state);
+ gigaset_at_init(&cs->at_state, NULL, cs, 0);
+
+ kfree(cs->inbuf->rcvbuf);
+ cs->inbuf->rcvbuf = NULL;
+ cs->inbuf->inputstate = INS_command;
+ atomic_set(&cs->inbuf->head, 0);
+ atomic_set(&cs->inbuf->tail, 0);
+
+ cb = cs->cmdbuf;
+ while (cb) {
+ tcb = cb;
+ cb = cb->next;
+ kfree(tcb);
+ }
+ cs->cmdbuf = cs->lastcmdbuf = NULL;
+ cs->curlen = 0;
+ cs->cmdbytes = 0;
+ cs->gotfwver = -1;
+ cs->dle = 0;
+ cs->cur_at_seq = 0;
+ atomic_set(&cs->commands_pending, 0);
+ cs->cbytes = 0;
+
+ spin_unlock_irqrestore(&cs->lock, flags);
+
+ for (i = 0; i < cs->channels; ++i) {
+ gigaset_freebcs(cs->bcs + i);
+ if (!gigaset_initbcs(cs->bcs + i, cs, i))
+ break; //FIXME error handling
+ }
+
+ if (cs->waiting) {
+ cs->cmd_result = -ENODEV;
+ cs->waiting = 0;
+ wake_up_interruptible(&cs->waitqueue);
+ }
+}
+
+
+int gigaset_start(struct cardstate *cs)
+{
+ if (down_interruptible(&cs->sem))
+ return 0;
+ //info("USB device for Gigaset 307x now attached to Dev %d", ucs->minor);
+
+ atomic_set(&cs->connected, 1);
+
+ if (atomic_read(&cs->mstate) != MS_LOCKED) {
+ cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
+ cs->ops->baud_rate(cs, B115200);
+ cs->ops->set_line_ctrl(cs, CS8);
+ cs->control_state = TIOCM_DTR|TIOCM_RTS;
+ } else {
+ //FIXME use some saved values?
+ }
+
+ cs->waiting = 1;
+
+ if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) {
+ cs->waiting = 0;
+ //FIXME what should we do?
+ goto error;
+ }
+
+ dbg(DEBUG_CMD, "scheduling START");
+ gigaset_schedule_event(cs);
+
+ wait_event(cs->waitqueue, !cs->waiting);
+
+ up(&cs->sem);
+ return 1;
+
+error:
+ up(&cs->sem);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(gigaset_start);
+
+void gigaset_shutdown(struct cardstate *cs)
+{
+ down(&cs->sem);
+
+ cs->waiting = 1;
+
+ if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) {
+ //FIXME what should we do?
+ goto exit;
+ }
+
+ dbg(DEBUG_CMD, "scheduling SHUTDOWN");
+ gigaset_schedule_event(cs);
+
+ if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
+ warn("aborted");
+ //FIXME
+ }
+
+ if (atomic_read(&cs->mstate) != MS_LOCKED) {
+ //FIXME?
+ //gigaset_baud_rate(cs, B115200);
+ //gigaset_set_line_ctrl(cs, CS8);
+ //gigaset_set_modem_ctrl(cs, TIOCM_DTR|TIOCM_RTS, 0);
+ //cs->control_state = 0;
+ } else {
+ //FIXME use some saved values?
+ }
+
+ cleanup_cs(cs);
+
+exit:
+ up(&cs->sem);
+}
+EXPORT_SYMBOL_GPL(gigaset_shutdown);
+
+void gigaset_stop(struct cardstate *cs)
+{
+ down(&cs->sem);
+
+ atomic_set(&cs->connected, 0);
+
+ cs->waiting = 1;
+
+ if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) {
+ //FIXME what should we do?
+ goto exit;
+ }
+
+ dbg(DEBUG_CMD, "scheduling STOP");
+ gigaset_schedule_event(cs);
+
+ if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
+ warn("aborted");
+ //FIXME
+ }
+
+ /* Tell the LL that the device is not available .. */
+ gigaset_i4l_cmd(cs, ISDN_STAT_STOP); // FIXME move to event layer?
+
+ cleanup_cs(cs);
+
+exit:
+ up(&cs->sem);
+}
+EXPORT_SYMBOL_GPL(gigaset_stop);
+
+static LIST_HEAD(drivers);
+static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
+
+struct cardstate *gigaset_get_cs_by_id(int id)
+{
+ unsigned long flags;
+ static struct cardstate *ret = NULL;
+ static struct cardstate *cs;
+ struct gigaset_driver *drv;
+ unsigned i;
+
+ spin_lock_irqsave(&driver_lock, flags);
+ list_for_each_entry(drv, &drivers, list) {
+ spin_lock(&drv->lock);
+ for (i = 0; i < drv->minors; ++i) {
+ if (drv->flags[i] & VALID_ID) {
+ cs = drv->cs + i;
+ if (cs->myid == id)
+ ret = cs;
+ }
+ if (ret)
+ break;
+ }
+ spin_unlock(&drv->lock);
+ if (ret)
+ break;
+ }
+ spin_unlock_irqrestore(&driver_lock, flags);
+ return ret;
+}
+
+void gigaset_debugdrivers(void)
+{
+ unsigned long flags;
+ static struct cardstate *cs;
+ struct gigaset_driver *drv;
+ unsigned i;
+
+ spin_lock_irqsave(&driver_lock, flags);
+ list_for_each_entry(drv, &drivers, list) {
+ dbg(DEBUG_DRIVER, "driver %p", drv);
+ spin_lock(&drv->lock);
+ for (i = 0; i < drv->minors; ++i) {
+ dbg(DEBUG_DRIVER, " index %u", i);
+ dbg(DEBUG_DRIVER, " flags 0x%02x", drv->flags[i]);
+ cs = drv->cs + i;
+ dbg(DEBUG_DRIVER, " cardstate %p", cs);
+ dbg(DEBUG_DRIVER, " minor_index %u", cs->minor_index);
+ dbg(DEBUG_DRIVER, " driver %p", cs->driver);
+ dbg(DEBUG_DRIVER, " i4l id %d", cs->myid);
+ }
+ spin_unlock(&drv->lock);
+ }
+ spin_unlock_irqrestore(&driver_lock, flags);
+}
+EXPORT_SYMBOL_GPL(gigaset_debugdrivers);
+
+struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty)
+{
+ if (tty->index < 0 || tty->index >= tty->driver->num)
+ return NULL;
+ return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start);
+}
+
+struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
+{
+ unsigned long flags;
+ static struct cardstate *ret = NULL;
+ struct gigaset_driver *drv;
+ unsigned index;
+
+ spin_lock_irqsave(&driver_lock, flags);
+ list_for_each_entry(drv, &drivers, list) {
+ if (minor < drv->minor || minor >= drv->minor + drv->minors)
+ continue;
+ index = minor - drv->minor;
+ spin_lock(&drv->lock);
+ if (drv->flags[index] & VALID_MINOR)
+ ret = drv->cs + index;
+ spin_unlock(&drv->lock);
+ if (ret)
+ break;
+ }
+ spin_unlock_irqrestore(&driver_lock, flags);
+ return ret;
+}
+
+void gigaset_freedriver(struct gigaset_driver *drv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&driver_lock, flags);
+ list_del(&drv->list);
+ spin_unlock_irqrestore(&driver_lock, flags);
+
+ gigaset_if_freedriver(drv);
+ module_put(drv->owner);
+
+ kfree(drv->cs);
+ kfree(drv->flags);
+ kfree(drv);
+}
+EXPORT_SYMBOL_GPL(gigaset_freedriver);
+
+/* gigaset_initdriver
+ * Allocate and initialize gigaset_driver structure. Initialize interface.
+ * parameters:
+ * minor First minor number
+ * minors Number of minors this driver can handle
+ * procname Name of the driver (e.g. for /proc/tty/drivers, path in /proc/driver)
+ * devname Name of the device files (prefix without minor number)
+ * devfsname Devfs name of the device files without %d
+ * return value:
+ * Pointer to the gigaset_driver structure on success, NULL on failure.
+ */
+struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
+ const char *procname,
+ const char *devname,
+ const char *devfsname,
+ const struct gigaset_ops *ops,
+ struct module *owner)
+{
+ struct gigaset_driver *drv;
+ unsigned long flags;
+ unsigned i;
+
+ drv = kmalloc(sizeof *drv, GFP_KERNEL);
+ if (!drv)
+ return NULL;
+ if (!try_module_get(owner))
+ return NULL;
+
+ drv->cs = NULL;
+ drv->have_tty = 0;
+ drv->minor = minor;
+ drv->minors = minors;
+ spin_lock_init(&drv->lock);
+ drv->blocked = 0;
+ drv->ops = ops;
+ drv->owner = owner;
+ INIT_LIST_HEAD(&drv->list);
+
+ drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL);
+ if (!drv->cs)
+ goto out1;
+ drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL);
+ if (!drv->flags)
+ goto out2;
+
+ for (i = 0; i < minors; ++i) {
+ drv->flags[i] = 0;
+ drv->cs[i].driver = drv;
+ drv->cs[i].ops = drv->ops;
+ drv->cs[i].minor_index = i;
+ }
+
+ gigaset_if_initdriver(drv, procname, devname, devfsname);
+
+ spin_lock_irqsave(&driver_lock, flags);
+ list_add(&drv->list, &drivers);
+ spin_unlock_irqrestore(&driver_lock, flags);
+
+ return drv;
+
+out2:
+ kfree(drv->cs);
+out1:
+ kfree(drv);
+ module_put(owner);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(gigaset_initdriver);
+
+static struct cardstate *alloc_cs(struct gigaset_driver *drv)
+{
+ unsigned long flags;
+ unsigned i;
+ static struct cardstate *ret = NULL;
+
+ spin_lock_irqsave(&drv->lock, flags);
+ for (i = 0; i < drv->minors; ++i) {
+ if (!(drv->flags[i] & VALID_MINOR)) {
+ drv->flags[i] = VALID_MINOR;
+ ret = drv->cs + i;
+ }
+ if (ret)
+ break;
+ }
+ spin_unlock_irqrestore(&drv->lock, flags);
+ return ret;
+}
+
+static void free_cs(struct cardstate *cs)
+{
+ unsigned long flags;
+ struct gigaset_driver *drv = cs->driver;
+ spin_lock_irqsave(&drv->lock, flags);
+ drv->flags[cs->minor_index] = 0;
+ spin_unlock_irqrestore(&drv->lock, flags);
+}
+
+static void make_valid(struct cardstate *cs, unsigned mask)
+{
+ unsigned long flags;
+ struct gigaset_driver *drv = cs->driver;
+ spin_lock_irqsave(&drv->lock, flags);
+ drv->flags[cs->minor_index] |= mask;
+ spin_unlock_irqrestore(&drv->lock, flags);
+}
+
+static void make_invalid(struct cardstate *cs, unsigned mask)
+{
+ unsigned long flags;
+ struct gigaset_driver *drv = cs->driver;
+ spin_lock_irqsave(&drv->lock, flags);
+ drv->flags[cs->minor_index] &= ~mask;
+ spin_unlock_irqrestore(&drv->lock, flags);
+}
+
+/* For drivers without fixed assignment device<->cardstate (usb) */
+struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv)
+{
+ unsigned long flags;
+ struct cardstate *cs = NULL;
+ unsigned i;
+
+ spin_lock_irqsave(&drv->lock, flags);
+ if (drv->blocked)
+ goto exit;
+ for (i = 0; i < drv->minors; ++i) {
+ if ((drv->flags[i] & VALID_MINOR) &&
+ !(drv->flags[i] & ASSIGNED)) {
+ drv->flags[i] |= ASSIGNED;
+ cs = drv->cs + i;
+ break;
+ }
+ }
+exit:
+ spin_unlock_irqrestore(&drv->lock, flags);
+ return cs;
+}
+EXPORT_SYMBOL_GPL(gigaset_getunassignedcs);
+
+void gigaset_unassign(struct cardstate *cs)
+{
+ unsigned long flags;
+ unsigned *minor_flags;
+ struct gigaset_driver *drv;
+
+ if (!cs)
+ return;
+ drv = cs->driver;
+ spin_lock_irqsave(&drv->lock, flags);
+ minor_flags = drv->flags + cs->minor_index;
+ if (*minor_flags & VALID_MINOR)
+ *minor_flags &= ~ASSIGNED;
+ spin_unlock_irqrestore(&drv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(gigaset_unassign);
+
+void gigaset_blockdriver(struct gigaset_driver *drv)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&drv->lock, flags);
+ drv->blocked = 1;
+ spin_unlock_irqrestore(&drv->lock, flags);
+}
+EXPORT_SYMBOL_GPL(gigaset_blockdriver);
+
+static int __init gigaset_init_module(void)
+{
+ /* in accordance with the principle of least astonishment,
+ * setting the 'debug' parameter to 1 activates a sensible
+ * set of default debug levels
+ */
+ if (gigaset_debuglevel == 1)
+ gigaset_debuglevel = DEBUG_DEFAULT;
+
+ info(DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+ return 0;
+}
+
+static void __exit gigaset_exit_module(void)
+{
+}
+
+module_init(gigaset_init_module);
+module_exit(gigaset_exit_module);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
new file mode 100644
index 00000000000..fdcb80bb21c
--- /dev/null
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -0,0 +1,1983 @@
+/*
+ * Stuff used by all variants of the driver
+ *
+ * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>,
+ * Hansjoerg Lipp <hjlipp@web.de>,
+ * Tilman Schmidt <tilman@imap.cc>.
+ *
+ * =====================================================================
+ * 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.
+ * =====================================================================
+ * ToDo: ...
+ * =====================================================================
+ * Version: $Id: ev-layer.c,v 1.4.2.18 2006/02/04 18:28:16 hjlipp Exp $
+ * =====================================================================
+ */
+
+#include "gigaset.h"
+
+/* ========================================================== */
+/* bit masks for pending commands */
+#define PC_INIT 0x004
+#define PC_DLE0 0x008
+#define PC_DLE1 0x010
+#define PC_CID 0x080
+#define PC_NOCID 0x100
+#define PC_HUP 0x002
+#define PC_DIAL 0x001
+#define PC_ACCEPT 0x040
+#define PC_SHUTDOWN 0x020
+#define PC_CIDMODE 0x200
+#define PC_UMMODE 0x400
+
+/* types of modem responses */
+#define RT_NOTHING 0
+#define RT_ZSAU 1
+#define RT_RING 2
+#define RT_NUMBER 3
+#define RT_STRING 4
+#define RT_HEX 5
+#define RT_ZCAU 6
+
+/* Possible ASCII responses */
+#define RSP_OK 0
+//#define RSP_BUSY 1
+//#define RSP_CONNECT 2
+#define RSP_ZGCI 3
+#define RSP_RING 4
+#define RSP_ZAOC 5
+#define RSP_ZCSTR 6
+#define RSP_ZCFGT 7
+#define RSP_ZCFG 8
+#define RSP_ZCCR 9
+#define RSP_EMPTY 10
+#define RSP_ZLOG 11
+#define RSP_ZCAU 12
+#define RSP_ZMWI 13
+#define RSP_ZABINFO 14
+#define RSP_ZSMLSTCHG 15
+#define RSP_VAR 100
+#define RSP_ZSAU (RSP_VAR + VAR_ZSAU)
+#define RSP_ZDLE (RSP_VAR + VAR_ZDLE)
+#define RSP_ZVLS (RSP_VAR + VAR_ZVLS)
+#define RSP_ZCTP (RSP_VAR + VAR_ZCTP)
+#define RSP_STR (RSP_VAR + VAR_NUM)
+#define RSP_NMBR (RSP_STR + STR_NMBR)
+#define RSP_ZCPN (RSP_STR + STR_ZCPN)
+#define RSP_ZCON (RSP_STR + STR_ZCON)
+#define RSP_ZBC (RSP_STR + STR_ZBC)
+#define RSP_ZHLC (RSP_STR + STR_ZHLC)
+#define RSP_ERROR -1 /* ERROR */
+#define RSP_WRONG_CID -2 /* unknown cid in cmd */
+//#define RSP_EMPTY -3
+#define RSP_UNKNOWN -4 /* unknown response */
+#define RSP_FAIL -5 /* internal error */
+#define RSP_INVAL -6 /* invalid response */
+
+#define RSP_NONE -19
+#define RSP_STRING -20
+#define RSP_NULL -21
+//#define RSP_RETRYFAIL -22
+//#define RSP_RETRY -23
+//#define RSP_SKIP -24
+#define RSP_INIT -27
+#define RSP_ANY -26
+#define RSP_LAST -28
+#define RSP_NODEV -9
+
+/* actions for process_response */
+#define ACT_NOTHING 0
+#define ACT_SETDLE1 1
+#define ACT_SETDLE0 2
+#define ACT_FAILINIT 3
+#define ACT_HUPMODEM 4
+#define ACT_CONFIGMODE 5
+#define ACT_INIT 6
+#define ACT_DLE0 7
+#define ACT_DLE1 8
+#define ACT_FAILDLE0 9
+#define ACT_FAILDLE1 10
+#define ACT_RING 11
+#define ACT_CID 12
+#define ACT_FAILCID 13
+#define ACT_SDOWN 14
+#define ACT_FAILSDOWN 15
+#define ACT_DEBUG 16
+#define ACT_WARN 17
+#define ACT_DIALING 18
+#define ACT_ABORTDIAL 19
+#define ACT_DISCONNECT 20
+#define ACT_CONNECT 21
+#define ACT_REMOTEREJECT 22
+#define ACT_CONNTIMEOUT 23
+#define ACT_REMOTEHUP 24
+#define ACT_ABORTHUP 25
+#define ACT_ICALL 26
+#define ACT_ACCEPTED 27
+#define ACT_ABORTACCEPT 28
+#define ACT_TIMEOUT 29
+#define ACT_GETSTRING 30
+#define ACT_SETVER 31
+#define ACT_FAILVER 32
+#define ACT_GOTVER 33
+#define ACT_TEST 34
+#define ACT_ERROR 35
+#define ACT_ABORTCID 36
+#define ACT_ZCAU 37
+#define ACT_NOTIFY_BC_DOWN 38
+#define ACT_NOTIFY_BC_UP 39
+#define ACT_DIAL 40
+#define ACT_ACCEPT 41
+#define ACT_PROTO_L2 42
+#define ACT_HUP 43
+#define ACT_IF_LOCK 44
+#define ACT_START 45
+#define ACT_STOP 46
+#define ACT_FAKEDLE0 47
+#define ACT_FAKEHUP 48
+#define ACT_FAKESDOWN 49
+#define ACT_SHUTDOWN 50
+#define ACT_PROC_CIDMODE 51
+#define ACT_UMODESET 52
+#define ACT_FAILUMODE 53
+#define ACT_CMODESET 54
+#define ACT_FAILCMODE 55
+#define ACT_IF_VER 56
+#define ACT_CMD 100
+
+/* at command sequences */
+#define SEQ_NONE 0
+#define SEQ_INIT 100
+#define SEQ_DLE0 200
+#define SEQ_DLE1 250
+#define SEQ_CID 300
+#define SEQ_NOCID 350
+#define SEQ_HUP 400
+#define SEQ_DIAL 600
+#define SEQ_ACCEPT 720
+#define SEQ_SHUTDOWN 500
+#define SEQ_CIDMODE 10
+#define SEQ_UMMODE 11
+
+
+// 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring
+struct reply_t gigaset_tab_nocid_m10x[]= /* with dle mode */
+{
+ /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
+
+ /* initialize device, set cid mode if possible */
+ //{RSP_INIT, -1, -1,100, 900, 0, {ACT_TEST}},
+ //{RSP_ERROR, 900,900, -1, 0, 0, {ACT_FAILINIT}},
+ //{RSP_OK, 900,900, -1, 100, INIT_TIMEOUT,
+ // {ACT_TIMEOUT}},
+
+ {RSP_INIT, -1, -1,SEQ_INIT, 100, INIT_TIMEOUT,
+ {ACT_TIMEOUT}}, /* wait until device is ready */
+
+ {EV_TIMEOUT, 100,100, -1, 101, 3, {0}, "Z\r"}, /* device in transparent mode? try to initialize it. */
+ {RSP_OK, 101,103, -1, 120, 5, {ACT_GETSTRING}, "+GMR\r"}, /* get version */
+
+ {EV_TIMEOUT, 101,101, -1, 102, 5, {0}, "Z\r"}, /* timeout => try once again. */
+ {RSP_ERROR, 101,101, -1, 102, 5, {0}, "Z\r"}, /* error => try once again. */
+
+ {EV_TIMEOUT, 102,102, -1, 108, 5, {ACT_SETDLE1}, "^SDLE=0\r"}, /* timeout => try again in DLE mode. */
+ {RSP_OK, 108,108, -1, 104,-1},
+ {RSP_ZDLE, 104,104, 0, 103, 5, {0}, "Z\r"},
+ {EV_TIMEOUT, 104,104, -1, 0, 0, {ACT_FAILINIT}},
+ {RSP_ERROR, 108,108, -1, 0, 0, {ACT_FAILINIT}},
+
+ {EV_TIMEOUT, 108,108, -1, 105, 2, {ACT_SETDLE0,
+ ACT_HUPMODEM,
+ ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */
+ {EV_TIMEOUT, 105,105, -1, 103, 5, {0}, "Z\r"},
+
+ {RSP_ERROR, 102,102, -1, 107, 5, {0}, "^GETPRE\r"}, /* ERROR on ATZ => maybe in config mode? */
+ {RSP_OK, 107,107, -1, 0, 0, {ACT_CONFIGMODE}},
+ {RSP_ERROR, 107,107, -1, 0, 0, {ACT_FAILINIT}},
+ {EV_TIMEOUT, 107,107, -1, 0, 0, {ACT_FAILINIT}},
+
+ {RSP_ERROR, 103,103, -1, 0, 0, {ACT_FAILINIT}},
+ {EV_TIMEOUT, 103,103, -1, 0, 0, {ACT_FAILINIT}},
+
+ {RSP_STRING, 120,120, -1, 121,-1, {ACT_SETVER}},
+
+ {EV_TIMEOUT, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}},
+ {RSP_ERROR, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}},
+ {RSP_OK, 121,121, -1, 0, 0, {ACT_GOTVER, ACT_INIT}},
+#if 0
+ {EV_TIMEOUT, 120,121, -1, 130, 5, {ACT_FAILVER}, "^SGCI=1\r"},
+ {RSP_ERROR, 120,121, -1, 130, 5, {ACT_FAILVER}, "^SGCI=1\r"},
+ {RSP_OK, 121,121, -1, 130, 5, {ACT_GOTVER}, "^SGCI=1\r"},
+
+ {RSP_OK, 130,130, -1, 0, 0, {ACT_INIT}},
+ {RSP_ERROR, 130,130, -1, 0, 0, {ACT_FAILINIT}},
+ {EV_TIMEOUT, 130,130, -1, 0, 0, {ACT_FAILINIT}},
+#endif
+
+ /* leave dle mode */
+ {RSP_INIT, 0, 0,SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"},
+ {RSP_OK, 201,201, -1, 202,-1},
+ //{RSP_ZDLE, 202,202, 0, 202, 0, {ACT_ERROR}},//DELETE
+ {RSP_ZDLE, 202,202, 0, 0, 0, {ACT_DLE0}},
+ {RSP_NODEV, 200,249, -1, 0, 0, {ACT_FAKEDLE0}},
+ {RSP_ERROR, 200,249, -1, 0, 0, {ACT_FAILDLE0}},
+ {EV_TIMEOUT, 200,249, -1, 0, 0, {ACT_FAILDLE0}},
+
+ /* enter dle mode */
+ {RSP_INIT, 0, 0,SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"},
+ {RSP_OK, 251,251, -1, 252,-1},
+ {RSP_ZDLE, 252,252, 1, 0, 0, {ACT_DLE1}},
+ {RSP_ERROR, 250,299, -1, 0, 0, {ACT_FAILDLE1}},
+ {EV_TIMEOUT, 250,299, -1, 0, 0, {ACT_FAILDLE1}},
+
+ /* incoming call */
+ {RSP_RING, -1, -1, -1, -1,-1, {ACT_RING}},
+
+ /* get cid */
+ //{RSP_INIT, 0, 0,300, 901, 0, {ACT_TEST}},
+ //{RSP_ERROR, 901,901, -1, 0, 0, {ACT_FAILCID}},
+ //{RSP_OK, 901,901, -1, 301, 5, {0}, "^SGCI?\r"},
+
+ {RSP_INIT, 0, 0,SEQ_CID, 301, 5, {0}, "^SGCI?\r"},
+ {RSP_OK, 301,301, -1, 302,-1},
+ {RSP_ZGCI, 302,302, -1, 0, 0, {ACT_CID}},
+ {RSP_ERROR, 301,349, -1, 0, 0, {ACT_FAILCID}},
+ {EV_TIMEOUT, 301,349, -1, 0, 0, {ACT_FAILCID}},
+
+ /* enter cid mode */
+ {RSP_INIT, 0, 0,SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"},
+ {RSP_OK, 150,150, -1, 0, 0, {ACT_CMODESET}},
+ {RSP_ERROR, 150,150, -1, 0, 0, {ACT_FAILCMODE}},
+ {EV_TIMEOUT, 150,150, -1, 0, 0, {ACT_FAILCMODE}},
+
+ /* leave cid mode */
+ //{RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "^SGCI=0\r"},
+ {RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "Z\r"},
+ {RSP_OK, 160,160, -1, 0, 0, {ACT_UMODESET}},
+ {RSP_ERROR, 160,160, -1, 0, 0, {ACT_FAILUMODE}},
+ {EV_TIMEOUT, 160,160, -1, 0, 0, {ACT_FAILUMODE}},
+
+ /* abort getting cid */
+ {RSP_INIT, 0, 0,SEQ_NOCID, 0, 0, {ACT_ABORTCID}},
+
+ /* reset */
+#if 0
+ {RSP_INIT, 0, 0,SEQ_SHUTDOWN, 503, 5, {0}, "^SGCI=0\r"},
+ {RSP_OK, 503,503, -1, 504, 5, {0}, "Z\r"},
+#endif
+ {RSP_INIT, 0, 0,SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"},
+ {RSP_OK, 504,504, -1, 0, 0, {ACT_SDOWN}},
+ {RSP_ERROR, 501,599, -1, 0, 0, {ACT_FAILSDOWN}},
+ {EV_TIMEOUT, 501,599, -1, 0, 0, {ACT_FAILSDOWN}},
+ {RSP_NODEV, 501,599, -1, 0, 0, {ACT_FAKESDOWN}},
+
+ {EV_PROC_CIDMODE,-1, -1, -1, -1,-1, {ACT_PROC_CIDMODE}}, //FIXME
+ {EV_IF_LOCK, -1, -1, -1, -1,-1, {ACT_IF_LOCK}}, //FIXME
+ {EV_IF_VER, -1, -1, -1, -1,-1, {ACT_IF_VER}}, //FIXME
+ {EV_START, -1, -1, -1, -1,-1, {ACT_START}}, //FIXME
+ {EV_STOP, -1, -1, -1, -1,-1, {ACT_STOP}}, //FIXME
+ {EV_SHUTDOWN, -1, -1, -1, -1,-1, {ACT_SHUTDOWN}}, //FIXME
+
+ /* misc. */
+ {RSP_EMPTY, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
+ {RSP_ZCFGT, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
+ {RSP_ZCFG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
+ {RSP_ZLOG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
+ {RSP_ZMWI, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
+ {RSP_ZABINFO, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
+ {RSP_ZSMLSTCHG,-1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
+
+ {RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}},
+ {RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}},
+ {RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}},
+ {RSP_LAST}
+};
+
+// 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, 400: hup, 750: accepted icall
+struct reply_t gigaset_tab_cid_m10x[] = /* for M10x */
+{
+ /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
+
+ /* dial */
+ {EV_DIAL, -1, -1, -1, -1,-1, {ACT_DIAL}}, //FIXME
+ {RSP_INIT, 0, 0,SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC}},
+ {RSP_OK, 601,601, -1, 602, 5, {ACT_CMD+AT_HLC}},
+ {RSP_NULL, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}},
+ {RSP_OK, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}},
+ {RSP_OK, 603,603, -1, 604, 5, {ACT_CMD+AT_TYPE}},
+ {RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}},
+ {RSP_OK, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}},
+ {RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}},
+ {RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */
+ {RSP_OK, 607,607, -1, 608,-1},
+ //{RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 608, 0, {ACT_ERROR}},//DELETE
+ {RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}},
+ {RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}},
+
+ {RSP_ZVLS, 608,608, 17, -1,-1, {ACT_DEBUG}},
+ {RSP_ZCTP, 609,609, -1, -1,-1, {ACT_DEBUG}},
+ {RSP_ZCPN, 609,609, -1, -1,-1, {ACT_DEBUG}},
+ {RSP_ERROR, 601,609, -1, 0, 0, {ACT_ABORTDIAL}},
+ {EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}},
+
+ /* dialing */
+ {RSP_ZCTP, 650,650, -1, -1,-1, {ACT_DEBUG}},
+ {RSP_ZCPN, 650,650, -1, -1,-1, {ACT_DEBUG}},
+ {RSP_ZSAU, 650,650,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, /* some devices don't send this */
+
+ /* connection established */
+ {RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, //FIXME -> DLE1
+ {RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, //FIXME -> DLE1
+
+ {EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}}, //FIXME new constate + timeout
+
+ /* remote hangup */
+ {RSP_ZSAU, 650,650,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}},
+ {RSP_ZSAU, 750,750,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}},
+ {RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}},
+
+ /* hangup */
+ {EV_HUP, -1, -1, -1, -1,-1, {ACT_HUP}}, //FIXME
+ {RSP_INIT, -1, -1,SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, /* hang up */ //-1,-1?
+ {RSP_OK, 401,401, -1, 402, 5},
+ {RSP_ZVLS, 402,402, 0, 403, 5},
+ {RSP_ZSAU, 403,403,ZSAU_DISCONNECT_REQ, -1,-1, {ACT_DEBUG}}, /* if not remote hup */
+ //{RSP_ZSAU, 403,403,ZSAU_NULL, 401, 0, {ACT_ERROR}}, //DELETE//FIXME -> DLE0 // should we do this _before_ hanging up for base driver?
+ {RSP_ZSAU, 403,403,ZSAU_NULL, 0, 0, {ACT_DISCONNECT}}, //FIXME -> DLE0 // should we do this _before_ hanging up for base driver?
+ {RSP_NODEV, 401,403, -1, 0, 0, {ACT_FAKEHUP}}, //FIXME -> DLE0 // should we do this _before_ hanging up for base driver?
+ {RSP_ERROR, 401,401, -1, 0, 0, {ACT_ABORTHUP}},
+ {EV_TIMEOUT, 401,403, -1, 0, 0, {ACT_ABORTHUP}},
+
+ {EV_BC_CLOSED, 0, 0, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME new constate + timeout
+
+ /* ring */
+ {RSP_ZBC, 700,700, -1, -1,-1, {0}},
+ {RSP_ZHLC, 700,700, -1, -1,-1, {0}},
+ {RSP_NMBR, 700,700, -1, -1,-1, {0}},
+ {RSP_ZCPN, 700,700, -1, -1,-1, {0}},
+ {RSP_ZCTP, 700,700, -1, -1,-1, {0}},
+ {EV_TIMEOUT, 700,700, -1, 720,720, {ACT_ICALL}},
+ {EV_BC_CLOSED,720,720, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}},
+
+ /*accept icall*/
+ {EV_ACCEPT, -1, -1, -1, -1,-1, {ACT_ACCEPT}}, //FIXME
+ {RSP_INIT, 720,720,SEQ_ACCEPT, 721, 5, {ACT_CMD+AT_PROTO}},
+ {RSP_OK, 721,721, -1, 722, 5, {ACT_CMD+AT_ISO}},
+ {RSP_OK, 722,722, -1, 723, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */
+ {RSP_OK, 723,723, -1, 724, 5, {0}},
+ {RSP_ZVLS, 724,724, 17, 750,50, {ACT_ACCEPTED}},
+ {RSP_ERROR, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}},
+ {EV_TIMEOUT, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}},
+ {RSP_ZSAU, 700,729,ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT}},
+ {RSP_ZSAU, 700,729,ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT}},
+ {RSP_ZSAU, 700,729,ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT}},
+
+ {EV_TIMEOUT, 750,750, -1, 0, 0, {ACT_CONNTIMEOUT}},
+
+ /* misc. */
+ {EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME
+
+ {RSP_ZCON, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
+ {RSP_ZCCR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
+ {RSP_ZAOC, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
+ {RSP_ZCSTR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
+
+ {RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}},
+ {RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}},
+ {RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}},
+ {RSP_LAST}
+};
+
+
+#if 0
+static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME aenderungen uebernehmen
+{
+ /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
+
+ {RSP_ANY, -1, -1, -1, -1,-1, ACT_WARN, NULL},
+ {RSP_LAST,0,0,0,0,0,0}
+};
+
+static struct reply_t tab_cid[] = /* no dle mode */ //FIXME aenderungen uebernehmen
+{
+ /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
+
+ {RSP_ANY, -1, -1, -1, -1,-1, ACT_WARN, NULL},
+ {RSP_LAST,0,0,0,0,0,0}
+};
+#endif
+
+static struct resp_type_t resp_type[]=
+{
+ /*{"", RSP_EMPTY, RT_NOTHING},*/
+ {"OK", RSP_OK, RT_NOTHING},
+ {"ERROR", RSP_ERROR, RT_NOTHING},
+ {"ZSAU", RSP_ZSAU, RT_ZSAU},
+ {"ZCAU", RSP_ZCAU, RT_ZCAU},
+ {"RING", RSP_RING, RT_RING},
+ {"ZGCI", RSP_ZGCI, RT_NUMBER},
+ {"ZVLS", RSP_ZVLS, RT_NUMBER},
+ {"ZCTP", RSP_ZCTP, RT_NUMBER},
+ {"ZDLE", RSP_ZDLE, RT_NUMBER},
+ {"ZCFGT", RSP_ZCFGT, RT_NUMBER},
+ {"ZCCR", RSP_ZCCR, RT_NUMBER},
+ {"ZMWI", RSP_ZMWI, RT_NUMBER},
+ {"ZHLC", RSP_ZHLC, RT_STRING},
+ {"ZBC", RSP_ZBC, RT_STRING},
+ {"NMBR", RSP_NMBR, RT_STRING},
+ {"ZCPN", RSP_ZCPN, RT_STRING},
+ {"ZCON", RSP_ZCON, RT_STRING},
+ {"ZAOC", RSP_ZAOC, RT_STRING},
+ {"ZCSTR", RSP_ZCSTR, RT_STRING},
+ {"ZCFG", RSP_ZCFG, RT_HEX},
+ {"ZLOG", RSP_ZLOG, RT_NOTHING},
+ {"ZABINFO", RSP_ZABINFO, RT_NOTHING},
+ {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING},
+ {NULL,0,0}
+};
+
+/*
+ * Get integer from char-pointer
+ */
+static int isdn_getnum(char *p)
+{
+ int v = -1;
+
+ IFNULLRETVAL(p, -1);
+
+ dbg(DEBUG_TRANSCMD, "string: %s", p);
+
+ while (*p >= '0' && *p <= '9')
+ v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p++) - '0');
+ if (*p)
+ v = -1; /* invalid Character */
+ return v;
+}
+
+/*
+ * Get integer from char-pointer
+ */
+static int isdn_gethex(char *p)
+{
+ int v = 0;
+ int c;
+
+ IFNULLRETVAL(p, -1);
+
+ dbg(DEBUG_TRANSCMD, "string: %s", p);
+
+ if (!*p)
+ return -1;
+
+ do {
+ if (v > (INT_MAX - 15) / 16)
+ return -1;
+ c = *p;
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'f')
+ c -= 'a' - 10;
+ else if (c >= 'A' && c <= 'F')
+ c -= 'A' - 10;
+ else
+ return -1;
+ v = v * 16 + c;
+ } while (*++p);
+
+ return v;
+}
+
+static inline void new_index(atomic_t *index, int max)
+{
+ if (atomic_read(index) == max) //FIXME race?
+ atomic_set(index, 0);
+ else
+ atomic_inc(index);
+}
+
+/* retrieve CID from parsed response
+ * returns 0 if no CID, -1 if invalid CID, or CID value 1..65535
+ */
+static int cid_of_response(char *s)
+{
+ int cid;
+
+ if (s[-1] != ';')
+ return 0; /* no CID separator */
+ cid = isdn_getnum(s);
+ if (cid < 0)
+ return 0; /* CID not numeric */
+ if (cid < 1 || cid > 65535)
+ return -1; /* CID out of range */
+ return cid;
+ //FIXME is ;<digit>+ at end of non-CID response really impossible?
+}
+
+/* This function will be called via task queue from the callback handler.
+ * We received a modem response and have to handle it..
+ */
+void gigaset_handle_modem_response(struct cardstate *cs)
+{
+ unsigned char *argv[MAX_REC_PARAMS + 1];
+ int params;
+ int i, j;
+ struct resp_type_t *rt;
+ int curarg;
+ unsigned long flags;
+ unsigned next, tail, head;
+ struct event_t *event;
+ int resp_code;
+ int param_type;
+ int abort;
+ size_t len;
+ int cid;
+ int rawstring;
+
+ IFNULLRET(cs);
+
+ len = cs->cbytes;
+ if (!len) {
+ /* ignore additional LFs/CRs (M10x config mode or cx100) */
+ dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]);
+ return;
+ }
+ cs->respdata[len] = 0;
+ dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata);
+ argv[0] = cs->respdata;
+ params = 1;
+ if (cs->at_state.getstring) {
+ /* getstring only allowed without cid at the moment */
+ cs->at_state.getstring = 0;
+ rawstring = 1;
+ cid = 0;
+ } else {
+ /* parse line */
+ for (i = 0; i < len; i++)
+ switch (cs->respdata[i]) {
+ case ';':
+ case ',':
+ case '=':
+ if (params > MAX_REC_PARAMS) {
+ warn("too many parameters in response");
+ /* need last parameter (might be CID) */
+ params--;
+ }
+ argv[params++] = cs->respdata + i + 1;
+ }
+
+ rawstring = 0;
+ cid = params > 1 ? cid_of_response(argv[params-1]) : 0;
+ if (cid < 0) {
+ gigaset_add_event(cs, &cs->at_state, RSP_INVAL,
+ NULL, 0, NULL);
+ return;
+ }
+
+ for (j = 1; j < params; ++j)
+ argv[j][-1] = 0;
+
+ dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]);
+ if (cid) {
+ --params;
+ dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]);
+ }
+ dbg(DEBUG_TRANSCMD, "available params: %d", params - 1);
+ for (j = 1; j < params; j++)
+ dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]);
+ }
+
+ spin_lock_irqsave(&cs->ev_lock, flags);
+ head = atomic_read(&cs->ev_head);
+ tail = atomic_read(&cs->ev_tail);
+
+ abort = 1;
+ curarg = 0;
+ while (curarg < params) {
+ next = (tail + 1) % MAX_EVENTS;
+ if (unlikely(next == head)) {
+ err("event queue full");
+ break;
+ }
+
+ event = cs->events + tail;
+ event->at_state = NULL;
+ event->cid = cid;
+ event->ptr = NULL;
+ event->arg = NULL;
+ tail = next;
+
+ if (rawstring) {
+ resp_code = RSP_STRING;
+ param_type = RT_STRING;
+ } else {
+ for (rt = resp_type; rt->response; ++rt)
+ if (!strcmp(argv[curarg], rt->response))
+ break;
+
+ if (!rt->response) {
+ event->type = RSP_UNKNOWN;
+ warn("unknown modem response: %s",
+ argv[curarg]);
+ break;
+ }
+
+ resp_code = rt->resp_code;
+ param_type = rt->type;
+ ++curarg;
+ }
+
+ event->type = resp_code;
+
+ switch (param_type) {
+ case RT_NOTHING:
+ break;
+ case RT_RING:
+ if (!cid) {
+ err("received RING without CID!");
+ event->type = RSP_INVAL;
+ abort = 1;
+ } else {
+ event->cid = 0;
+ event->parameter = cid;
+ abort = 0;
+ }
+ break;
+ case RT_ZSAU:
+ if (curarg >= params) {
+ event->parameter = ZSAU_NONE;
+ break;
+ }
+ if (!strcmp(argv[curarg], "OUTGOING_CALL_PROCEEDING"))
+ event->parameter = ZSAU_OUTGOING_CALL_PROCEEDING;
+ else if (!strcmp(argv[curarg], "CALL_DELIVERED"))
+ event->parameter = ZSAU_CALL_DELIVERED;
+ else if (!strcmp(argv[curarg], "ACTIVE"))
+ event->parameter = ZSAU_ACTIVE;
+ else if (!strcmp(argv[curarg], "DISCONNECT_IND"))
+ event->parameter = ZSAU_DISCONNECT_IND;
+ else if (!strcmp(argv[curarg], "NULL"))
+ event->parameter = ZSAU_NULL;
+ else if (!strcmp(argv[curarg], "DISCONNECT_REQ"))
+ event->parameter = ZSAU_DISCONNECT_REQ;
+ else {
+ event->parameter = ZSAU_UNKNOWN;
+ warn("%s: unknown parameter %s after ZSAU",
+ __func__, argv[curarg]);
+ }
+ ++curarg;
+ break;
+ case RT_STRING:
+ if (curarg < params) {
+ len = strlen(argv[curarg]) + 1;
+ event->ptr = kmalloc(len, GFP_ATOMIC);
+ if (event->ptr)
+ memcpy(event->ptr, argv[curarg], len);
+ else
+ err("no memory for string!");
+ ++curarg;
+ }
+#ifdef CONFIG_GIGASET_DEBUG
+ if (!event->ptr)
+ dbg(DEBUG_CMD, "string==NULL");
+ else
+ dbg(DEBUG_CMD,
+ "string==%s", (char *) event->ptr);
+#endif
+ break;
+ case RT_ZCAU:
+ event->parameter = -1;
+ if (curarg + 1 < params) {
+ i = isdn_gethex(argv[curarg]);
+ j = isdn_gethex(argv[curarg + 1]);
+ if (i >= 0 && i < 256 && j >= 0 && j < 256)
+ event->parameter = (unsigned) i << 8
+ | j;
+ curarg += 2;
+ } else
+ curarg = params - 1;
+ break;
+ case RT_NUMBER:
+ case RT_HEX:
+ if (curarg < params) {
+ if (param_type == RT_HEX)
+ event->parameter =
+ isdn_gethex(argv[curarg]);
+ else
+ event->parameter =
+ isdn_getnum(argv[curarg]);
+ ++curarg;
+ } else
+ event->parameter = -1;
+#ifdef CONFIG_GIGASET_DEBUG
+ dbg(DEBUG_CMD, "parameter==%d", event->parameter);
+#endif
+ break;
+ }
+
+ if (resp_code == RSP_ZDLE)
+ cs->dle = event->parameter;
+
+ if (abort)
+ break;
+ }
+
+ atomic_set(&cs->ev_tail, tail);
+ spin_unlock_irqrestore(&cs->ev_lock, flags);
+
+ if (curarg != params)
+ dbg(DEBUG_ANY, "invalid number of processed parameters: %d/%d",
+ curarg, params);
+}
+EXPORT_SYMBOL_GPL(gigaset_handle_modem_response);
+
+/* disconnect
+ * process closing of connection associated with given AT state structure
+ */
+static void disconnect(struct at_state_t **at_state_p)
+{
+ unsigned long flags;
+ struct bc_state *bcs;
+ struct cardstate *cs;
+
+ IFNULLRET(at_state_p);
+ IFNULLRET(*at_state_p);
+ bcs = (*at_state_p)->bcs;
+ cs = (*at_state_p)->cs;
+ IFNULLRET(cs);
+
+ new_index(&(*at_state_p)->seq_index, MAX_SEQ_INDEX);
+
+ /* revert to selected idle mode */
+ if (!atomic_read(&cs->cidmode)) {
+ cs->at_state.pending_commands |= PC_UMMODE;
+ atomic_set(&cs->commands_pending, 1); //FIXME
+ dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
+ }
+
+ if (bcs) {
+ /* B channel assigned: invoke hardware specific handler */
+ cs->ops->close_bchannel(bcs);
+ } else {
+ /* no B channel assigned: just deallocate */
+ spin_lock_irqsave(&cs->lock, flags);
+ list_del(&(*at_state_p)->list);
+ kfree(*at_state_p);
+ *at_state_p = NULL;
+ spin_unlock_irqrestore(&cs->lock, flags);
+ }
+}
+
+/* get_free_channel
+ * get a free AT state structure: either one of those associated with the
+ * B channels of the Gigaset device, or if none of those is available,
+ * a newly allocated one with bcs=NULL
+ * The structure should be freed by calling disconnect() after use.
+ */
+static inline struct at_state_t *get_free_channel(struct cardstate *cs,
+ int cid)
+/* cids: >0: siemens-cid
+ 0: without cid
+ -1: no cid assigned yet
+*/
+{
+ unsigned long flags;
+ int i;
+ struct at_state_t *ret;
+
+ for (i = 0; i < cs->channels; ++i)
+ if (gigaset_get_channel(cs->bcs + i)) {
+ ret = &cs->bcs[i].at_state;
+ ret->cid = cid;
+ return ret;
+ }
+
+ spin_lock_irqsave(&cs->lock, flags);
+ ret = kmalloc(sizeof(struct at_state_t), GFP_ATOMIC);
+ if (ret) {
+ gigaset_at_init(ret, NULL, cs, cid);
+ list_add(&ret->list, &cs->temp_at_states);
+ }
+ spin_unlock_irqrestore(&cs->lock, flags);
+ return ret;
+}
+
+static void init_failed(struct cardstate *cs, int mode)
+{
+ int i;
+ struct at_state_t *at_state;
+
+ cs->at_state.pending_commands &= ~PC_INIT;
+ atomic_set(&cs->mode, mode);
+ atomic_set(&cs->mstate, MS_UNINITIALIZED);
+ gigaset_free_channels(cs);
+ for (i = 0; i < cs->channels; ++i) {
+ at_state = &cs->bcs[i].at_state;
+ if (at_state->pending_commands & PC_CID) {
+ at_state->pending_commands &= ~PC_CID;
+ at_state->pending_commands |= PC_NOCID;
+ atomic_set(&cs->commands_pending, 1);
+ }
+ }
+}
+
+static void schedule_init(struct cardstate *cs, int state)
+{
+ if (cs->at_state.pending_commands & PC_INIT) {
+ dbg(DEBUG_CMD, "not scheduling PC_INIT again");
+ return;
+ }
+ atomic_set(&cs->mstate, state);
+ atomic_set(&cs->mode, M_UNKNOWN);
+ gigaset_block_channels(cs);
+ cs->at_state.pending_commands |= PC_INIT;
+ atomic_set(&cs->commands_pending, 1);
+ dbg(DEBUG_CMD, "Scheduling PC_INIT");
+}
+
+/* Add "AT" to a command, add the cid, dle encode it, send the result to the hardware. */
+static void send_command(struct cardstate *cs, const char *cmd, int cid,
+ int dle, gfp_t kmallocflags)
+{
+ size_t cmdlen, buflen;
+ char *cmdpos, *cmdbuf, *cmdtail;
+
+ cmdlen = strlen(cmd);
+ buflen = 11 + cmdlen;
+
+ if (likely(buflen > cmdlen)) {
+ cmdbuf = kmalloc(buflen, kmallocflags);
+ if (likely(cmdbuf != NULL)) {
+ cmdpos = cmdbuf + 9;
+ cmdtail = cmdpos + cmdlen;
+ memcpy(cmdpos, cmd, cmdlen);
+
+ if (cid > 0 && cid <= 65535) {
+ do {
+ *--cmdpos = '0' + cid % 10;
+ cid /= 10;
+ ++cmdlen;
+ } while (cid);
+ }
+
+ cmdlen += 2;
+ *--cmdpos = 'T';
+ *--cmdpos = 'A';
+
+ if (dle) {
+ cmdlen += 4;
+ *--cmdpos = '(';
+ *--cmdpos = 0x10;
+ *cmdtail++ = 0x10;
+ *cmdtail++ = ')';
+ }
+
+ cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL);
+ kfree(cmdbuf);
+ } else
+ err("no memory for command buffer");
+ } else
+ err("overflow in buflen");
+}
+
+static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid)
+{
+ struct at_state_t *at_state;
+ int i;
+ unsigned long flags;
+
+ if (cid == 0)
+ return &cs->at_state;
+
+ for (i = 0; i < cs->channels; ++i)
+ if (cid == cs->bcs[i].at_state.cid)
+ return &cs->bcs[i].at_state;
+
+ spin_lock_irqsave(&cs->lock, flags);
+
+ list_for_each_entry(at_state, &cs->temp_at_states, list)
+ if (cid == at_state->cid) {
+ spin_unlock_irqrestore(&cs->lock, flags);
+ return at_state;
+ }
+
+ spin_unlock_irqrestore(&cs->lock, flags);
+
+ return NULL;
+}
+
+static void bchannel_down(struct bc_state *bcs)
+{
+ IFNULLRET(bcs);
+ IFNULLRET(bcs->cs);
+
+ if (bcs->chstate & CHS_B_UP) {
+ bcs->chstate &= ~CHS_B_UP;
+ gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP);
+ }
+
+ if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) {
+ bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL);
+ gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP);
+ }
+
+ gigaset_free_channel(bcs);
+
+ gigaset_bcs_reinit(bcs);
+}
+
+static void bchannel_up(struct bc_state *bcs)
+{
+ IFNULLRET(bcs);
+
+ if (!(bcs->chstate & CHS_D_UP)) {
+ notice("%s: D channel not up", __func__);
+ bcs->chstate |= CHS_D_UP;
+ gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
+ }
+
+ if (bcs->chstate & CHS_B_UP) {
+ notice("%s: B channel already up", __func__);
+ return;
+ }
+
+ bcs->chstate |= CHS_B_UP;
+ gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN);
+}
+
+static void start_dial(struct at_state_t *at_state, void *data, int seq_index)
+{
+ struct bc_state *bcs = at_state->bcs;
+ struct cardstate *cs = at_state->cs;
+ int retval;
+
+ bcs->chstate |= CHS_NOTIFY_LL;
+ //atomic_set(&bcs->status, BCS_INIT);
+
+ if (atomic_read(&at_state->seq_index) != seq_index)
+ goto error;
+
+ retval = gigaset_isdn_setup_dial(at_state, data);
+ if (retval != 0)
+ goto error;
+
+
+ at_state->pending_commands |= PC_CID;
+ dbg(DEBUG_CMD, "Scheduling PC_CID");
+//#ifdef GIG_MAYINITONDIAL
+// if (atomic_read(&cs->MState) == MS_UNKNOWN) {
+// cs->at_state.pending_commands |= PC_INIT;
+// dbg(DEBUG_CMD, "Scheduling PC_INIT");
+// }
+//#endif
+ atomic_set(&cs->commands_pending, 1); //FIXME
+ return;
+
+error:
+ at_state->pending_commands |= PC_NOCID;
+ dbg(DEBUG_CMD, "Scheduling PC_NOCID");
+ atomic_set(&cs->commands_pending, 1); //FIXME
+ return;
+}
+
+static void start_accept(struct at_state_t *at_state)
+{
+ struct cardstate *cs = at_state->cs;
+ int retval;
+
+ retval = gigaset_isdn_setup_accept(at_state);
+
+ if (retval == 0) {
+ at_state->pending_commands |= PC_ACCEPT;
+ dbg(DEBUG_CMD, "Scheduling PC_ACCEPT");
+ atomic_set(&cs->commands_pending, 1); //FIXME
+ } else {
+ //FIXME
+ at_state->pending_commands |= PC_HUP;
+ dbg(DEBUG_CMD, "Scheduling PC_HUP");
+ atomic_set(&cs->commands_pending, 1); //FIXME
+ }
+}
+
+static void do_start(struct cardstate *cs)
+{
+ gigaset_free_channels(cs);
+
+ if (atomic_read(&cs->mstate) != MS_LOCKED)
+ schedule_init(cs, MS_INIT);
+
+ gigaset_i4l_cmd(cs, ISDN_STAT_RUN);
+ // FIXME: not in locked mode
+ // FIXME 2: only after init sequence
+
+ cs->waiting = 0;
+ wake_up(&cs->waitqueue);
+}
+
+static void finish_shutdown(struct cardstate *cs)
+{
+ if (atomic_read(&cs->mstate) != MS_LOCKED) {
+ atomic_set(&cs->mstate, MS_UNINITIALIZED);
+ atomic_set(&cs->mode, M_UNKNOWN);
+ }
+
+ /* The rest is done by cleanup_cs () in user mode. */
+
+ cs->cmd_result = -ENODEV;
+ cs->waiting = 0;
+ wake_up_interruptible(&cs->waitqueue);
+}
+
+static void do_shutdown(struct cardstate *cs)
+{
+ gigaset_block_channels(cs);
+
+ if (atomic_read(&cs->mstate) == MS_READY) {
+ atomic_set(&cs->mstate, MS_SHUTDOWN);
+ cs->at_state.pending_commands |= PC_SHUTDOWN;
+ atomic_set(&cs->commands_pending, 1); //FIXME
+ dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); //FIXME
+ //gigaset_schedule_event(cs); //FIXME
+ } else
+ finish_shutdown(cs);
+}
+
+static void do_stop(struct cardstate *cs)
+{
+ do_shutdown(cs);
+}
+
+/* Entering cid mode or getting a cid failed:
+ * try to initialize the device and try again.
+ *
+ * channel >= 0: getting cid for the channel failed
+ * channel < 0: entering cid mode failed
+ *
+ * returns 0 on failure
+ */
+static int reinit_and_retry(struct cardstate *cs, int channel)
+{
+ int i;
+
+ if (--cs->retry_count <= 0)
+ return 0;
+
+ for (i = 0; i < cs->channels; ++i)
+ if (cs->bcs[i].at_state.cid > 0)
+ return 0;
+
+ if (channel < 0)
+ warn("Could not enter cid mode. Reinit device and try again.");
+ else {
+ warn("Could not get a call id. Reinit device and try again.");
+ cs->bcs[channel].at_state.pending_commands |= PC_CID;
+ }
+ schedule_init(cs, MS_INIT);
+ return 1;
+}
+
+static int at_state_invalid(struct cardstate *cs,
+ struct at_state_t *test_ptr)
+{
+ unsigned long flags;
+ unsigned channel;
+ struct at_state_t *at_state;
+ int retval = 0;
+
+ spin_lock_irqsave(&cs->lock, flags);
+
+ if (test_ptr == &cs->at_state)
+ goto exit;
+
+ list_for_each_entry(at_state, &cs->temp_at_states, list)
+ if (at_state == test_ptr)
+ goto exit;
+
+ for (channel = 0; channel < cs->channels; ++channel)
+ if (&cs->bcs[channel].at_state == test_ptr)
+ goto exit;
+
+ retval = 1;
+exit:
+ spin_unlock_irqrestore(&cs->lock, flags);
+ return retval;
+}
+
+static void handle_icall(struct cardstate *cs, struct bc_state *bcs,
+ struct at_state_t **p_at_state)
+{
+ int retval;
+ struct at_state_t *at_state = *p_at_state;
+
+ retval = gigaset_isdn_icall(at_state);
+ switch (retval) {
+ case ICALL_ACCEPT:
+ break;
+ default:
+ err("internal error: disposition=%d", retval);
+ /* --v-- fall through --v-- */
+ case ICALL_IGNORE:
+ case ICALL_REJECT:
+ /* hang up actively
+ * Device doc says that would reject the call.
+ * In fact it doesn't.
+ */
+ at_state->pending_commands |= PC_HUP;
+ atomic_set(&cs->commands_pending, 1);
+ break;
+ }
+}
+
+static int do_lock(struct cardstate *cs)
+{
+ int mode;
+ int i;
+
+ switch (atomic_read(&cs->mstate)) {
+ case MS_UNINITIALIZED:
+ case MS_READY:
+ if (cs->cur_at_seq || !list_empty(&cs->temp_at_states) ||
+ cs->at_state.pending_commands)
+ return -EBUSY;
+
+ for (i = 0; i < cs->channels; ++i)
+ if (cs->bcs[i].at_state.pending_commands)
+ return -EBUSY;
+
+ if (!gigaset_get_channels(cs))
+ return -EBUSY;
+
+ break;
+ case MS_LOCKED:
+ //retval = -EACCES;
+ break;
+ default:
+ return -EBUSY;
+ }
+
+ mode = atomic_read(&cs->mode);
+ atomic_set(&cs->mstate, MS_LOCKED);
+ atomic_set(&cs->mode, M_UNKNOWN);
+ //FIXME reset card state / at states / bcs states
+
+ return mode;
+}
+
+static int do_unlock(struct cardstate *cs)
+{
+ if (atomic_read(&cs->mstate) != MS_LOCKED)
+ return -EINVAL;
+
+ atomic_set(&cs->mstate, MS_UNINITIALIZED);
+ atomic_set(&cs->mode, M_UNKNOWN);
+ gigaset_free_channels(cs);
+ //FIXME reset card state / at states / bcs states
+ if (atomic_read(&cs->connected))
+ schedule_init(cs, MS_INIT);
+
+ return 0;
+}
+
+static void do_action(int action, struct cardstate *cs,
+ struct bc_state *bcs,
+ struct at_state_t **p_at_state, char **pp_command,
+ int *p_genresp, int *p_resp_code,
+ struct event_t *ev)
+{
+ struct at_state_t *at_state = *p_at_state;
+ struct at_state_t *at_state2;
+ unsigned long flags;
+
+ int channel;
+
+ unsigned char *s, *e;
+ int i;
+ unsigned long val;
+
+ switch (action) {
+ case ACT_NOTHING:
+ break;
+ case ACT_TIMEOUT:
+ at_state->waiting = 1;
+ break;
+ case ACT_INIT:
+ //FIXME setup everything
+ cs->at_state.pending_commands &= ~PC_INIT;
+ cs->cur_at_seq = SEQ_NONE;
+ atomic_set(&cs->mode, M_UNIMODEM);
+ if (!atomic_read(&cs->cidmode)) {
+ gigaset_free_channels(cs);
+ atomic_set(&cs->mstate, MS_READY);
+ break;
+ }
+ cs->at_state.pending_commands |= PC_CIDMODE;
+ atomic_set(&cs->commands_pending, 1); //FIXME
+ dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
+ break;
+ case ACT_FAILINIT:
+ warn("Could not initialize the device.");
+ cs->dle = 0;
+ init_failed(cs, M_UNKNOWN);
+ cs->cur_at_seq = SEQ_NONE;
+ break;
+ case ACT_CONFIGMODE:
+ init_failed(cs, M_CONFIG);
+ cs->cur_at_seq = SEQ_NONE;
+ break;
+ case ACT_SETDLE1:
+ cs->dle = 1;
+ /* cs->inbuf[0].inputstate |= INS_command | INS_DLE_command; */
+ cs->inbuf[0].inputstate &=
+ ~(INS_command | INS_DLE_command);
+ break;
+ case ACT_SETDLE0:
+ cs->dle = 0;
+ cs->inbuf[0].inputstate =
+ (cs->inbuf[0].inputstate & ~INS_DLE_command)
+ | INS_command;
+ break;
+ case ACT_CMODESET:
+ if (atomic_read(&cs->mstate) == MS_INIT ||
+ atomic_read(&cs->mstate) == MS_RECOVER) {
+ gigaset_free_channels(cs);
+ atomic_set(&cs->mstate, MS_READY);
+ }
+ atomic_set(&cs->mode, M_CID);
+ cs->cur_at_seq = SEQ_NONE;
+ break;
+ case ACT_UMODESET:
+ atomic_set(&cs->mode, M_UNIMODEM);
+ cs->cur_at_seq = SEQ_NONE;
+ break;
+ case ACT_FAILCMODE:
+ cs->cur_at_seq = SEQ_NONE;
+ if (atomic_read(&cs->mstate) == MS_INIT ||
+ atomic_read(&cs->mstate) == MS_RECOVER) {
+ init_failed(cs, M_UNKNOWN);
+ break;
+ }
+ if (!reinit_and_retry(cs, -1))
+ schedule_init(cs, MS_RECOVER);
+ break;
+ case ACT_FAILUMODE:
+ cs->cur_at_seq = SEQ_NONE;
+ schedule_init(cs, MS_RECOVER);
+ break;
+ case ACT_HUPMODEM:
+ /* send "+++" (hangup in unimodem mode) */
+ cs->ops->write_cmd(cs, "+++", 3, NULL);
+ break;
+ case ACT_RING:
+ /* get fresh AT state structure for new CID */
+ at_state2 = get_free_channel(cs, ev->parameter);
+ if (!at_state2) {
+ warn("RING ignored: "
+ "could not allocate channel structure");
+ break;
+ }
+
+ /* initialize AT state structure
+ * note that bcs may be NULL if no B channel is free
+ */
+ at_state2->ConState = 700;
+ kfree(at_state2->str_var[STR_NMBR]);
+ at_state2->str_var[STR_NMBR] = NULL;
+ kfree(at_state2->str_var[STR_ZCPN]);
+ at_state2->str_var[STR_ZCPN] = NULL;
+ kfree(at_state2->str_var[STR_ZBC]);
+ at_state2->str_var[STR_ZBC] = NULL;
+ kfree(at_state2->str_var[STR_ZHLC]);
+ at_state2->str_var[STR_ZHLC] = NULL;
+ at_state2->int_var[VAR_ZCTP] = -1;
+
+ spin_lock_irqsave(&cs->lock, flags);
+ at_state2->timer_expires = RING_TIMEOUT;
+ at_state2->timer_active = 1;
+ spin_unlock_irqrestore(&cs->lock, flags);
+ break;
+ case ACT_ICALL:
+ handle_icall(cs, bcs, p_at_state);
+ at_state = *p_at_state;
+ break;
+ case ACT_FAILSDOWN:
+ warn("Could not shut down the device.");
+ /* fall through */
+ case ACT_FAKESDOWN:
+ case ACT_SDOWN:
+ cs->cur_at_seq = SEQ_NONE;
+ finish_shutdown(cs);
+ break;
+ case ACT_CONNECT:
+ if (cs->onechannel) {
+ at_state->pending_commands |= PC_DLE1;
+ atomic_set(&cs->commands_pending, 1);
+ break;
+ }
+ bcs->chstate |= CHS_D_UP;
+ gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
+ cs->ops->init_bchannel(bcs);
+ break;
+ case ACT_DLE1:
+ cs->cur_at_seq = SEQ_NONE;
+ bcs = cs->bcs + cs->curchannel;
+
+ bcs->chstate |= CHS_D_UP;
+ gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
+ cs->ops->init_bchannel(bcs);
+ break;
+ case ACT_FAKEHUP:
+ at_state->int_var[VAR_ZSAU] = ZSAU_NULL;
+ /* fall through */
+ case ACT_DISCONNECT:
+ cs->cur_at_seq = SEQ_NONE;
+ at_state->cid = -1;
+ if (bcs && cs->onechannel && cs->dle) {
+ /* Check for other open channels not needed:
+ * DLE only used for M10x with one B channel.
+ */
+ at_state->pending_commands |= PC_DLE0;
+ atomic_set(&cs->commands_pending, 1);
+ } else {
+ disconnect(p_at_state);
+ at_state = *p_at_state;
+ }
+ break;
+ case ACT_FAKEDLE0:
+ at_state->int_var[VAR_ZDLE] = 0;
+ cs->dle = 0;
+ /* fall through */
+ case ACT_DLE0:
+ cs->cur_at_seq = SEQ_NONE;
+ at_state2 = &cs->bcs[cs->curchannel].at_state;
+ disconnect(&at_state2);
+ break;
+ case ACT_ABORTHUP:
+ cs->cur_at_seq = SEQ_NONE;
+ warn("Could not hang up.");
+ at_state->cid = -1;
+ if (bcs && cs->onechannel)
+ at_state->pending_commands |= PC_DLE0;
+ else {
+ disconnect(p_at_state);
+ at_state = *p_at_state;
+ }
+ schedule_init(cs, MS_RECOVER);
+ break;
+ case ACT_FAILDLE0:
+ cs->cur_at_seq = SEQ_NONE;
+ warn("Could not leave DLE mode.");
+ at_state2 = &cs->bcs[cs->curchannel].at_state;
+ disconnect(&at_state2);
+ schedule_init(cs, MS_RECOVER);
+ break;
+ case ACT_FAILDLE1:
+ cs->cur_at_seq = SEQ_NONE;
+ warn("Could not enter DLE mode. Try to hang up.");
+ channel = cs->curchannel;
+ cs->bcs[channel].at_state.pending_commands |= PC_HUP;
+ atomic_set(&cs->commands_pending, 1);
+ break;
+
+ case ACT_CID: /* got cid; start dialing */
+ cs->cur_at_seq = SEQ_NONE;
+ channel = cs->curchannel;
+ if (ev->parameter > 0 && ev->parameter <= 65535) {
+ cs->bcs[channel].at_state.cid = ev->parameter;
+ cs->bcs[channel].at_state.pending_commands |=
+ PC_DIAL;
+ atomic_set(&cs->commands_pending, 1);
+ break;
+ }
+ /* fall through */
+ case ACT_FAILCID:
+ cs->cur_at_seq = SEQ_NONE;
+ channel = cs->curchannel;
+ if (!reinit_and_retry(cs, channel)) {
+ warn("Could not get a call id. Dialing not possible");
+ at_state2 = &cs->bcs[channel].at_state;
+ disconnect(&at_state2);
+ }
+ break;
+ case ACT_ABORTCID:
+ cs->cur_at_seq = SEQ_NONE;
+ at_state2 = &cs->bcs[cs->curchannel].at_state;
+ disconnect(&at_state2);
+ break;
+
+ case ACT_DIALING:
+ case ACT_ACCEPTED:
+ cs->cur_at_seq = SEQ_NONE;
+ break;
+
+ case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL processing */
+ disconnect(p_at_state);
+ at_state = *p_at_state;
+ break;
+
+ case ACT_ABORTDIAL: /* error/timeout during dial preparation */
+ cs->cur_at_seq = SEQ_NONE;
+ at_state->pending_commands |= PC_HUP;
+ atomic_set(&cs->commands_pending, 1);
+ break;
+
+ case ACT_REMOTEREJECT: /* DISCONNECT_IND after dialling */
+ case ACT_CONNTIMEOUT: /* timeout waiting for ZSAU=ACTIVE */
+ case ACT_REMOTEHUP: /* DISCONNECT_IND with established connection */
+ at_state->pending_commands |= PC_HUP;
+ atomic_set(&cs->commands_pending, 1);
+ break;
+ case ACT_GETSTRING: /* warning: RING, ZDLE, ... are not handled properly any more */
+ at_state->getstring = 1;
+ break;
+ case ACT_SETVER:
+ if (!ev->ptr) {
+ *p_genresp = 1;
+ *p_resp_code = RSP_ERROR;
+ break;
+ }
+ s = ev->ptr;
+
+ if (!strcmp(s, "OK")) {
+ *p_genresp = 1;
+ *p_resp_code = RSP_ERROR;
+ break;
+ }
+
+ for (i = 0; i < 4; ++i) {
+ val = simple_strtoul(s, (char **) &e, 10);
+ if (val > INT_MAX || e == s)
+ break;
+ if (i == 3) {
+ if (*e)
+ break;
+ } else if (*e != '.')
+ break;
+ else
+ s = e + 1;
+ cs->fwver[i] = val;
+ }
+ if (i != 4) {
+ *p_genresp = 1;
+ *p_resp_code = RSP_ERROR;
+ break;
+ }
+ /*at_state->getstring = 1;*/
+ cs->gotfwver = 0;
+ break;
+ case ACT_GOTVER:
+ if (cs->gotfwver == 0) {
+ cs->gotfwver = 1;
+ dbg(DEBUG_ANY,
+ "firmware version %02d.%03d.%02d.%02d",
+ cs->fwver[0], cs->fwver[1],
+ cs->fwver[2], cs->fwver[3]);
+ break;
+ }
+ /* fall through */
+ case ACT_FAILVER:
+ cs->gotfwver = -1;
+ err("could not read firmware version.");
+ break;
+#ifdef CONFIG_GIGASET_DEBUG
+ case ACT_ERROR:
+ *p_genresp = 1;
+ *p_resp_code = RSP_ERROR;
+ break;
+ case ACT_TEST:
+ {
+ static int count = 3; //2; //1;
+ *p_genresp = 1;
+ *p_resp_code = count ? RSP_ERROR : RSP_OK;
+ if (count > 0)
+ --count;
+ }
+ break;
+#endif
+ case ACT_DEBUG:
+ dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d",
+ __func__, ev->type, at_state->ConState);
+ break;
+ case ACT_WARN:
+ warn("%s: resp_code %d in ConState %d!",
+ __func__, ev->type, at_state->ConState);
+ break;
+ case ACT_ZCAU:
+ warn("cause code %04x in connection state %d.",
+ ev->parameter, at_state->ConState);
+ break;
+
+ /* events from the LL */
+ case ACT_DIAL:
+ start_dial(at_state, ev->ptr, ev->parameter);
+ break;
+ case ACT_ACCEPT:
+ start_accept(at_state);
+ break;
+ case ACT_PROTO_L2:
+ dbg(DEBUG_CMD,
+ "set protocol to %u", (unsigned) ev->parameter);
+ at_state->bcs->proto2 = ev->parameter;
+ break;
+ case ACT_HUP:
+ at_state->pending_commands |= PC_HUP;
+ atomic_set(&cs->commands_pending, 1); //FIXME
+ dbg(DEBUG_CMD, "Scheduling PC_HUP");
+ break;
+
+ /* hotplug events */
+ case ACT_STOP:
+ do_stop(cs);
+ break;
+ case ACT_START:
+ do_start(cs);
+ break;
+
+ /* events from the interface */ // FIXME without ACT_xxxx?
+ case ACT_IF_LOCK:
+ cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs);
+ cs->waiting = 0;
+ wake_up(&cs->waitqueue);
+ break;
+ case ACT_IF_VER:
+ if (ev->parameter != 0)
+ cs->cmd_result = -EINVAL;
+ else if (cs->gotfwver != 1) {
+ cs->cmd_result = -ENOENT;
+ } else {
+ memcpy(ev->arg, cs->fwver, sizeof cs->fwver);
+ cs->cmd_result = 0;
+ }
+ cs->waiting = 0;
+ wake_up(&cs->waitqueue);
+ break;
+
+ /* events from the proc file system */ // FIXME without ACT_xxxx?
+ case ACT_PROC_CIDMODE:
+ if (ev->parameter != atomic_read(&cs->cidmode)) {
+ atomic_set(&cs->cidmode, ev->parameter);
+ if (ev->parameter) {
+ cs->at_state.pending_commands |= PC_CIDMODE;
+ dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
+ } else {
+ cs->at_state.pending_commands |= PC_UMMODE;
+ dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
+ }
+ atomic_set(&cs->commands_pending, 1);
+ }
+ cs->waiting = 0;
+ wake_up(&cs->waitqueue);
+ break;
+
+ /* events from the hardware drivers */
+ case ACT_NOTIFY_BC_DOWN:
+ bchannel_down(bcs);
+ break;
+ case ACT_NOTIFY_BC_UP:
+ bchannel_up(bcs);
+ break;
+ case ACT_SHUTDOWN:
+ do_shutdown(cs);
+ break;
+
+
+ default:
+ if (action >= ACT_CMD && action < ACT_CMD + AT_NUM) {
+ *pp_command = at_state->bcs->commands[action - ACT_CMD];
+ if (!*pp_command) {
+ *p_genresp = 1;
+ *p_resp_code = RSP_NULL;
+ }
+ } else
+ err("%s: action==%d!", __func__, action);
+ }
+}
+
+/* State machine to do the calling and hangup procedure */
+static void process_event(struct cardstate *cs, struct event_t *ev)
+{
+ struct bc_state *bcs;
+ char *p_command = NULL;
+ struct reply_t *rep;
+ int rcode;
+ int genresp = 0;
+ int resp_code = RSP_ERROR;
+ int sendcid;
+ struct at_state_t *at_state;
+ int index;
+ int curact;
+ unsigned long flags;
+
+ IFNULLRET(cs);
+ IFNULLRET(ev);
+
+ if (ev->cid >= 0) {
+ at_state = at_state_from_cid(cs, ev->cid);
+ if (!at_state) {
+ gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID,
+ NULL, 0, NULL);
+ return;
+ }
+ } else {
+ at_state = ev->at_state;
+ if (at_state_invalid(cs, at_state)) {
+ dbg(DEBUG_ANY,
+ "event for invalid at_state %p", at_state);
+ return;
+ }
+ }
+
+ dbg(DEBUG_CMD,
+ "connection state %d, event %d", at_state->ConState, ev->type);
+
+ bcs = at_state->bcs;
+ sendcid = at_state->cid;
+
+ /* Setting the pointer to the dial array */
+ rep = at_state->replystruct;
+ IFNULLRET(rep);
+
+ if (ev->type == EV_TIMEOUT) {
+ if (ev->parameter != atomic_read(&at_state->timer_index)
+ || !at_state->timer_active) {
+ ev->type = RSP_NONE; /* old timeout */
+ dbg(DEBUG_ANY, "old timeout");
+ } else if (!at_state->waiting)
+ dbg(DEBUG_ANY, "timeout occured");
+ else
+ dbg(DEBUG_ANY, "stopped waiting");
+ }
+
+ /* if the response belongs to a variable in at_state->int_var[VAR_XXXX] or at_state->str_var[STR_XXXX], set it */
+ if (ev->type >= RSP_VAR && ev->type < RSP_VAR + VAR_NUM) {
+ index = ev->type - RSP_VAR;
+ at_state->int_var[index] = ev->parameter;
+ } else if (ev->type >= RSP_STR && ev->type < RSP_STR + STR_NUM) {
+ index = ev->type - RSP_STR;
+ kfree(at_state->str_var[index]);
+ at_state->str_var[index] = ev->ptr;
+ ev->ptr = NULL; /* prevent process_events() from deallocating ptr */
+ }
+
+ if (ev->type == EV_TIMEOUT || ev->type == RSP_STRING)
+ at_state->getstring = 0;
+
+ /* Search row in dial array which matches modem response and current constate */
+ for (;; rep++) {
+ rcode = rep->resp_code;
+ /* dbg (DEBUG_ANY, "rcode %d", rcode); */
+ if (rcode == RSP_LAST) {
+ /* found nothing...*/
+ warn("%s: rcode=RSP_LAST: resp_code %d in ConState %d!",
+ __func__, ev->type, at_state->ConState);
+ return;
+ }
+ if ((rcode == RSP_ANY || rcode == ev->type)
+ && ((int) at_state->ConState >= rep->min_ConState)
+ && (rep->max_ConState < 0
+ || (int) at_state->ConState <= rep->max_ConState)
+ && (rep->parameter < 0 || rep->parameter == ev->parameter))
+ break;
+ }
+
+ p_command = rep->command;
+
+ at_state->waiting = 0;
+ for (curact = 0; curact < MAXACT; ++curact) {
+ /* The row tells us what we should do ..
+ */
+ do_action(rep->action[curact], cs, bcs, &at_state, &p_command, &genresp, &resp_code, ev);
+ if (!at_state)
+ break; /* may be freed after disconnect */
+ }
+
+ if (at_state) {
+ /* Jump to the next con-state regarding the array */
+ if (rep->new_ConState >= 0)
+ at_state->ConState = rep->new_ConState;
+
+ if (genresp) {
+ spin_lock_irqsave(&cs->lock, flags);
+ at_state->timer_expires = 0; //FIXME
+ at_state->timer_active = 0; //FIXME
+ spin_unlock_irqrestore(&cs->lock, flags);
+ gigaset_add_event(cs, at_state, resp_code, NULL, 0, NULL);
+ } else {
+ /* Send command to modem if not NULL... */
+ if (p_command/*rep->command*/) {
+ if (atomic_read(&cs->connected))
+ send_command(cs, p_command,
+ sendcid, cs->dle,
+ GFP_ATOMIC);
+ else
+ gigaset_add_event(cs, at_state,
+ RSP_NODEV,
+ NULL, 0, NULL);
+ }
+
+ spin_lock_irqsave(&cs->lock, flags);
+ if (!rep->timeout) {
+ at_state->timer_expires = 0;
+ at_state->timer_active = 0;
+ } else if (rep->timeout > 0) { /* new timeout */
+ at_state->timer_expires = rep->timeout * 10;
+ at_state->timer_active = 1;
+ new_index(&at_state->timer_index,
+ MAX_TIMER_INDEX);
+ }
+ spin_unlock_irqrestore(&cs->lock, flags);
+ }
+ }
+}
+
+static void schedule_sequence(struct cardstate *cs,
+ struct at_state_t *at_state, int sequence)
+{
+ cs->cur_at_seq = sequence;
+ gigaset_add_event(cs, at_state, RSP_INIT, NULL, sequence, NULL);
+}
+
+static void process_command_flags(struct cardstate *cs)
+{
+ struct at_state_t *at_state = NULL;
+ struct bc_state *bcs;
+ int i;
+ int sequence;
+
+ IFNULLRET(cs);
+
+ atomic_set(&cs->commands_pending, 0);
+
+ if (cs->cur_at_seq) {
+ dbg(DEBUG_CMD, "not searching scheduled commands: busy");
+ return;
+ }
+
+ dbg(DEBUG_CMD, "searching scheduled commands");
+
+ sequence = SEQ_NONE;
+
+ /* clear pending_commands and hangup channels on shutdown */
+ if (cs->at_state.pending_commands & PC_SHUTDOWN) {
+ cs->at_state.pending_commands &= ~PC_CIDMODE;
+ for (i = 0; i < cs->channels; ++i) {
+ bcs = cs->bcs + i;
+ at_state = &bcs->at_state;
+ at_state->pending_commands &=
+ ~(PC_DLE1 | PC_ACCEPT | PC_DIAL);
+ if (at_state->cid > 0)
+ at_state->pending_commands |= PC_HUP;
+ if (at_state->pending_commands & PC_CID) {
+ at_state->pending_commands |= PC_NOCID;
+ at_state->pending_commands &= ~PC_CID;
+ }
+ }
+ }
+
+ /* clear pending_commands and hangup channels on reset */
+ if (cs->at_state.pending_commands & PC_INIT) {
+ cs->at_state.pending_commands &= ~PC_CIDMODE;
+ for (i = 0; i < cs->channels; ++i) {
+ bcs = cs->bcs + i;
+ at_state = &bcs->at_state;
+ at_state->pending_commands &=
+ ~(PC_DLE1 | PC_ACCEPT | PC_DIAL);
+ if (at_state->cid > 0)
+ at_state->pending_commands |= PC_HUP;
+ if (atomic_read(&cs->mstate) == MS_RECOVER) {
+ if (at_state->pending_commands & PC_CID) {
+ at_state->pending_commands |= PC_NOCID;
+ at_state->pending_commands &= ~PC_CID;
+ }
+ }
+ }
+ }
+
+ /* only switch back to unimodem mode, if no commands are pending and no channels are up */
+ if (cs->at_state.pending_commands == PC_UMMODE
+ && !atomic_read(&cs->cidmode)
+ && list_empty(&cs->temp_at_states)
+ && atomic_read(&cs->mode) == M_CID) {
+ sequence = SEQ_UMMODE;
+ at_state = &cs->at_state;
+ for (i = 0; i < cs->channels; ++i) {
+ bcs = cs->bcs + i;
+ if (bcs->at_state.pending_commands ||
+ bcs->at_state.cid > 0) {
+ sequence = SEQ_NONE;
+ break;
+ }
+ }
+ }
+ cs->at_state.pending_commands &= ~PC_UMMODE;
+ if (sequence != SEQ_NONE) {
+ schedule_sequence(cs, at_state, sequence);
+ return;
+ }
+
+ for (i = 0; i < cs->channels; ++i) {
+ bcs = cs->bcs + i;
+ if (bcs->at_state.pending_commands & PC_HUP) {
+ bcs->at_state.pending_commands &= ~PC_HUP;
+ if (bcs->at_state.pending_commands & PC_CID) {
+ /* not yet dialing: PC_NOCID is sufficient */
+ bcs->at_state.pending_commands |= PC_NOCID;
+ bcs->at_state.pending_commands &= ~PC_CID;
+ } else {
+ schedule_sequence(cs, &bcs->at_state, SEQ_HUP);
+ return;
+ }
+ }
+ if (bcs->at_state.pending_commands & PC_NOCID) {
+ bcs->at_state.pending_commands &= ~PC_NOCID;
+ cs->curchannel = bcs->channel;
+ schedule_sequence(cs, &cs->at_state, SEQ_NOCID);
+ return;
+ } else if (bcs->at_state.pending_commands & PC_DLE0) {
+ bcs->at_state.pending_commands &= ~PC_DLE0;
+ cs->curchannel = bcs->channel;
+ schedule_sequence(cs, &cs->at_state, SEQ_DLE0);
+ return;
+ }
+ }
+
+ list_for_each_entry(at_state, &cs->temp_at_states, list)
+ if (at_state->pending_commands & PC_HUP) {
+ at_state->pending_commands &= ~PC_HUP;
+ schedule_sequence(cs, at_state, SEQ_HUP);
+ return;
+ }
+
+ if (cs->at_state.pending_commands & PC_INIT) {
+ cs->at_state.pending_commands &= ~PC_INIT;
+ cs->dle = 0; //FIXME
+ cs->inbuf->inputstate = INS_command;
+ //FIXME reset card state (or -> LOCK0)?
+ schedule_sequence(cs, &cs->at_state, SEQ_INIT);
+ return;
+ }
+ if (cs->at_state.pending_commands & PC_SHUTDOWN) {
+ cs->at_state.pending_commands &= ~PC_SHUTDOWN;
+ schedule_sequence(cs, &cs->at_state, SEQ_SHUTDOWN);
+ return;
+ }
+ if (cs->at_state.pending_commands & PC_CIDMODE) {
+ cs->at_state.pending_commands &= ~PC_CIDMODE;
+ if (atomic_read(&cs->mode) == M_UNIMODEM) {
+#if 0
+ cs->retry_count = 2;
+#else
+ cs->retry_count = 1;
+#endif
+ schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE);
+ return;
+ }
+ }
+
+ for (i = 0; i < cs->channels; ++i) {
+ bcs = cs->bcs + i;
+ if (bcs->at_state.pending_commands & PC_DLE1) {
+ bcs->at_state.pending_commands &= ~PC_DLE1;
+ cs->curchannel = bcs->channel;
+ schedule_sequence(cs, &cs->at_state, SEQ_DLE1);
+ return;
+ }
+ if (bcs->at_state.pending_commands & PC_ACCEPT) {
+ bcs->at_state.pending_commands &= ~PC_ACCEPT;
+ schedule_sequence(cs, &bcs->at_state, SEQ_ACCEPT);
+ return;
+ }
+ if (bcs->at_state.pending_commands & PC_DIAL) {
+ bcs->at_state.pending_commands &= ~PC_DIAL;
+ schedule_sequence(cs, &bcs->at_state, SEQ_DIAL);
+ return;
+ }
+ if (bcs->at_state.pending_commands & PC_CID) {
+ switch (atomic_read(&cs->mode)) {
+ case M_UNIMODEM:
+ cs->at_state.pending_commands |= PC_CIDMODE;
+ dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
+ atomic_set(&cs->commands_pending, 1);
+ return;
+#ifdef GIG_MAYINITONDIAL
+ case M_UNKNOWN:
+ schedule_init(cs, MS_INIT);
+ return;
+#endif
+ }
+ bcs->at_state.pending_commands &= ~PC_CID;
+ cs->curchannel = bcs->channel;
+#ifdef GIG_RETRYCID
+ cs->retry_count = 2;
+#else
+ cs->retry_count = 1;
+#endif
+ schedule_sequence(cs, &cs->at_state, SEQ_CID);
+ return;
+ }
+ }
+}
+
+static void process_events(struct cardstate *cs)
+{
+ struct event_t *ev;
+ unsigned head, tail;
+ int i;
+ int check_flags = 0;
+ int was_busy;
+
+ /* no locking needed (only one reader) */
+ head = atomic_read(&cs->ev_head);
+
+ for (i = 0; i < 2 * MAX_EVENTS; ++i) {
+ tail = atomic_read(&cs->ev_tail);
+ if (tail == head) {
+ if (!check_flags && !atomic_read(&cs->commands_pending))
+ break;
+ check_flags = 0;
+ process_command_flags(cs);
+ tail = atomic_read(&cs->ev_tail);
+ if (tail == head) {
+ if (!atomic_read(&cs->commands_pending))
+ break;
+ continue;
+ }
+ }
+
+ ev = cs->events + head;
+ was_busy = cs->cur_at_seq != SEQ_NONE;
+ process_event(cs, ev);
+ kfree(ev->ptr);
+ ev->ptr = NULL;
+ if (was_busy && cs->cur_at_seq == SEQ_NONE)
+ check_flags = 1;
+
+ head = (head + 1) % MAX_EVENTS;
+ atomic_set(&cs->ev_head, head);
+ }
+
+ if (i == 2 * MAX_EVENTS) {
+ err("infinite loop in process_events; aborting.");
+ }
+}
+
+/* tasklet scheduled on any event received from the Gigaset device
+ * parameter:
+ * data ISDN controller state structure
+ */
+void gigaset_handle_event(unsigned long data)
+{
+ struct cardstate *cs = (struct cardstate *) data;
+
+ IFNULLRET(cs);
+ IFNULLRET(cs->inbuf);
+
+ /* handle incoming data on control/common channel */
+ if (atomic_read(&cs->inbuf->head) != atomic_read(&cs->inbuf->tail)) {
+ dbg(DEBUG_INTR, "processing new data");
+ cs->ops->handle_input(cs->inbuf);
+ }
+
+ process_events(cs);
+}
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
new file mode 100644
index 00000000000..729edcdb6da
--- /dev/null
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -0,0 +1,938 @@
+/* Siemens Gigaset 307x driver
+ * Common header file for all connection variants
+ *
+ * Written by Stefan Eilers <Eilers.Stefan@epost.de>
+ * and Hansjoerg Lipp <hjlipp@web.de>
+ *
+ * Version: $Id: gigaset.h,v 1.97.4.26 2006/02/04 18:28:16 hjlipp Exp $
+ * ===========================================================================
+ */
+
+#ifndef GIGASET_H
+#define GIGASET_H
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <asm/atomic.h>
+#include <linux/spinlock.h>
+#include <linux/isdnif.h>
+#include <linux/usb.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ppp_defs.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/list.h>
+
+#define GIG_VERSION {0,5,0,0}
+#define GIG_COMPAT {0,4,0,0}
+
+#define MAX_REC_PARAMS 10 /* Max. number of params in response string */
+#define MAX_RESP_SIZE 512 /* Max. size of a response string */
+#define HW_HDR_LEN 2 /* Header size used to store ack info */
+
+#define MAX_EVENTS 64 /* size of event queue */
+
+#define RBUFSIZE 8192
+#define SBUFSIZE 4096 /* sk_buff payload size */
+
+#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */
+#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */
+
+/* compile time options */
+#define GIG_MAJOR 0
+
+#define GIG_MAYINITONDIAL
+#define GIG_RETRYCID
+#define GIG_X75
+
+#define MAX_TIMER_INDEX 1000
+#define MAX_SEQ_INDEX 1000
+
+#define GIG_TICK (HZ / 10)
+
+/* timeout values (unit: 1 sec) */
+#define INIT_TIMEOUT 1
+
+/* timeout values (unit: 0.1 sec) */
+#define RING_TIMEOUT 3 /* for additional parameters to RING */
+#define BAS_TIMEOUT 20 /* for response to Base USB ops */
+#define ATRDY_TIMEOUT 3 /* for HD_READY_SEND_ATDATA */
+
+#define BAS_RETRY 3 /* max. retries for base USB ops */
+
+#define MAXACT 3
+
+#define IFNULL(a) if (unlikely(!(a)))
+#define IFNULLRET(a) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return; }
+#define IFNULLRETVAL(a,b) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return (b); }
+#define IFNULLCONT(a) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); continue; }
+#define IFNULLGOTO(a,b) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); goto b; }
+
+extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */
+
+/* any combination of these can be given with the 'debug=' parameter to insmod, e.g.
+ * 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and DEBUG_INTR. */
+enum debuglevel { /* up to 24 bits (atomic_t) */
+ DEBUG_REG = 0x0002, /* serial port I/O register operations */
+ DEBUG_OPEN = 0x0004, /* open/close serial port */
+ DEBUG_INTR = 0x0008, /* interrupt processing */
+ DEBUG_INTR_DUMP = 0x0010, /* Activating hexdump debug output on interrupt
+ requests, not available as run-time option */
+ DEBUG_CMD = 0x00020, /* sent/received LL commands */
+ DEBUG_STREAM = 0x00040, /* application data stream I/O events */
+ DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */
+ DEBUG_LLDATA = 0x00100, /* sent/received LL data */
+ DEBUG_INTR_0 = 0x00200, /* serial port output interrupt processing */
+ DEBUG_DRIVER = 0x00400, /* driver structure */
+ DEBUG_HDLC = 0x00800, /* M10x HDLC processing */
+ DEBUG_WRITE = 0x01000, /* M105 data write */
+ DEBUG_TRANSCMD = 0x02000, /*AT-COMMANDS+RESPONSES*/
+ DEBUG_MCMD = 0x04000, /*COMMANDS THAT ARE SENT VERY OFTEN*/
+ DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data structures */
+ DEBUG_LOCK = 0x10000, /* semaphore operations */
+ DEBUG_OUTPUT = 0x20000, /* output to device */
+ DEBUG_ISO = 0x40000, /* isochronous transfers */
+ DEBUG_IF = 0x80000, /* character device operations */
+ DEBUG_USBREQ = 0x100000, /* USB communication (except payload data) */
+ DEBUG_LOCKCMD = 0x200000, /* AT commands and responses when MS_LOCKED */
+
+ DEBUG_ANY = 0x3fffff, /* print message if any of the others is activated */
+};
+
+#ifdef CONFIG_GIGASET_DEBUG
+#define DEBUG_DEFAULT (DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ)
+//#define DEBUG_DEFAULT (DEBUG_LOCK | DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUF_IF | DEBUG_DRIVER | DEBUG_OUTPUT | DEBUG_INTR)
+#else
+#define DEBUG_DEFAULT 0
+#endif
+
+/* redefine syslog macros to prepend module name instead of entire source path */
+/* The space before the comma in ", ##" is needed by gcc 2.95 */
+#undef info
+#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
+
+#undef notice
+#define notice(format, arg...) printk(KERN_NOTICE "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
+
+#undef warn
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
+
+#undef err
+#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
+
+#undef dbg
+#ifdef CONFIG_GIGASET_DEBUG
+#define dbg(level, format, arg...) do { if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \
+ printk(KERN_DEBUG "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg); } while (0)
+#else
+#define dbg(level, format, arg...) do {} while (0)
+#endif
+
+void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
+ size_t len, const unsigned char *buf, int from_user);
+
+/* connection state */
+#define ZSAU_NONE 0
+#define ZSAU_DISCONNECT_IND 4
+#define ZSAU_OUTGOING_CALL_PROCEEDING 1
+#define ZSAU_PROCEEDING 1
+#define ZSAU_CALL_DELIVERED 2
+#define ZSAU_ACTIVE 3
+#define ZSAU_NULL 5
+#define ZSAU_DISCONNECT_REQ 6
+#define ZSAU_UNKNOWN -1
+
+/* USB control transfer requests */
+#define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
+#define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
+
+/* int-in-events 3070 */
+#define HD_B1_FLOW_CONTROL 0x80
+#define HD_B2_FLOW_CONTROL 0x81
+#define HD_RECEIVEATDATA_ACK (0x35) // 3070 // att: HD_RECEIVE>>AT<<DATA_ACK
+#define HD_READY_SEND_ATDATA (0x36) // 3070
+#define HD_OPEN_ATCHANNEL_ACK (0x37) // 3070
+#define HD_CLOSE_ATCHANNEL_ACK (0x38) // 3070
+#define HD_DEVICE_INIT_OK (0x11) // ISurf USB + 3070
+#define HD_OPEN_B1CHANNEL_ACK (0x51) // ISurf USB + 3070
+#define HD_OPEN_B2CHANNEL_ACK (0x52) // ISurf USB + 3070
+#define HD_CLOSE_B1CHANNEL_ACK (0x53) // ISurf USB + 3070
+#define HD_CLOSE_B2CHANNEL_ACK (0x54) // ISurf USB + 3070
+// Powermangment
+#define HD_SUSPEND_END (0x61) // ISurf USB
+// Configuration
+#define HD_RESET_INTERRUPT_PIPE_ACK (0xFF) // ISurf USB + 3070
+
+/* control requests 3070 */
+#define HD_OPEN_B1CHANNEL (0x23) // ISurf USB + 3070
+#define HD_CLOSE_B1CHANNEL (0x24) // ISurf USB + 3070
+#define HD_OPEN_B2CHANNEL (0x25) // ISurf USB + 3070
+#define HD_CLOSE_B2CHANNEL (0x26) // ISurf USB + 3070
+#define HD_RESET_INTERRUPT_PIPE (0x27) // ISurf USB + 3070
+#define HD_DEVICE_INIT_ACK (0x34) // ISurf USB + 3070
+#define HD_WRITE_ATMESSAGE (0x12) // 3070
+#define HD_READ_ATMESSAGE (0x13) // 3070
+#define HD_OPEN_ATCHANNEL (0x28) // 3070
+#define HD_CLOSE_ATCHANNEL (0x29) // 3070
+
+/* USB frames for isochronous transfer */
+#define BAS_FRAMETIME 1 /* number of milliseconds between frames */
+#define BAS_NUMFRAMES 8 /* number of frames per URB */
+#define BAS_MAXFRAME 16 /* allocated bytes per frame */
+#define BAS_NORMFRAME 8 /* send size without flow control */
+#define BAS_HIGHFRAME 10 /* " " with positive flow control */
+#define BAS_LOWFRAME 5 /* " " with negative flow control */
+#define BAS_CORRFRAMES 4 /* flow control multiplicator */
+
+#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES) /* size of isochronous input buffer per URB */
+#define BAS_OUTBUFSIZE 4096 /* size of common isochronous output buffer */
+#define BAS_OUTBUFPAD BAS_MAXFRAME /* size of pad area for isochronous output buffer */
+
+#define BAS_INURBS 3
+#define BAS_OUTURBS 3
+
+/* variable commands in struct bc_state */
+#define AT_ISO 0
+#define AT_DIAL 1
+#define AT_MSN 2
+#define AT_BC 3
+#define AT_PROTO 4
+#define AT_TYPE 5
+#define AT_HLC 6
+#define AT_NUM 7
+
+/* variables in struct at_state_t */
+#define VAR_ZSAU 0
+#define VAR_ZDLE 1
+#define VAR_ZVLS 2
+#define VAR_ZCTP 3
+#define VAR_NUM 4
+
+#define STR_NMBR 0
+#define STR_ZCPN 1
+#define STR_ZCON 2
+#define STR_ZBC 3
+#define STR_ZHLC 4
+#define STR_NUM 5
+
+#define EV_TIMEOUT -105
+#define EV_IF_VER -106
+#define EV_PROC_CIDMODE -107
+#define EV_SHUTDOWN -108
+#define EV_START -110
+#define EV_STOP -111
+#define EV_IF_LOCK -112
+#define EV_PROTO_L2 -113
+#define EV_ACCEPT -114
+#define EV_DIAL -115
+#define EV_HUP -116
+#define EV_BC_OPEN -117
+#define EV_BC_CLOSED -118
+
+/* input state */
+#define INS_command 0x0001
+#define INS_DLE_char 0x0002
+#define INS_byte_stuff 0x0004
+#define INS_have_data 0x0008
+#define INS_skip_frame 0x0010
+#define INS_DLE_command 0x0020
+#define INS_flag_hunt 0x0040
+
+/* channel state */
+#define CHS_D_UP 0x01
+#define CHS_B_UP 0x02
+#define CHS_NOTIFY_LL 0x04
+
+#define ICALL_REJECT 0
+#define ICALL_ACCEPT 1
+#define ICALL_IGNORE 2
+
+/* device state */
+#define MS_UNINITIALIZED 0
+#define MS_INIT 1
+#define MS_LOCKED 2
+#define MS_SHUTDOWN 3
+#define MS_RECOVER 4
+#define MS_READY 5
+
+/* mode */
+#define M_UNKNOWN 0
+#define M_CONFIG 1
+#define M_UNIMODEM 2
+#define M_CID 3
+
+/* start mode */
+#define SM_LOCKED 0
+#define SM_ISDN 1 /* default */
+
+struct gigaset_ops;
+struct gigaset_driver;
+
+struct usb_cardstate;
+struct ser_cardstate;
+struct bas_cardstate;
+
+struct bc_state;
+struct usb_bc_state;
+struct ser_bc_state;
+struct bas_bc_state;
+
+struct reply_t {
+ int resp_code; /* RSP_XXXX */
+ int min_ConState; /* <0 => ignore */
+ int max_ConState; /* <0 => ignore */
+ int parameter; /* e.g. ZSAU_XXXX <0: ignore*/
+ int new_ConState; /* <0 => ignore */
+ int timeout; /* >0 => *HZ; <=0 => TOUT_XXXX*/
+ int action[MAXACT]; /* ACT_XXXX */
+ char *command; /* NULL==none */
+};
+
+extern struct reply_t gigaset_tab_cid_m10x[];
+extern struct reply_t gigaset_tab_nocid_m10x[];
+
+struct inbuf_t {
+ unsigned char *rcvbuf; /* usb-gigaset receive buffer */
+ struct bc_state *bcs;
+ struct cardstate *cs;
+ int inputstate;
+
+ atomic_t head, tail;
+ unsigned char data[RBUFSIZE];
+};
+
+/* isochronous write buffer structure
+ * circular buffer with pad area for extraction of complete USB frames
+ * - data[read..nextread-1] is valid data already submitted to the USB subsystem
+ * - data[nextread..write-1] is valid data yet to be sent
+ * - data[write] is the next byte to write to
+ * - in byte-oriented L2 procotols, it is completely free
+ * - in bit-oriented L2 procotols, it may contain a partial byte of valid data
+ * - data[write+1..read-1] is free
+ * - wbits is the number of valid data bits in data[write], starting at the LSB
+ * - writesem is the semaphore for writing to the buffer:
+ * if writesem <= 0, data[write..read-1] is currently being written to
+ * - idle contains the byte value to repeat when the end of valid data is
+ * reached; if nextread==write (buffer contains no data to send), either the
+ * BAS_OUTBUFPAD bytes immediately before data[write] (if write>=BAS_OUTBUFPAD)
+ * or those of the pad area (if write<BAS_OUTBUFPAD) are also filled with that
+ * value
+ * - optionally, the following statistics on the buffer's usage can be collected:
+ * maxfill: maximum number of bytes occupied
+ * idlefills: number of times a frame of idle bytes is prepared
+ * emptygets: number of times the buffer was empty when a data frame was requested
+ * backtoback: number of times two data packets were entered into the buffer
+ * without intervening idle flags
+ * nakedback: set if no idle flags have been inserted since the last data packet
+ */
+struct isowbuf_t {
+ atomic_t read;
+ atomic_t nextread;
+ atomic_t write;
+ atomic_t writesem;
+ int wbits;
+ unsigned char data[BAS_OUTBUFSIZE + BAS_OUTBUFPAD];
+ unsigned char idle;
+};
+
+/* isochronous write URB context structure
+ * data to be stored along with the URB and retrieved when it is returned
+ * as completed by the USB subsystem
+ * - urb: pointer to the URB itself
+ * - bcs: pointer to the B Channel control structure
+ * - limit: end of write buffer area covered by this URB
+ */
+struct isow_urbctx_t {
+ struct urb *urb;
+ struct bc_state *bcs;
+ int limit;
+};
+
+/* AT state structure
+ * data associated with the state of an ISDN connection, whether or not
+ * it is currently assigned a B channel
+ */
+struct at_state_t {
+ struct list_head list;
+ int waiting;
+ int getstring;
+ atomic_t timer_index;
+ unsigned long timer_expires;
+ int timer_active;
+ unsigned int ConState; /* State of connection */
+ struct reply_t *replystruct;
+ int cid;
+ int int_var[VAR_NUM]; /* see VAR_XXXX */
+ char *str_var[STR_NUM]; /* see STR_XXXX */
+ unsigned pending_commands; /* see PC_XXXX */
+ atomic_t seq_index;
+
+ struct cardstate *cs;
+ struct bc_state *bcs;
+};
+
+struct resp_type_t {
+ unsigned char *response;
+ int resp_code; /* RSP_XXXX */
+ int type; /* RT_XXXX */
+};
+
+struct prot_skb {
+ atomic_t empty;
+ struct semaphore *sem;
+ struct sk_buff *skb;
+};
+
+struct event_t {
+ int type;
+ void *ptr, *arg;
+ int parameter;
+ int cid;
+ struct at_state_t *at_state;
+};
+
+/* This buffer holds all information about the used B-Channel */
+struct bc_state {
+ struct sk_buff *tx_skb; /* Current transfer buffer to modem */
+ struct sk_buff_head squeue; /* B-Channel send Queue */
+
+ /* Variables for debugging .. */
+ int corrupted; /* Counter for corrupted packages */
+ int trans_down; /* Counter of packages (downstream) */
+ int trans_up; /* Counter of packages (upstream) */
+
+ struct at_state_t at_state;
+ unsigned long rcvbytes;
+
+ __u16 fcs;
+ struct sk_buff *skb;
+ int inputstate; /* see INS_XXXX */
+
+ int channel;
+
+ struct cardstate *cs;
+
+ unsigned chstate; /* bitmap (CHS_*) */
+ int ignore;
+ unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */
+ char *commands[AT_NUM]; /* see AT_XXXX */
+
+#ifdef CONFIG_GIGASET_DEBUG
+ int emptycount;
+#endif
+ int busy;
+ int use_count;
+
+ /* hardware drivers */
+ union {
+ struct ser_bc_state *ser; /* private data of serial hardware driver */
+ struct usb_bc_state *usb; /* private data of usb hardware driver */
+ struct bas_bc_state *bas;
+ } hw;
+};
+
+struct cardstate {
+ struct gigaset_driver *driver;
+ unsigned minor_index;
+
+ const struct gigaset_ops *ops;
+
+ /* Stuff to handle communication */
+ //wait_queue_head_t initwait;
+ wait_queue_head_t waitqueue;
+ int waiting;
+ atomic_t mode; /* see M_XXXX */
+ atomic_t mstate; /* Modem state: see MS_XXXX */
+ /* only changed by the event layer */
+ int cmd_result;
+
+ int channels;
+ struct bc_state *bcs; /* Array of struct bc_state */
+
+ int onechannel; /* data and commands transmitted in one stream (M10x) */
+
+ spinlock_t lock;
+ struct at_state_t at_state; /* at_state_t for cid == 0 */
+ struct list_head temp_at_states; /* list of temporary "struct at_state_t"s without B channel */
+
+ struct inbuf_t *inbuf;
+
+ struct cmdbuf_t *cmdbuf, *lastcmdbuf;
+ spinlock_t cmdlock;
+ unsigned curlen, cmdbytes;
+
+ unsigned open_count;
+ struct tty_struct *tty;
+ struct tasklet_struct if_wake_tasklet;
+ unsigned control_state;
+
+ unsigned fwver[4];
+ int gotfwver;
+
+ atomic_t running; /* !=0 if events are handled */
+ atomic_t connected; /* !=0 if hardware is connected */
+
+ atomic_t cidmode;
+
+ int myid; /* id for communication with LL */
+ isdn_if iif;
+
+ struct reply_t *tabnocid;
+ struct reply_t *tabcid;
+ int cs_init;
+ int ignoreframes; /* frames to ignore after setting up the B channel */
+ struct semaphore sem; /* locks this structure: */
+ /* connected is not changed, */
+ /* hardware_up is not changed, */
+ /* MState is not changed to or from MS_LOCKED */
+
+ struct timer_list timer;
+ int retry_count;
+ int dle; /* !=0 if modem commands/responses are dle encoded */
+ int cur_at_seq; /* sequence of AT commands being processed */
+ int curchannel; /* channel, those commands are meant for */
+ atomic_t commands_pending; /* flag(s) in xxx.commands_pending have been set */
+ struct tasklet_struct event_tasklet; /* tasklet for serializing AT commands. Scheduled
+ * -> for modem reponses (and incomming data for M10x)
+ * -> on timeout
+ * -> after setting bits in xxx.at_state.pending_command
+ * (e.g. command from LL) */
+ struct tasklet_struct write_tasklet; /* tasklet for serial output
+ * (not used in base driver) */
+
+ /* event queue */
+ struct event_t events[MAX_EVENTS];
+ atomic_t ev_tail, ev_head;
+ spinlock_t ev_lock;
+
+ /* current modem response */
+ unsigned char respdata[MAX_RESP_SIZE];
+ unsigned cbytes;
+
+ /* hardware drivers */
+ union {
+ struct usb_cardstate *usb; /* private data of USB hardware driver */
+ struct ser_cardstate *ser; /* private data of serial hardware driver */
+ struct bas_cardstate *bas; /* private data of base hardware driver */
+ } hw;
+};
+
+struct gigaset_driver {
+ struct list_head list;
+ spinlock_t lock; /* locks minor tables and blocked */
+ //struct semaphore sem; /* locks this structure */
+ struct tty_driver *tty;
+ unsigned have_tty;
+ unsigned minor;
+ unsigned minors;
+ struct cardstate *cs;
+ unsigned *flags;
+ int blocked;
+
+ const struct gigaset_ops *ops;
+ struct module *owner;
+};
+
+struct cmdbuf_t {
+ struct cmdbuf_t *next, *prev;
+ int len, offset;
+ struct tasklet_struct *wake_tasklet;
+ unsigned char buf[0];
+};
+
+struct bas_bc_state {
+ /* isochronous output state */
+ atomic_t running;
+ atomic_t corrbytes;
+ spinlock_t isooutlock;
+ struct isow_urbctx_t isoouturbs[BAS_OUTURBS];
+ struct isow_urbctx_t *isooutdone, *isooutfree, *isooutovfl;
+ struct isowbuf_t *isooutbuf;
+ unsigned numsub; /* submitted URB counter (for diagnostic messages only) */
+ struct tasklet_struct sent_tasklet;
+
+ /* isochronous input state */
+ spinlock_t isoinlock;
+ struct urb *isoinurbs[BAS_INURBS];
+ unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS];
+ struct urb *isoindone; /* completed isoc read URB */
+ int loststatus; /* status of dropped URB */
+ unsigned isoinlost; /* number of bytes lost */
+ /* state of bit unstuffing algorithm (in addition to BC_state.inputstate) */
+ unsigned seqlen; /* number of '1' bits not yet unstuffed */
+ unsigned inbyte, inbits; /* collected bits for next byte */
+ /* statistics */
+ unsigned goodbytes; /* bytes correctly received */
+ unsigned alignerrs; /* frames with incomplete byte at end */
+ unsigned fcserrs; /* FCS errors */
+ unsigned frameerrs; /* framing errors */
+ unsigned giants; /* long frames */
+ unsigned runts; /* short frames */
+ unsigned aborts; /* HDLC aborts */
+ unsigned shared0s; /* '0' bits shared between flags */
+ unsigned stolen0s; /* '0' stuff bits also serving as leading flag bits */
+ struct tasklet_struct rcvd_tasklet;
+};
+
+struct gigaset_ops {
+ /* Called from ev-layer.c/interface.c for sending AT commands to the device */
+ int (*write_cmd)(struct cardstate *cs,
+ const unsigned char *buf, int len,
+ struct tasklet_struct *wake_tasklet);
+
+ /* Called from interface.c for additional device control */
+ int (*write_room)(struct cardstate *cs);
+ int (*chars_in_buffer)(struct cardstate *cs);
+ int (*brkchars)(struct cardstate *cs, const unsigned char buf[6]);
+
+ /* Called from ev-layer.c after setting up connection
+ * Should call gigaset_bchannel_up(), when finished. */
+ int (*init_bchannel)(struct bc_state *bcs);
+
+ /* Called from ev-layer.c after hanging up
+ * Should call gigaset_bchannel_down(), when finished. */
+ int (*close_bchannel)(struct bc_state *bcs);
+
+ /* Called by gigaset_initcs() for setting up bcs->hw.xxx */
+ int (*initbcshw)(struct bc_state *bcs);
+
+ /* Called by gigaset_freecs() for freeing bcs->hw.xxx */
+ int (*freebcshw)(struct bc_state *bcs);
+
+ /* Called by gigaset_stop() or gigaset_bchannel_down() for resetting bcs->hw.xxx */
+ void (*reinitbcshw)(struct bc_state *bcs);
+
+ /* Called by gigaset_initcs() for setting up cs->hw.xxx */
+ int (*initcshw)(struct cardstate *cs);
+
+ /* Called by gigaset_freecs() for freeing cs->hw.xxx */
+ void (*freecshw)(struct cardstate *cs);
+
+ ///* Called by gigaset_stop() for killing URBs, shutting down the device, ...
+ // hardwareup: ==0: don't try to shut down the device, hardware is really not accessible
+ // !=0: hardware still up */
+ //void (*stophw)(struct cardstate *cs, int hardwareup);
+
+ /* Called from common.c/interface.c for additional serial port control */
+ int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state, unsigned new_state);
+ int (*baud_rate)(struct cardstate *cs, unsigned cflag);
+ int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag);
+
+ /* Called from i4l.c to put an skb into the send-queue. */
+ int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb);
+
+ /* Called from ev-layer.c to process a block of data
+ * received through the common/control channel. */
+ void (*handle_input)(struct inbuf_t *inbuf);
+
+};
+
+/* = Common structures and definitions ======================================= */
+
+/* Parser states for DLE-Event:
+ * <DLE-EVENT>: <DLE_FLAG> "X" <EVENT> <DLE_FLAG> "."
+ * <DLE_FLAG>: 0x10
+ * <EVENT>: ((a-z)* | (A-Z)* | (0-10)*)+
+ */
+#define DLE_FLAG 0x10
+
+/* ===========================================================================
+ * Functions implemented in asyncdata.c
+ */
+
+/* Called from i4l.c to put an skb into the send-queue.
+ * After sending gigaset_skb_sent() should be called. */
+int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb);
+
+/* Called from ev-layer.c to process a block of data
+ * received through the common/control channel. */
+void gigaset_m10x_input(struct inbuf_t *inbuf);
+
+/* ===========================================================================
+ * Functions implemented in isocdata.c
+ */
+
+/* Called from i4l.c to put an skb into the send-queue.
+ * After sending gigaset_skb_sent() should be called. */
+int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb);
+
+/* Called from ev-layer.c to process a block of data
+ * received through the common/control channel. */
+void gigaset_isoc_input(struct inbuf_t *inbuf);
+
+/* Called from bas-gigaset.c to process a block of data
+ * received through the isochronous channel */
+void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs);
+
+/* Called from bas-gigaset.c to put a block of data
+ * into the isochronous output buffer */
+int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len);
+
+/* Called from bas-gigaset.c to initialize the isochronous output buffer */
+void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle);
+
+/* Called from bas-gigaset.c to retrieve a block of bytes for sending */
+int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size);
+
+/* ===========================================================================
+ * Functions implemented in i4l.c/gigaset.h
+ */
+
+/* Called by gigaset_initcs() for setting up with the isdn4linux subsystem */
+int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid);
+
+/* Called from xxx-gigaset.c to indicate completion of sending an skb */
+void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb);
+
+/* Called from common.c/ev-layer.c to indicate events relevant to the LL */
+int gigaset_isdn_icall(struct at_state_t *at_state);
+int gigaset_isdn_setup_accept(struct at_state_t *at_state);
+int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data);
+
+void gigaset_i4l_cmd(struct cardstate *cs, int cmd);
+void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd);
+
+
+static inline void gigaset_isdn_rcv_err(struct bc_state *bcs)
+{
+ isdn_ctrl response;
+
+ /* error -> LL */
+ dbg(DEBUG_CMD, "sending L1ERR");
+ response.driver = bcs->cs->myid;
+ response.command = ISDN_STAT_L1ERR;
+ response.arg = bcs->channel;
+ response.parm.errcode = ISDN_STAT_L1ERR_RECV;
+ bcs->cs->iif.statcallb(&response);
+}
+
+/* ===========================================================================
+ * Functions implemented in ev-layer.c
+ */
+
+/* tasklet called from common.c to process queued events */
+void gigaset_handle_event(unsigned long data);
+
+/* called from isocdata.c / asyncdata.c
+ * when a complete modem response line has been received */
+void gigaset_handle_modem_response(struct cardstate *cs);
+
+/* ===========================================================================
+ * Functions implemented in proc.c
+ */
+
+/* initialize sysfs for device */
+void gigaset_init_dev_sysfs(struct usb_interface *interface);
+void gigaset_free_dev_sysfs(struct usb_interface *interface);
+
+/* ===========================================================================
+ * Functions implemented in common.c/gigaset.h
+ */
+
+void gigaset_bcs_reinit(struct bc_state *bcs);
+void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
+ struct cardstate *cs, int cid);
+int gigaset_get_channel(struct bc_state *bcs);
+void gigaset_free_channel(struct bc_state *bcs);
+int gigaset_get_channels(struct cardstate *cs);
+void gigaset_free_channels(struct cardstate *cs);
+void gigaset_block_channels(struct cardstate *cs);
+
+/* Allocate and initialize driver structure. */
+struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
+ const char *procname,
+ const char *devname,
+ const char *devfsname,
+ const struct gigaset_ops *ops,
+ struct module *owner);
+
+/* Deallocate driver structure. */
+void gigaset_freedriver(struct gigaset_driver *drv);
+void gigaset_debugdrivers(void);
+struct cardstate *gigaset_get_cs_by_minor(unsigned minor);
+struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty);
+struct cardstate *gigaset_get_cs_by_id(int id);
+
+/* For drivers without fixed assignment device<->cardstate (usb) */
+struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv);
+void gigaset_unassign(struct cardstate *cs);
+void gigaset_blockdriver(struct gigaset_driver *drv);
+
+/* Allocate and initialize card state. Calls hardware dependent gigaset_init[b]cs(). */
+struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
+ int onechannel, int ignoreframes,
+ int cidmode, const char *modulename);
+
+/* Free card state. Calls hardware dependent gigaset_free[b]cs(). */
+void gigaset_freecs(struct cardstate *cs);
+
+/* Tell common.c that hardware and driver are ready. */
+int gigaset_start(struct cardstate *cs);
+
+/* Tell common.c that the device is not present any more. */
+void gigaset_stop(struct cardstate *cs);
+
+/* Tell common.c that the driver is being unloaded. */
+void gigaset_shutdown(struct cardstate *cs);
+
+/* Tell common.c that an skb has been sent. */
+void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb);
+
+/* Append event to the queue.
+ * Returns NULL on failure or a pointer to the event on success.
+ * ptr must be kmalloc()ed (and not be freed by the caller).
+ */
+struct event_t *gigaset_add_event(struct cardstate *cs,
+ struct at_state_t *at_state, int type,
+ void *ptr, int parameter, void *arg);
+
+/* Called on CONFIG1 command from frontend. */
+int gigaset_enterconfigmode(struct cardstate *cs); //0: success <0: errorcode
+
+/* cs->lock must not be locked */
+static inline void gigaset_schedule_event(struct cardstate *cs)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&cs->lock, flags);
+ if (atomic_read(&cs->running))
+ tasklet_schedule(&cs->event_tasklet);
+ spin_unlock_irqrestore(&cs->lock, flags);
+}
+
+/* Tell common.c that B channel has been closed. */
+/* cs->lock must not be locked */
+static inline void gigaset_bchannel_down(struct bc_state *bcs)
+{
+ gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_CLOSED, NULL, 0, NULL);
+
+ dbg(DEBUG_CMD, "scheduling BC_CLOSED");
+ gigaset_schedule_event(bcs->cs);
+}
+
+/* Tell common.c that B channel has been opened. */
+/* cs->lock must not be locked */
+static inline void gigaset_bchannel_up(struct bc_state *bcs)
+{
+ gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_OPEN, NULL, 0, NULL);
+
+ dbg(DEBUG_CMD, "scheduling BC_OPEN");
+ gigaset_schedule_event(bcs->cs);
+}
+
+/* handling routines for sk_buff */
+/* ============================= */
+
+/* private version of __skb_put()
+ * append 'len' bytes to the content of 'skb', already knowing that the
+ * existing buffer can accomodate them
+ * returns a pointer to the location where the new bytes should be copied to
+ * This function does not take any locks so it must be called with the
+ * appropriate locks held only.
+ */
+static inline unsigned char *gigaset_skb_put_quick(struct sk_buff *skb,
+ unsigned int len)
+{
+ unsigned char *tmp = skb->tail;
+ /*SKB_LINEAR_ASSERT(skb);*/ /* not needed here */
+ skb->tail += len;
+ skb->len += len;
+ return tmp;
+}
+
+/* pass received skb to LL
+ * Warning: skb must not be accessed anymore!
+ */
+static inline void gigaset_rcv_skb(struct sk_buff *skb,
+ struct cardstate *cs,
+ struct bc_state *bcs)
+{
+ cs->iif.rcvcallb_skb(cs->myid, bcs->channel, skb);
+ bcs->trans_down++;
+}
+
+/* handle reception of corrupted skb
+ * Warning: skb must not be accessed anymore!
+ */
+static inline void gigaset_rcv_error(struct sk_buff *procskb,
+ struct cardstate *cs,
+ struct bc_state *bcs)
+{
+ if (procskb)
+ dev_kfree_skb(procskb);
+
+ if (bcs->ignore)
+ --bcs->ignore;
+ else {
+ ++bcs->corrupted;
+ gigaset_isdn_rcv_err(bcs);
+ }
+}
+
+
+/* bitwise byte inversion table */
+extern __u8 gigaset_invtab[]; /* in common.c */
+
+
+/* append received bytes to inbuf */
+static inline int gigaset_fill_inbuf(struct inbuf_t *inbuf,
+ const unsigned char *src,
+ unsigned numbytes)
+{
+ unsigned n, head, tail, bytesleft;
+
+ dbg(DEBUG_INTR, "received %u bytes", numbytes);
+
+ if (!numbytes)
+ return 0;
+
+ bytesleft = numbytes;
+ tail = atomic_read(&inbuf->tail);
+ head = atomic_read(&inbuf->head);
+ dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
+
+ while (bytesleft) {
+ if (head > tail)
+ n = head - 1 - tail;
+ else if (head == 0)
+ n = (RBUFSIZE-1) - tail;
+ else
+ n = RBUFSIZE - tail;
+ if (!n) {
+ err("buffer overflow (%u bytes lost)", bytesleft);
+ break;
+ }
+ if (n > bytesleft)
+ n = bytesleft;
+ memcpy(inbuf->data + tail, src, n);
+ bytesleft -= n;
+ tail = (tail + n) % RBUFSIZE;
+ src += n;
+ }
+ dbg(DEBUG_INTR, "setting tail to %u", tail);
+ atomic_set(&inbuf->tail, tail);
+ return numbytes != bytesleft;
+}
+
+/* ===========================================================================
+ * Functions implemented in interface.c
+ */
+
+/* initialize interface */
+void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
+ const char *devname, const char *devfsname);
+/* release interface */
+void gigaset_if_freedriver(struct gigaset_driver *drv);
+/* add minor */
+void gigaset_if_init(struct cardstate *cs);
+/* remove minor */
+void gigaset_if_free(struct cardstate *cs);
+/* device received data */
+void gigaset_if_receive(struct cardstate *cs,
+ unsigned char *buffer, size_t len);
+
+#endif
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
new file mode 100644
index 00000000000..731a675f21b
--- /dev/null
+++ b/drivers/isdn/gigaset/i4l.c
@@ -0,0 +1,567 @@
+/*
+ * Stuff used by all variants of the driver
+ *
+ * Copyright (c) 2001 by Stefan Eilers (Eilers.Stefan@epost.de),
+ * Hansjoerg Lipp (hjlipp@web.de),
+ * Tilman Schmidt (tilman@imap.cc).
+ *
+ * =====================================================================
+ * 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.
+ * =====================================================================
+ * ToDo: ...
+ * =====================================================================
+ * Version: $Id: i4l.c,v 1.3.2.9 2006/02/04 18:28:16 hjlipp Exp $
+ * =====================================================================
+ */
+
+#include "gigaset.h"
+
+/* == Handling of I4L IO ============================================================================*/
+
+/* writebuf_from_LL
+ * called by LL to transmit data on an open channel
+ * inserts the buffer data into the send queue and starts the transmission
+ * Note that this operation must not sleep!
+ * When the buffer is processed completely, gigaset_skb_sent() should be called.
+ * parameters:
+ * driverID driver ID as assigned by LL
+ * channel channel number
+ * ack if != 0 LL wants to be notified on completion via statcallb(ISDN_STAT_BSENT)
+ * skb skb containing data to send
+ * return value:
+ * number of accepted bytes
+ * 0 if temporarily unable to accept data (out of buffer space)
+ * <0 on error (eg. -EINVAL)
+ */
+static int writebuf_from_LL(int driverID, int channel, int ack, struct sk_buff *skb)
+{
+ struct cardstate *cs;
+ struct bc_state *bcs;
+ unsigned len;
+ unsigned skblen;
+
+ if (!(cs = gigaset_get_cs_by_id(driverID))) {
+ err("%s: invalid driver ID (%d)", __func__, driverID);
+ return -ENODEV;
+ }
+ if (channel < 0 || channel >= cs->channels) {
+ err("%s: invalid channel ID (%d)", __func__, channel);
+ return -ENODEV;
+ }
+ bcs = &cs->bcs[channel];
+ len = skb->len;
+
+ dbg(DEBUG_LLDATA,
+ "Receiving data from LL (id: %d, channel: %d, ack: %d, size: %d)",
+ driverID, channel, ack, len);
+
+ if (!len) {
+ if (ack)
+ warn("not ACKing empty packet from LL");
+ return 0;
+ }
+ if (len > MAX_BUF_SIZE) {
+ err("%s: packet too large (%d bytes)", __func__, channel);
+ return -EINVAL;
+ }
+
+ if (!atomic_read(&cs->connected))
+ return -ENODEV;
+
+ skblen = ack ? len : 0;
+ skb->head[0] = skblen & 0xff;
+ skb->head[1] = skblen >> 8;
+ dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x", len, skblen,
+ (unsigned) skb->head[0], (unsigned) skb->head[1]);
+
+ /* pass to device-specific module */
+ return cs->ops->send_skb(bcs, skb);
+}
+
+void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
+{
+ unsigned len;
+ isdn_ctrl response;
+
+ ++bcs->trans_up;
+
+ if (skb->len)
+ warn("%s: skb->len==%d", __func__, skb->len);
+
+ len = (unsigned char) skb->head[0] |
+ (unsigned) (unsigned char) skb->head[1] << 8;
+ if (len) {
+ dbg(DEBUG_MCMD,
+ "Acknowledge sending to LL (id: %d, channel: %d size: %u)",
+ bcs->cs->myid, bcs->channel, len);
+
+ response.driver = bcs->cs->myid;
+ response.command = ISDN_STAT_BSENT;
+ response.arg = bcs->channel;
+ response.parm.length = len;
+ bcs->cs->iif.statcallb(&response);
+ }
+}
+EXPORT_SYMBOL_GPL(gigaset_skb_sent);
+
+/* This function will be called by LL to send commands
+ * NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL,
+ * so don't put too much effort into it.
+ */
+static int command_from_LL(isdn_ctrl *cntrl)
+{
+ struct cardstate *cs = gigaset_get_cs_by_id(cntrl->driver);
+ //isdn_ctrl response;
+ //unsigned long flags;
+ struct bc_state *bcs;
+ int retval = 0;
+ struct setup_parm *sp;
+
+ //dbg(DEBUG_ANY, "Gigaset_HW: Receiving command");
+ gigaset_debugdrivers();
+
+ /* Terminate this call if no device is present. Bt if the command is "ISDN_CMD_LOCK" or
+ * "ISDN_CMD_UNLOCK" then execute it due to the fact that they are device independent !
+ */
+ //FIXME "remove test for &connected"
+ if ((!cs || !atomic_read(&cs->connected))) {
+ warn("LL tried to access unknown device with nr. %d",
+ cntrl->driver);
+ return -ENODEV;
+ }
+
+ switch (cntrl->command) {
+ case ISDN_CMD_IOCTL:
+
+ dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver:%d,arg: %ld)",
+ cntrl->driver, cntrl->arg);
+
+ warn("ISDN_CMD_IOCTL is not supported.");
+ return -EINVAL;
+
+ case ISDN_CMD_DIAL:
+ dbg(DEBUG_ANY, "ISDN_CMD_DIAL (driver: %d, channel: %ld, "
+ "phone: %s,ownmsn: %s, si1: %d, si2: %d)",
+ cntrl->driver, cntrl->arg,
+ cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
+ cntrl->parm.setup.si1, cntrl->parm.setup.si2);
+
+ if (cntrl->arg >= cs->channels) {
+ err("invalid channel (%d)", (int) cntrl->arg);
+ return -EINVAL;
+ }
+
+ bcs = cs->bcs + cntrl->arg;
+
+ if (!gigaset_get_channel(bcs)) {
+ err("channel not free");
+ return -EBUSY;
+ }
+
+ sp = kmalloc(sizeof *sp, GFP_ATOMIC);
+ if (!sp) {
+ gigaset_free_channel(bcs);
+ err("ISDN_CMD_DIAL: out of memory");
+ return -ENOMEM;
+ }
+ *sp = cntrl->parm.setup;
+
+ if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp,
+ atomic_read(&bcs->at_state.seq_index),
+ NULL)) {
+ //FIXME what should we do?
+ kfree(sp);
+ gigaset_free_channel(bcs);
+ return -ENOMEM;
+ }
+
+ dbg(DEBUG_CMD, "scheduling DIAL");
+ gigaset_schedule_event(cs);
+ break;
+ case ISDN_CMD_ACCEPTD: //FIXME
+ dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD");
+
+ if (cntrl->arg >= cs->channels) {
+ err("invalid channel (%d)", (int) cntrl->arg);
+ return -EINVAL;
+ }
+
+ if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
+ EV_ACCEPT, NULL, 0, NULL)) {
+ //FIXME what should we do?
+ return -ENOMEM;
+ }
+
+ dbg(DEBUG_CMD, "scheduling ACCEPT");
+ gigaset_schedule_event(cs);
+
+ break;
+ case ISDN_CMD_ACCEPTB:
+ dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB");
+ break;
+ case ISDN_CMD_HANGUP:
+ dbg(DEBUG_ANY,
+ "ISDN_CMD_HANGUP (channel: %d)", (int) cntrl->arg);
+
+ if (cntrl->arg >= cs->channels) {
+ err("ISDN_CMD_HANGUP: invalid channel (%u)",
+ (unsigned) cntrl->arg);
+ return -EINVAL;
+ }
+
+ if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
+ EV_HUP, NULL, 0, NULL)) {
+ //FIXME what should we do?
+ return -ENOMEM;
+ }
+
+ dbg(DEBUG_CMD, "scheduling HUP");
+ gigaset_schedule_event(cs);
+
+ break;
+ case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME
+ dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ");
+ break;
+ case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME
+ dbg(DEBUG_ANY,
+ "ISDN_CMD_SETEAZ (id:%d, channel: %ld, number: %s)",
+ cntrl->driver, cntrl->arg, cntrl->parm.num);
+ break;
+ case ISDN_CMD_SETL2: /* Set L2 to given protocol */
+ dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (Channel: %ld, Proto: %lx)",
+ cntrl->arg & 0xff, (cntrl->arg >> 8));
+
+ if ((cntrl->arg & 0xff) >= cs->channels) {
+ err("invalid channel (%u)",
+ (unsigned) cntrl->arg & 0xff);
+ return -EINVAL;
+ }
+
+ if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state,
+ EV_PROTO_L2, NULL, cntrl->arg >> 8,
+ NULL)) {
+ //FIXME what should we do?
+ return -ENOMEM;
+ }
+
+ dbg(DEBUG_CMD, "scheduling PROTO_L2");
+ gigaset_schedule_event(cs);
+ break;
+ case ISDN_CMD_SETL3: /* Set L3 to given protocol */
+ dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (Channel: %ld, Proto: %lx)",
+ cntrl->arg & 0xff, (cntrl->arg >> 8));
+
+ if ((cntrl->arg & 0xff) >= cs->channels) {
+ err("invalid channel (%u)",
+ (unsigned) cntrl->arg & 0xff);
+ return -EINVAL;
+ }
+
+ if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
+ err("invalid protocol %lu", cntrl->arg >> 8);
+ return -EINVAL;
+ }
+
+ break;
+ case ISDN_CMD_PROCEED:
+ dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME
+ break;
+ case ISDN_CMD_ALERT:
+ dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME
+ if (cntrl->arg >= cs->channels) {
+ err("invalid channel (%d)", (int) cntrl->arg);
+ return -EINVAL;
+ }
+ //bcs = cs->bcs + cntrl->arg;
+ //bcs->proto2 = -1;
+ // FIXME
+ break;
+ case ISDN_CMD_REDIR:
+ dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME
+ break;
+ case ISDN_CMD_PROT_IO:
+ dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO");
+ break;
+ case ISDN_CMD_FAXCMD:
+ dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD");
+ break;
+ case ISDN_CMD_GETL2:
+ dbg(DEBUG_ANY, "ISDN_CMD_GETL2");
+ break;
+ case ISDN_CMD_GETL3:
+ dbg(DEBUG_ANY, "ISDN_CMD_GETL3");
+ break;
+ case ISDN_CMD_GETEAZ:
+ dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ");
+ break;
+ case ISDN_CMD_SETSIL:
+ dbg(DEBUG_ANY, "ISDN_CMD_SETSIL");
+ break;
+ case ISDN_CMD_GETSIL:
+ dbg(DEBUG_ANY, "ISDN_CMD_GETSIL");
+ break;
+ default:
+ err("unknown command %d from LL",
+ cntrl->command);
+ return -EINVAL;
+ }
+
+ return retval;
+}
+
+void gigaset_i4l_cmd(struct cardstate *cs, int cmd)
+{
+ isdn_ctrl command;
+
+ command.driver = cs->myid;
+ command.command = cmd;
+ command.arg = 0;
+ cs->iif.statcallb(&command);
+}
+
+void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd)
+{
+ isdn_ctrl command;
+
+ command.driver = bcs->cs->myid;
+ command.command = cmd;
+ command.arg = bcs->channel;
+ bcs->cs->iif.statcallb(&command);
+}
+
+int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data)
+{
+ struct bc_state *bcs = at_state->bcs;
+ unsigned proto;
+ const char *bc;
+ size_t length[AT_NUM];
+ size_t l;
+ int i;
+ struct setup_parm *sp = data;
+
+ switch (bcs->proto2) {
+ case ISDN_PROTO_L2_HDLC:
+ proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */
+ break;
+ case ISDN_PROTO_L2_TRANS:
+ proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
+ break;
+ default:
+ err("invalid protocol: %u", bcs->proto2);
+ return -EINVAL;
+ }
+
+ switch (sp->si1) {
+ case 1: /* audio */
+ bc = "9090A3"; /* 3.1 kHz audio, A-law */
+ break;
+ case 7: /* data */
+ default: /* hope the app knows what it is doing */
+ bc = "8890"; /* unrestricted digital information */
+ }
+ //FIXME add missing si1 values from 1TR6, inspect si2, set HLC/LLC
+
+ length[AT_DIAL ] = 1 + strlen(sp->phone) + 1 + 1;
+ l = strlen(sp->eazmsn);
+ length[AT_MSN ] = l ? 6 + l + 1 + 1 : 0;
+ length[AT_BC ] = 5 + strlen(bc) + 1 + 1;
+ length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */
+ length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */
+ length[AT_TYPE ] = 6 + 1 + 1 + 1; /* call type: 1 character */
+ length[AT_HLC ] = 0;
+
+ for (i = 0; i < AT_NUM; ++i) {
+ kfree(bcs->commands[i]);
+ bcs->commands[i] = NULL;
+ if (length[i] &&
+ !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {
+ err("out of memory");
+ return -ENOMEM;
+ }
+ }
+
+ /* type = 1: extern, 0: intern, 2: recall, 3: door, 4: centrex */
+ if (sp->phone[0] == '*' && sp->phone[1] == '*') {
+ /* internal call: translate ** prefix to CTP value */
+ snprintf(bcs->commands[AT_DIAL], length[AT_DIAL],
+ "D%s\r", sp->phone+2);
+ strncpy(bcs->commands[AT_TYPE], "^SCTP=0\r", length[AT_TYPE]);
+ } else {
+ snprintf(bcs->commands[AT_DIAL], length[AT_DIAL],
+ "D%s\r", sp->phone);
+ strncpy(bcs->commands[AT_TYPE], "^SCTP=1\r", length[AT_TYPE]);
+ }
+
+ if (bcs->commands[AT_MSN])
+ snprintf(bcs->commands[AT_MSN], length[AT_MSN], "^SMSN=%s\r", sp->eazmsn);
+ snprintf(bcs->commands[AT_BC ], length[AT_BC ], "^SBC=%s\r", bc);
+ snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto);
+ snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], "^SISO=%u\r", (unsigned)bcs->channel + 1);
+
+ return 0;
+}
+
+int gigaset_isdn_setup_accept(struct at_state_t *at_state)
+{
+ unsigned proto;
+ size_t length[AT_NUM];
+ int i;
+ struct bc_state *bcs = at_state->bcs;
+
+ switch (bcs->proto2) {
+ case ISDN_PROTO_L2_HDLC:
+ proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */
+ break;
+ case ISDN_PROTO_L2_TRANS:
+ proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
+ break;
+ default:
+ err("invalid protocol: %u", bcs->proto2);
+ return -EINVAL;
+ }
+
+ length[AT_DIAL ] = 0;
+ length[AT_MSN ] = 0;
+ length[AT_BC ] = 0;
+ length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */
+ length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */
+ length[AT_TYPE ] = 0;
+ length[AT_HLC ] = 0;
+
+ for (i = 0; i < AT_NUM; ++i) {
+ kfree(bcs->commands[i]);
+ bcs->commands[i] = NULL;
+ if (length[i] &&
+ !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {
+ err("out of memory");
+ return -ENOMEM;
+ }
+ }
+
+ snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto);
+ snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], "^SISO=%u\r", (unsigned) bcs->channel + 1);
+
+ return 0;
+}
+
+int gigaset_isdn_icall(struct at_state_t *at_state)
+{
+ struct cardstate *cs = at_state->cs;
+ struct bc_state *bcs = at_state->bcs;
+ isdn_ctrl response;
+ int retval;
+
+ /* fill ICALL structure */
+ response.parm.setup.si1 = 0; /* default: unknown */
+ response.parm.setup.si2 = 0;
+ response.parm.setup.screen = 0; //FIXME how to set these?
+ response.parm.setup.plan = 0;
+ if (!at_state->str_var[STR_ZBC]) {
+ /* no BC (internal call): assume speech, A-law */
+ response.parm.setup.si1 = 1;
+ } else if (!strcmp(at_state->str_var[STR_ZBC], "8890")) {
+ /* unrestricted digital information */
+ response.parm.setup.si1 = 7;
+ } else if (!strcmp(at_state->str_var[STR_ZBC], "8090A3")) {
+ /* speech, A-law */
+ response.parm.setup.si1 = 1;
+ } else if (!strcmp(at_state->str_var[STR_ZBC], "9090A3")) {
+ /* 3,1 kHz audio, A-law */
+ response.parm.setup.si1 = 1;
+ response.parm.setup.si2 = 2;
+ } else {
+ warn("RING ignored - unsupported BC %s",
+ at_state->str_var[STR_ZBC]);
+ return ICALL_IGNORE;
+ }
+ if (at_state->str_var[STR_NMBR]) {
+ strncpy(response.parm.setup.phone, at_state->str_var[STR_NMBR],
+ sizeof response.parm.setup.phone - 1);
+ response.parm.setup.phone[sizeof response.parm.setup.phone - 1] = 0;
+ } else
+ response.parm.setup.phone[0] = 0;
+ if (at_state->str_var[STR_ZCPN]) {
+ strncpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN],
+ sizeof response.parm.setup.eazmsn - 1);
+ response.parm.setup.eazmsn[sizeof response.parm.setup.eazmsn - 1] = 0;
+ } else
+ response.parm.setup.eazmsn[0] = 0;
+
+ if (!bcs) {
+ notice("no channel for incoming call");
+ dbg(DEBUG_CMD, "Sending ICALLW");
+ response.command = ISDN_STAT_ICALLW;
+ response.arg = 0; //FIXME
+ } else {
+ dbg(DEBUG_CMD, "Sending ICALL");
+ response.command = ISDN_STAT_ICALL;
+ response.arg = bcs->channel; //FIXME
+ }
+ response.driver = cs->myid;
+ retval = cs->iif.statcallb(&response);
+ dbg(DEBUG_CMD, "Response: %d", retval);
+ switch (retval) {
+ case 0: /* no takers */
+ return ICALL_IGNORE;
+ case 1: /* alerting */
+ bcs->chstate |= CHS_NOTIFY_LL;
+ return ICALL_ACCEPT;
+ case 2: /* reject */
+ return ICALL_REJECT;
+ case 3: /* incomplete */
+ warn("LL requested unsupported feature: Incomplete Number");
+ return ICALL_IGNORE;
+ case 4: /* proceeding */
+ /* Gigaset will send ALERTING anyway.
+ * There doesn't seem to be a way to avoid this.
+ */
+ return ICALL_ACCEPT;
+ case 5: /* deflect */
+ warn("LL requested unsupported feature: Call Deflection");
+ return ICALL_IGNORE;
+ default:
+ err("LL error %d on ICALL", retval);
+ return ICALL_IGNORE;
+ }
+}
+
+/* Set Callback function pointer */
+int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid)
+{
+ isdn_if *iif = &cs->iif;
+
+ dbg(DEBUG_ANY, "Register driver capabilities to LL");
+
+ //iif->id[sizeof(iif->id) - 1]=0;
+ //strncpy(iif->id, isdnid, sizeof(iif->id) - 1);
+ if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index)
+ >= sizeof iif->id)
+ return -ENOMEM; //FIXME EINVAL/...??
+
+ iif->owner = THIS_MODULE;
+ iif->channels = cs->channels; /* I am supporting just one channel *//* I was supporting...*/
+ iif->maxbufsize = MAX_BUF_SIZE;
+ iif->features = ISDN_FEATURE_L2_TRANS | /* Our device is very advanced, therefore */
+ ISDN_FEATURE_L2_HDLC |
+#ifdef GIG_X75
+ ISDN_FEATURE_L2_X75I |
+#endif
+ ISDN_FEATURE_L3_TRANS |
+ ISDN_FEATURE_P_EURO;
+ iif->hl_hdrlen = HW_HDR_LEN; /* Area for storing ack */
+ iif->command = command_from_LL;
+ iif->writebuf_skb = writebuf_from_LL;
+ iif->writecmd = NULL; /* Don't support isdnctrl */
+ iif->readstat = NULL; /* Don't support isdnctrl */
+ iif->rcvcallb_skb = NULL; /* Will be set by LL */
+ iif->statcallb = NULL; /* Will be set by LL */
+
+ if (!register_isdn(iif))
+ return 0;
+
+ cs->myid = iif->channels; /* Set my device id */
+ return 1;
+}
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
new file mode 100644
index 00000000000..3a81d9c6514
--- /dev/null
+++ b/drivers/isdn/gigaset/interface.c
@@ -0,0 +1,718 @@
+/*
+ * interface to user space for the gigaset driver
+ *
+ * Copyright (c) 2004 by Hansjoerg Lipp <hjlipp@web.de>
+ *
+ * =====================================================================
+ * 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.
+ * =====================================================================
+ * Version: $Id: interface.c,v 1.14.4.15 2006/02/04 18:28:16 hjlipp Exp $
+ * =====================================================================
+ */
+
+#include "gigaset.h"
+#include <linux/gigaset_dev.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+/*** our ioctls ***/
+
+static int if_lock(struct cardstate *cs, int *arg)
+{
+ int cmd = *arg;
+
+ dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd);
+
+ if (cmd > 1)
+ return -EINVAL;
+
+ if (cmd < 0) {
+ *arg = atomic_read(&cs->mstate) == MS_LOCKED; //FIXME remove?
+ return 0;
+ }
+
+ if (!cmd && atomic_read(&cs->mstate) == MS_LOCKED
+ && atomic_read(&cs->connected)) {
+ cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
+ cs->ops->baud_rate(cs, B115200);
+ cs->ops->set_line_ctrl(cs, CS8);
+ cs->control_state = TIOCM_DTR|TIOCM_RTS;
+ }
+
+ cs->waiting = 1;
+ if (!gigaset_add_event(cs, &cs->at_state, EV_IF_LOCK,
+ NULL, cmd, NULL)) {
+ cs->waiting = 0;
+ return -ENOMEM;
+ }
+
+ dbg(DEBUG_CMD, "scheduling IF_LOCK");
+ gigaset_schedule_event(cs);
+
+ wait_event(cs->waitqueue, !cs->waiting);
+
+ if (cs->cmd_result >= 0) {
+ *arg = cs->cmd_result;
+ return 0;
+ }
+
+ return cs->cmd_result;
+}
+
+static int if_version(struct cardstate *cs, unsigned arg[4])
+{
+ static const unsigned version[4] = GIG_VERSION;
+ static const unsigned compat[4] = GIG_COMPAT;
+ unsigned cmd = arg[0];
+
+ dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd);
+
+ switch (cmd) {
+ case GIGVER_DRIVER:
+ memcpy(arg, version, sizeof version);
+ return 0;
+ case GIGVER_COMPAT:
+ memcpy(arg, compat, sizeof compat);
+ return 0;
+ case GIGVER_FWBASE:
+ cs->waiting = 1;
+ if (!gigaset_add_event(cs, &cs->at_state, EV_IF_VER,
+ NULL, 0, arg)) {
+ cs->waiting = 0;
+ return -ENOMEM;
+ }
+
+ dbg(DEBUG_CMD, "scheduling IF_VER");
+ gigaset_schedule_event(cs);
+
+ wait_event(cs->waitqueue, !cs->waiting);
+
+ if (cs->cmd_result >= 0)
+ return 0;
+
+ return cs->cmd_result;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int if_config(struct cardstate *cs, int *arg)
+{
+ dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg);
+
+ if (*arg != 1)
+ return -EINVAL;
+
+ if (atomic_read(&cs->mstate) != MS_LOCKED)
+ return -EBUSY;
+
+ *arg = 0;
+ return gigaset_enterconfigmode(cs);
+}
+
+/*** the terminal driver ***/
+/* stolen from usbserial and some other tty drivers */
+
+static int if_open(struct tty_struct *tty, struct file *filp);
+static void if_close(struct tty_struct *tty, struct file *filp);
+static int if_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static int if_write_room(struct tty_struct *tty);
+static int if_chars_in_buffer(struct tty_struct *tty);
+static void if_throttle(struct tty_struct *tty);
+static void if_unthrottle(struct tty_struct *tty);
+static void if_set_termios(struct tty_struct *tty, struct termios *old);
+static int if_tiocmget(struct tty_struct *tty, struct file *file);
+static int if_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static int if_write(struct tty_struct *tty,
+ const unsigned char *buf, int count);
+
+static struct tty_operations if_ops = {
+ .open = if_open,
+ .close = if_close,
+ .ioctl = if_ioctl,
+ .write = if_write,
+ .write_room = if_write_room,
+ .chars_in_buffer = if_chars_in_buffer,
+ .set_termios = if_set_termios,
+ .throttle = if_throttle,
+ .unthrottle = if_unthrottle,
+#if 0
+ .break_ctl = serial_break,
+#endif
+ .tiocmget = if_tiocmget,
+ .tiocmset = if_tiocmset,
+};
+
+static int if_open(struct tty_struct *tty, struct file *filp)
+{
+ struct cardstate *cs;
+ unsigned long flags;
+
+ dbg(DEBUG_IF, "%d+%d: %s()", tty->driver->minor_start, tty->index,
+ __FUNCTION__);
+
+ tty->driver_data = NULL;
+
+ cs = gigaset_get_cs_by_tty(tty);
+ if (!cs)
+ return -ENODEV;
+
+ if (down_interruptible(&cs->sem))
+ return -ERESTARTSYS; // FIXME -EINTR?
+ tty->driver_data = cs;
+
+ ++cs->open_count;
+
+ if (cs->open_count == 1) {
+ spin_lock_irqsave(&cs->lock, flags);
+ cs->tty = tty;
+ spin_unlock_irqrestore(&cs->lock, flags);
+ tty->low_latency = 1; //FIXME test
+ //FIXME
+ }
+
+ up(&cs->sem);
+ return 0;
+}
+
+static void if_close(struct tty_struct *tty, struct file *filp)
+{
+ struct cardstate *cs;
+ unsigned long flags;
+
+ cs = (struct cardstate *) tty->driver_data;
+ if (!cs) {
+ err("cs==NULL in %s", __FUNCTION__);
+ return;
+ }
+
+ dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+
+ down(&cs->sem);
+
+ if (!cs->open_count)
+ warn("%s: device not opened", __FUNCTION__);
+ else {
+ if (!--cs->open_count) {
+ spin_lock_irqsave(&cs->lock, flags);
+ cs->tty = NULL;
+ spin_unlock_irqrestore(&cs->lock, flags);
+ //FIXME
+ }
+ }
+
+ up(&cs->sem);
+}
+
+static int if_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct cardstate *cs;
+ int retval = -ENODEV;
+ int int_arg;
+ unsigned char buf[6];
+ unsigned version[4];
+
+ cs = (struct cardstate *) tty->driver_data;
+ if (!cs) {
+ err("cs==NULL in %s", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __FUNCTION__, cmd);
+
+ if (down_interruptible(&cs->sem))
+ return -ERESTARTSYS; // FIXME -EINTR?
+
+ if (!cs->open_count)
+ warn("%s: device not opened", __FUNCTION__);
+ else {
+ retval = 0;
+ switch (cmd) {
+ case GIGASET_REDIR:
+ retval = get_user(int_arg, (int __user *) arg);
+ if (retval >= 0)
+ retval = if_lock(cs, &int_arg);
+ if (retval >= 0)
+ retval = put_user(int_arg, (int __user *) arg);
+ break;
+ case GIGASET_CONFIG:
+ retval = get_user(int_arg, (int __user *) arg);
+ if (retval >= 0)
+ retval = if_config(cs, &int_arg);
+ if (retval >= 0)
+ retval = put_user(int_arg, (int __user *) arg);
+ break;
+ case GIGASET_BRKCHARS:
+ //FIXME test if MS_LOCKED
+ gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS",
+ 6, (const unsigned char *) arg, 1);
+ if (!atomic_read(&cs->connected)) {
+ dbg(DEBUG_ANY, "can't communicate with unplugged device");
+ retval = -ENODEV;
+ break;
+ }
+ retval = copy_from_user(&buf,
+ (const unsigned char __user *) arg, 6)
+ ? -EFAULT : 0;
+ if (retval >= 0)
+ retval = cs->ops->brkchars(cs, buf);
+ break;
+ case GIGASET_VERSION:
+ retval = copy_from_user(version, (unsigned __user *) arg,
+ sizeof version) ? -EFAULT : 0;
+ if (retval >= 0)
+ retval = if_version(cs, version);
+ if (retval >= 0)
+ retval = copy_to_user((unsigned __user *) arg, version,
+ sizeof version)
+ ? -EFAULT : 0;
+ break;
+ default:
+ dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x",
+ __FUNCTION__, cmd);
+ retval = -ENOIOCTLCMD;
+ }
+ }
+
+ up(&cs->sem);
+
+ return retval;
+}
+
+static int if_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct cardstate *cs;
+ int retval;
+
+ cs = (struct cardstate *) tty->driver_data;
+ if (!cs) {
+ err("cs==NULL in %s", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+
+ if (down_interruptible(&cs->sem))
+ return -ERESTARTSYS; // FIXME -EINTR?
+
+ // FIXME read from device?
+ retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR);
+
+ up(&cs->sem);
+
+ return retval;
+}
+
+static int if_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct cardstate *cs;
+ int retval;
+ unsigned mc;
+
+ cs = (struct cardstate *) tty->driver_data;
+ if (!cs) {
+ err("cs==NULL in %s", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ dbg(DEBUG_IF,
+ "%u: %s(0x%x, 0x%x)", cs->minor_index, __FUNCTION__, set, clear);
+
+ if (down_interruptible(&cs->sem))
+ return -ERESTARTSYS; // FIXME -EINTR?
+
+ if (!atomic_read(&cs->connected)) {
+ dbg(DEBUG_ANY, "can't communicate with unplugged device");
+ retval = -ENODEV;
+ } else {
+ mc = (cs->control_state | set) & ~clear & (TIOCM_RTS|TIOCM_DTR);
+ retval = cs->ops->set_modem_ctrl(cs, cs->control_state, mc);
+ cs->control_state = mc;
+ }
+
+ up(&cs->sem);
+
+ return retval;
+}
+
+static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+ struct cardstate *cs;
+ int retval = -ENODEV;
+
+ cs = (struct cardstate *) tty->driver_data;
+ if (!cs) {
+ err("cs==NULL in %s", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+
+ if (down_interruptible(&cs->sem))
+ return -ERESTARTSYS; // FIXME -EINTR?
+
+ if (!cs->open_count)
+ warn("%s: device not opened", __FUNCTION__);
+ else if (atomic_read(&cs->mstate) != MS_LOCKED) {
+ warn("can't write to unlocked device");
+ retval = -EBUSY;
+ } else if (!atomic_read(&cs->connected)) {
+ dbg(DEBUG_ANY, "can't write to unplugged device");
+ retval = -EBUSY; //FIXME
+ } else {
+ retval = cs->ops->write_cmd(cs, buf, count,
+ &cs->if_wake_tasklet);
+ }
+
+ up(&cs->sem);
+
+ return retval;
+}
+
+static int if_write_room(struct tty_struct *tty)
+{
+ struct cardstate *cs;
+ int retval = -ENODEV;
+
+ cs = (struct cardstate *) tty->driver_data;
+ if (!cs) {
+ err("cs==NULL in %s", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+
+ if (down_interruptible(&cs->sem))
+ return -ERESTARTSYS; // FIXME -EINTR?
+
+ if (!cs->open_count)
+ warn("%s: device not opened", __FUNCTION__);
+ else if (atomic_read(&cs->mstate) != MS_LOCKED) {
+ warn("can't write to unlocked device");
+ retval = -EBUSY; //FIXME
+ } else if (!atomic_read(&cs->connected)) {
+ dbg(DEBUG_ANY, "can't write to unplugged device");
+ retval = -EBUSY; //FIXME
+ } else
+ retval = cs->ops->write_room(cs);
+
+ up(&cs->sem);
+
+ return retval;
+}
+
+static int if_chars_in_buffer(struct tty_struct *tty)
+{
+ struct cardstate *cs;
+ int retval = -ENODEV;
+
+ cs = (struct cardstate *) tty->driver_data;
+ if (!cs) {
+ err("cs==NULL in %s", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+
+ if (down_interruptible(&cs->sem))
+ return -ERESTARTSYS; // FIXME -EINTR?
+
+ if (!cs->open_count)
+ warn("%s: device not opened", __FUNCTION__);
+ else if (atomic_read(&cs->mstate) != MS_LOCKED) {
+ warn("can't write to unlocked device");
+ retval = -EBUSY;
+ } else if (!atomic_read(&cs->connected)) {
+ dbg(DEBUG_ANY, "can't write to unplugged device");
+ retval = -EBUSY; //FIXME
+ } else
+ retval = cs->ops->chars_in_buffer(cs);
+
+ up(&cs->sem);
+
+ return retval;
+}
+
+static void if_throttle(struct tty_struct *tty)
+{
+ struct cardstate *cs;
+
+ cs = (struct cardstate *) tty->driver_data;
+ if (!cs) {
+ err("cs==NULL in %s", __FUNCTION__);
+ return;
+ }
+
+ dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+
+ down(&cs->sem);
+
+ if (!cs->open_count)
+ warn("%s: device not opened", __FUNCTION__);
+ else {
+ //FIXME
+ }
+
+ up(&cs->sem);
+}
+
+static void if_unthrottle(struct tty_struct *tty)
+{
+ struct cardstate *cs;
+
+ cs = (struct cardstate *) tty->driver_data;
+ if (!cs) {
+ err("cs==NULL in %s", __FUNCTION__);
+ return;
+ }
+
+ dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+
+ down(&cs->sem);
+
+ if (!cs->open_count)
+ warn("%s: device not opened", __FUNCTION__);
+ else {
+ //FIXME
+ }
+
+ up(&cs->sem);
+}
+
+static void if_set_termios(struct tty_struct *tty, struct termios *old)
+{
+ struct cardstate *cs;
+ unsigned int iflag;
+ unsigned int cflag;
+ unsigned int old_cflag;
+ unsigned int control_state, new_state;
+
+ cs = (struct cardstate *) tty->driver_data;
+ if (!cs) {
+ err("cs==NULL in %s", __FUNCTION__);
+ return;
+ }
+
+ dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+
+ down(&cs->sem);
+
+ if (!cs->open_count) {
+ warn("%s: device not opened", __FUNCTION__);
+ goto out;
+ }
+
+ if (!atomic_read(&cs->connected)) {
+ dbg(DEBUG_ANY, "can't communicate with unplugged device");
+ goto out;
+ }
+
+ // stolen from mct_u232.c
+ iflag = tty->termios->c_iflag;
+ cflag = tty->termios->c_cflag;
+ old_cflag = old ? old->c_cflag : cflag; //FIXME?
+ dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", cs->minor_index,
+ iflag, cflag, old_cflag);
+
+ /* get a local copy of the current port settings */
+ control_state = cs->control_state;
+
+ /*
+ * Update baud rate.
+ * Do not attempt to cache old rates and skip settings,
+ * disconnects screw such tricks up completely.
+ * Premature optimization is the root of all evil.
+ */
+
+ /* reassert DTR and (maybe) RTS on transition from B0 */
+ if ((old_cflag & CBAUD) == B0) {
+ new_state = control_state | TIOCM_DTR;
+ /* don't set RTS if using hardware flow control */
+ if (!(old_cflag & CRTSCTS))
+ new_state |= TIOCM_RTS;
+ dbg(DEBUG_IF, "%u: from B0 - set DTR%s", cs->minor_index,
+ (new_state & TIOCM_RTS) ? " only" : "/RTS");
+ cs->ops->set_modem_ctrl(cs, control_state, new_state);
+ control_state = new_state;
+ }
+
+ cs->ops->baud_rate(cs, cflag & CBAUD);
+
+ if ((cflag & CBAUD) == B0) {
+ /* Drop RTS and DTR */
+ dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index);
+ new_state = control_state & ~(TIOCM_DTR | TIOCM_RTS);
+ cs->ops->set_modem_ctrl(cs, control_state, new_state);
+ control_state = new_state;
+ }
+
+ /*
+ * Update line control register (LCR)
+ */
+
+ cs->ops->set_line_ctrl(cs, cflag);
+
+#if 0
+ //FIXME this hangs M101 [ts 2005-03-09]
+ //FIXME do we need this?
+ /*
+ * Set flow control: well, I do not really now how to handle DTR/RTS.
+ * Just do what we have seen with SniffUSB on Win98.
+ */
+ /* Drop DTR/RTS if no flow control otherwise assert */
+ dbg(DEBUG_IF, "%u: control_state %x", cs->minor_index, control_state);
+ new_state = control_state;
+ if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
+ new_state |= TIOCM_DTR | TIOCM_RTS;
+ else
+ new_state &= ~(TIOCM_DTR | TIOCM_RTS);
+ if (new_state != control_state) {
+ dbg(DEBUG_IF, "%u: new_state %x", cs->minor_index, new_state);
+ gigaset_set_modem_ctrl(cs, control_state, new_state); // FIXME: mct_u232.c sets the old state here. is this a bug?
+ control_state = new_state;
+ }
+#endif
+
+ /* save off the modified port settings */
+ cs->control_state = control_state;
+
+out:
+ up(&cs->sem);
+}
+
+
+/* wakeup tasklet for the write operation */
+static void if_wake(unsigned long data)
+{
+ struct cardstate *cs = (struct cardstate *) data;
+ struct tty_struct *tty;
+
+ tty = cs->tty;
+ if (!tty)
+ return;
+
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup) {
+ dbg(DEBUG_IF, "write wakeup call");
+ tty->ldisc.write_wakeup(tty);
+ }
+
+ wake_up_interruptible(&tty->write_wait);
+}
+
+/*** interface to common ***/
+
+void gigaset_if_init(struct cardstate *cs)
+{
+ struct gigaset_driver *drv;
+
+ drv = cs->driver;
+ if (!drv->have_tty)
+ return;
+
+ tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs);
+ tty_register_device(drv->tty, cs->minor_index, NULL);
+}
+
+void gigaset_if_free(struct cardstate *cs)
+{
+ struct gigaset_driver *drv;
+
+ drv = cs->driver;
+ if (!drv->have_tty)
+ return;
+
+ tasklet_disable(&cs->if_wake_tasklet);
+ tasklet_kill(&cs->if_wake_tasklet);
+ tty_unregister_device(drv->tty, cs->minor_index);
+}
+
+void gigaset_if_receive(struct cardstate *cs,
+ unsigned char *buffer, size_t len)
+{
+ unsigned long flags;
+ struct tty_struct *tty;
+
+ spin_lock_irqsave(&cs->lock, flags);
+ if ((tty = cs->tty) == NULL)
+ dbg(DEBUG_ANY, "receive on closed device");
+ else {
+ tty_buffer_request_room(tty, len);
+ tty_insert_flip_string(tty, buffer, len);
+ tty_flip_buffer_push(tty);
+ }
+ spin_unlock_irqrestore(&cs->lock, flags);
+}
+EXPORT_SYMBOL_GPL(gigaset_if_receive);
+
+/* gigaset_if_initdriver
+ * Initialize tty interface.
+ * parameters:
+ * drv Driver
+ * procname Name of the driver (e.g. for /proc/tty/drivers)
+ * devname Name of the device files (prefix without minor number)
+ * devfsname Devfs name of the device files without %d
+ */
+void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
+ const char *devname, const char *devfsname)
+{
+ unsigned minors = drv->minors;
+ int ret;
+ struct tty_driver *tty;
+
+ drv->have_tty = 0;
+
+ if ((drv->tty = alloc_tty_driver(minors)) == NULL)
+ goto enomem;
+ tty = drv->tty;
+
+ tty->magic = TTY_DRIVER_MAGIC,
+ tty->major = GIG_MAJOR,
+ tty->type = TTY_DRIVER_TYPE_SERIAL,
+ tty->subtype = SERIAL_TYPE_NORMAL,
+ tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
+
+ tty->driver_name = procname;
+ tty->name = devname;
+ tty->minor_start = drv->minor;
+ tty->num = drv->minors;
+
+ tty->owner = THIS_MODULE;
+ tty->devfs_name = devfsname;
+
+ tty->init_termios = tty_std_termios; //FIXME
+ tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; //FIXME
+ tty_set_operations(tty, &if_ops);
+
+ ret = tty_register_driver(tty);
+ if (ret < 0) {
+ warn("failed to register tty driver (error %d)", ret);
+ goto error;
+ }
+ dbg(DEBUG_IF, "tty driver initialized");
+ drv->have_tty = 1;
+ return;
+
+enomem:
+ warn("could not allocate tty structures");
+error:
+ if (drv->tty)
+ put_tty_driver(drv->tty);
+}
+
+void gigaset_if_freedriver(struct gigaset_driver *drv)
+{
+ if (!drv->have_tty)
+ return;
+
+ drv->have_tty = 0;
+ tty_unregister_driver(drv->tty);
+ put_tty_driver(drv->tty);
+}
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
new file mode 100644
index 00000000000..5744eb91b31
--- /dev/null
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -0,0 +1,1009 @@
+/*
+ * Common data handling layer for bas_gigaset
+ *
+ * Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>,
+ * Hansjoerg Lipp <hjlipp@web.de>.
+ *
+ * =====================================================================
+ * 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.
+ * =====================================================================
+ * ToDo: ...
+ * =====================================================================
+ * Version: $Id: isocdata.c,v 1.2.2.5 2005/11/13 23:05:19 hjlipp Exp $
+ * =====================================================================
+ */
+
+#include "gigaset.h"
+#include <linux/crc-ccitt.h>
+
+/* access methods for isowbuf_t */
+/* ============================ */
+
+/* initialize buffer structure
+ */
+void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle)
+{
+ atomic_set(&iwb->read, 0);
+ atomic_set(&iwb->nextread, 0);
+ atomic_set(&iwb->write, 0);
+ atomic_set(&iwb->writesem, 1);
+ iwb->wbits = 0;
+ iwb->idle = idle;
+ memset(iwb->data + BAS_OUTBUFSIZE, idle, BAS_OUTBUFPAD);
+}
+
+/* compute number of bytes which can be appended to buffer
+ * so that there is still room to append a maximum frame of flags
+ */
+static inline int isowbuf_freebytes(struct isowbuf_t *iwb)
+{
+ int read, write, freebytes;
+
+ read = atomic_read(&iwb->read);
+ write = atomic_read(&iwb->write);
+ if ((freebytes = read - write) > 0) {
+ /* no wraparound: need padding space within regular area */
+ return freebytes - BAS_OUTBUFPAD;
+ } else if (read < BAS_OUTBUFPAD) {
+ /* wraparound: can use space up to end of regular area */
+ return BAS_OUTBUFSIZE - write;
+ } else {
+ /* following the wraparound yields more space */
+ return freebytes + BAS_OUTBUFSIZE - BAS_OUTBUFPAD;
+ }
+}
+
+/* compare two offsets within the buffer
+ * The buffer is seen as circular, with the read position as start
+ * returns -1/0/1 if position a </=/> position b without crossing 'read'
+ */
+static inline int isowbuf_poscmp(struct isowbuf_t *iwb, int a, int b)
+{
+ int read;
+ if (a == b)
+ return 0;
+ read = atomic_read(&iwb->read);
+ if (a < b) {
+ if (a < read && read <= b)
+ return +1;
+ else
+ return -1;
+ } else {
+ if (b < read && read <= a)
+ return -1;
+ else
+ return +1;
+ }
+}
+
+/* start writing
+ * acquire the write semaphore
+ * return true if acquired, false if busy
+ */
+static inline int isowbuf_startwrite(struct isowbuf_t *iwb)
+{
+ if (!atomic_dec_and_test(&iwb->writesem)) {
+ atomic_inc(&iwb->writesem);
+ dbg(DEBUG_ISO,
+ "%s: couldn't acquire iso write semaphore", __func__);
+ return 0;
+ }
+#ifdef CONFIG_GIGASET_DEBUG
+ dbg(DEBUG_ISO,
+ "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
+ __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits);
+#endif
+ return 1;
+}
+
+/* finish writing
+ * release the write semaphore and update the maximum buffer fill level
+ * returns the current write position
+ */
+static inline int isowbuf_donewrite(struct isowbuf_t *iwb)
+{
+ int write = atomic_read(&iwb->write);
+ atomic_inc(&iwb->writesem);
+ return write;
+}
+
+/* append bits to buffer without any checks
+ * - data contains bits to append, starting at LSB
+ * - nbits is number of bits to append (0..24)
+ * must be called with the write semaphore held
+ * If more than nbits bits are set in data, the extraneous bits are set in the
+ * buffer too, but the write position is only advanced by nbits.
+ */
+static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits)
+{
+ int write = atomic_read(&iwb->write);
+ data <<= iwb->wbits;
+ data |= iwb->data[write];
+ nbits += iwb->wbits;
+ while (nbits >= 8) {
+ iwb->data[write++] = data & 0xff;
+ write %= BAS_OUTBUFSIZE;
+ data >>= 8;
+ nbits -= 8;
+ }
+ iwb->wbits = nbits;
+ iwb->data[write] = data & 0xff;
+ atomic_set(&iwb->write, write);
+}
+
+/* put final flag on HDLC bitstream
+ * also sets the idle fill byte to the correspondingly shifted flag pattern
+ * must be called with the write semaphore held
+ */
+static inline void isowbuf_putflag(struct isowbuf_t *iwb)
+{
+ int write;
+
+ /* add two flags, thus reliably covering one byte */
+ isowbuf_putbits(iwb, 0x7e7e, 8);
+ /* recover the idle flag byte */
+ write = atomic_read(&iwb->write);
+ iwb->idle = iwb->data[write];
+ dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle);
+ /* mask extraneous bits in buffer */
+ iwb->data[write] &= (1 << iwb->wbits) - 1;
+}
+
+/* retrieve a block of bytes for sending
+ * The requested number of bytes is provided as a contiguous block.
+ * If necessary, the frame is filled to the requested number of bytes
+ * with the idle value.
+ * returns offset to frame, < 0 on busy or error
+ */
+int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
+{
+ int read, write, limit, src, dst;
+ unsigned char pbyte;
+
+ read = atomic_read(&iwb->nextread);
+ write = atomic_read(&iwb->write);
+ if (likely(read == write)) {
+ //dbg(DEBUG_STREAM, "%s: send buffer empty", __func__);
+ /* return idle frame */
+ return read < BAS_OUTBUFPAD ?
+ BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD;
+ }
+
+ limit = read + size;
+ dbg(DEBUG_STREAM,
+ "%s: read=%d write=%d limit=%d", __func__, read, write, limit);
+#ifdef CONFIG_GIGASET_DEBUG
+ if (unlikely(size < 0 || size > BAS_OUTBUFPAD)) {
+ err("invalid size %d", size);
+ return -EINVAL;
+ }
+ src = atomic_read(&iwb->read);
+ if (unlikely(limit > BAS_OUTBUFSIZE + BAS_OUTBUFPAD ||
+ (read < src && limit >= src))) {
+ err("isoc write buffer frame reservation violated");
+ return -EFAULT;
+ }
+#endif
+
+ if (read < write) {
+ /* no wraparound in valid data */
+ if (limit >= write) {
+ /* append idle frame */
+ if (!isowbuf_startwrite(iwb))
+ return -EBUSY;
+ /* write position could have changed */
+ if (limit >= (write = atomic_read(&iwb->write))) {
+ pbyte = iwb->data[write]; /* save partial byte */
+ limit = write + BAS_OUTBUFPAD;
+ dbg(DEBUG_STREAM,
+ "%s: filling %d->%d with %02x",
+ __func__, write, limit, iwb->idle);
+ if (write + BAS_OUTBUFPAD < BAS_OUTBUFSIZE)
+ memset(iwb->data + write, iwb->idle,
+ BAS_OUTBUFPAD);
+ else {
+ /* wraparound, fill entire pad area */
+ memset(iwb->data + write, iwb->idle,
+ BAS_OUTBUFSIZE + BAS_OUTBUFPAD
+ - write);
+ limit = 0;
+ }
+ dbg(DEBUG_STREAM, "%s: restoring %02x at %d",
+ __func__, pbyte, limit);
+ iwb->data[limit] = pbyte; /* restore partial byte */
+ atomic_set(&iwb->write, limit);
+ }
+ isowbuf_donewrite(iwb);
+ }
+ } else {
+ /* valid data wraparound */
+ if (limit >= BAS_OUTBUFSIZE) {
+ /* copy wrapped part into pad area */
+ src = 0;
+ dst = BAS_OUTBUFSIZE;
+ while (dst < limit && src < write)
+ iwb->data[dst++] = iwb->data[src++];
+ if (dst <= limit) {
+ /* fill pad area with idle byte */
+ memset(iwb->data + dst, iwb->idle,
+ BAS_OUTBUFSIZE + BAS_OUTBUFPAD - dst);
+ }
+ limit = src;
+ }
+ }
+ atomic_set(&iwb->nextread, limit);
+ return read;
+}
+
+/* dump_bytes
+ * write hex bytes to syslog for debugging
+ */
+static inline void dump_bytes(enum debuglevel level, const char *tag,
+ unsigned char *bytes, int count)
+{
+#ifdef CONFIG_GIGASET_DEBUG
+ unsigned char c;
+ static char dbgline[3 * 32 + 1];
+ static const char hexdigit[] = "0123456789abcdef";
+ int i = 0;
+ IFNULLRET(tag);
+ IFNULLRET(bytes);
+ while (count-- > 0) {
+ if (i > sizeof(dbgline) - 4) {
+ dbgline[i] = '\0';
+ dbg(level, "%s:%s", tag, dbgline);
+ i = 0;
+ }
+ c = *bytes++;
+ dbgline[i] = (i && !(i % 12)) ? '-' : ' ';
+ i++;
+ dbgline[i++] = hexdigit[(c >> 4) & 0x0f];
+ dbgline[i++] = hexdigit[c & 0x0f];
+ }
+ dbgline[i] = '\0';
+ dbg(level, "%s:%s", tag, dbgline);
+#endif
+}
+
+/*============================================================================*/
+
+/* bytewise HDLC bitstuffing via table lookup
+ * lookup table: 5 subtables for 0..4 preceding consecutive '1' bits
+ * index: 256*(number of preceding '1' bits) + (next byte to stuff)
+ * value: bit 9.. 0 = result bits
+ * bit 12..10 = number of trailing '1' bits in result
+ * bit 14..13 = number of bits added by stuffing
+ */
+static u16 stufftab[5 * 256] = {
+// previous 1s = 0:
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x205f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x209f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20df,
+ 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x048f,
+ 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x251f,
+ 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x04af,
+ 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x255f,
+ 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x08cf,
+ 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x299f,
+ 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef,
+ 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf,
+
+// previous 1s = 1:
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x206f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x208f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20af,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20cf,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20ef,
+ 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x250f,
+ 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x252f,
+ 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x254f,
+ 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x256f,
+ 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x298f,
+ 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29af,
+ 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf,
+ 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef,
+
+// previous 1s = 2:
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x2067, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x2077,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x2087, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x2097,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x20a7, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20b7,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x20c7, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20d7,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x20e7, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20f7,
+ 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x2507, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x2517,
+ 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x2527, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x2537,
+ 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x2547, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x2557,
+ 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x2567, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x2577,
+ 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x2987, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x2997,
+ 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x29a7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29b7,
+ 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7,
+ 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7,
+
+// previous 1s = 3:
+ 0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b,
+ 0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b,
+ 0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b,
+ 0x0030, 0x0031, 0x0032, 0x2063, 0x0034, 0x0035, 0x0036, 0x206b, 0x0038, 0x0039, 0x003a, 0x2073, 0x003c, 0x003d, 0x203e, 0x207b,
+ 0x0040, 0x0041, 0x0042, 0x2083, 0x0044, 0x0045, 0x0046, 0x208b, 0x0048, 0x0049, 0x004a, 0x2093, 0x004c, 0x004d, 0x004e, 0x209b,
+ 0x0050, 0x0051, 0x0052, 0x20a3, 0x0054, 0x0055, 0x0056, 0x20ab, 0x0058, 0x0059, 0x005a, 0x20b3, 0x005c, 0x005d, 0x005e, 0x20bb,
+ 0x0060, 0x0061, 0x0062, 0x20c3, 0x0064, 0x0065, 0x0066, 0x20cb, 0x0068, 0x0069, 0x006a, 0x20d3, 0x006c, 0x006d, 0x006e, 0x20db,
+ 0x0070, 0x0071, 0x0072, 0x20e3, 0x0074, 0x0075, 0x0076, 0x20eb, 0x0078, 0x0079, 0x007a, 0x20f3, 0x207c, 0x207d, 0x20be, 0x40fb,
+ 0x0480, 0x0481, 0x0482, 0x2503, 0x0484, 0x0485, 0x0486, 0x250b, 0x0488, 0x0489, 0x048a, 0x2513, 0x048c, 0x048d, 0x048e, 0x251b,
+ 0x0490, 0x0491, 0x0492, 0x2523, 0x0494, 0x0495, 0x0496, 0x252b, 0x0498, 0x0499, 0x049a, 0x2533, 0x049c, 0x049d, 0x049e, 0x253b,
+ 0x04a0, 0x04a1, 0x04a2, 0x2543, 0x04a4, 0x04a5, 0x04a6, 0x254b, 0x04a8, 0x04a9, 0x04aa, 0x2553, 0x04ac, 0x04ad, 0x04ae, 0x255b,
+ 0x04b0, 0x04b1, 0x04b2, 0x2563, 0x04b4, 0x04b5, 0x04b6, 0x256b, 0x04b8, 0x04b9, 0x04ba, 0x2573, 0x04bc, 0x04bd, 0x253e, 0x257b,
+ 0x08c0, 0x08c1, 0x08c2, 0x2983, 0x08c4, 0x08c5, 0x08c6, 0x298b, 0x08c8, 0x08c9, 0x08ca, 0x2993, 0x08cc, 0x08cd, 0x08ce, 0x299b,
+ 0x08d0, 0x08d1, 0x08d2, 0x29a3, 0x08d4, 0x08d5, 0x08d6, 0x29ab, 0x08d8, 0x08d9, 0x08da, 0x29b3, 0x08dc, 0x08dd, 0x08de, 0x29bb,
+ 0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb,
+ 0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb,
+
+// previous 1s = 4:
+ 0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d,
+ 0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d,
+ 0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d,
+ 0x0030, 0x2061, 0x0032, 0x2065, 0x0034, 0x2069, 0x0036, 0x206d, 0x0038, 0x2071, 0x003a, 0x2075, 0x003c, 0x2079, 0x203e, 0x407d,
+ 0x0040, 0x2081, 0x0042, 0x2085, 0x0044, 0x2089, 0x0046, 0x208d, 0x0048, 0x2091, 0x004a, 0x2095, 0x004c, 0x2099, 0x004e, 0x209d,
+ 0x0050, 0x20a1, 0x0052, 0x20a5, 0x0054, 0x20a9, 0x0056, 0x20ad, 0x0058, 0x20b1, 0x005a, 0x20b5, 0x005c, 0x20b9, 0x005e, 0x20bd,
+ 0x0060, 0x20c1, 0x0062, 0x20c5, 0x0064, 0x20c9, 0x0066, 0x20cd, 0x0068, 0x20d1, 0x006a, 0x20d5, 0x006c, 0x20d9, 0x006e, 0x20dd,
+ 0x0070, 0x20e1, 0x0072, 0x20e5, 0x0074, 0x20e9, 0x0076, 0x20ed, 0x0078, 0x20f1, 0x007a, 0x20f5, 0x207c, 0x40f9, 0x20be, 0x417d,
+ 0x0480, 0x2501, 0x0482, 0x2505, 0x0484, 0x2509, 0x0486, 0x250d, 0x0488, 0x2511, 0x048a, 0x2515, 0x048c, 0x2519, 0x048e, 0x251d,
+ 0x0490, 0x2521, 0x0492, 0x2525, 0x0494, 0x2529, 0x0496, 0x252d, 0x0498, 0x2531, 0x049a, 0x2535, 0x049c, 0x2539, 0x049e, 0x253d,
+ 0x04a0, 0x2541, 0x04a2, 0x2545, 0x04a4, 0x2549, 0x04a6, 0x254d, 0x04a8, 0x2551, 0x04aa, 0x2555, 0x04ac, 0x2559, 0x04ae, 0x255d,
+ 0x04b0, 0x2561, 0x04b2, 0x2565, 0x04b4, 0x2569, 0x04b6, 0x256d, 0x04b8, 0x2571, 0x04ba, 0x2575, 0x04bc, 0x2579, 0x253e, 0x467d,
+ 0x08c0, 0x2981, 0x08c2, 0x2985, 0x08c4, 0x2989, 0x08c6, 0x298d, 0x08c8, 0x2991, 0x08ca, 0x2995, 0x08cc, 0x2999, 0x08ce, 0x299d,
+ 0x08d0, 0x29a1, 0x08d2, 0x29a5, 0x08d4, 0x29a9, 0x08d6, 0x29ad, 0x08d8, 0x29b1, 0x08da, 0x29b5, 0x08dc, 0x29b9, 0x08de, 0x29bd,
+ 0x0ce0, 0x2dc1, 0x0ce2, 0x2dc5, 0x0ce4, 0x2dc9, 0x0ce6, 0x2dcd, 0x0ce8, 0x2dd1, 0x0cea, 0x2dd5, 0x0cec, 0x2dd9, 0x0cee, 0x2ddd,
+ 0x10f0, 0x31e1, 0x10f2, 0x31e5, 0x10f4, 0x31e9, 0x10f6, 0x31ed, 0x20f8, 0x41f1, 0x20fa, 0x41f5, 0x257c, 0x46f9, 0x29be, 0x4b7d
+};
+
+/* hdlc_bitstuff_byte
+ * perform HDLC bitstuffing for one input byte (8 bits, LSB first)
+ * parameters:
+ * cin input byte
+ * ones number of trailing '1' bits in result before this step
+ * iwb pointer to output buffer structure (write semaphore must be held)
+ * return value:
+ * number of trailing '1' bits in result after this step
+ */
+
+static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin,
+ int ones)
+{
+ u16 stuff;
+ int shiftinc, newones;
+
+ /* get stuffing information for input byte
+ * value: bit 9.. 0 = result bits
+ * bit 12..10 = number of trailing '1' bits in result
+ * bit 14..13 = number of bits added by stuffing
+ */
+ stuff = stufftab[256 * ones + cin];
+ shiftinc = (stuff >> 13) & 3;
+ newones = (stuff >> 10) & 7;
+ stuff &= 0x3ff;
+
+ /* append stuffed byte to output stream */
+ isowbuf_putbits(iwb, stuff, 8 + shiftinc);
+ return newones;
+}
+
+/* hdlc_buildframe
+ * Perform HDLC framing with bitstuffing on a byte buffer
+ * The input buffer is regarded as a sequence of bits, starting with the least
+ * significant bit of the first byte and ending with the most significant bit
+ * of the last byte. A 16 bit FCS is appended as defined by RFC 1662.
+ * Whenever five consecutive '1' bits appear in the resulting bit sequence, a
+ * '0' bit is inserted after them.
+ * The resulting bit string and a closing flag pattern (PPP_FLAG, '01111110')
+ * are appended to the output buffer starting at the given bit position, which
+ * is assumed to already contain a leading flag.
+ * The output buffer must have sufficient length; count + count/5 + 6 bytes
+ * starting at *out are safe and are verified to be present.
+ * parameters:
+ * in input buffer
+ * count number of bytes in input buffer
+ * iwb pointer to output buffer structure (write semaphore must be held)
+ * return value:
+ * position of end of packet in output buffer on success,
+ * -EAGAIN if write semaphore busy or buffer full
+ */
+
+static inline int hdlc_buildframe(struct isowbuf_t *iwb,
+ unsigned char *in, int count)
+{
+ int ones;
+ u16 fcs;
+ int end;
+ unsigned char c;
+
+ if (isowbuf_freebytes(iwb) < count + count / 5 + 6 ||
+ !isowbuf_startwrite(iwb)) {
+ dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN",
+ __func__, isowbuf_freebytes(iwb));
+ return -EAGAIN;
+ }
+
+ dump_bytes(DEBUG_STREAM, "snd data", in, count);
+
+ /* bitstuff and checksum input data */
+ fcs = PPP_INITFCS;
+ ones = 0;
+ while (count-- > 0) {
+ c = *in++;
+ ones = hdlc_bitstuff_byte(iwb, c, ones);
+ fcs = crc_ccitt_byte(fcs, c);
+ }
+
+ /* bitstuff and append FCS (complemented, least significant byte first) */
+ fcs ^= 0xffff;
+ ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones);
+ ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 0x00ff, ones);
+
+ /* put closing flag and repeat byte for flag idle */
+ isowbuf_putflag(iwb);
+ end = isowbuf_donewrite(iwb);
+ dump_bytes(DEBUG_STREAM_DUMP, "isowbuf", iwb->data, end + 1);
+ return end;
+}
+
+/* trans_buildframe
+ * Append a block of 'transparent' data to the output buffer,
+ * inverting the bytes.
+ * The output buffer must have sufficient length; count bytes
+ * starting at *out are safe and are verified to be present.
+ * parameters:
+ * in input buffer
+ * count number of bytes in input buffer
+ * iwb pointer to output buffer structure (write semaphore must be held)
+ * return value:
+ * position of end of packet in output buffer on success,
+ * -EAGAIN if write semaphore busy or buffer full
+ */
+
+static inline int trans_buildframe(struct isowbuf_t *iwb,
+ unsigned char *in, int count)
+{
+ int write;
+ unsigned char c;
+
+ if (unlikely(count <= 0))
+ return atomic_read(&iwb->write); /* better ideas? */
+
+ if (isowbuf_freebytes(iwb) < count ||
+ !isowbuf_startwrite(iwb)) {
+ dbg(DEBUG_ISO, "can't put %d bytes", count);
+ return -EAGAIN;
+ }
+
+ dbg(DEBUG_STREAM, "put %d bytes", count);
+ write = atomic_read(&iwb->write);
+ do {
+ c = gigaset_invtab[*in++];
+ iwb->data[write++] = c;
+ write %= BAS_OUTBUFSIZE;
+ } while (--count > 0);
+ atomic_set(&iwb->write, write);
+ iwb->idle = c;
+
+ return isowbuf_donewrite(iwb);
+}
+
+int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len)
+{
+ int result;
+
+ switch (bcs->proto2) {
+ case ISDN_PROTO_L2_HDLC:
+ result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len);
+ dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", __func__, len, result);
+ break;
+ default: /* assume transparent */
+ result = trans_buildframe(bcs->hw.bas->isooutbuf, in, len);
+ dbg(DEBUG_ISO, "%s: %d bytes trans -> %d", __func__, len, result);
+ }
+ return result;
+}
+
+/* hdlc_putbyte
+ * append byte c to current skb of B channel structure *bcs, updating fcs
+ */
+static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
+{
+ bcs->fcs = crc_ccitt_byte(bcs->fcs, c);
+ if (unlikely(bcs->skb == NULL)) {
+ /* skipping */
+ return;
+ }
+ if (unlikely(bcs->skb->len == SBUFSIZE)) {
+ warn("received oversized packet discarded");
+ bcs->hw.bas->giants++;
+ dev_kfree_skb_any(bcs->skb);
+ bcs->skb = NULL;
+ return;
+ }
+ *gigaset_skb_put_quick(bcs->skb, 1) = c;
+}
+
+/* hdlc_flush
+ * drop partial HDLC data packet
+ */
+static inline void hdlc_flush(struct bc_state *bcs)
+{
+ /* clear skb or allocate new if not skipping */
+ if (likely(bcs->skb != NULL))
+ skb_trim(bcs->skb, 0);
+ else if (!bcs->ignore) {
+ if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
+ skb_reserve(bcs->skb, HW_HDR_LEN);
+ else
+ err("could not allocate skb");
+ }
+
+ /* reset packet state */
+ bcs->fcs = PPP_INITFCS;
+}
+
+/* hdlc_done
+ * process completed HDLC data packet
+ */
+static inline void hdlc_done(struct bc_state *bcs)
+{
+ struct sk_buff *procskb;
+
+ if (unlikely(bcs->ignore)) {
+ bcs->ignore--;
+ hdlc_flush(bcs);
+ return;
+ }
+
+ if ((procskb = bcs->skb) == NULL) {
+ /* previous error */
+ dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
+ gigaset_rcv_error(NULL, bcs->cs, bcs);
+ } else if (procskb->len < 2) {
+ notice("received short frame (%d octets)", procskb->len);
+ bcs->hw.bas->runts++;
+ gigaset_rcv_error(procskb, bcs->cs, bcs);
+ } else if (bcs->fcs != PPP_GOODFCS) {
+ notice("frame check error (0x%04x)", bcs->fcs);
+ bcs->hw.bas->fcserrs++;
+ gigaset_rcv_error(procskb, bcs->cs, bcs);
+ } else {
+ procskb->len -= 2; /* subtract FCS */
+ procskb->tail -= 2;
+ dbg(DEBUG_ISO,
+ "%s: good frame (%d octets)", __func__, procskb->len);
+ dump_bytes(DEBUG_STREAM,
+ "rcv data", procskb->data, procskb->len);
+ bcs->hw.bas->goodbytes += procskb->len;
+ gigaset_rcv_skb(procskb, bcs->cs, bcs);
+ }
+
+ if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
+ skb_reserve(bcs->skb, HW_HDR_LEN);
+ else
+ err("could not allocate skb");
+ bcs->fcs = PPP_INITFCS;
+}
+
+/* hdlc_frag
+ * drop HDLC data packet with non-integral last byte
+ */
+static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits)
+{
+ if (unlikely(bcs->ignore)) {
+ bcs->ignore--;
+ hdlc_flush(bcs);
+ return;
+ }
+
+ notice("received partial byte (%d bits)", inbits);
+ bcs->hw.bas->alignerrs++;
+ gigaset_rcv_error(bcs->skb, bcs->cs, bcs);
+
+ if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
+ skb_reserve(bcs->skb, HW_HDR_LEN);
+ else
+ err("could not allocate skb");
+ bcs->fcs = PPP_INITFCS;
+}
+
+/* bit counts lookup table for HDLC bit unstuffing
+ * index: input byte
+ * value: bit 0..3 = number of consecutive '1' bits starting from LSB
+ * bit 4..6 = number of consecutive '1' bits starting from MSB
+ * (replacing 8 by 7 to make it fit; the algorithm won't care)
+ * bit 7 set if there are 5 or more "interior" consecutive '1' bits
+ */
+static unsigned char bitcounts[256] = {
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x80, 0x06,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x80, 0x81, 0x80, 0x07,
+ 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14,
+ 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x15,
+ 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14,
+ 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x90, 0x16,
+ 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x24,
+ 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x25,
+ 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x34,
+ 0x40, 0x41, 0x40, 0x42, 0x40, 0x41, 0x40, 0x43, 0x50, 0x51, 0x50, 0x52, 0x60, 0x61, 0x70, 0x78
+};
+
+/* hdlc_unpack
+ * perform HDLC frame processing (bit unstuffing, flag detection, FCS calculation)
+ * on a sequence of received data bytes (8 bits each, LSB first)
+ * pass on successfully received, complete frames as SKBs via gigaset_rcv_skb
+ * notify of errors via gigaset_rcv_error
+ * tally frames, errors etc. in BC structure counters
+ * parameters:
+ * src received data
+ * count number of received bytes
+ * bcs receiving B channel structure
+ */
+static inline void hdlc_unpack(unsigned char *src, unsigned count,
+ struct bc_state *bcs)
+{
+ struct bas_bc_state *ubc;
+ int inputstate;
+ unsigned seqlen, inbyte, inbits;
+
+ IFNULLRET(bcs);
+ ubc = bcs->hw.bas;
+ IFNULLRET(ubc);
+
+ /* load previous state:
+ * inputstate = set of flag bits:
+ * - INS_flag_hunt: no complete opening flag received since connection setup or last abort
+ * - INS_have_data: at least one complete data byte received since last flag
+ * seqlen = number of consecutive '1' bits in last 7 input stream bits (0..7)
+ * inbyte = accumulated partial data byte (if !INS_flag_hunt)
+ * inbits = number of valid bits in inbyte, starting at LSB (0..6)
+ */
+ inputstate = bcs->inputstate;
+ seqlen = ubc->seqlen;
+ inbyte = ubc->inbyte;
+ inbits = ubc->inbits;
+
+ /* bit unstuffing a byte a time
+ * Take your time to understand this; it's straightforward but tedious.
+ * The "bitcounts" lookup table is used to speed up the counting of
+ * leading and trailing '1' bits.
+ */
+ while (count--) {
+ unsigned char c = *src++;
+ unsigned char tabentry = bitcounts[c];
+ unsigned lead1 = tabentry & 0x0f;
+ unsigned trail1 = (tabentry >> 4) & 0x0f;
+
+ seqlen += lead1;
+
+ if (unlikely(inputstate & INS_flag_hunt)) {
+ if (c == PPP_FLAG) {
+ /* flag-in-one */
+ inputstate &= ~(INS_flag_hunt | INS_have_data);
+ inbyte = 0;
+ inbits = 0;
+ } else if (seqlen == 6 && trail1 != 7) {
+ /* flag completed & not followed by abort */
+ inputstate &= ~(INS_flag_hunt | INS_have_data);
+ inbyte = c >> (lead1 + 1);
+ inbits = 7 - lead1;
+ if (trail1 >= 8) {
+ /* interior stuffing: omitting the MSB handles most cases */
+ inbits--;
+ /* correct the incorrectly handled cases individually */
+ switch (c) {
+ case 0xbe:
+ inbyte = 0x3f;
+ break;
+ }
+ }
+ }
+ /* else: continue flag-hunting */
+ } else if (likely(seqlen < 5 && trail1 < 7)) {
+ /* streamlined case: 8 data bits, no stuffing */
+ inbyte |= c << inbits;
+ hdlc_putbyte(inbyte & 0xff, bcs);
+ inputstate |= INS_have_data;
+ inbyte >>= 8;
+ /* inbits unchanged */
+ } else if (likely(seqlen == 6 && inbits == 7 - lead1 &&
+ trail1 + 1 == inbits &&
+ !(inputstate & INS_have_data))) {
+ /* streamlined case: flag idle - state unchanged */
+ } else if (unlikely(seqlen > 6)) {
+ /* abort sequence */
+ ubc->aborts++;
+ hdlc_flush(bcs);
+ inputstate |= INS_flag_hunt;
+ } else if (seqlen == 6) {
+ /* closing flag, including (6 - lead1) '1's and one '0' from inbits */
+ if (inbits > 7 - lead1) {
+ hdlc_frag(bcs, inbits + lead1 - 7);
+ inputstate &= ~INS_have_data;
+ } else {
+ if (inbits < 7 - lead1)
+ ubc->stolen0s ++;
+ if (inputstate & INS_have_data) {
+ hdlc_done(bcs);
+ inputstate &= ~INS_have_data;
+ }
+ }
+
+ if (c == PPP_FLAG) {
+ /* complete flag, LSB overlaps preceding flag */
+ ubc->shared0s ++;
+ inbits = 0;
+ inbyte = 0;
+ } else if (trail1 != 7) {
+ /* remaining bits */
+ inbyte = c >> (lead1 + 1);
+ inbits = 7 - lead1;
+ if (trail1 >= 8) {
+ /* interior stuffing: omitting the MSB handles most cases */
+ inbits--;
+ /* correct the incorrectly handled cases individually */
+ switch (c) {
+ case 0xbe:
+ inbyte = 0x3f;
+ break;
+ }
+ }
+ } else {
+ /* abort sequence follows, skb already empty anyway */
+ ubc->aborts++;
+ inputstate |= INS_flag_hunt;
+ }
+ } else { /* (seqlen < 6) && (seqlen == 5 || trail1 >= 7) */
+
+ if (c == PPP_FLAG) {
+ /* complete flag */
+ if (seqlen == 5)
+ ubc->stolen0s++;
+ if (inbits) {
+ hdlc_frag(bcs, inbits);
+ inbits = 0;
+ inbyte = 0;
+ } else if (inputstate & INS_have_data)
+ hdlc_done(bcs);
+ inputstate &= ~INS_have_data;
+ } else if (trail1 == 7) {
+ /* abort sequence */
+ ubc->aborts++;
+ hdlc_flush(bcs);
+ inputstate |= INS_flag_hunt;
+ } else {
+ /* stuffed data */
+ if (trail1 < 7) { /* => seqlen == 5 */
+ /* stuff bit at position lead1, no interior stuffing */
+ unsigned char mask = (1 << lead1) - 1;
+ c = (c & mask) | ((c & ~mask) >> 1);
+ inbyte |= c << inbits;
+ inbits += 7;
+ } else if (seqlen < 5) { /* trail1 >= 8 */
+ /* interior stuffing: omitting the MSB handles most cases */
+ /* correct the incorrectly handled cases individually */
+ switch (c) {
+ case 0xbe:
+ c = 0x7e;
+ break;
+ }
+ inbyte |= c << inbits;
+ inbits += 7;
+ } else { /* seqlen == 5 && trail1 >= 8 */
+
+ /* stuff bit at lead1 *and* interior stuffing */
+ switch (c) { /* unstuff individually */
+ case 0x7d:
+ c = 0x3f;
+ break;
+ case 0xbe:
+ c = 0x3f;
+ break;
+ case 0x3e:
+ c = 0x1f;
+ break;
+ case 0x7c:
+ c = 0x3e;
+ break;
+ }
+ inbyte |= c << inbits;
+ inbits += 6;
+ }
+ if (inbits >= 8) {
+ inbits -= 8;
+ hdlc_putbyte(inbyte & 0xff, bcs);
+ inputstate |= INS_have_data;
+ inbyte >>= 8;
+ }
+ }
+ }
+ seqlen = trail1 & 7;
+ }
+
+ /* save new state */
+ bcs->inputstate = inputstate;
+ ubc->seqlen = seqlen;
+ ubc->inbyte = inbyte;
+ ubc->inbits = inbits;
+}
+
+/* trans_receive
+ * pass on received USB frame transparently as SKB via gigaset_rcv_skb
+ * invert bytes
+ * tally frames, errors etc. in BC structure counters
+ * parameters:
+ * src received data
+ * count number of received bytes
+ * bcs receiving B channel structure
+ */
+static inline void trans_receive(unsigned char *src, unsigned count,
+ struct bc_state *bcs)
+{
+ struct sk_buff *skb;
+ int dobytes;
+ unsigned char *dst;
+
+ if (unlikely(bcs->ignore)) {
+ bcs->ignore--;
+ hdlc_flush(bcs);
+ return;
+ }
+ if (unlikely((skb = bcs->skb) == NULL)) {
+ bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
+ if (!skb) {
+ err("could not allocate skb");
+ return;
+ }
+ skb_reserve(skb, HW_HDR_LEN);
+ }
+ bcs->hw.bas->goodbytes += skb->len;
+ dobytes = TRANSBUFSIZE - skb->len;
+ while (count > 0) {
+ dst = skb_put(skb, count < dobytes ? count : dobytes);
+ while (count > 0 && dobytes > 0) {
+ *dst++ = gigaset_invtab[*src++];
+ count--;
+ dobytes--;
+ }
+ if (dobytes == 0) {
+ gigaset_rcv_skb(skb, bcs->cs, bcs);
+ bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
+ if (!skb) {
+ err("could not allocate skb");
+ return;
+ }
+ skb_reserve(bcs->skb, HW_HDR_LEN);
+ dobytes = TRANSBUFSIZE;
+ }
+ }
+}
+
+void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs)
+{
+ switch (bcs->proto2) {
+ case ISDN_PROTO_L2_HDLC:
+ hdlc_unpack(src, count, bcs);
+ break;
+ default: /* assume transparent */
+ trans_receive(src, count, bcs);
+ }
+}
+
+/* == data input =========================================================== */
+
+static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf)
+{
+ struct cardstate *cs = inbuf->cs;
+ unsigned cbytes = cs->cbytes;
+
+ while (numbytes--) {
+ /* copy next character, check for end of line */
+ switch (cs->respdata[cbytes] = *src++) {
+ case '\r':
+ case '\n':
+ /* end of line */
+ dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
+ __func__, cbytes);
+ cs->cbytes = cbytes;
+ gigaset_handle_modem_response(cs);
+ cbytes = 0;
+ break;
+ default:
+ /* advance in line buffer, checking for overflow */
+ if (cbytes < MAX_RESP_SIZE - 1)
+ cbytes++;
+ else
+ warn("response too large");
+ }
+ }
+
+ /* save state */
+ cs->cbytes = cbytes;
+}
+
+
+/* process a block of data received through the control channel
+ */
+void gigaset_isoc_input(struct inbuf_t *inbuf)
+{
+ struct cardstate *cs = inbuf->cs;
+ unsigned tail, head, numbytes;
+ unsigned char *src;
+
+ head = atomic_read(&inbuf->head);
+ while (head != (tail = atomic_read(&inbuf->tail))) {
+ dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
+ if (head > tail)
+ tail = RBUFSIZE;
+ src = inbuf->data + head;
+ numbytes = tail - head;
+ dbg(DEBUG_INTR, "processing %u bytes", numbytes);
+
+ if (atomic_read(&cs->mstate) == MS_LOCKED) {
+ gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
+ numbytes, src, 0);
+ gigaset_if_receive(inbuf->cs, src, numbytes);
+ } else {
+ gigaset_dbg_buffer(DEBUG_CMD, "received response",
+ numbytes, src, 0);
+ cmd_loop(src, numbytes, inbuf);
+ }
+
+ head += numbytes;
+ if (head == RBUFSIZE)
+ head = 0;
+ dbg(DEBUG_INTR, "setting head to %u", head);
+ atomic_set(&inbuf->head, head);
+ }
+}
+
+
+/* == data output ========================================================== */
+
+/* gigaset_send_skb
+ * called by common.c to queue an skb for sending
+ * and start transmission if necessary
+ * parameters:
+ * B Channel control structure
+ * skb
+ * return value:
+ * number of bytes accepted for sending
+ * (skb->len if ok, 0 if out of buffer space)
+ * or error code (< 0, eg. -EINVAL)
+ */
+int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb)
+{
+ int len;
+
+ IFNULLRETVAL(bcs, -EFAULT);
+ IFNULLRETVAL(skb, -EFAULT);
+ len = skb->len;
+
+ skb_queue_tail(&bcs->squeue, skb);
+ dbg(DEBUG_ISO,
+ "%s: skb queued, qlen=%d", __func__, skb_queue_len(&bcs->squeue));
+
+ /* tasklet submits URB if necessary */
+ tasklet_schedule(&bcs->hw.bas->sent_tasklet);
+
+ return len; /* ok so far */
+}
diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c
new file mode 100644
index 00000000000..c6915fa2be6
--- /dev/null
+++ b/drivers/isdn/gigaset/proc.c
@@ -0,0 +1,81 @@
+/*
+ * Stuff used by all variants of the driver
+ *
+ * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>,
+ * Hansjoerg Lipp <hjlipp@web.de>,
+ * Tilman Schmidt <tilman@imap.cc>.
+ *
+ * =====================================================================
+ * 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.
+ * =====================================================================
+ * ToDo: ...
+ * =====================================================================
+ * Version: $Id: proc.c,v 1.5.2.13 2006/02/04 18:28:16 hjlipp Exp $
+ * =====================================================================
+ */
+
+#include "gigaset.h"
+#include <linux/ctype.h>
+
+static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct cardstate *cs = usb_get_intfdata(intf);
+ return sprintf(buf, "%d\n", atomic_read(&cs->cidmode)); // FIXME use scnprintf for 13607 bit architectures (if PAGE_SIZE==4096)
+}
+
+static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct cardstate *cs = usb_get_intfdata(intf);
+ long int value;
+ char *end;
+
+ value = simple_strtol(buf, &end, 0);
+ while (*end)
+ if (!isspace(*end++))
+ return -EINVAL;
+ if (value < 0 || value > 1)
+ return -EINVAL;
+
+ if (down_interruptible(&cs->sem))
+ return -ERESTARTSYS; // FIXME -EINTR?
+
+ cs->waiting = 1;
+ if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE,
+ NULL, value, NULL)) {
+ cs->waiting = 0;
+ up(&cs->sem);
+ return -ENOMEM;
+ }
+
+ dbg(DEBUG_CMD, "scheduling PROC_CIDMODE");
+ gigaset_schedule_event(cs);
+
+ wait_event(cs->waitqueue, !cs->waiting);
+
+ up(&cs->sem);
+
+ return count;
+}
+
+static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode);
+
+/* free sysfs for device */
+void gigaset_free_dev_sysfs(struct usb_interface *interface)
+{
+ dbg(DEBUG_INIT, "removing sysfs entries");
+ device_remove_file(&interface->dev, &dev_attr_cidmode);
+}
+EXPORT_SYMBOL_GPL(gigaset_free_dev_sysfs);
+
+/* initialize sysfs for device */
+void gigaset_init_dev_sysfs(struct usb_interface *interface)
+{
+ dbg(DEBUG_INIT, "setting up sysfs");
+ device_create_file(&interface->dev, &dev_attr_cidmode);
+}
+EXPORT_SYMBOL_GPL(gigaset_init_dev_sysfs);
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
new file mode 100644
index 00000000000..323fc7349de
--- /dev/null
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -0,0 +1,1008 @@
+/*
+ * USB driver for Gigaset 307x directly or using M105 Data.
+ *
+ * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>
+ * and Hansjoerg Lipp <hjlipp@web.de>.
+ *
+ * This driver was derived from the USB skeleton driver by
+ * Greg Kroah-Hartman <greg@kroah.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.
+ * =====================================================================
+ * ToDo: ...
+ * =====================================================================
+ * Version: $Id: usb-gigaset.c,v 1.85.4.18 2006/02/04 18:28:16 hjlipp Exp $
+ * =====================================================================
+ */
+
+#include "gigaset.h"
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+/* Version Information */
+#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_DESC "USB Driver for Gigaset 307x using M105"
+
+/* Module parameters */
+
+static int startmode = SM_ISDN;
+static int cidmode = 1;
+
+module_param(startmode, int, S_IRUGO);
+module_param(cidmode, int, S_IRUGO);
+MODULE_PARM_DESC(startmode, "start in isdn4linux mode");
+MODULE_PARM_DESC(cidmode, "Call-ID mode");
+
+#define GIGASET_MINORS 1
+#define GIGASET_MINOR 8
+#define GIGASET_MODULENAME "usb_gigaset"
+#define GIGASET_DEVFSNAME "gig/usb/"
+#define GIGASET_DEVNAME "ttyGU"
+
+#define IF_WRITEBUF 2000 //FIXME // WAKEUP_CHARS: 256
+
+/* Values for the Gigaset M105 Data */
+#define USB_M105_VENDOR_ID 0x0681
+#define USB_M105_PRODUCT_ID 0x0009
+
+/* table of devices that work with this driver */
+static struct usb_device_id gigaset_table [] = {
+ { USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, gigaset_table);
+
+/* Get a minor range for your devices from the usb maintainer */
+#define USB_SKEL_MINOR_BASE 200
+
+
+/*
+ * Control requests (empty fields: 00)
+ *
+ * RT|RQ|VALUE|INDEX|LEN |DATA
+ * In:
+ * C1 08 01
+ * Get flags (1 byte). Bits: 0=dtr,1=rts,3-7:?
+ * C1 0F ll ll
+ * Get device information/status (llll: 0x200 and 0x40 seen).
+ * Real size: I only saw MIN(llll,0x64).
+ * Contents: seems to be always the same...
+ * offset 0x00: Length of this structure (0x64) (len: 1,2,3 bytes)
+ * offset 0x3c: String (16 bit chars): "MCCI USB Serial V2.0"
+ * rest: ?
+ * Out:
+ * 41 11
+ * Initialize/reset device ?
+ * 41 00 xx 00
+ * ? (xx=00 or 01; 01 on start, 00 on close)
+ * 41 07 vv mm
+ * Set/clear flags vv=value, mm=mask (see RQ 08)
+ * 41 12 xx
+ * Used before the following configuration requests are issued
+ * (with xx=0x0f). I've seen other values<0xf, though.
+ * 41 01 xx xx
+ * Set baud rate. xxxx=ceil(0x384000/rate)=trunc(0x383fff/rate)+1.
+ * 41 03 ps bb
+ * Set byte size and parity. p: 0x20=even,0x10=odd,0x00=no parity
+ * [ 0x30: m, 0x40: s ]
+ * [s: 0: 1 stop bit; 1: 1.5; 2: 2]
+ * bb: bits/byte (seen 7 and 8)
+ * 41 13 -- -- -- -- 10 00 ww 00 00 00 xx 00 00 00 yy 00 00 00 zz 00 00 00
+ * ??
+ * Initialization: 01, 40, 00, 00
+ * Open device: 00 40, 00, 00
+ * yy and zz seem to be equal, either 0x00 or 0x0a
+ * (ww,xx) pairs seen: (00,00), (00,40), (01,40), (09,80), (19,80)
+ * 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13
+ * Used after every "configuration sequence" (RQ 12, RQs 01/03/13).
+ * xx is usually 0x00 but was 0x7e before starting data transfer
+ * in unimodem mode. So, this might be an array of characters that need
+ * special treatment ("commit all bufferd data"?), 11=^Q, 13=^S.
+ *
+ * Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two
+ * flags per packet.
+ */
+
+static int gigaset_probe(struct usb_interface *interface,
+ const struct usb_device_id *id);
+static void gigaset_disconnect(struct usb_interface *interface);
+
+static struct gigaset_driver *driver = NULL;
+static struct cardstate *cardstate = NULL;
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver gigaset_usb_driver = {
+ .name = GIGASET_MODULENAME,
+ .probe = gigaset_probe,
+ .disconnect = gigaset_disconnect,
+ .id_table = gigaset_table,
+};
+
+struct usb_cardstate {
+ struct usb_device *udev; /* save off the usb device pointer */
+ struct usb_interface *interface; /* the interface for this device */
+ atomic_t busy; /* bulk output in progress */
+
+ /* Output buffer for commands (M105: and data)*/
+ unsigned char *bulk_out_buffer; /* the buffer to send data */
+ int bulk_out_size; /* the size of the send buffer */
+ __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
+ struct urb *bulk_out_urb; /* the urb used to transmit data */
+
+ /* Input buffer for command responses (M105: and data)*/
+ int rcvbuf_size; /* the size of the receive buffer */
+ struct urb *read_urb; /* the urb used to receive data */
+ __u8 int_in_endpointAddr; /* the address of the bulk in endpoint */
+
+ char bchars[6]; /* req. 0x19 */
+};
+
+struct usb_bc_state {};
+
+static inline unsigned tiocm_to_gigaset(unsigned state)
+{
+ return ((state & TIOCM_DTR) ? 1 : 0) | ((state & TIOCM_RTS) ? 2 : 0);
+}
+
+#ifdef CONFIG_GIGASET_UNDOCREQ
+/* WARNING: EXPERIMENTAL! */
+static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
+ unsigned new_state)
+{
+ unsigned mask, val;
+ int r;
+
+ mask = tiocm_to_gigaset(old_state ^ new_state);
+ val = tiocm_to_gigaset(new_state);
+
+ dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask);
+ r = usb_control_msg(cs->hw.usb->udev,
+ usb_sndctrlpipe(cs->hw.usb->udev, 0), 7, 0x41,
+ (val & 0xff) | ((mask & 0xff) << 8), 0,
+ NULL, 0, 2000 /*timeout??*/); // don't use this in an interrupt/BH
+ if (r < 0)
+ return r;
+ //..
+ return 0;
+}
+
+static int set_value(struct cardstate *cs, u8 req, u16 val)
+{
+ int r, r2;
+
+ dbg(DEBUG_USBREQ, "request %02x (%04x)", (unsigned)req, (unsigned)val);
+ r = usb_control_msg(cs->hw.usb->udev,
+ usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x12, 0x41,
+ 0xf /*?*/, 0,
+ NULL, 0, 2000 /*?*/); /* no idea, what this does */
+ if (r < 0) {
+ err("error %d on request 0x12", -r);
+ return r;
+ }
+
+ r = usb_control_msg(cs->hw.usb->udev,
+ usb_sndctrlpipe(cs->hw.usb->udev, 0), req, 0x41,
+ val, 0,
+ NULL, 0, 2000 /*?*/);
+ if (r < 0)
+ err("error %d on request 0x%02x", -r, (unsigned)req);
+
+ r2 = usb_control_msg(cs->hw.usb->udev,
+ usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41,
+ 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/);
+ if (r2 < 0)
+ err("error %d on request 0x19", -r2);
+
+ return r < 0 ? r : (r2 < 0 ? r2 : 0);
+}
+
+/* WARNING: HIGHLY EXPERIMENTAL! */
+// don't use this in an interrupt/BH
+static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
+{
+ u16 val;
+ u32 rate;
+
+ cflag &= CBAUD;
+
+ switch (cflag) {
+ //FIXME more values?
+ case B300: rate = 300; break;
+ case B600: rate = 600; break;
+ case B1200: rate = 1200; break;
+ case B2400: rate = 2400; break;
+ case B4800: rate = 4800; break;
+ case B9600: rate = 9600; break;
+ case B19200: rate = 19200; break;
+ case B38400: rate = 38400; break;
+ case B57600: rate = 57600; break;
+ case B115200: rate = 115200; break;
+ default:
+ rate = 9600;
+ err("unsupported baudrate request 0x%x,"
+ " using default of B9600", cflag);
+ }
+
+ val = 0x383fff / rate + 1;
+
+ return set_value(cs, 1, val);
+}
+
+/* WARNING: HIGHLY EXPERIMENTAL! */
+// don't use this in an interrupt/BH
+static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
+{
+ u16 val = 0;
+
+ /* set the parity */
+ if (cflag & PARENB)
+ val |= (cflag & PARODD) ? 0x10 : 0x20;
+
+ /* set the number of data bits */
+ switch (cflag & CSIZE) {
+ case CS5:
+ val |= 5 << 8; break;
+ case CS6:
+ val |= 6 << 8; break;
+ case CS7:
+ val |= 7 << 8; break;
+ case CS8:
+ val |= 8 << 8; break;
+ default:
+ err("CSIZE was not CS5-CS8, using default of 8");
+ val |= 8 << 8;
+ break;
+ }
+
+ /* set the number of stop bits */
+ if (cflag & CSTOPB) {
+ if ((cflag & CSIZE) == CS5)
+ val |= 1; /* 1.5 stop bits */ //FIXME is this okay?
+ else
+ val |= 2; /* 2 stop bits */
+ }
+
+ return set_value(cs, 3, val);
+}
+
+#else
+static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
+ unsigned new_state)
+{
+ return -EINVAL;
+}
+
+static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
+{
+ return -EINVAL;
+}
+
+static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
+{
+ return -EINVAL;
+}
+#endif
+
+
+ /*================================================================================================================*/
+static int gigaset_init_bchannel(struct bc_state *bcs)
+{
+ /* nothing to do for M10x */
+ gigaset_bchannel_up(bcs);
+ return 0;
+}
+
+static int gigaset_close_bchannel(struct bc_state *bcs)
+{
+ /* nothing to do for M10x */
+ gigaset_bchannel_down(bcs);
+ return 0;
+}
+
+//void send_ack_to_LL(void *data);
+static int write_modem(struct cardstate *cs);
+static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb);
+
+
+/* Handling of send queue. If there is already a skb opened, put data to
+ * the transfer buffer by calling "write_modem". Otherwise take a new skb out of the queue.
+ * This function will be called by the ISR via "transmit_chars" (USB: B-Channel Bulk callback handler
+ * via immediate task queue) or by writebuf_from_LL if the LL wants to transmit data.
+ */
+static void gigaset_modem_fill(unsigned long data)
+{
+ struct cardstate *cs = (struct cardstate *) data;
+ struct bc_state *bcs = &cs->bcs[0]; /* only one channel */
+ struct cmdbuf_t *cb;
+ unsigned long flags;
+ int again;
+
+ dbg(DEBUG_OUTPUT, "modem_fill");
+
+ if (atomic_read(&cs->hw.usb->busy)) {
+ dbg(DEBUG_OUTPUT, "modem_fill: busy");
+ return;
+ }
+
+ do {
+ again = 0;
+ if (!bcs->tx_skb) { /* no skb is being sent */
+ spin_lock_irqsave(&cs->cmdlock, flags);
+ cb = cs->cmdbuf;
+ spin_unlock_irqrestore(&cs->cmdlock, flags);
+ if (cb) { /* commands to send? */
+ dbg(DEBUG_OUTPUT, "modem_fill: cb");
+ if (send_cb(cs, cb) < 0) {
+ dbg(DEBUG_OUTPUT,
+ "modem_fill: send_cb failed");
+ again = 1; /* no callback will be called! */
+ }
+ } else { /* skbs to send? */
+ bcs->tx_skb = skb_dequeue(&bcs->squeue);
+ if (bcs->tx_skb)
+ dbg(DEBUG_INTR,
+ "Dequeued skb (Adr: %lx)!",
+ (unsigned long) bcs->tx_skb);
+ }
+ }
+
+ if (bcs->tx_skb) {
+ dbg(DEBUG_OUTPUT, "modem_fill: tx_skb");
+ if (write_modem(cs) < 0) {
+ dbg(DEBUG_OUTPUT,
+ "modem_fill: write_modem failed");
+ // FIXME should we tell the LL?
+ again = 1; /* no callback will be called! */
+ }
+ }
+ } while (again);
+}
+
+/**
+ * gigaset_read_int_callback
+ *
+ * It is called if the data was received from the device. This is almost similiar to
+ * the interrupt service routine in the serial device.
+ */
+static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs)
+{
+ int resubmit = 0;
+ int r;
+ struct cardstate *cs;
+ unsigned numbytes;
+ unsigned char *src;
+ //unsigned long flags;
+ struct inbuf_t *inbuf;
+
+ IFNULLRET(urb);
+ inbuf = (struct inbuf_t *) urb->context;
+ IFNULLRET(inbuf);
+ //spin_lock_irqsave(&inbuf->lock, flags);
+ cs = inbuf->cs;
+ IFNULLGOTO(cs, exit);
+ IFNULLGOTO(cardstate, exit);
+
+ if (!atomic_read(&cs->connected)) {
+ err("%s: disconnected", __func__);
+ goto exit;
+ }
+
+ if (!urb->status) {
+ numbytes = urb->actual_length;
+
+ if (numbytes) {
+ src = inbuf->rcvbuf;
+ if (unlikely(*src))
+ warn("%s: There was no leading 0, but 0x%02x!",
+ __func__, (unsigned) *src);
+ ++src; /* skip leading 0x00 */
+ --numbytes;
+ if (gigaset_fill_inbuf(inbuf, src, numbytes)) {
+ dbg(DEBUG_INTR, "%s-->BH", __func__);
+ gigaset_schedule_event(inbuf->cs);
+ }
+ } else
+ dbg(DEBUG_INTR, "Received zero block length");
+ resubmit = 1;
+ } else {
+ /* The urb might have been killed. */
+ dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d",
+ __func__, urb->status);
+ if (urb->status != -ENOENT) /* not killed */
+ resubmit = 1;
+ }
+exit:
+ //spin_unlock_irqrestore(&inbuf->lock, flags);
+ if (resubmit) {
+ r = usb_submit_urb(urb, SLAB_ATOMIC);
+ if (r)
+ err("error %d when resubmitting urb.", -r);
+ }
+}
+
+
+/* This callback routine is called when data was transmitted to a B-Channel.
+ * Therefore it has to check if there is still data to transmit. This
+ * happens by calling modem_fill via task queue.
+ *
+ */
+static void gigaset_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct cardstate *cs = (struct cardstate *) urb->context;
+
+ IFNULLRET(cs);
+#ifdef CONFIG_GIGASET_DEBUG
+ if (!atomic_read(&cs->connected)) {
+ err("%s:not connected", __func__);
+ return;
+ }
+#endif
+ if (urb->status)
+ err("bulk transfer failed (status %d)", -urb->status); /* That's all we can do. Communication problems
+ are handeled by timeouts or network protocols */
+
+ atomic_set(&cs->hw.usb->busy, 0);
+ tasklet_schedule(&cs->write_tasklet);
+}
+
+static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
+{
+ struct cmdbuf_t *tcb;
+ unsigned long flags;
+ int count;
+ int status = -ENOENT; // FIXME
+ struct usb_cardstate *ucs = cs->hw.usb;
+
+ do {
+ if (!cb->len) {
+ tcb = cb;
+
+ spin_lock_irqsave(&cs->cmdlock, flags);
+ cs->cmdbytes -= cs->curlen;
+ dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left",
+ cs->curlen, cs->cmdbytes);
+ cs->cmdbuf = cb = cb->next;
+ if (cb) {
+ cb->prev = NULL;
+ cs->curlen = cb->len;
+ } else {
+ cs->lastcmdbuf = NULL;
+ cs->curlen = 0;
+ }
+ spin_unlock_irqrestore(&cs->cmdlock, flags);
+
+ if (tcb->wake_tasklet)
+ tasklet_schedule(tcb->wake_tasklet);
+ kfree(tcb);
+ }
+ if (cb) {
+ count = min(cb->len, ucs->bulk_out_size);
+ usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
+ usb_sndbulkpipe(ucs->udev,
+ ucs->bulk_out_endpointAddr & 0x0f),
+ cb->buf + cb->offset, count,
+ gigaset_write_bulk_callback, cs);
+
+ cb->offset += count;
+ cb->len -= count;
+ atomic_set(&ucs->busy, 1);
+ dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count);
+
+ status = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
+ if (status) {
+ atomic_set(&ucs->busy, 0);
+ err("could not submit urb (error %d).",
+ -status);
+ cb->len = 0; /* skip urb => remove cb+wakeup in next loop cycle */
+ }
+ }
+ } while (cb && status); /* bei Fehler naechster Befehl //FIXME: ist das OK? */
+
+ return status;
+}
+
+/* Write string into transbuf and send it to modem.
+ */
+static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
+ int len, struct tasklet_struct *wake_tasklet)
+{
+ struct cmdbuf_t *cb;
+ unsigned long flags;
+
+ gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
+ DEBUG_TRANSCMD : DEBUG_LOCKCMD,
+ "CMD Transmit", len, buf, 0);
+
+ if (!atomic_read(&cs->connected)) {
+ err("%s: not connected", __func__);
+ return -ENODEV;
+ }
+
+ if (len <= 0)
+ return 0;
+
+ if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
+ err("%s: out of memory", __func__);
+ return -ENOMEM;
+ }
+
+ memcpy(cb->buf, buf, len);
+ cb->len = len;
+ cb->offset = 0;
+ cb->next = NULL;
+ cb->wake_tasklet = wake_tasklet;
+
+ spin_lock_irqsave(&cs->cmdlock, flags);
+ cb->prev = cs->lastcmdbuf;
+ if (cs->lastcmdbuf)
+ cs->lastcmdbuf->next = cb;
+ else {
+ cs->cmdbuf = cb;
+ cs->curlen = len;
+ }
+ cs->cmdbytes += len;
+ cs->lastcmdbuf = cb;
+ spin_unlock_irqrestore(&cs->cmdlock, flags);
+
+ tasklet_schedule(&cs->write_tasklet);
+ return len;
+}
+
+static int gigaset_write_room(struct cardstate *cs)
+{
+ unsigned long flags;
+ unsigned bytes;
+
+ spin_lock_irqsave(&cs->cmdlock, flags);
+ bytes = cs->cmdbytes;
+ spin_unlock_irqrestore(&cs->cmdlock, flags);
+
+ return bytes < IF_WRITEBUF ? IF_WRITEBUF - bytes : 0;
+}
+
+static int gigaset_chars_in_buffer(struct cardstate *cs)
+{
+ return cs->cmdbytes;
+}
+
+static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
+{
+#ifdef CONFIG_GIGASET_UNDOCREQ
+ gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf, 0);
+ memcpy(cs->hw.usb->bchars, buf, 6);
+ return usb_control_msg(cs->hw.usb->udev,
+ usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41,
+ 0, 0, &buf, 6, 2000);
+#else
+ return -EINVAL;
+#endif
+}
+
+static int gigaset_freebcshw(struct bc_state *bcs)
+{
+ if (!bcs->hw.usb)
+ return 0;
+ //FIXME
+ kfree(bcs->hw.usb);
+ return 1;
+}
+
+/* Initialize the b-channel structure */
+static int gigaset_initbcshw(struct bc_state *bcs)
+{
+ bcs->hw.usb = kmalloc(sizeof(struct usb_bc_state), GFP_KERNEL);
+ if (!bcs->hw.usb)
+ return 0;
+
+ //bcs->hw.usb->trans_flg = READY_TO_TRNSMIT; /* B-Channel ready to transmit */
+ return 1;
+}
+
+static void gigaset_reinitbcshw(struct bc_state *bcs)
+{
+}
+
+static void gigaset_freecshw(struct cardstate *cs)
+{
+ //FIXME
+ tasklet_kill(&cs->write_tasklet);
+ kfree(cs->hw.usb);
+}
+
+static int gigaset_initcshw(struct cardstate *cs)
+{
+ struct usb_cardstate *ucs;
+
+ cs->hw.usb = ucs =
+ kmalloc(sizeof(struct usb_cardstate), GFP_KERNEL);
+ if (!ucs)
+ return 0;
+
+ ucs->bchars[0] = 0;
+ ucs->bchars[1] = 0;
+ ucs->bchars[2] = 0;
+ ucs->bchars[3] = 0;
+ ucs->bchars[4] = 0x11;
+ ucs->bchars[5] = 0x13;
+ ucs->bulk_out_buffer = NULL;
+ ucs->bulk_out_urb = NULL;
+ //ucs->urb_cmd_out = NULL;
+ ucs->read_urb = NULL;
+ tasklet_init(&cs->write_tasklet,
+ &gigaset_modem_fill, (unsigned long) cs);
+
+ return 1;
+}
+
+/* Writes the data of the current open skb into the modem.
+ * We have to protect against multiple calls until the
+ * callback handler () is called , due to the fact that we
+ * are just allowed to send data once to an endpoint. Therefore
+ * we using "trans_flg" to synchonize ...
+ */
+static int write_modem(struct cardstate *cs)
+{
+ int ret;
+ int count;
+ struct bc_state *bcs = &cs->bcs[0]; /* only one channel */
+ struct usb_cardstate *ucs = cs->hw.usb;
+ //unsigned long flags;
+
+ IFNULLRETVAL(bcs->tx_skb, -EINVAL);
+
+ dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len);
+
+ ret = -ENODEV;
+ IFNULLGOTO(ucs->bulk_out_buffer, error);
+ IFNULLGOTO(ucs->bulk_out_urb, error);
+ ret = 0;
+
+ if (!bcs->tx_skb->len) {
+ dev_kfree_skb_any(bcs->tx_skb);
+ bcs->tx_skb = NULL;
+ return -EINVAL;
+ }
+
+ /* Copy data to bulk out buffer and // FIXME copying not necessary
+ * transmit data
+ */
+ count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size);
+ memcpy(ucs->bulk_out_buffer, bcs->tx_skb->data, count);
+ skb_pull(bcs->tx_skb, count);
+
+ usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
+ usb_sndbulkpipe(ucs->udev,
+ ucs->bulk_out_endpointAddr & 0x0f),
+ ucs->bulk_out_buffer, count,
+ gigaset_write_bulk_callback, cs);
+ atomic_set(&ucs->busy, 1);
+ dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count);
+
+ ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
+ if (ret) {
+ err("could not submit urb (error %d).", -ret);
+ atomic_set(&ucs->busy, 0);
+ }
+ if (!bcs->tx_skb->len) {
+ /* skb sent completely */
+ gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0?
+
+ dbg(DEBUG_INTR,
+ "kfree skb (Adr: %lx)!", (unsigned long) bcs->tx_skb);
+ dev_kfree_skb_any(bcs->tx_skb);
+ bcs->tx_skb = NULL;
+ }
+
+ return ret;
+error:
+ dev_kfree_skb_any(bcs->tx_skb);
+ bcs->tx_skb = NULL;
+ return ret;
+
+}
+
+static int gigaset_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ int retval;
+ struct usb_device *udev = interface_to_usbdev(interface);
+ unsigned int ifnum;
+ struct usb_host_interface *hostif;
+ struct cardstate *cs = NULL;
+ struct usb_cardstate *ucs = NULL;
+ //struct usb_interface_descriptor *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ //isdn_ctrl command;
+ int buffer_size;
+ int alt;
+ //unsigned long flags;
+
+ info("%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
+ __func__, le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+
+ retval = -ENODEV; //FIXME
+
+ /* See if the device offered us matches what we can accept */
+ if ((le16_to_cpu(udev->descriptor.idVendor != USB_M105_VENDOR_ID)) ||
+ (le16_to_cpu(udev->descriptor.idProduct != USB_M105_PRODUCT_ID)))
+ return -ENODEV;
+
+ /* this starts to become ascii art... */
+ hostif = interface->cur_altsetting;
+ alt = hostif->desc.bAlternateSetting;
+ ifnum = hostif->desc.bInterfaceNumber; // FIXME ?
+
+ if (alt != 0 || ifnum != 0) {
+ warn("ifnum %d, alt %d", ifnum, alt);
+ return -ENODEV;
+ }
+
+ /* Reject application specific intefaces
+ *
+ */
+ if (hostif->desc.bInterfaceClass != 255) {
+ info("%s: Device matched, but iface_desc[%d]->bInterfaceClass==%d !",
+ __func__, ifnum, hostif->desc.bInterfaceClass);
+ return -ENODEV;
+ }
+
+ info("%s: Device matched ... !", __func__);
+
+ cs = gigaset_getunassignedcs(driver);
+ if (!cs) {
+ warn("No free cardstate!");
+ return -ENODEV;
+ }
+ ucs = cs->hw.usb;
+
+#if 0
+ if (usb_set_configuration(udev, udev->config[0].desc.bConfigurationValue) < 0) {
+ warn("set_configuration failed");
+ goto error;
+ }
+
+
+ if (usb_set_interface(udev, ifnum/*==0*/, alt/*==0*/) < 0) {
+ warn("usb_set_interface failed, device %d interface %d altsetting %d",
+ udev->devnum, ifnum, alt);
+ goto error;
+ }
+#endif
+
+ /* set up the endpoint information */
+ /* check out the endpoints */
+ /* We will get 2 endpoints: One for sending commands to the device (bulk out) and one to
+ * poll messages from the device(int in).
+ * Therefore we will have an almost similiar situation as with our serial port handler.
+ * If an connection will be established, we will have to create data in/out pipes
+ * dynamically...
+ */
+
+ endpoint = &hostif->endpoint[0].desc;
+
+ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ ucs->bulk_out_size = buffer_size;
+ ucs->bulk_out_endpointAddr = endpoint->bEndpointAddress;
+ ucs->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!ucs->bulk_out_buffer) {
+ err("Couldn't allocate bulk_out_buffer");
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ ucs->bulk_out_urb = usb_alloc_urb(0, SLAB_KERNEL);
+ if (!ucs->bulk_out_urb) {
+ err("Couldn't allocate bulk_out_buffer");
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ endpoint = &hostif->endpoint[1].desc;
+
+ atomic_set(&ucs->busy, 0);
+ ucs->udev = udev;
+ ucs->interface = interface;
+
+ ucs->read_urb = usb_alloc_urb(0, SLAB_KERNEL);
+ if (!ucs->read_urb) {
+ err("No free urbs available");
+ retval = -ENOMEM;
+ goto error;
+ }
+ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ ucs->rcvbuf_size = buffer_size;
+ ucs->int_in_endpointAddr = endpoint->bEndpointAddress;
+ cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL);
+ if (!cs->inbuf[0].rcvbuf) {
+ err("Couldn't allocate rcvbuf");
+ retval = -ENOMEM;
+ goto error;
+ }
+ /* Fill the interrupt urb and send it to the core */
+ usb_fill_int_urb(ucs->read_urb, udev,
+ usb_rcvintpipe(udev,
+ endpoint->bEndpointAddress & 0x0f),
+ cs->inbuf[0].rcvbuf, buffer_size,
+ gigaset_read_int_callback,
+ cs->inbuf + 0, endpoint->bInterval);
+
+ retval = usb_submit_urb(ucs->read_urb, SLAB_KERNEL);
+ if (retval) {
+ err("Could not submit URB!");
+ goto error;
+ }
+
+ /* tell common part that the device is ready */
+ if (startmode == SM_LOCKED)
+ atomic_set(&cs->mstate, MS_LOCKED);
+ if (!gigaset_start(cs)) {
+ tasklet_kill(&cs->write_tasklet);
+ retval = -ENODEV; //FIXME
+ goto error;
+ }
+
+ /* save address of controller structure */
+ usb_set_intfdata(interface, cs);
+
+ /* set up device sysfs */
+ gigaset_init_dev_sysfs(interface);
+ return 0;
+
+error:
+ if (ucs->read_urb)
+ usb_kill_urb(ucs->read_urb);
+ kfree(ucs->bulk_out_buffer);
+ if (ucs->bulk_out_urb != NULL)
+ usb_free_urb(ucs->bulk_out_urb);
+ kfree(cs->inbuf[0].rcvbuf);
+ if (ucs->read_urb != NULL)
+ usb_free_urb(ucs->read_urb);
+ ucs->read_urb = ucs->bulk_out_urb = NULL;
+ cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
+ gigaset_unassign(cs);
+ return retval;
+}
+
+/**
+ * skel_disconnect
+ */
+static void gigaset_disconnect(struct usb_interface *interface)
+{
+ struct cardstate *cs;
+ struct usb_cardstate *ucs;
+
+ cs = usb_get_intfdata(interface);
+
+ /* clear device sysfs */
+ gigaset_free_dev_sysfs(interface);
+
+ usb_set_intfdata(interface, NULL);
+ ucs = cs->hw.usb;
+ usb_kill_urb(ucs->read_urb);
+ //info("GigaSet USB device #%d will be disconnected", minor);
+
+ gigaset_stop(cs);
+
+ tasklet_kill(&cs->write_tasklet);
+
+ usb_kill_urb(ucs->bulk_out_urb); /* FIXME: nur, wenn noetig */
+ //usb_kill_urb(ucs->urb_cmd_out); /* FIXME: nur, wenn noetig */
+
+ kfree(ucs->bulk_out_buffer);
+ if (ucs->bulk_out_urb != NULL)
+ usb_free_urb(ucs->bulk_out_urb);
+ //if(ucs->urb_cmd_out != NULL)
+ // usb_free_urb(ucs->urb_cmd_out);
+ kfree(cs->inbuf[0].rcvbuf);
+ if (ucs->read_urb != NULL)
+ usb_free_urb(ucs->read_urb);
+ ucs->read_urb = ucs->bulk_out_urb/*=ucs->urb_cmd_out*/=NULL;
+ cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
+
+ gigaset_unassign(cs);
+}
+
+static struct gigaset_ops ops = {
+ gigaset_write_cmd,
+ gigaset_write_room,
+ gigaset_chars_in_buffer,
+ gigaset_brkchars,
+ gigaset_init_bchannel,
+ gigaset_close_bchannel,
+ gigaset_initbcshw,
+ gigaset_freebcshw,
+ gigaset_reinitbcshw,
+ gigaset_initcshw,
+ gigaset_freecshw,
+ gigaset_set_modem_ctrl,
+ gigaset_baud_rate,
+ gigaset_set_line_ctrl,
+ gigaset_m10x_send_skb,
+ gigaset_m10x_input,
+};
+
+/**
+ * usb_gigaset_init
+ * This function is called while kernel-module is loaded
+ */
+static int __init usb_gigaset_init(void)
+{
+ int result;
+
+ /* allocate memory for our driver state and intialize it */
+ if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
+ GIGASET_MODULENAME, GIGASET_DEVNAME,
+ GIGASET_DEVFSNAME, &ops,
+ THIS_MODULE)) == NULL)
+ goto error;
+
+ /* allocate memory for our device state and intialize it */
+ cardstate = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME);
+ if (!cardstate)
+ goto error;
+
+ /* register this driver with the USB subsystem */
+ result = usb_register(&gigaset_usb_driver);
+ if (result < 0) {
+ err("usb_gigaset: usb_register failed (error %d)",
+ -result);
+ goto error;
+ }
+
+ info(DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+ return 0;
+
+error: if (cardstate)
+ gigaset_freecs(cardstate);
+ cardstate = NULL;
+ if (driver)
+ gigaset_freedriver(driver);
+ driver = NULL;
+ return -1;
+}
+
+
+/**
+ * usb_gigaset_exit
+ * This function is called while unloading the kernel-module
+ */
+static void __exit usb_gigaset_exit(void)
+{
+ gigaset_blockdriver(driver); /* => probe will fail
+ * => no gigaset_start any more
+ */
+
+ gigaset_shutdown(cardstate);
+ /* from now on, no isdn callback should be possible */
+
+ /* deregister this driver with the USB subsystem */
+ usb_deregister(&gigaset_usb_driver);
+ /* this will call the disconnect-callback */
+ /* from now on, no disconnect/probe callback should be running */
+
+ gigaset_freecs(cardstate);
+ cardstate = NULL;
+ gigaset_freedriver(driver);
+ driver = NULL;
+}
+
+
+module_init(usb_gigaset_init);
+module_exit(usb_gigaset_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/isdn/hardware/avm/avmcard.h b/drivers/isdn/hardware/avm/avmcard.h
index 296d6a6f749..3b431723c7c 100644
--- a/drivers/isdn/hardware/avm/avmcard.h
+++ b/drivers/isdn/hardware/avm/avmcard.h
@@ -437,9 +437,7 @@ static inline unsigned int t1_get_slice(unsigned int base,
#endif
dp += i;
i = 0;
- if (i == 0)
- break;
- /* fall through */
+ break;
default:
*dp++ = b1_get_byte(base);
i--;
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
index 91dd0551fc7..4d64e5cbcdb 100644
--- a/drivers/isdn/hardware/avm/b1dma.c
+++ b/drivers/isdn/hardware/avm/b1dma.c
@@ -39,7 +39,7 @@ MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
static int suppress_pollack = 0;
-MODULE_PARM(suppress_pollack, "0-1i");
+module_param(suppress_pollack, bool, 0);
/* ------------------------------------------------------------- */
diff --git a/drivers/isdn/hardware/avm/b1isa.c b/drivers/isdn/hardware/avm/b1isa.c
index 38bd4dfecbd..80fb488848b 100644
--- a/drivers/isdn/hardware/avm/b1isa.c
+++ b/drivers/isdn/hardware/avm/b1isa.c
@@ -169,8 +169,8 @@ static struct pci_dev isa_dev[MAX_CARDS];
static int io[MAX_CARDS];
static int irq[MAX_CARDS];
-MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
MODULE_PARM_DESC(io, "I/O base address(es)");
MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index 724aac2c1cc..f7253b2136e 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -50,7 +50,7 @@ MODULE_DEVICE_TABLE(pci, c4_pci_tbl);
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM C2/C4 cards");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
-MODULE_PARM(suppress_pollack, "0-1i");
+module_param(suppress_pollack, bool, 0);
/* ------------------------------------------------------------- */
diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c
index 3b701d97bdf..5a2f854d55b 100644
--- a/drivers/isdn/hardware/avm/t1isa.c
+++ b/drivers/isdn/hardware/avm/t1isa.c
@@ -519,9 +519,9 @@ static int io[MAX_CARDS];
static int irq[MAX_CARDS];
static int cardnr[MAX_CARDS];
-MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
-MODULE_PARM(cardnr, "1-" __MODULE_STRING(MAX_CARDS) "i");
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(cardnr, int, NULL, 0);
MODULE_PARM_DESC(io, "I/O base address(es)");
MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
MODULE_PARM_DESC(cardnr, "Card number(s) (as jumpered)");
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
index dc7ef957e89..dbcca287ee2 100644
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c
@@ -387,8 +387,7 @@ static void hdlc_fill_fifo(struct fritz_bcs *bcs)
DBG(0x40, "hdlc_fill_fifo");
- if (skb->len == 0)
- BUG();
+ BUG_ON(skb->len == 0);
bcs->ctrl.sr.cmd &= ~HDLC_CMD_XME;
if (bcs->tx_skb->len > bcs->fifo_size) {
@@ -630,9 +629,7 @@ static void fritz_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
switch (pr) {
case PH_DATA | REQUEST:
- if (bcs->tx_skb)
- BUG();
-
+ BUG_ON(bcs->tx_skb);
bcs->tx_skb = skb;
DBG_SKB(1, skb);
hdlc_fill_fifo(bcs);
diff --git a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c
index f4972f6c1f5..81eac344bb0 100644
--- a/drivers/isdn/hisax/hisax_isac.c
+++ b/drivers/isdn/hisax/hisax_isac.c
@@ -476,12 +476,10 @@ static void isac_fill_fifo(struct isac *isac)
unsigned char cmd;
u_char *ptr;
- if (!isac->tx_skb)
- BUG();
+ BUG_ON(!isac->tx_skb);
count = isac->tx_skb->len;
- if (count <= 0)
- BUG();
+ BUG_ON(count <= 0);
DBG(DBG_IRQ, "count %d", count);
@@ -859,8 +857,7 @@ void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg)
dev_kfree_skb(skb);
break;
}
- if (isac->tx_skb)
- BUG();
+ BUG_ON(isac->tx_skb);
isac->tx_skb = skb;
isac_fill_fifo(isac);
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
index 657817a591f..22fd5db18d4 100644
--- a/drivers/isdn/hisax/st5481_b.c
+++ b/drivers/isdn/hisax/st5481_b.c
@@ -356,9 +356,7 @@ void st5481_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
switch (pr) {
case PH_DATA | REQUEST:
- if (bcs->b_out.tx_skb)
- BUG();
-
+ BUG_ON(bcs->b_out.tx_skb);
bcs->b_out.tx_skb = skb;
break;
case PH_ACTIVATE | REQUEST:
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index 941f7022ada..493dc94992e 100644
--- a/drivers/isdn/hisax/st5481_d.c
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -596,9 +596,7 @@ void st5481_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg)
break;
case PH_DATA | REQUEST:
DBG(2, "PH_DATA REQUEST len %d", skb->len);
- if (adapter->d_out.tx_skb)
- BUG();
-
+ BUG_ON(adapter->d_out.tx_skb);
adapter->d_out.tx_skb = skb;
FsmEvent(&adapter->d_out.fsm, EV_DOUT_START_XMIT, NULL);
break;
diff --git a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c
index e19a01a305a..48d134be990 100644
--- a/drivers/isdn/hysdn/boardergo.c
+++ b/drivers/isdn/hysdn/boardergo.c
@@ -38,8 +38,8 @@ ergo_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{
hysdn_card *card = dev_id; /* parameter from irq */
tErgDpram *dpr;
- ulong flags;
- uchar volatile b;
+ unsigned long flags;
+ unsigned char volatile b;
if (!card)
return IRQ_NONE; /* error -> spurious interrupt */
@@ -77,7 +77,7 @@ ergo_irq_bh(hysdn_card * card)
{
tErgDpram *dpr;
int again;
- ulong flags;
+ unsigned long flags;
if (card->state != CARD_STATE_RUN)
return; /* invalid call */
@@ -131,8 +131,8 @@ ergo_irq_bh(hysdn_card * card)
static void
ergo_stopcard(hysdn_card * card)
{
- ulong flags;
- uchar val;
+ unsigned long flags;
+ unsigned char val;
hysdn_net_release(card); /* first release the net device if existing */
#ifdef CONFIG_HYSDN_CAPI
@@ -157,7 +157,7 @@ ergo_stopcard(hysdn_card * card)
static void
ergo_set_errlog_state(hysdn_card * card, int on)
{
- ulong flags;
+ unsigned long flags;
if (card->state != CARD_STATE_RUN) {
card->err_log_state = ERRLOG_STATE_OFF; /* must be off */
@@ -217,9 +217,10 @@ ergo_testram(hysdn_card * card)
/* Negative return values are interpreted as errors. */
/*****************************************************************************/
static int
-ergo_writebootimg(struct HYSDN_CARD *card, uchar * buf, ulong offs)
+ergo_writebootimg(struct HYSDN_CARD *card, unsigned char *buf,
+ unsigned long offs)
{
- uchar *dst;
+ unsigned char *dst;
tErgDpram *dpram;
int cnt = (BOOT_IMG_SIZE >> 2); /* number of words to move and swap (byte order!) */
@@ -264,14 +265,14 @@ ergo_writebootimg(struct HYSDN_CARD *card, uchar * buf, ulong offs)
/* case of errors a negative error value is returned. */
/********************************************************************************/
static int
-ergo_writebootseq(struct HYSDN_CARD *card, uchar * buf, int len)
+ergo_writebootseq(struct HYSDN_CARD *card, unsigned char *buf, int len)
{
tDpramBootSpooler *sp = (tDpramBootSpooler *) card->dpram;
- uchar *dst;
- uchar buflen;
+ unsigned char *dst;
+ unsigned char buflen;
int nr_write;
- uchar tmp_rdptr;
- uchar wr_mirror;
+ unsigned char tmp_rdptr;
+ unsigned char wr_mirror;
int i;
if (card->debug_flags & LOG_POF_CARD)
@@ -330,7 +331,7 @@ ergo_waitpofready(struct HYSDN_CARD *card)
{
tErgDpram *dpr = card->dpram; /* pointer to DPRAM structure */
int timecnt = 10000 / 50; /* timeout is 10 secs max. */
- ulong flags;
+ unsigned long flags;
int msg_size;
int i;
@@ -345,7 +346,7 @@ ergo_waitpofready(struct HYSDN_CARD *card)
if ((dpr->ToPcChannel != CHAN_SYSTEM) ||
(dpr->ToPcSize < MIN_RDY_MSG_SIZE) ||
(dpr->ToPcSize > MAX_RDY_MSG_SIZE) ||
- ((*(ulong *) dpr->ToPcBuf) != RDY_MAGIC))
+ ((*(unsigned long *) dpr->ToPcBuf) != RDY_MAGIC))
break; /* an error occurred */
/* Check for additional data delivered during SysReady */
diff --git a/drivers/isdn/hysdn/boardergo.h b/drivers/isdn/hysdn/boardergo.h
index b56ff0889ea..c59422aa8c3 100644
--- a/drivers/isdn/hysdn/boardergo.h
+++ b/drivers/isdn/hysdn/boardergo.h
@@ -23,36 +23,36 @@
/* following DPRAM layout copied from OS2-driver boarderg.h */
typedef struct ErgDpram_tag {
-/*0000 */ uchar ToHyBuf[ERG_TO_HY_BUF_SIZE];
-/*0E00 */ uchar ToPcBuf[ERG_TO_PC_BUF_SIZE];
+/*0000 */ unsigned char ToHyBuf[ERG_TO_HY_BUF_SIZE];
+/*0E00 */ unsigned char ToPcBuf[ERG_TO_PC_BUF_SIZE];
- /*1C00 */ uchar bSoftUart[SIZE_RSV_SOFT_UART];
+ /*1C00 */ unsigned char bSoftUart[SIZE_RSV_SOFT_UART];
/* size 0x1B0 */
- /*1DB0 *//* tErrLogEntry */ uchar volatile ErrLogMsg[64];
+ /*1DB0 *//* tErrLogEntry */ unsigned char volatile ErrLogMsg[64];
/* size 64 bytes */
- /*1DB0 ulong ulErrType; */
- /*1DB4 ulong ulErrSubtype; */
- /*1DB8 ulong ucTextSize; */
- /*1DB9 ulong ucText[ERRLOG_TEXT_SIZE]; *//* ASCIIZ of len ucTextSize-1 */
+ /*1DB0 unsigned long ulErrType; */
+ /*1DB4 unsigned long ulErrSubtype; */
+ /*1DB8 unsigned long ucTextSize; */
+ /*1DB9 unsigned long ucText[ERRLOG_TEXT_SIZE]; *//* ASCIIZ of len ucTextSize-1 */
/*1DF0 */
-/*1DF0 */ word volatile ToHyChannel;
-/*1DF2 */ word volatile ToHySize;
- /*1DF4 */ uchar volatile ToHyFlag;
+/*1DF0 */ unsigned short volatile ToHyChannel;
+/*1DF2 */ unsigned short volatile ToHySize;
+ /*1DF4 */ unsigned char volatile ToHyFlag;
/* !=0: msg for Hy waiting */
- /*1DF5 */ uchar volatile ToPcFlag;
+ /*1DF5 */ unsigned char volatile ToPcFlag;
/* !=0: msg for PC waiting */
-/*1DF6 */ word volatile ToPcChannel;
-/*1DF8 */ word volatile ToPcSize;
- /*1DFA */ uchar bRes1DBA[0x1E00 - 0x1DFA];
+/*1DF6 */ unsigned short volatile ToPcChannel;
+/*1DF8 */ unsigned short volatile ToPcSize;
+ /*1DFA */ unsigned char bRes1DBA[0x1E00 - 0x1DFA];
/* 6 bytes */
-/*1E00 */ uchar bRestOfEntryTbl[0x1F00 - 0x1E00];
-/*1F00 */ ulong TrapTable[62];
- /*1FF8 */ uchar bRes1FF8[0x1FFB - 0x1FF8];
+/*1E00 */ unsigned char bRestOfEntryTbl[0x1F00 - 0x1E00];
+/*1F00 */ unsigned long TrapTable[62];
+ /*1FF8 */ unsigned char bRes1FF8[0x1FFB - 0x1FF8];
/* low part of reset vetor */
-/*1FFB */ uchar ToPcIntMetro;
+/*1FFB */ unsigned char ToPcIntMetro;
/* notes:
* - metro has 32-bit boot ram - accessing
* ToPcInt and ToHyInt would be the same;
@@ -65,16 +65,16 @@ typedef struct ErgDpram_tag {
* so E1 side should NOT change this byte
* when writing!
*/
-/*1FFC */ uchar volatile ToHyNoDpramErrLog;
+/*1FFC */ unsigned char volatile ToHyNoDpramErrLog;
/* note: ToHyNoDpramErrLog is used to inform
* boot loader, not to use DPRAM based
* ErrLog; when DOS driver is rewritten
* this becomes obsolete
*/
-/*1FFD */ uchar bRes1FFD;
- /*1FFE */ uchar ToPcInt;
+/*1FFD */ unsigned char bRes1FFD;
+ /*1FFE */ unsigned char ToPcInt;
/* E1_intclear; on CHAMP2: E1_intset */
- /*1FFF */ uchar ToHyInt;
+ /*1FFF */ unsigned char ToHyInt;
/* E1_intset; on CHAMP2: E1_intclear */
} tErgDpram;
diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c
index acc1d3cceeb..6bac43cc91b 100644
--- a/drivers/isdn/hysdn/hycapi.c
+++ b/drivers/isdn/hysdn/hycapi.c
@@ -31,7 +31,7 @@
static char hycapi_revision[]="$Revision: 1.8.6.4 $";
unsigned int hycapi_enable = 0xffffffff;
-MODULE_PARM(hycapi_enable, "i");
+module_param(hycapi_enable, uint, 0);
typedef struct _hycapi_appl {
unsigned int ctrl_mask;
@@ -523,7 +523,7 @@ New nccis are created if necessary.
*******************************************************************/
void
-hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len)
+hycapi_rx_capipkt(hysdn_card * card, unsigned char *buf, unsigned short len)
{
struct sk_buff *skb;
hycapictrl_info *cinfo = card->hyctrlinfo;
diff --git a/drivers/isdn/hysdn/hysdn_boot.c b/drivers/isdn/hysdn/hysdn_boot.c
index 7bfba196f31..6d0eb0f42fc 100644
--- a/drivers/isdn/hysdn/hysdn_boot.c
+++ b/drivers/isdn/hysdn/hysdn_boot.c
@@ -30,17 +30,17 @@
/* needed during boot and so allocated dynamically. */
/************************************************************/
struct boot_data {
- word Cryptor; /* for use with Decrypt function */
- word Nrecs; /* records remaining in file */
- uchar pof_state; /* actual state of read handler */
- uchar is_crypted; /* card data is crypted */
+ unsigned short Cryptor; /* for use with Decrypt function */
+ unsigned short Nrecs; /* records remaining in file */
+ unsigned char pof_state;/* actual state of read handler */
+ unsigned char is_crypted;/* card data is crypted */
int BufSize; /* actual number of bytes bufferd */
int last_error; /* last occurred error */
- word pof_recid; /* actual pof recid */
- ulong pof_reclen; /* total length of pof record data */
- ulong pof_recoffset; /* actual offset inside pof record */
+ unsigned short pof_recid;/* actual pof recid */
+ unsigned long pof_reclen;/* total length of pof record data */
+ unsigned long pof_recoffset;/* actual offset inside pof record */
union {
- uchar BootBuf[BOOT_BUF_SIZE]; /* buffer as byte count */
+ unsigned char BootBuf[BOOT_BUF_SIZE];/* buffer as byte count */
tPofRecHdr PofRecHdr; /* header for actual record/chunk */
tPofFileHdr PofFileHdr; /* header from POF file */
tPofTimeStamp PofTime; /* time information */
@@ -69,11 +69,11 @@ StartDecryption(struct boot_data *boot)
static void
DecryptBuf(struct boot_data *boot, int cnt)
{
- uchar *bufp = boot->buf.BootBuf;
+ unsigned char *bufp = boot->buf.BootBuf;
while (cnt--) {
boot->Cryptor = (boot->Cryptor >> 1) ^ ((boot->Cryptor & 1U) ? CRYPT_FEEDTERM : 0);
- *bufp++ ^= (uchar) boot->Cryptor;
+ *bufp++ ^= (unsigned char)boot->Cryptor;
}
} /* DecryptBuf */
@@ -86,7 +86,7 @@ pof_handle_data(hysdn_card * card, int datlen)
{
struct boot_data *boot = card->boot; /* pointer to boot specific data */
long l;
- uchar *imgp;
+ unsigned char *imgp;
int img_len;
/* handle the different record types */
@@ -197,7 +197,7 @@ pof_write_buffer(hysdn_card * card, int datlen)
break;
}
/* Setup the new state and vars */
- boot->Nrecs = (word) (boot->buf.PofFileHdr.N_PofRecs); /* limited to 65535 */
+ boot->Nrecs = (unsigned short)(boot->buf.PofFileHdr.N_PofRecs); /* limited to 65535 */
boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */
boot->last_error = sizeof(tPofRecHdr); /* new length */
break;
@@ -268,7 +268,7 @@ pof_write_buffer(hysdn_card * card, int datlen)
/* occurred. Additionally the pointer to the buffer data area is set on success */
/*******************************************************************************/
int
-pof_write_open(hysdn_card * card, uchar ** bufp)
+pof_write_open(hysdn_card * card, unsigned char **bufp)
{
struct boot_data *boot; /* pointer to boot specific data */
@@ -335,7 +335,7 @@ pof_write_close(hysdn_card * card)
/* when POF has been booted. A return value of 0 is used if no error occurred. */
/*********************************************************************************/
int
-EvalSysrTokData(hysdn_card * card, uchar * cp, int len)
+EvalSysrTokData(hysdn_card *card, unsigned char *cp, int len)
{
u_char *p;
u_char crc;
diff --git a/drivers/isdn/hysdn/hysdn_defs.h b/drivers/isdn/hysdn/hysdn_defs.h
index 432f6f99089..3a9b29b38bc 100644
--- a/drivers/isdn/hysdn/hysdn_defs.h
+++ b/drivers/isdn/hysdn/hysdn_defs.h
@@ -20,14 +20,6 @@
#include <linux/workqueue.h>
#include <linux/skbuff.h>
-/****************************/
-/* storage type definitions */
-/****************************/
-#define uchar unsigned char
-#define uint unsigned int
-#define ulong unsigned long
-#define word unsigned short
-
#include "ince1pc.h"
#ifdef CONFIG_HYSDN_CAPI
@@ -147,18 +139,18 @@ typedef struct HYSDN_CARD {
/* general variables for the cards */
int myid; /* own driver card id */
- uchar bus; /* pci bus the card is connected to */
- uchar devfn; /* slot+function bit encoded */
- word subsysid; /* PCI subsystem id */
- uchar brdtype; /* type of card */
- uint bchans; /* number of available B-channels */
- uint faxchans; /* number of available fax-channels */
- uchar mac_addr[6]; /* MAC Address read from card */
- uint irq; /* interrupt number */
- uint iobase; /* IO-port base address */
- ulong plxbase; /* PLX memory base */
- ulong membase; /* DPRAM memory base */
- ulong memend; /* DPRAM memory end */
+ unsigned char bus; /* pci bus the card is connected to */
+ unsigned char devfn; /* slot+function bit encoded */
+ unsigned short subsysid;/* PCI subsystem id */
+ unsigned char brdtype; /* type of card */
+ unsigned int bchans; /* number of available B-channels */
+ unsigned int faxchans; /* number of available fax-channels */
+ unsigned char mac_addr[6];/* MAC Address read from card */
+ unsigned int irq; /* interrupt number */
+ unsigned int iobase; /* IO-port base address */
+ unsigned long plxbase; /* PLX memory base */
+ unsigned long membase; /* DPRAM memory base */
+ unsigned long memend; /* DPRAM memory end */
void *dpram; /* mapped dpram */
int state; /* actual state of card -> CARD_STATE_** */
struct HYSDN_CARD *next; /* pointer to next card */
@@ -168,26 +160,26 @@ typedef struct HYSDN_CARD {
void *procconf; /* pointer to procconf filesystem specific data */
/* debugging and logging */
- uchar err_log_state; /* actual error log state of the card */
- ulong debug_flags; /* tells what should be debugged and where */
+ unsigned char err_log_state;/* actual error log state of the card */
+ unsigned long debug_flags;/* tells what should be debugged and where */
void (*set_errlog_state) (struct HYSDN_CARD *, int);
/* interrupt handler + interrupt synchronisation */
struct work_struct irq_queue; /* interrupt task queue */
- uchar volatile irq_enabled; /* interrupt enabled if != 0 */
- uchar volatile hw_lock; /* hardware is currently locked -> no access */
+ unsigned char volatile irq_enabled;/* interrupt enabled if != 0 */
+ unsigned char volatile hw_lock;/* hardware is currently locked -> no access */
/* boot process */
void *boot; /* pointer to boot private data */
- int (*writebootimg) (struct HYSDN_CARD *, uchar *, ulong);
- int (*writebootseq) (struct HYSDN_CARD *, uchar *, int);
+ int (*writebootimg) (struct HYSDN_CARD *, unsigned char *, unsigned long);
+ int (*writebootseq) (struct HYSDN_CARD *, unsigned char *, int);
int (*waitpofready) (struct HYSDN_CARD *);
int (*testram) (struct HYSDN_CARD *);
/* scheduler for data transfer (only async parts) */
- uchar async_data[256]; /* async data to be sent (normally for config) */
- word volatile async_len; /* length of data to sent */
- word volatile async_channel; /* channel number for async transfer */
+ unsigned char async_data[256];/* async data to be sent (normally for config) */
+ unsigned short volatile async_len;/* length of data to sent */
+ unsigned short volatile async_channel;/* channel number for async transfer */
int volatile async_busy; /* flag != 0 sending in progress */
int volatile net_tx_busy; /* a network packet tx is in progress */
@@ -251,15 +243,18 @@ extern int ergo_inithardware(hysdn_card * card); /* get hardware -> module init
/* hysdn_boot.c */
extern int pof_write_close(hysdn_card *); /* close proc file after writing pof */
-extern int pof_write_open(hysdn_card *, uchar **); /* open proc file for writing pof */
+extern int pof_write_open(hysdn_card *, unsigned char **); /* open proc file for writing pof */
extern int pof_write_buffer(hysdn_card *, int); /* write boot data to card */
-extern int EvalSysrTokData(hysdn_card *, uchar *, int); /* Check Sysready Token Data */
+extern int EvalSysrTokData(hysdn_card *, unsigned char *, int); /* Check Sysready Token Data */
/* hysdn_sched.c */
-extern int hysdn_sched_tx(hysdn_card *, uchar *, word volatile *, word volatile *,
- word);
-extern int hysdn_sched_rx(hysdn_card *, uchar *, word, word);
-extern int hysdn_tx_cfgline(hysdn_card *, uchar *, word); /* send one cfg line */
+extern int hysdn_sched_tx(hysdn_card *, unsigned char *,
+ unsigned short volatile *, unsigned short volatile *,
+ unsigned short);
+extern int hysdn_sched_rx(hysdn_card *, unsigned char *, unsigned short,
+ unsigned short);
+extern int hysdn_tx_cfgline(hysdn_card *, unsigned char *,
+ unsigned short); /* send one cfg line */
/* hysdn_net.c */
extern unsigned int hynet_enable;
@@ -269,14 +264,16 @@ extern int hysdn_net_release(hysdn_card *); /* delete the device */
extern char *hysdn_net_getname(hysdn_card *); /* get name of net interface */
extern void hysdn_tx_netack(hysdn_card *); /* acknowledge a packet tx */
extern struct sk_buff *hysdn_tx_netget(hysdn_card *); /* get next network packet */
-extern void hysdn_rx_netpkt(hysdn_card *, uchar *, word); /* rxed packet from network */
+extern void hysdn_rx_netpkt(hysdn_card *, unsigned char *,
+ unsigned short); /* rxed packet from network */
#ifdef CONFIG_HYSDN_CAPI
extern unsigned int hycapi_enable;
extern int hycapi_capi_create(hysdn_card *); /* create a new capi device */
extern int hycapi_capi_release(hysdn_card *); /* delete the device */
extern int hycapi_capi_stop(hysdn_card *card); /* suspend */
-extern void hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len);
+extern void hycapi_rx_capipkt(hysdn_card * card, unsigned char * buf,
+ unsigned short len);
extern void hycapi_tx_capiack(hysdn_card * card);
extern struct sk_buff *hycapi_tx_capiget(hysdn_card *card);
extern int hycapi_init(void);
diff --git a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c
index cb791f8e793..b75ac5af236 100644
--- a/drivers/isdn/hysdn/hysdn_init.c
+++ b/drivers/isdn/hysdn/hysdn_init.c
@@ -41,8 +41,8 @@ hysdn_card *card_root = NULL; /* pointer to first card */
/* the last entry contains all 0 */
/**********************************************/
static struct {
- word subid; /* PCI sub id */
- uchar cardtyp; /* card type assigned */
+ unsigned short subid; /* PCI sub id */
+ unsigned char cardtyp; /* card type assigned */
} pci_subid_map[] = {
{
diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c
index aa01628d74c..d205249a124 100644
--- a/drivers/isdn/hysdn/hysdn_net.c
+++ b/drivers/isdn/hysdn/hysdn_net.c
@@ -24,7 +24,7 @@
#include "hysdn_defs.h"
unsigned int hynet_enable = 0xffffffff;
-MODULE_PARM(hynet_enable, "i");
+module_param(hynet_enable, uint, 0);
/* store the actual version for log reporting */
char *hysdn_net_revision = "$Revision: 1.8.6.4 $";
@@ -83,12 +83,12 @@ net_open(struct net_device *dev)
/* Fill in the MAC-level header (if not already set) */
if (!card->mac_addr[0]) {
- for (i = 0; i < ETH_ALEN - sizeof(ulong); i++)
+ for (i = 0; i < ETH_ALEN - sizeof(unsigned long); i++)
dev->dev_addr[i] = 0xfc;
if ((in_dev = dev->ip_ptr) != NULL) {
struct in_ifaddr *ifa = in_dev->ifa_list;
if (ifa != NULL)
- memcpy(dev->dev_addr + (ETH_ALEN - sizeof(ulong)), &ifa->ifa_local, sizeof(ulong));
+ memcpy(dev->dev_addr + (ETH_ALEN - sizeof(unsigned long)), &ifa->ifa_local, sizeof(unsigned long));
}
} else
memcpy(dev->dev_addr, card->mac_addr, ETH_ALEN);
@@ -197,7 +197,7 @@ hysdn_tx_netack(hysdn_card * card)
/* we got a packet from the network, go and queue it */
/*****************************************************/
void
-hysdn_rx_netpkt(hysdn_card * card, uchar * buf, word len)
+hysdn_rx_netpkt(hysdn_card * card, unsigned char *buf, unsigned short len)
{
struct net_local *lp = card->netif;
struct sk_buff *skb;
diff --git a/drivers/isdn/hysdn/hysdn_pof.h b/drivers/isdn/hysdn/hysdn_pof.h
index 6cd81b9b08b..a368d6caca0 100644
--- a/drivers/isdn/hysdn/hysdn_pof.h
+++ b/drivers/isdn/hysdn/hysdn_pof.h
@@ -47,20 +47,20 @@
/*--------------------------------------POF file record structs------------*/
typedef struct PofFileHdr_tag { /* Pof file header */
-/*00 */ ulong Magic __attribute__((packed));
-/*04 */ ulong N_PofRecs __attribute__((packed));
+/*00 */ unsigned long Magic __attribute__((packed));
+/*04 */ unsigned long N_PofRecs __attribute__((packed));
/*08 */
} tPofFileHdr;
typedef struct PofRecHdr_tag { /* Pof record header */
-/*00 */ word PofRecId __attribute__((packed));
-/*02 */ ulong PofRecDataLen __attribute__((packed));
+/*00 */ unsigned short PofRecId __attribute__((packed));
+/*02 */ unsigned long PofRecDataLen __attribute__((packed));
/*06 */
} tPofRecHdr;
typedef struct PofTimeStamp_tag {
-/*00 */ ulong UnixTime __attribute__((packed));
- /*04 */ uchar DateTimeText[0x28] __attribute__((packed));
+/*00 */ unsigned long UnixTime __attribute__((packed));
+ /*04 */ unsigned char DateTimeText[0x28] __attribute__((packed));
/* =40 */
/*2C */
} tPofTimeStamp;
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
index 40e56143c76..8e2b03889f3 100644
--- a/drivers/isdn/hysdn/hysdn_procconf.c
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -36,9 +36,9 @@ struct conf_writedata {
int buf_size; /* actual number of bytes in the buffer */
int needed_size; /* needed size when reading pof */
int state; /* actual interface states from above constants */
- uchar conf_line[CONF_LINE_LEN]; /* buffered conf line */
- word channel; /* active channel number */
- uchar *pof_buffer; /* buffer when writing pof */
+ unsigned char conf_line[CONF_LINE_LEN]; /* buffered conf line */
+ unsigned short channel; /* active channel number */
+ unsigned char *pof_buffer; /* buffer when writing pof */
};
/***********************************************************************/
@@ -49,7 +49,7 @@ struct conf_writedata {
static int
process_line(struct conf_writedata *cnf)
{
- uchar *cp = cnf->conf_line;
+ unsigned char *cp = cnf->conf_line;
int i;
if (cnf->card->debug_flags & LOG_CNF_LINE)
@@ -92,7 +92,7 @@ hysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t
{
struct conf_writedata *cnf;
int i;
- uchar ch, *cp;
+ unsigned char ch, *cp;
if (!count)
return (0); /* nothing to handle */
@@ -390,7 +390,7 @@ int
hysdn_procconf_init(void)
{
hysdn_card *card;
- uchar conf_name[20];
+ unsigned char conf_name[20];
hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, proc_net);
if (!hysdn_proc_entry) {
@@ -423,7 +423,7 @@ void
hysdn_procconf_release(void)
{
hysdn_card *card;
- uchar conf_name[20];
+ unsigned char conf_name[20];
card = card_root; /* start with first card */
while (card) {
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index 6c26f1efabd..c4301e8338e 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -28,7 +28,7 @@ static void put_log_buffer(hysdn_card * card, char *cp);
/*************************************************/
struct log_data {
struct log_data *next;
- ulong usage_cnt; /* number of files still to work */
+ unsigned long usage_cnt;/* number of files still to work */
void *proc_ctrl; /* pointer to own control procdata structure */
char log_start[2]; /* log string start (final len aligned by size) */
};
@@ -42,7 +42,7 @@ struct procdata {
struct log_data *log_head, *log_tail; /* head and tail for queue */
int if_used; /* open count for interface */
int volatile del_lock; /* lock for delete operations */
- uchar logtmp[LOG_MAX_LINELEN];
+ unsigned char logtmp[LOG_MAX_LINELEN];
wait_queue_head_t rd_queue;
};
@@ -153,9 +153,9 @@ put_log_buffer(hysdn_card * card, char *cp)
static ssize_t
hysdn_log_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
{
- ulong u = 0;
+ unsigned long u = 0;
int found = 0;
- uchar *cp, valbuf[128];
+ unsigned char *cp, valbuf[128];
long base = 10;
hysdn_card *card = (hysdn_card *) file->private_data;
@@ -249,7 +249,7 @@ hysdn_log_open(struct inode *ino, struct file *filep)
{
hysdn_card *card;
struct procdata *pd = NULL;
- ulong flags;
+ unsigned long flags;
lock_kernel();
card = card_root;
diff --git a/drivers/isdn/hysdn/hysdn_sched.c b/drivers/isdn/hysdn/hysdn_sched.c
index 4fa3b01707c..133032920ff 100644
--- a/drivers/isdn/hysdn/hysdn_sched.c
+++ b/drivers/isdn/hysdn/hysdn_sched.c
@@ -30,7 +30,8 @@
/* to keep the data until later. */
/*****************************************************************************/
int
-hysdn_sched_rx(hysdn_card * card, uchar * buf, word len, word chan)
+hysdn_sched_rx(hysdn_card *card, unsigned char *buf, unsigned short len,
+ unsigned short chan)
{
switch (chan) {
@@ -72,7 +73,9 @@ hysdn_sched_rx(hysdn_card * card, uchar * buf, word len, word chan)
/* sending. */
/*****************************************************************************/
int
-hysdn_sched_tx(hysdn_card * card, uchar * buf, word volatile *len, word volatile *chan, word maxlen)
+hysdn_sched_tx(hysdn_card *card, unsigned char *buf,
+ unsigned short volatile *len, unsigned short volatile *chan,
+ unsigned short maxlen)
{
struct sk_buff *skb;
@@ -145,10 +148,10 @@ hysdn_sched_tx(hysdn_card * card, uchar * buf, word volatile *len, word volatile
/* are to be sent and this happens very seldom. */
/*****************************************************************************/
int
-hysdn_tx_cfgline(hysdn_card * card, uchar * line, word chan)
+hysdn_tx_cfgline(hysdn_card *card, unsigned char *line, unsigned short chan)
{
int cnt = 50; /* timeout intervalls */
- ulong flags;
+ unsigned long flags;
if (card->debug_flags & LOG_SCHED_ASYN)
hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1);
diff --git a/drivers/isdn/hysdn/ince1pc.h b/drivers/isdn/hysdn/ince1pc.h
index 4a115a87c78..7a36694df6d 100644
--- a/drivers/isdn/hysdn/ince1pc.h
+++ b/drivers/isdn/hysdn/ince1pc.h
@@ -62,7 +62,7 @@
* s. RotlCRC algorithm
*
* RotlCRC algorithm:
- * ucSum= 0 1 uchar
+ * ucSum= 0 1 unsigned char
* for all NonEndTokenChunk bytes:
* ROTL(ucSum,1) rotate left by 1
* ucSum += Char; add current byte with swap around
@@ -85,13 +85,13 @@
typedef struct ErrLogEntry_tag {
-/*00 */ ulong ulErrType;
+/*00 */ unsigned long ulErrType;
-/*04 */ ulong ulErrSubtype;
+/*04 */ unsigned long ulErrSubtype;
-/*08 */ uchar ucTextSize;
+/*08 */ unsigned char ucTextSize;
- /*09 */ uchar ucText[ERRLOG_TEXT_SIZE];
+ /*09 */ unsigned char ucText[ERRLOG_TEXT_SIZE];
/* ASCIIZ of len ucTextSize-1 */
/*40 */
@@ -111,13 +111,13 @@ typedef struct ErrLogEntry_tag {
#define DPRAM_SPOOLER_DATA_SIZE 0x20
typedef struct DpramBootSpooler_tag {
-/*00 */ uchar Len;
+/*00 */ unsigned char Len;
-/*01 */ volatile uchar RdPtr;
+/*01 */ volatile unsigned char RdPtr;
-/*02 */ uchar WrPtr;
+/*02 */ unsigned char WrPtr;
-/*03 */ uchar Data[DPRAM_SPOOLER_DATA_SIZE];
+/*03 */ unsigned char Data[DPRAM_SPOOLER_DATA_SIZE];
/*23 */
} tDpramBootSpooler;
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
index 1789b607f09..a4f7288a1fc 100644
--- a/drivers/isdn/i4l/Kconfig
+++ b/drivers/isdn/i4l/Kconfig
@@ -139,3 +139,4 @@ source "drivers/isdn/hysdn/Kconfig"
endmenu
+source "drivers/isdn/gigaset/Kconfig"
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 1a19a0f8942..a0927d1b7a0 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -782,7 +782,8 @@ isdn_ppp_read(int min, struct file *file, char __user *buf, int count)
is->first = b;
spin_unlock_irqrestore(&is->buflock, flags);
- copy_to_user(buf, save_buf, count);
+ if (copy_to_user(buf, save_buf, count))
+ count = -EFAULT;
kfree(save_buf);
return count;
@@ -973,8 +974,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
int slot;
int proto;
- if (net_dev->local->master)
- BUG(); // we're called with the master device always
+ BUG_ON(net_dev->local->master); // we're called with the master device always
slot = lp->ppp_slot;
if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
@@ -2526,8 +2526,7 @@ static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struc
printk(KERN_DEBUG "ippp: no decompressor defined!\n");
return skb;
}
- if (!stat) // if we have a compressor, stat has been set as well
- BUG();
+ BUG_ON(!stat); // if we have a compressor, stat has been set as well
if((master && *proto == PPP_COMP) || (!master && *proto == PPP_COMPFRAG) ) {
// compressed packets are compressed by their protocol type
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index aeaa1db74bd..3585fb1f334 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -2345,12 +2345,15 @@ isdn_tty_at_cout(char *msg, modem_info * info)
u_long flags;
struct sk_buff *skb = NULL;
char *sp = NULL;
- int l = strlen(msg);
+ int l;
if (!msg) {
printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
return;
}
+
+ l = strlen(msg);
+
spin_lock_irqsave(&info->readlock, flags);
tty = info->tty;
if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {
diff --git a/drivers/isdn/i4l/isdn_x25iface.c b/drivers/isdn/i4l/isdn_x25iface.c
index edf14a2aa3c..743ac4077f3 100644
--- a/drivers/isdn/i4l/isdn_x25iface.c
+++ b/drivers/isdn/i4l/isdn_x25iface.c
@@ -7,7 +7,7 @@
*
* stuff needed to support the Linux X.25 PLP code on top of devices that
* can provide a lab_b service using the concap_proto mechanism.
- * This module supports a network interface wich provides lapb_sematics
+ * This module supports a network interface which provides lapb_sematics
* -- as defined in Documentation/networking/x25-iface.txt -- to
* the upper layer and assumes that the lower layer provides a reliable
* data link service by means of the concap_device_ops callbacks.
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
index 33d33970041..a67d31af797 100644
--- a/drivers/isdn/isdnloop/isdnloop.c
+++ b/drivers/isdn/isdnloop/isdnloop.c
@@ -22,7 +22,7 @@ static char *isdnloop_id = "loop0";
MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card");
MODULE_AUTHOR("Fritz Elfert");
MODULE_LICENSE("GPL");
-MODULE_PARM(isdnloop_id, "s");
+module_param(isdnloop_id, charp, 0);
MODULE_PARM_DESC(isdnloop_id, "ID-String of first card");
static int isdnloop_addcard(char *);
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index d2ead1776c1..259fd8973ce 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -42,6 +42,7 @@
#include <asm/semaphore.h>
#ifdef CONFIG_PPC
#include <asm/prom.h>
+#include <asm/machdep.h>
#endif
@@ -80,7 +81,7 @@ static struct adb_driver *adb_driver_list[] = {
static struct class *adb_dev_class;
struct adb_driver *adb_controller;
-struct notifier_block *adb_client_list = NULL;
+BLOCKING_NOTIFIER_HEAD(adb_client_list);
static int adb_got_sleep;
static int adb_inited;
static pid_t adb_probe_task_pid;
@@ -294,7 +295,7 @@ int __init adb_init(void)
int i;
#ifdef CONFIG_PPC32
- if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
+ if (!machine_is(chrp) && !machine_is(powermac))
return 0;
#endif
#ifdef CONFIG_MAC
@@ -354,7 +355,8 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
/* Stop autopoll */
if (adb_controller->autopoll)
adb_controller->autopoll(0);
- ret = notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL);
+ ret = blocking_notifier_call_chain(&adb_client_list,
+ ADB_MSG_POWERDOWN, NULL);
if (ret & NOTIFY_STOP_MASK) {
up(&adb_probe_mutex);
return PBOOK_SLEEP_REFUSE;
@@ -391,7 +393,8 @@ do_adb_reset_bus(void)
if (adb_controller->autopoll)
adb_controller->autopoll(0);
- nret = notifier_call_chain(&adb_client_list, ADB_MSG_PRE_RESET, NULL);
+ nret = blocking_notifier_call_chain(&adb_client_list,
+ ADB_MSG_PRE_RESET, NULL);
if (nret & NOTIFY_STOP_MASK) {
if (adb_controller->autopoll)
adb_controller->autopoll(autopoll_devs);
@@ -426,7 +429,8 @@ do_adb_reset_bus(void)
}
up(&adb_handler_sem);
- nret = notifier_call_chain(&adb_client_list, ADB_MSG_POST_RESET, NULL);
+ nret = blocking_notifier_call_chain(&adb_client_list,
+ ADB_MSG_POST_RESET, NULL);
if (nret & NOTIFY_STOP_MASK)
return -EBUSY;
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index c0b46bceb5d..394334ec576 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -1206,15 +1206,16 @@ init_ms_a3(int id)
static int __init adbhid_init(void)
{
#ifndef CONFIG_MAC
- if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
- return 0;
+ if (!machine_is(chrp) && !machine_is(powermac))
+ return 0;
#endif
led_request.complete = 1;
adbhid_probe();
- notifier_chain_register(&adb_client_list, &adbhid_adb_notifier);
+ blocking_notifier_chain_register(&adb_client_list,
+ &adbhid_adb_notifier);
return 0;
}
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 8dbf2852bae..53c1c790941 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -839,8 +839,8 @@ static int __init media_bay_init(void)
media_bays[i].cd_index = -1;
#endif
}
- if (_machine != _MACH_Pmac)
- return -ENODEV;
+ if (!machine_is(powermac))
+ return 0;
macio_register_driver(&media_bay_driver);
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index 4eb05d7143d..f4516ca7aa3 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -35,6 +35,7 @@
#include <linux/delay.h>
#include <linux/sysdev.h>
#include <linux/poll.h>
+#include <linux/mutex.h>
#include <asm/byteorder.h>
#include <asm/io.h>
@@ -92,7 +93,7 @@ struct smu_device {
* for now, just hard code that
*/
static struct smu_device *smu;
-static DECLARE_MUTEX(smu_part_access);
+static DEFINE_MUTEX(smu_part_access);
static void smu_i2c_retry(unsigned long data);
@@ -976,11 +977,11 @@ struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size,
if (interruptible) {
int rc;
- rc = down_interruptible(&smu_part_access);
+ rc = mutex_lock_interruptible(&smu_part_access);
if (rc)
return ERR_PTR(rc);
} else
- down(&smu_part_access);
+ mutex_lock(&smu_part_access);
part = (struct smu_sdbp_header *)get_property(smu->of_node,
pname, size);
@@ -990,7 +991,7 @@ struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size,
if (part != NULL && size)
*size = part->len << 2;
}
- up(&smu_part_access);
+ mutex_unlock(&smu_part_access);
return part;
}
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 4f5f3abc9cb..0b5ff553e39 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -187,7 +187,7 @@ extern int disable_kernel_backlight;
int __fake_sleep;
int asleep;
-struct notifier_block *sleep_notifier_list;
+BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
#ifdef CONFIG_ADB
static int adb_dev_map = 0;
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index f08e52f2107..35b70323e7e 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -102,7 +102,7 @@ static int pmu_kind = PMU_UNKNOWN;
static int pmu_fully_inited = 0;
int asleep;
-struct notifier_block *sleep_notifier_list;
+BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
static int pmu_probe(void);
static int pmu_init(void);
@@ -913,7 +913,8 @@ int powerbook_sleep(void)
struct adb_request sleep_req;
/* Notify device drivers */
- ret = notifier_call_chain(&sleep_notifier_list, PBOOK_SLEEP, NULL);
+ ret = blocking_notifier_call_chain(&sleep_notifier_list,
+ PBOOK_SLEEP, NULL);
if (ret & NOTIFY_STOP_MASK)
return -EBUSY;
@@ -984,7 +985,7 @@ int powerbook_sleep(void)
enable_irq(i);
/* Notify drivers */
- notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL);
+ blocking_notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL);
/* reenable ADB autopoll */
pmu_adb_autopoll(adb_dev_map);
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 6c0ba04bc57..ab3faa702d5 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -52,7 +52,7 @@
static LIST_HEAD(wf_controls);
static LIST_HEAD(wf_sensors);
static DEFINE_MUTEX(wf_lock);
-static struct notifier_block *wf_client_list;
+static BLOCKING_NOTIFIER_HEAD(wf_client_list);
static int wf_client_count;
static unsigned int wf_overtemp;
static unsigned int wf_overtemp_counter;
@@ -68,7 +68,7 @@ static struct platform_device wf_platform_device = {
static inline void wf_notify(int event, void *param)
{
- notifier_call_chain(&wf_client_list, event, param);
+ blocking_notifier_call_chain(&wf_client_list, event, param);
}
int wf_critical_overtemp(void)
@@ -398,7 +398,7 @@ int wf_register_client(struct notifier_block *nb)
struct wf_sensor *sr;
mutex_lock(&wf_lock);
- rc = notifier_chain_register(&wf_client_list, nb);
+ rc = blocking_notifier_chain_register(&wf_client_list, nb);
if (rc != 0)
goto bail;
wf_client_count++;
@@ -417,7 +417,7 @@ EXPORT_SYMBOL_GPL(wf_register_client);
int wf_unregister_client(struct notifier_block *nb)
{
mutex_lock(&wf_lock);
- notifier_chain_unregister(&wf_client_list, nb);
+ blocking_notifier_chain_unregister(&wf_client_list, nb);
wf_client_count++;
if (wf_client_count == 0)
wf_stop_thread();
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index ac43f98062f..fd2aae150cc 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -127,6 +127,32 @@ config MD_RAID5
If unsure, say Y.
+config MD_RAID5_RESHAPE
+ bool "Support adding drives to a raid-5 array (experimental)"
+ depends on MD_RAID5 && EXPERIMENTAL
+ ---help---
+ A RAID-5 set can be expanded by adding extra drives. This
+ requires "restriping" the array which means (almost) every
+ block must be written to a different place.
+
+ This option allows such restriping to be done while the array
+ is online. However it is still EXPERIMENTAL code. It should
+ work, but please be sure that you have backups.
+
+ You will need a version of mdadm newer than 2.3.1. During the
+ early stage of reshape there is a critical section where live data
+ is being over-written. A crash during this time needs extra care
+ for recovery. The newer mdadm takes a copy of the data in the
+ critical section and will restore it, if necessary, after a crash.
+
+ The mdadm usage is e.g.
+ mdadm --grow /dev/md1 --raid-disks=6
+ to grow '/dev/md1' to having 6 disks.
+
+ Note: The array can only be expanded, not contracted.
+ There should be enough spares already present to make the new
+ array workable.
+
config MD_RAID6
tristate "RAID-6 mode"
depends on BLK_DEV_MD
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index eae4473eadd..f8ffaee20ff 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -89,16 +89,6 @@ int bitmap_active(struct bitmap *bitmap)
}
#define WRITE_POOL_SIZE 256
-/* mempool for queueing pending writes on the bitmap file */
-static void *write_pool_alloc(gfp_t gfp_flags, void *data)
-{
- return kmalloc(sizeof(struct page_list), gfp_flags);
-}
-
-static void write_pool_free(void *ptr, void *data)
-{
- kfree(ptr);
-}
/*
* just a placeholder - calls kmalloc for bitmap pages
@@ -556,7 +546,7 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
unsigned long flags;
spin_lock_irqsave(&bitmap->lock, flags);
- if (!bitmap || !bitmap->sb_page) { /* can't set the state */
+ if (!bitmap->sb_page) { /* can't set the state */
spin_unlock_irqrestore(&bitmap->lock, flags);
return;
}
@@ -1309,7 +1299,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
case 1:
*bmc = 2;
}
- if ((*bmc & COUNTER_MAX) == COUNTER_MAX) BUG();
+ BUG_ON((*bmc & COUNTER_MAX) == COUNTER_MAX);
(*bmc)++;
spin_unlock_irq(&bitmap->lock);
@@ -1564,8 +1554,8 @@ int bitmap_create(mddev_t *mddev)
spin_lock_init(&bitmap->write_lock);
INIT_LIST_HEAD(&bitmap->complete_pages);
init_waitqueue_head(&bitmap->write_wait);
- bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc,
- write_pool_free, NULL);
+ bitmap->write_pool = mempool_create_kmalloc_pool(WRITE_POOL_SIZE,
+ sizeof(struct page_list));
err = -ENOMEM;
if (!bitmap->write_pool)
goto error;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index e7a650f9ca0..61a590bb624 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -94,20 +94,6 @@ struct crypt_config {
static kmem_cache_t *_crypt_io_pool;
/*
- * Mempool alloc and free functions for the page
- */
-static void *mempool_alloc_page(gfp_t gfp_mask, void *data)
-{
- return alloc_page(gfp_mask);
-}
-
-static void mempool_free_page(void *page, void *data)
-{
- __free_page(page);
-}
-
-
-/*
* Different IV generation algorithms:
*
* plain: the initial vector is the 32-bit low-endian version of the sector
@@ -532,6 +518,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
char *ivopts;
unsigned int crypto_flags;
unsigned int key_size;
+ unsigned long long tmpll;
if (argc != 5) {
ti->error = PFX "Not enough arguments";
@@ -630,15 +617,13 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
}
}
- cc->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
- mempool_free_slab, _crypt_io_pool);
+ cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool);
if (!cc->io_pool) {
ti->error = PFX "Cannot allocate crypt io mempool";
goto bad3;
}
- cc->page_pool = mempool_create(MIN_POOL_PAGES, mempool_alloc_page,
- mempool_free_page, NULL);
+ cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0);
if (!cc->page_pool) {
ti->error = PFX "Cannot allocate page mempool";
goto bad4;
@@ -649,15 +634,17 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad5;
}
- if (sscanf(argv[2], SECTOR_FORMAT, &cc->iv_offset) != 1) {
+ if (sscanf(argv[2], "%llu", &tmpll) != 1) {
ti->error = PFX "Invalid iv_offset sector";
goto bad5;
}
+ cc->iv_offset = tmpll;
- if (sscanf(argv[4], SECTOR_FORMAT, &cc->start) != 1) {
+ if (sscanf(argv[4], "%llu", &tmpll) != 1) {
ti->error = PFX "Invalid device sector";
goto bad5;
}
+ cc->start = tmpll;
if (dm_get_device(ti, argv[3], cc->start, ti->len,
dm_table_get_mode(ti->table), &cc->dev)) {
@@ -901,8 +888,8 @@ static int crypt_status(struct dm_target *ti, status_type_t type,
result[sz++] = '-';
}
- DMEMIT(" " SECTOR_FORMAT " %s " SECTOR_FORMAT,
- cc->iv_offset, cc->dev->name, cc->start);
+ DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset,
+ cc->dev->name, (unsigned long long)cc->start);
break;
}
return 0;
diff --git a/drivers/md/dm-hw-handler.c b/drivers/md/dm-hw-handler.c
index 4cc0010e015..baafaaba4d4 100644
--- a/drivers/md/dm-hw-handler.c
+++ b/drivers/md/dm-hw-handler.c
@@ -83,8 +83,7 @@ void dm_put_hw_handler(struct hw_handler_type *hwht)
if (--hwhi->use == 0)
module_put(hwhi->hwht.module);
- if (hwhi->use < 0)
- BUG();
+ BUG_ON(hwhi->use < 0);
out:
up_read(&_hwh_lock);
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 4809b209fbb..da663d2ff55 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -32,16 +32,6 @@ struct io {
static unsigned _num_ios;
static mempool_t *_io_pool;
-static void *alloc_io(gfp_t gfp_mask, void *pool_data)
-{
- return kmalloc(sizeof(struct io), gfp_mask);
-}
-
-static void free_io(void *element, void *pool_data)
-{
- kfree(element);
-}
-
static unsigned int pages_to_ios(unsigned int pages)
{
return 4 * pages; /* too many ? */
@@ -65,7 +55,8 @@ static int resize_pool(unsigned int new_ios)
} else {
/* create new pool */
- _io_pool = mempool_create(new_ios, alloc_io, free_io, NULL);
+ _io_pool = mempool_create_kmalloc_pool(new_ios,
+ sizeof(struct io));
if (!_io_pool)
return -ENOMEM;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 442e2be6052..8edd6435414 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/dm-ioctl.h>
+#include <linux/hdreg.h>
#include <asm/uaccess.h>
@@ -244,9 +245,9 @@ static void __hash_remove(struct hash_cell *hc)
dm_table_put(table);
}
- dm_put(hc->md);
if (hc->new_map)
dm_table_put(hc->new_map);
+ dm_put(hc->md);
free_cell(hc);
}
@@ -600,12 +601,22 @@ static int dev_create(struct dm_ioctl *param, size_t param_size)
*/
static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
{
+ struct mapped_device *md;
+ void *mdptr = NULL;
+
if (*param->uuid)
return __get_uuid_cell(param->uuid);
- else if (*param->name)
+
+ if (*param->name)
return __get_name_cell(param->name);
- else
- return dm_get_mdptr(huge_decode_dev(param->dev));
+
+ md = dm_get_md(huge_decode_dev(param->dev));
+ if (md) {
+ mdptr = dm_get_mdptr(md);
+ dm_put(md);
+ }
+
+ return mdptr;
}
static struct mapped_device *find_device(struct dm_ioctl *param)
@@ -690,6 +701,54 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size)
return dm_hash_rename(param->name, new_name);
}
+static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
+{
+ int r = -EINVAL, x;
+ struct mapped_device *md;
+ struct hd_geometry geometry;
+ unsigned long indata[4];
+ char *geostr = (char *) param + param->data_start;
+
+ md = find_device(param);
+ if (!md)
+ return -ENXIO;
+
+ if (geostr < (char *) (param + 1) ||
+ invalid_str(geostr, (void *) param + param_size)) {
+ DMWARN("Invalid geometry supplied.");
+ goto out;
+ }
+
+ x = sscanf(geostr, "%lu %lu %lu %lu", indata,
+ indata + 1, indata + 2, indata + 3);
+
+ if (x != 4) {
+ DMWARN("Unable to interpret geometry settings.");
+ goto out;
+ }
+
+ if (indata[0] > 65535 || indata[1] > 255 ||
+ indata[2] > 255 || indata[3] > ULONG_MAX) {
+ DMWARN("Geometry exceeds range limits.");
+ goto out;
+ }
+
+ geometry.cylinders = indata[0];
+ geometry.heads = indata[1];
+ geometry.sectors = indata[2];
+ geometry.start = indata[3];
+
+ r = dm_set_geometry(md, &geometry);
+ if (!r)
+ r = __dev_status(md, param);
+
+ param->data_size = 0;
+
+out:
+ dm_put(md);
+ return r;
+}
+
static int do_suspend(struct dm_ioctl *param)
{
int r = 0;
@@ -975,33 +1034,43 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
int r;
struct hash_cell *hc;
struct dm_table *t;
+ struct mapped_device *md;
- r = dm_table_create(&t, get_mode(param), param->target_count);
+ md = find_device(param);
+ if (!md)
+ return -ENXIO;
+
+ r = dm_table_create(&t, get_mode(param), param->target_count, md);
if (r)
- return r;
+ goto out;
r = populate_table(t, param, param_size);
if (r) {
dm_table_put(t);
- return r;
+ goto out;
}
down_write(&_hash_lock);
- hc = __find_device_hash_cell(param);
- if (!hc) {
- DMWARN("device doesn't appear to be in the dev hash table.");
- up_write(&_hash_lock);
+ hc = dm_get_mdptr(md);
+ if (!hc || hc->md != md) {
+ DMWARN("device has been removed from the dev hash table.");
dm_table_put(t);
- return -ENXIO;
+ up_write(&_hash_lock);
+ r = -ENXIO;
+ goto out;
}
if (hc->new_map)
dm_table_put(hc->new_map);
hc->new_map = t;
+ up_write(&_hash_lock);
+
param->flags |= DM_INACTIVE_PRESENT_FLAG;
+ r = __dev_status(md, param);
+
+out:
+ dm_put(md);
- r = __dev_status(hc->md, param);
- up_write(&_hash_lock);
return r;
}
@@ -1214,7 +1283,8 @@ static ioctl_fn lookup_ioctl(unsigned int cmd)
{DM_LIST_VERSIONS_CMD, list_versions},
- {DM_TARGET_MSG_CMD, target_message}
+ {DM_TARGET_MSG_CMD, target_message},
+ {DM_DEV_SET_GEOMETRY_CMD, dev_set_geometry}
};
return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn;
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 6a2cd5dc8a6..daf586c0898 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -26,6 +26,7 @@ struct linear_c {
static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
struct linear_c *lc;
+ unsigned long long tmp;
if (argc != 2) {
ti->error = "dm-linear: Invalid argument count";
@@ -38,10 +39,11 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
return -ENOMEM;
}
- if (sscanf(argv[1], SECTOR_FORMAT, &lc->start) != 1) {
+ if (sscanf(argv[1], "%llu", &tmp) != 1) {
ti->error = "dm-linear: Invalid device sector";
goto bad;
}
+ lc->start = tmp;
if (dm_get_device(ti, argv[0], lc->start, ti->len,
dm_table_get_mode(ti->table), &lc->dev)) {
@@ -87,8 +89,8 @@ static int linear_status(struct dm_target *ti, status_type_t type,
break;
case STATUSTYPE_TABLE:
- snprintf(result, maxlen, "%s " SECTOR_FORMAT, lc->dev->name,
- lc->start);
+ snprintf(result, maxlen, "%s %llu", lc->dev->name,
+ (unsigned long long)lc->start);
break;
}
return 0;
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index f72a82fb943..1816f30678e 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -179,8 +179,7 @@ static struct multipath *alloc_multipath(void)
m->queue_io = 1;
INIT_WORK(&m->process_queued_ios, process_queued_ios, m);
INIT_WORK(&m->trigger_event, trigger_event, m);
- m->mpio_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
- mempool_free_slab, _mpio_cache);
+ m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache);
if (!m->mpio_pool) {
kfree(m);
return NULL;
diff --git a/drivers/md/dm-path-selector.c b/drivers/md/dm-path-selector.c
index a28c1c2b4ef..f10a0c89b3f 100644
--- a/drivers/md/dm-path-selector.c
+++ b/drivers/md/dm-path-selector.c
@@ -86,8 +86,7 @@ void dm_put_path_selector(struct path_selector_type *pst)
if (--psi->use == 0)
module_put(psi->pst.module);
- if (psi->use < 0)
- BUG();
+ BUG_ON(psi->use < 0);
out:
up_read(&_ps_lock);
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 6cfa8d435d5..d12cf3e5e07 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -122,16 +122,6 @@ static inline sector_t region_to_sector(struct region_hash *rh, region_t region)
/* FIXME move this */
static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw);
-static void *region_alloc(gfp_t gfp_mask, void *pool_data)
-{
- return kmalloc(sizeof(struct region), gfp_mask);
-}
-
-static void region_free(void *element, void *pool_data)
-{
- kfree(element);
-}
-
#define MIN_REGIONS 64
#define MAX_RECOVERY 1
static int rh_init(struct region_hash *rh, struct mirror_set *ms,
@@ -173,8 +163,8 @@ static int rh_init(struct region_hash *rh, struct mirror_set *ms,
INIT_LIST_HEAD(&rh->quiesced_regions);
INIT_LIST_HEAD(&rh->recovered_regions);
- rh->region_pool = mempool_create(MIN_REGIONS, region_alloc,
- region_free, NULL);
+ rh->region_pool = mempool_create_kmalloc_pool(MIN_REGIONS,
+ sizeof(struct region));
if (!rh->region_pool) {
vfree(rh->buckets);
rh->buckets = NULL;
@@ -412,9 +402,21 @@ static void rh_dec(struct region_hash *rh, region_t region)
spin_lock_irqsave(&rh->region_lock, flags);
if (atomic_dec_and_test(&reg->pending)) {
+ /*
+ * There is no pending I/O for this region.
+ * We can move the region to corresponding list for next action.
+ * At this point, the region is not yet connected to any list.
+ *
+ * If the state is RH_NOSYNC, the region should be kept off
+ * from clean list.
+ * The hash entry for RH_NOSYNC will remain in memory
+ * until the region is recovered or the map is reloaded.
+ */
+
+ /* do nothing for RH_NOSYNC */
if (reg->state == RH_RECOVERING) {
list_add_tail(&reg->list, &rh->quiesced_regions);
- } else {
+ } else if (reg->state == RH_DIRTY) {
reg->state = RH_CLEAN;
list_add(&reg->list, &rh->clean_regions);
}
@@ -932,9 +934,9 @@ static inline int _check_region_size(struct dm_target *ti, uint32_t size)
static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
unsigned int mirror, char **argv)
{
- sector_t offset;
+ unsigned long long offset;
- if (sscanf(argv[1], SECTOR_FORMAT, &offset) != 1) {
+ if (sscanf(argv[1], "%llu", &offset) != 1) {
ti->error = "dm-mirror: Invalid offset";
return -EINVAL;
}
@@ -1201,16 +1203,17 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
for (m = 0; m < ms->nr_mirrors; m++)
DMEMIT("%s ", ms->mirror[m].dev->name);
- DMEMIT(SECTOR_FORMAT "/" SECTOR_FORMAT,
- ms->rh.log->type->get_sync_count(ms->rh.log),
- ms->nr_regions);
+ DMEMIT("%llu/%llu",
+ (unsigned long long)ms->rh.log->type->
+ get_sync_count(ms->rh.log),
+ (unsigned long long)ms->nr_regions);
break;
case STATUSTYPE_TABLE:
DMEMIT("%d ", ms->nr_mirrors);
for (m = 0; m < ms->nr_mirrors; m++)
- DMEMIT("%s " SECTOR_FORMAT " ",
- ms->mirror[m].dev->name, ms->mirror[m].offset);
+ DMEMIT("%s %llu ", ms->mirror[m].dev->name,
+ (unsigned long long)ms->mirror[m].offset);
}
return 0;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index f3759dd7828..08312b46463 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -49,11 +49,26 @@ struct pending_exception {
struct bio_list snapshot_bios;
/*
- * Other pending_exceptions that are processing this
- * chunk. When this list is empty, we know we can
- * complete the origins.
+ * Short-term queue of pending exceptions prior to submission.
*/
- struct list_head siblings;
+ struct list_head list;
+
+ /*
+ * The primary pending_exception is the one that holds
+ * the sibling_count and the list of origin_bios for a
+ * group of pending_exceptions. It is always last to get freed.
+ * These fields get set up when writing to the origin.
+ */
+ struct pending_exception *primary_pe;
+
+ /*
+ * Number of pending_exceptions processing this chunk.
+ * When this drops to zero we must complete the origin bios.
+ * If incrementing or decrementing this, hold pe->snap->lock for
+ * the sibling concerned and not pe->primary_pe->snap->lock unless
+ * they are the same.
+ */
+ atomic_t sibling_count;
/* Pointer back to snapshot context */
struct dm_snapshot *snap;
@@ -377,6 +392,8 @@ static void read_snapshot_metadata(struct dm_snapshot *s)
down_write(&s->lock);
s->valid = 0;
up_write(&s->lock);
+
+ dm_table_event(s->table);
}
}
@@ -542,8 +559,12 @@ static void snapshot_dtr(struct dm_target *ti)
{
struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+ /* Prevent further origin writes from using this snapshot. */
+ /* After this returns there can be no new kcopyd jobs. */
unregister_snapshot(s);
+ kcopyd_client_destroy(s->kcopyd_client);
+
exit_exception_table(&s->pending, pending_cache);
exit_exception_table(&s->complete, exception_cache);
@@ -552,7 +573,7 @@ static void snapshot_dtr(struct dm_target *ti)
dm_put_device(ti, s->origin);
dm_put_device(ti, s->cow);
- kcopyd_client_destroy(s->kcopyd_client);
+
kfree(s);
}
@@ -586,78 +607,117 @@ static void error_bios(struct bio *bio)
}
}
+static inline void error_snapshot_bios(struct pending_exception *pe)
+{
+ error_bios(bio_list_get(&pe->snapshot_bios));
+}
+
static struct bio *__flush_bios(struct pending_exception *pe)
{
- struct pending_exception *sibling;
+ /*
+ * If this pe is involved in a write to the origin and
+ * it is the last sibling to complete then release
+ * the bios for the original write to the origin.
+ */
+
+ if (pe->primary_pe &&
+ atomic_dec_and_test(&pe->primary_pe->sibling_count))
+ return bio_list_get(&pe->primary_pe->origin_bios);
+
+ return NULL;
+}
+
+static void __invalidate_snapshot(struct dm_snapshot *s,
+ struct pending_exception *pe, int err)
+{
+ if (!s->valid)
+ return;
- if (list_empty(&pe->siblings))
- return bio_list_get(&pe->origin_bios);
+ if (err == -EIO)
+ DMERR("Invalidating snapshot: Error reading/writing.");
+ else if (err == -ENOMEM)
+ DMERR("Invalidating snapshot: Unable to allocate exception.");
- sibling = list_entry(pe->siblings.next,
- struct pending_exception, siblings);
+ if (pe)
+ remove_exception(&pe->e);
- list_del(&pe->siblings);
+ if (s->store.drop_snapshot)
+ s->store.drop_snapshot(&s->store);
- /* This is fine as long as kcopyd is single-threaded. If kcopyd
- * becomes multi-threaded, we'll need some locking here.
- */
- bio_list_merge(&sibling->origin_bios, &pe->origin_bios);
+ s->valid = 0;
- return NULL;
+ dm_table_event(s->table);
}
static void pending_complete(struct pending_exception *pe, int success)
{
struct exception *e;
+ struct pending_exception *primary_pe;
struct dm_snapshot *s = pe->snap;
struct bio *flush = NULL;
- if (success) {
- e = alloc_exception();
- if (!e) {
- DMWARN("Unable to allocate exception.");
- down_write(&s->lock);
- s->store.drop_snapshot(&s->store);
- s->valid = 0;
- flush = __flush_bios(pe);
- up_write(&s->lock);
-
- error_bios(bio_list_get(&pe->snapshot_bios));
- goto out;
- }
- *e = pe->e;
-
- /*
- * Add a proper exception, and remove the
- * in-flight exception from the list.
- */
+ if (!success) {
+ /* Read/write error - snapshot is unusable */
down_write(&s->lock);
- insert_exception(&s->complete, e);
- remove_exception(&pe->e);
+ __invalidate_snapshot(s, pe, -EIO);
flush = __flush_bios(pe);
-
- /* Submit any pending write bios */
up_write(&s->lock);
- flush_bios(bio_list_get(&pe->snapshot_bios));
- } else {
- /* Read/write error - snapshot is unusable */
+ error_snapshot_bios(pe);
+ goto out;
+ }
+
+ e = alloc_exception();
+ if (!e) {
down_write(&s->lock);
- if (s->valid)
- DMERR("Error reading/writing snapshot");
- s->store.drop_snapshot(&s->store);
- s->valid = 0;
- remove_exception(&pe->e);
+ __invalidate_snapshot(s, pe, -ENOMEM);
flush = __flush_bios(pe);
up_write(&s->lock);
- error_bios(bio_list_get(&pe->snapshot_bios));
+ error_snapshot_bios(pe);
+ goto out;
+ }
+ *e = pe->e;
- dm_table_event(s->table);
+ /*
+ * Add a proper exception, and remove the
+ * in-flight exception from the list.
+ */
+ down_write(&s->lock);
+ if (!s->valid) {
+ flush = __flush_bios(pe);
+ up_write(&s->lock);
+
+ free_exception(e);
+
+ error_snapshot_bios(pe);
+ goto out;
}
+ insert_exception(&s->complete, e);
+ remove_exception(&pe->e);
+ flush = __flush_bios(pe);
+
+ up_write(&s->lock);
+
+ /* Submit any pending write bios */
+ flush_bios(bio_list_get(&pe->snapshot_bios));
+
out:
- free_pending_exception(pe);
+ primary_pe = pe->primary_pe;
+
+ /*
+ * Free the pe if it's not linked to an origin write or if
+ * it's not itself a primary pe.
+ */
+ if (!primary_pe || primary_pe != pe)
+ free_pending_exception(pe);
+
+ /*
+ * Free the primary pe if nothing references it.
+ */
+ if (primary_pe && !atomic_read(&primary_pe->sibling_count))
+ free_pending_exception(primary_pe);
if (flush)
flush_bios(flush);
@@ -734,38 +794,45 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
if (e) {
/* cast the exception to a pending exception */
pe = container_of(e, struct pending_exception, e);
+ goto out;
+ }
- } else {
- /*
- * Create a new pending exception, we don't want
- * to hold the lock while we do this.
- */
- up_write(&s->lock);
- pe = alloc_pending_exception();
- down_write(&s->lock);
+ /*
+ * Create a new pending exception, we don't want
+ * to hold the lock while we do this.
+ */
+ up_write(&s->lock);
+ pe = alloc_pending_exception();
+ down_write(&s->lock);
- e = lookup_exception(&s->pending, chunk);
- if (e) {
- free_pending_exception(pe);
- pe = container_of(e, struct pending_exception, e);
- } else {
- pe->e.old_chunk = chunk;
- bio_list_init(&pe->origin_bios);
- bio_list_init(&pe->snapshot_bios);
- INIT_LIST_HEAD(&pe->siblings);
- pe->snap = s;
- pe->started = 0;
-
- if (s->store.prepare_exception(&s->store, &pe->e)) {
- free_pending_exception(pe);
- s->valid = 0;
- return NULL;
- }
+ if (!s->valid) {
+ free_pending_exception(pe);
+ return NULL;
+ }
- insert_exception(&s->pending, &pe->e);
- }
+ e = lookup_exception(&s->pending, chunk);
+ if (e) {
+ free_pending_exception(pe);
+ pe = container_of(e, struct pending_exception, e);
+ goto out;
+ }
+
+ pe->e.old_chunk = chunk;
+ bio_list_init(&pe->origin_bios);
+ bio_list_init(&pe->snapshot_bios);
+ pe->primary_pe = NULL;
+ atomic_set(&pe->sibling_count, 1);
+ pe->snap = s;
+ pe->started = 0;
+
+ if (s->store.prepare_exception(&s->store, &pe->e)) {
+ free_pending_exception(pe);
+ return NULL;
}
+ insert_exception(&s->pending, &pe->e);
+
+ out:
return pe;
}
@@ -782,13 +849,15 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
{
struct exception *e;
struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+ int copy_needed = 0;
int r = 1;
chunk_t chunk;
- struct pending_exception *pe;
+ struct pending_exception *pe = NULL;
chunk = sector_to_chunk(s, bio->bi_sector);
/* Full snapshots are not usable */
+ /* To get here the table must be live so s->active is always set. */
if (!s->valid)
return -EIO;
@@ -806,36 +875,41 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
* to copy an exception */
down_write(&s->lock);
+ if (!s->valid) {
+ r = -EIO;
+ goto out_unlock;
+ }
+
/* If the block is already remapped - use that, else remap it */
e = lookup_exception(&s->complete, chunk);
if (e) {
remap_exception(s, e, bio);
- up_write(&s->lock);
-
- } else {
- pe = __find_pending_exception(s, bio);
-
- if (!pe) {
- if (s->store.drop_snapshot)
- s->store.drop_snapshot(&s->store);
- s->valid = 0;
- r = -EIO;
- up_write(&s->lock);
- } else {
- remap_exception(s, &pe->e, bio);
- bio_list_add(&pe->snapshot_bios, bio);
-
- if (!pe->started) {
- /* this is protected by snap->lock */
- pe->started = 1;
- up_write(&s->lock);
- start_copy(pe);
- } else
- up_write(&s->lock);
- r = 0;
- }
+ goto out_unlock;
+ }
+
+ pe = __find_pending_exception(s, bio);
+ if (!pe) {
+ __invalidate_snapshot(s, pe, -ENOMEM);
+ r = -EIO;
+ goto out_unlock;
+ }
+
+ remap_exception(s, &pe->e, bio);
+ bio_list_add(&pe->snapshot_bios, bio);
+
+ if (!pe->started) {
+ /* this is protected by snap->lock */
+ pe->started = 1;
+ copy_needed = 1;
}
+ r = 0;
+
+ out_unlock:
+ up_write(&s->lock);
+
+ if (copy_needed)
+ start_copy(pe);
} else {
/*
* FIXME: this read path scares me because we
@@ -847,6 +921,11 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
/* Do reads */
down_read(&s->lock);
+ if (!s->valid) {
+ up_read(&s->lock);
+ return -EIO;
+ }
+
/* See if it it has been remapped */
e = lookup_exception(&s->complete, chunk);
if (e)
@@ -884,9 +963,9 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
snap->store.fraction_full(&snap->store,
&numerator,
&denominator);
- snprintf(result, maxlen,
- SECTOR_FORMAT "/" SECTOR_FORMAT,
- numerator, denominator);
+ snprintf(result, maxlen, "%llu/%llu",
+ (unsigned long long)numerator,
+ (unsigned long long)denominator);
}
else
snprintf(result, maxlen, "Unknown");
@@ -899,9 +978,10 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
* to make private copies if the output is to
* make sense.
*/
- snprintf(result, maxlen, "%s %s %c " SECTOR_FORMAT,
+ snprintf(result, maxlen, "%s %s %c %llu",
snap->origin->name, snap->cow->name,
- snap->type, snap->chunk_size);
+ snap->type,
+ (unsigned long long)snap->chunk_size);
break;
}
@@ -911,40 +991,27 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
/*-----------------------------------------------------------------
* Origin methods
*---------------------------------------------------------------*/
-static void list_merge(struct list_head *l1, struct list_head *l2)
-{
- struct list_head *l1_n, *l2_p;
-
- l1_n = l1->next;
- l2_p = l2->prev;
-
- l1->next = l2;
- l2->prev = l1;
-
- l2_p->next = l1_n;
- l1_n->prev = l2_p;
-}
-
static int __origin_write(struct list_head *snapshots, struct bio *bio)
{
- int r = 1, first = 1;
+ int r = 1, first = 0;
struct dm_snapshot *snap;
struct exception *e;
- struct pending_exception *pe, *last = NULL;
+ struct pending_exception *pe, *next_pe, *primary_pe = NULL;
chunk_t chunk;
+ LIST_HEAD(pe_queue);
/* Do all the snapshots on this origin */
list_for_each_entry (snap, snapshots, list) {
+ down_write(&snap->lock);
+
/* Only deal with valid and active snapshots */
if (!snap->valid || !snap->active)
- continue;
+ goto next_snapshot;
/* Nothing to do if writing beyond end of snapshot */
if (bio->bi_sector >= dm_table_get_size(snap->table))
- continue;
-
- down_write(&snap->lock);
+ goto next_snapshot;
/*
* Remember, different snapshots can have
@@ -956,49 +1023,75 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
* Check exception table to see if block
* is already remapped in this snapshot
* and trigger an exception if not.
+ *
+ * sibling_count is initialised to 1 so pending_complete()
+ * won't destroy the primary_pe while we're inside this loop.
*/
e = lookup_exception(&snap->complete, chunk);
- if (!e) {
- pe = __find_pending_exception(snap, bio);
- if (!pe) {
- snap->store.drop_snapshot(&snap->store);
- snap->valid = 0;
-
- } else {
- if (last)
- list_merge(&pe->siblings,
- &last->siblings);
-
- last = pe;
- r = 0;
+ if (e)
+ goto next_snapshot;
+
+ pe = __find_pending_exception(snap, bio);
+ if (!pe) {
+ __invalidate_snapshot(snap, pe, ENOMEM);
+ goto next_snapshot;
+ }
+
+ if (!primary_pe) {
+ /*
+ * Either every pe here has same
+ * primary_pe or none has one yet.
+ */
+ if (pe->primary_pe)
+ primary_pe = pe->primary_pe;
+ else {
+ primary_pe = pe;
+ first = 1;
}
+
+ bio_list_add(&primary_pe->origin_bios, bio);
+
+ r = 0;
+ }
+
+ if (!pe->primary_pe) {
+ atomic_inc(&primary_pe->sibling_count);
+ pe->primary_pe = primary_pe;
+ }
+
+ if (!pe->started) {
+ pe->started = 1;
+ list_add_tail(&pe->list, &pe_queue);
}
+ next_snapshot:
up_write(&snap->lock);
}
+ if (!primary_pe)
+ goto out;
+
/*
- * Now that we have a complete pe list we can start the copying.
+ * If this is the first time we're processing this chunk and
+ * sibling_count is now 1 it means all the pending exceptions
+ * got completed while we were in the loop above, so it falls to
+ * us here to remove the primary_pe and submit any origin_bios.
*/
- if (last) {
- pe = last;
- do {
- down_write(&pe->snap->lock);
- if (first)
- bio_list_add(&pe->origin_bios, bio);
- if (!pe->started) {
- pe->started = 1;
- up_write(&pe->snap->lock);
- start_copy(pe);
- } else
- up_write(&pe->snap->lock);
- first = 0;
- pe = list_entry(pe->siblings.next,
- struct pending_exception, siblings);
-
- } while (pe != last);
+
+ if (first && atomic_dec_and_test(&primary_pe->sibling_count)) {
+ flush_bios(bio_list_get(&primary_pe->origin_bios));
+ free_pending_exception(primary_pe);
+ /* If we got here, pe_queue is necessarily empty. */
+ goto out;
}
+ /*
+ * Now that we have a complete pe list we can start the copying.
+ */
+ list_for_each_entry_safe(pe, next_pe, &pe_queue, list)
+ start_copy(pe);
+
+ out:
return r;
}
@@ -1174,8 +1267,7 @@ static int __init dm_snapshot_init(void)
goto bad4;
}
- pending_pool = mempool_create(128, mempool_alloc_slab,
- mempool_free_slab, pending_cache);
+ pending_pool = mempool_create_slab_pool(128, pending_cache);
if (!pending_pool) {
DMERR("Couldn't create pending pool.");
r = -ENOMEM;
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 697aacafb02..08328a8f5a3 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -49,9 +49,9 @@ static inline struct stripe_c *alloc_context(unsigned int stripes)
static int get_stripe(struct dm_target *ti, struct stripe_c *sc,
unsigned int stripe, char **argv)
{
- sector_t start;
+ unsigned long long start;
- if (sscanf(argv[1], SECTOR_FORMAT, &start) != 1)
+ if (sscanf(argv[1], "%llu", &start) != 1)
return -EINVAL;
if (dm_get_device(ti, argv[0], start, sc->stripe_width,
@@ -103,7 +103,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
return -EINVAL;
}
- if (((uint32_t)ti->len) & (chunk_size - 1)) {
+ if (ti->len & (chunk_size - 1)) {
ti->error = "dm-stripe: Target length not divisible by "
"chunk size";
return -EINVAL;
@@ -201,10 +201,11 @@ static int stripe_status(struct dm_target *ti,
break;
case STATUSTYPE_TABLE:
- DMEMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1);
+ DMEMIT("%d %llu", sc->stripes,
+ (unsigned long long)sc->chunk_mask + 1);
for (i = 0; i < sc->stripes; i++)
- DMEMIT(" %s " SECTOR_FORMAT, sc->stripe[i].dev->name,
- sc->stripe[i].physical_start);
+ DMEMIT(" %s %llu", sc->stripe[i].dev->name,
+ (unsigned long long)sc->stripe[i].physical_start);
break;
}
return 0;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 9b1e2f5ca63..8f56a54cf0c 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -14,6 +14,7 @@
#include <linux/ctype.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
+#include <linux/mutex.h>
#include <asm/atomic.h>
#define MAX_DEPTH 16
@@ -22,6 +23,7 @@
#define CHILDREN_PER_NODE (KEYS_PER_NODE + 1)
struct dm_table {
+ struct mapped_device *md;
atomic_t holders;
/* btree table */
@@ -97,6 +99,8 @@ static void combine_restrictions_low(struct io_restrictions *lhs,
lhs->seg_boundary_mask =
min_not_zero(lhs->seg_boundary_mask, rhs->seg_boundary_mask);
+
+ lhs->no_cluster |= rhs->no_cluster;
}
/*
@@ -204,7 +208,8 @@ static int alloc_targets(struct dm_table *t, unsigned int num)
return 0;
}
-int dm_table_create(struct dm_table **result, int mode, unsigned num_targets)
+int dm_table_create(struct dm_table **result, int mode,
+ unsigned num_targets, struct mapped_device *md)
{
struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL);
@@ -227,6 +232,7 @@ int dm_table_create(struct dm_table **result, int mode, unsigned num_targets)
}
t->mode = mode;
+ t->md = md;
*result = t;
return 0;
}
@@ -345,20 +351,19 @@ static struct dm_dev *find_device(struct list_head *l, dev_t dev)
/*
* Open a device so we can use it as a map destination.
*/
-static int open_dev(struct dm_dev *d, dev_t dev)
+static int open_dev(struct dm_dev *d, dev_t dev, struct mapped_device *md)
{
static char *_claim_ptr = "I belong to device-mapper";
struct block_device *bdev;
int r;
- if (d->bdev)
- BUG();
+ BUG_ON(d->bdev);
bdev = open_by_devnum(dev, d->mode);
if (IS_ERR(bdev))
return PTR_ERR(bdev);
- r = bd_claim(bdev, _claim_ptr);
+ r = bd_claim_by_disk(bdev, _claim_ptr, dm_disk(md));
if (r)
blkdev_put(bdev);
else
@@ -369,12 +374,12 @@ static int open_dev(struct dm_dev *d, dev_t dev)
/*
* Close a device that we've been using.
*/
-static void close_dev(struct dm_dev *d)
+static void close_dev(struct dm_dev *d, struct mapped_device *md)
{
if (!d->bdev)
return;
- bd_release(d->bdev);
+ bd_release_from_disk(d->bdev, dm_disk(md));
blkdev_put(d->bdev);
d->bdev = NULL;
}
@@ -395,7 +400,7 @@ static int check_device_area(struct dm_dev *dd, sector_t start, sector_t len)
* careful to leave things as they were if we fail to reopen the
* device.
*/
-static int upgrade_mode(struct dm_dev *dd, int new_mode)
+static int upgrade_mode(struct dm_dev *dd, int new_mode, struct mapped_device *md)
{
int r;
struct dm_dev dd_copy;
@@ -405,9 +410,9 @@ static int upgrade_mode(struct dm_dev *dd, int new_mode)
dd->mode |= new_mode;
dd->bdev = NULL;
- r = open_dev(dd, dev);
+ r = open_dev(dd, dev, md);
if (!r)
- close_dev(&dd_copy);
+ close_dev(&dd_copy, md);
else
*dd = dd_copy;
@@ -427,8 +432,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
struct dm_dev *dd;
unsigned int major, minor;
- if (!t)
- BUG();
+ BUG_ON(!t);
if (sscanf(path, "%u:%u", &major, &minor) == 2) {
/* Extract the major/minor numbers */
@@ -450,7 +454,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
dd->mode = mode;
dd->bdev = NULL;
- if ((r = open_dev(dd, dev))) {
+ if ((r = open_dev(dd, dev, t->md))) {
kfree(dd);
return r;
}
@@ -461,7 +465,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
list_add(&dd->list, &t->devices);
} else if (dd->mode != (mode | dd->mode)) {
- r = upgrade_mode(dd, mode);
+ r = upgrade_mode(dd, mode, t->md);
if (r)
return r;
}
@@ -525,6 +529,8 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
rs->seg_boundary_mask =
min_not_zero(rs->seg_boundary_mask,
q->seg_boundary_mask);
+
+ rs->no_cluster |= !test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
}
return r;
@@ -536,7 +542,7 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
void dm_put_device(struct dm_target *ti, struct dm_dev *dd)
{
if (atomic_dec_and_test(&dd->count)) {
- close_dev(dd);
+ close_dev(dd, ti->table->md);
list_del(&dd->list);
kfree(dd);
}
@@ -765,14 +771,14 @@ int dm_table_complete(struct dm_table *t)
return r;
}
-static DECLARE_MUTEX(_event_lock);
+static DEFINE_MUTEX(_event_lock);
void dm_table_event_callback(struct dm_table *t,
void (*fn)(void *), void *context)
{
- down(&_event_lock);
+ mutex_lock(&_event_lock);
t->event_fn = fn;
t->event_context = context;
- up(&_event_lock);
+ mutex_unlock(&_event_lock);
}
void dm_table_event(struct dm_table *t)
@@ -783,10 +789,10 @@ void dm_table_event(struct dm_table *t)
*/
BUG_ON(in_interrupt());
- down(&_event_lock);
+ mutex_lock(&_event_lock);
if (t->event_fn)
t->event_fn(t->event_context);
- up(&_event_lock);
+ mutex_unlock(&_event_lock);
}
sector_t dm_table_get_size(struct dm_table *t)
@@ -834,6 +840,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q)
q->hardsect_size = t->limits.hardsect_size;
q->max_segment_size = t->limits.max_segment_size;
q->seg_boundary_mask = t->limits.seg_boundary_mask;
+ if (t->limits.no_cluster)
+ q->queue_flags &= ~(1 << QUEUE_FLAG_CLUSTER);
+ else
+ q->queue_flags |= (1 << QUEUE_FLAG_CLUSTER);
+
}
unsigned int dm_table_get_num_targets(struct dm_table *t)
@@ -945,12 +956,20 @@ int dm_table_flush_all(struct dm_table *t)
return ret;
}
+struct mapped_device *dm_table_get_md(struct dm_table *t)
+{
+ dm_get(t->md);
+
+ return t->md;
+}
+
EXPORT_SYMBOL(dm_vcalloc);
EXPORT_SYMBOL(dm_get_device);
EXPORT_SYMBOL(dm_put_device);
EXPORT_SYMBOL(dm_table_event);
EXPORT_SYMBOL(dm_table_get_size);
EXPORT_SYMBOL(dm_table_get_mode);
+EXPORT_SYMBOL(dm_table_get_md);
EXPORT_SYMBOL(dm_table_put);
EXPORT_SYMBOL(dm_table_get);
EXPORT_SYMBOL(dm_table_unplug_all);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 8c82373f7ff..4d710b7a133 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/moduleparam.h>
#include <linux/blkpg.h>
#include <linux/bio.h>
@@ -17,6 +18,7 @@
#include <linux/mempool.h>
#include <linux/slab.h>
#include <linux/idr.h>
+#include <linux/hdreg.h>
#include <linux/blktrace_api.h>
static const char *_name = DM_NAME;
@@ -69,6 +71,7 @@ struct mapped_device {
request_queue_t *queue;
struct gendisk *disk;
+ char name[16];
void *interface_ptr;
@@ -101,6 +104,9 @@ struct mapped_device {
*/
struct super_block *frozen_sb;
struct block_device *suspended_bdev;
+
+ /* forced geometry settings */
+ struct hd_geometry geometry;
};
#define MIN_IOS 256
@@ -226,6 +232,13 @@ static int dm_blk_close(struct inode *inode, struct file *file)
return 0;
}
+static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct mapped_device *md = bdev->bd_disk->private_data;
+
+ return dm_get_geometry(md, geo);
+}
+
static inline struct dm_io *alloc_io(struct mapped_device *md)
{
return mempool_alloc(md->io_pool, GFP_NOIO);
@@ -312,6 +325,33 @@ struct dm_table *dm_get_table(struct mapped_device *md)
return t;
}
+/*
+ * Get the geometry associated with a dm device
+ */
+int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo)
+{
+ *geo = md->geometry;
+
+ return 0;
+}
+
+/*
+ * Set the geometry of a device.
+ */
+int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo)
+{
+ sector_t sz = (sector_t)geo->cylinders * geo->heads * geo->sectors;
+
+ if (geo->start > sz) {
+ DMWARN("Start sector is beyond the geometry limits.");
+ return -EINVAL;
+ }
+
+ md->geometry = *geo;
+
+ return 0;
+}
+
/*-----------------------------------------------------------------
* CRUD START:
* A more elegant soln is in the works that uses the queue
@@ -704,14 +744,14 @@ static int dm_any_congested(void *congested_data, int bdi_bits)
/*-----------------------------------------------------------------
* An IDR is used to keep track of allocated minor numbers.
*---------------------------------------------------------------*/
-static DECLARE_MUTEX(_minor_lock);
+static DEFINE_MUTEX(_minor_lock);
static DEFINE_IDR(_minor_idr);
static void free_minor(unsigned int minor)
{
- down(&_minor_lock);
+ mutex_lock(&_minor_lock);
idr_remove(&_minor_idr, minor);
- up(&_minor_lock);
+ mutex_unlock(&_minor_lock);
}
/*
@@ -724,7 +764,7 @@ static int specific_minor(struct mapped_device *md, unsigned int minor)
if (minor >= (1 << MINORBITS))
return -EINVAL;
- down(&_minor_lock);
+ mutex_lock(&_minor_lock);
if (idr_find(&_minor_idr, minor)) {
r = -EBUSY;
@@ -749,7 +789,7 @@ static int specific_minor(struct mapped_device *md, unsigned int minor)
}
out:
- up(&_minor_lock);
+ mutex_unlock(&_minor_lock);
return r;
}
@@ -758,7 +798,7 @@ static int next_free_minor(struct mapped_device *md, unsigned int *minor)
int r;
unsigned int m;
- down(&_minor_lock);
+ mutex_lock(&_minor_lock);
r = idr_pre_get(&_minor_idr, GFP_KERNEL);
if (!r) {
@@ -780,7 +820,7 @@ static int next_free_minor(struct mapped_device *md, unsigned int *minor)
*minor = m;
out:
- up(&_minor_lock);
+ mutex_unlock(&_minor_lock);
return r;
}
@@ -823,13 +863,11 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent)
md->queue->unplug_fn = dm_unplug_all;
md->queue->issue_flush_fn = dm_flush_all;
- md->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
- mempool_free_slab, _io_cache);
+ md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache);
if (!md->io_pool)
goto bad2;
- md->tio_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
- mempool_free_slab, _tio_cache);
+ md->tio_pool = mempool_create_slab_pool(MIN_IOS, _tio_cache);
if (!md->tio_pool)
goto bad3;
@@ -844,6 +882,7 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent)
md->disk->private_data = md;
sprintf(md->disk->disk_name, "dm-%d", minor);
add_disk(md->disk);
+ format_dev_t(md->name, MKDEV(_major, minor));
atomic_set(&md->pending, 0);
init_waitqueue_head(&md->wait);
@@ -906,6 +945,13 @@ static int __bind(struct mapped_device *md, struct dm_table *t)
sector_t size;
size = dm_table_get_size(t);
+
+ /*
+ * Wipe any geometry if the size of the table changed.
+ */
+ if (size != get_capacity(md->disk))
+ memset(&md->geometry, 0, sizeof(md->geometry));
+
__set_size(md, size);
if (size == 0)
return 0;
@@ -969,13 +1015,13 @@ static struct mapped_device *dm_find_md(dev_t dev)
if (MAJOR(dev) != _major || minor >= (1 << MINORBITS))
return NULL;
- down(&_minor_lock);
+ mutex_lock(&_minor_lock);
md = idr_find(&_minor_idr, minor);
if (!md || (dm_disk(md)->first_minor != minor))
md = NULL;
- up(&_minor_lock);
+ mutex_unlock(&_minor_lock);
return md;
}
@@ -990,15 +1036,9 @@ struct mapped_device *dm_get_md(dev_t dev)
return md;
}
-void *dm_get_mdptr(dev_t dev)
+void *dm_get_mdptr(struct mapped_device *md)
{
- struct mapped_device *md;
- void *mdptr = NULL;
-
- md = dm_find_md(dev);
- if (md)
- mdptr = md->interface_ptr;
- return mdptr;
+ return md->interface_ptr;
}
void dm_set_mdptr(struct mapped_device *md, void *ptr)
@@ -1013,18 +1053,18 @@ void dm_get(struct mapped_device *md)
void dm_put(struct mapped_device *md)
{
- struct dm_table *map = dm_get_table(md);
+ struct dm_table *map;
if (atomic_dec_and_test(&md->holders)) {
+ map = dm_get_table(md);
if (!dm_suspended(md)) {
dm_table_presuspend_targets(map);
dm_table_postsuspend_targets(map);
}
__unbind(md);
+ dm_table_put(map);
free_dev(md);
}
-
- dm_table_put(map);
}
/*
@@ -1109,6 +1149,7 @@ int dm_suspend(struct mapped_device *md, int do_lockfs)
{
struct dm_table *map = NULL;
DECLARE_WAITQUEUE(wait, current);
+ struct bio *def;
int r = -EINVAL;
down(&md->suspend_lock);
@@ -1168,9 +1209,11 @@ int dm_suspend(struct mapped_device *md, int do_lockfs)
/* were we interrupted ? */
r = -EINTR;
if (atomic_read(&md->pending)) {
+ clear_bit(DMF_BLOCK_IO, &md->flags);
+ def = bio_list_get(&md->deferred);
+ __flush_deferred_io(md, def);
up_write(&md->io_lock);
unlock_fs(md);
- clear_bit(DMF_BLOCK_IO, &md->flags);
goto out;
}
up_write(&md->io_lock);
@@ -1264,6 +1307,7 @@ int dm_suspended(struct mapped_device *md)
static struct block_device_operations dm_blk_dops = {
.open = dm_blk_open,
.release = dm_blk_close,
+ .getgeo = dm_blk_getgeo,
.owner = THIS_MODULE
};
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 4eaf075da21..fd90bc8f9e4 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -14,6 +14,7 @@
#include <linux/device-mapper.h>
#include <linux/list.h>
#include <linux/blkdev.h>
+#include <linux/hdreg.h>
#define DM_NAME "device-mapper"
#define DMWARN(f, x...) printk(KERN_WARNING DM_NAME ": " f "\n" , ## x)
@@ -23,16 +24,6 @@
#define DMEMIT(x...) sz += ((sz >= maxlen) ? \
0 : scnprintf(result + sz, maxlen - sz, x))
-/*
- * FIXME: I think this should be with the definition of sector_t
- * in types.h.
- */
-#ifdef CONFIG_LBD
-#define SECTOR_FORMAT "%llu"
-#else
-#define SECTOR_FORMAT "%lu"
-#endif
-
#define SECTOR_SHIFT 9
/*
@@ -57,7 +48,7 @@ struct mapped_device;
int dm_create(struct mapped_device **md);
int dm_create_with_minor(unsigned int minor, struct mapped_device **md);
void dm_set_mdptr(struct mapped_device *md, void *ptr);
-void *dm_get_mdptr(dev_t dev);
+void *dm_get_mdptr(struct mapped_device *md);
struct mapped_device *dm_get_md(dev_t dev);
/*
@@ -95,11 +86,18 @@ int dm_wait_event(struct mapped_device *md, int event_nr);
struct gendisk *dm_disk(struct mapped_device *md);
int dm_suspended(struct mapped_device *md);
+/*
+ * Geometry functions.
+ */
+int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo);
+int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo);
+
/*-----------------------------------------------------------------
* Functions for manipulating a table. Tables are also reference
* counted.
*---------------------------------------------------------------*/
-int dm_table_create(struct dm_table **result, int mode, unsigned num_targets);
+int dm_table_create(struct dm_table **result, int mode,
+ unsigned num_targets, struct mapped_device *md);
void dm_table_get(struct dm_table *t);
void dm_table_put(struct dm_table *t);
@@ -117,6 +115,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q);
unsigned int dm_table_get_num_targets(struct dm_table *t);
struct list_head *dm_table_get_devices(struct dm_table *t);
int dm_table_get_mode(struct dm_table *t);
+struct mapped_device *dm_table_get_md(struct dm_table *t);
void dm_table_presuspend_targets(struct dm_table *t);
void dm_table_postsuspend_targets(struct dm_table *t);
void dm_table_resume_targets(struct dm_table *t);
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
index 8b3515f394a..72480a48d88 100644
--- a/drivers/md/kcopyd.c
+++ b/drivers/md/kcopyd.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
+#include <linux/mutex.h>
#include "kcopyd.h"
@@ -44,6 +45,9 @@ struct kcopyd_client {
struct page_list *pages;
unsigned int nr_pages;
unsigned int nr_free_pages;
+
+ wait_queue_head_t destroyq;
+ atomic_t nr_jobs;
};
static struct page_list *alloc_pl(void)
@@ -227,8 +231,7 @@ static int jobs_init(void)
if (!_job_cache)
return -ENOMEM;
- _job_pool = mempool_create(MIN_JOBS, mempool_alloc_slab,
- mempool_free_slab, _job_cache);
+ _job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
if (!_job_pool) {
kmem_cache_destroy(_job_cache);
return -ENOMEM;
@@ -293,10 +296,15 @@ static int run_complete_job(struct kcopyd_job *job)
int read_err = job->read_err;
unsigned int write_err = job->write_err;
kcopyd_notify_fn fn = job->fn;
+ struct kcopyd_client *kc = job->kc;
- kcopyd_put_pages(job->kc, job->pages);
+ kcopyd_put_pages(kc, job->pages);
mempool_free(job, _job_pool);
fn(read_err, write_err, context);
+
+ if (atomic_dec_and_test(&kc->nr_jobs))
+ wake_up(&kc->destroyq);
+
return 0;
}
@@ -431,6 +439,7 @@ static void do_work(void *ignored)
*/
static void dispatch_job(struct kcopyd_job *job)
{
+ atomic_inc(&job->kc->nr_jobs);
push(&_pages_jobs, job);
wake();
}
@@ -573,68 +582,68 @@ int kcopyd_cancel(struct kcopyd_job *job, int block)
/*-----------------------------------------------------------------
* Unit setup
*---------------------------------------------------------------*/
-static DECLARE_MUTEX(_client_lock);
+static DEFINE_MUTEX(_client_lock);
static LIST_HEAD(_clients);
static void client_add(struct kcopyd_client *kc)
{
- down(&_client_lock);
+ mutex_lock(&_client_lock);
list_add(&kc->list, &_clients);
- up(&_client_lock);
+ mutex_unlock(&_client_lock);
}
static void client_del(struct kcopyd_client *kc)
{
- down(&_client_lock);
+ mutex_lock(&_client_lock);
list_del(&kc->list);
- up(&_client_lock);
+ mutex_unlock(&_client_lock);
}
-static DECLARE_MUTEX(kcopyd_init_lock);
+static DEFINE_MUTEX(kcopyd_init_lock);
static int kcopyd_clients = 0;
static int kcopyd_init(void)
{
int r;
- down(&kcopyd_init_lock);
+ mutex_lock(&kcopyd_init_lock);
if (kcopyd_clients) {
/* Already initialized. */
kcopyd_clients++;
- up(&kcopyd_init_lock);
+ mutex_unlock(&kcopyd_init_lock);
return 0;
}
r = jobs_init();
if (r) {
- up(&kcopyd_init_lock);
+ mutex_unlock(&kcopyd_init_lock);
return r;
}
_kcopyd_wq = create_singlethread_workqueue("kcopyd");
if (!_kcopyd_wq) {
jobs_exit();
- up(&kcopyd_init_lock);
+ mutex_unlock(&kcopyd_init_lock);
return -ENOMEM;
}
kcopyd_clients++;
INIT_WORK(&_kcopyd_work, do_work, NULL);
- up(&kcopyd_init_lock);
+ mutex_unlock(&kcopyd_init_lock);
return 0;
}
static void kcopyd_exit(void)
{
- down(&kcopyd_init_lock);
+ mutex_lock(&kcopyd_init_lock);
kcopyd_clients--;
if (!kcopyd_clients) {
jobs_exit();
destroy_workqueue(_kcopyd_wq);
_kcopyd_wq = NULL;
}
- up(&kcopyd_init_lock);
+ mutex_unlock(&kcopyd_init_lock);
}
int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
@@ -670,6 +679,9 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
return r;
}
+ init_waitqueue_head(&kc->destroyq);
+ atomic_set(&kc->nr_jobs, 0);
+
client_add(kc);
*result = kc;
return 0;
@@ -677,6 +689,9 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
void kcopyd_client_destroy(struct kcopyd_client *kc)
{
+ /* Wait for completion of all jobs submitted by this client. */
+ wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
+
dm_io_put(kc->nr_pages);
client_free_pages(kc);
client_del(kc);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 5ed2228745c..039e071c100 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -43,6 +43,7 @@
#include <linux/buffer_head.h> /* for invalidate_bdev */
#include <linux/suspend.h>
#include <linux/poll.h>
+#include <linux/mutex.h>
#include <linux/init.h>
@@ -158,11 +159,12 @@ static int start_readonly;
*/
static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
static atomic_t md_event_count;
-static void md_new_event(mddev_t *mddev)
+void md_new_event(mddev_t *mddev)
{
atomic_inc(&md_event_count);
wake_up(&md_event_waiters);
}
+EXPORT_SYMBOL_GPL(md_new_event);
/*
* Enables to iterate over all existing md arrays
@@ -253,7 +255,7 @@ static mddev_t * mddev_find(dev_t unit)
else
new->md_minor = MINOR(unit) >> MdpMinorShift;
- init_MUTEX(&new->reconfig_sem);
+ mutex_init(&new->reconfig_mutex);
INIT_LIST_HEAD(&new->disks);
INIT_LIST_HEAD(&new->all_mddevs);
init_timer(&new->safemode_timer);
@@ -266,6 +268,7 @@ static mddev_t * mddev_find(dev_t unit)
kfree(new);
return NULL;
}
+ set_bit(QUEUE_FLAG_CLUSTER, &new->queue->queue_flags);
blk_queue_make_request(new->queue, md_fail_request);
@@ -274,22 +277,22 @@ static mddev_t * mddev_find(dev_t unit)
static inline int mddev_lock(mddev_t * mddev)
{
- return down_interruptible(&mddev->reconfig_sem);
+ return mutex_lock_interruptible(&mddev->reconfig_mutex);
}
static inline void mddev_lock_uninterruptible(mddev_t * mddev)
{
- down(&mddev->reconfig_sem);
+ mutex_lock(&mddev->reconfig_mutex);
}
static inline int mddev_trylock(mddev_t * mddev)
{
- return down_trylock(&mddev->reconfig_sem);
+ return mutex_trylock(&mddev->reconfig_mutex);
}
static inline void mddev_unlock(mddev_t * mddev)
{
- up(&mddev->reconfig_sem);
+ mutex_unlock(&mddev->reconfig_mutex);
md_wakeup_thread(mddev->thread);
}
@@ -660,7 +663,8 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
}
if (sb->major_version != 0 ||
- sb->minor_version != 90) {
+ sb->minor_version < 90 ||
+ sb->minor_version > 91) {
printk(KERN_WARNING "Bad version number %d.%d on %s\n",
sb->major_version, sb->minor_version,
b);
@@ -745,6 +749,20 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->bitmap_offset = 0;
mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
+ if (mddev->minor_version >= 91) {
+ mddev->reshape_position = sb->reshape_position;
+ mddev->delta_disks = sb->delta_disks;
+ mddev->new_level = sb->new_level;
+ mddev->new_layout = sb->new_layout;
+ mddev->new_chunk = sb->new_chunk;
+ } else {
+ mddev->reshape_position = MaxSector;
+ mddev->delta_disks = 0;
+ mddev->new_level = mddev->level;
+ mddev->new_layout = mddev->layout;
+ mddev->new_chunk = mddev->chunk_size;
+ }
+
if (sb->state & (1<<MD_SB_CLEAN))
mddev->recovery_cp = MaxSector;
else {
@@ -764,7 +782,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
mddev->bitmap_file == NULL) {
- if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6
+ if (mddev->level != 1 && mddev->level != 4
+ && mddev->level != 5 && mddev->level != 6
&& mddev->level != 10) {
/* FIXME use a better test */
printk(KERN_WARNING "md: bitmaps not supported for this level.\n");
@@ -838,7 +857,6 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->md_magic = MD_SB_MAGIC;
sb->major_version = mddev->major_version;
- sb->minor_version = mddev->minor_version;
sb->patch_version = mddev->patch_version;
sb->gvalid_words = 0; /* ignored */
memcpy(&sb->set_uuid0, mddev->uuid+0, 4);
@@ -857,6 +875,17 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->events_hi = (mddev->events>>32);
sb->events_lo = (u32)mddev->events;
+ if (mddev->reshape_position == MaxSector)
+ sb->minor_version = 90;
+ else {
+ sb->minor_version = 91;
+ sb->reshape_position = mddev->reshape_position;
+ sb->new_level = mddev->new_level;
+ sb->delta_disks = mddev->delta_disks;
+ sb->new_layout = mddev->new_layout;
+ sb->new_chunk = mddev->new_chunk;
+ }
+ mddev->minor_version = sb->minor_version;
if (mddev->in_sync)
{
sb->recovery_cp = mddev->recovery_cp;
@@ -893,10 +922,9 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
d->raid_disk = rdev2->raid_disk;
else
d->raid_disk = rdev2->desc_nr; /* compatibility */
- if (test_bit(Faulty, &rdev2->flags)) {
+ if (test_bit(Faulty, &rdev2->flags))
d->state = (1<<MD_DISK_FAULTY);
- failed++;
- } else if (test_bit(In_sync, &rdev2->flags)) {
+ else if (test_bit(In_sync, &rdev2->flags)) {
d->state = (1<<MD_DISK_ACTIVE);
d->state |= (1<<MD_DISK_SYNC);
active++;
@@ -1102,6 +1130,20 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
}
mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset);
}
+ if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) {
+ mddev->reshape_position = le64_to_cpu(sb->reshape_position);
+ mddev->delta_disks = le32_to_cpu(sb->delta_disks);
+ mddev->new_level = le32_to_cpu(sb->new_level);
+ mddev->new_layout = le32_to_cpu(sb->new_layout);
+ mddev->new_chunk = le32_to_cpu(sb->new_chunk)<<9;
+ } else {
+ mddev->reshape_position = MaxSector;
+ mddev->delta_disks = 0;
+ mddev->new_level = mddev->level;
+ mddev->new_layout = mddev->layout;
+ mddev->new_chunk = mddev->chunk_size;
+ }
+
} else if (mddev->pers == NULL) {
/* Insist of good event counter while assembling */
__u64 ev1 = le64_to_cpu(sb->events);
@@ -1173,6 +1215,14 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
}
+ if (mddev->reshape_position != MaxSector) {
+ sb->feature_map |= cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE);
+ sb->reshape_position = cpu_to_le64(mddev->reshape_position);
+ sb->new_layout = cpu_to_le32(mddev->new_layout);
+ sb->delta_disks = cpu_to_le32(mddev->delta_disks);
+ sb->new_level = cpu_to_le32(mddev->new_level);
+ sb->new_chunk = cpu_to_le32(mddev->new_chunk>>9);
+ }
max_dev = 0;
ITERATE_RDEV(mddev,rdev2,tmp)
@@ -1301,6 +1351,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
else
ko = &rdev->bdev->bd_disk->kobj;
sysfs_create_link(&rdev->kobj, ko, "block");
+ bd_claim_by_disk(rdev->bdev, rdev, mddev->gendisk);
return 0;
}
@@ -1311,6 +1362,7 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
MD_BUG();
return;
}
+ bd_release_from_disk(rdev->bdev, rdev->mddev->gendisk);
list_del_init(&rdev->same_set);
printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b));
rdev->mddev = NULL;
@@ -1493,7 +1545,7 @@ static void sync_sbs(mddev_t * mddev)
}
}
-static void md_update_sb(mddev_t * mddev)
+void md_update_sb(mddev_t * mddev)
{
int err;
struct list_head *tmp;
@@ -1570,6 +1622,7 @@ repeat:
wake_up(&mddev->sb_wait);
}
+EXPORT_SYMBOL_GPL(md_update_sb);
/* words written to sysfs files may, or my not, be \n terminated.
* We want to accept with case. For this we use cmd_match.
@@ -2162,7 +2215,9 @@ action_show(mddev_t *mddev, char *page)
char *type = "idle";
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) {
- if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+ if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
+ type = "reshape";
+ else if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
type = "resync";
else if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
@@ -2193,7 +2248,14 @@ action_store(mddev_t *mddev, const char *page, size_t len)
return -EBUSY;
else if (cmd_match(page, "resync") || cmd_match(page, "recover"))
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
- else {
+ else if (cmd_match(page, "reshape")) {
+ int err;
+ if (mddev->pers->start_reshape == NULL)
+ return -EINVAL;
+ err = mddev->pers->start_reshape(mddev);
+ if (err)
+ return err;
+ } else {
if (cmd_match(page, "check"))
set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
else if (cmd_match(page, "repair"))
@@ -2304,6 +2366,63 @@ sync_completed_show(mddev_t *mddev, char *page)
static struct md_sysfs_entry
md_sync_completed = __ATTR_RO(sync_completed);
+static ssize_t
+suspend_lo_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo);
+}
+
+static ssize_t
+suspend_lo_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ char *e;
+ unsigned long long new = simple_strtoull(buf, &e, 10);
+
+ if (mddev->pers->quiesce == NULL)
+ return -EINVAL;
+ if (buf == e || (*e && *e != '\n'))
+ return -EINVAL;
+ if (new >= mddev->suspend_hi ||
+ (new > mddev->suspend_lo && new < mddev->suspend_hi)) {
+ mddev->suspend_lo = new;
+ mddev->pers->quiesce(mddev, 2);
+ return len;
+ } else
+ return -EINVAL;
+}
+static struct md_sysfs_entry md_suspend_lo =
+__ATTR(suspend_lo, S_IRUGO|S_IWUSR, suspend_lo_show, suspend_lo_store);
+
+
+static ssize_t
+suspend_hi_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_hi);
+}
+
+static ssize_t
+suspend_hi_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ char *e;
+ unsigned long long new = simple_strtoull(buf, &e, 10);
+
+ if (mddev->pers->quiesce == NULL)
+ return -EINVAL;
+ if (buf == e || (*e && *e != '\n'))
+ return -EINVAL;
+ if ((new <= mddev->suspend_lo && mddev->suspend_lo >= mddev->suspend_hi) ||
+ (new > mddev->suspend_lo && new > mddev->suspend_hi)) {
+ mddev->suspend_hi = new;
+ mddev->pers->quiesce(mddev, 1);
+ mddev->pers->quiesce(mddev, 0);
+ return len;
+ } else
+ return -EINVAL;
+}
+static struct md_sysfs_entry md_suspend_hi =
+__ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store);
+
+
static struct attribute *md_default_attrs[] = {
&md_level.attr,
&md_raid_disks.attr,
@@ -2321,6 +2440,8 @@ static struct attribute *md_redundancy_attrs[] = {
&md_sync_max.attr,
&md_sync_speed.attr,
&md_sync_completed.attr,
+ &md_suspend_lo.attr,
+ &md_suspend_hi.attr,
NULL,
};
static struct attribute_group md_redundancy_group = {
@@ -2380,7 +2501,7 @@ int mdp_major = 0;
static struct kobject *md_probe(dev_t dev, int *part, void *data)
{
- static DECLARE_MUTEX(disks_sem);
+ static DEFINE_MUTEX(disks_mutex);
mddev_t *mddev = mddev_find(dev);
struct gendisk *disk;
int partitioned = (MAJOR(dev) != MD_MAJOR);
@@ -2390,15 +2511,15 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data)
if (!mddev)
return NULL;
- down(&disks_sem);
+ mutex_lock(&disks_mutex);
if (mddev->gendisk) {
- up(&disks_sem);
+ mutex_unlock(&disks_mutex);
mddev_put(mddev);
return NULL;
}
disk = alloc_disk(1 << shift);
if (!disk) {
- up(&disks_sem);
+ mutex_unlock(&disks_mutex);
mddev_put(mddev);
return NULL;
}
@@ -2416,7 +2537,7 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data)
disk->queue = mddev->queue;
add_disk(disk);
mddev->gendisk = disk;
- up(&disks_sem);
+ mutex_unlock(&disks_mutex);
mddev->kobj.parent = &disk->kobj;
mddev->kobj.k_name = NULL;
snprintf(mddev->kobj.name, KOBJ_NAME_LEN, "%s", "md");
@@ -2539,6 +2660,14 @@ static int do_md_run(mddev_t * mddev)
mddev->level = pers->level;
strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
+ if (mddev->reshape_position != MaxSector &&
+ pers->start_reshape == NULL) {
+ /* This personality cannot handle reshaping... */
+ mddev->pers = NULL;
+ module_put(pers->owner);
+ return -EINVAL;
+ }
+
mddev->recovery = 0;
mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
mddev->barriers_work = 1;
@@ -2772,7 +2901,6 @@ static void autorun_array(mddev_t *mddev)
*/
static void autorun_devices(int part)
{
- struct list_head candidates;
struct list_head *tmp;
mdk_rdev_t *rdev0, *rdev;
mddev_t *mddev;
@@ -2781,6 +2909,7 @@ static void autorun_devices(int part)
printk(KERN_INFO "md: autorun ...\n");
while (!list_empty(&pending_raid_disks)) {
dev_t dev;
+ LIST_HEAD(candidates);
rdev0 = list_entry(pending_raid_disks.next,
mdk_rdev_t, same_set);
@@ -3427,11 +3556,18 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
mddev->bitmap_offset = 0;
+ mddev->reshape_position = MaxSector;
+
/*
* Generate a 128 bit UUID
*/
get_random_bytes(mddev->uuid, 16);
+ mddev->new_level = mddev->level;
+ mddev->new_chunk = mddev->chunk_size;
+ mddev->new_layout = mddev->layout;
+ mddev->delta_disks = 0;
+
return 0;
}
@@ -3440,6 +3576,7 @@ static int update_size(mddev_t *mddev, unsigned long size)
mdk_rdev_t * rdev;
int rv;
struct list_head *tmp;
+ int fit = (size == 0);
if (mddev->pers->resize == NULL)
return -EINVAL;
@@ -3457,7 +3594,6 @@ static int update_size(mddev_t *mddev, unsigned long size)
return -EBUSY;
ITERATE_RDEV(mddev,rdev,tmp) {
sector_t avail;
- int fit = (size == 0);
if (rdev->sb_offset > rdev->data_offset)
avail = (rdev->sb_offset*2) - rdev->data_offset;
else
@@ -3487,14 +3623,16 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks)
{
int rv;
/* change the number of raid disks */
- if (mddev->pers->reshape == NULL)
+ if (mddev->pers->check_reshape == NULL)
return -EINVAL;
if (raid_disks <= 0 ||
raid_disks >= mddev->max_disks)
return -EINVAL;
- if (mddev->sync_thread)
+ if (mddev->sync_thread || mddev->reshape_position != MaxSector)
return -EBUSY;
- rv = mddev->pers->reshape(mddev, raid_disks);
+ mddev->delta_disks = raid_disks - mddev->raid_disks;
+
+ rv = mddev->pers->check_reshape(mddev);
return rv;
}
@@ -4041,7 +4179,10 @@ static void status_unused(struct seq_file *seq)
static void status_resync(struct seq_file *seq, mddev_t * mddev)
{
- unsigned long max_blocks, resync, res, dt, db, rt;
+ sector_t max_blocks, resync, res;
+ unsigned long dt, db, rt;
+ int scale;
+ unsigned int per_milli;
resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2;
@@ -4057,9 +4198,22 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev)
MD_BUG();
return;
}
- res = (resync/1024)*1000/(max_blocks/1024 + 1);
+ /* Pick 'scale' such that (resync>>scale)*1000 will fit
+ * in a sector_t, and (max_blocks>>scale) will fit in a
+ * u32, as those are the requirements for sector_div.
+ * Thus 'scale' must be at least 10
+ */
+ scale = 10;
+ if (sizeof(sector_t) > sizeof(unsigned long)) {
+ while ( max_blocks/2 > (1ULL<<(scale+32)))
+ scale++;
+ }
+ res = (resync>>scale)*1000;
+ sector_div(res, (u32)((max_blocks>>scale)+1));
+
+ per_milli = res;
{
- int i, x = res/50, y = 20-x;
+ int i, x = per_milli/50, y = 20-x;
seq_printf(seq, "[");
for (i = 0; i < x; i++)
seq_printf(seq, "=");
@@ -4068,10 +4222,14 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev)
seq_printf(seq, ".");
seq_printf(seq, "] ");
}
- seq_printf(seq, " %s =%3lu.%lu%% (%lu/%lu)",
+ seq_printf(seq, " %s =%3u.%u%% (%llu/%llu)",
+ (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)?
+ "reshape" :
(test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ?
- "resync" : "recovery"),
- res/10, res % 10, resync, max_blocks);
+ "resync" : "recovery")),
+ per_milli/10, per_milli % 10,
+ (unsigned long long) resync,
+ (unsigned long long) max_blocks);
/*
* We do not want to overflow, so the order of operands and
@@ -4085,7 +4243,7 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev)
dt = ((jiffies - mddev->resync_mark) / HZ);
if (!dt) dt++;
db = resync - (mddev->resync_mark_cnt/2);
- rt = (dt * ((max_blocks-resync) / (db/100+1)))/100;
+ rt = (dt * ((unsigned long)(max_blocks-resync) / (db/100+1)))/100;
seq_printf(seq, " finish=%lu.%lumin", rt / 60, (rt % 60)/6);
@@ -4442,7 +4600,7 @@ static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
#define SYNC_MARKS 10
#define SYNC_MARK_STEP (3*HZ)
-static void md_do_sync(mddev_t *mddev)
+void md_do_sync(mddev_t *mddev)
{
mddev_t *mddev2;
unsigned int currspeed = 0,
@@ -4522,7 +4680,9 @@ static void md_do_sync(mddev_t *mddev)
*/
max_sectors = mddev->resync_max_sectors;
mddev->resync_mismatches = 0;
- } else
+ } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
+ max_sectors = mddev->size << 1;
+ else
/* recovery follows the physical size of devices */
max_sectors = mddev->size << 1;
@@ -4658,6 +4818,8 @@ static void md_do_sync(mddev_t *mddev)
mddev->pers->sync_request(mddev, max_sectors, &skipped, 1);
if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
+ test_bit(MD_RECOVERY_SYNC, &mddev->recovery) &&
+ !test_bit(MD_RECOVERY_CHECK, &mddev->recovery) &&
mddev->curr_resync > 2 &&
mddev->curr_resync >= mddev->recovery_cp) {
if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
@@ -4675,6 +4837,7 @@ static void md_do_sync(mddev_t *mddev)
set_bit(MD_RECOVERY_DONE, &mddev->recovery);
md_wakeup_thread(mddev->thread);
}
+EXPORT_SYMBOL_GPL(md_do_sync);
/*
@@ -4730,7 +4893,7 @@ void md_check_recovery(mddev_t *mddev)
))
return;
- if (mddev_trylock(mddev)==0) {
+ if (mddev_trylock(mddev)) {
int spares =0;
spin_lock_irq(&mddev->write_lock);
@@ -4866,7 +5029,7 @@ static int md_notify_reboot(struct notifier_block *this,
printk(KERN_INFO "md: stopping all md devices.\n");
ITERATE_MDDEV(mddev,tmp)
- if (mddev_trylock(mddev)==0)
+ if (mddev_trylock(mddev))
do_md_stop (mddev, 1);
/*
* certain more exotic SCSI devices are known to be
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 96f7af4ae40..1cc9de44ce8 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -35,18 +35,6 @@
#define NR_RESERVED_BUFS 32
-static void *mp_pool_alloc(gfp_t gfp_flags, void *data)
-{
- struct multipath_bh *mpb;
- mpb = kzalloc(sizeof(*mpb), gfp_flags);
- return mpb;
-}
-
-static void mp_pool_free(void *mpb, void *data)
-{
- kfree(mpb);
-}
-
static int multipath_map (multipath_conf_t *conf)
{
int i, disks = conf->raid_disks;
@@ -494,9 +482,8 @@ static int multipath_run (mddev_t *mddev)
}
mddev->degraded = conf->raid_disks = conf->working_disks;
- conf->pool = mempool_create(NR_RESERVED_BUFS,
- mp_pool_alloc, mp_pool_free,
- NULL);
+ conf->pool = mempool_create_kzalloc_pool(NR_RESERVED_BUFS,
+ sizeof(struct multipath_bh));
if (conf->pool == NULL) {
printk(KERN_ERR
"multipath: couldn't allocate memory for %s\n",
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 5d88329e3c7..3cb0872a845 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1402,6 +1402,9 @@ static void raid1d(mddev_t *mddev)
clear_bit(R1BIO_BarrierRetry, &r1_bio->state);
clear_bit(R1BIO_Barrier, &r1_bio->state);
for (i=0; i < conf->raid_disks; i++)
+ if (r1_bio->bios[i])
+ atomic_inc(&r1_bio->remaining);
+ for (i=0; i < conf->raid_disks; i++)
if (r1_bio->bios[i]) {
struct bio_vec *bvec;
int j;
@@ -1789,6 +1792,11 @@ static int run(mddev_t *mddev)
mdname(mddev), mddev->level);
goto out;
}
+ if (mddev->reshape_position != MaxSector) {
+ printk("raid1: %s: reshape_position set but not supported\n",
+ mdname(mddev));
+ goto out;
+ }
/*
* copy the already verified devices into our private RAID1
* bookkeeping area. [whatever we allocate in run(),
@@ -1971,7 +1979,7 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
return 0;
}
-static int raid1_reshape(mddev_t *mddev, int raid_disks)
+static int raid1_reshape(mddev_t *mddev)
{
/* We need to:
* 1/ resize the r1bio_pool
@@ -1988,10 +1996,22 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
struct pool_info *newpoolinfo;
mirror_info_t *newmirrors;
conf_t *conf = mddev_to_conf(mddev);
- int cnt;
+ int cnt, raid_disks;
int d, d2;
+ /* Cannot change chunk_size, layout, or level */
+ if (mddev->chunk_size != mddev->new_chunk ||
+ mddev->layout != mddev->new_layout ||
+ mddev->level != mddev->new_level) {
+ mddev->new_chunk = mddev->chunk_size;
+ mddev->new_layout = mddev->layout;
+ mddev->new_level = mddev->level;
+ return -EINVAL;
+ }
+
+ raid_disks = mddev->raid_disks + mddev->delta_disks;
+
if (raid_disks < conf->raid_disks) {
cnt=0;
for (d= 0; d < conf->raid_disks; d++)
@@ -2038,6 +2058,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
mddev->degraded += (raid_disks - conf->raid_disks);
conf->raid_disks = mddev->raid_disks = raid_disks;
+ mddev->delta_disks = 0;
conf->last_used = 0; /* just make sure it is in-range */
lower_barrier(conf);
@@ -2079,7 +2100,7 @@ static struct mdk_personality raid1_personality =
.spare_active = raid1_spare_active,
.sync_request = sync_request,
.resize = raid1_resize,
- .reshape = raid1_reshape,
+ .check_reshape = raid1_reshape,
.quiesce = raid1_quiesce,
};
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 2dba305daf3..dae740adaf6 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -22,6 +22,7 @@
#include <linux/raid/raid5.h>
#include <linux/highmem.h>
#include <linux/bitops.h>
+#include <linux/kthread.h>
#include <asm/atomic.h>
#include <linux/raid/bitmap.h>
@@ -93,11 +94,11 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
md_wakeup_thread(conf->mddev->thread);
}
- list_add_tail(&sh->lru, &conf->inactive_list);
atomic_dec(&conf->active_stripes);
- if (!conf->inactive_blocked ||
- atomic_read(&conf->active_stripes) < (conf->max_nr_stripes*3/4))
+ if (!test_bit(STRIPE_EXPANDING, &sh->state)) {
+ list_add_tail(&sh->lru, &conf->inactive_list);
wake_up(&conf->wait_for_stripe);
+ }
}
}
}
@@ -178,10 +179,10 @@ static int grow_buffers(struct stripe_head *sh, int num)
static void raid5_build_block (struct stripe_head *sh, int i);
-static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
+static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int disks)
{
raid5_conf_t *conf = sh->raid_conf;
- int disks = conf->raid_disks, i;
+ int i;
if (atomic_read(&sh->count) != 0)
BUG();
@@ -198,7 +199,9 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
sh->pd_idx = pd_idx;
sh->state = 0;
- for (i=disks; i--; ) {
+ sh->disks = disks;
+
+ for (i = sh->disks; i--; ) {
struct r5dev *dev = &sh->dev[i];
if (dev->toread || dev->towrite || dev->written ||
@@ -215,7 +218,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
insert_hash(conf, sh);
}
-static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector)
+static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector, int disks)
{
struct stripe_head *sh;
struct hlist_node *hn;
@@ -223,7 +226,7 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector)
CHECK_DEVLOCK();
PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
- if (sh->sector == sector)
+ if (sh->sector == sector && sh->disks == disks)
return sh;
PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
return NULL;
@@ -232,8 +235,8 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector)
static void unplug_slaves(mddev_t *mddev);
static void raid5_unplug_device(request_queue_t *q);
-static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector,
- int pd_idx, int noblock)
+static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector, int disks,
+ int pd_idx, int noblock)
{
struct stripe_head *sh;
@@ -245,7 +248,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
wait_event_lock_irq(conf->wait_for_stripe,
conf->quiesce == 0,
conf->device_lock, /* nothing */);
- sh = __find_stripe(conf, sector);
+ sh = __find_stripe(conf, sector, disks);
if (!sh) {
if (!conf->inactive_blocked)
sh = get_free_stripe(conf);
@@ -259,11 +262,11 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
< (conf->max_nr_stripes *3/4)
|| !conf->inactive_blocked),
conf->device_lock,
- unplug_slaves(conf->mddev);
+ unplug_slaves(conf->mddev)
);
conf->inactive_blocked = 0;
} else
- init_stripe(sh, sector, pd_idx);
+ init_stripe(sh, sector, pd_idx, disks);
} else {
if (atomic_read(&sh->count)) {
if (!list_empty(&sh->lru))
@@ -271,9 +274,8 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
} else {
if (!test_bit(STRIPE_HANDLE, &sh->state))
atomic_inc(&conf->active_stripes);
- if (list_empty(&sh->lru))
- BUG();
- list_del_init(&sh->lru);
+ if (!list_empty(&sh->lru))
+ list_del_init(&sh->lru);
}
}
} while (sh == NULL);
@@ -300,6 +302,7 @@ static int grow_one_stripe(raid5_conf_t *conf)
kmem_cache_free(conf->slab_cache, sh);
return 0;
}
+ sh->disks = conf->raid_disks;
/* we just created an active stripe so... */
atomic_set(&sh->count, 1);
atomic_inc(&conf->active_stripes);
@@ -313,14 +316,16 @@ static int grow_stripes(raid5_conf_t *conf, int num)
kmem_cache_t *sc;
int devs = conf->raid_disks;
- sprintf(conf->cache_name, "raid5/%s", mdname(conf->mddev));
-
- sc = kmem_cache_create(conf->cache_name,
+ sprintf(conf->cache_name[0], "raid5/%s", mdname(conf->mddev));
+ sprintf(conf->cache_name[1], "raid5/%s-alt", mdname(conf->mddev));
+ conf->active_name = 0;
+ sc = kmem_cache_create(conf->cache_name[conf->active_name],
sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
0, 0, NULL, NULL);
if (!sc)
return 1;
conf->slab_cache = sc;
+ conf->pool_size = devs;
while (num--) {
if (!grow_one_stripe(conf))
return 1;
@@ -328,6 +333,129 @@ static int grow_stripes(raid5_conf_t *conf, int num)
return 0;
}
+#ifdef CONFIG_MD_RAID5_RESHAPE
+static int resize_stripes(raid5_conf_t *conf, int newsize)
+{
+ /* Make all the stripes able to hold 'newsize' devices.
+ * New slots in each stripe get 'page' set to a new page.
+ *
+ * This happens in stages:
+ * 1/ create a new kmem_cache and allocate the required number of
+ * stripe_heads.
+ * 2/ gather all the old stripe_heads and tranfer the pages across
+ * to the new stripe_heads. This will have the side effect of
+ * freezing the array as once all stripe_heads have been collected,
+ * no IO will be possible. Old stripe heads are freed once their
+ * pages have been transferred over, and the old kmem_cache is
+ * freed when all stripes are done.
+ * 3/ reallocate conf->disks to be suitable bigger. If this fails,
+ * we simple return a failre status - no need to clean anything up.
+ * 4/ allocate new pages for the new slots in the new stripe_heads.
+ * If this fails, we don't bother trying the shrink the
+ * stripe_heads down again, we just leave them as they are.
+ * As each stripe_head is processed the new one is released into
+ * active service.
+ *
+ * Once step2 is started, we cannot afford to wait for a write,
+ * so we use GFP_NOIO allocations.
+ */
+ struct stripe_head *osh, *nsh;
+ LIST_HEAD(newstripes);
+ struct disk_info *ndisks;
+ int err = 0;
+ kmem_cache_t *sc;
+ int i;
+
+ if (newsize <= conf->pool_size)
+ return 0; /* never bother to shrink */
+
+ /* Step 1 */
+ sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
+ sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev),
+ 0, 0, NULL, NULL);
+ if (!sc)
+ return -ENOMEM;
+
+ for (i = conf->max_nr_stripes; i; i--) {
+ nsh = kmem_cache_alloc(sc, GFP_KERNEL);
+ if (!nsh)
+ break;
+
+ memset(nsh, 0, sizeof(*nsh) + (newsize-1)*sizeof(struct r5dev));
+
+ nsh->raid_conf = conf;
+ spin_lock_init(&nsh->lock);
+
+ list_add(&nsh->lru, &newstripes);
+ }
+ if (i) {
+ /* didn't get enough, give up */
+ while (!list_empty(&newstripes)) {
+ nsh = list_entry(newstripes.next, struct stripe_head, lru);
+ list_del(&nsh->lru);
+ kmem_cache_free(sc, nsh);
+ }
+ kmem_cache_destroy(sc);
+ return -ENOMEM;
+ }
+ /* Step 2 - Must use GFP_NOIO now.
+ * OK, we have enough stripes, start collecting inactive
+ * stripes and copying them over
+ */
+ list_for_each_entry(nsh, &newstripes, lru) {
+ spin_lock_irq(&conf->device_lock);
+ wait_event_lock_irq(conf->wait_for_stripe,
+ !list_empty(&conf->inactive_list),
+ conf->device_lock,
+ unplug_slaves(conf->mddev)
+ );
+ osh = get_free_stripe(conf);
+ spin_unlock_irq(&conf->device_lock);
+ atomic_set(&nsh->count, 1);
+ for(i=0; i<conf->pool_size; i++)
+ nsh->dev[i].page = osh->dev[i].page;
+ for( ; i<newsize; i++)
+ nsh->dev[i].page = NULL;
+ kmem_cache_free(conf->slab_cache, osh);
+ }
+ kmem_cache_destroy(conf->slab_cache);
+
+ /* Step 3.
+ * At this point, we are holding all the stripes so the array
+ * is completely stalled, so now is a good time to resize
+ * conf->disks.
+ */
+ ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO);
+ if (ndisks) {
+ for (i=0; i<conf->raid_disks; i++)
+ ndisks[i] = conf->disks[i];
+ kfree(conf->disks);
+ conf->disks = ndisks;
+ } else
+ err = -ENOMEM;
+
+ /* Step 4, return new stripes to service */
+ while(!list_empty(&newstripes)) {
+ nsh = list_entry(newstripes.next, struct stripe_head, lru);
+ list_del_init(&nsh->lru);
+ for (i=conf->raid_disks; i < newsize; i++)
+ if (nsh->dev[i].page == NULL) {
+ struct page *p = alloc_page(GFP_NOIO);
+ nsh->dev[i].page = p;
+ if (!p)
+ err = -ENOMEM;
+ }
+ release_stripe(nsh);
+ }
+ /* critical section pass, GFP_NOIO no longer needed */
+
+ conf->slab_cache = sc;
+ conf->active_name = 1-conf->active_name;
+ conf->pool_size = newsize;
+ return err;
+}
+#endif
+
static int drop_one_stripe(raid5_conf_t *conf)
{
struct stripe_head *sh;
@@ -339,7 +467,7 @@ static int drop_one_stripe(raid5_conf_t *conf)
return 0;
if (atomic_read(&sh->count))
BUG();
- shrink_buffers(sh, conf->raid_disks);
+ shrink_buffers(sh, conf->pool_size);
kmem_cache_free(conf->slab_cache, sh);
atomic_dec(&conf->active_stripes);
return 1;
@@ -360,7 +488,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
{
struct stripe_head *sh = bi->bi_private;
raid5_conf_t *conf = sh->raid_conf;
- int disks = conf->raid_disks, i;
+ int disks = sh->disks, i;
int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
if (bi->bi_size)
@@ -458,7 +586,7 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
{
struct stripe_head *sh = bi->bi_private;
raid5_conf_t *conf = sh->raid_conf;
- int disks = conf->raid_disks, i;
+ int disks = sh->disks, i;
unsigned long flags;
int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -612,7 +740,7 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks,
static sector_t compute_blocknr(struct stripe_head *sh, int i)
{
raid5_conf_t *conf = sh->raid_conf;
- int raid_disks = conf->raid_disks, data_disks = raid_disks - 1;
+ int raid_disks = sh->disks, data_disks = raid_disks - 1;
sector_t new_sector = sh->sector, check;
int sectors_per_chunk = conf->chunk_size >> 9;
sector_t stripe;
@@ -713,8 +841,7 @@ static void copy_data(int frombio, struct bio *bio,
static void compute_block(struct stripe_head *sh, int dd_idx)
{
- raid5_conf_t *conf = sh->raid_conf;
- int i, count, disks = conf->raid_disks;
+ int i, count, disks = sh->disks;
void *ptr[MAX_XOR_BLOCKS], *p;
PRINTK("compute_block, stripe %llu, idx %d\n",
@@ -744,7 +871,7 @@ static void compute_block(struct stripe_head *sh, int dd_idx)
static void compute_parity(struct stripe_head *sh, int method)
{
raid5_conf_t *conf = sh->raid_conf;
- int i, pd_idx = sh->pd_idx, disks = conf->raid_disks, count;
+ int i, pd_idx = sh->pd_idx, disks = sh->disks, count;
void *ptr[MAX_XOR_BLOCKS];
struct bio *chosen;
@@ -910,6 +1037,20 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
return 0;
}
+static void end_reshape(raid5_conf_t *conf);
+
+static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks)
+{
+ int sectors_per_chunk = conf->chunk_size >> 9;
+ sector_t x = stripe;
+ int pd_idx, dd_idx;
+ int chunk_offset = sector_div(x, sectors_per_chunk);
+ stripe = x;
+ raid5_compute_sector(stripe*(disks-1)*sectors_per_chunk
+ + chunk_offset, disks, disks-1, &dd_idx, &pd_idx, conf);
+ return pd_idx;
+}
+
/*
* handle_stripe - do things to a stripe.
@@ -932,11 +1073,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
static void handle_stripe(struct stripe_head *sh)
{
raid5_conf_t *conf = sh->raid_conf;
- int disks = conf->raid_disks;
+ int disks = sh->disks;
struct bio *return_bi= NULL;
struct bio *bi;
int i;
- int syncing;
+ int syncing, expanding, expanded;
int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
int non_overwrite = 0;
int failed_num=0;
@@ -951,6 +1092,8 @@ static void handle_stripe(struct stripe_head *sh)
clear_bit(STRIPE_DELAYED, &sh->state);
syncing = test_bit(STRIPE_SYNCING, &sh->state);
+ expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+ expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
/* Now to look around and see what can be done */
rcu_read_lock();
@@ -1143,13 +1286,14 @@ static void handle_stripe(struct stripe_head *sh)
* parity, or to satisfy requests
* or to load a block that is being partially written.
*/
- if (to_read || non_overwrite || (syncing && (uptodate < disks))) {
+ if (to_read || non_overwrite || (syncing && (uptodate < disks)) || expanding) {
for (i=disks; i--;) {
dev = &sh->dev[i];
if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
(dev->toread ||
(dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
syncing ||
+ expanding ||
(failed && (sh->dev[failed_num].toread ||
(sh->dev[failed_num].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num].flags))))
)
@@ -1339,13 +1483,77 @@ static void handle_stripe(struct stripe_head *sh)
set_bit(R5_Wantwrite, &dev->flags);
set_bit(R5_ReWrite, &dev->flags);
set_bit(R5_LOCKED, &dev->flags);
+ locked++;
} else {
/* let's read it back */
set_bit(R5_Wantread, &dev->flags);
set_bit(R5_LOCKED, &dev->flags);
+ locked++;
}
}
+ if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
+ /* Need to write out all blocks after computing parity */
+ sh->disks = conf->raid_disks;
+ sh->pd_idx = stripe_to_pdidx(sh->sector, conf, conf->raid_disks);
+ compute_parity(sh, RECONSTRUCT_WRITE);
+ for (i= conf->raid_disks; i--;) {
+ set_bit(R5_LOCKED, &sh->dev[i].flags);
+ locked++;
+ set_bit(R5_Wantwrite, &sh->dev[i].flags);
+ }
+ clear_bit(STRIPE_EXPANDING, &sh->state);
+ } else if (expanded) {
+ clear_bit(STRIPE_EXPAND_READY, &sh->state);
+ atomic_dec(&conf->reshape_stripes);
+ wake_up(&conf->wait_for_overlap);
+ md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
+ }
+
+ if (expanding && locked == 0) {
+ /* We have read all the blocks in this stripe and now we need to
+ * copy some of them into a target stripe for expand.
+ */
+ clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+ for (i=0; i< sh->disks; i++)
+ if (i != sh->pd_idx) {
+ int dd_idx, pd_idx, j;
+ struct stripe_head *sh2;
+
+ sector_t bn = compute_blocknr(sh, i);
+ sector_t s = raid5_compute_sector(bn, conf->raid_disks,
+ conf->raid_disks-1,
+ &dd_idx, &pd_idx, conf);
+ sh2 = get_active_stripe(conf, s, conf->raid_disks, pd_idx, 1);
+ if (sh2 == NULL)
+ /* so far only the early blocks of this stripe
+ * have been requested. When later blocks
+ * get requested, we will try again
+ */
+ continue;
+ if(!test_bit(STRIPE_EXPANDING, &sh2->state) ||
+ test_bit(R5_Expanded, &sh2->dev[dd_idx].flags)) {
+ /* must have already done this block */
+ release_stripe(sh2);
+ continue;
+ }
+ memcpy(page_address(sh2->dev[dd_idx].page),
+ page_address(sh->dev[i].page),
+ STRIPE_SIZE);
+ set_bit(R5_Expanded, &sh2->dev[dd_idx].flags);
+ set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags);
+ for (j=0; j<conf->raid_disks; j++)
+ if (j != sh2->pd_idx &&
+ !test_bit(R5_Expanded, &sh2->dev[j].flags))
+ break;
+ if (j == conf->raid_disks) {
+ set_bit(STRIPE_EXPAND_READY, &sh2->state);
+ set_bit(STRIPE_HANDLE, &sh2->state);
+ }
+ release_stripe(sh2);
+ }
+ }
+
spin_unlock(&sh->lock);
while ((bi=return_bi)) {
@@ -1384,7 +1592,7 @@ static void handle_stripe(struct stripe_head *sh)
rcu_read_unlock();
if (rdev) {
- if (syncing)
+ if (syncing || expanding || expanded)
md_sync_acct(rdev->bdev, STRIPE_SECTORS);
bi->bi_bdev = rdev->bdev;
@@ -1526,17 +1734,16 @@ static inline void raid5_plug_device(raid5_conf_t *conf)
spin_unlock_irq(&conf->device_lock);
}
-static int make_request (request_queue_t *q, struct bio * bi)
+static int make_request(request_queue_t *q, struct bio * bi)
{
mddev_t *mddev = q->queuedata;
raid5_conf_t *conf = mddev_to_conf(mddev);
- const unsigned int raid_disks = conf->raid_disks;
- const unsigned int data_disks = raid_disks - 1;
unsigned int dd_idx, pd_idx;
sector_t new_sector;
sector_t logical_sector, last_sector;
struct stripe_head *sh;
const int rw = bio_data_dir(bi);
+ int remaining;
if (unlikely(bio_barrier(bi))) {
bio_endio(bi, bi->bi_size, -EOPNOTSUPP);
@@ -1555,20 +1762,77 @@ static int make_request (request_queue_t *q, struct bio * bi)
for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
DEFINE_WAIT(w);
-
- new_sector = raid5_compute_sector(logical_sector,
- raid_disks, data_disks, &dd_idx, &pd_idx, conf);
+ int disks;
+ retry:
+ prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE);
+ if (likely(conf->expand_progress == MaxSector))
+ disks = conf->raid_disks;
+ else {
+ /* spinlock is needed as expand_progress may be
+ * 64bit on a 32bit platform, and so it might be
+ * possible to see a half-updated value
+ * Ofcourse expand_progress could change after
+ * the lock is dropped, so once we get a reference
+ * to the stripe that we think it is, we will have
+ * to check again.
+ */
+ spin_lock_irq(&conf->device_lock);
+ disks = conf->raid_disks;
+ if (logical_sector >= conf->expand_progress)
+ disks = conf->previous_raid_disks;
+ else {
+ if (logical_sector >= conf->expand_lo) {
+ spin_unlock_irq(&conf->device_lock);
+ schedule();
+ goto retry;
+ }
+ }
+ spin_unlock_irq(&conf->device_lock);
+ }
+ new_sector = raid5_compute_sector(logical_sector, disks, disks - 1,
+ &dd_idx, &pd_idx, conf);
PRINTK("raid5: make_request, sector %llu logical %llu\n",
(unsigned long long)new_sector,
(unsigned long long)logical_sector);
- retry:
- prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE);
- sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK));
+ sh = get_active_stripe(conf, new_sector, disks, pd_idx, (bi->bi_rw&RWA_MASK));
if (sh) {
- if (!add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) {
- /* Add failed due to overlap. Flush everything
+ if (unlikely(conf->expand_progress != MaxSector)) {
+ /* expansion might have moved on while waiting for a
+ * stripe, so we must do the range check again.
+ * Expansion could still move past after this
+ * test, but as we are holding a reference to
+ * 'sh', we know that if that happens,
+ * STRIPE_EXPANDING will get set and the expansion
+ * won't proceed until we finish with the stripe.
+ */
+ int must_retry = 0;
+ spin_lock_irq(&conf->device_lock);
+ if (logical_sector < conf->expand_progress &&
+ disks == conf->previous_raid_disks)
+ /* mismatch, need to try again */
+ must_retry = 1;
+ spin_unlock_irq(&conf->device_lock);
+ if (must_retry) {
+ release_stripe(sh);
+ goto retry;
+ }
+ }
+ /* FIXME what if we get a false positive because these
+ * are being updated.
+ */
+ if (logical_sector >= mddev->suspend_lo &&
+ logical_sector < mddev->suspend_hi) {
+ release_stripe(sh);
+ schedule();
+ goto retry;
+ }
+
+ if (test_bit(STRIPE_EXPANDING, &sh->state) ||
+ !add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) {
+ /* Stripe is busy expanding or
+ * add failed due to overlap. Flush everything
* and wait a while
*/
raid5_unplug_device(mddev->queue);
@@ -1580,7 +1844,6 @@ static int make_request (request_queue_t *q, struct bio * bi)
raid5_plug_device(conf);
handle_stripe(sh);
release_stripe(sh);
-
} else {
/* cannot get stripe for read-ahead, just give-up */
clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -1590,7 +1853,9 @@ static int make_request (request_queue_t *q, struct bio * bi)
}
spin_lock_irq(&conf->device_lock);
- if (--bi->bi_phys_segments == 0) {
+ remaining = --bi->bi_phys_segments;
+ spin_unlock_irq(&conf->device_lock);
+ if (remaining == 0) {
int bytes = bi->bi_size;
if ( bio_data_dir(bi) == WRITE )
@@ -1598,7 +1863,6 @@ static int make_request (request_queue_t *q, struct bio * bi)
bi->bi_size = 0;
bi->bi_end_io(bi, bytes, 0);
}
- spin_unlock_irq(&conf->device_lock);
return 0;
}
@@ -1607,12 +1871,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
{
raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
struct stripe_head *sh;
- int sectors_per_chunk = conf->chunk_size >> 9;
- sector_t x;
- unsigned long stripe;
- int chunk_offset;
- int dd_idx, pd_idx;
- sector_t first_sector;
+ int pd_idx;
+ sector_t first_sector, last_sector;
int raid_disks = conf->raid_disks;
int data_disks = raid_disks-1;
sector_t max_sector = mddev->size << 1;
@@ -1621,6 +1881,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
if (sector_nr >= max_sector) {
/* just being told to finish up .. nothing much to do */
unplug_slaves(mddev);
+ if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) {
+ end_reshape(conf);
+ return 0;
+ }
if (mddev->curr_resync < max_sector) /* aborted */
bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
@@ -1631,6 +1895,123 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return 0;
}
+
+ if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) {
+ /* reshaping is quite different to recovery/resync so it is
+ * handled quite separately ... here.
+ *
+ * On each call to sync_request, we gather one chunk worth of
+ * destination stripes and flag them as expanding.
+ * Then we find all the source stripes and request reads.
+ * As the reads complete, handle_stripe will copy the data
+ * into the destination stripe and release that stripe.
+ */
+ int i;
+ int dd_idx;
+ sector_t writepos, safepos, gap;
+
+ if (sector_nr == 0 &&
+ conf->expand_progress != 0) {
+ /* restarting in the middle, skip the initial sectors */
+ sector_nr = conf->expand_progress;
+ sector_div(sector_nr, conf->raid_disks-1);
+ *skipped = 1;
+ return sector_nr;
+ }
+
+ /* we update the metadata when there is more than 3Meg
+ * in the block range (that is rather arbitrary, should
+ * probably be time based) or when the data about to be
+ * copied would over-write the source of the data at
+ * the front of the range.
+ * i.e. one new_stripe forward from expand_progress new_maps
+ * to after where expand_lo old_maps to
+ */
+ writepos = conf->expand_progress +
+ conf->chunk_size/512*(conf->raid_disks-1);
+ sector_div(writepos, conf->raid_disks-1);
+ safepos = conf->expand_lo;
+ sector_div(safepos, conf->previous_raid_disks-1);
+ gap = conf->expand_progress - conf->expand_lo;
+
+ if (writepos >= safepos ||
+ gap > (conf->raid_disks-1)*3000*2 /*3Meg*/) {
+ /* Cannot proceed until we've updated the superblock... */
+ wait_event(conf->wait_for_overlap,
+ atomic_read(&conf->reshape_stripes)==0);
+ mddev->reshape_position = conf->expand_progress;
+ mddev->sb_dirty = 1;
+ md_wakeup_thread(mddev->thread);
+ wait_event(mddev->sb_wait, mddev->sb_dirty == 0 ||
+ kthread_should_stop());
+ spin_lock_irq(&conf->device_lock);
+ conf->expand_lo = mddev->reshape_position;
+ spin_unlock_irq(&conf->device_lock);
+ wake_up(&conf->wait_for_overlap);
+ }
+
+ for (i=0; i < conf->chunk_size/512; i+= STRIPE_SECTORS) {
+ int j;
+ int skipped = 0;
+ pd_idx = stripe_to_pdidx(sector_nr+i, conf, conf->raid_disks);
+ sh = get_active_stripe(conf, sector_nr+i,
+ conf->raid_disks, pd_idx, 0);
+ set_bit(STRIPE_EXPANDING, &sh->state);
+ atomic_inc(&conf->reshape_stripes);
+ /* If any of this stripe is beyond the end of the old
+ * array, then we need to zero those blocks
+ */
+ for (j=sh->disks; j--;) {
+ sector_t s;
+ if (j == sh->pd_idx)
+ continue;
+ s = compute_blocknr(sh, j);
+ if (s < (mddev->array_size<<1)) {
+ skipped = 1;
+ continue;
+ }
+ memset(page_address(sh->dev[j].page), 0, STRIPE_SIZE);
+ set_bit(R5_Expanded, &sh->dev[j].flags);
+ set_bit(R5_UPTODATE, &sh->dev[j].flags);
+ }
+ if (!skipped) {
+ set_bit(STRIPE_EXPAND_READY, &sh->state);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ }
+ release_stripe(sh);
+ }
+ spin_lock_irq(&conf->device_lock);
+ conf->expand_progress = (sector_nr + i)*(conf->raid_disks-1);
+ spin_unlock_irq(&conf->device_lock);
+ /* Ok, those stripe are ready. We can start scheduling
+ * reads on the source stripes.
+ * The source stripes are determined by mapping the first and last
+ * block on the destination stripes.
+ */
+ raid_disks = conf->previous_raid_disks;
+ data_disks = raid_disks - 1;
+ first_sector =
+ raid5_compute_sector(sector_nr*(conf->raid_disks-1),
+ raid_disks, data_disks,
+ &dd_idx, &pd_idx, conf);
+ last_sector =
+ raid5_compute_sector((sector_nr+conf->chunk_size/512)
+ *(conf->raid_disks-1) -1,
+ raid_disks, data_disks,
+ &dd_idx, &pd_idx, conf);
+ if (last_sector >= (mddev->size<<1))
+ last_sector = (mddev->size<<1)-1;
+ while (first_sector <= last_sector) {
+ pd_idx = stripe_to_pdidx(first_sector, conf, conf->previous_raid_disks);
+ sh = get_active_stripe(conf, first_sector,
+ conf->previous_raid_disks, pd_idx, 0);
+ set_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ release_stripe(sh);
+ first_sector += STRIPE_SECTORS;
+ }
+ return conf->chunk_size>>9;
+ }
/* if there is 1 or more failed drives and we are trying
* to resync, then assert that we are finished, because there is
* nothing we can do.
@@ -1649,16 +2030,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
}
- x = sector_nr;
- chunk_offset = sector_div(x, sectors_per_chunk);
- stripe = x;
- BUG_ON(x != stripe);
-
- first_sector = raid5_compute_sector((sector_t)stripe*data_disks*sectors_per_chunk
- + chunk_offset, raid_disks, data_disks, &dd_idx, &pd_idx, conf);
- sh = get_active_stripe(conf, sector_nr, pd_idx, 1);
+ pd_idx = stripe_to_pdidx(sector_nr, conf, raid_disks);
+ sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 1);
if (sh == NULL) {
- sh = get_active_stripe(conf, sector_nr, pd_idx, 0);
+ sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 0);
/* make sure we don't swamp the stripe cache if someone else
* is trying to get access
*/
@@ -1822,11 +2197,64 @@ static int run(mddev_t *mddev)
return -EIO;
}
- mddev->private = kzalloc(sizeof (raid5_conf_t)
- + mddev->raid_disks * sizeof(struct disk_info),
- GFP_KERNEL);
+ if (mddev->reshape_position != MaxSector) {
+ /* Check that we can continue the reshape.
+ * Currently only disks can change, it must
+ * increase, and we must be past the point where
+ * a stripe over-writes itself
+ */
+ sector_t here_new, here_old;
+ int old_disks;
+
+ if (mddev->new_level != mddev->level ||
+ mddev->new_layout != mddev->layout ||
+ mddev->new_chunk != mddev->chunk_size) {
+ printk(KERN_ERR "raid5: %s: unsupported reshape required - aborting.\n",
+ mdname(mddev));
+ return -EINVAL;
+ }
+ if (mddev->delta_disks <= 0) {
+ printk(KERN_ERR "raid5: %s: unsupported reshape (reduce disks) required - aborting.\n",
+ mdname(mddev));
+ return -EINVAL;
+ }
+ old_disks = mddev->raid_disks - mddev->delta_disks;
+ /* reshape_position must be on a new-stripe boundary, and one
+ * further up in new geometry must map after here in old geometry.
+ */
+ here_new = mddev->reshape_position;
+ if (sector_div(here_new, (mddev->chunk_size>>9)*(mddev->raid_disks-1))) {
+ printk(KERN_ERR "raid5: reshape_position not on a stripe boundary\n");
+ return -EINVAL;
+ }
+ /* here_new is the stripe we will write to */
+ here_old = mddev->reshape_position;
+ sector_div(here_old, (mddev->chunk_size>>9)*(old_disks-1));
+ /* here_old is the first stripe that we might need to read from */
+ if (here_new >= here_old) {
+ /* Reading from the same stripe as writing to - bad */
+ printk(KERN_ERR "raid5: reshape_position too early for auto-recovery - aborting.\n");
+ return -EINVAL;
+ }
+ printk(KERN_INFO "raid5: reshape will continue\n");
+ /* OK, we should be able to continue; */
+ }
+
+
+ mddev->private = kzalloc(sizeof (raid5_conf_t), GFP_KERNEL);
if ((conf = mddev->private) == NULL)
goto abort;
+ if (mddev->reshape_position == MaxSector) {
+ conf->previous_raid_disks = conf->raid_disks = mddev->raid_disks;
+ } else {
+ conf->raid_disks = mddev->raid_disks;
+ conf->previous_raid_disks = mddev->raid_disks - mddev->delta_disks;
+ }
+
+ conf->disks = kzalloc(conf->raid_disks * sizeof(struct disk_info),
+ GFP_KERNEL);
+ if (!conf->disks)
+ goto abort;
conf->mddev = mddev;
@@ -1847,7 +2275,7 @@ static int run(mddev_t *mddev)
ITERATE_RDEV(mddev,rdev,tmp) {
raid_disk = rdev->raid_disk;
- if (raid_disk >= mddev->raid_disks
+ if (raid_disk >= conf->raid_disks
|| raid_disk < 0)
continue;
disk = conf->disks + raid_disk;
@@ -1863,7 +2291,6 @@ static int run(mddev_t *mddev)
}
}
- conf->raid_disks = mddev->raid_disks;
/*
* 0 for a fully functional array, 1 for a degraded array.
*/
@@ -1873,6 +2300,7 @@ static int run(mddev_t *mddev)
conf->level = mddev->level;
conf->algorithm = mddev->layout;
conf->max_nr_stripes = NR_STRIPES;
+ conf->expand_progress = mddev->reshape_position;
/* device size must be a multiple of chunk size */
mddev->size &= ~(mddev->chunk_size/1024 -1);
@@ -1945,6 +2373,21 @@ static int run(mddev_t *mddev)
print_raid5_conf(conf);
+ if (conf->expand_progress != MaxSector) {
+ printk("...ok start reshape thread\n");
+ conf->expand_lo = conf->expand_progress;
+ atomic_set(&conf->reshape_stripes, 0);
+ clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+ clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+ set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
+ set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+ mddev->sync_thread = md_register_thread(md_do_sync, mddev,
+ "%s_reshape");
+ /* FIXME if md_register_thread fails?? */
+ md_wakeup_thread(mddev->sync_thread);
+
+ }
+
/* read-ahead size must cover two whole stripes, which is
* 2 * (n-1) * chunksize where 'n' is the number of raid devices
*/
@@ -1960,12 +2403,13 @@ static int run(mddev_t *mddev)
mddev->queue->unplug_fn = raid5_unplug_device;
mddev->queue->issue_flush_fn = raid5_issue_flush;
+ mddev->array_size = mddev->size * (conf->previous_raid_disks - 1);
- mddev->array_size = mddev->size * (mddev->raid_disks - 1);
return 0;
abort:
if (conf) {
print_raid5_conf(conf);
+ kfree(conf->disks);
kfree(conf->stripe_hashtbl);
kfree(conf);
}
@@ -1986,6 +2430,7 @@ static int stop(mddev_t *mddev)
kfree(conf->stripe_hashtbl);
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
sysfs_remove_group(&mddev->kobj, &raid5_attrs_group);
+ kfree(conf->disks);
kfree(conf);
mddev->private = NULL;
return 0;
@@ -2001,7 +2446,7 @@ static void print_sh (struct stripe_head *sh)
printk("sh %llu, count %d.\n",
(unsigned long long)sh->sector, atomic_read(&sh->count));
printk("sh %llu, ", (unsigned long long)sh->sector);
- for (i = 0; i < sh->raid_conf->raid_disks; i++) {
+ for (i = 0; i < sh->disks; i++) {
printk("(cache%d: %p %ld) ",
i, sh->dev[i].page, sh->dev[i].flags);
}
@@ -2132,7 +2577,7 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
/*
* find the disk ...
*/
- for (disk=0; disk < mddev->raid_disks; disk++)
+ for (disk=0; disk < conf->raid_disks; disk++)
if ((p=conf->disks + disk)->rdev == NULL) {
clear_bit(In_sync, &rdev->flags);
rdev->raid_disk = disk;
@@ -2168,11 +2613,146 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
return 0;
}
+#ifdef CONFIG_MD_RAID5_RESHAPE
+static int raid5_check_reshape(mddev_t *mddev)
+{
+ raid5_conf_t *conf = mddev_to_conf(mddev);
+ int err;
+
+ if (mddev->delta_disks < 0 ||
+ mddev->new_level != mddev->level)
+ return -EINVAL; /* Cannot shrink array or change level yet */
+ if (mddev->delta_disks == 0)
+ return 0; /* nothing to do */
+
+ /* Can only proceed if there are plenty of stripe_heads.
+ * We need a minimum of one full stripe,, and for sensible progress
+ * it is best to have about 4 times that.
+ * If we require 4 times, then the default 256 4K stripe_heads will
+ * allow for chunk sizes up to 256K, which is probably OK.
+ * If the chunk size is greater, user-space should request more
+ * stripe_heads first.
+ */
+ if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes ||
+ (mddev->new_chunk / STRIPE_SIZE) * 4 > conf->max_nr_stripes) {
+ printk(KERN_WARNING "raid5: reshape: not enough stripes. Needed %lu\n",
+ (mddev->chunk_size / STRIPE_SIZE)*4);
+ return -ENOSPC;
+ }
+
+ err = resize_stripes(conf, conf->raid_disks + mddev->delta_disks);
+ if (err)
+ return err;
+
+ /* looks like we might be able to manage this */
+ return 0;
+}
+
+static int raid5_start_reshape(mddev_t *mddev)
+{
+ raid5_conf_t *conf = mddev_to_conf(mddev);
+ mdk_rdev_t *rdev;
+ struct list_head *rtmp;
+ int spares = 0;
+ int added_devices = 0;
+
+ if (mddev->degraded ||
+ test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+ return -EBUSY;
+
+ ITERATE_RDEV(mddev, rdev, rtmp)
+ if (rdev->raid_disk < 0 &&
+ !test_bit(Faulty, &rdev->flags))
+ spares++;
+
+ if (spares < mddev->delta_disks-1)
+ /* Not enough devices even to make a degraded array
+ * of that size
+ */
+ return -EINVAL;
+
+ atomic_set(&conf->reshape_stripes, 0);
+ spin_lock_irq(&conf->device_lock);
+ conf->previous_raid_disks = conf->raid_disks;
+ conf->raid_disks += mddev->delta_disks;
+ conf->expand_progress = 0;
+ conf->expand_lo = 0;
+ spin_unlock_irq(&conf->device_lock);
+
+ /* Add some new drives, as many as will fit.
+ * We know there are enough to make the newly sized array work.
+ */
+ ITERATE_RDEV(mddev, rdev, rtmp)
+ if (rdev->raid_disk < 0 &&
+ !test_bit(Faulty, &rdev->flags)) {
+ if (raid5_add_disk(mddev, rdev)) {
+ char nm[20];
+ set_bit(In_sync, &rdev->flags);
+ conf->working_disks++;
+ added_devices++;
+ sprintf(nm, "rd%d", rdev->raid_disk);
+ sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
+ } else
+ break;
+ }
+
+ mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) - added_devices;
+ mddev->raid_disks = conf->raid_disks;
+ mddev->reshape_position = 0;
+ mddev->sb_dirty = 1;
+
+ clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+ clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+ set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
+ set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+ mddev->sync_thread = md_register_thread(md_do_sync, mddev,
+ "%s_reshape");
+ if (!mddev->sync_thread) {
+ mddev->recovery = 0;
+ spin_lock_irq(&conf->device_lock);
+ mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks;
+ conf->expand_progress = MaxSector;
+ spin_unlock_irq(&conf->device_lock);
+ return -EAGAIN;
+ }
+ md_wakeup_thread(mddev->sync_thread);
+ md_new_event(mddev);
+ return 0;
+}
+#endif
+
+static void end_reshape(raid5_conf_t *conf)
+{
+ struct block_device *bdev;
+
+ if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
+ conf->mddev->array_size = conf->mddev->size * (conf->raid_disks-1);
+ set_capacity(conf->mddev->gendisk, conf->mddev->array_size << 1);
+ conf->mddev->changed = 1;
+
+ bdev = bdget_disk(conf->mddev->gendisk, 0);
+ if (bdev) {
+ mutex_lock(&bdev->bd_inode->i_mutex);
+ i_size_write(bdev->bd_inode, conf->mddev->array_size << 10);
+ mutex_unlock(&bdev->bd_inode->i_mutex);
+ bdput(bdev);
+ }
+ spin_lock_irq(&conf->device_lock);
+ conf->expand_progress = MaxSector;
+ spin_unlock_irq(&conf->device_lock);
+ conf->mddev->reshape_position = MaxSector;
+ }
+}
+
static void raid5_quiesce(mddev_t *mddev, int state)
{
raid5_conf_t *conf = mddev_to_conf(mddev);
switch(state) {
+ case 2: /* resume for a suspend */
+ wake_up(&conf->wait_for_overlap);
+ break;
+
case 1: /* stop all writes */
spin_lock_irq(&conf->device_lock);
conf->quiesce = 1;
@@ -2186,6 +2766,7 @@ static void raid5_quiesce(mddev_t *mddev, int state)
spin_lock_irq(&conf->device_lock);
conf->quiesce = 0;
wake_up(&conf->wait_for_stripe);
+ wake_up(&conf->wait_for_overlap);
spin_unlock_irq(&conf->device_lock);
break;
}
@@ -2206,6 +2787,10 @@ static struct mdk_personality raid5_personality =
.spare_active = raid5_spare_active,
.sync_request = sync_request,
.resize = raid5_resize,
+#ifdef CONFIG_MD_RAID5_RESHAPE
+ .check_reshape = raid5_check_reshape,
+ .start_reshape = raid5_start_reshape,
+#endif
.quiesce = raid5_quiesce,
};
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index cd477ebf2ee..6df4930fdde 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -331,9 +331,9 @@ static int grow_stripes(raid6_conf_t *conf, int num)
kmem_cache_t *sc;
int devs = conf->raid_disks;
- sprintf(conf->cache_name, "raid6/%s", mdname(conf->mddev));
+ sprintf(conf->cache_name[0], "raid6/%s", mdname(conf->mddev));
- sc = kmem_cache_create(conf->cache_name,
+ sc = kmem_cache_create(conf->cache_name[0],
sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
0, 0, NULL, NULL);
if (!sc)
@@ -2006,11 +2006,14 @@ static int run(mddev_t *mddev)
return -EIO;
}
- mddev->private = kzalloc(sizeof (raid6_conf_t)
- + mddev->raid_disks * sizeof(struct disk_info),
- GFP_KERNEL);
+ mddev->private = kzalloc(sizeof (raid6_conf_t), GFP_KERNEL);
if ((conf = mddev->private) == NULL)
goto abort;
+ conf->disks = kzalloc(mddev->raid_disks * sizeof(struct disk_info),
+ GFP_KERNEL);
+ if (!conf->disks)
+ goto abort;
+
conf->mddev = mddev;
if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL)
@@ -2158,6 +2161,7 @@ abort:
print_raid6_conf(conf);
safe_put_page(conf->spare_page);
kfree(conf->stripe_hashtbl);
+ kfree(conf->disks);
kfree(conf);
}
mddev->private = NULL;
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index c2602b34049..baa9f58beff 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -50,5 +50,19 @@ config VIDEO_IR
config VIDEO_TVEEPROM
tristate
+config USB_DABUSB
+ tristate "DABUSB driver"
+ depends on USB
+ ---help---
+ A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
+ brought to you by the DAB-Team
+ <http://wwwbode.cs.tum.edu/Par/arch/dab/>. This driver can be taken
+ as an example for URB-based bulk, control, and isochronous
+ transactions. URB's are explained in
+ <Documentation/usb/URB.txt>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called dabusb.
+
endmenu
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index 3870fa948cc..523ab3851c7 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -50,14 +50,15 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
/********************************************************************************/
/* common dma functions */
-void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf)
+void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
+ struct saa7146_buf *buf)
{
DEB_EE(("dev:%p, buf:%p\n",dev,buf));
BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb,0,0);
- videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma);
+ videobuf_dma_unmap(q, &buf->vb.dma);
videobuf_dma_free(&buf->vb.dma);
buf->vb.state = STATE_NEEDS_INIT;
}
diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
index 500bd3f05e1..063608462eb 100644
--- a/drivers/media/common/saa7146_vbi.c
+++ b/drivers/media/common/saa7146_vbi.c
@@ -236,7 +236,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
}
if (buf->vb.size != size)
- saa7146_dma_free(dev,buf);
+ saa7146_dma_free(dev,q,buf);
if (STATE_NEEDS_INIT == buf->vb.state) {
buf->vb.width = llength;
@@ -247,7 +247,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
saa7146_pgtable_free(dev->pci, &buf->pt[2]);
saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
- err = videobuf_iolock(dev->pci,&buf->vb, NULL);
+ err = videobuf_iolock(q,&buf->vb, NULL);
if (err)
goto oops;
err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen);
@@ -261,7 +261,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
oops:
DEB_VBI(("error out.\n"));
- saa7146_dma_free(dev,buf);
+ saa7146_dma_free(dev,q,buf);
return err;
}
@@ -301,7 +301,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
DEB_VBI(("vb:%p\n",vb));
- saa7146_dma_free(dev,buf);
+ saa7146_dma_free(dev,q,buf);
}
static struct videobuf_queue_ops vbi_qops = {
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 6b42713d97f..e7079d1bd53 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -1275,7 +1275,7 @@ static int buffer_prepare(struct videobuf_queue *q,
buf->vb.field != field ||
buf->vb.field != fh->video_fmt.field ||
buf->fmt != &fh->video_fmt) {
- saa7146_dma_free(dev,buf);
+ saa7146_dma_free(dev,q,buf);
}
if (STATE_NEEDS_INIT == buf->vb.state) {
@@ -1304,7 +1304,7 @@ static int buffer_prepare(struct videobuf_queue *q,
saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
}
- err = videobuf_iolock(dev->pci,&buf->vb, &vv->ov_fb);
+ err = videobuf_iolock(q,&buf->vb, &vv->ov_fb);
if (err)
goto oops;
err = saa7146_pgtable_build(dev,buf);
@@ -1318,7 +1318,7 @@ static int buffer_prepare(struct videobuf_queue *q,
oops:
DEB_D(("error out.\n"));
- saa7146_dma_free(dev,buf);
+ saa7146_dma_free(dev,q,buf);
return err;
}
@@ -1363,7 +1363,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
DEB_CAP(("vbuf:%p\n",vb));
- saa7146_dma_free(dev,buf);
+ saa7146_dma_free(dev,q,buf);
}
static struct videobuf_queue_ops video_qops = {
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
index a6c91db40ad..06ec9fff0ec 100644
--- a/drivers/media/dvb/b2c2/flexcop-usb.c
+++ b/drivers/media/dvb/b2c2/flexcop-usb.c
@@ -541,6 +541,7 @@ static struct usb_device_id flexcop_usb_table [] = {
{ USB_DEVICE(0x0af7, 0x0101) },
{ }
};
+MODULE_DEVICE_TABLE (usb, flexcop_usb_table);
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver flexcop_usb_driver = {
diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile
index d188e4c670b..9d197efb481 100644
--- a/drivers/media/dvb/bt8xx/Makefile
+++ b/drivers/media/dvb/bt8xx/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 54f8b95717b..96fe0ecae25 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -86,7 +86,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
if (dvbdev && dvbdev->fops) {
int err = 0;
- struct file_operations *old_fops;
+ const struct file_operations *old_fops;
file->private_data = dvbdev;
old_fops = file->f_op;
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index e14bf43941e..a14e737ec84 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -81,18 +81,19 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
return -EAGAIN;
if (num > 2)
- warn("more than 2 i2c messages at a time is not handled yet. TODO.");
+ warn("more than two i2c messages at a time is not handled yet. TODO.");
for (i = 0; i < num; i++) {
- switch (msg[i].addr) {
- case 0x63:
- cxusb_gpio_tuner(d,0);
- break;
- default:
- cxusb_gpio_tuner(d,1);
- break;
- }
+ if (d->udev->descriptor.idVendor == USB_VID_MEDION)
+ switch (msg[i].addr) {
+ case 0x63:
+ cxusb_gpio_tuner(d,0);
+ break;
+ default:
+ cxusb_gpio_tuner(d,1);
+ break;
+ }
/* read request */
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
@@ -108,7 +109,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
break;
if (ibuf[0] != 0x08)
- deb_info("i2c read could have been failed\n");
+ deb_i2c("i2c read may have failed\n");
memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len);
@@ -122,7 +123,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0)
break;
if (ibuf != 0x08)
- deb_info("i2c write could have been failed\n");
+ deb_i2c("i2c write may have failed\n");
}
}
@@ -410,7 +411,6 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const
if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
- /* FIXME: are we allowed to change the fw-data ? */
fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1;
fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8;
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
index 087c9942785..c8ef77554b0 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.h
+++ b/drivers/media/dvb/dvb-usb/cxusb.h
@@ -6,6 +6,8 @@
extern int dvb_usb_cxusb_debug;
#define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args)
+#define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \
+ dprintk(dvb_usb_cxusb_debug,0x01,args)
/* usb commands - some of it are guesses, don't have a reference yet */
#define CMD_I2C_WRITE 0x08
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index 2f23ceab8d4..603a22e4bfe 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -369,6 +369,11 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
fm_matrix = 0x3001; // stereo
src = 0x0020;
break;
+ case V4L2_TUNER_MODE_LANG1_LANG2:
+ dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n");
+ fm_matrix = 0x3000; // bilingual
+ src = 0x0020;
+ break;
case V4L2_TUNER_MODE_LANG1:
dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n");
fm_matrix = 0x3000; // mono
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index c622a4da566..f31a19890b1 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -16,31 +16,7 @@ config VIDEO_ADV_DEBUG
V4L devices.
In doubt, say N.
-config VIDEO_BT848
- tristate "BT848 Video For Linux"
- depends on VIDEO_DEV && PCI && I2C
- select I2C_ALGOBIT
- select FW_LOADER
- select VIDEO_BTCX
- select VIDEO_BUF
- select VIDEO_IR
- select VIDEO_TUNER
- select VIDEO_TVEEPROM
- select VIDEO_MSP3400
- ---help---
- Support for BT848 based frame grabber/overlay boards. This includes
- the Miro, Hauppauge and STB boards. Please read the material in
- <file:Documentation/video4linux/bttv/> for more information.
-
- To compile this driver as a module, choose M here: the
- module will be called bttv.
-
-config VIDEO_BT848_DVB
- bool "DVB/ATSC Support for bt878 based TV cards"
- depends on VIDEO_BT848 && DVB_CORE
- select DVB_BT8XX
- ---help---
- This adds support for DVB/ATSC cards based on the BT878 chip.
+source "drivers/media/video/bt8xx/Kconfig"
config VIDEO_SAA6588
tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards"
@@ -315,8 +291,6 @@ config VIDEO_HEXIUM_GEMINI
source "drivers/media/video/cx88/Kconfig"
-source "drivers/media/video/em28xx/Kconfig"
-
config VIDEO_OVCAMCHIP
tristate "OmniVision Camera Chip support"
depends on VIDEO_DEV && I2C
@@ -391,4 +365,234 @@ config VIDEO_SAA7127
To compile this driver as a module, choose M here: the
module will be called saa7127
+#
+# USB Multimedia device configuration
+#
+
+menu "V4L USB devices"
+ depends on USB && VIDEO_DEV
+
+source "drivers/media/video/em28xx/Kconfig"
+
+config USB_VICAM
+ tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
+ depends on USB && VIDEO_DEV && EXPERIMENTAL
+ ---help---
+ Say Y here if you have 3com homeconnect camera (vicam).
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Multimedia Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ at <file:Documentation/video4linux/API.html>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vicam.
+
+config USB_DSBR
+ tristate "D-Link USB FM radio support (EXPERIMENTAL)"
+ depends on USB && VIDEO_DEV && EXPERIMENTAL
+ ---help---
+ Say Y here if you want to connect this type of radio to your
+ computer's USB port. Note that the audio is not digital, and
+ you must connect the line out connector to a sound card or a
+ set of speakers.
+
+ This driver uses the Video For Linux API. You must enable
+ (Y or M in config) Video For Linux (under Character Devices)
+ to use this driver. Information on this API and pointers to
+ "v4l" programs may be found at
+ <file:Documentation/video4linux/API.html>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called dsbr100.
+
+config USB_ET61X251
+ tristate "USB ET61X[12]51 PC Camera Controller support"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y here if you want support for cameras based on Etoms ET61X151
+ or ET61X251 PC Camera Controllers.
+
+ See <file:Documentation/usb/et61x251.txt> for more informations.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" to use this driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called et61x251.
+
+config USB_IBMCAM
+ tristate "USB IBM (Xirlink) C-it Camera support"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y here if you want to connect a IBM "C-It" camera, also known as
+ "Xirlink PC Camera" to your computer's USB port. For more
+ information, read <file:Documentation/usb/ibmcam.txt>.
+
+ This driver uses the Video For Linux API. You must enable
+ (Y or M in config) Video For Linux (under Character Devices)
+ to use this driver. Information on this API and pointers to
+ "v4l" programs may be found at
+ <file:Documentation/video4linux/API.html>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ibmcam.
+
+ This camera has several configuration options which
+ can be specified when you load the module. Read
+ <file:Documentation/usb/ibmcam.txt> to learn more.
+
+config USB_KONICAWC
+ tristate "USB Konica Webcam support"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y here if you want support for webcams based on a Konica
+ chipset. This is known to work with the Intel YC76 webcam.
+
+ This driver uses the Video For Linux API. You must enable
+ (Y or M in config) Video For Linux (under Character Devices)
+ to use this driver. Information on this API and pointers to
+ "v4l" programs may be found at
+ <file:Documentation/video4linux/API.html>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called konicawc.
+
+config USB_OV511
+ tristate "USB OV511 Camera support"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y here if you want to connect this type of camera to your
+ computer's USB port. See <file:Documentation/usb/ov511.txt> for more
+ information and for a list of supported cameras.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Character Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ at <file:Documentation/video4linux/API.html>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ov511.
+
+config USB_SE401
+ tristate "USB SE401 Camera support"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y here if you want to connect this type of camera to your
+ computer's USB port. See <file:Documentation/usb/se401.txt> for more
+ information and for a list of supported cameras.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Multimedia Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ at <file:Documentation/video4linux/API.html>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called se401.
+
+config USB_SN9C102
+ tristate "USB SN9C10x PC Camera Controller support"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y here if you want support for cameras based on SONiX SN9C101,
+ SN9C102 or SN9C103 PC Camera Controllers.
+
+ See <file:Documentation/usb/sn9c102.txt> for more informations.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" to use this driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sn9c102.
+
+config USB_STV680
+ tristate "USB STV680 (Pencam) Camera support"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y here if you want to connect this type of camera to your
+ computer's USB port. This includes the Pencam line of cameras.
+ See <file:Documentation/usb/stv680.txt> for more information and for
+ a list of supported cameras.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Multimedia Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ at <file:Documentation/video4linux/API.html>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stv680.
+
+config USB_W9968CF
+ tristate "USB W996[87]CF JPEG Dual Mode Camera support"
+ depends on USB && VIDEO_DEV && I2C && VIDEO_OVCAMCHIP
+ ---help---
+ Say Y here if you want support for cameras based on OV681 or
+ Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
+
+ This driver has an optional plugin, which is distributed as a
+ separate module only (released under GPL). It allows to use higher
+ resolutions and framerates, but cannot be included in the official
+ Linux kernel for performance purposes.
+
+ See <file:Documentation/usb/w9968cf.txt> for more informations.
+
+ This driver uses the Video For Linux and the I2C APIs. It needs the
+ OmniVision Camera Chip support as well. You must say Y or M to
+ "Video For Linux", "I2C Support" and "OmniVision Camera Chip
+ support" to use this driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called w9968cf.
+
+config USB_ZC0301
+ tristate "USB ZC0301 Image Processor and Control Chip support"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y here if you want support for cameras based on the ZC0301
+ Image Processor and Control Chip.
+
+ See <file:Documentation/usb/zc0301.txt> for more informations.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" to use this driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called zc0301.
+
+config USB_PWC
+ tristate "USB Philips Cameras"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y or M here if you want to use one of these Philips & OEM
+ webcams:
+ * Philips PCA645, PCA646
+ * Philips PCVC675, PCVC680, PCVC690
+ * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
+ * Askey VC010
+ * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
+ and 'Orbit'/'Sphere'
+ * Samsung MPC-C10, MPC-C30
+ * Creative Webcam 5, Pro Ex
+ * SOTEC Afina Eye
+ * Visionite VCS-UC300, VCS-UM100
+
+ The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
+ and never will be, but the 665 and 720/20 are supported by other
+ drivers.
+
+ See <file:Documentation/usb/philips.txt> for more information and
+ installation instructions.
+
+ The built-in microphone is enabled by selecting USB Audio support.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Character Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ at <file:Documentation/video4linux/API.html>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pwc.
+
+endmenu # V4L USB devices
+
endmenu
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index f2bd4c0c4f1..1c0e72e5a59 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -2,9 +2,6 @@
# Makefile for the video capture/playback device drivers.
#
-bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
- bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
- bttv-input.o
zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o
zr36067-objs := zoran_procfs.o zoran_device.o \
zoran_driver.o zoran_card.o
@@ -15,8 +12,8 @@ msp3400-objs := msp3400-driver.o msp3400-kthreads.o
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o
-obj-$(CONFIG_VIDEO_BT848) += bttv.o tvaudio.o \
- tda7432.o tda9875.o ir-kbd-i2c.o
+obj-$(CONFIG_VIDEO_BT848) += bt8xx/
+obj-$(CONFIG_VIDEO_BT848) += tvaudio.o tda7432.o tda9875.o ir-kbd-i2c.o
obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
@@ -68,4 +65,23 @@ obj-$(CONFIG_VIDEO_CX25840) += cx25840/
obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
+et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o
+zc0301-objs := zc0301_core.o zc0301_pas202bcb.o
+
+obj-$(CONFIG_USB_DABUSB) += dabusb.o
+obj-$(CONFIG_USB_DSBR) += dsbr100.o
+obj-$(CONFIG_USB_OV511) += ov511.o
+obj-$(CONFIG_USB_SE401) += se401.o
+obj-$(CONFIG_USB_STV680) += stv680.o
+obj-$(CONFIG_USB_W9968CF) += w9968cf.o
+
+obj-$(CONFIG_USB_SN9C102) += sn9c102/
+obj-$(CONFIG_USB_ET61X251) += et61x251/
+obj-$(CONFIG_USB_PWC) += pwc/
+obj-$(CONFIG_USB_ZC0301) += zc0301/
+
+obj-$(CONFIG_USB_IBMCAM) += usbvideo/
+obj-$(CONFIG_USB_KONICAWC) += usbvideo/
+obj-$(CONFIG_USB_VICAM) += usbvideo/
+
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index 671e36db224..48709582a18 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -1,9 +1,9 @@
-/*
+/*
* adv7170 - adv7170, adv7171 video encoder driver version 0.0.1
*
* Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
*
- * Based on adv7176 driver by:
+ * Based on adv7176 driver by:
*
* Copyright (C) 1998 Dave Perks <dperks@ibm.net>
* Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
@@ -173,7 +173,7 @@ adv7170_write_block (struct i2c_client *client,
static const unsigned char init_NTSC[] = {
0x00, 0x10, // MR0
0x01, 0x20, // MR1
- 0x02, 0x0e, // MR2 RTC control: bits 2 and 1
+ 0x02, 0x0e, // MR2 RTC control: bits 2 and 1
0x03, 0x80, // MR3
0x04, 0x30, // MR4
0x05, 0x00, // Reserved
@@ -196,7 +196,7 @@ static const unsigned char init_NTSC[] = {
0x16, 0x00, // CGMS_WSS_0
0x17, 0x00, // CGMS_WSS_1
0x18, 0x00, // CGMS_WSS_2
- 0x19, 0x00, // Teletext Ctl
+ 0x19, 0x00, // Teletext Ctl
};
static const unsigned char init_PAL[] = {
@@ -381,7 +381,7 @@ static unsigned short normal_i2c[] =
};
static unsigned short ignore = I2C_CLIENT_END;
-
+
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 085e8863cac..68e7d7aff5e 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -1,4 +1,4 @@
-/*
+/*
* adv7175 - adv7175a video encoder driver version 0.0.3
*
* Copyright (C) 1998 Dave Perks <dperks@ibm.net>
@@ -233,7 +233,7 @@ adv7175_command (struct i2c_client *client,
sizeof(init_common));
adv7175_write(client, 0x07, TR0MODE | TR0RST);
adv7175_write(client, 0x07, TR0MODE);
- break;
+ break;
case ENCODER_GET_CAPABILITIES:
{
@@ -399,7 +399,7 @@ static unsigned short normal_i2c[] =
};
static unsigned short ignore = I2C_CLIENT_END;
-
+
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index c586f64b6b7..dbe02517059 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -161,39 +161,39 @@ void iic(int n, unsigned long addr, unsigned long data1, unsigned long data2,
{
int i;
- /* Slave Address */
- ar_outl(addr, PLDI2CDATA);
+ /* Slave Address */
+ ar_outl(addr, PLDI2CDATA);
wait_for_vsync();
- /* Start */
- ar_outl(1, PLDI2CCND);
+ /* Start */
+ ar_outl(1, PLDI2CCND);
wait_acknowledge();
/* Transfer data 1 */
- ar_outl(data1, PLDI2CDATA);
+ ar_outl(data1, PLDI2CDATA);
wait_for_vsync();
- ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN);
+ ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN);
wait_acknowledge();
/* Transfer data 2 */
- ar_outl(data2, PLDI2CDATA);
+ ar_outl(data2, PLDI2CDATA);
wait_for_vsync();
- ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN);
+ ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN);
wait_acknowledge();
if (n == 3) {
/* Transfer data 3 */
- ar_outl(data3, PLDI2CDATA);
+ ar_outl(data3, PLDI2CDATA);
wait_for_vsync();
- ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN);
+ ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN);
wait_acknowledge();
- }
+ }
- /* Stop */
+ /* Stop */
for (i = 0; i < 100; i++)
cpu_relax();
- ar_outl(2, PLDI2CCND);
- ar_outl(2, PLDI2CCND);
+ ar_outl(2, PLDI2CCND);
+ ar_outl(2, PLDI2CCND);
while (ar_inl(PLDI2CSTS) & PLDI2CSTS_BB)
cpu_relax();
@@ -204,24 +204,24 @@ void init_iic(void)
{
DEBUG(1, "init_iic:\n");
- /*
+ /*
* ICU Setting (iic)
*/
- /* I2C Setting */
- ar_outl(0x0, PLDI2CCR); /* I2CCR Disable */
- ar_outl(0x0300, PLDI2CMOD); /* I2CMOD ACK/8b-data/7b-addr/auto */
- ar_outl(0x1, PLDI2CACK); /* I2CACK ACK */
+ /* I2C Setting */
+ ar_outl(0x0, PLDI2CCR); /* I2CCR Disable */
+ ar_outl(0x0300, PLDI2CMOD); /* I2CMOD ACK/8b-data/7b-addr/auto */
+ ar_outl(0x1, PLDI2CACK); /* I2CACK ACK */
/* I2C CLK */
- /* 50MH-100k */
+ /* 50MH-100k */
if (freq == 75) {
- ar_outl(369, PLDI2CFREQ); /* BCLK = 75MHz */
+ ar_outl(369, PLDI2CFREQ); /* BCLK = 75MHz */
} else if (freq == 50) {
ar_outl(244, PLDI2CFREQ); /* BCLK = 50MHz */
} else {
ar_outl(244, PLDI2CFREQ); /* default: BCLK = 50MHz */
}
- ar_outl(0x1, PLDI2CCR); /* I2CCR Enable */
+ ar_outl(0x1, PLDI2CCR); /* I2CCR Enable */
}
/**************************************************************************
@@ -253,7 +253,7 @@ static inline void wait_for_vertical_sync(int exp_line)
/*
* check HCOUNT because we cannot check vertical sync.
- */
+ */
for (; tmout >= 0; tmout--) {
l = ar_inl(ARVHCOUNT);
if (l == exp_line)
@@ -562,8 +562,8 @@ static void ar_interrupt(int irq, void *dev, struct pt_regs *regs)
/* operations for interlace mode */
if ( line_count < (AR_HEIGHT_VGA/2) ) /* even line */
line_number = (line_count << 1);
- else /* odd line */
- line_number =
+ else /* odd line */
+ line_number =
(((line_count - (AR_HEIGHT_VGA/2)) << 1) + 1);
} else {
line_number = line_count;
@@ -651,7 +651,7 @@ static int ar_initialize(struct video_device *dev)
cr |= ARVCR1_NORMAL;
ar_outl(cr, ARVCR1);
- /*
+ /*
* Initialize IIC so that CPU can communicate with AR LSI,
* and send boot commands to AR LSI.
*/
@@ -846,7 +846,7 @@ static int __init ar_init(void)
* so register video device as a frame grabber type.
* device is named "video[0-64]".
* video_register_device() initializes h/w using ar_initialize().
- */
+ */
if (video_register_device(ar->vdev, VFL_TYPE_GRABBER, video_nr) != 0) {
/* return -1, -ENFILE(full) or others */
printk("arv: register video (Colour AR) failed.\n");
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index d8a18a6a5be..e7b38fdd5e3 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -1,4 +1,4 @@
-/*
+/*
* bt819 - BT819A VideoStream Decoder (Rockwell Part)
*
* Copyright (C) 1999 Mike Bernson <mike@mlb.org>
@@ -6,7 +6,7 @@
*
* Modifications for LML33/DC10plus unified driver
* Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
+ *
* Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
* - moved over to linux>=2.4.x i2c protocol (9/9/2002)
*
@@ -206,9 +206,9 @@ bt819_init (struct i2c_client *client)
Bug in the bt819 stepping on my board?
*/
0x14, 0x00, /* 0x14 Vertial Scaling lsb */
- 0x16, 0x07, /* 0x16 Video Timing Polarity
+ 0x16, 0x07, /* 0x16 Video Timing Polarity
ACTIVE=active low
- FIELD: high=odd,
+ FIELD: high=odd,
vreset=active high,
hreset=active high */
0x18, 0x68, /* 0x18 AGC Delay */
@@ -497,7 +497,7 @@ static unsigned short normal_i2c[] = {
};
static unsigned short ignore = I2C_CLIENT_END;
-
+
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index 4d47a0a0e97..af3b61d4fa7 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -1,4 +1,4 @@
-/*
+/*
* bt856 - BT856A Digital Video Encoder (Rockwell Part)
*
* Copyright (C) 1999 Mike Bernson <mike@mlb.org>
@@ -285,7 +285,7 @@ bt856_command (struct i2c_client *client,
static unsigned short normal_i2c[] = { I2C_BT856 >> 1, I2C_CLIENT_END };
static unsigned short ignore = I2C_CLIENT_END;
-
+
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig
new file mode 100644
index 00000000000..085477c1261
--- /dev/null
+++ b/drivers/media/video/bt8xx/Kconfig
@@ -0,0 +1,25 @@
+config VIDEO_BT848
+ tristate "BT848 Video For Linux"
+ depends on VIDEO_DEV && PCI && I2C
+ select I2C_ALGOBIT
+ select FW_LOADER
+ select VIDEO_BTCX
+ select VIDEO_BUF
+ select VIDEO_IR
+ select VIDEO_TUNER
+ select VIDEO_TVEEPROM
+ select VIDEO_MSP3400
+ ---help---
+ Support for BT848 based frame grabber/overlay boards. This includes
+ the Miro, Hauppauge and STB boards. Please read the material in
+ <file:Documentation/video4linux/bttv/> for more information.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bttv.
+
+config VIDEO_BT848_DVB
+ bool "DVB/ATSC Support for bt878 based TV cards"
+ depends on VIDEO_BT848 && DVB_CORE
+ select DVB_BT8XX
+ ---help---
+ This adds support for DVB/ATSC cards based on the BT878 chip.
diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile
new file mode 100644
index 00000000000..94350f21cdc
--- /dev/null
+++ b/drivers/media/video/bt8xx/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the video capture/playback device drivers.
+#
+
+bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
+ bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
+ bttv-input.o
+
+obj-$(CONFIG_VIDEO_BT848) += bttv.o
+
+EXTRA_CFLAGS += -I$(src)/..
+EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt8xx/bt832.c
index cc54b62f460..a5187613788 100644
--- a/drivers/media/video/bt832.c
+++ b/drivers/media/video/bt8xx/bt832.c
@@ -30,7 +30,6 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
-#include <media/audiochip.h>
#include <media/v4l2-common.h>
#include "bttv.h"
@@ -39,7 +38,7 @@
MODULE_LICENSE("GPL");
/* Addresses to scan */
-static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1,
+static unsigned short normal_i2c[] = { I2C_ADDR_BT832_ALT1>>1, I2C_ADDR_BT832_ALT2>>1,
I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
diff --git a/drivers/media/video/bt832.h b/drivers/media/video/bt8xx/bt832.h
index 1ce8fa71f7d..1ce8fa71f7d 100644
--- a/drivers/media/video/bt832.h
+++ b/drivers/media/video/bt8xx/bt832.h
diff --git a/drivers/media/video/bt848.h b/drivers/media/video/bt8xx/bt848.h
index 0bcd95303bb..0bcd95303bb 100644
--- a/drivers/media/video/bt848.h
+++ b/drivers/media/video/bt8xx/bt848.h
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index abfa6ad857a..f209a749205 100644
--- a/drivers/media/video/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -39,6 +39,7 @@
#include "bttvp.h"
#include <media/v4l2-common.h>
+#include <media/tvaudio.h>
/* fwd decl */
static void boot_msp34xx(struct bttv *btv, int pin);
@@ -336,7 +337,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 15,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 2, 0, 0, 0, 10 },
+ .gpiomux = { 2, 0, 0, 0 },
+ .gpiomute = 10,
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -350,7 +352,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 7,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 1, 2, 3, 4 },
+ .gpiomux = { 0, 1, 2, 3 },
+ .gpiomute = 4,
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -364,7 +367,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 7,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 4, 0, 2, 3, 1 },
+ .gpiomux = { 4, 0, 2, 3 },
+ .gpiomute = 1,
.no_msp34xx = 1,
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_NTSC,
@@ -383,7 +387,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0 },
+ .gpiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = 4,
.tuner_addr = ADDR_UNSET,
@@ -397,7 +401,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 3,
.muxsel = { 2, 3, 1, 0 },
- .audiomux = { 0, 1, 0, 1, 3 },
+ .gpiomux = { 0, 1, 0, 1 },
+ .gpiomute = 3,
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -411,7 +416,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 3,
.muxsel = { 2, 3, 1, 1 },
.gpiomask = 0x0f,
- .audiomux = { 0x0c, 0x04, 0x08, 0x04, 0 },
+ .gpiomux = { 0x0c, 0x04, 0x08, 0x04 },
/* 0x04 for some cards ?? */
.needs_tvaudio = 1,
.tuner_type = -1,
@@ -428,7 +433,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 3,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 0, 0 },
- .audiomux = { 0 },
+ .gpiomux = { 0 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -444,7 +449,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xc00,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 0xc00, 0x800, 0x400, 0xc00, 0 },
+ .gpiomux = { 0, 0xc00, 0x800, 0x400 },
+ .gpiomute = 0xc00,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -459,7 +465,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 3,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 1, 1, 2, 3, 0 },
+ .gpiomux = { 1, 1, 2, 3 },
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_PAL,
@@ -474,7 +480,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x0f, /* old: 7 */
.muxsel = { 2, 0, 1, 1 },
- .audiomux = { 0, 1, 2, 3, 4 },
+ .gpiomux = { 0, 1, 2, 3 },
+ .gpiomute = 4,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -489,7 +496,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x3014f,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0x20001,0x10001, 0, 0,10 },
+ .gpiomux = { 0x20001,0x10001, 0, 0 },
+ .gpiomute = 10,
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -505,7 +513,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 15,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 13, 14, 11, 7, 0, 0 },
+ .gpiomux = { 13, 14, 11, 7 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -519,7 +527,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 15,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 13, 14, 11, 7, 0, 0 },
+ .gpiomux = { 13, 14, 11, 7 },
.needs_tvaudio = 1,
.msp34xx_alt = 1,
.pll = PLL_28,
@@ -537,7 +545,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 7,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 2, 1, 3, 4 }, /* old: {0, 1, 2, 3, 4} */
+ .gpiomux = { 0, 2, 1, 3 }, /* old: {0, 1, 2, 3, 4} */
+ .gpiomute = 4,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -552,7 +561,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 15,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0 , 0, 1 , 0, 10 },
+ .gpiomux = { 0, 0, 1, 0 },
+ .gpiomute = 10,
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -570,10 +580,11 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 3, 1, 1 },
#if 0
/* old */
- .audiomux = { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 },
+ .gpiomux = { 0x01c000, 0, 0x018000, 0x014000, 0x002000 },
#else
/* 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru> */
- .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 },
+ .gpiomux = { 0x001e00, 0, 0x018000, 0x014000 },
+ .gpiomute = 0x002000,
#endif
.needs_tvaudio = 1,
.pll = PLL_28,
@@ -587,7 +598,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x8300f8,
.muxsel = { 2, 3, 1, 1,0 },
- .audiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007 },
+ .gpiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007 },
+ .gpiomute = 0xcfa007,
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -603,7 +615,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 1, 0, 0, 0, 0 },
+ .gpiomux = { 1, 0, 0, 0 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -617,7 +629,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.gpiomask = 0x8dff00,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0 },
+ .gpiomux = { 0 },
.no_msp34xx = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -644,7 +656,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x1800,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 },
+ .gpiomux = { 0, 0x800, 0x1000, 0x1000 },
+ .gpiomute = 0x1800,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL_I,
.tuner_addr = ADDR_UNSET,
@@ -658,7 +671,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xc00,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 1, 0x800, 0x400, 0xc00, 0 },
+ .gpiomux = { 0, 1, 0x800, 0x400 },
+ .gpiomute = 0xc00,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -674,7 +688,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 7,
.muxsel = { 2, 3, -1 },
.digital_mode = DIGITAL_MODE_CAMERA,
- .audiomux = { 0, 0, 0, 0, 0 },
+ .gpiomux = { 0, 0, 0, 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_ALPS_TSBB5_PAL_I,
@@ -691,7 +705,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xe00,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = {0x400, 0x400, 0x400, 0x400, 0xc00 },
+ .gpiomux = {0x400, 0x400, 0x400, 0x400 },
+ .gpiomute = 0xc00,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -707,7 +722,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x1f0fff,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000 },
+ .gpiomux = { 0x20000, 0x30000, 0x10000, 0 },
+ .gpiomute = 0x40000,
.needs_tvaudio = 0,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -722,7 +738,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 3,
.gpiomask = 7,
.muxsel = { 2, 0, 1, 1 },
- .audiomux = { 0, 1, 2, 3, 4 },
+ .gpiomux = { 0, 1, 2, 3 },
+ .gpiomute = 4,
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -736,7 +753,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x1800,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 },
+ .gpiomux = { 0, 0x800, 0x1000, 0x1000 },
+ .gpiomute = 0x1800,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_SECAM,
.tuner_addr = ADDR_UNSET,
@@ -752,7 +770,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x1f0fff,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000 },
+ .gpiomux = { 0x20000, 0x30000, 0x10000, 0x00000 },
+ .gpiomute = 0x40000,
.needs_tvaudio = 0,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -799,7 +818,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 1, /* was: 4 */
.gpiomask = 0,
.muxsel = { 2, 3, 1, 0, 0},
- .audiomux = { 0 },
+ .gpiomux = { 0 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -815,7 +834,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x1800, /* 0x8dfe00 */
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 },
+ .gpiomux = { 0, 0x0800, 0x1000, 0x1000 },
+ .gpiomute = 0x1800,
.pll = PLL_28,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -829,7 +849,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 3,
.gpiomask = 1,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 1, 0, 0, 0, 0 },
+ .gpiomux = { 1, 0, 0, 0 },
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -845,7 +865,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0 },
+ .gpiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = 4,
.tuner_addr = ADDR_UNSET,
@@ -859,7 +879,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xffff00,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0x500, 0, 0x300, 0x900, 0x900 },
+ .gpiomux = { 0x500, 0, 0x300, 0x900 },
+ .gpiomute = 0x900,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -875,11 +896,12 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 3, 1, 1, 0 }, /* TV, CVid, SVid, CVid over SVid connector */
#if 0
.gpiomask = 0xc33000,
- .audiomux = { 0x422000,0x1000,0x0000,0x620000,0x800000 },
+ .gpiomux = { 0x422000,0x1000,0x0000,0x620000,0x800000 },
#else
/* Alexander Varakin <avarakin@hotmail.com> [stereo version] */
.gpiomask = 0xb33000,
- .audiomux = { 0x122000,0x1000,0x0000,0x620000,0x800000 },
+ .gpiomux = { 0x122000,0x1000,0x0000,0x620000 },
+ .gpiomute = 0x800000,
#endif
/* Audio Routing for "WinFast 2000 XP" (no tv stereo !)
gpio23 -- hef4052:nEnable (0x800000)
@@ -909,7 +931,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x1800,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 },
+ .gpiomux = { 0, 0x800, 0x1000, 0x1000 },
+ .gpiomute = 0x1800,
.pll = PLL_28,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -925,7 +948,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x1800,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
+ .gpiomux = { 0, 0x800, 0x1000, 0x1000 },
+ .gpiomute = 0x1800,
.pll = PLL_28,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -940,7 +964,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xff,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 },
+ .gpiomux = { 0x21, 0x20, 0x24, 0x2c },
+ .gpiomute = 0x29,
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -955,7 +980,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x551e00,
.muxsel = { 2, 3, 1, 0 },
- .audiomux = { 0x551400, 0x551200, 0, 0, 0x551c00, 0x551200 },
+ .gpiomux = { 0x551400, 0x551200, 0, 0 },
+ .gpiomute = 0x551c00,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = 1,
@@ -971,7 +997,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x03000F,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 2, 0xd0001, 0, 0, 1 },
+ .gpiomux = { 2, 0xd0001, 0, 0 },
+ .gpiomute = 1,
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = -1,
@@ -988,7 +1015,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 7,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 4, 0, 2, 3, 1 },
+ .gpiomux = { 4, 0, 2, 3 },
+ .gpiomute = 1,
.no_msp34xx = 1,
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_NTSC,
@@ -1005,7 +1033,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 15,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 13, 4, 11, 7, 0, 0 },
+ .gpiomux = { 13, 4, 11, 7 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -1022,7 +1050,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 0, 0, 0, 0},
+ .gpiomux = { 0, 0, 0, 0},
.needs_tvaudio = 1,
.no_msp34xx = 1,
.pll = PLL_28,
@@ -1038,7 +1066,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xe00b,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc },
+ .gpiomux = { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0 },
+ .gpiomute = 0xff3ffc,
.no_msp34xx = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -1054,7 +1083,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.gpiomask = 3,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 1, 1, 0, 2, 3 },
+ .gpiomux = { 1, 1, 0, 2 },
+ .gpiomute = 3,
.no_msp34xx = 1,
.pll = PLL_NONE,
.tuner_type = -1,
@@ -1069,7 +1099,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 3,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 0, 0 },
- .audiomux = { 0 },
+ .gpiomux = { 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -1084,7 +1114,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xbcf03f,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0xbc803f, 0xbc903f, 0xbcb03f, 0, 0xbcb03f },
+ .gpiomux = { 0xbc803f, 0xbc903f, 0xbcb03f, 0 },
+ .gpiomute = 0xbcb03f,
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = 21,
@@ -1099,7 +1130,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x70000,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000, 0x20000 },
+ .gpiomux = { 0x20000, 0x30000, 0x10000, 0 },
+ .gpiomute = 0x40000,
.needs_tvaudio = 1,
.no_msp34xx = 1,
.pll = PLL_35,
@@ -1118,7 +1150,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 15,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = {2,0,0,0,1 },
+ .gpiomux = {2,0,0,0 },
+ .gpiomute = 1,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -1133,7 +1166,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x010f00,
.muxsel = {2, 3, 0, 0 },
- .audiomux = {0x10000, 0, 0x10000, 0, 0, 0 },
+ .gpiomux = {0x10000, 0, 0x10000, 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_ALPS_TSHC6_NTSC,
@@ -1150,7 +1183,8 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 0xAA0000,
.muxsel = { 2,3,1,1,-1 },
.digital_mode = DIGITAL_MODE_CAMERA,
- .audiomux = { 0x20000, 0, 0x80000, 0x80000, 0xa8000, 0x46000 },
+ .gpiomux = { 0x20000, 0, 0x80000, 0x80000 },
+ .gpiomute = 0xa8000,
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL_I,
@@ -1175,7 +1209,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 7,
.muxsel = { 2, 0, 1, 1 },
- .audiomux = { 0, 1, 2, 3, 4 },
+ .gpiomux = { 0, 1, 2, 3 },
+ .gpiomute = 4,
.pll = PLL_28,
.tuner_type = -1 /* TUNER_ALPS_TMDH2_NTSC */,
.tuner_addr = ADDR_UNSET,
@@ -1192,7 +1227,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 3,
.gpiomask = 0x03000F,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 1, 0xd0001, 0, 0, 10 },
+ .gpiomux = { 1, 0xd0001, 0, 0 },
+ .gpiomute = 10,
/* sound path (5 sources):
MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable)
0= ext. Audio IN
@@ -1218,7 +1254,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x1c,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 0, 0x10, 8, 4 },
+ .gpiomux = { 0, 0, 0x10, 8 },
+ .gpiomute = 4,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -1230,7 +1267,7 @@ struct tvcard bttv_tvcards[] = {
/* Tim Röstermundt <rosterm@uni-muenster.de>
in de.comp.os.unix.linux.hardware:
options bttv card=0 pll=1 radio=1 gpiomask=0x18e0
- audiomux=0x44c71f,0x44d71f,0,0x44d71f,0x44dfff
+ gpiomux =0x44c71f,0x44d71f,0,0x44d71f,0x44dfff
options tuner type=5 */
.name = "Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]",
.video_inputs = 4,
@@ -1239,7 +1276,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x18e0,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0x0000,0x0800,0x1000,0x1000,0x18e0 },
+ .gpiomux = { 0x0000,0x0800,0x1000,0x1000 },
+ .gpiomute = 0x18e0,
/* For cards with tda9820/tda9821:
0x0000: Tuner normal stereo
0x0080: Tuner A2 SAP (second audio program = Zweikanalton)
@@ -1259,7 +1297,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xF,
.muxsel = { 2, 3, 1, 0 },
- .audiomux = { 2, 0, 0, 0, 10 },
+ .gpiomux = { 2, 0, 0, 0 },
+ .gpiomute = 10,
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_PAL,
@@ -1277,7 +1316,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x1800,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
+ .gpiomux = { 0, 0x800, 0x1000, 0x1000 },
+ .gpiomute = 0x1800,
.pll = PLL_28,
.tuner_type = 5,
.tuner_addr = ADDR_UNSET,
@@ -1294,7 +1334,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 1,
.gpiomask = 0,
.muxsel = { 3, 1 },
- .audiomux = { 0 },
+ .gpiomux = { 0 },
.needs_tvaudio = 0,
.no_msp34xx = 1,
.pll = PLL_35,
@@ -1311,7 +1351,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xe00,
.muxsel = { 2, 3, 1, 1},
- .audiomux = { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 },
+ .gpiomux = { 0x400, 0x400, 0x400, 0x400 },
+ .gpiomute = 0x800,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_4036FY5_NTSC,
@@ -1327,7 +1368,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x03000F,
.muxsel = { 2, 3, 1, 0 },
- .audiomux = { 2, 0, 0, 0, 1 },
+ .gpiomux = { 2, 0, 0, 0 },
+ .gpiomute = 1,
.pll = PLL_28,
.tuner_type = 0,
.tuner_addr = ADDR_UNSET,
@@ -1344,7 +1386,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.gpiomask = 11,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 2, 0, 0, 1, 8 },
+ .gpiomux = { 2, 0, 0, 1 },
+ .gpiomute = 8,
.pll = PLL_35,
.tuner_type = TUNER_TEMIC_PAL,
.tuner_addr = ADDR_UNSET,
@@ -1359,7 +1402,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 1,
.gpiomask = 0xF,
.muxsel = { 2, 2 },
- .audiomux = { },
+ .gpiomux = { },
.no_msp34xx = 1,
.needs_tvaudio = 0,
.pll = PLL_28,
@@ -1378,7 +1421,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xFF,
.muxsel = { 2, 3, 1, 0 },
- .audiomux = { 1, 0, 4, 4, 9 },
+ .gpiomux = { 1, 0, 4, 4 },
+ .gpiomute = 9,
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -1394,7 +1438,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xf03f,
.muxsel = { 2, 3, 1, 0 },
- .audiomux = { 0xbffe, 0, 0xbfff, 0, 0xbffe },
+ .gpiomux = { 0xbffe, 0, 0xbfff, 0 },
+ .gpiomute = 0xbffe,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL,
.tuner_addr = ADDR_UNSET,
@@ -1411,7 +1456,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.gpiomask = 1,
.muxsel = { 2, 3, 0, 1 },
- .audiomux = { 0, 0, 1, 0, 0 },
+ .gpiomux = { 0, 0, 1, 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL,
@@ -1430,7 +1475,8 @@ struct tvcard bttv_tvcards[] = {
/* Radio changed from 1e80 to 0x800 to make
FlyVideo2000S in .hu happy (gm)*/
/* -dk-???: set mute=0x1800 for tda9874h daughterboard */
- .audiomux = { 0x0000,0x0800,0x1000,0x1000,0x1800, 0x1080 },
+ .gpiomux = { 0x0000,0x0800,0x1000,0x1000 },
+ .gpiomute = 0x1800,
.audio_hook = fv2000s_audio,
.no_msp34xx = 1,
.no_tda9875 = 1,
@@ -1448,7 +1494,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xffff00,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0x500, 0x500, 0x300, 0x900, 0x900 },
+ .gpiomux = { 0x500, 0x500, 0x300, 0x900 },
+ .gpiomute = 0x900,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -1465,7 +1512,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x010f00,
.muxsel = {2, 3, 0, 0 },
- .audiomux = {0x10000, 0, 0x10000, 0, 0, 0 },
+ .gpiomux = {0x10000, 0, 0x10000, 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_SHARP_2U5JF5540_NTSC,
@@ -1486,7 +1533,8 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 0x4f8a00,
/* 0x100000: 1=MSP enabled (0=disable again)
* 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */
- .audiomux = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff},
+ .gpiomux = {0x947fff, 0x987fff,0x947fff,0x947fff },
+ .gpiomute = 0x947fff,
/* tvtuner, radio, external,internal, mute, stereo
* tuner, Composit, SVid, Composit-on-Svid-adapter */
.muxsel = { 2, 3 ,0 ,1 },
@@ -1518,7 +1566,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 15,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 0, 11, 7, 13, 0 }, /* TV and Radio with same GPIO ! */
+ .gpiomux = { 0, 0, 11, 7 }, /* TV and Radio with same GPIO ! */
+ .gpiomute = 13,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = 25,
@@ -1557,7 +1606,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x3f,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0x01, 0x00, 0x03, 0x03, 0x09, 0x02 },
+ .gpiomux = { 0x01, 0x00, 0x03, 0x03 },
+ .gpiomute = 0x09,
.needs_tvaudio = 1,
.no_msp34xx = 1,
.no_tda9875 = 1,
@@ -1586,7 +1636,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 4,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 0, 0 },
- .audiomux = { 0 },
+ .gpiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -1618,7 +1668,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x1C800F, /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */
.muxsel = { 2, 1, 1, },
- .audiomux = { 0, 1, 2, 2, 4 },
+ .gpiomux = { 0, 1, 2, 2 },
+ .gpiomute = 4,
.needs_tvaudio = 0,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -1637,7 +1688,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x140007,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 1, 2, 3, 4, 0 },
+ .gpiomux = { 0, 1, 2, 3 },
+ .gpiomute = 4,
.tuner_type = TUNER_PHILIPS_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1651,7 +1703,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 0 },
- .audiomux = { 0 },
+ .gpiomux = { 0 },
.needs_tvaudio = 0,
.no_msp34xx = 1,
.pll = PLL_28,
@@ -1667,13 +1719,14 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 7,
.muxsel = { 2, 3, 1, 1 }, /* Tuner, SVid, SVHS, SVid to SVHS connector */
- .audiomux = { 0 ,0 ,4, 4,4,4},/* Yes, this tuner uses the same audio output for TV and FM radio!
+ .gpiomux = { 0, 0, 4, 4 },/* Yes, this tuner uses the same audio output for TV and FM radio!
* This card lacks external Audio In, so we mute it on Ext. & Int.
* The PCB can take a sbx1637/sbx1673, wiring unknown.
* This card lacks PCI subsystem ID, sigh.
- * audiomux=1: lower volume, 2+3: mute
+ * gpiomux =1: lower volume, 2+3: mute
* btwincap uses 0x80000/0x80003
*/
+ .gpiomute = 4,
.needs_tvaudio = 0,
.no_msp34xx = 1,
.pll = PLL_28,
@@ -1720,7 +1773,7 @@ struct tvcard bttv_tvcards[] = {
.radio_addr = ADDR_UNSET,
.gpiomask = 7,
- .audiomux = {7},
+ .gpiomux = {7},
},
[BTTV_BOARD_GVBCTV5PCI] = {
.name = "IODATA GV-BCTV5/PCI",
@@ -1730,7 +1783,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x0f0f80,
.muxsel = {2, 3, 1, 0 },
- .audiomux = {0x030000, 0x010000, 0, 0, 0x020000, 0},
+ .gpiomux = {0x030000, 0x010000, 0, 0 },
+ .gpiomute = 0x020000,
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_NTSC_M,
@@ -1960,7 +2014,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 2,
/* TV, Comp1, Composite over SVID con, SVID */
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 2, 2, 0, 0, 0 },
+ .gpiomux = { 2, 2, 0, 0 },
.pll = PLL_28,
.has_radio = 1,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -1984,7 +2038,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.gpiomask = 7,
.muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 1, 2, 3, 4},
+ .gpiomux = { 0, 1, 2, 3},
+ .gpiomute = 4,
.needs_tvaudio = 1,
.tuner_type = 5,
.tuner_addr = ADDR_UNSET,
@@ -2016,7 +2071,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.gpiomask = 0,
.muxsel = { 2, 3 },
- .audiomux = { 0 },
+ .gpiomux = { 0 },
.needs_tvaudio = 0,
.no_msp34xx = 1,
.pll = PLL_28,
@@ -2035,7 +2090,8 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 0x001e8007,
.muxsel = { 2, 3, 1, 0 },
/* Tuner, Radio, external, internal, off, on */
- .audiomux = { 0x08, 0x0f, 0x0a, 0x08, 0x0f, 0x08 },
+ .gpiomux = { 0x08, 0x0f, 0x0a, 0x08 },
+ .gpiomute = 0x0f,
.needs_tvaudio = 0,
.no_msp34xx = 1,
.pll = PLL_28,
@@ -2152,7 +2208,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.gpiomask = 0,
.muxsel = { 2, 3, 1, 0 },
- .audiomux = { 0 },
+ .gpiomux = { 0 },
.needs_tvaudio = 0,
.no_msp34xx = 1,
.pll = PLL_28,
@@ -2169,7 +2225,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 3,
.gpiomask = 0x00,
.muxsel = { 2, 3, 1, 0 },
- .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+ .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -2184,7 +2240,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 3,
.gpiomask = 0x00,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+ .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -2204,7 +2260,7 @@ struct tvcard bttv_tvcards[] = {
via the upper nibble of muxsel. here: used for
xternal video-mux */
.muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 },
- .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+ .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -2222,7 +2278,7 @@ struct tvcard bttv_tvcards[] = {
via the upper nibble of muxsel. here: used for
xternal video-mux */
.muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 },
- .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+ .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -2310,7 +2366,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 3,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 1, 1, 1, 1, 0 },
+ .gpiomux = { 1, 1, 1, 1 },
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -2341,7 +2397,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x008007,
.muxsel = { 2, 3, 0, 0 },
- .audiomux = { 0, 0, 0, 0, 0x000003, 0 },
+ .gpiomux = { 0, 0, 0, 0 },
+ .gpiomute = 0x000003,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -2377,7 +2434,7 @@ struct tvcard bttv_tvcards[] = {
.needs_tvaudio = 0,
.gpiomask = 0x68,
.muxsel = { 2, 3, 1 },
- .audiomux = { 0x68, 0x68, 0x61, 0x61, 0x00 },
+ .gpiomux = { 0x68, 0x68, 0x61, 0x61 },
.pll = PLL_28,
},
@@ -2392,7 +2449,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x008007,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 1, 2, 2, 3 },
+ .gpiomux = { 0, 1, 2, 2 },
+ .gpiomute = 3,
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -2417,7 +2475,7 @@ struct tvcard bttv_tvcards[] = {
.no_tda9875 = 1,
.no_tda7432 = 1,
.muxsel = {2,2,2,2},/*878A input is always MUX0, see above.*/
- .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+ .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */
.pll = PLL_28,
.needs_tvaudio = 0,
.muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/
@@ -2435,7 +2493,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x0000000f,
.muxsel = { 2, 1, 1 },
- .audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00 },
+ .gpiomux = { 0x02, 0x00, 0x00, 0x00 },
.tuner_type = TUNER_TEMIC_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2491,7 +2549,7 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3 },
.muxsel_hook = sigmaSQ_muxsel,
- .audiomux = { 0 },
+ .gpiomux = { 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -2508,7 +2566,7 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 0x0,
.muxsel = { 2, 2, 2, 2 },
.muxsel_hook = sigmaSLC_muxsel,
- .audiomux = { 0 },
+ .gpiomux = { 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -2526,7 +2584,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = -1,
.gpiomask = 0xFF,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 2, 0, 0, 0, 10 },
+ .gpiomux = { 2, 0, 0, 0 },
+ .gpiomute = 10,
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -2560,7 +2619,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x3f,
.muxsel = {2, 3, 1, 0 },
- .audiomux = {0x31, 0x31, 0x31, 0x31, 0x31, 0x31 },
+ .gpiomux = {0x31, 0x31, 0x31, 0x31 },
+ .gpiomute = 0x31,
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_NTSC_M,
@@ -2583,7 +2643,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.gpiomask = 0x008007,
- .audiomux = { 0, 0x000001,0,0, 0 },
+ .gpiomux = { 0, 0x000001,0,0 },
.needs_tvaudio = 1,
.has_radio = 1,
},
@@ -2693,7 +2753,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.muxsel = { 2, 3, 1 },
.gpiomask = 0x00e00007,
- .audiomux = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 },
+ .gpiomux = { 0x00400005, 0, 0x00000001, 0 },
+ .gpiomute = 0x00c00007,
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -2709,7 +2770,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x01fe00,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 },
+ .gpiomux = { 0x001e00, 0, 0x018000, 0x014000 },
+ .gpiomute = 0x002000,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_YMEC_TVF66T5_B_DFF,
@@ -2726,7 +2788,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x001c0007,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 1, 2, 2, 3 },
+ .gpiomux = { 0, 1, 2, 2 },
+ .gpiomute = 3,
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_TENA_9533_DI,
@@ -2745,7 +2808,8 @@ struct tvcard bttv_tvcards[] = {
.gpiomask = 0x01fe00,
.muxsel = { 2,3,1,1,-1 },
.digital_mode = DIGITAL_MODE_CAMERA,
- .audiomux = { 0x00400, 0x10400, 0x04400, 0x80000, 0x12400, 0x46000 },
+ .gpiomux = { 0x00400, 0x10400, 0x04400, 0x80000 },
+ .gpiomute = 0x12400,
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_LG_PAL_FM,
@@ -2763,7 +2827,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x3f,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 },
+ .gpiomux = { 0x21, 0x20, 0x24, 0x2c },
+ .gpiomute = 0x29,
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_YMEC_TVF_5533MF,
@@ -2797,7 +2862,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 15,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 2, 0, 0, 0, 1 },
+ .gpiomux = { 2, 0, 0, 0 },
+ .gpiomute = 1,
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = 2,
@@ -2813,7 +2879,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x108007,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 100000, 100002, 100002, 100000 },
+ .gpiomux = { 100000, 100002, 100002, 100000 },
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -2853,7 +2919,8 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 7,
.muxsel = { 2, 3, 1, 1 },
- .audiomux = { 0, 1, 2, 3, 4 },
+ .gpiomux = { 0, 1, 2, 3 },
+ .gpiomute = 4,
.tuner_type = TUNER_TEMIC_4009FR5_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2925,20 +2992,20 @@ void __devinit bttv_idcard(struct bttv *btv)
if (UNSET != audiomux[0]) {
gpiobits = 0;
for (i = 0; i < 5; i++) {
- bttv_tvcards[btv->c.type].audiomux[i] = audiomux[i];
+ bttv_tvcards[btv->c.type].gpiomux[i] = audiomux[i];
gpiobits |= audiomux[i];
}
} else {
gpiobits = audioall;
for (i = 0; i < 5; i++) {
- bttv_tvcards[btv->c.type].audiomux[i] = audioall;
+ bttv_tvcards[btv->c.type].gpiomux[i] = audioall;
}
}
bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits;
printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=",
btv->c.nr,bttv_tvcards[btv->c.type].gpiomask);
for (i = 0; i < 5; i++) {
- printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->c.type].audiomux[i]);
+ printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]);
}
printk("\n");
}
@@ -3046,7 +3113,7 @@ static void miro_pinnacle_gpio(struct bttv *btv)
gpio_inout(0xffffff, 0);
gpio = gpio_read();
id = ((gpio>>10) & 63) -1;
- msp = bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx");
+ msp = bttv_I2CRead(btv, I2C_ADDR_MSP3400, "MSP34xx");
if (id < 32) {
btv->tuner_type = miro_tunermap[id];
if (0 == (gpio & 0x20)) {
@@ -3442,8 +3509,8 @@ void __devinit bttv_init_card2(struct bttv *btv)
if (bttv_tvcards[btv->c.type].digital_mode == DIGITAL_MODE_CAMERA) {
/* detect Bt832 chip for quartzsight digital camera */
- if ((bttv_I2CRead(btv, I2C_BT832_ALT1, "Bt832") >=0) ||
- (bttv_I2CRead(btv, I2C_BT832_ALT2, "Bt832") >=0))
+ if ((bttv_I2CRead(btv, I2C_ADDR_BT832_ALT1, "Bt832") >=0) ||
+ (bttv_I2CRead(btv, I2C_ADDR_BT832_ALT2, "Bt832") >=0))
boot_bt832(btv);
}
@@ -3452,19 +3519,19 @@ void __devinit bttv_init_card2(struct bttv *btv)
/* try to detect audio/fader chips */
if (!bttv_tvcards[btv->c.type].no_msp34xx &&
- bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0)
+ bttv_I2CRead(btv, I2C_ADDR_MSP3400, "MSP34xx") >=0)
request_module("msp3400");
if (bttv_tvcards[btv->c.type].msp34xx_alt &&
- bttv_I2CRead(btv, I2C_MSP3400_ALT, "MSP34xx (alternate address)") >=0)
+ bttv_I2CRead(btv, I2C_ADDR_MSP3400_ALT, "MSP34xx (alternate address)") >=0)
request_module("msp3400");
if (!bttv_tvcards[btv->c.type].no_tda9875 &&
- bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0)
+ bttv_I2CRead(btv, I2C_ADDR_TDA9875, "TDA9875") >=0)
request_module("tda9875");
if (!bttv_tvcards[btv->c.type].no_tda7432 &&
- bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0)
+ bttv_I2CRead(btv, I2C_ADDR_TDA7432, "TDA7432") >=0)
request_module("tda7432");
if (bttv_tvcards[btv->c.type].needs_tvaudio)
@@ -3475,7 +3542,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
if (btv->tda9887_conf)
tda9887 = 1;
if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb &&
- bttv_I2CRead(btv, I2C_TDA9887, "TDA9887") >=0)
+ bttv_I2CRead(btv, I2C_ADDR_TDA9887, "TDA9887") >=0)
tda9887 = 1;
/* Hybrid DVB card, DOES have a tda9887 */
if (btv->c.type == BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE)
@@ -3796,18 +3863,18 @@ void bttv_tda9880_setnorm(struct bttv *btv, int norm)
{
/* fix up our card entry */
if(norm==VIDEO_MODE_NTSC) {
- bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x957fff;
- bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x957fff;
+ bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff;
+ bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x957fff;
dprintk("bttv_tda9880_setnorm to NTSC\n");
}
else {
- bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x947fff;
- bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x947fff;
+ bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x947fff;
+ bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x947fff;
dprintk("bttv_tda9880_setnorm to PAL\n");
}
/* set GPIO according */
gpio_bits(bttv_tvcards[btv->c.type].gpiomask,
- bttv_tvcards[btv->c.type].audiomux[btv->audio]);
+ bttv_tvcards[btv->c.type].gpiomux[btv->audio]);
}
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index c0415d6e7fe..74def9c2395 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -36,13 +36,15 @@
#include <linux/kdev_t.h>
#include "bttvp.h"
#include <media/v4l2-common.h>
+#include <media/tvaudio.h>
+#include <media/msp3400.h>
#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/byteorder.h>
-#include "rds.h"
+#include <media/rds.h>
unsigned int bttv_num; /* number of Bt848s in use */
@@ -926,45 +928,98 @@ video_mux(struct bttv *btv, unsigned int input)
static char *audio_modes[] = {
"audio: tuner", "audio: radio", "audio: extern",
- "audio: intern", "audio: off"
+ "audio: intern", "audio: mute"
};
static int
-audio_mux(struct bttv *btv, int mode)
+audio_mux(struct bttv *btv, int input, int mute)
{
- int val,mux,i2c_mux,signal;
+ int gpio_val, signal;
+ struct v4l2_control ctrl;
+ struct i2c_client *c;
gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
bttv_tvcards[btv->c.type].gpiomask);
signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
- switch (mode) {
- case AUDIO_MUTE:
- btv->audio |= AUDIO_MUTE;
- break;
- case AUDIO_UNMUTE:
- btv->audio &= ~AUDIO_MUTE;
- break;
- case AUDIO_TUNER:
- case AUDIO_RADIO:
- case AUDIO_EXTERN:
- case AUDIO_INTERN:
- btv->audio &= AUDIO_MUTE;
- btv->audio |= mode;
- }
- i2c_mux = mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio;
- if (btv->opt_automute && !signal && !btv->radio_user)
- mux = AUDIO_OFF;
-
- val = bttv_tvcards[btv->c.type].audiomux[mux];
- gpio_bits(bttv_tvcards[btv->c.type].gpiomask,val);
+ btv->mute = mute;
+ btv->audio = input;
+
+ /* automute */
+ mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
+
+ if (mute)
+ gpio_val = bttv_tvcards[btv->c.type].gpiomute;
+ else
+ gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
+
+ gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
if (bttv_gpio)
- bttv_gpio_tracking(btv,audio_modes[mux]);
- if (!in_interrupt())
- bttv_call_i2c_clients(btv,AUDC_SET_INPUT,&(i2c_mux));
+ bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
+ if (in_interrupt())
+ return 0;
+
+ ctrl.id = V4L2_CID_AUDIO_MUTE;
+ ctrl.value = btv->mute;
+ bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, &ctrl);
+ c = btv->i2c_msp34xx_client;
+ if (c) {
+ struct v4l2_routing route;
+
+ /* Note: the inputs tuner/radio/extern/intern are translated
+ to msp routings. This assumes common behavior for all msp3400
+ based TV cards. When this assumption fails, then the
+ specific MSP routing must be added to the card table.
+ For now this is sufficient. */
+ switch (input) {
+ case TVAUDIO_INPUT_RADIO:
+ route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
+ MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+ break;
+ case TVAUDIO_INPUT_EXTERN:
+ route.input = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
+ MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+ break;
+ case TVAUDIO_INPUT_INTERN:
+ /* Yes, this is the same input as for RADIO. I doubt
+ if this is ever used. The only board with an INTERN
+ input is the BTTV_BOARD_AVERMEDIA98. I wonder how
+ that was tested. My guess is that the whole INTERN
+ input does not work. */
+ route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
+ MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+ break;
+ case TVAUDIO_INPUT_TUNER:
+ default:
+ route.input = MSP_INPUT_DEFAULT;
+ break;
+ }
+ route.output = MSP_OUTPUT_DEFAULT;
+ c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+ }
+ c = btv->i2c_tvaudio_client;
+ if (c) {
+ struct v4l2_routing route;
+
+ route.input = input;
+ route.output = 0;
+ c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+ }
return 0;
}
+static inline int
+audio_mute(struct bttv *btv, int mute)
+{
+ return audio_mux(btv, btv->audio, mute);
+}
+
+static inline int
+audio_input(struct bttv *btv, int input)
+{
+ return audio_mux(btv, input, btv->mute);
+}
+
static void
i2c_vidiocschan(struct bttv *btv)
{
@@ -1023,8 +1078,8 @@ set_input(struct bttv *btv, unsigned int input)
} else {
video_mux(btv,input);
}
- audio_mux(btv,(input == bttv_tvcards[btv->c.type].tuner ?
- AUDIO_TUNER : AUDIO_EXTERN));
+ audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ?
+ TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN));
set_tvnorm(btv,btv->tvnorm);
i2c_vidiocschan(btv);
}
@@ -1236,10 +1291,10 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
case V4L2_CID_AUDIO_MUTE:
if (c->value) {
va.flags |= VIDEO_AUDIO_MUTE;
- audio_mux(btv, AUDIO_MUTE);
+ audio_mute(btv, 1);
} else {
va.flags &= ~VIDEO_AUDIO_MUTE;
- audio_mux(btv, AUDIO_UNMUTE);
+ audio_mute(btv, 0);
}
break;
@@ -1397,7 +1452,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
free_btres(btv,fh,RESOURCE_OVERLAY);
if (NULL != old) {
dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
- bttv_dma_free(btv, old);
+ bttv_dma_free(&fh->cap,btv, old);
kfree(old);
}
dprintk("switch_overlay: done\n");
@@ -1407,7 +1462,8 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
/* ----------------------------------------------------------------------- */
/* video4linux (1) interface */
-static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf,
+static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
+ struct bttv_buffer *buf,
const struct bttv_format *fmt,
unsigned int width, unsigned int height,
enum v4l2_field field)
@@ -1450,7 +1506,7 @@ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf,
/* alloc risc memory */
if (STATE_NEEDS_INIT == buf->vb.state) {
redo_dma_risc = 1;
- if (0 != (rc = videobuf_iolock(btv->c.pci,&buf->vb,&btv->fbuf)))
+ if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
goto fail;
}
@@ -1462,7 +1518,7 @@ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf,
return 0;
fail:
- bttv_dma_free(btv,buf);
+ bttv_dma_free(q,btv,buf);
return rc;
}
@@ -1486,7 +1542,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
struct bttv_fh *fh = q->priv_data;
- return bttv_prepare_buffer(fh->btv, buf, fh->fmt,
+ return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt,
fh->width, fh->height, field);
}
@@ -1510,7 +1566,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
struct bttv_fh *fh = q->priv_data;
- bttv_dma_free(fh->btv,buf);
+ bttv_dma_free(&fh->cap,fh->btv,buf);
}
static struct videobuf_queue_ops bttv_video_qops = {
@@ -1653,7 +1709,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
mutex_lock(&btv->lock);
- audio_mux(btv, (v->flags&VIDEO_AUDIO_MUTE) ? AUDIO_MUTE : AUDIO_UNMUTE);
+ audio_mute(btv, (v->flags&VIDEO_AUDIO_MUTE) ? 1 : 0);
bttv_call_i2c_clients(btv,cmd,v);
/* card specific hooks */
@@ -1822,7 +1878,8 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
if (t->audmode == V4L2_TUNER_MODE_MONO)
va.mode = VIDEO_SOUND_MONO;
- else if (t->audmode == V4L2_TUNER_MODE_STEREO)
+ else if (t->audmode == V4L2_TUNER_MODE_STEREO ||
+ t->audmode == V4L2_TUNER_MODE_LANG1_LANG2)
va.mode = VIDEO_SOUND_STEREO;
else if (t->audmode == V4L2_TUNER_MODE_LANG1)
va.mode = VIDEO_SOUND_LANG1;
@@ -2496,7 +2553,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2)
? V4L2_FIELD_INTERLACED
: V4L2_FIELD_BOTTOM;
- retval = bttv_prepare_buffer(btv,buf,
+ retval = bttv_prepare_buffer(&fh->cap,btv,buf,
format_by_palette(vm->format),
vm->width,vm->height,field);
if (0 != retval)
@@ -2528,8 +2585,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
retval = -EIO;
/* fall through */
case STATE_DONE:
- videobuf_dma_pci_sync(btv->c.pci,&buf->vb.dma);
- bttv_dma_free(btv,buf);
+ videobuf_dma_sync(&fh->cap,&buf->vb.dma);
+ bttv_dma_free(&fh->cap,btv,buf);
break;
default:
retval = -EINVAL;
@@ -3162,8 +3219,8 @@ static int radio_open(struct inode *inode, struct file *file)
file->private_data = btv;
- bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
- audio_mux(btv,AUDIO_RADIO);
+ bttv_call_i2c_clients(btv,AUDC_SET_RADIO,NULL);
+ audio_input(btv,TVAUDIO_INPUT_RADIO);
mutex_unlock(&btv->lock);
return 0;
@@ -3749,7 +3806,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
bttv_irq_switch_video(btv);
if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
- audio_mux(btv, -1);
+ audio_mute(btv, btv->mute); /* trigger automute */
if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr,
@@ -4050,7 +4107,7 @@ static int __devinit bttv_probe(struct pci_dev *dev,
bt848_contrast(btv,32768);
bt848_hue(btv,32768);
bt848_sat(btv,32768);
- audio_mux(btv,AUDIO_MUTE);
+ audio_mute(btv, 1);
set_input(btv,0);
}
diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bt8xx/bttv-gpio.c
index c4d5e2b70c2..c4d5e2b70c2 100644
--- a/drivers/media/video/bttv-gpio.c
+++ b/drivers/media/video/bt8xx/bttv-gpio.c
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c
index 614c1201855..4b562b386fc 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bt8xx/bttv-i2c.c
@@ -302,6 +302,10 @@ static int attach_inform(struct i2c_client *client)
if (!client->driver->command)
return 0;
+ if (client->driver->id == I2C_DRIVERID_MSP3400)
+ btv->i2c_msp34xx_client = client;
+ if (client->driver->id == I2C_DRIVERID_TVAUDIO)
+ btv->i2c_tvaudio_client = client;
if (btv->tuner_type != UNSET) {
struct tuner_setup tun_setup;
diff --git a/drivers/media/video/bttv-if.c b/drivers/media/video/bt8xx/bttv-if.c
index 19b564ab0e9..19b564ab0e9 100644
--- a/drivers/media/video/bttv-if.c
+++ b/drivers/media/video/bt8xx/bttv-if.c
diff --git a/drivers/media/video/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
index 69efa0e5174..69efa0e5174 100644
--- a/drivers/media/video/bttv-input.c
+++ b/drivers/media/video/bt8xx/bttv-input.c
diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c
index 344f84e9af0..16323a5d68a 100644
--- a/drivers/media/video/bttv-risc.c
+++ b/drivers/media/video/bt8xx/bttv-risc.c
@@ -509,11 +509,11 @@ bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
}
void
-bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf)
+bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
{
BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb,0,0);
- videobuf_dma_pci_unmap(btv->c.pci, &buf->vb.dma);
+ videobuf_dma_unmap(q, &buf->vb.dma);
videobuf_dma_free(&buf->vb.dma);
btcx_riscmem_free(btv->c.pci,&buf->bottom);
btcx_riscmem_free(btv->c.pci,&buf->top);
diff --git a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index 72afdd64b88..e20ff238e40 100644
--- a/drivers/media/video/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -96,7 +96,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q,
return -EINVAL;
if (STATE_NEEDS_INIT == buf->vb.state) {
- if (0 != (rc = videobuf_iolock(btv->c.pci, &buf->vb, NULL)))
+ if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
goto fail;
if (0 != (rc = vbi_buffer_risc(btv,buf,fh->lines)))
goto fail;
@@ -109,7 +109,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q,
return 0;
fail:
- bttv_dma_free(btv,buf);
+ bttv_dma_free(q,btv,buf);
return rc;
}
@@ -136,7 +136,7 @@ static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
dprintk("free %p\n",vb);
- bttv_dma_free(fh->btv,buf);
+ bttv_dma_free(&fh->cap,fh->btv,buf);
}
struct videobuf_queue_ops bttv_vbi_qops = {
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bt8xx/bttv.h
index 9908c8e0c95..3a23265c153 100644
--- a/drivers/media/video/bttv.h
+++ b/drivers/media/video/bt8xx/bttv.h
@@ -18,6 +18,7 @@
#include <linux/i2c.h>
#include <media/ir-common.h>
#include <media/ir-kbd-i2c.h>
+#include <media/i2c-addr.h>
/* ---------------------------------------------------------- */
/* exported by bttv-cards.c */
@@ -168,25 +169,6 @@
#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f
#define BTTV_BOARD_MACHTV_MAGICTV 0x90
-/* i2c address list */
-#define I2C_TSA5522 0xc2
-#define I2C_TDA7432 0x8a
-#define I2C_BT832_ALT1 0x88
-#define I2C_BT832_ALT2 0x8a // alternate setting
-#define I2C_TDA8425 0x82
-#define I2C_TDA9840 0x84
-#define I2C_TDA9850 0xb6 /* also used by 9855,9873 */
-#define I2C_TDA9874 0xb0 /* also used by 9875 */
-#define I2C_TDA9875 0xb0
-#define I2C_HAUPEE 0xa0
-#define I2C_STBEE 0xae
-#define I2C_VHX 0xc0
-#define I2C_MSP3400 0x80
-#define I2C_MSP3400_ALT 0x88
-#define I2C_TEA6300 0x80 /* also used by 6320 */
-#define I2C_DPL3518 0x84
-#define I2C_TDA9887 0x86
-
/* more card-specific defines */
#define PT2254_L_CHANNEL 0x10
#define PT2254_R_CHANNEL 0x08
@@ -252,7 +234,8 @@ struct tvcard
unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO
u32 gpiomask;
u32 muxsel[16];
- u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */
+ u32 gpiomux[4]; /* Tuner, Radio, external, internal */
+ u32 gpiomute; /* GPIO mute setting */
u32 gpiomask2; /* GPIO MUX mask */
/* i2c audio flags */
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
index 9cb72f176f7..ee989d2e15d 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bt8xx/bttvp.h
@@ -41,7 +41,6 @@
#include <linux/device.h>
#include <media/video-buf.h>
-#include <media/audiochip.h>
#include <media/tuner.h>
#include <media/tveeprom.h>
#include <media/ir-common.h>
@@ -190,7 +189,8 @@ int bttv_buffer_activate_video(struct bttv *btv,
struct bttv_buffer_set *set);
int bttv_buffer_activate_vbi(struct bttv *btv,
struct bttv_buffer *vbi);
-void bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf);
+void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv,
+ struct bttv_buffer *buf);
/* overlay handling */
int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov,
@@ -298,6 +298,8 @@ struct bttv {
int i2c_state, i2c_rc;
int i2c_done;
wait_queue_head_t i2c_queue;
+ struct i2c_client *i2c_msp34xx_client;
+ struct i2c_client *i2c_tvaudio_client;
/* video4linux (1) */
struct video_device *video_dev;
@@ -320,6 +322,7 @@ struct bttv {
/* video state */
unsigned int input;
unsigned int audio;
+ unsigned int mute;
unsigned long freq;
int tvnorm,hue,contrast,bright,saturation;
struct v4l2_framebuffer fbuf;
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index d97b7d8ac33..cf61c590f4a 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -150,7 +150,7 @@ static int qc_calibrate(struct qcam_device *q)
static struct qcam_device *qcam_init(struct parport *port)
{
struct qcam_device *q;
-
+
q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
if(q==NULL)
return NULL;
@@ -158,16 +158,16 @@ static struct qcam_device *qcam_init(struct parport *port)
q->pport = port;
q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
NULL, 0, NULL);
- if (q->pdev == NULL)
+ if (q->pdev == NULL)
{
printk(KERN_ERR "bw-qcam: couldn't register for %s.\n",
port->name);
kfree(q);
return NULL;
}
-
+
memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
-
+
mutex_init(&q->lock);
q->port_mode = (QC_ANY | QC_NOTSET);
@@ -236,12 +236,12 @@ static int qc_waithand(struct qcam_device *q, int val)
while (!((status = read_lpstatus(q)) & 8))
{
/* 1000 is enough spins on the I/O for all normal
- cases, at that point we start to poll slowly
+ cases, at that point we start to poll slowly
until the camera wakes up. However, we are
busy blocked until the camera responds, so
setting it lower is much better for interactive
response. */
-
+
if(runs++>maxpoll)
{
msleep_interruptible(5);
@@ -255,12 +255,12 @@ static int qc_waithand(struct qcam_device *q, int val)
while (((status = read_lpstatus(q)) & 8))
{
/* 1000 is enough spins on the I/O for all normal
- cases, at that point we start to poll slowly
+ cases, at that point we start to poll slowly
until the camera wakes up. However, we are
busy blocked until the camera responds, so
setting it lower is much better for interactive
response. */
-
+
if(runs++>maxpoll)
{
msleep_interruptible(5);
@@ -282,17 +282,17 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val)
{
unsigned int status;
int runs=0;
-
- do
+
+ do
{
status = read_lpdata(q);
/* 1000 is enough spins on the I/O for all normal
- cases, at that point we start to poll slowly
+ cases, at that point we start to poll slowly
until the camera wakes up. However, we are
busy blocked until the camera responds, so
setting it lower is much better for interactive
response. */
-
+
if(runs++>maxpoll)
{
msleep_interruptible(5);
@@ -321,7 +321,7 @@ static int qc_detect(struct qcam_device *q)
lastreg = reg = read_lpstatus(q) & 0xf0;
- for (i = 0; i < 500; i++)
+ for (i = 0; i < 500; i++)
{
reg = read_lpstatus(q) & 0xf0;
if (reg != lastreg)
@@ -357,7 +357,7 @@ static int qc_detect(struct qcam_device *q)
static void qc_reset(struct qcam_device *q)
{
- switch (q->port_mode & QC_FORCE_MASK)
+ switch (q->port_mode & QC_FORCE_MASK)
{
case QC_FORCE_UNIDIR:
q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
@@ -370,7 +370,7 @@ static void qc_reset(struct qcam_device *q)
case QC_ANY:
write_lpcontrol(q, 0x20);
write_lpdata(q, 0x75);
-
+
if (read_lpdata(q) != 0x75) {
q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
} else {
@@ -398,8 +398,8 @@ static void qc_reset(struct qcam_device *q)
static int qc_setscanmode(struct qcam_device *q)
{
int old_mode = q->mode;
-
- switch (q->transfer_scale)
+
+ switch (q->transfer_scale)
{
case 1:
q->mode = 0;
@@ -412,7 +412,7 @@ static int qc_setscanmode(struct qcam_device *q)
break;
}
- switch (q->bpp)
+ switch (q->bpp)
{
case 4:
break;
@@ -421,7 +421,7 @@ static int qc_setscanmode(struct qcam_device *q)
break;
}
- switch (q->port_mode & QC_MODE_MASK)
+ switch (q->port_mode & QC_MODE_MASK)
{
case QC_BIDIR:
q->mode += 1;
@@ -430,10 +430,10 @@ static int qc_setscanmode(struct qcam_device *q)
case QC_UNIDIR:
break;
}
-
+
if (q->mode != old_mode)
q->status |= QC_PARAM_CHANGE;
-
+
return 0;
}
@@ -451,7 +451,7 @@ static void qc_set(struct qcam_device *q)
/* Set the brightness. Yes, this is repetitive, but it works.
* Shorter versions seem to fail subtly. Feel free to try :-). */
/* I think the problem was in qc_command, not here -- bls */
-
+
qc_command(q, 0xb);
qc_command(q, q->brightness);
@@ -502,13 +502,13 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
unsigned int hi2, lo2;
static int state = 0;
- if (buffer == NULL)
+ if (buffer == NULL)
{
state = 0;
return 0;
}
-
- switch (q->port_mode & QC_MODE_MASK)
+
+ switch (q->port_mode & QC_MODE_MASK)
{
case QC_BIDIR: /* Bi-directional Port */
write_lpcontrol(q, 0x26);
@@ -517,7 +517,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
write_lpcontrol(q, 0x2e);
lo2 = (qc_waithand2(q, 0) >> 1);
hi2 = (read_lpstatus(q) >> 3) & 0x1f;
- switch (q->bpp)
+ switch (q->bpp)
{
case 4:
buffer[0] = lo & 0xf;
@@ -544,7 +544,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
write_lpcontrol(q, 0xe);
hi = (qc_waithand(q, 0) & 0xf0) >> 4;
- switch (q->bpp)
+ switch (q->bpp)
{
case 4:
buffer[0] = lo;
@@ -552,7 +552,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
ret = 2;
break;
case 6:
- switch (state)
+ switch (state)
{
case 0:
buffer[0] = (lo << 2) | ((hi & 0xc) >> 2);
@@ -604,13 +604,13 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
int shift=8-q->bpp;
char invert;
- if (q->mode == -1)
+ if (q->mode == -1)
return -ENXIO;
qc_command(q, 0x7);
qc_command(q, q->mode);
- if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR)
+ if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR)
{
write_lpcontrol(q, 0x2e); /* turn port around */
write_lpcontrol(q, 0x26);
@@ -618,7 +618,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
write_lpcontrol(q, 0x2e);
(void) qc_waithand(q, 0);
}
-
+
/* strange -- should be 15:63 below, but 4bpp is odd */
invert = (q->bpp == 4) ? 16 : 63;
@@ -629,15 +629,15 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
q->transfer_scale;
transperline = (transperline + divisor - 1) / divisor;
- for (i = 0, yield = yieldlines; i < linestotrans; i++)
+ for (i = 0, yield = yieldlines; i < linestotrans; i++)
{
- for (pixels_read = j = 0; j < transperline; j++)
+ for (pixels_read = j = 0; j < transperline; j++)
{
bytes = qc_readbytes(q, buffer);
- for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++)
+ for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++)
{
int o;
- if (buffer[k] == 0 && invert == 16)
+ if (buffer[k] == 0 && invert == 16)
{
/* 4bpp is odd (again) -- inverter is 16, not 15, but output
must be 0-15 -- bls */
@@ -653,7 +653,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
pixels_read += bytes;
}
(void) qc_readbytes(q, NULL); /* reset state machine */
-
+
/* Grabbing an entire frame from the quickcam is a lengthy
process. We don't (usually) want to busy-block the
processor for the entire frame. yieldlines is a module
@@ -666,7 +666,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
}
}
- if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR)
+ if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR)
{
write_lpcontrol(q, 2);
write_lpcontrol(q, 6);
@@ -687,7 +687,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam=(struct qcam_device *)dev;
-
+
switch(cmd)
{
case VIDIOCGCAP:
@@ -762,7 +762,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
if(p->depth!=4 && p->depth!=6)
return -EINVAL;
-
+
/*
* Now load the camera.
*/
@@ -790,11 +790,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
if(vw->width<80||vw->width>320)
return -EINVAL;
-
+
qcam->width = 320;
qcam->height = 240;
qcam->transfer_scale = 4;
-
+
if(vw->width>=160 && vw->height>=120)
{
qcam->transfer_scale = 2;
@@ -808,11 +808,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
mutex_lock(&qcam->lock);
qc_setscanmode(qcam);
mutex_unlock(&qcam->lock);
-
+
/* We must update the camera before we grab. We could
just have changed the grab size */
qcam->status |= QC_PARAM_CHANGE;
-
+
/* Ok we figured out what to use from our wide choice */
return 0;
}
@@ -853,9 +853,9 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
struct qcam_device *qcam=(struct qcam_device *)v;
int len;
parport_claim_or_block(qcam->pdev);
-
+
mutex_lock(&qcam->lock);
-
+
qc_reset(qcam);
/* Update the camera parameters if we need to */
@@ -863,13 +863,13 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
qc_set(qcam);
len=qc_capture(qcam, buf,count);
-
+
mutex_unlock(&qcam->lock);
-
+
parport_release(qcam->pdev);
return len;
}
-
+
static struct file_operations qcam_fops = {
.owner = THIS_MODULE,
.open = video_exclusive_open,
@@ -905,11 +905,11 @@ static int init_bwqcam(struct parport *port)
qcam=qcam_init(port);
if(qcam==NULL)
return -ENODEV;
-
+
parport_claim_or_block(qcam->pdev);
qc_reset(qcam);
-
+
if(qc_detect(qcam)==0)
{
parport_release(qcam->pdev);
@@ -920,9 +920,9 @@ static int init_bwqcam(struct parport *port)
qc_calibrate(qcam);
parport_release(qcam->pdev);
-
+
printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name);
-
+
if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
{
parport_unregister_device(qcam->pdev);
@@ -1013,7 +1013,7 @@ static int __init init_bw_qcams(void)
printk("Connectix Quickcam max-poll was above 5000. Using 5000.\n");
maxpoll = 5000;
}
-
+
if (yieldlines < 1) {
printk("Connectix Quickcam yieldlines was less than 1. Using 1.\n");
yieldlines = 1;
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index 8211fd8d7cb..22a7386bbea 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -16,7 +16,7 @@
*
* The parport parameter controls which parports will be scanned.
* Scanning all parports causes some printers to print a garbage page.
- * -- March 14, 1999 Billy Donahue <billy@escape.com>
+ * -- March 14, 1999 Billy Donahue <billy@escape.com>
*
* Fixed data format to BGR, added force_rgb parameter. Added missing
* parport_unregister_driver() on module removal.
@@ -88,7 +88,7 @@ static inline unsigned int qcam_ready2(struct qcam_device *qcam)
return (parport_read_data(qcam->pport) & 0x1)?1:0;
}
-static unsigned int qcam_await_ready1(struct qcam_device *qcam,
+static unsigned int qcam_await_ready1(struct qcam_device *qcam,
int value)
{
unsigned long oldjiffies = jiffies;
@@ -98,7 +98,7 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam,
if (qcam_ready1(qcam) == value)
return 0;
- /* If the camera didn't respond within 1/25 second, poll slowly
+ /* If the camera didn't respond within 1/25 second, poll slowly
for a while. */
for (i = 0; i < 50; i++)
{
@@ -123,7 +123,7 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
if (qcam_ready2(qcam) == value)
return 0;
- /* If the camera didn't respond within 1/25 second, poll slowly
+ /* If the camera didn't respond within 1/25 second, poll slowly
for a while. */
for (i = 0; i < 50; i++)
{
@@ -157,12 +157,12 @@ static int qcam_write_data(struct qcam_device *qcam, unsigned int data)
unsigned int idata;
parport_write_data(qcam->pport, data);
idata = qcam_read_data(qcam);
- if (data != idata)
+ if (data != idata)
{
- printk(KERN_WARNING "cqcam: sent %x but received %x\n", data,
+ printk(KERN_WARNING "cqcam: sent %x but received %x\n", data,
idata);
return 1;
- }
+ }
return 0;
}
@@ -193,12 +193,12 @@ static int qc_detect(struct qcam_device *qcam)
no device was found". Fix this one day. */
if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA
&& qcam->pport->probe_info[0].model
- && !strcmp(qcam->pdev->port->probe_info[0].model,
+ && !strcmp(qcam->pdev->port->probe_info[0].model,
"Color QuickCam 2.0")) {
printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n");
return 1;
}
-
+
if (probe < 2)
return 0;
@@ -206,11 +206,11 @@ static int qc_detect(struct qcam_device *qcam)
/* look for a heartbeat */
ostat = stat = parport_read_status(qcam->pport);
- for (i=0; i<250; i++)
+ for (i=0; i<250; i++)
{
mdelay(1);
stat = parport_read_status(qcam->pport);
- if (ostat != stat)
+ if (ostat != stat)
{
if (++count >= 3) return 1;
ostat = stat;
@@ -226,11 +226,11 @@ static int qc_detect(struct qcam_device *qcam)
count = 0;
ostat = stat = parport_read_status(qcam->pport);
- for (i=0; i<250; i++)
+ for (i=0; i<250; i++)
{
mdelay(1);
stat = parport_read_status(qcam->pport);
- if (ostat != stat)
+ if (ostat != stat)
{
if (++count >= 3) return 1;
ostat = stat;
@@ -247,7 +247,7 @@ static void qc_reset(struct qcam_device *qcam)
parport_write_control(qcam->pport, 0x8);
mdelay(1);
parport_write_control(qcam->pport, 0xc);
- mdelay(1);
+ mdelay(1);
}
/* Reset the QuickCam and program for brightness, contrast,
@@ -258,7 +258,7 @@ static void qc_setup(struct qcam_device *q)
qc_reset(q);
/* Set the brightness. */
- qcam_set(q, 11, q->brightness);
+ qcam_set(q, 11, q->brightness);
/* Set the height and width. These refer to the actual
CCD area *before* applying the selected decimation. */
@@ -272,12 +272,12 @@ static void qc_setup(struct qcam_device *q)
/* Set contrast and white balance. */
qcam_set(q, 0x19, q->contrast);
qcam_set(q, 0x1f, q->whitebal);
-
+
/* Set the speed. */
qcam_set(q, 45, 2);
}
-/* Read some bytes from the camera and put them in the buffer.
+/* Read some bytes from the camera and put them in the buffer.
nbytes should be a multiple of 3, because bidirectional mode gives
us three bytes at a time. */
@@ -383,7 +383,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
if (qcam_set(q, 7, (q->mode | (is_bi_dir?1:0)) + 1))
return -EIO;
-
+
lines = q->height;
pixelsperline = q->width;
bitsperxfer = (is_bi_dir) ? 24 : 8;
@@ -499,7 +499,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam=(struct qcam_device *)dev;
-
+
switch(cmd)
{
case VIDIOCGCAP:
@@ -574,7 +574,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
*/
if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24)
return -EINVAL;
-
+
/*
* Now load the camera.
*/
@@ -584,7 +584,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
mutex_lock(&qcam->lock);
parport_claim_or_block(qcam->pdev);
- qc_setup(qcam);
+ qc_setup(qcam);
parport_release(qcam->pdev);
mutex_unlock(&qcam->lock);
return 0;
@@ -601,11 +601,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
if(vw->width<80||vw->width>320)
return -EINVAL;
-
+
qcam->width = 80;
qcam->height = 60;
qcam->mode = QC_DECIMATION_4;
-
+
if(vw->width>=160 && vw->height>=120)
{
qcam->width = 160;
@@ -627,7 +627,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
qcam->mode = QC_BILLIONS | QC_DECIMATION_1;
}
#endif
- /* Ok we figured out what to use from our
+ /* Ok we figured out what to use from our
wide choice */
mutex_lock(&qcam->lock);
parport_claim_or_block(qcam->pdev);
@@ -676,7 +676,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
mutex_lock(&qcam->lock);
parport_claim_or_block(qcam->pdev);
/* Probably should have a semaphore against multiple users */
- len = qc_capture(qcam, buf,count);
+ len = qc_capture(qcam, buf,count);
parport_release(qcam->pdev);
mutex_unlock(&qcam->lock);
return len;
@@ -707,7 +707,7 @@ static struct video_device qcam_template=
static struct qcam_device *qcam_init(struct parport *port)
{
struct qcam_device *q;
-
+
q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
if(q==NULL)
return NULL;
@@ -718,14 +718,14 @@ static struct qcam_device *qcam_init(struct parport *port)
q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE)?1:0;
- if (q->pdev == NULL)
+ if (q->pdev == NULL)
{
printk(KERN_ERR "c-qcam: couldn't register for %s.\n",
port->name);
kfree(q);
return NULL;
}
-
+
memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
mutex_init(&q->lock);
@@ -766,11 +766,11 @@ static int init_cqcam(struct parport *port)
qcam = qcam_init(port);
if (qcam==NULL)
return -ENODEV;
-
+
parport_claim_or_block(qcam->pdev);
qc_reset(qcam);
-
+
if (probe && qc_detect(qcam)==0)
{
parport_release(qcam->pdev);
@@ -782,7 +782,7 @@ static int init_cqcam(struct parport *port)
qc_setup(qcam);
parport_release(qcam->pdev);
-
+
if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
{
printk(KERN_ERR "Unable to register Colour QuickCam on %s\n",
@@ -792,9 +792,9 @@ static int init_cqcam(struct parport *port)
return -ENODEV;
}
- printk(KERN_INFO "video%d: Colour QuickCam found on %s\n",
+ printk(KERN_INFO "video%d: Colour QuickCam found on %s\n",
qcam->vdev.minor, qcam->pport->name);
-
+
qcams[num_cams++] = qcam;
return 0;
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 3cebfa91ca1..2227c5640c1 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -24,7 +24,7 @@
*/
/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
-/* #define _CPIA_DEBUG_ 1 */
+/* #define _CPIA_DEBUG_ 1 */
#include <linux/config.h>
@@ -67,11 +67,11 @@ MODULE_SUPPORTED_DEVICE("video");
static unsigned short colorspace_conv = 0;
module_param(colorspace_conv, ushort, 0444);
MODULE_PARM_DESC(colorspace_conv,
- "\n<n> Colorspace conversion:"
- "\n0 = disable"
- "\n1 = enable"
- "\nDefault value is 0"
- "\n");
+ "\n<n> Colorspace conversion:"
+ "\n0 = disable"
+ "\n1 = enable"
+ "\nDefault value is 0"
+ "\n");
#define ABOUT "V4L-Driver for Vision CPiA based cameras"
@@ -189,8 +189,8 @@ enum {
#define TC 94
#define EXP_ACC_DARK 50
#define EXP_ACC_LIGHT 90
-#define HIGH_COMP_102 160
-#define MAX_COMP 239
+#define HIGH_COMP_102 160
+#define MAX_COMP 239
#define DARK_TIME 3
#define LIGHT_TIME 3
@@ -208,7 +208,7 @@ static u8 flicker_jumps[2][2][4] =
static void reset_camera_struct(struct cam_data *cam);
static int find_over_exposure(int brightness);
static void set_flicker(struct cam_params *params, volatile u32 *command_flags,
- int on);
+ int on);
/**********************************************************************
@@ -262,7 +262,7 @@ static void rvfree(void *mem, unsigned long size)
static struct proc_dir_entry *cpia_proc_root=NULL;
static int cpia_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+ int count, int *eof, void *data)
{
char *out = page;
int len, tmp;
@@ -276,58 +276,58 @@ static int cpia_read_proc(char *page, char **start, off_t off,
out += sprintf(out, "V4L Driver version: %d.%d.%d\n",
CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
out += sprintf(out, "CPIA Version: %d.%02d (%d.%d)\n",
- cam->params.version.firmwareVersion,
- cam->params.version.firmwareRevision,
- cam->params.version.vcVersion,
- cam->params.version.vcRevision);
+ cam->params.version.firmwareVersion,
+ cam->params.version.firmwareRevision,
+ cam->params.version.vcVersion,
+ cam->params.version.vcRevision);
out += sprintf(out, "CPIA PnP-ID: %04x:%04x:%04x\n",
- cam->params.pnpID.vendor, cam->params.pnpID.product,
- cam->params.pnpID.deviceRevision);
+ cam->params.pnpID.vendor, cam->params.pnpID.product,
+ cam->params.pnpID.deviceRevision);
out += sprintf(out, "VP-Version: %d.%d %04x\n",
- cam->params.vpVersion.vpVersion,
- cam->params.vpVersion.vpRevision,
- cam->params.vpVersion.cameraHeadID);
-
+ cam->params.vpVersion.vpVersion,
+ cam->params.vpVersion.vpRevision,
+ cam->params.vpVersion.cameraHeadID);
+
out += sprintf(out, "system_state: %#04x\n",
- cam->params.status.systemState);
+ cam->params.status.systemState);
out += sprintf(out, "grab_state: %#04x\n",
- cam->params.status.grabState);
+ cam->params.status.grabState);
out += sprintf(out, "stream_state: %#04x\n",
- cam->params.status.streamState);
+ cam->params.status.streamState);
out += sprintf(out, "fatal_error: %#04x\n",
- cam->params.status.fatalError);
+ cam->params.status.fatalError);
out += sprintf(out, "cmd_error: %#04x\n",
- cam->params.status.cmdError);
+ cam->params.status.cmdError);
out += sprintf(out, "debug_flags: %#04x\n",
- cam->params.status.debugFlags);
+ cam->params.status.debugFlags);
out += sprintf(out, "vp_status: %#04x\n",
- cam->params.status.vpStatus);
+ cam->params.status.vpStatus);
out += sprintf(out, "error_code: %#04x\n",
- cam->params.status.errorCode);
+ cam->params.status.errorCode);
/* QX3 specific entries */
if (cam->params.qx3.qx3_detected) {
out += sprintf(out, "button: %4d\n",
- cam->params.qx3.button);
+ cam->params.qx3.button);
out += sprintf(out, "cradled: %4d\n",
- cam->params.qx3.cradled);
+ cam->params.qx3.cradled);
}
out += sprintf(out, "video_size: %s\n",
- cam->params.format.videoSize == VIDEOSIZE_CIF ?
+ cam->params.format.videoSize == VIDEOSIZE_CIF ?
"CIF " : "QCIF");
out += sprintf(out, "roi: (%3d, %3d) to (%3d, %3d)\n",
- cam->params.roi.colStart*8,
- cam->params.roi.rowStart*4,
- cam->params.roi.colEnd*8,
- cam->params.roi.rowEnd*4);
+ cam->params.roi.colStart*8,
+ cam->params.roi.rowStart*4,
+ cam->params.roi.colEnd*8,
+ cam->params.roi.rowEnd*4);
out += sprintf(out, "actual_fps: %3d\n", cam->fps);
out += sprintf(out, "transfer_rate: %4dkB/s\n",
- cam->transfer_rate);
-
+ cam->transfer_rate);
+
out += sprintf(out, "\nread-write\n");
out += sprintf(out, "----------------------- current min"
- " max default comment\n");
+ " max default comment\n");
out += sprintf(out, "brightness: %8d %8d %8d %8d\n",
- cam->params.colourParams.brightness, 0, 100, 50);
+ cam->params.colourParams.brightness, 0, 100, 50);
if (cam->params.version.firmwareVersion == 1 &&
cam->params.version.firmwareRevision == 2)
/* 1-02 firmware limits contrast to 80 */
@@ -336,26 +336,26 @@ static int cpia_read_proc(char *page, char **start, off_t off,
tmp = 96;
out += sprintf(out, "contrast: %8d %8d %8d %8d"
- " steps of 8\n",
- cam->params.colourParams.contrast, 0, tmp, 48);
+ " steps of 8\n",
+ cam->params.colourParams.contrast, 0, tmp, 48);
out += sprintf(out, "saturation: %8d %8d %8d %8d\n",
- cam->params.colourParams.saturation, 0, 100, 50);
+ cam->params.colourParams.saturation, 0, 100, 50);
tmp = (25000+5000*cam->params.sensorFps.baserate)/
(1<<cam->params.sensorFps.divisor);
out += sprintf(out, "sensor_fps: %4d.%03d %8d %8d %8d\n",
- tmp/1000, tmp%1000, 3, 30, 15);
+ tmp/1000, tmp%1000, 3, 30, 15);
out += sprintf(out, "stream_start_line: %8d %8d %8d %8d\n",
- 2*cam->params.streamStartLine, 0,
+ 2*cam->params.streamStartLine, 0,
cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144,
cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120);
out += sprintf(out, "sub_sample: %8s %8s %8s %8s\n",
- cam->params.format.subSample == SUBSAMPLE_420 ?
+ cam->params.format.subSample == SUBSAMPLE_420 ?
"420" : "422", "420", "422", "422");
out += sprintf(out, "yuv_order: %8s %8s %8s %8s\n",
- cam->params.format.yuvOrder == YUVORDER_YUYV ?
+ cam->params.format.yuvOrder == YUVORDER_YUYV ?
"YUYV" : "UYVY", "YUYV" , "UYVY", "YUYV");
out += sprintf(out, "ecp_timing: %8s %8s %8s %8s\n",
- cam->params.ecpTiming ? "slow" : "normal", "slow",
+ cam->params.ecpTiming ? "slow" : "normal", "slow",
"normal", "normal");
if (cam->params.colourBalance.balanceMode == 2) {
@@ -366,11 +366,11 @@ static int cpia_read_proc(char *page, char **start, off_t off,
out += sprintf(out, "color_balance_mode: %8s %8s %8s"
" %8s\n", tmpstr, "manual", "auto", "auto");
out += sprintf(out, "red_gain: %8d %8d %8d %8d\n",
- cam->params.colourBalance.redGain, 0, 212, 32);
+ cam->params.colourBalance.redGain, 0, 212, 32);
out += sprintf(out, "green_gain: %8d %8d %8d %8d\n",
- cam->params.colourBalance.greenGain, 0, 212, 6);
+ cam->params.colourBalance.greenGain, 0, 212, 6);
out += sprintf(out, "blue_gain: %8d %8d %8d %8d\n",
- cam->params.colourBalance.blueGain, 0, 212, 92);
+ cam->params.colourBalance.blueGain, 0, 212, 92);
if (cam->params.version.firmwareVersion == 1 &&
cam->params.version.firmwareRevision == 2)
@@ -381,11 +381,11 @@ static int cpia_read_proc(char *page, char **start, off_t off,
if (cam->params.exposure.gainMode == 0)
out += sprintf(out, "max_gain: unknown %28s"
- " powers of 2\n", tmpstr);
+ " powers of 2\n", tmpstr);
else
out += sprintf(out, "max_gain: %8d %28s"
" 1,2,4 or 8 \n",
- 1<<(cam->params.exposure.gainMode-1), tmpstr);
+ 1<<(cam->params.exposure.gainMode-1), tmpstr);
switch(cam->params.exposure.expMode) {
case 1:
@@ -402,10 +402,10 @@ static int cpia_read_proc(char *page, char **start, off_t off,
out += sprintf(out, "exposure_mode: %8s %8s %8s"
" %8s\n", tmpstr, "manual", "auto", "auto");
out += sprintf(out, "centre_weight: %8s %8s %8s %8s\n",
- (2-cam->params.exposure.centreWeight) ? "on" : "off",
- "off", "on", "on");
+ (2-cam->params.exposure.centreWeight) ? "on" : "off",
+ "off", "on", "on");
out += sprintf(out, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n",
- 1<<cam->params.exposure.gain, 1, 1);
+ 1<<cam->params.exposure.gain, 1, 1);
if (cam->params.version.firmwareVersion == 1 &&
cam->params.version.firmwareRevision == 2)
/* 1-02 firmware limits fineExp/2 to 127 */
@@ -414,7 +414,7 @@ static int cpia_read_proc(char *page, char **start, off_t off,
tmp = 510;
out += sprintf(out, "fine_exp: %8d %8d %8d %8d\n",
- cam->params.exposure.fineExp*2, 0, tmp, 0);
+ cam->params.exposure.fineExp*2, 0, tmp, 0);
if (cam->params.version.firmwareVersion == 1 &&
cam->params.version.firmwareRevision == 2)
/* 1-02 firmware limits coarseExpHi to 0 */
@@ -426,46 +426,46 @@ static int cpia_read_proc(char *page, char **start, off_t off,
" %8d\n", cam->params.exposure.coarseExpLo+
256*cam->params.exposure.coarseExpHi, 0, tmp, 185);
out += sprintf(out, "red_comp: %8d %8d %8d %8d\n",
- cam->params.exposure.redComp, COMP_RED, 255, COMP_RED);
+ cam->params.exposure.redComp, COMP_RED, 255, COMP_RED);
out += sprintf(out, "green1_comp: %8d %8d %8d %8d\n",
- cam->params.exposure.green1Comp, COMP_GREEN1, 255,
+ cam->params.exposure.green1Comp, COMP_GREEN1, 255,
COMP_GREEN1);
out += sprintf(out, "green2_comp: %8d %8d %8d %8d\n",
- cam->params.exposure.green2Comp, COMP_GREEN2, 255,
+ cam->params.exposure.green2Comp, COMP_GREEN2, 255,
COMP_GREEN2);
out += sprintf(out, "blue_comp: %8d %8d %8d %8d\n",
- cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE);
-
+ cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE);
+
out += sprintf(out, "apcor_gain1: %#8x %#8x %#8x %#8x\n",
- cam->params.apcor.gain1, 0, 0xff, 0x1c);
+ cam->params.apcor.gain1, 0, 0xff, 0x1c);
out += sprintf(out, "apcor_gain2: %#8x %#8x %#8x %#8x\n",
- cam->params.apcor.gain2, 0, 0xff, 0x1a);
+ cam->params.apcor.gain2, 0, 0xff, 0x1a);
out += sprintf(out, "apcor_gain4: %#8x %#8x %#8x %#8x\n",
- cam->params.apcor.gain4, 0, 0xff, 0x2d);
+ cam->params.apcor.gain4, 0, 0xff, 0x2d);
out += sprintf(out, "apcor_gain8: %#8x %#8x %#8x %#8x\n",
- cam->params.apcor.gain8, 0, 0xff, 0x2a);
+ cam->params.apcor.gain8, 0, 0xff, 0x2a);
out += sprintf(out, "vl_offset_gain1: %8d %8d %8d %8d\n",
- cam->params.vlOffset.gain1, 0, 255, 24);
+ cam->params.vlOffset.gain1, 0, 255, 24);
out += sprintf(out, "vl_offset_gain2: %8d %8d %8d %8d\n",
- cam->params.vlOffset.gain2, 0, 255, 28);
+ cam->params.vlOffset.gain2, 0, 255, 28);
out += sprintf(out, "vl_offset_gain4: %8d %8d %8d %8d\n",
- cam->params.vlOffset.gain4, 0, 255, 30);
+ cam->params.vlOffset.gain4, 0, 255, 30);
out += sprintf(out, "vl_offset_gain8: %8d %8d %8d %8d\n",
- cam->params.vlOffset.gain8, 0, 255, 30);
+ cam->params.vlOffset.gain8, 0, 255, 30);
out += sprintf(out, "flicker_control: %8s %8s %8s %8s\n",
- cam->params.flickerControl.flickerMode ? "on" : "off",
+ cam->params.flickerControl.flickerMode ? "on" : "off",
"off", "on", "off");
out += sprintf(out, "mains_frequency: %8d %8d %8d %8d"
- " only 50/60\n",
- cam->mainsFreq ? 60 : 50, 50, 60, 50);
+ " only 50/60\n",
+ cam->mainsFreq ? 60 : 50, 50, 60, 50);
if(cam->params.flickerControl.allowableOverExposure < 0)
out += sprintf(out, "allowable_overexposure: %4dauto auto %8d auto\n",
- -cam->params.flickerControl.allowableOverExposure,
- 255);
+ -cam->params.flickerControl.allowableOverExposure,
+ 255);
else
out += sprintf(out, "allowable_overexposure: %8d auto %8d auto\n",
- cam->params.flickerControl.allowableOverExposure,
- 255);
+ cam->params.flickerControl.allowableOverExposure,
+ 255);
out += sprintf(out, "compression_mode: ");
switch(cam->params.compression.mode) {
case CPIA_COMPRESSION_NONE:
@@ -483,52 +483,52 @@ static int cpia_read_proc(char *page, char **start, off_t off,
}
out += sprintf(out, " none,auto,manual auto\n");
out += sprintf(out, "decimation_enable: %8s %8s %8s %8s\n",
- cam->params.compression.decimation ==
- DECIMATION_ENAB ? "on":"off", "off", "on",
+ cam->params.compression.decimation ==
+ DECIMATION_ENAB ? "on":"off", "off", "on",
"off");
out += sprintf(out, "compression_target: %9s %9s %9s %9s\n",
- cam->params.compressionTarget.frTargeting ==
+ cam->params.compressionTarget.frTargeting ==
CPIA_COMPRESSION_TARGET_FRAMERATE ?
"framerate":"quality",
"framerate", "quality", "quality");
out += sprintf(out, "target_framerate: %8d %8d %8d %8d\n",
- cam->params.compressionTarget.targetFR, 1, 30, 15);
+ cam->params.compressionTarget.targetFR, 1, 30, 15);
out += sprintf(out, "target_quality: %8d %8d %8d %8d\n",
- cam->params.compressionTarget.targetQ, 1, 64, 5);
+ cam->params.compressionTarget.targetQ, 1, 64, 5);
out += sprintf(out, "y_threshold: %8d %8d %8d %8d\n",
- cam->params.yuvThreshold.yThreshold, 0, 31, 6);
+ cam->params.yuvThreshold.yThreshold, 0, 31, 6);
out += sprintf(out, "uv_threshold: %8d %8d %8d %8d\n",
- cam->params.yuvThreshold.uvThreshold, 0, 31, 6);
+ cam->params.yuvThreshold.uvThreshold, 0, 31, 6);
out += sprintf(out, "hysteresis: %8d %8d %8d %8d\n",
- cam->params.compressionParams.hysteresis, 0, 255, 3);
+ cam->params.compressionParams.hysteresis, 0, 255, 3);
out += sprintf(out, "threshold_max: %8d %8d %8d %8d\n",
- cam->params.compressionParams.threshMax, 0, 255, 11);
+ cam->params.compressionParams.threshMax, 0, 255, 11);
out += sprintf(out, "small_step: %8d %8d %8d %8d\n",
- cam->params.compressionParams.smallStep, 0, 255, 1);
+ cam->params.compressionParams.smallStep, 0, 255, 1);
out += sprintf(out, "large_step: %8d %8d %8d %8d\n",
- cam->params.compressionParams.largeStep, 0, 255, 3);
+ cam->params.compressionParams.largeStep, 0, 255, 3);
out += sprintf(out, "decimation_hysteresis: %8d %8d %8d %8d\n",
- cam->params.compressionParams.decimationHysteresis,
+ cam->params.compressionParams.decimationHysteresis,
0, 255, 2);
out += sprintf(out, "fr_diff_step_thresh: %8d %8d %8d %8d\n",
- cam->params.compressionParams.frDiffStepThresh,
+ cam->params.compressionParams.frDiffStepThresh,
0, 255, 5);
out += sprintf(out, "q_diff_step_thresh: %8d %8d %8d %8d\n",
- cam->params.compressionParams.qDiffStepThresh,
+ cam->params.compressionParams.qDiffStepThresh,
0, 255, 3);
out += sprintf(out, "decimation_thresh_mod: %8d %8d %8d %8d\n",
- cam->params.compressionParams.decimationThreshMod,
+ cam->params.compressionParams.decimationThreshMod,
0, 255, 2);
/* QX3 specific entries */
if (cam->params.qx3.qx3_detected) {
- out += sprintf(out, "toplight: %8s %8s %8s %8s\n",
- cam->params.qx3.toplight ? "on" : "off",
+ out += sprintf(out, "toplight: %8s %8s %8s %8s\n",
+ cam->params.qx3.toplight ? "on" : "off",
"off", "on", "off");
- out += sprintf(out, "bottomlight: %8s %8s %8s %8s\n",
- cam->params.qx3.bottomlight ? "on" : "off",
+ out += sprintf(out, "bottomlight: %8s %8s %8s %8s\n",
+ cam->params.qx3.bottomlight ? "on" : "off",
"off", "on", "off");
}
-
+
len = out - page;
len -= off;
if (len < count) {
@@ -543,7 +543,7 @@ static int cpia_read_proc(char *page, char **start, off_t off,
static int match(char *checkstr, char **buffer, unsigned long *count,
- int *find_colon, int *err)
+ int *find_colon, int *err)
{
int ret, colon_found = 1;
int len = strlen(checkstr);
@@ -583,7 +583,7 @@ static unsigned long int value(char **buffer, unsigned long *count, int *err)
}
static int cpia_write_proc(struct file *file, const char __user *buf,
- unsigned long count, void *data)
+ unsigned long count, void *data)
{
struct cam_data *cam = data;
struct cam_params new_params;
@@ -619,12 +619,12 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
retval = -EINVAL;
goto out;
}
-
+
buffer = page;
-
+
if (mutex_lock_interruptible(&cam->param_lock))
return -ERESTARTSYS;
-
+
/*
* Skip over leading whitespace
*/
@@ -632,15 +632,15 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
--count;
++buffer;
}
-
+
memcpy(&new_params, &cam->params, sizeof(struct cam_params));
new_mains = cam->mainsFreq;
-
+
#define MATCH(x) (match(x, &buffer, &count, &find_colon, &retval))
#define VALUE (value(&buffer,&count, &retval))
#define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \
- new_params.version.firmwareRevision == (y))
-
+ new_params.version.firmwareRevision == (y))
+
retval = 0;
while (count && !retval) {
find_colon = 1;
@@ -656,7 +656,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
}
command_flags |= COMMAND_SETCOLOURPARAMS;
if(new_params.flickerControl.allowableOverExposure < 0)
- new_params.flickerControl.allowableOverExposure =
+ new_params.flickerControl.allowableOverExposure =
-find_over_exposure(new_params.colourParams.brightness);
if(new_params.flickerControl.flickerMode != 0)
command_flags |= COMMAND_SETFLICKERCTRL;
@@ -721,7 +721,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
/* Either base rate would work here */
new_params.sensorFps.baserate = 1;
}
- new_params.flickerControl.coarseJump =
+ new_params.flickerControl.coarseJump =
flicker_jumps[new_mains]
[new_params.sensorFps.baserate]
[new_params.sensorFps.divisor];
@@ -1085,7 +1085,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
} else if (MATCH("mains_frequency")) {
if (!retval && MATCH("50")) {
new_mains = 0;
- new_params.flickerControl.coarseJump =
+ new_params.flickerControl.coarseJump =
flicker_jumps[new_mains]
[new_params.sensorFps.baserate]
[new_params.sensorFps.divisor];
@@ -1093,7 +1093,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
command_flags |= COMMAND_SETFLICKERCTRL;
} else if (!retval && MATCH("60")) {
new_mains = 1;
- new_params.flickerControl.coarseJump =
+ new_params.flickerControl.coarseJump =
flicker_jumps[new_mains]
[new_params.sensorFps.baserate]
[new_params.sensorFps.divisor];
@@ -1103,7 +1103,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
retval = -EINVAL;
} else if (MATCH("allowable_overexposure")) {
if (!retval && MATCH("auto")) {
- new_params.flickerControl.allowableOverExposure =
+ new_params.flickerControl.allowableOverExposure =
-find_over_exposure(new_params.colourParams.brightness);
if(new_params.flickerControl.flickerMode != 0)
command_flags |= COMMAND_SETFLICKERCTRL;
@@ -1146,10 +1146,10 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
command_flags |= COMMAND_SETCOMPRESSION;
} else if (MATCH("compression_target")) {
if (!retval && MATCH("quality"))
- new_params.compressionTarget.frTargeting =
+ new_params.compressionTarget.frTargeting =
CPIA_COMPRESSION_TARGET_QUALITY;
else if (!retval && MATCH("framerate"))
- new_params.compressionTarget.frTargeting =
+ new_params.compressionTarget.frTargeting =
CPIA_COMPRESSION_TARGET_FRAMERATE;
else
retval = -EINVAL;
@@ -1173,7 +1173,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
if (!retval) {
if(val > 0 && val <= 64)
new_params.compressionTarget.targetQ = val;
- else
+ else
retval = -EINVAL;
}
command_flags |= COMMAND_SETCOMPRESSIONTARGET;
@@ -1288,19 +1288,19 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
}
command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
} else if (MATCH("toplight")) {
- if (!retval && MATCH("on"))
+ if (!retval && MATCH("on"))
new_params.qx3.toplight = 1;
else if (!retval && MATCH("off"))
new_params.qx3.toplight = 0;
- else
+ else
retval = -EINVAL;
command_flags |= COMMAND_SETLIGHTS;
} else if (MATCH("bottomlight")) {
- if (!retval && MATCH("on"))
+ if (!retval && MATCH("on"))
new_params.qx3.bottomlight = 1;
- else if (!retval && MATCH("off"))
+ else if (!retval && MATCH("off"))
new_params.qx3.bottomlight = 0;
- else
+ else
retval = -EINVAL;
command_flags |= COMMAND_SETLIGHTS;
} else {
@@ -1326,7 +1326,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
}
}
}
-#undef MATCH
+#undef MATCH
#undef VALUE
#undef FIRMWARE_VERSION
if (!retval) {
@@ -1349,24 +1349,24 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
retval = size;
} else
DBG("error: %d\n", retval);
-
+
mutex_unlock(&cam->param_lock);
-
+
out:
free_page((unsigned long)page);
- return retval;
+ return retval;
}
static void create_proc_cpia_cam(struct cam_data *cam)
{
char name[7];
struct proc_dir_entry *ent;
-
+
if (!cpia_proc_root || !cam)
return;
sprintf(name, "video%d", cam->vdev.minor);
-
+
ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root);
if (!ent)
return;
@@ -1374,9 +1374,9 @@ static void create_proc_cpia_cam(struct cam_data *cam)
ent->data = cam;
ent->read_proc = cpia_read_proc;
ent->write_proc = cpia_write_proc;
- /*
+ /*
size of the proc entry is 3736 bytes for the standard webcam;
- the extra features of the QX3 microscope add 189 bytes.
+ the extra features of the QX3 microscope add 189 bytes.
(we have not yet probed the camera to see which type it is).
*/
ent->size = 3736 + 189;
@@ -1386,10 +1386,10 @@ static void create_proc_cpia_cam(struct cam_data *cam)
static void destroy_proc_cpia_cam(struct cam_data *cam)
{
char name[7];
-
+
if (!cam || !cam->proc_entry)
return;
-
+
sprintf(name, "video%d", cam->vdev.minor);
remove_proc_entry(name, cpia_proc_root);
cam->proc_entry = NULL;
@@ -1596,13 +1596,13 @@ static void set_vw_size(struct cam_data *cam)
cam->vc.width = cam->vw.width;
if(cam->vc.height == 0)
cam->vc.height = cam->vw.height;
-
+
cam->params.roi.colStart += cam->vc.x >> 3;
cam->params.roi.colEnd = cam->params.roi.colStart +
- (cam->vc.width >> 3);
+ (cam->vc.width >> 3);
cam->params.roi.rowStart += cam->vc.y >> 2;
cam->params.roi.rowEnd = cam->params.roi.rowStart +
- (cam->vc.height >> 2);
+ (cam->vc.height >> 2);
return;
}
@@ -1624,7 +1624,7 @@ static int allocate_frame_buf(struct cam_data *cam)
static int free_frame_buf(struct cam_data *cam)
{
int i;
-
+
rvfree(cam->frame_buf, FRAME_NUM*CPIA_MAX_FRAME_SIZE);
cam->frame_buf = NULL;
for (i=0; i < FRAME_NUM; i++)
@@ -1667,7 +1667,7 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d)
mutex_lock(&cam->param_lock);
datasize=8;
break;
- case CPIA_COMMAND_ReadMCPorts:
+ case CPIA_COMMAND_ReadMCPorts:
case CPIA_COMMAND_ReadVCRegs:
datasize = 4;
break;
@@ -1746,10 +1746,10 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d)
mutex_unlock(&cam->param_lock);
break;
- case CPIA_COMMAND_ReadMCPorts:
- if (!cam->params.qx3.qx3_detected)
+ case CPIA_COMMAND_ReadMCPorts:
+ if (!cam->params.qx3.qx3_detected)
break;
- /* test button press */
+ /* test button press */
cam->params.qx3.button = ((data[1] & 0x02) == 0);
if (cam->params.qx3.button) {
/* button pressed - unlock the latch */
@@ -1770,9 +1770,9 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d)
/* send a command to the camera with an additional data transaction */
static int do_command_extended(struct cam_data *cam, u16 command,
- u8 a, u8 b, u8 c, u8 d,
- u8 e, u8 f, u8 g, u8 h,
- u8 i, u8 j, u8 k, u8 l)
+ u8 a, u8 b, u8 c, u8 d,
+ u8 e, u8 f, u8 g, u8 h,
+ u8 i, u8 j, u8 k, u8 l)
{
int retval;
u8 cmd[8], data[8];
@@ -1809,10 +1809,10 @@ static int do_command_extended(struct cam_data *cam, u16 command,
#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
static int convert420(unsigned char *yuv, unsigned char *rgb, int out_fmt,
- int linesize, int mmap_kludge)
+ int linesize, int mmap_kludge)
{
int y, u, v, r, g, b, y1;
-
+
/* Odd lines use the same u and v as the previous line.
* Because of compression, it is necessary to get this
* information from the decoded image. */
@@ -1925,7 +1925,7 @@ static int convert420(unsigned char *yuv, unsigned char *rgb, int out_fmt,
static int yuvconvert(unsigned char *yuv, unsigned char *rgb, int out_fmt,
- int in_uyvy, int mmap_kludge)
+ int in_uyvy, int mmap_kludge)
{
int y, u, v, r, g, b, y1;
@@ -2078,21 +2078,21 @@ static int parse_picture(struct cam_data *cam, int size)
mutex_unlock(&cam->param_lock);
return -1;
}
-
+
if (ibuf[17] != SUBSAMPLE_420 && ibuf[17] != SUBSAMPLE_422) {
LOG("illegal subtype %d\n",ibuf[17]);
mutex_unlock(&cam->param_lock);
return -1;
}
subsample_422 = ibuf[17] == SUBSAMPLE_422;
-
+
if (ibuf[18] != YUVORDER_YUYV && ibuf[18] != YUVORDER_UYVY) {
LOG("illegal yuvorder %d\n",ibuf[18]);
mutex_unlock(&cam->param_lock);
return -1;
}
in_uyvy = ibuf[18] == YUVORDER_UYVY;
-
+
if ((ibuf[24] != cam->params.roi.colStart) ||
(ibuf[25] != cam->params.roi.colEnd) ||
(ibuf[26] != cam->params.roi.rowStart) ||
@@ -2104,20 +2104,20 @@ static int parse_picture(struct cam_data *cam, int size)
cols = 8*(ibuf[25] - ibuf[24]);
rows = 4*(ibuf[27] - ibuf[26]);
-
+
if ((ibuf[28] != NOT_COMPRESSED) && (ibuf[28] != COMPRESSED)) {
LOG("illegal compression %d\n",ibuf[28]);
mutex_unlock(&cam->param_lock);
return -1;
}
compressed = (ibuf[28] == COMPRESSED);
-
+
if (ibuf[29] != NO_DECIMATION && ibuf[29] != DECIMATION_ENAB) {
LOG("illegal decimation %d\n",ibuf[29]);
mutex_unlock(&cam->param_lock);
return -1;
}
- decimation = (ibuf[29] == DECIMATION_ENAB);
+ decimation = (ibuf[29] == DECIMATION_ENAB);
cam->params.yuvThreshold.yThreshold = ibuf[30];
cam->params.yuvThreshold.uvThreshold = ibuf[31];
@@ -2131,7 +2131,7 @@ static int parse_picture(struct cam_data *cam, int size)
cam->params.status.errorCode = ibuf[39];
cam->fps = ibuf[41];
mutex_unlock(&cam->param_lock);
-
+
linesize = skipcount(cols, out_fmt);
ibuf += FRAME_HEADER_SIZE;
size -= FRAME_HEADER_SIZE;
@@ -2150,14 +2150,14 @@ static int parse_picture(struct cam_data *cam, int size)
if (!compressed || (compressed && !(*ibuf & 1))) {
if(subsample_422 || even_line) {
obuf += yuvconvert(ibuf, obuf, out_fmt,
- in_uyvy, cam->mmap_kludge);
+ in_uyvy, cam->mmap_kludge);
ibuf += 4;
ll -= 4;
} else {
/* SUBSAMPLE_420 on an odd line */
obuf += convert420(ibuf, obuf,
- out_fmt, linesize,
- cam->mmap_kludge);
+ out_fmt, linesize,
+ cam->mmap_kludge);
ibuf += 2;
ll -= 2;
}
@@ -2183,7 +2183,7 @@ static int parse_picture(struct cam_data *cam, int size)
if ((size > 3) && (ibuf[0] == EOI) && (ibuf[1] == EOI) &&
(ibuf[2] == EOI) && (ibuf[3] == EOI)) {
- size -= 4;
+ size -= 4;
break;
}
@@ -2204,7 +2204,7 @@ static int parse_picture(struct cam_data *cam, int size)
return -1;
}
}
-
+
if(decimation) {
/* interpolate odd rows */
int i, j;
@@ -2233,7 +2233,7 @@ static int parse_picture(struct cam_data *cam, int size)
static inline int init_stream_cap(struct cam_data *cam)
{
return do_command(cam, CPIA_COMMAND_InitStreamCap,
- 0, cam->params.streamStartLine, 0, 0);
+ 0, cam->params.streamStartLine, 0, 0);
}
@@ -2254,7 +2254,7 @@ static int find_over_exposure(int brightness)
int MaxAllowableOverExposure, OverExposure;
MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness -
- FLICKER_BRIGHTNESS_CONSTANT;
+ FLICKER_BRIGHTNESS_CONSTANT;
if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE) {
OverExposure = MaxAllowableOverExposure;
@@ -2280,62 +2280,62 @@ static void dispatch_commands(struct cam_data *cam)
DEB_BYTE(cam->cmd_queue>>8);
if (cam->cmd_queue & COMMAND_SETFORMAT) {
do_command(cam, CPIA_COMMAND_SetFormat,
- cam->params.format.videoSize,
- cam->params.format.subSample,
- cam->params.format.yuvOrder, 0);
+ cam->params.format.videoSize,
+ cam->params.format.subSample,
+ cam->params.format.yuvOrder, 0);
do_command(cam, CPIA_COMMAND_SetROI,
- cam->params.roi.colStart, cam->params.roi.colEnd,
- cam->params.roi.rowStart, cam->params.roi.rowEnd);
+ cam->params.roi.colStart, cam->params.roi.colEnd,
+ cam->params.roi.rowStart, cam->params.roi.rowEnd);
cam->first_frame = 1;
}
if (cam->cmd_queue & COMMAND_SETCOLOURPARAMS)
do_command(cam, CPIA_COMMAND_SetColourParams,
- cam->params.colourParams.brightness,
- cam->params.colourParams.contrast,
- cam->params.colourParams.saturation, 0);
+ cam->params.colourParams.brightness,
+ cam->params.colourParams.contrast,
+ cam->params.colourParams.saturation, 0);
if (cam->cmd_queue & COMMAND_SETAPCOR)
do_command(cam, CPIA_COMMAND_SetApcor,
- cam->params.apcor.gain1,
- cam->params.apcor.gain2,
- cam->params.apcor.gain4,
- cam->params.apcor.gain8);
+ cam->params.apcor.gain1,
+ cam->params.apcor.gain2,
+ cam->params.apcor.gain4,
+ cam->params.apcor.gain8);
if (cam->cmd_queue & COMMAND_SETVLOFFSET)
do_command(cam, CPIA_COMMAND_SetVLOffset,
- cam->params.vlOffset.gain1,
- cam->params.vlOffset.gain2,
- cam->params.vlOffset.gain4,
- cam->params.vlOffset.gain8);
+ cam->params.vlOffset.gain1,
+ cam->params.vlOffset.gain2,
+ cam->params.vlOffset.gain4,
+ cam->params.vlOffset.gain8);
if (cam->cmd_queue & COMMAND_SETEXPOSURE) {
do_command_extended(cam, CPIA_COMMAND_SetExposure,
- cam->params.exposure.gainMode,
- 1,
- cam->params.exposure.compMode,
- cam->params.exposure.centreWeight,
- cam->params.exposure.gain,
- cam->params.exposure.fineExp,
- cam->params.exposure.coarseExpLo,
- cam->params.exposure.coarseExpHi,
- cam->params.exposure.redComp,
- cam->params.exposure.green1Comp,
- cam->params.exposure.green2Comp,
- cam->params.exposure.blueComp);
+ cam->params.exposure.gainMode,
+ 1,
+ cam->params.exposure.compMode,
+ cam->params.exposure.centreWeight,
+ cam->params.exposure.gain,
+ cam->params.exposure.fineExp,
+ cam->params.exposure.coarseExpLo,
+ cam->params.exposure.coarseExpHi,
+ cam->params.exposure.redComp,
+ cam->params.exposure.green1Comp,
+ cam->params.exposure.green2Comp,
+ cam->params.exposure.blueComp);
if(cam->params.exposure.expMode != 1) {
do_command_extended(cam, CPIA_COMMAND_SetExposure,
- 0,
- cam->params.exposure.expMode,
- 0, 0,
- cam->params.exposure.gain,
- cam->params.exposure.fineExp,
- cam->params.exposure.coarseExpLo,
- cam->params.exposure.coarseExpHi,
- 0, 0, 0, 0);
+ 0,
+ cam->params.exposure.expMode,
+ 0, 0,
+ cam->params.exposure.gain,
+ cam->params.exposure.fineExp,
+ cam->params.exposure.coarseExpLo,
+ cam->params.exposure.coarseExpHi,
+ 0, 0, 0, 0);
}
}
-
+
if (cam->cmd_queue & COMMAND_SETCOLOURBALANCE) {
if (cam->params.colourBalance.balanceMode == 1) {
do_command(cam, CPIA_COMMAND_SetColourBalance,
@@ -2358,47 +2358,47 @@ static void dispatch_commands(struct cam_data *cam)
if (cam->cmd_queue & COMMAND_SETCOMPRESSIONTARGET)
do_command(cam, CPIA_COMMAND_SetCompressionTarget,
- cam->params.compressionTarget.frTargeting,
- cam->params.compressionTarget.targetFR,
- cam->params.compressionTarget.targetQ, 0);
+ cam->params.compressionTarget.frTargeting,
+ cam->params.compressionTarget.targetFR,
+ cam->params.compressionTarget.targetQ, 0);
if (cam->cmd_queue & COMMAND_SETYUVTHRESH)
do_command(cam, CPIA_COMMAND_SetYUVThresh,
- cam->params.yuvThreshold.yThreshold,
- cam->params.yuvThreshold.uvThreshold, 0, 0);
+ cam->params.yuvThreshold.yThreshold,
+ cam->params.yuvThreshold.uvThreshold, 0, 0);
if (cam->cmd_queue & COMMAND_SETCOMPRESSIONPARAMS)
do_command_extended(cam, CPIA_COMMAND_SetCompressionParams,
- 0, 0, 0, 0,
- cam->params.compressionParams.hysteresis,
- cam->params.compressionParams.threshMax,
- cam->params.compressionParams.smallStep,
- cam->params.compressionParams.largeStep,
- cam->params.compressionParams.decimationHysteresis,
- cam->params.compressionParams.frDiffStepThresh,
- cam->params.compressionParams.qDiffStepThresh,
- cam->params.compressionParams.decimationThreshMod);
+ 0, 0, 0, 0,
+ cam->params.compressionParams.hysteresis,
+ cam->params.compressionParams.threshMax,
+ cam->params.compressionParams.smallStep,
+ cam->params.compressionParams.largeStep,
+ cam->params.compressionParams.decimationHysteresis,
+ cam->params.compressionParams.frDiffStepThresh,
+ cam->params.compressionParams.qDiffStepThresh,
+ cam->params.compressionParams.decimationThreshMod);
if (cam->cmd_queue & COMMAND_SETCOMPRESSION)
do_command(cam, CPIA_COMMAND_SetCompression,
- cam->params.compression.mode,
+ cam->params.compression.mode,
cam->params.compression.decimation, 0, 0);
if (cam->cmd_queue & COMMAND_SETSENSORFPS)
do_command(cam, CPIA_COMMAND_SetSensorFPS,
- cam->params.sensorFps.divisor,
- cam->params.sensorFps.baserate, 0, 0);
+ cam->params.sensorFps.divisor,
+ cam->params.sensorFps.baserate, 0, 0);
if (cam->cmd_queue & COMMAND_SETFLICKERCTRL)
do_command(cam, CPIA_COMMAND_SetFlickerCtrl,
- cam->params.flickerControl.flickerMode,
- cam->params.flickerControl.coarseJump,
- abs(cam->params.flickerControl.allowableOverExposure),
- 0);
+ cam->params.flickerControl.flickerMode,
+ cam->params.flickerControl.coarseJump,
+ abs(cam->params.flickerControl.allowableOverExposure),
+ 0);
if (cam->cmd_queue & COMMAND_SETECPTIMING)
do_command(cam, CPIA_COMMAND_SetECPTiming,
- cam->params.ecpTiming, 0, 0, 0);
+ cam->params.ecpTiming, 0, 0, 0);
if (cam->cmd_queue & COMMAND_PAUSE)
do_command(cam, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0);
@@ -2409,9 +2409,9 @@ static void dispatch_commands(struct cam_data *cam)
if (cam->cmd_queue & COMMAND_SETLIGHTS && cam->params.qx3.qx3_detected)
{
int p1 = (cam->params.qx3.bottomlight == 0) << 1;
- int p2 = (cam->params.qx3.toplight == 0) << 3;
- do_command(cam, CPIA_COMMAND_WriteVCReg, 0x90, 0x8F, 0x50, 0);
- do_command(cam, CPIA_COMMAND_WriteMCPort, 2, 0, (p1|p2|0xE0), 0);
+ int p2 = (cam->params.qx3.toplight == 0) << 3;
+ do_command(cam, CPIA_COMMAND_WriteVCReg, 0x90, 0x8F, 0x50, 0);
+ do_command(cam, CPIA_COMMAND_WriteMCPort, 2, 0, (p1|p2|0xE0), 0);
}
cam->cmd_queue = COMMAND_NONE;
@@ -2422,11 +2422,11 @@ static void dispatch_commands(struct cam_data *cam)
static void set_flicker(struct cam_params *params, volatile u32 *command_flags,
- int on)
+ int on)
{
/* Everything in here is from the Windows driver */
#define FIRMWARE_VERSION(x,y) (params->version.firmwareVersion == (x) && \
- params->version.firmwareRevision == (y))
+ params->version.firmwareRevision == (y))
/* define for compgain calculation */
#if 0
#define COMPGAIN(base, curexp, newexp) \
@@ -2441,7 +2441,7 @@ static void set_flicker(struct cam_params *params, volatile u32 *command_flags,
(u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128)))
#endif
-
+
int currentexp = params->exposure.coarseExpLo +
params->exposure.coarseExpHi*256;
int startexp;
@@ -2482,7 +2482,7 @@ static void set_flicker(struct cam_params *params, volatile u32 *command_flags,
}
if(FIRMWARE_VERSION(1,2))
params->exposure.compMode = 0;
- else
+ else
params->exposure.compMode = 1;
params->apcor.gain1 = 0x18;
@@ -2533,14 +2533,14 @@ static void set_flicker(struct cam_params *params, volatile u32 *command_flags,
}
#define FIRMWARE_VERSION(x,y) (cam->params.version.firmwareVersion == (x) && \
- cam->params.version.firmwareRevision == (y))
+ cam->params.version.firmwareRevision == (y))
/* monitor the exposure and adjust the sensor frame rate if needed */
static void monitor_exposure(struct cam_data *cam)
{
u8 exp_acc, bcomp, gain, coarseL, cmd[8], data[8];
int retval, light_exp, dark_exp, very_dark_exp;
int old_exposure, new_exposure, framerate;
-
+
/* get necessary stats and register settings from camera */
/* do_command can't handle this, so do it ourselves */
cmd[0] = CPIA_COMMAND_ReadVPRegs>>8;
@@ -2564,17 +2564,17 @@ static void monitor_exposure(struct cam_data *cam)
mutex_lock(&cam->param_lock);
light_exp = cam->params.colourParams.brightness +
- TC - 50 + EXP_ACC_LIGHT;
+ TC - 50 + EXP_ACC_LIGHT;
if(light_exp > 255)
light_exp = 255;
dark_exp = cam->params.colourParams.brightness +
- TC - 50 - EXP_ACC_DARK;
+ TC - 50 - EXP_ACC_DARK;
if(dark_exp < 0)
dark_exp = 0;
very_dark_exp = dark_exp/2;
-
+
old_exposure = cam->params.exposure.coarseExpHi * 256 +
- cam->params.exposure.coarseExpLo;
+ cam->params.exposure.coarseExpLo;
if(!cam->params.flickerControl.disabled) {
/* Flicker control on */
@@ -2667,11 +2667,11 @@ static void monitor_exposure(struct cam_data *cam)
cam->exposure_status = EXPOSURE_NORMAL;
}
}
-
+
framerate = cam->fps;
if(framerate > 30 || framerate < 1)
framerate = 1;
-
+
if(!cam->params.flickerControl.disabled) {
/* Flicker control on */
if((cam->exposure_status == EXPOSURE_VERY_DARK ||
@@ -2683,10 +2683,10 @@ static void monitor_exposure(struct cam_data *cam)
++cam->params.sensorFps.divisor;
cam->cmd_queue |= COMMAND_SETSENSORFPS;
- cam->params.flickerControl.coarseJump =
+ cam->params.flickerControl.coarseJump =
flicker_jumps[cam->mainsFreq]
- [cam->params.sensorFps.baserate]
- [cam->params.sensorFps.divisor];
+ [cam->params.sensorFps.baserate]
+ [cam->params.sensorFps.divisor];
cam->cmd_queue |= COMMAND_SETFLICKERCTRL;
new_exposure = cam->params.flickerControl.coarseJump-1;
@@ -2704,15 +2704,15 @@ static void monitor_exposure(struct cam_data *cam)
cam->params.sensorFps.divisor > 0) {
/* light for too long */
- int max_exp = FIRMWARE_VERSION(1,2) ? MAX_EXP_102 : MAX_EXP ;
+ int max_exp = FIRMWARE_VERSION(1,2) ? MAX_EXP_102 : MAX_EXP ;
--cam->params.sensorFps.divisor;
cam->cmd_queue |= COMMAND_SETSENSORFPS;
- cam->params.flickerControl.coarseJump =
+ cam->params.flickerControl.coarseJump =
flicker_jumps[cam->mainsFreq]
- [cam->params.sensorFps.baserate]
- [cam->params.sensorFps.divisor];
+ [cam->params.sensorFps.baserate]
+ [cam->params.sensorFps.divisor];
cam->cmd_queue |= COMMAND_SETFLICKERCTRL;
new_exposure = cam->params.flickerControl.coarseJump-1;
@@ -2772,7 +2772,7 @@ static void monitor_exposure(struct cam_data *cam)
It also adjust the colour balance when an exposure step is detected - as
long as flicker is running
-*/
+*/
static void restart_flicker(struct cam_data *cam)
{
int cam_exposure, old_exp;
@@ -2786,22 +2786,22 @@ static void restart_flicker(struct cam_data *cam)
}
cam_exposure = cam->raw_image[39]*2;
old_exp = cam->params.exposure.coarseExpLo +
- cam->params.exposure.coarseExpHi*256;
- /*
- see how far away camera exposure is from a valid
- flicker exposure value
- */
- cam_exposure %= cam->params.flickerControl.coarseJump;
+ cam->params.exposure.coarseExpHi*256;
+ /*
+ see how far away camera exposure is from a valid
+ flicker exposure value
+ */
+ cam_exposure %= cam->params.flickerControl.coarseJump;
if(!cam->params.flickerControl.disabled &&
- cam_exposure <= cam->params.flickerControl.coarseJump - 3) {
+ cam_exposure <= cam->params.flickerControl.coarseJump - 3) {
/* Flicker control auto-disabled */
cam->params.flickerControl.disabled = 1;
}
-
+
if(cam->params.flickerControl.disabled &&
cam->params.flickerControl.flickerMode &&
old_exp > cam->params.flickerControl.coarseJump +
- ROUND_UP_EXP_FOR_FLICKER) {
+ ROUND_UP_EXP_FOR_FLICKER) {
/* exposure is now high enough to switch
flicker control back on */
set_flicker(&cam->params, &cam->cmd_queue, 1);
@@ -2818,7 +2818,7 @@ static int clear_stall(struct cam_data *cam)
{
/* FIXME: Does this actually work? */
LOG("Clearing stall\n");
-
+
cam->ops->streamRead(cam->lowlevel_data, cam->raw_image, 0);
do_command(cam, CPIA_COMMAND_GetCameraStatus,0,0,0,0);
return cam->params.status.streamState != STREAM_PAUSED;
@@ -2878,7 +2878,7 @@ static int fetch_frame(void *data)
return -EINTR;
do_command(cam, CPIA_COMMAND_GetCameraStatus,
- 0, 0, 0, 0);
+ 0, 0, 0, 0);
}
if(cam->params.status.streamState != STREAM_READY) {
continue;
@@ -2903,18 +2903,18 @@ static int fetch_frame(void *data)
/* Switch flicker control back on if it got turned off */
restart_flicker(cam);
-
+
/* If AEC is enabled, monitor the exposure and
adjust the sensor frame rate if needed */
if(cam->params.exposure.expMode == 2)
monitor_exposure(cam);
-
+
/* camera idle now so dispatch queued commands */
dispatch_commands(cam);
/* Update our knowledge of the camera state */
- do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
- do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
+ do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
+ do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
do_command(cam, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0);
/* decompress and convert image to by copying it from
@@ -2933,7 +2933,7 @@ static int fetch_frame(void *data)
uncompressed. */
cam->first_frame = 1;
do_command(cam, CPIA_COMMAND_SetGrabMode,
- CPIA_GRAB_SINGLE, 0, 0, 0);
+ CPIA_GRAB_SINGLE, 0, 0, 0);
/* FIXME: Trial & error - need up to 70ms for
the grab mode change to complete ? */
msleep_interruptible(70);
@@ -2957,12 +2957,12 @@ static int fetch_frame(void *data)
if (cam->first_frame) {
cam->first_frame = 0;
do_command(cam, CPIA_COMMAND_SetCompression,
- cam->params.compression.mode,
+ cam->params.compression.mode,
cam->params.compression.decimation, 0, 0);
/* Switch from single-grab to continuous grab */
do_command(cam, CPIA_COMMAND_SetGrabMode,
- CPIA_GRAB_CONTINUOUS, 0, 0, 0);
+ CPIA_GRAB_CONTINUOUS, 0, 0, 0);
}
return 0;
}
@@ -2977,12 +2977,12 @@ static int capture_frame(struct cam_data *cam, struct video_mmap *vm)
if ((err = allocate_frame_buf(cam)))
return err;
}
-
+
cam->curframe = vm->frame;
cam->frame[cam->curframe].state = FRAME_READY;
return fetch_frame(cam);
}
-
+
static int goto_high_power(struct cam_data *cam)
{
if (do_command(cam, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0))
@@ -3039,22 +3039,22 @@ static void save_camera_state(struct cam_data *cam)
static int set_camera_state(struct cam_data *cam)
{
cam->cmd_queue = COMMAND_SETCOMPRESSION |
- COMMAND_SETCOMPRESSIONTARGET |
- COMMAND_SETCOLOURPARAMS |
- COMMAND_SETFORMAT |
- COMMAND_SETYUVTHRESH |
- COMMAND_SETECPTIMING |
- COMMAND_SETCOMPRESSIONPARAMS |
- COMMAND_SETEXPOSURE |
- COMMAND_SETCOLOURBALANCE |
- COMMAND_SETSENSORFPS |
- COMMAND_SETAPCOR |
- COMMAND_SETFLICKERCTRL |
- COMMAND_SETVLOFFSET;
+ COMMAND_SETCOMPRESSIONTARGET |
+ COMMAND_SETCOLOURPARAMS |
+ COMMAND_SETFORMAT |
+ COMMAND_SETYUVTHRESH |
+ COMMAND_SETECPTIMING |
+ COMMAND_SETCOMPRESSIONPARAMS |
+ COMMAND_SETEXPOSURE |
+ COMMAND_SETCOLOURBALANCE |
+ COMMAND_SETSENSORFPS |
+ COMMAND_SETAPCOR |
+ COMMAND_SETFLICKERCTRL |
+ COMMAND_SETVLOFFSET;
do_command(cam, CPIA_COMMAND_SetGrabMode, CPIA_GRAB_SINGLE,0,0,0);
dispatch_commands(cam);
-
+
/* Wait 6 frames for the sensor to get all settings and
AEC/ACB to settle */
msleep_interruptible(6*(cam->params.sensorFps.baserate ? 33 : 40) *
@@ -3062,7 +3062,7 @@ static int set_camera_state(struct cam_data *cam)
if(signal_pending(current))
return -EINTR;
-
+
save_camera_state(cam);
return 0;
@@ -3094,9 +3094,9 @@ static int reset_camera(struct cam_data *cam)
if (goto_low_power(cam))
return -ENODEV;
}
-
+
/* procedure described in developer's guide p3-28 */
-
+
/* Check the firmware version. */
cam->params.version.firmwareVersion = 0;
get_version_information(cam);
@@ -3113,14 +3113,14 @@ static int reset_camera(struct cam_data *cam)
cam->params.qx3.qx3_detected = (cam->params.pnpID.vendor == 0x0813 &&
cam->params.pnpID.product == 0x0001);
- /* The fatal error checking should be done after
+ /* The fatal error checking should be done after
* the camera powers up (developer's guide p 3-38) */
/* Set streamState before transition to high power to avoid bug
* in firmware 1-02 */
do_command(cam, CPIA_COMMAND_ModifyCameraStatus, STREAMSTATE, 0,
- STREAM_NOT_READY, 0);
-
+ STREAM_NOT_READY, 0);
+
/* GotoHiPower */
err = goto_high_power(cam);
if (err)
@@ -3142,16 +3142,16 @@ static int reset_camera(struct cam_data *cam)
/* Firmware 1-02 may do this for parallel port cameras,
* just clear the flags (developer's guide p 3-38) */
do_command(cam, CPIA_COMMAND_ModifyCameraStatus,
- FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0);
+ FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0);
}
}
-
+
/* Check the camera status again */
if (cam->params.status.fatalError) {
if (cam->params.status.fatalError)
return -EIO;
}
-
+
/* VPVersion can't be retrieved before the camera is in HiPower,
* so get it here instead of in get_version_information. */
do_command(cam, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0);
@@ -3193,24 +3193,24 @@ static int cpia_open(struct inode *inode, struct file *file)
if (!cam->raw_image)
goto oops;
}
-
+
if (!cam->decompressed_frame.data) {
cam->decompressed_frame.data = rvmalloc(CPIA_MAX_FRAME_SIZE);
if (!cam->decompressed_frame.data)
goto oops;
}
-
+
/* open cpia */
err = -ENODEV;
if (cam->ops->open(cam->lowlevel_data))
goto oops;
-
+
/* reset the camera */
if ((err = reset_camera(cam)) != 0) {
cam->ops->close(cam->lowlevel_data);
goto oops;
}
-
+
err = -EINTR;
if(signal_pending(current))
goto oops;
@@ -3224,7 +3224,7 @@ static int cpia_open(struct inode *inode, struct file *file)
/* init it to something */
cam->mmap_kludge = 0;
-
+
++cam->open_count;
file->private_data = dev;
mutex_unlock(&cam->busy_lock);
@@ -3250,10 +3250,10 @@ static int cpia_close(struct inode *inode, struct file *file)
struct cam_data *cam = dev->priv;
if (cam->ops) {
- /* Return ownership of /proc/cpia/videoX to root */
+ /* Return ownership of /proc/cpia/videoX to root */
if(cam->proc_entry)
cam->proc_entry->uid = 0;
-
+
/* save camera state for later open (developers guide ch 3.5.3) */
save_camera_state(cam);
@@ -3342,7 +3342,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf,
return -EFAULT;
}
if (copy_to_user(buf, cam->decompressed_frame.data,
- cam->decompressed_frame.count)) {
+ cam->decompressed_frame.count)) {
DBG("copy_to_user failed\n");
mutex_unlock(&cam->busy_lock);
return -EFAULT;
@@ -3361,7 +3361,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
if (!cam || !cam->ops)
return -ENODEV;
-
+
/* make this _really_ smp-safe */
if (mutex_lock_interruptible(&cam->busy_lock))
return -EINTR;
@@ -3405,7 +3405,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
v->norm = 0;
break;
}
-
+
case VIDIOCSCHAN:
{
struct video_channel *v = arg;
@@ -3424,7 +3424,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
*pic = cam->vp;
break;
}
-
+
case VIDIOCSPICT:
{
struct video_picture *vp = arg;
@@ -3458,11 +3458,11 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
/* Adjust flicker control if necessary */
if(cam->params.flickerControl.allowableOverExposure < 0)
- cam->params.flickerControl.allowableOverExposure =
+ cam->params.flickerControl.allowableOverExposure =
-find_over_exposure(cam->params.colourParams.brightness);
if(cam->params.flickerControl.flickerMode != 0)
cam->cmd_queue |= COMMAND_SETFLICKERCTRL;
-
+
/* queue command to update camera */
cam->cmd_queue |= COMMAND_SETCOLOURPARAMS;
@@ -3482,7 +3482,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
*vw = cam->vw;
break;
}
-
+
case VIDIOCSWIN:
{
/* copy_from_user, check validity, copy to internal structure */
@@ -3514,7 +3514,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
/* video size is changing, reset the subcapture area */
memset(&cam->vc, 0, sizeof(cam->vc));
-
+
set_vw_size(cam);
DBG("%d / %d\n", cam->vw.width, cam->vw.height);
cam->cmd_queue |= COMMAND_SETFORMAT;
@@ -3547,7 +3547,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
vm->offsets[i] = CPIA_MAX_FRAME_SIZE * i;
break;
}
-
+
case VIDIOCMCAPTURE:
{
struct video_mmap *vm = arg;
@@ -3597,7 +3597,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
/* video size is changing, reset the subcapture area */
memset(&cam->vc, 0, sizeof(cam->vc));
-
+
set_vw_size(cam);
cam->cmd_queue |= COMMAND_SETFORMAT;
dispatch_commands(cam);
@@ -3608,7 +3608,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
break;
}
-
+
case VIDIOCSYNC:
{
int *frame = arg;
@@ -3649,7 +3649,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
*vc = cam->vc;
break;
- }
+ }
case VIDIOCSCAPTURE:
{
@@ -3665,7 +3665,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
retval = -EINVAL;
break;
}
-
+
/* Clip to the resolution we can set for the ROI
(every 8 columns and 4 rows) */
vc->x = vc->x & ~(__u32)7;
@@ -3681,14 +3681,14 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
}
DBG("%d,%d/%dx%d\n", vc->x,vc->y,vc->width, vc->height);
-
+
mutex_lock(&cam->param_lock);
-
+
cam->vc.x = vc->x;
cam->vc.y = vc->y;
cam->vc.width = vc->width;
cam->vc.height = vc->height;
-
+
set_vw_size(cam);
cam->cmd_queue |= COMMAND_SETFORMAT;
@@ -3699,7 +3699,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
dispatch_commands(cam);
break;
}
-
+
case VIDIOCGUNIT:
{
struct video_unit *vu = arg;
@@ -3715,7 +3715,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
break;
}
-
+
/* pointless to implement overlay with this camera */
case VIDIOCCAPTURE:
case VIDIOCGFBUF:
@@ -3738,7 +3738,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
mutex_unlock(&cam->busy_lock);
return retval;
-}
+}
static int cpia_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
@@ -3759,7 +3759,7 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
if (!cam || !cam->ops)
return -ENODEV;
-
+
DBG("cpia_mmap: %ld\n", size);
if (size > FRAME_NUM*CPIA_MAX_FRAME_SIZE)
@@ -3767,7 +3767,7 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
if (!cam || !cam->ops)
return -ENODEV;
-
+
/* make this _really_ smp-safe */
if (mutex_lock_interruptible(&cam->busy_lock))
return -EINTR;
@@ -3851,11 +3851,11 @@ static void reset_camera_struct(struct cam_data *cam)
cam->params.flickerControl.flickerMode = 0;
cam->params.flickerControl.disabled = 1;
- cam->params.flickerControl.coarseJump =
+ cam->params.flickerControl.coarseJump =
flicker_jumps[cam->mainsFreq]
- [cam->params.sensorFps.baserate]
- [cam->params.sensorFps.divisor];
- cam->params.flickerControl.allowableOverExposure =
+ [cam->params.sensorFps.baserate]
+ [cam->params.sensorFps.divisor];
+ cam->params.flickerControl.allowableOverExposure =
-find_over_exposure(cam->params.colourParams.brightness);
cam->params.vlOffset.gain1 = 20;
cam->params.vlOffset.gain2 = 24;
@@ -3870,21 +3870,21 @@ static void reset_camera_struct(struct cam_data *cam)
cam->params.compressionParams.qDiffStepThresh = 3;
cam->params.compressionParams.decimationThreshMod = 2;
/* End of default values from Software Developer's Guide */
-
+
cam->transfer_rate = 0;
cam->exposure_status = EXPOSURE_NORMAL;
-
+
/* Set Sensor FPS to 15fps. This seems better than 30fps
* for indoor lighting. */
cam->params.sensorFps.divisor = 1;
cam->params.sensorFps.baserate = 1;
-
+
cam->params.yuvThreshold.yThreshold = 6; /* From windows driver */
cam->params.yuvThreshold.uvThreshold = 6; /* From windows driver */
-
+
cam->params.format.subSample = SUBSAMPLE_422;
cam->params.format.yuvOrder = YUVORDER_YUYV;
-
+
cam->params.compression.mode = CPIA_COMPRESSION_AUTO;
cam->params.compressionTarget.frTargeting =
CPIA_COMPRESSION_TARGET_QUALITY;
@@ -3898,7 +3898,7 @@ static void reset_camera_struct(struct cam_data *cam)
cam->params.qx3.cradled = 0;
cam->video_size = VIDEOSIZE_CIF;
-
+
cam->vp.colour = 32768; /* 50% */
cam->vp.hue = 32768; /* 50% */
cam->vp.brightness = 32768; /* 50% */
@@ -3911,7 +3911,7 @@ static void reset_camera_struct(struct cam_data *cam)
cam->vc.y = 0;
cam->vc.width = 0;
cam->vc.height = 0;
-
+
cam->vw.x = 0;
cam->vw.y = 0;
set_vw_size(cam);
@@ -3928,7 +3928,7 @@ static void reset_camera_struct(struct cam_data *cam)
/* initialize cam_data structure */
static void init_camera_struct(struct cam_data *cam,
- struct cpia_camera_ops *ops )
+ struct cpia_camera_ops *ops )
{
int i;
@@ -3945,7 +3945,7 @@ static void init_camera_struct(struct cam_data *cam,
memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template));
cam->vdev.priv = cam;
-
+
cam->curframe = 0;
for (i = 0; i < FRAME_NUM; i++) {
cam->frame[i].width = 0;
@@ -3961,15 +3961,15 @@ static void init_camera_struct(struct cam_data *cam,
struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel)
{
- struct cam_data *camera;
-
+ struct cam_data *camera;
+
if ((camera = kmalloc(sizeof(struct cam_data), GFP_KERNEL)) == NULL)
return NULL;
-
+
init_camera_struct( camera, ops );
camera->lowlevel_data = lowlevel;
-
+
/* register v4l device */
if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
kfree(camera);
@@ -3982,7 +3982,7 @@ struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowleve
/* open cpia */
if (camera->ops->open(camera->lowlevel_data))
return camera;
-
+
/* reset the camera */
if (reset_camera(camera) != 0) {
camera->ops->close(camera->lowlevel_data);
@@ -4022,11 +4022,11 @@ void cpia_unregister_camera(struct cam_data *cam)
DBG("camera open -- setting ops to NULL\n");
cam->ops = NULL;
}
-
+
#ifdef CONFIG_PROC_FS
DBG("destroying /proc/cpia/video%d\n", cam->vdev.minor);
destroy_proc_cpia_cam(cam);
-#endif
+#endif
if (!cam->open_count) {
DBG("freeing camera\n");
kfree(cam);
diff --git a/drivers/media/video/cpia.h b/drivers/media/video/cpia.h
index de6678200a5..dde27a6a4a0 100644
--- a/drivers/media/video/cpia.h
+++ b/drivers/media/video/cpia.h
@@ -52,10 +52,10 @@
struct cpia_camera_ops
{
/* open sets privdata to point to structure for this camera.
- * Returns negative value on error, otherwise 0.
+ * Returns negative value on error, otherwise 0.
*/
int (*open)(void *privdata);
-
+
/* Registers callback function cb to be called with cbdata
* when an image is ready. If cb is NULL, only single image grabs
* should be used. cb should immediately call streamRead to read
@@ -63,8 +63,8 @@ struct cpia_camera_ops
* otherwise 0.
*/
int (*registerCallback)(void *privdata, void (*cb)(void *cbdata),
- void *cbdata);
-
+ void *cbdata);
+
/* transferCmd sends commands to the camera. command MUST point to
* an 8 byte buffer in kernel space. data can be NULL if no extra
* data is needed. The size of the data is given by the last 2
@@ -77,30 +77,30 @@ struct cpia_camera_ops
* Returns negative value on error, otherwise 0.
*/
int (*streamStart)(void *privdata);
-
+
/* streamStop terminates stream capture mode.
* Returns negative value on error, otherwise 0.
*/
int (*streamStop)(void *privdata);
-
+
/* streamRead reads a frame from the camera. buffer points to a
- * buffer large enough to hold a complete frame in kernel space.
- * noblock indicates if this should be a non blocking read.
+ * buffer large enough to hold a complete frame in kernel space.
+ * noblock indicates if this should be a non blocking read.
* Returns the number of bytes read, or negative value on error.
- */
+ */
int (*streamRead)(void *privdata, u8 *buffer, int noblock);
-
+
/* close disables the device until open() is called again.
* Returns negative value on error, otherwise 0.
*/
int (*close)(void *privdata);
-
+
/* If wait_for_stream_ready is non-zero, wait until the streamState
* is STREAM_READY before calling streamRead.
*/
int wait_for_stream_ready;
- /*
+ /*
* Used to maintain lowlevel module usage counts
*/
struct module *owner;
@@ -215,14 +215,14 @@ struct cam_params {
u8 videoSize; /* CIF/QCIF */
u8 subSample;
u8 yuvOrder;
- } format;
- struct { /* Intel QX3 specific data */
- u8 qx3_detected; /* a QX3 is present */
- u8 toplight; /* top light lit , R/W */
- u8 bottomlight; /* bottom light lit, R/W */
- u8 button; /* snapshot button pressed (R/O) */
- u8 cradled; /* microscope is in cradle (R/O) */
- } qx3;
+ } format;
+ struct { /* Intel QX3 specific data */
+ u8 qx3_detected; /* a QX3 is present */
+ u8 toplight; /* top light lit , R/W */
+ u8 bottomlight; /* bottom light lit, R/W */
+ u8 button; /* snapshot button pressed (R/O) */
+ u8 cradled; /* microscope is in cradle (R/O) */
+ } qx3;
struct {
u8 colStart; /* skip first 8*colStart pixels */
u8 colEnd; /* finish at 8*colEnd pixels */
@@ -247,13 +247,13 @@ enum v4l_camstates {
struct cam_data {
struct list_head cam_data_list;
- struct mutex busy_lock; /* guard against SMP multithreading */
+ struct mutex busy_lock; /* guard against SMP multithreading */
struct cpia_camera_ops *ops; /* lowlevel driver operations */
void *lowlevel_data; /* private data for lowlevel driver */
u8 *raw_image; /* buffer for raw image data */
struct cpia_frame decompressed_frame;
- /* buffer to hold decompressed frame */
- int image_size; /* sizeof last decompressed image */
+ /* buffer to hold decompressed frame */
+ int image_size; /* sizeof last decompressed image */
int open_count; /* # of process that have camera open */
/* camera status */
@@ -265,7 +265,7 @@ struct cam_data {
struct mutex param_lock; /* params lock for this camera */
struct cam_params params; /* camera settings */
struct proc_dir_entry *proc_entry; /* /proc/cpia/videoX */
-
+
/* v4l */
int video_size; /* VIDEO_SIZE_ */
volatile enum v4l_camstates camstate; /* v4l layer status */
@@ -277,7 +277,7 @@ struct cam_data {
/* mmap interface */
int curframe; /* the current frame to grab into */
u8 *frame_buf; /* frame buffer data */
- struct cpia_frame frame[FRAME_NUM];
+ struct cpia_frame frame[FRAME_NUM];
/* FRAME_NUM-buffering, so we need a array */
int first_frame;
@@ -424,7 +424,7 @@ void cpia_unregister_camera(struct cam_data *cam);
#define DEB_BYTE(p)\
DBG("%1d %1d %1d %1d %1d %1d %1d %1d \n",\
(p)&0x80?1:0, (p)&0x40?1:0, (p)&0x20?1:0, (p)&0x10?1:0,\
- (p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0);
+ (p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0);
#endif /* __KERNEL__ */
diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h
index 95d3afa94a3..8394283993f 100644
--- a/drivers/media/video/cpia2/cpia2.h
+++ b/drivers/media/video/cpia2/cpia2.h
@@ -381,7 +381,7 @@ struct cpia2_fh {
struct camera_data {
/* locks */
- struct semaphore busy_lock; /* guard against SMP multithreading */
+ struct mutex busy_lock; /* guard against SMP multithreading */
struct v4l2_prio_state prio;
/* camera status */
diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c
index 5dfb242d5b8..fd771c7a2fe 100644
--- a/drivers/media/video/cpia2/cpia2_core.c
+++ b/drivers/media/video/cpia2/cpia2_core.c
@@ -2238,7 +2238,7 @@ struct camera_data *cpia2_init_camera_struct(void)
memset(cam, 0, sizeof(struct camera_data));
cam->present = 1;
- init_MUTEX(&cam->busy_lock);
+ mutex_init(&cam->busy_lock);
init_waitqueue_head(&cam->wq_stream);
return cam;
@@ -2371,12 +2371,12 @@ long cpia2_read(struct camera_data *cam,
}
/* make this _really_ smp and multithread-safe */
- if (down_interruptible(&cam->busy_lock))
+ if (mutex_lock_interruptible(&cam->busy_lock))
return -ERESTARTSYS;
if (!cam->present) {
LOG("%s: camera removed\n",__FUNCTION__);
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return 0; /* EOF */
}
@@ -2389,34 +2389,34 @@ long cpia2_read(struct camera_data *cam,
/* Copy cam->curbuff in case it changes while we're processing */
frame = cam->curbuff;
if (noblock && frame->status != FRAME_READY) {
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return -EAGAIN;
}
if(frame->status != FRAME_READY) {
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
wait_event_interruptible(cam->wq_stream,
!cam->present ||
(frame = cam->curbuff)->status == FRAME_READY);
if (signal_pending(current))
return -ERESTARTSYS;
/* make this _really_ smp and multithread-safe */
- if (down_interruptible(&cam->busy_lock)) {
+ if (mutex_lock_interruptible(&cam->busy_lock)) {
return -ERESTARTSYS;
}
if(!cam->present) {
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return 0;
}
}
/* copy data to user space */
if (frame->length > count) {
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return -EFAULT;
}
if (copy_to_user(buf, frame->data, frame->length)) {
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return -EFAULT;
}
@@ -2424,7 +2424,7 @@ long cpia2_read(struct camera_data *cam,
frame->status = FRAME_EMPTY;
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return count;
}
@@ -2443,10 +2443,10 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
return POLLERR;
}
- down(&cam->busy_lock);
+ mutex_lock(&cam->busy_lock);
if(!cam->present) {
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return POLLHUP;
}
@@ -2456,16 +2456,16 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
cam->params.camera_state.stream_mode);
}
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
poll_wait(filp, &cam->wq_stream, wait);
- down(&cam->busy_lock);
+ mutex_lock(&cam->busy_lock);
if(!cam->present)
status = POLLHUP;
else if(cam->curbuff->status == FRAME_READY)
status = POLLIN | POLLRDNORM;
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return status;
}
@@ -2488,18 +2488,18 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma)
DBG("mmap offset:%ld size:%ld\n", start_offset, size);
/* make this _really_ smp-safe */
- if (down_interruptible(&cam->busy_lock))
+ if (mutex_lock_interruptible(&cam->busy_lock))
return -ERESTARTSYS;
if (!cam->present) {
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return -ENODEV;
}
if (size > cam->frame_size*cam->num_frames ||
(start_offset % cam->frame_size) != 0 ||
(start_offset+size > cam->frame_size*cam->num_frames)) {
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return -EINVAL;
}
@@ -2507,7 +2507,7 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma)
while (size > 0) {
page = kvirt_to_pa(pos);
if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED)) {
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return -EAGAIN;
}
start += PAGE_SIZE;
@@ -2519,7 +2519,7 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma)
}
cam->mmapped = true;
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return 0;
}
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index 08f8be345fa..481e178ef56 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -255,7 +255,7 @@ static int cpia2_open(struct inode *inode, struct file *file)
return -ENODEV;
}
- if(down_interruptible(&cam->busy_lock))
+ if(mutex_lock_interruptible(&cam->busy_lock))
return -ERESTARTSYS;
if(!cam->present) {
@@ -299,7 +299,7 @@ skip_init:
cpia2_dbg_dump_registers(cam);
err_return:
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return retval;
}
@@ -314,7 +314,7 @@ static int cpia2_close(struct inode *inode, struct file *file)
struct camera_data *cam = video_get_drvdata(dev);
struct cpia2_fh *fh = file->private_data;
- down(&cam->busy_lock);
+ mutex_lock(&cam->busy_lock);
if (cam->present &&
(cam->open_count == 1
@@ -347,7 +347,7 @@ static int cpia2_close(struct inode *inode, struct file *file)
}
}
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return 0;
}
@@ -523,11 +523,11 @@ static int sync(struct camera_data *cam, int frame_nr)
return 0;
}
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
wait_event_interruptible(cam->wq_stream,
!cam->streaming ||
frame->status == FRAME_READY);
- down(&cam->busy_lock);
+ mutex_lock(&cam->busy_lock);
if (signal_pending(current))
return -ERESTARTSYS;
if(!cam->present)
@@ -1544,11 +1544,11 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file)
if(frame < 0) {
/* Wait for a frame to become available */
struct framebuf *cb=cam->curbuff;
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
wait_event_interruptible(cam->wq_stream,
!cam->present ||
(cb=cam->curbuff)->status == FRAME_READY);
- down(&cam->busy_lock);
+ mutex_lock(&cam->busy_lock);
if (signal_pending(current))
return -ERESTARTSYS;
if(!cam->present)
@@ -1591,11 +1591,11 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
return -ENOTTY;
/* make this _really_ smp-safe */
- if (down_interruptible(&cam->busy_lock))
+ if (mutex_lock_interruptible(&cam->busy_lock))
return -ERESTARTSYS;
if (!cam->present) {
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return -ENODEV;
}
@@ -1608,7 +1608,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
struct cpia2_fh *fh = file->private_data;
retval = v4l2_prio_check(&cam->prio, &fh->prio);
if(retval) {
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return retval;
}
break;
@@ -1618,7 +1618,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
{
struct cpia2_fh *fh = file->private_data;
if(fh->prio != V4L2_PRIORITY_RECORD) {
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return -EBUSY;
}
break;
@@ -1847,7 +1847,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
break;
}
- up(&cam->busy_lock);
+ mutex_unlock(&cam->busy_lock);
return retval;
}
@@ -1924,14 +1924,15 @@ static void reset_camera_struct_v4l(struct camera_data *cam)
* The v4l video device structure initialized for this device
***/
static struct file_operations fops_template = {
- .owner= THIS_MODULE,
- .open= cpia2_open,
- .release= cpia2_close,
- .read= cpia2_v4l_read,
- .poll= cpia2_v4l_poll,
- .ioctl= cpia2_ioctl,
- .llseek= no_llseek,
- .mmap= cpia2_mmap,
+ .owner = THIS_MODULE,
+ .open = cpia2_open,
+ .release = cpia2_close,
+ .read = cpia2_v4l_read,
+ .poll = cpia2_v4l_poll,
+ .ioctl = cpia2_ioctl,
+ .llseek = no_llseek,
+ .compat_ioctl = v4l_compat_ioctl32,
+ .mmap = cpia2_mmap,
};
static struct video_device cpia2_template = {
diff --git a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c
index 74cff626e04..3021f21aae3 100644
--- a/drivers/media/video/cpia_pp.c
+++ b/drivers/media/video/cpia_pp.c
@@ -23,7 +23,7 @@
*/
/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
-/* #define _CPIA_DEBUG_ 1 */
+/* #define _CPIA_DEBUG_ 1 */
#include <linux/config.h>
@@ -45,7 +45,7 @@
static int cpia_pp_open(void *privdata);
static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata),
- void *cbdata);
+ void *cbdata);
static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data);
static int cpia_pp_streamStart(void *privdata);
static int cpia_pp_streamStop(void *privdata);
@@ -93,7 +93,7 @@ struct pp_cam_entry {
int stream_irq;
};
-static struct cpia_camera_ops cpia_pp_ops =
+static struct cpia_camera_ops cpia_pp_ops =
{
cpia_pp_open,
cpia_pp_registerCallback,
@@ -123,7 +123,7 @@ static void cpia_parport_disable_irq( struct parport *port ) {
}
/* Special CPiA PPC modes: These are invoked by using the 1284 Extensibility
- * Link Flag during negotiation */
+ * Link Flag during negotiation */
#define UPLOAD_FLAG 0x08
#define NIBBLE_TRANSFER 0x01
#define ECP_TRANSFER 0x03
@@ -139,17 +139,17 @@ static void cpia_parport_disable_irq( struct parport *port ) {
/* CPiA nonstandard "Nibble" mode (no nDataAvail signal after each byte). */
/* The standard kernel parport_ieee1284_read_nibble() fails with the CPiA... */
-static size_t cpia_read_nibble (struct parport *port,
- void *buffer, size_t len,
+static size_t cpia_read_nibble (struct parport *port,
+ void *buffer, size_t len,
int flags)
{
- /* adapted verbatim, with one change, from
+ /* adapted verbatim, with one change, from
parport_ieee1284_read_nibble() in drivers/parport/ieee1284-ops.c */
unsigned char *buf = buffer;
int i;
unsigned char byte = 0;
-
+
len *= 2; /* in nibbles */
for (i=0; i < len; i++) {
unsigned char nibble;
@@ -158,12 +158,12 @@ static size_t cpia_read_nibble (struct parport *port,
* after every second nibble to signal that more
* data is available. (the total number of Bytes that
* should be sent is known; if too few are received, an error
- * will be recorded after a timeout).
+ * will be recorded after a timeout).
* This is incompatible with parport_ieee1284_read_nibble(),
* which expects to find nFault LO after every second nibble.
*/
- /* Solution: modify cpia_read_nibble to only check for
+ /* Solution: modify cpia_read_nibble to only check for
* nDataAvail before the first nibble is sent.
*/
@@ -216,7 +216,7 @@ static size_t cpia_read_nibble (struct parport *port,
/* Second nibble */
byte |= nibble << 4;
*buf++ = byte;
- } else
+ } else
byte = nibble;
}
@@ -238,18 +238,18 @@ static size_t cpia_read_nibble (struct parport *port,
}
/* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1)
- * (See CPiA Data sheet p. 31)
- *
- * "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a
- * nonstandard variant of nibble mode which allows the same (mediocre)
- * data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable
+ * (See CPiA Data sheet p. 31)
+ *
+ * "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a
+ * nonstandard variant of nibble mode which allows the same (mediocre)
+ * data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable
* parallel ports, but works also for non-TRISTATE-capable ports.
* (Standard nibble mode only send 4 bits per cycle)
*
*/
-static size_t cpia_read_nibble_stream(struct parport *port,
- void *buffer, size_t len,
+static size_t cpia_read_nibble_stream(struct parport *port,
+ void *buffer, size_t len,
int flags)
{
int i;
@@ -260,7 +260,7 @@ static size_t cpia_read_nibble_stream(struct parport *port,
unsigned char nibble[2], byte = 0;
int j;
- /* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */
+ /* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */
if (endseen > 3 )
break;
@@ -268,7 +268,7 @@ static size_t cpia_read_nibble_stream(struct parport *port,
parport_frob_control (port,
PARPORT_CONTROL_AUTOFD,
PARPORT_CONTROL_AUTOFD);
-
+
/* Event 9: nAck goes low. */
port->ieee1284.phase = IEEE1284_PH_REV_DATA;
if (parport_wait_peripheral (port,
@@ -282,7 +282,7 @@ static size_t cpia_read_nibble_stream(struct parport *port,
/* Read lower nibble */
nibble[0] = parport_read_status (port) >>3;
-
+
/* Event 10: Set nAutoFd high. */
parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
@@ -295,10 +295,10 @@ static size_t cpia_read_nibble_stream(struct parport *port,
port->name);
break;
}
-
+
/* Read upper nibble */
nibble[1] = parport_read_status (port) >>3;
-
+
/* reassemble the byte */
for (j = 0; j < 2 ; j++ ) {
nibble[j] &= ~8;
@@ -335,8 +335,8 @@ static void EndTransferMode(struct pp_cam_entry *cam)
static int ForwardSetup(struct pp_cam_entry *cam)
{
int retry;
-
- /* The CPiA uses ECP protocol for Downloads from the Host to the camera.
+
+ /* The CPiA uses ECP protocol for Downloads from the Host to the camera.
* This will be software-emulated if ECP hardware is not present
*/
@@ -375,9 +375,9 @@ static int ReverseSetup(struct pp_cam_entry *cam, int extensibility)
upload_mode = mode;
if(extensibility) mode = UPLOAD_FLAG|transfer_mode|IEEE1284_EXT_LINK;
- /* the usual camera maximum response time is 10ms, but after
+ /* the usual camera maximum response time is 10ms, but after
* receiving some commands, it needs up to 40ms. */
-
+
for(retry = 0; retry < 4; ++retry) {
if(!parport_negotiate(cam->port, mode)) {
break;
@@ -439,10 +439,10 @@ static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size)
/* support for CPiA variant nibble reads */
if(cam->port->ieee1284.mode == IEEE1284_MODE_NIBBLE) {
- if(cpia_read_nibble(cam->port, packet, size, 0) != size)
- retval = -EIO;
+ if(cpia_read_nibble(cam->port, packet, size, 0) != size)
+ retval = -EIO;
} else {
- if(parport_read(cam->port, packet, size) != size)
+ if(parport_read(cam->port, packet, size) != size)
retval = -EIO;
}
EndTransferMode(cam);
@@ -542,18 +542,18 @@ static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock)
block_size = PARPORT_CHUNK_SIZE;
while( !cam->image_complete ) {
cond_resched();
-
+
new_bytes = cpia_pp_read(cam->port, buffer, block_size );
if( new_bytes <= 0 ) {
break;
}
i=-1;
while(++i<new_bytes && endseen<4) {
- if(*buffer==EOI) {
- endseen++;
- } else {
- endseen=0;
- }
+ if(*buffer==EOI) {
+ endseen++;
+ } else {
+ endseen=0;
+ }
buffer++;
}
read_bytes += i;
@@ -601,7 +601,7 @@ static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data)
}
if((err = ReadPacket(cam, buffer, 8)) < 0) {
DBG("Error reading command result\n");
- return err;
+ return err;
}
memcpy(data, buffer, databytes);
} else if(command[0] == DATA_OUT) {
@@ -631,10 +631,10 @@ static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data)
static int cpia_pp_open(void *privdata)
{
struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata;
-
+
if (cam == NULL)
return -EINVAL;
-
+
if(cam->open_count == 0) {
if (parport_claim(cam->pdev)) {
DBG("failed to claim the port\n");
@@ -645,12 +645,12 @@ static int cpia_pp_open(void *privdata)
parport_write_control(cam->port, PARPORT_CONTROL_SELECT);
udelay(50);
parport_write_control(cam->port,
- PARPORT_CONTROL_SELECT
- | PARPORT_CONTROL_INIT);
+ PARPORT_CONTROL_SELECT
+ | PARPORT_CONTROL_INIT);
}
-
+
++cam->open_count;
-
+
return 0;
}
@@ -663,7 +663,7 @@ static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), vo
{
struct pp_cam_entry *cam = privdata;
int retval = 0;
-
+
if(cam->port->irq != PARPORT_IRQ_NONE) {
INIT_WORK(&cam->cb_task, cb, cbdata);
} else {
@@ -707,9 +707,9 @@ static int cpia_pp_register(struct parport *port)
LOG("failed to allocate camera structure\n");
return -ENOMEM;
}
-
+
pdev = parport_register_device(port, "cpia_pp", NULL, NULL,
- NULL, 0, cam);
+ NULL, 0, cam);
if (!pdev) {
LOG("failed to parport_register_device\n");
@@ -753,19 +753,19 @@ static void cpia_pp_detach (struct parport *port)
}
cpia = NULL;
}
- spin_unlock( &cam_list_lock_pp );
+ spin_unlock( &cam_list_lock_pp );
if (!cpia) {
DBG("cpia_pp_detach failed to find cam_data in cam_list\n");
return;
}
-
- cam = (struct pp_cam_entry *) cpia->lowlevel_data;
+
+ cam = (struct pp_cam_entry *) cpia->lowlevel_data;
cpia_unregister_camera(cpia);
- if(cam->open_count > 0)
+ if(cam->open_count > 0)
cpia_pp_close(cam);
parport_unregister_device(cam->pdev);
- cpia->lowlevel_data = NULL;
+ cpia->lowlevel_data = NULL;
kfree(cam);
}
@@ -805,14 +805,14 @@ static struct parport_driver cpia_pp_driver = {
int cpia_pp_init(void)
{
- printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
+ printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER);
if(parport_nr[0] == PPCPIA_PARPORT_OFF) {
printk(" disabled\n");
return 0;
}
-
+
spin_lock_init( &cam_list_lock_pp );
if (parport_register_driver (&cpia_pp_driver)) {
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
index 03275c37c5d..9c49a4b0011 100644
--- a/drivers/media/video/cpia_usb.c
+++ b/drivers/media/video/cpia_usb.c
@@ -22,7 +22,7 @@
*/
/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */
-/* #define _CPIA_DEBUG_ 1 */
+/* #define _CPIA_DEBUG_ 1 */
#include <linux/module.h>
#include <linux/kernel.h>
@@ -85,7 +85,7 @@ struct usb_cpia {
static int cpia_usb_open(void *privdata);
static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata),
- void *cbdata);
+ void *cbdata);
static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data);
static int cpia_usb_streamStart(void *privdata);
static int cpia_usb_streamStop(void *privdata);
@@ -127,7 +127,7 @@ static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs)
ucpia->workbuff->status = FRAME_READING;
ucpia->workbuff->length = 0;
}
-
+
for (i = 0; i < urb->number_of_packets; i++) {
int n = urb->iso_frame_desc[i].actual_length;
int st = urb->iso_frame_desc[i].status;
@@ -141,9 +141,9 @@ static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs)
printk(KERN_DEBUG "cpia: scratch buf overflow!scr_len: %d, n: %d\n", ucpia->workbuff->length, n);
return;
}
-
+
if (n) {
- if ((ucpia->workbuff->length > 0) ||
+ if ((ucpia->workbuff->length > 0) ||
(0x19 == cdata[0] && 0x68 == cdata[1])) {
memcpy(ucpia->workbuff->data + ucpia->workbuff->length, cdata, n);
ucpia->workbuff->length += n;
@@ -160,7 +160,7 @@ static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs)
ucpia->workbuff = ucpia->workbuff->next;
ucpia->workbuff->status = FRAME_EMPTY;
ucpia->workbuff->length = 0;
-
+
if (waitqueue_active(&ucpia->wq_stream))
wake_up_interruptible(&ucpia->wq_stream);
}
@@ -178,7 +178,7 @@ static int cpia_usb_open(void *privdata)
struct usb_cpia *ucpia = (struct usb_cpia *) privdata;
struct urb *urb;
int ret, retval = 0, fx, err;
-
+
if (!ucpia)
return -EINVAL;
@@ -191,7 +191,7 @@ static int cpia_usb_open(void *privdata)
retval = -EINVAL;
goto error_0;
}
-
+
ret = usb_set_interface(ucpia->dev, ucpia->iface, 3);
if (ret < 0) {
printk(KERN_ERR "cpia_usb_open: usb_set_interface error (ret = %d)\n", ret);
@@ -286,7 +286,7 @@ error_1:
error_0:
kfree (ucpia->sbuf[0].data);
ucpia->sbuf[0].data = NULL;
-
+
return retval;
}
@@ -307,7 +307,7 @@ static int WritePacket(struct usb_device *udev, const u8 *packet, u8 *buf, size_
return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
packet[1] + (packet[0] << 8),
USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- packet[2] + (packet[3] << 8),
+ packet[2] + (packet[3] << 8),
packet[4] + (packet[5] << 8), buf, size, 1000);
}
@@ -324,7 +324,7 @@ static int ReadPacket(struct usb_device *udev, u8 *packet, u8 *buf, size_t size)
return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
packet[1] + (packet[0] << 8),
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- packet[2] + (packet[3] << 8),
+ packet[2] + (packet[3] << 8),
packet[4] + (packet[5] << 8), buf, size, 1000);
}
@@ -393,7 +393,7 @@ static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock)
if (!ucpia || !ucpia->present)
return -1;
-
+
if (ucpia->curbuff->status != FRAME_READY)
interruptible_sleep_on(&ucpia->wq_stream);
else
@@ -403,7 +403,7 @@ static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock)
if (!mybuff)
return -1;
-
+
if (mybuff->status != FRAME_READY || mybuff->length < 4) {
DBG("Something went wrong!\n");
return -1;
@@ -411,7 +411,7 @@ static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock)
memcpy(frame, mybuff->data, mybuff->length);
mybuff->status = FRAME_EMPTY;
-
+
/* DBG("read done, %d bytes, Header: %x/%x, Footer: %x%x%x%x\n", */
/* mybuff->length, frame[0], frame[1], */
/* frame[mybuff->length-4], frame[mybuff->length-3], */
@@ -447,7 +447,7 @@ static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
kfree(ucpia->sbuf[1].data);
ucpia->sbuf[1].data = NULL;
-
+
if (ucpia->sbuf[0].urb) {
usb_kill_urb(ucpia->sbuf[0].urb);
usb_free_urb(ucpia->sbuf[0].urb);
@@ -490,7 +490,7 @@ static int cpia_probe(struct usb_interface *intf,
struct usb_cpia *ucpia;
struct cam_data *cam;
int ret;
-
+
/* A multi-config CPiA camera? */
if (udev->descriptor.bNumConfigurations != 1)
return -ENODEV;
@@ -539,7 +539,7 @@ static int cpia_probe(struct usb_interface *intf,
/* Before register_camera, important */
ucpia->present = 1;
-
+
cam = cpia_register_camera(&cpia_usb_ops, ucpia);
if (!cam) {
LOG("failed to cpia_register_camera\n");
@@ -591,7 +591,7 @@ static void cpia_disconnect(struct usb_interface *intf)
struct cam_data *cam = usb_get_intfdata(intf);
struct usb_cpia *ucpia;
struct usb_device *udev;
-
+
usb_set_intfdata(intf, NULL);
if (!cam)
return;
@@ -600,7 +600,7 @@ static void cpia_disconnect(struct usb_interface *intf)
spin_lock( &cam_list_lock_usb );
list_del(&cam->cam_data_list);
spin_unlock( &cam_list_lock_usb );
-
+
ucpia->present = 0;
cpia_unregister_camera(cam);
@@ -631,7 +631,7 @@ static void cpia_disconnect(struct usb_interface *intf)
static int __init usb_cpia_init(void)
{
- printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
+ printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
CPIA_USB_MAJ_VER,CPIA_USB_MIN_VER,CPIA_USB_PATCH_VER);
spin_lock_init(&cam_list_lock_usb);
diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c
index 8739c64785e..de87247c74e 100644
--- a/drivers/media/video/cs53l32a.c
+++ b/drivers/media/video/cs53l32a.c
@@ -59,25 +59,25 @@ static int cs53l32a_read(struct i2c_client *client, u8 reg)
static int cs53l32a_command(struct i2c_client *client, unsigned int cmd,
void *arg)
{
- struct v4l2_audio *input = arg;
+ struct v4l2_routing *route = arg;
struct v4l2_control *ctrl = arg;
switch (cmd) {
- case VIDIOC_S_AUDIO:
+ case VIDIOC_INT_G_AUDIO_ROUTING:
+ route->input = (cs53l32a_read(client, 0x01) >> 4) & 3;
+ route->output = 0;
+ break;
+
+ case VIDIOC_INT_S_AUDIO_ROUTING:
/* There are 2 physical inputs, but the second input can be
placed in two modes, the first mode bypasses the PGA (gain),
the second goes through the PGA. Hence there are three
possible inputs to choose from. */
- if (input->index > 2) {
- v4l_err(client, "Invalid input %d.\n", input->index);
+ if (route->input > 2) {
+ v4l_err(client, "Invalid input %d.\n", route->input);
return -EINVAL;
}
- cs53l32a_write(client, 0x01, 0x01 + (input->index << 4));
- break;
-
- case VIDIOC_G_AUDIO:
- memset(input, 0, sizeof(*input));
- input->index = (cs53l32a_read(client, 0x01) >> 4) & 3;
+ cs53l32a_write(client, 0x01, 0x01 + (route->input << 4));
break;
case VIDIOC_G_CTRL:
diff --git a/drivers/media/video/cs8420.h b/drivers/media/video/cs8420.h
index 2b22f3a38de..621c0c6678e 100644
--- a/drivers/media/video/cs8420.h
+++ b/drivers/media/video/cs8420.h
@@ -20,7 +20,7 @@
#define __CS8420_H__
/* Initialization Sequence */
-
+
static __u8 init8420[] = {
1, 0x01, 2, 0x02, 3, 0x00, 4, 0x46,
5, 0x24, 6, 0x84, 18, 0x18, 19, 0x13,
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index cb9a7981e40..a4540e858f2 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -18,7 +18,6 @@
#include <linux/videodev2.h>
#include <linux/i2c.h>
-#include <media/audiochip.h>
#include <media/v4l2-common.h>
#include "cx25840.h"
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 8a257978056..a65b3cc4bf0 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -31,7 +31,6 @@
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/i2c.h>
-#include <media/audiochip.h>
#include <media/v4l2-common.h>
#include "cx25840.h"
@@ -176,9 +175,9 @@ static void cx25840_initialize(struct i2c_client *client, int loadfw)
cx25840_write(client, 0x4a5, 0x00);
cx25840_write(client, 0x402, 0x00);
/* 8. */
- cx25840_write(client, 0x401, 0x18);
- cx25840_write(client, 0x4a2, 0x10);
- cx25840_write(client, 0x402, 0x04);
+ cx25840_and_or(client, 0x401, ~0x18, 0);
+ cx25840_and_or(client, 0x4a2, ~0x10, 0x10);
+ /* steps 8c and 8d are done in change_input() */
/* 10. */
cx25840_write(client, 0x8d3, 0x1f);
cx25840_write(client, 0x8e3, 0x03);
@@ -209,6 +208,17 @@ static void input_change(struct i2c_client *client)
struct cx25840_state *state = i2c_get_clientdata(client);
v4l2_std_id std = cx25840_get_v4lstd(client);
+ /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */
+ if (std & V4L2_STD_SECAM) {
+ cx25840_write(client, 0x402, 0);
+ }
+ else {
+ cx25840_write(client, 0x402, 0x04);
+ cx25840_write(client, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
+ }
+ cx25840_and_or(client, 0x401, ~0x60, 0);
+ cx25840_and_or(client, 0x401, ~0x60, 0x60);
+
/* Note: perhaps V4L2_STD_PAL_M should be handled as V4L2_STD_NTSC
instead of V4L2_STD_PAL. Someone needs to test this. */
if (std & V4L2_STD_PAL) {
@@ -343,6 +353,15 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
}
}
+ /* Follow step 9 of section 3.16 in the cx25840 datasheet.
+ Without this PAL may display a vertical ghosting effect.
+ This happens for example with the Yuan MPC622. */
+ if (fmt >= 4 && fmt < 8) {
+ /* Set format to NTSC-M */
+ cx25840_and_or(client, 0x400, ~0xf, 1);
+ /* Turn off LCOMB */
+ cx25840_and_or(client, 0x47b, ~6, 0);
+ }
cx25840_and_or(client, 0x400, ~0xf, fmt);
cx25840_vbi_setup(client);
return 0;
@@ -359,7 +378,14 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
}
switch (fmt) {
- case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR;
+ case 0x1:
+ {
+ /* if the audio std is A2-M, then this is the South Korean
+ NTSC standard */
+ if (cx25840_read(client, 0x805) == 2)
+ return V4L2_STD_NTSC_M_KR;
+ return V4L2_STD_NTSC_M;
+ }
case 0x2: return V4L2_STD_NTSC_M_JP;
case 0x3: return V4L2_STD_NTSC_443;
case 0x4: return V4L2_STD_PAL;
@@ -737,16 +763,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
return set_input(client, state->vid_input, input->index);
}
- case VIDIOC_G_AUDIO:
- {
- struct v4l2_audio *input = arg;
-
- memset(input, 0, sizeof(*input));
- input->index = state->aud_input;
- input->capability = V4L2_AUDCAP_STEREO;
- break;
- }
-
case VIDIOC_S_FREQUENCY:
input_change(client);
break;
@@ -794,13 +810,14 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
bilingual -> lang1 */
cx25840_and_or(client, 0x809, ~0xf, 0x00);
break;
+ case V4L2_TUNER_MODE_STEREO:
case V4L2_TUNER_MODE_LANG1:
/* mono -> mono
stereo -> stereo
bilingual -> lang1 */
cx25840_and_or(client, 0x809, ~0xf, 0x04);
break;
- case V4L2_TUNER_MODE_STEREO:
+ case V4L2_TUNER_MODE_LANG1_LANG2:
/* mono -> mono
stereo -> stereo
bilingual -> lang1/lang2 */
@@ -808,7 +825,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
break;
case V4L2_TUNER_MODE_LANG2:
/* mono -> mono
- stereo ->stereo
+ stereo -> stereo
bilingual -> lang2 */
cx25840_and_or(client, 0x809, ~0xf, 0x01);
break;
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index e140996e6ee..ff0f72340d6 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -16,12 +16,13 @@ config VIDEO_CX88
module will be called cx8800
config VIDEO_CX88_ALSA
- tristate "ALSA DMA audio support"
+ tristate "Conexant 2388x DMA audio support"
depends on VIDEO_CX88 && SND && EXPERIMENTAL
select SND_PCM
---help---
This is a video4linux driver for direct (DMA) audio on
- Conexant 2388x based TV cards.
+ Conexant 2388x based TV cards using ALSA.
+
It only works with boards with function 01 enabled.
To check if your board supports, use lspci -n.
If supported, you should see 1471:8801 or 1471:8811
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 3170b8f72c6..f9d87b86492 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -303,7 +303,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip)
BUG_ON(!chip->dma_size);
dprintk(2,"Freeing buffer\n");
- videobuf_dma_pci_unmap(chip->pci, &chip->dma_risc);
+ videobuf_pci_dma_unmap(chip->pci, &chip->dma_risc);
videobuf_dma_free(&chip->dma_risc);
btcx_riscmem_free(chip->pci,&chip->buf->risc);
kfree(chip->buf);
@@ -429,7 +429,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE,
(PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT));
- videobuf_dma_pci_map(chip->pci,&buf->vb.dma);
+ videobuf_pci_dma_map(chip->pci,&buf->vb.dma);
cx88_risc_databuffer(chip->pci, &buf->risc,
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index a502a4d6e4a..e100d8ef369 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1341,7 +1341,7 @@ bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
enum v4l2_field field)
{
struct cx8802_fh *fh = q->priv_data;
- return cx8802_buf_prepare(fh->dev, (struct cx88_buffer*)vb, field);
+ return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);
}
static void
@@ -1354,8 +1354,7 @@ bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
static void
bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct cx8802_fh *fh = q->priv_data;
- cx88_free_buffer(fh->dev->pci, (struct cx88_buffer*)vb);
+ cx88_free_buffer(q, (struct cx88_buffer*)vb);
}
static struct videobuf_queue_ops blackbird_qops = {
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index c2cdbafdb77..2c3d9f1999b 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -213,13 +213,13 @@ int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
}
void
-cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf)
+cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
{
BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb,0,0);
- videobuf_dma_pci_unmap(pci, &buf->vb.dma);
+ videobuf_dma_unmap(q, &buf->vb.dma);
videobuf_dma_free(&buf->vb.dma);
- btcx_riscmem_free(pci, &buf->risc);
+ btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
buf->vb.state = STATE_NEEDS_INIT;
}
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index a9fc2695b15..f0ea9b5cdbc 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -90,7 +90,7 @@ static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
enum v4l2_field field)
{
struct cx8802_dev *dev = q->priv_data;
- return cx8802_buf_prepare(dev, (struct cx88_buffer*)vb,field);
+ return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field);
}
static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
@@ -101,8 +101,7 @@ static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct cx8802_dev *dev = q->priv_data;
- cx88_free_buffer(dev->pci, (struct cx88_buffer*)vb);
+ cx88_free_buffer(q, (struct cx88_buffer*)vb);
}
static struct videobuf_queue_ops dvb_qops = {
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index c79cc1d2bf8..7d16888b4a8 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -163,8 +163,8 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
/* ------------------------------------------------------------------ */
-int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf,
- enum v4l2_field field)
+int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
+ struct cx88_buffer *buf, enum v4l2_field field)
{
int size = dev->ts_packet_size * dev->ts_packet_count;
int rc;
@@ -179,7 +179,7 @@ int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf,
buf->vb.size = size;
buf->vb.field = field /*V4L2_FIELD_TOP*/;
- if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL)))
+ if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
goto fail;
cx88_risc_databuffer(dev->pci, &buf->risc,
buf->vb.dma.sglist,
@@ -189,36 +189,36 @@ int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf,
return 0;
fail:
- cx88_free_buffer(dev->pci,buf);
+ cx88_free_buffer(q,buf);
return rc;
}
void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
{
struct cx88_buffer *prev;
- struct cx88_dmaqueue *q = &dev->mpegq;
+ struct cx88_dmaqueue *cx88q = &dev->mpegq;
dprintk( 1, "cx8802_buf_queue\n" );
/* add jump to stopper */
buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
- buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
- if (list_empty(&q->active)) {
+ if (list_empty(&cx88q->active)) {
dprintk( 0, "queue is empty - first active\n" );
- list_add_tail(&buf->vb.queue,&q->active);
- cx8802_start_dma(dev, q, buf);
+ list_add_tail(&buf->vb.queue,&cx88q->active);
+ cx8802_start_dma(dev, cx88q, buf);
buf->vb.state = STATE_ACTIVE;
- buf->count = q->count++;
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+ buf->count = cx88q->count++;
+ mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(0,"[%p/%d] %s - first active\n",
buf, buf->vb.i, __FUNCTION__);
} else {
dprintk( 1, "queue is not empty - append to active\n" );
- prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
- list_add_tail(&buf->vb.queue,&q->active);
+ prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue);
+ list_add_tail(&buf->vb.queue,&cx88q->active);
buf->vb.state = STATE_ACTIVE;
- buf->count = q->count++;
+ buf->count = cx88q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk( 1, "[%p/%d] %s - append to active\n",
buf, buf->vb.i, __FUNCTION__);
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index da8d97ce0c4..641a0c5a649 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -885,6 +885,7 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP);
break;
case V4L2_TUNER_MODE_STEREO:
+ case V4L2_TUNER_MODE_LANG1_LANG2:
set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO);
break;
}
@@ -905,6 +906,7 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
EN_NICAM_FORCE_MONO2);
break;
case V4L2_TUNER_MODE_STEREO:
+ case V4L2_TUNER_MODE_LANG1_LANG2:
set_audio_standard_NICAM(core,
EN_NICAM_FORCE_STEREO);
break;
@@ -926,6 +928,7 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
EN_A2_FORCE_MONO2);
break;
case V4L2_TUNER_MODE_STEREO:
+ case V4L2_TUNER_MODE_LANG1_LANG2:
set_audio_standard_A2(core,
EN_A2_FORCE_STEREO);
break;
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
index 9bc6c899558..846faadc9f1 100644
--- a/drivers/media/video/cx88/cx88-vbi.c
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -175,7 +175,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
buf->vb.size = size;
buf->vb.field = V4L2_FIELD_SEQ_TB;
- if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL)))
+ if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
goto fail;
cx88_risc_buffer(dev->pci, &buf->risc,
buf->vb.dma.sglist,
@@ -187,7 +187,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
return 0;
fail:
- cx88_free_buffer(dev->pci,buf);
+ cx88_free_buffer(q,buf);
return rc;
}
@@ -227,9 +227,8 @@ vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
- struct cx8800_fh *fh = q->priv_data;
- cx88_free_buffer(fh->dev->pci,buf);
+ cx88_free_buffer(q,buf);
}
struct videobuf_queue_ops cx8800_vbi_qops = {
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 6c97aa740d2..72a417b3174 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -564,7 +564,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
if (STATE_NEEDS_INIT == buf->vb.state) {
init_buffer = 1;
- if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL)))
+ if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
goto fail;
}
@@ -614,7 +614,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
return 0;
fail:
- cx88_free_buffer(dev->pci,buf);
+ cx88_free_buffer(q,buf);
return rc;
}
@@ -671,9 +671,8 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
- struct cx8800_fh *fh = q->priv_data;
- cx88_free_buffer(fh->dev->pci,buf);
+ cx88_free_buffer(q,buf);
}
static struct videobuf_queue_ops cx8800_video_qops = {
@@ -1251,9 +1250,17 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
{
int err;
- dprintk(2, "CORE IOCTL: 0x%x\n", cmd );
- if (video_debug > 1)
- v4l_print_ioctl(core->name,cmd);
+ if (video_debug) {
+ if (video_debug > 1) {
+ if (_IOC_DIR(cmd) & _IOC_WRITE)
+ v4l_printk_ioctl_arg("cx88(w)",cmd, arg);
+ else if (!_IOC_DIR(cmd) & _IOC_READ) {
+ v4l_print_ioctl("cx88", cmd);
+ }
+ } else
+ v4l_print_ioctl(core->name,cmd);
+
+ }
switch (cmd) {
/* ---------- tv norms ---------- */
@@ -1460,7 +1467,19 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
static int video_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- return video_usercopy(inode, file, cmd, arg, video_do_ioctl);
+ int retval;
+
+ retval=video_usercopy(inode, file, cmd, arg, video_do_ioctl);
+
+ if (video_debug > 1) {
+ if (retval < 0) {
+ v4l_print_ioctl("cx88(err)", cmd);
+ printk(KERN_DEBUG "cx88(err): errcode=%d\n",retval);
+ } else if (_IOC_DIR(cmd) & _IOC_READ)
+ v4l_printk_ioctl_arg("cx88(r)",cmd, (void *)arg);
+ }
+
+ return retval;
}
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index cfa8668784b..326a25f147f 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -27,7 +27,6 @@
#include <media/tuner.h>
#include <media/tveeprom.h>
-#include <media/audiochip.h>
#include <media/video-buf.h>
#include <media/video-buf-dvb.h>
@@ -485,7 +484,7 @@ extern int
cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
u32 reg, u32 mask, u32 value);
extern void
-cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf);
+cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf);
extern void cx88_risc_disasm(struct cx88_core *core,
struct btcx_riscmem *risc);
@@ -577,8 +576,8 @@ void cx88_ir_irq(struct cx88_core *core);
/* ----------------------------------------------------------- */
/* cx88-mpeg.c */
-int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf,
- enum v4l2_field field);
+int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev,
+ struct cx88_buffer *buf, enum v4l2_field field);
void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
void cx8802_cancel_buffers(struct cx8802_dev *dev);
diff --git a/drivers/usb/media/dabfirmware.h b/drivers/media/video/dabfirmware.h
index d14d803566a..d14d803566a 100644
--- a/drivers/usb/media/dabfirmware.h
+++ b/drivers/media/video/dabfirmware.h
diff --git a/drivers/usb/media/dabusb.c b/drivers/media/video/dabusb.c
index 1774ab7a40d..b9ba95f5e02 100644
--- a/drivers/usb/media/dabusb.c
+++ b/drivers/media/video/dabusb.c
@@ -86,7 +86,7 @@ static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_
return ret;
}
/*-------------------------------------------------------------------*/
-#ifdef DEBUG
+#ifdef DEBUG
static void dump_urb (struct urb *urb)
{
dbg("urb :%p", urb);
@@ -136,7 +136,7 @@ static int dabusb_free_queue (struct list_head *q)
for (p = q->next; p != q;) {
b = list_entry (p, buff_t, buff_list);
-#ifdef DEBUG
+#ifdef DEBUG
dump_urb(b->purb);
#endif
kfree(b->purb->transfer_buffer);
@@ -287,7 +287,7 @@ static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
}
}
-
+
if( ret == -EPIPE ) {
warn("CLEAR_FEATURE request to remove STALL condition.");
if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
@@ -328,7 +328,7 @@ static int dabusb_loadmem (pdabusb_t s, const char *fname)
PINTEL_HEX_RECORD ptr = firmware;
dbg("Enter dabusb_loadmem (internal)");
-
+
ret = dabusb_8051_reset (s, 1);
while (ptr->Type == 0) {
@@ -449,7 +449,7 @@ static int dabusb_startrek (pdabusb_t s)
if (!list_empty (&s->free_buff_list)) {
pbuff_t end;
int ret;
-
+
while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {
dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list);
@@ -506,7 +506,7 @@ static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, l
err("error: rec_buf_list is empty");
goto err;
}
-
+
b = list_entry (s->rec_buff_list.next, buff_t, buff_list);
purb = b->purb;
@@ -783,9 +783,9 @@ static void dabusb_disconnect (struct usb_interface *intf)
pdabusb_t s = usb_get_intfdata (intf);
dbg("dabusb_disconnect");
-
+
init_waitqueue_entry(&__wait, current);
-
+
usb_set_intfdata (intf, NULL);
if (s) {
usb_deregister_dev (intf, &dabusb_class);
@@ -797,7 +797,7 @@ static void dabusb_disconnect (struct usb_interface *intf)
schedule();
current->state = TASK_RUNNING;
remove_wait_queue(&s->remove_ok, &__wait);
-
+
s->usbdev = NULL;
s->overruns = 0;
}
diff --git a/drivers/usb/media/dabusb.h b/drivers/media/video/dabusb.h
index 96b03e4af8b..00eb34c863e 100644
--- a/drivers/usb/media/dabusb.h
+++ b/drivers/media/video/dabusb.h
@@ -10,7 +10,7 @@ typedef struct
#define DABUSB_VERSION 0x1000
#define IOCTL_DAB_BULK _IOWR('d', 0x30, bulk_transfer_t)
#define IOCTL_DAB_OVERRUNS _IOR('d', 0x15, int)
-#define IOCTL_DAB_VERSION _IOR('d', 0x3f, int)
+#define IOCTL_DAB_VERSION _IOR('d', 0x3f, int)
#ifdef __KERNEL__
@@ -36,7 +36,7 @@ typedef struct
struct list_head rec_buff_list;
} dabusb_t,*pdabusb_t;
-typedef struct
+typedef struct
{
pdabusb_t s;
struct urb *purb;
diff --git a/drivers/usb/media/dsbr100.c b/drivers/media/video/dsbr100.c
index 25646804d5b..3b4e9985c3d 100644
--- a/drivers/usb/media/dsbr100.c
+++ b/drivers/media/video/dsbr100.c
@@ -37,28 +37,28 @@
Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing
Version 0.30:
- Markus: Updates for 2.5.x kernel and more ISO compliant source
+ Markus: Updates for 2.5.x kernel and more ISO compliant source
Version 0.25:
- PSL and Markus: Cleanup, radio now doesn't stop on device close
+ PSL and Markus: Cleanup, radio now doesn't stop on device close
Version 0.24:
- Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
+ Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
right. Some minor cleanup, improved standalone compilation
Version 0.23:
- Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
+ Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
Version 0.22:
- Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns,
+ Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns,
thanks to Mike Cox for pointing the problem out.
Version 0.21:
- Markus: Minor cleanup, warnings if something goes wrong, lame attempt
+ Markus: Minor cleanup, warnings if something goes wrong, lame attempt
to adhere to Documentation/CodingStyle
- Version 0.2:
- Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
+ Version 0.2:
+ Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
Markus: Copyright clarification
Version 0.01: Markus: initial release
@@ -163,11 +163,11 @@ static struct usb_driver usb_dsbr100_driver = {
static int dsbr100_start(dsbr100_device *radio)
{
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
- USB_REQ_GET_STATUS,
+ USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
- DSB100_ONOFF,
+ DSB100_ONOFF,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x01, 0x00, radio->transfer_buffer, 8, 300)<0)
return -1;
@@ -179,11 +179,11 @@ static int dsbr100_start(dsbr100_device *radio)
static int dsbr100_stop(dsbr100_device *radio)
{
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
- USB_REQ_GET_STATUS,
+ USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
- DSB100_ONOFF,
+ DSB100_ONOFF,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x00, 0x00, radio->transfer_buffer, 8, 300)<0)
return -1;
@@ -195,16 +195,16 @@ static int dsbr100_setfreq(dsbr100_device *radio, int freq)
{
freq = (freq/16*80)/1000+856;
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
- DSB100_TUNE,
+ DSB100_TUNE,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- (freq>>8)&0x00ff, freq&0xff,
+ (freq>>8)&0x00ff, freq&0xff,
radio->transfer_buffer, 8, 300)<0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
- USB_REQ_GET_STATUS,
+ USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
- USB_REQ_GET_STATUS,
+ USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
radio->stereo = -1;
@@ -219,7 +219,7 @@ sees a stereo signal or not. Pity. */
static void dsbr100_getstat(dsbr100_device *radio)
{
if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
- USB_REQ_GET_STATUS,
+ USB_REQ_GET_STATUS,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x00 , 0x24, radio->transfer_buffer, 8, 300)<0)
radio->stereo = -1;
@@ -232,7 +232,7 @@ static void dsbr100_getstat(dsbr100_device *radio)
/* check if the device is present and register with v4l and
usb if it is */
-static int usb_dsbr100_probe(struct usb_interface *intf,
+static int usb_dsbr100_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
dsbr100_device *radio;
@@ -243,7 +243,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
kfree(radio);
return -ENOMEM;
}
- memcpy(radio->videodev, &dsbr100_videodev_template,
+ memcpy(radio->videodev, &dsbr100_videodev_template,
sizeof(dsbr100_videodev_template));
radio->removed = 0;
radio->users = 0;
@@ -310,7 +310,7 @@ static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,
struct video_tuner *v = arg;
dsbr100_getstat(radio);
- if(v->tuner) /* Only 1 tuner */
+ if(v->tuner) /* Only 1 tuner */
return -EINVAL;
v->rangelow = FREQ_MIN*FREQ_MUL;
v->rangehigh = FREQ_MAX*FREQ_MUL;
@@ -355,12 +355,12 @@ static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,
v->volume = 1;
v->step = 1;
strcpy(v->name, "Radio");
- return 0;
+ return 0;
}
case VIDIOCSAUDIO: {
struct video_audio *v = arg;
- if (v->audio)
+ if (v->audio)
return -EINVAL;
if (v->flags&VIDEO_AUDIO_MUTE) {
if (dsbr100_stop(radio)==-1)
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 4e22fc4889e..f62fd706b45 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -28,10 +28,10 @@
#include <linux/i2c.h>
#include <linux/usb.h>
#include <media/tuner.h>
-#include <media/audiochip.h>
+#include <media/msp3400.h>
#include <media/tveeprom.h>
+#include <media/audiochip.h>
#include <media/v4l2-common.h>
-#include "msp3400.h"
#include "em28xx.h"
@@ -147,11 +147,12 @@ struct em28xx_board em28xx_boards[] = {
.input = {{
.type = EM28XX_VMUX_TELEVISION,
.vmux = 0,
- .amux = 6,
+ .amux = MSP_INPUT_DEFAULT,
},{
.type = EM28XX_VMUX_SVIDEO,
.vmux = 2,
- .amux = 1,
+ .amux = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
+ MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART),
}},
},
[EM2820_BOARD_MSI_VOX_USB_2] = {
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 780342f7b23..dfba33d0fa6 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -38,6 +38,7 @@
#include "em28xx.h"
#include <media/tuner.h>
#include <media/v4l2-common.h>
+#include <media/msp3400.h>
#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
"Markus Rechberger <mrechberger@gmail.com>, " \
@@ -216,9 +217,14 @@ static void video_mux(struct em28xx *dev, int index)
em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput);
if (dev->has_msp34xx) {
+ struct v4l2_routing route;
+
if (dev->i2s_speed)
em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
- em28xx_i2c_call_clients(dev, VIDIOC_S_AUDIO, &dev->ctl_ainput);
+ route.input = dev->ctl_ainput;
+ route.output = MSP_OUTPUT(MSP_OUT_SCART1_DA);
+ /* Note: this is msp3400 specific */
+ em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
ainput = EM28XX_AUDIO_SRC_TUNER;
em28xx_audio_source(dev, ainput);
} else {
diff --git a/drivers/media/video/et61x251/Makefile b/drivers/media/video/et61x251/Makefile
new file mode 100644
index 00000000000..2ff4db9ec88
--- /dev/null
+++ b/drivers/media/video/et61x251/Makefile
@@ -0,0 +1,4 @@
+et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o
+
+obj-$(CONFIG_USB_ET61X251) += et61x251.o
+
diff --git a/drivers/usb/media/et61x251.h b/drivers/media/video/et61x251/et61x251.h
index eee8afc9be7..2e5ca403248 100644
--- a/drivers/usb/media/et61x251.h
+++ b/drivers/media/video/et61x251/et61x251.h
@@ -180,7 +180,7 @@ et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id)
void
et61x251_attach_sensor(struct et61x251_device* cam,
- struct et61x251_sensor* sensor)
+ struct et61x251_sensor* sensor)
{
memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor));
}
@@ -199,7 +199,7 @@ do { \
dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
else if ((level) >= 3) \
dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args); \
+ __FUNCTION__, __LINE__ , ## args); \
} \
} while (0)
# define KDBG(level, fmt, args...) \
@@ -209,7 +209,7 @@ do { \
pr_info("et61x251: " fmt "\n", ## args); \
else if ((level) == 3) \
pr_debug("et61x251: [%s:%d] " fmt "\n", __FUNCTION__, \
- __LINE__ , ## args); \
+ __LINE__ , ## args); \
} \
} while (0)
# define V4LDBG(level, name, cmd) \
@@ -226,7 +226,7 @@ do { \
#undef PDBG
#define PDBG(fmt, args...) \
dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args)
+ __FUNCTION__, __LINE__ , ## args)
#undef PDBGG
#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
diff --git a/drivers/usb/media/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index 7cc01b828b3..dfc9dd732c9 100644
--- a/drivers/usb/media/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -44,7 +44,7 @@
/*****************************************************************************/
#define ET61X251_MODULE_NAME "V4L2 driver for ET61X[12]51 " \
- "PC Camera Controllers"
+ "PC Camera Controllers"
#define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia"
#define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define ET61X251_MODULE_LICENSE "GPL"
@@ -63,68 +63,68 @@ MODULE_LICENSE(ET61X251_MODULE_LICENSE);
static short video_nr[] = {[0 ... ET61X251_MAX_DEVICES-1] = -1};
module_param_array(video_nr, short, NULL, 0444);
MODULE_PARM_DESC(video_nr,
- "\n<-1|n[,...]> Specify V4L2 minor mode number."
- "\n -1 = use next available (default)"
- "\n n = use minor number n (integer >= 0)"
- "\nYou can specify up to "
- __MODULE_STRING(ET61X251_MAX_DEVICES) " cameras this way."
- "\nFor example:"
- "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
- "\nthe second registered camera and use auto for the first"
- "\none and for every other camera."
- "\n");
+ "\n<-1|n[,...]> Specify V4L2 minor mode number."
+ "\n -1 = use next available (default)"
+ "\n n = use minor number n (integer >= 0)"
+ "\nYou can specify up to "
+ __MODULE_STRING(ET61X251_MAX_DEVICES) " cameras this way."
+ "\nFor example:"
+ "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
+ "\nthe second registered camera and use auto for the first"
+ "\none and for every other camera."
+ "\n");
static short force_munmap[] = {[0 ... ET61X251_MAX_DEVICES-1] =
- ET61X251_FORCE_MUNMAP};
+ ET61X251_FORCE_MUNMAP};
module_param_array(force_munmap, bool, NULL, 0444);
MODULE_PARM_DESC(force_munmap,
- "\n<0|1[,...]> Force the application to unmap previously"
- "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
- "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
- "\nthis feature. This parameter is specific for each"
- "\ndetected camera."
- "\n 0 = do not force memory unmapping"
- "\n 1 = force memory unmapping (save memory)"
- "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
- "\n");
+ "\n<0|1[,...]> Force the application to unmap previously"
+ "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
+ "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
+ "\nthis feature. This parameter is specific for each"
+ "\ndetected camera."
+ "\n 0 = do not force memory unmapping"
+ "\n 1 = force memory unmapping (save memory)"
+ "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+ "\n");
static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] =
- ET61X251_FRAME_TIMEOUT};
+ ET61X251_FRAME_TIMEOUT};
module_param_array(frame_timeout, uint, NULL, 0644);
MODULE_PARM_DESC(frame_timeout,
- "\n<n[,...]> Timeout for a video frame in seconds."
- "\nThis parameter is specific for each detected camera."
- "\nDefault value is "
- __MODULE_STRING(ET61X251_FRAME_TIMEOUT)"."
- "\n");
+ "\n<n[,...]> Timeout for a video frame in seconds."
+ "\nThis parameter is specific for each detected camera."
+ "\nDefault value is "
+ __MODULE_STRING(ET61X251_FRAME_TIMEOUT)"."
+ "\n");
#ifdef ET61X251_DEBUG
static unsigned short debug = ET61X251_DEBUG_LEVEL;
module_param(debug, ushort, 0644);
MODULE_PARM_DESC(debug,
- "\n<n> Debugging information level, from 0 to 3:"
- "\n0 = none (use carefully)"
- "\n1 = critical errors"
- "\n2 = significant informations"
- "\n3 = more verbose messages"
- "\nLevel 3 is useful for testing only, when only "
- "one device is used."
- "\nDefault value is "__MODULE_STRING(ET61X251_DEBUG_LEVEL)"."
- "\n");
+ "\n<n> Debugging information level, from 0 to 3:"
+ "\n0 = none (use carefully)"
+ "\n1 = critical errors"
+ "\n2 = significant informations"
+ "\n3 = more verbose messages"
+ "\nLevel 3 is useful for testing only, when only "
+ "one device is used."
+ "\nDefault value is "__MODULE_STRING(ET61X251_DEBUG_LEVEL)"."
+ "\n");
#endif
/*****************************************************************************/
static u32
et61x251_request_buffers(struct et61x251_device* cam, u32 count,
- enum et61x251_io_method io)
+ enum et61x251_io_method io)
{
struct v4l2_pix_format* p = &(cam->sensor.pix_format);
struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
const size_t imagesize = cam->module_param.force_munmap ||
- io == IO_READ ?
- (p->width * p->height * p->priv) / 8 :
- (r->width * r->height * p->priv) / 8;
+ io == IO_READ ?
+ (p->width * p->height * p->priv) / 8 :
+ (r->width * r->height * p->priv) / 8;
void* buff = NULL;
u32 i;
@@ -216,7 +216,7 @@ int et61x251_write_reg(struct et61x251_device* cam, u8 value, u16 index)
*buff = value;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
- 0, index, buff, 1, ET61X251_CTRL_TIMEOUT);
+ 0, index, buff, 1, ET61X251_CTRL_TIMEOUT);
if (res < 0) {
DBG(3, "Failed to write a register (value 0x%02X, index "
"0x%02X, error %d)", value, index, res);
@@ -234,7 +234,7 @@ int et61x251_read_reg(struct et61x251_device* cam, u16 index)
int res;
res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
- 0, index, buff, 1, ET61X251_CTRL_TIMEOUT);
+ 0, index, buff, 1, ET61X251_CTRL_TIMEOUT);
if (res < 0)
DBG(3, "Failed to read a register (index 0x%02X, error %d)",
index, res);
@@ -269,7 +269,7 @@ et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor)
int
et61x251_i2c_try_read(struct et61x251_device* cam,
- struct et61x251_sensor* sensor, u8 address)
+ struct et61x251_sensor* sensor, u8 address)
{
struct usb_device* udev = cam->usbdev;
u8* data = cam->control_buffer;
@@ -280,14 +280,14 @@ et61x251_i2c_try_read(struct et61x251_device* cam,
data[2] = cam->sensor.rsta | 0x10;
data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02);
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
- 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT);
+ 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT);
if (res < 0)
err += res;
err += et61x251_i2c_wait(cam, sensor);
res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
- 0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT);
+ 0, 0x80, data, 8, ET61X251_CTRL_TIMEOUT);
if (res < 0)
err += res;
@@ -302,7 +302,7 @@ et61x251_i2c_try_read(struct et61x251_device* cam,
int
et61x251_i2c_try_write(struct et61x251_device* cam,
- struct et61x251_sensor* sensor, u8 address, u8 value)
+ struct et61x251_sensor* sensor, u8 address, u8 value)
{
struct usb_device* udev = cam->usbdev;
u8* data = cam->control_buffer;
@@ -312,13 +312,13 @@ et61x251_i2c_try_write(struct et61x251_device* cam,
data[1] = cam->sensor.i2c_slave_id;
data[2] = cam->sensor.rsta | 0x12;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
- 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT);
+ 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT);
if (res < 0)
err += res;
data[0] = value;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
- 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT);
+ 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT);
if (res < 0)
err += res;
@@ -335,8 +335,8 @@ et61x251_i2c_try_write(struct et61x251_device* cam,
int
et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2,
- u8 data3, u8 data4, u8 data5, u8 data6, u8 data7,
- u8 data8, u8 address)
+ u8 data3, u8 data4, u8 data5, u8 data6, u8 data7,
+ u8 data8, u8 address)
{
struct usb_device* udev = cam->usbdev;
u8* data = cam->control_buffer;
@@ -350,7 +350,7 @@ et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2,
data[5] = data7;
data[6] = data8;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
- 0, 0x81, data, n-1, ET61X251_CTRL_TIMEOUT);
+ 0, 0x81, data, n-1, ET61X251_CTRL_TIMEOUT);
if (res < 0)
err += res;
@@ -358,14 +358,14 @@ et61x251_i2c_raw_write(struct et61x251_device* cam, u8 n, u8 data1, u8 data2,
data[1] = cam->sensor.i2c_slave_id;
data[2] = cam->sensor.rsta | 0x02 | (n << 4);
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
- 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT);
+ 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT);
if (res < 0)
err += res;
/* Start writing through the serial interface */
data[0] = data1;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41,
- 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT);
+ 0, 0x80, data, 1, ET61X251_CTRL_TIMEOUT);
if (res < 0)
err += res;
@@ -432,11 +432,11 @@ static void et61x251_urb_complete(struct urb *urb, struct pt_regs* regs)
if (!(*f))
(*f) = list_entry(cam->inqueue.next, struct et61x251_frame_t,
- frame);
+ frame);
imagesize = (cam->sensor.pix_format.width *
- cam->sensor.pix_format.height *
- cam->sensor.pix_format.priv) / 8;
+ cam->sensor.pix_format.height *
+ cam->sensor.pix_format.priv) / 8;
for (i = 0; i < urb->number_of_packets; i++) {
unsigned int len, status;
@@ -476,7 +476,7 @@ start_of_frame:
if ((*f)->state == F_GRABBING) {
if (sof && (*f)->buf.bytesused) {
if (cam->sensor.pix_format.pixelformat ==
- V4L2_PIX_FMT_ET61X251)
+ V4L2_PIX_FMT_ET61X251)
goto end_of_frame;
else {
DBG(3, "Not expected SOF detected "
@@ -508,8 +508,8 @@ end_of_frame:
list_move_tail(&(*f)->frame, &cam->outqueue);
if (!list_empty(&cam->inqueue))
(*f) = list_entry(cam->inqueue.next,
- struct et61x251_frame_t,
- frame);
+ struct et61x251_frame_t,
+ frame);
else
(*f) = NULL;
spin_unlock(&cam->queue_lock);
@@ -521,7 +521,7 @@ end_of_frame:
if (sof &&
cam->sensor.pix_format.pixelformat ==
- V4L2_PIX_FMT_ET61X251)
+ V4L2_PIX_FMT_ET61X251)
goto start_of_frame;
}
}
@@ -544,15 +544,15 @@ static int et61x251_start_transfer(struct et61x251_device* cam)
struct usb_device *udev = cam->usbdev;
struct urb* urb;
const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832,
- 864, 896, 920, 956, 980, 1000,
- 1022};
+ 864, 896, 920, 956, 980, 1000,
+ 1022};
const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING];
s8 i, j;
int err = 0;
for (i = 0; i < ET61X251_URBS; i++) {
cam->transfer_buffer[i] = kzalloc(ET61X251_ISO_PACKETS * psz,
- GFP_KERNEL);
+ GFP_KERNEL);
if (!cam->transfer_buffer[i]) {
err = -ENOMEM;
DBG(1, "Not enough memory");
@@ -653,9 +653,9 @@ static int et61x251_stream_interrupt(struct et61x251_device* cam)
cam->stream = STREAM_INTERRUPT;
timeout = wait_event_timeout(cam->wait_stream,
- (cam->stream == STREAM_OFF) ||
- (cam->state & DEV_DISCONNECTED),
- ET61X251_URB_TIMEOUT);
+ (cam->stream == STREAM_OFF) ||
+ (cam->state & DEV_DISCONNECTED),
+ ET61X251_URB_TIMEOUT);
if (cam->state & DEV_DISCONNECTED)
return -ENODEV;
else if (cam->stream != STREAM_OFF) {
@@ -699,7 +699,7 @@ static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count)
/*
NOTE 1: being inside one of the following methods implies that the v4l
- device exists for sure (see kobjects and reference counters)
+ device exists for sure (see kobjects and reference counters)
NOTE 2: buffers are PAGE_SIZE long
*/
@@ -964,13 +964,13 @@ et61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,
- et61x251_show_reg, et61x251_store_reg);
+ et61x251_show_reg, et61x251_store_reg);
static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR,
- et61x251_show_val, et61x251_store_val);
+ et61x251_show_val, et61x251_store_val);
static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
- et61x251_show_i2c_reg, et61x251_store_i2c_reg);
+ et61x251_show_i2c_reg, et61x251_store_i2c_reg);
static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
- et61x251_show_i2c_val, et61x251_store_i2c_val);
+ et61x251_show_i2c_val, et61x251_store_i2c_val);
static void et61x251_create_sysfs(struct et61x251_device* cam)
@@ -990,7 +990,7 @@ static void et61x251_create_sysfs(struct et61x251_device* cam)
static int
et61x251_set_pix_format(struct et61x251_device* cam,
- struct v4l2_pix_format* pix)
+ struct v4l2_pix_format* pix)
{
int r, err = 0;
@@ -1007,7 +1007,7 @@ et61x251_set_pix_format(struct et61x251_device* cam,
static int
et61x251_set_compression(struct et61x251_device* cam,
- struct v4l2_jpegcompression* compression)
+ struct v4l2_jpegcompression* compression)
{
int r, err = 0;
@@ -1049,9 +1049,9 @@ et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect)
{
struct et61x251_sensor* s = &cam->sensor;
u16 fmw_sx = (u16)(rect->left - s->cropcap.bounds.left +
- s->active_pixel.left),
+ s->active_pixel.left),
fmw_sy = (u16)(rect->top - s->cropcap.bounds.top +
- s->active_pixel.top),
+ s->active_pixel.top),
fmw_length = (u16)(rect->width),
fmw_height = (u16)(rect->height);
int err = 0;
@@ -1061,8 +1061,8 @@ et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect)
err += et61x251_write_reg(cam, fmw_length & 0xff, 0x6b);
err += et61x251_write_reg(cam, fmw_height & 0xff, 0x6c);
err += et61x251_write_reg(cam, (fmw_sx >> 8) | ((fmw_sy & 0x300) >> 6)
- | ((fmw_length & 0x300) >> 4)
- | ((fmw_height & 0x300) >> 2), 0x6d);
+ | ((fmw_length & 0x300) >> 4)
+ | ((fmw_height & 0x300) >> 2), 0x6d);
if (err)
return -EIO;
@@ -1203,8 +1203,8 @@ static int et61x251_open(struct inode* inode, struct file* filp)
}
mutex_unlock(&cam->dev_mutex);
err = wait_event_interruptible_exclusive(cam->open,
- cam->state & DEV_DISCONNECTED
- || !cam->users);
+ cam->state & DEV_DISCONNECTED
+ || !cam->users);
if (err) {
up_read(&et61x251_disconnect);
return err;
@@ -1277,7 +1277,7 @@ static int et61x251_release(struct inode* inode, struct file* filp)
static ssize_t
et61x251_read(struct file* filp, char __user * buf,
- size_t count, loff_t* f_pos)
+ size_t count, loff_t* f_pos)
{
struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
struct et61x251_frame_t* f, * i;
@@ -1310,7 +1310,7 @@ et61x251_read(struct file* filp, char __user * buf,
if (cam->io == IO_NONE) {
if (!et61x251_request_buffers(cam, cam->nreadbuffers,
- IO_READ)) {
+ IO_READ)) {
DBG(1, "read() failed, not enough memory");
mutex_unlock(&cam->fileop_mutex);
return -ENOMEM;
@@ -1336,12 +1336,12 @@ et61x251_read(struct file* filp, char __user * buf,
return -EAGAIN;
}
timeout = wait_event_interruptible_timeout
- ( cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED),
- cam->module_param.frame_timeout *
- 1000 * msecs_to_jiffies(1) );
+ ( cam->wait_frame,
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED),
+ cam->module_param.frame_timeout *
+ 1000 * msecs_to_jiffies(1) );
if (timeout < 0) {
mutex_unlock(&cam->fileop_mutex);
return timeout;
@@ -1408,7 +1408,7 @@ static unsigned int et61x251_poll(struct file *filp, poll_table *wait)
if (cam->io == IO_NONE) {
if (!et61x251_request_buffers(cam, cam->nreadbuffers,
- IO_READ)) {
+ IO_READ)) {
DBG(1, "poll() failed, not enough memory");
goto error;
}
@@ -1465,7 +1465,7 @@ static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma)
{
struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
unsigned long size = vma->vm_end - vma->vm_start,
- start = vma->vm_start;
+ start = vma->vm_start;
void *pos;
u32 i;
@@ -1533,13 +1533,13 @@ et61x251_vidioc_querycap(struct et61x251_device* cam, void __user * arg)
.driver = "et61x251",
.version = ET61X251_MODULE_VERSION_CODE,
.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
- V4L2_CAP_STREAMING,
+ V4L2_CAP_STREAMING,
};
strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
- sizeof(cap.bus_info));
+ sizeof(cap.bus_info));
if (copy_to_user(arg, &cap, sizeof(cap)))
return -EFAULT;
@@ -1871,7 +1871,7 @@ et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg)
return -EINVAL;
pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_ET61X251)
- ? 0 : (pfmt->width * pfmt->priv) / 8;
+ ? 0 : (pfmt->width * pfmt->priv) / 8;
pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
pfmt->field = V4L2_FIELD_NONE;
memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
@@ -1885,7 +1885,7 @@ et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg)
static int
et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
- void __user * arg)
+ void __user * arg)
{
struct et61x251_sensor* s = &cam->sensor;
struct v4l2_format format;
@@ -1947,7 +1947,7 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
pix->priv = pfmt->priv; /* bpp */
pix->colorspace = pfmt->colorspace;
pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_ET61X251)
- ? 0 : (pix->width * pix->priv) / 8;
+ ? 0 : (pix->width * pix->priv) / 8;
pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
pix->field = V4L2_FIELD_NONE;
@@ -2020,7 +2020,7 @@ static int
et61x251_vidioc_g_jpegcomp(struct et61x251_device* cam, void __user * arg)
{
if (copy_to_user(arg, &cam->compression,
- sizeof(cam->compression)))
+ sizeof(cam->compression)))
return -EFAULT;
return 0;
@@ -2169,7 +2169,7 @@ et61x251_vidioc_qbuf(struct et61x251_device* cam, void __user * arg)
static int
et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp,
- void __user * arg)
+ void __user * arg)
{
struct v4l2_buffer b;
struct et61x251_frame_t *f;
@@ -2188,12 +2188,12 @@ et61x251_vidioc_dqbuf(struct et61x251_device* cam, struct file* filp,
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
timeout = wait_event_interruptible_timeout
- ( cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED),
- cam->module_param.frame_timeout *
- 1000 * msecs_to_jiffies(1) );
+ ( cam->wait_frame,
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED),
+ cam->module_param.frame_timeout *
+ 1000 * msecs_to_jiffies(1) );
if (timeout < 0)
return timeout;
if (cam->state & DEV_DISCONNECTED)
@@ -2317,7 +2317,7 @@ et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg)
static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
- unsigned int cmd, void __user * arg)
+ unsigned int cmd, void __user * arg)
{
struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
@@ -2411,7 +2411,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
static int et61x251_ioctl(struct inode* inode, struct file* filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
int err = 0;
@@ -2518,7 +2518,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
mutex_lock(&cam->dev_mutex);
err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
- video_nr[dev_nr]);
+ video_nr[dev_nr]);
if (err) {
DBG(1, "V4L2 device registration failed");
if (err == -ENFILE && video_nr[dev_nr] == -1)
diff --git a/drivers/usb/media/et61x251_sensor.h b/drivers/media/video/et61x251/et61x251_sensor.h
index 56841ae8a20..65edd08dc38 100644
--- a/drivers/usb/media/et61x251_sensor.h
+++ b/drivers/media/video/et61x251/et61x251_sensor.h
@@ -47,7 +47,7 @@ et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id);
extern void
et61x251_attach_sensor(struct et61x251_device* cam,
- struct et61x251_sensor* sensor);
+ struct et61x251_sensor* sensor);
/*****************************************************************************/
@@ -56,13 +56,13 @@ extern int et61x251_read_reg(struct et61x251_device*, u16 index);
extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value);
extern int et61x251_i2c_read(struct et61x251_device*, u8 address);
extern int et61x251_i2c_try_write(struct et61x251_device*,
- struct et61x251_sensor*, u8 address,
- u8 value);
+ struct et61x251_sensor*, u8 address,
+ u8 value);
extern int et61x251_i2c_try_read(struct et61x251_device*,
- struct et61x251_sensor*, u8 address);
+ struct et61x251_sensor*, u8 address);
extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1,
- u8 data2, u8 data3, u8 data4, u8 data5,
- u8 data6, u8 data7, u8 data8, u8 address);
+ u8 data2, u8 data3, u8 data4, u8 data5,
+ u8 data6, u8 data7, u8 data8, u8 address);
/*****************************************************************************/
@@ -100,13 +100,13 @@ struct et61x251_sensor {
int (*init)(struct et61x251_device* cam);
int (*get_ctrl)(struct et61x251_device* cam,
- struct v4l2_control* ctrl);
+ struct v4l2_control* ctrl);
int (*set_ctrl)(struct et61x251_device* cam,
- const struct v4l2_control* ctrl);
+ const struct v4l2_control* ctrl);
int (*set_crop)(struct et61x251_device* cam,
- const struct v4l2_rect* rect);
+ const struct v4l2_rect* rect);
int (*set_pix_format)(struct et61x251_device* cam,
- const struct v4l2_pix_format* pix);
+ const struct v4l2_pix_format* pix);
/* Private */
struct v4l2_queryctrl _qctrl[ET61X251_MAX_CTRLS];
diff --git a/drivers/usb/media/et61x251_tas5130d1b.c b/drivers/media/video/et61x251/et61x251_tas5130d1b.c
index 3998d76a307..a7d65b82b2f 100644
--- a/drivers/usb/media/et61x251_tas5130d1b.c
+++ b/drivers/media/video/et61x251/et61x251_tas5130d1b.c
@@ -46,20 +46,20 @@ static int tas5130d1b_init(struct et61x251_device* cam)
static int tas5130d1b_set_ctrl(struct et61x251_device* cam,
- const struct v4l2_control* ctrl)
+ const struct v4l2_control* ctrl)
{
int err = 0;
switch (ctrl->id) {
case V4L2_CID_GAIN:
err += et61x251_i2c_raw_write(cam, 2, 0x20,
- 0xf6-ctrl->value, 0, 0, 0,
- 0, 0, 0, 0);
+ 0xf6-ctrl->value, 0, 0, 0,
+ 0, 0, 0, 0);
break;
case V4L2_CID_EXPOSURE:
err += et61x251_i2c_raw_write(cam, 2, 0x40,
- 0x47-ctrl->value, 0, 0, 0,
- 0, 0, 0, 0);
+ 0x47-ctrl->value, 0, 0, 0,
+ 0, 0, 0, 0);
break;
default:
return -EINVAL;
diff --git a/drivers/media/video/font.h b/drivers/media/video/font.h
new file mode 100644
index 00000000000..8b1fecc3759
--- /dev/null
+++ b/drivers/media/video/font.h
@@ -0,0 +1,407 @@
+static unsigned char rom8x16_bits[] = {
+/* Character 0 (0x30):
+ ht=16, width=8
+ +--------+
+ | |
+ | |
+ | ***** |
+ |** ** |
+ |** ** |
+ |** *** |
+ |** **** |
+ |**** ** |
+ |*** ** |
+ |** ** |
+ |** ** |
+ | ***** |
+ | |
+ | |
+ | |
+ | |
+ +--------+ */
+0x00,
+0x00,
+0x7c,
+0xc6,
+0xc6,
+0xce,
+0xde,
+0xf6,
+0xe6,
+0xc6,
+0xc6,
+0x7c,
+0x00,
+0x00,
+0x00,
+0x00,
+
+/* Character 1 (0x31):
+ ht=16, width=8
+ +--------+
+ | |
+ | |
+ | ** |
+ | **** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ****** |
+ | |
+ | |
+ | |
+ | |
+ +--------+ */
+0x00,
+0x00,
+0x18,
+0x78,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x7e,
+0x00,
+0x00,
+0x00,
+0x00,
+
+/* Character 2 (0x32):
+ ht=16, width=8
+ +--------+
+ | |
+ | |
+ | ***** |
+ |** ** |
+ |** ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |** ** |
+ |******* |
+ | |
+ | |
+ | |
+ | |
+ +--------+ */
+0x00,
+0x00,
+0x7c,
+0xc6,
+0xc6,
+0x06,
+0x0c,
+0x18,
+0x30,
+0x60,
+0xc6,
+0xfe,
+0x00,
+0x00,
+0x00,
+0x00,
+
+/* Character 3 (0x33):
+ ht=16, width=8
+ +--------+
+ | |
+ | |
+ | ***** |
+ |** ** |
+ | ** |
+ | ** |
+ | **** |
+ | ** |
+ | ** |
+ | ** |
+ |** ** |
+ | ***** |
+ | |
+ | |
+ | |
+ | |
+ +--------+ */
+0x00,
+0x00,
+0x7c,
+0xc6,
+0x06,
+0x06,
+0x3c,
+0x06,
+0x06,
+0x06,
+0xc6,
+0x7c,
+0x00,
+0x00,
+0x00,
+0x00,
+
+/* Character 4 (0x34):
+ ht=16, width=8
+ +--------+
+ | |
+ | |
+ | ** |
+ | *** |
+ | **** |
+ | ** ** |
+ |** ** |
+ |** ** |
+ |******* |
+ | ** |
+ | ** |
+ | **** |
+ | |
+ | |
+ | |
+ | |
+ +--------+ */
+0x00,
+0x00,
+0x0c,
+0x1c,
+0x3c,
+0x6c,
+0xcc,
+0xcc,
+0xfe,
+0x0c,
+0x0c,
+0x1e,
+0x00,
+0x00,
+0x00,
+0x00,
+
+/* Character 5 (0x35):
+ ht=16, width=8
+ +--------+
+ | |
+ | |
+ |******* |
+ |** |
+ |** |
+ |** |
+ |****** |
+ | ** |
+ | ** |
+ | ** |
+ |** ** |
+ | ***** |
+ | |
+ | |
+ | |
+ | |
+ +--------+ */
+0x00,
+0x00,
+0xfe,
+0xc0,
+0xc0,
+0xc0,
+0xfc,
+0x06,
+0x06,
+0x06,
+0xc6,
+0x7c,
+0x00,
+0x00,
+0x00,
+0x00,
+
+/* Character 6 (0x36):
+ ht=16, width=8
+ +--------+
+ | |
+ | |
+ | ***** |
+ |** ** |
+ |** |
+ |** |
+ |****** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | ***** |
+ | |
+ | |
+ | |
+ | |
+ +--------+ */
+0x00,
+0x00,
+0x7c,
+0xc6,
+0xc0,
+0xc0,
+0xfc,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0x7c,
+0x00,
+0x00,
+0x00,
+0x00,
+
+/* Character 7 (0x37):
+ ht=16, width=8
+ +--------+
+ | |
+ | |
+ |******* |
+ |** ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ | |
+ | |
+ | |
+ +--------+ */
+0x00,
+0x00,
+0xfe,
+0xc6,
+0x06,
+0x0c,
+0x18,
+0x30,
+0x30,
+0x30,
+0x30,
+0x30,
+0x00,
+0x00,
+0x00,
+0x00,
+
+/* Character 8 (0x38):
+ ht=16, width=8
+ +--------+
+ | |
+ | |
+ | ***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | ***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | ***** |
+ | |
+ | |
+ | |
+ | |
+ +--------+ */
+0x00,
+0x00,
+0x7c,
+0xc6,
+0xc6,
+0xc6,
+0x7c,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0x7c,
+0x00,
+0x00,
+0x00,
+0x00,
+
+/* Character 9 (0x39):
+ ht=16, width=8
+ +--------+
+ | |
+ | |
+ | ***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | ****** |
+ | ** |
+ | ** |
+ |** ** |
+ | ***** |
+ | |
+ | |
+ | |
+ | |
+ +--------+ */
+0x00,
+0x00,
+0x7c,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0x7e,
+0x06,
+0x06,
+0xc6,
+0x7c,
+0x00,
+0x00,
+0x00,
+0x00,
+/* Character : (0x3a):
+ ht=16, width=8
+ +--------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | ** |
+ | ** |
+ | |
+ | |
+ | ** |
+ | ** |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +--------+ */
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x0c,
+0x0c,
+0x00,
+0x00,
+0x0c,
+0x0c,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+};
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index 11ea9765769..c40e8ba9a2e 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -53,10 +53,11 @@
#include <linux/videodev.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
-#include <media/audiochip.h>
+#include <media/tvaudio.h>
+#include <media/msp3400.h>
#include <linux/kthread.h>
#include <linux/suspend.h>
-#include "msp3400.h"
+#include "msp3400-driver.h"
/* ---------------------------------------------------------------------- */
@@ -245,31 +246,31 @@ int msp_write_dsp(struct i2c_client *client, int addr, int val)
* ----------------------------------------------------------------------- */
static int scarts[3][9] = {
- /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */
+ /* MASK IN1 IN2 IN3 IN4 IN1_DA IN2_DA MONO MUTE */
/* SCART DSP Input select */
- { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 },
+ { 0x0320, 0x0000, 0x0200, 0x0300, 0x0020, -1, -1, 0x0100, 0x0320 },
/* SCART1 Output select */
- { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 },
+ { 0x0c40, 0x0440, 0x0400, 0x0000, 0x0840, 0x0c00, 0x0040, 0x0800, 0x0c40 },
/* SCART2 Output select */
- { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 },
+ { 0x3080, 0x1000, 0x1080, 0x2080, 0x3080, 0x0000, 0x0080, 0x2000, 0x3000 },
};
static char *scart_names[] = {
- "mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute"
+ "in1", "in2", "in3", "in4", "in1 da", "in2 da", "mono", "mute"
};
void msp_set_scart(struct i2c_client *client, int in, int out)
{
struct msp_state *state = i2c_get_clientdata(client);
- state->in_scart=in;
+ state->in_scart = in;
- if (in >= 1 && in <= 8 && out >= 0 && out <= 2) {
- if (-1 == scarts[out][in])
+ if (in >= 0 && in <= 7 && out >= 0 && out <= 2) {
+ if (-1 == scarts[out][in + 1])
return;
- state->acb &= ~scarts[out][SCART_MASK];
- state->acb |= scarts[out][in];
+ state->acb &= ~scarts[out][0];
+ state->acb |= scarts[out][in + 1];
} else
state->acb = 0xf60; /* Mute Input and SCART 1 Output */
@@ -336,37 +337,6 @@ void msp_set_audio(struct i2c_client *client)
msp_write_dsp(client, 0x0033, loudness);
}
-int msp_modus(struct i2c_client *client)
-{
- struct msp_state *state = i2c_get_clientdata(client);
-
- if (state->radio) {
- v4l_dbg(1, msp_debug, client, "video mode selected to Radio\n");
- return 0x0003;
- }
-
- if (state->v4l2_std & V4L2_STD_PAL) {
- v4l_dbg(1, msp_debug, client, "video mode selected to PAL\n");
-
-#if 1
- /* experimental: not sure this works with all chip versions */
- return 0x7003;
-#else
- /* previous value, try this if it breaks ... */
- return 0x1003;
-#endif
- }
- if (state->v4l2_std & V4L2_STD_NTSC) {
- v4l_dbg(1, msp_debug, client, "video mode selected to NTSC\n");
- return 0x2003;
- }
- if (state->v4l2_std & V4L2_STD_SECAM) {
- v4l_dbg(1, msp_debug, client, "video mode selected to SECAM\n");
- return 0x0003;
- }
- return 0x0003;
-}
-
/* ------------------------------------------------------------------------ */
@@ -585,51 +555,11 @@ static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct msp_state *state = i2c_get_clientdata(client);
- u16 *sarg = arg;
- int scart = 0;
if (msp_debug >= 2)
v4l_i2c_print_ioctl(client, cmd);
switch (cmd) {
- case AUDC_SET_INPUT:
- if (*sarg == state->input)
- break;
- state->input = *sarg;
- switch (*sarg) {
- case AUDIO_RADIO:
- /* Hauppauge uses IN2 for the radio */
- state->mode = MSP_MODE_FM_RADIO;
- scart = SCART_IN2;
- break;
- case AUDIO_EXTERN_1:
- /* IN1 is often used for external input ... */
- state->mode = MSP_MODE_EXTERN;
- scart = SCART_IN1;
- break;
- case AUDIO_EXTERN_2:
- /* ... sometimes it is IN2 through ;) */
- state->mode = MSP_MODE_EXTERN;
- scart = SCART_IN2;
- break;
- case AUDIO_TUNER:
- state->mode = -1;
- break;
- default:
- if (*sarg & AUDIO_MUTE)
- msp_set_scart(client, SCART_MUTE, 0);
- break;
- }
- if (scart) {
- state->rxsubchans = V4L2_TUNER_SUB_STEREO;
- msp_set_scart(client, scart, 0);
- msp_write_dsp(client, 0x000d, 0x1900);
- if (state->opmode != OPMODE_AUTOSELECT)
- msp_set_audmode(client);
- }
- msp_wake_thread(client);
- break;
-
case AUDC_SET_RADIO:
if (state->radio)
return 0;
@@ -692,6 +622,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (va->mode != 0 && state->radio == 0) {
state->audmode = msp_mode_v4l1_to_v4l2(va->mode);
+ msp_set_audmode(client);
}
break;
}
@@ -728,15 +659,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
break;
}
- /* msp34xx specific */
- case MSP_SET_MATRIX:
- {
- struct msp_matrix *mspm = arg;
-
- msp_set_scart(client, mspm->input, mspm->output);
- break;
- }
-
/* --- v4l2 ioctls --- */
case VIDIOC_S_STD:
{
@@ -750,90 +672,34 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
- case VIDIOC_ENUMINPUT:
- {
- struct v4l2_input *i = arg;
-
- if (i->index != 0)
- return -EINVAL;
-
- i->type = V4L2_INPUT_TYPE_TUNER;
- switch (i->index) {
- case AUDIO_RADIO:
- strcpy(i->name, "Radio");
- break;
- case AUDIO_EXTERN_1:
- strcpy(i->name, "Extern 1");
- break;
- case AUDIO_EXTERN_2:
- strcpy(i->name, "Extern 2");
- break;
- case AUDIO_TUNER:
- strcpy(i->name, "Television");
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
-
- case VIDIOC_G_AUDIO:
+ case VIDIOC_INT_G_AUDIO_ROUTING:
{
- struct v4l2_audio *a = arg;
+ struct v4l2_routing *rt = arg;
- memset(a, 0, sizeof(*a));
-
- switch (a->index) {
- case AUDIO_RADIO:
- strcpy(a->name, "Radio");
- break;
- case AUDIO_EXTERN_1:
- strcpy(a->name, "Extern 1");
- break;
- case AUDIO_EXTERN_2:
- strcpy(a->name, "Extern 2");
- break;
- case AUDIO_TUNER:
- strcpy(a->name, "Television");
- break;
- default:
- return -EINVAL;
- }
-
- a->capability = V4L2_AUDCAP_STEREO;
- a->mode = 0; /* TODO: add support for AVL */
+ *rt = state->routing;
break;
}
- case VIDIOC_S_AUDIO:
+ case VIDIOC_INT_S_AUDIO_ROUTING:
{
- struct v4l2_audio *sarg = arg;
-
- switch (sarg->index) {
- case AUDIO_RADIO:
- /* Hauppauge uses IN2 for the radio */
- state->mode = MSP_MODE_FM_RADIO;
- scart = SCART_IN2;
- break;
- case AUDIO_EXTERN_1:
- /* IN1 is often used for external input ... */
- state->mode = MSP_MODE_EXTERN;
- scart = SCART_IN1;
- break;
- case AUDIO_EXTERN_2:
- /* ... sometimes it is IN2 through ;) */
- state->mode = MSP_MODE_EXTERN;
- scart = SCART_IN2;
- break;
- case AUDIO_TUNER:
- state->mode = -1;
- break;
- }
- if (scart) {
- state->rxsubchans = V4L2_TUNER_SUB_STEREO;
- msp_set_scart(client, scart, 0);
- msp_write_dsp(client, 0x000d, 0x1900);
+ struct v4l2_routing *rt = arg;
+ int tuner = (rt->input >> 3) & 1;
+ int sc_in = rt->input & 0x7;
+ int sc1_out = rt->output & 0xf;
+ int sc2_out = (rt->output >> 4) & 0xf;
+ u16 val;
+
+ state->routing = *rt;
+ if (state->opmode == OPMODE_AUTOSELECT) {
+ val = msp_read_dem(client, 0x30) & ~0x100;
+ msp_write_dem(client, 0x30, val | (tuner ? 0x100 : 0));
+ } else {
+ val = msp_read_dem(client, 0xbb) & ~0x100;
+ msp_write_dem(client, 0xbb, val | (tuner ? 0x100 : 0));
}
+ msp_set_scart(client, sc_in, 0);
+ msp_set_scart(client, sc1_out, 1);
+ msp_set_scart(client, sc2_out, 2);
msp_set_audmode(client);
msp_wake_thread(client);
break;
@@ -866,42 +732,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
break;
}
- case VIDIOC_G_AUDOUT:
- {
- struct v4l2_audioout *a = (struct v4l2_audioout *)arg;
- int idx = a->index;
-
- memset(a, 0, sizeof(*a));
-
- switch (idx) {
- case 0:
- strcpy(a->name, "Scart1 Out");
- break;
- case 1:
- strcpy(a->name, "Scart2 Out");
- break;
- case 2:
- strcpy(a->name, "I2S Out");
- break;
- default:
- return -EINVAL;
- }
- break;
- }
-
- case VIDIOC_S_AUDOUT:
- {
- struct v4l2_audioout *a = (struct v4l2_audioout *)arg;
-
- if (a->index < 0 || a->index > 2)
- return -EINVAL;
-
- v4l_dbg(1, msp_debug, client, "Setting audio out on msp34xx to input %i\n", a->index);
- msp_set_scart(client, state->in_scart, a->index + 1);
-
- break;
- }
-
case VIDIOC_INT_I2S_CLOCK_FREQ:
{
u32 *a = (u32 *)arg;
@@ -979,12 +809,16 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
} else {
- v4l_info(client, "Mode: %s\n", p);
+ if (state->opmode == OPMODE_AUTODETECT)
+ v4l_info(client, "Mode: %s\n", p);
v4l_info(client, "Standard: %s (%s%s)\n",
msp_standard_std_name(state->std),
(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
}
+ v4l_info(client, "Audmode: 0x%04x\n", state->audmode);
+ v4l_info(client, "Routing: 0x%08x (input) 0x%08x (output)\n",
+ state->routing.input, state->routing.output);
v4l_info(client, "ACB: 0x%04x\n", state->acb);
break;
}
@@ -1063,6 +897,9 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
state->muted = 0;
state->i2s_mode = 0;
init_waitqueue_head(&state->wq);
+ /* These are the reset input/output positions */
+ state->routing.input = MSP_INPUT_DEFAULT;
+ state->routing.output = MSP_OUTPUT_DEFAULT;
state->rev1 = msp_read_dsp(client, 0x1e);
if (state->rev1 != -1)
diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400-driver.h
index 6fb5c8c994e..1940748bb63 100644
--- a/drivers/media/video/msp3400.h
+++ b/drivers/media/video/msp3400-driver.h
@@ -1,8 +1,10 @@
/*
*/
-#ifndef MSP3400_H
-#define MSP3400_H
+#ifndef MSP3400_DRIVER_H
+#define MSP3400_DRIVER_H
+
+#include <media/msp3400.h>
/* ---------------------------------------------------------------------- */
@@ -20,15 +22,14 @@
#define MSP_MODE_BTSC 8
#define MSP_MODE_EXTERN 9
-#define SCART_MASK 0
-#define SCART_IN1 1
-#define SCART_IN2 2
-#define SCART_IN1_DA 3
-#define SCART_IN2_DA 4
-#define SCART_IN3 5
-#define SCART_IN4 6
-#define SCART_MONO 7
-#define SCART_MUTE 8
+#define SCART_IN1 0
+#define SCART_IN2 1
+#define SCART_IN3 2
+#define SCART_IN4 3
+#define SCART_IN1_DA 4
+#define SCART_IN2_DA 5
+#define SCART_MONO 6
+#define SCART_MUTE 7
#define SCART_DSP_IN 0
#define SCART1_OUT 1
@@ -73,7 +74,7 @@ struct msp_state {
int i2s_mode;
int main, second; /* sound carrier */
int input;
- int source; /* see msp34xxg_set_source */
+ struct v4l2_routing routing;
/* v4l2 */
int audmode;
@@ -99,17 +100,16 @@ int msp_reset(struct i2c_client *client);
void msp_set_scart(struct i2c_client *client, int in, int out);
void msp_set_mute(struct i2c_client *client);
void msp_set_audio(struct i2c_client *client);
-int msp_modus(struct i2c_client *client);
int msp_sleep(struct msp_state *state, int timeout);
/* msp3400-kthreads.c */
const char *msp_standard_std_name(int std);
void msp_set_audmode(struct i2c_client *client);
-void msp_detect_stereo(struct i2c_client *client);
+int msp_detect_stereo(struct i2c_client *client);
int msp3400c_thread(void *data);
int msp3410d_thread(void *data);
int msp34xxg_thread(void *data);
void msp3400c_set_mode(struct i2c_client *client, int mode);
void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2);
-#endif /* MSP3400_H */
+#endif /* MSP3400_DRIVER_H */
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index 852ab6a115f..c3984ea9ca0 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -26,10 +26,10 @@
#include <linux/videodev.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
-#include <media/audiochip.h>
+#include <media/msp3400.h>
#include <linux/kthread.h>
#include <linux/suspend.h>
-#include "msp3400.h"
+#include "msp3400-driver.h"
/* this one uses the automatic sound standard detection of newer msp34xx
chip versions */
@@ -45,11 +45,13 @@ static struct {
{ 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" },
{ 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" },
{ 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" },
+ { 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875), "6.5/5.74 D/K3 Dual FM-Stereo" },
{ 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" },
{ 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" },
{ 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" },
{ 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" },
{ 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" },
+ { 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV3)" },
{ 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" },
{ 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" },
{ 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" },
@@ -185,13 +187,14 @@ void msp3400c_set_mode(struct i2c_client *client, int mode)
{
struct msp_state *state = i2c_get_clientdata(client);
struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode];
+ int tuner = (state->routing.input >> 3) & 1;
int i;
v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode);
state->mode = mode;
state->rxsubchans = V4L2_TUNER_SUB_MONO;
- msp_write_dem(client, 0x00bb, data->ad_cv);
+ msp_write_dem(client, 0x00bb, data->ad_cv | (tuner ? 0x100 : 0));
for (i = 5; i >= 0; i--) /* fir 1 */
msp_write_dem(client, 0x0001, data->fir1[i]);
@@ -207,21 +210,22 @@ void msp3400c_set_mode(struct i2c_client *client, int mode)
msp3400c_set_carrier(client, data->cdo1, data->cdo2);
msp_set_source(client, data->dsp_src);
- msp_write_dsp(client, 0x000e, data->dsp_matrix);
+ /* set prescales */
- if (state->has_nicam) {
- /* nicam prescale */
- msp_write_dsp(client, 0x0010, 0x5a00); /* was: 0x3000 */
- }
+ /* volume prescale for SCART (AM mono input) */
+ msp_write_dsp(client, 0x000d, 0x1900);
+ msp_write_dsp(client, 0x000e, data->dsp_matrix);
+ if (state->has_nicam) /* nicam prescale */
+ msp_write_dsp(client, 0x0010, 0x5a00);
}
/* Set audio mode. Note that the pre-'G' models do not support BTSC+SAP,
nor do they support stereo BTSC. */
static void msp3400c_set_audmode(struct i2c_client *client)
{
- static char *strmode[] = { "mono", "stereo", "lang2", "lang1" };
+ static char *strmode[] = { "mono", "stereo", "lang2", "lang1", "lang1+lang2" };
struct msp_state *state = i2c_get_clientdata(client);
- char *modestr = (state->audmode >= 0 && state->audmode < 4) ?
+ char *modestr = (state->audmode >= 0 && state->audmode < 5) ?
strmode[state->audmode] : "unknown";
int src = 0; /* channel source: FM/AM, nicam or SCART */
@@ -246,6 +250,7 @@ static void msp3400c_set_audmode(struct i2c_client *client)
case V4L2_TUNER_MODE_MONO:
case V4L2_TUNER_MODE_LANG1:
case V4L2_TUNER_MODE_LANG2:
+ case V4L2_TUNER_MODE_LANG1_LANG2:
msp_write_dsp(client, 0x000e, 0x3000);
break;
}
@@ -257,6 +262,7 @@ static void msp3400c_set_audmode(struct i2c_client *client)
msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
break;
case V4L2_TUNER_MODE_STEREO:
+ case V4L2_TUNER_MODE_LANG1_LANG2:
msp3400c_set_carrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02));
break;
case V4L2_TUNER_MODE_LANG1:
@@ -271,7 +277,6 @@ static void msp3400c_set_audmode(struct i2c_client *client)
case MSP_MODE_FM_NICAM2:
case MSP_MODE_AM_NICAM:
v4l_dbg(1, msp_debug, client, "NICAM set_audmode: %s\n",modestr);
- msp3400c_set_carrier(client, state->second, state->main);
if (state->nicam_on)
src = 0x0100; /* NICAM */
break;
@@ -293,6 +298,7 @@ static void msp3400c_set_audmode(struct i2c_client *client)
/* switch audio */
switch (state->audmode) {
case V4L2_TUNER_MODE_STEREO:
+ case V4L2_TUNER_MODE_LANG1_LANG2:
src |= 0x0020;
break;
case V4L2_TUNER_MODE_MONO:
@@ -427,8 +433,8 @@ static void watch_stereo(struct i2c_client *client)
{
struct msp_state *state = i2c_get_clientdata(client);
- if (msp3400c_detect_stereo(client)) {
- msp3400c_set_audmode(client);
+ if (msp_detect_stereo(client)) {
+ msp_set_audmode(client);
}
if (msp_once)
@@ -464,7 +470,7 @@ int msp3400c_thread(void *data)
/* mute */
msp_set_mute(client);
- msp3400c_set_mode(client, MSP_MODE_AM_DETECT /* +1 */ );
+ msp3400c_set_mode(client, MSP_MODE_AM_DETECT);
val1 = val2 = 0;
max1 = max2 = -1;
state->watch_stereo = 0;
@@ -572,8 +578,6 @@ int msp3400c_thread(void *data)
state->second = msp3400c_carrier_detect_65[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_AM_NICAM);
msp3400c_set_carrier(client, state->second, state->main);
- /* volume prescale for SCART (AM mono input) */
- msp_write_dsp(client, 0x000d, 0x1900);
state->watch_stereo = 1;
} else if (max2 == 0 && state->has_nicam) {
/* D/K NICAM */
@@ -651,7 +655,8 @@ int msp3410d_thread(void *data)
if (msp_sleep(state,200))
goto restart;
- /* start autodetect */
+ /* start autodetect. Note: autodetect is not supported for
+ NTSC-M and radio, hence we force the standard in those cases. */
if (state->radio)
std = 0x40;
else
@@ -695,23 +700,19 @@ int msp3410d_thread(void *data)
v4l_dbg(1, msp_debug, client, "autodetection failed,"
" switching to backup standard: %s (0x%04x)\n",
msp_stdlist[8].name ? msp_stdlist[8].name : "unknown",val);
- val = 0x0009;
+ state->std = val = 0x0009;
msp_write_dem(client, 0x20, val);
}
- /* set various prescales */
- msp_write_dsp(client, 0x0d, 0x1900); /* scart */
- msp_write_dsp(client, 0x0e, 0x2403); /* FM */
- msp_write_dsp(client, 0x10, 0x5a00); /* nicam */
-
/* set stereo */
switch (val) {
case 0x0008: /* B/G NICAM */
case 0x000a: /* I NICAM */
- if (val == 0x0008)
- state->mode = MSP_MODE_FM_NICAM1;
- else
+ case 0x000b: /* D/K NICAM */
+ if (val == 0x000a)
state->mode = MSP_MODE_FM_NICAM2;
+ else
+ state->mode = MSP_MODE_FM_NICAM1;
/* just turn on stereo */
state->rxsubchans = V4L2_TUNER_SUB_STEREO;
state->nicam_on = 1;
@@ -739,6 +740,7 @@ int msp3410d_thread(void *data)
/* scart routing (this doesn't belong here I think) */
msp_set_scart(client,SCART_IN2,0);
break;
+ case 0x0002:
case 0x0003:
case 0x0004:
case 0x0005:
@@ -748,12 +750,19 @@ int msp3410d_thread(void *data)
break;
}
- /* unmute, restore misc registers */
- msp_set_audio(client);
- msp_write_dsp(client, 0x13, state->acb);
+ /* set various prescales */
+ msp_write_dsp(client, 0x0d, 0x1900); /* scart */
+ msp_write_dsp(client, 0x0e, 0x3000); /* FM */
+ if (state->has_nicam)
+ msp_write_dsp(client, 0x10, 0x5a00); /* nicam */
+
if (state->has_i2s_conf)
msp_write_dem(client, 0x40, state->i2s_mode);
+ /* unmute, restore misc registers */
+ msp_set_audio(client);
+
+ msp_write_dsp(client, 0x13, state->acb);
msp3400c_set_audmode(client);
/* monitor tv audio mode, the first time don't wait
@@ -772,97 +781,154 @@ int msp3410d_thread(void *data)
/* ----------------------------------------------------------------------- */
-/* msp34xxG + (autoselect no-thread) */
-/* this one uses both automatic standard detection and automatic sound */
-/* select which are available in the newer G versions */
-/* struct msp: only norm, acb and source are really used in this mode */
-
-/* set the same 'source' for the loudspeaker, scart and quasi-peak detector
- * the value for source is the same as bit 15:8 of DSP registers 0x08,
- * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B
- *
- * this function replaces msp3400c_set_audmode
+/* msp34xxG + (autoselect no-thread)
+ * this one uses both automatic standard detection and automatic sound
+ * select which are available in the newer G versions
+ * struct msp: only norm, acb and source are really used in this mode
*/
-static void msp34xxg_set_source(struct i2c_client *client, int source)
+
+static int msp34xxg_modus(struct i2c_client *client)
{
struct msp_state *state = i2c_get_clientdata(client);
- /* fix matrix mode to stereo and let the msp choose what
- * to output according to 'source', as recommended
- * for MONO (source==0) downmixing set bit[7:0] to 0x30
- */
- int value = (source & 0x07) << 8 | (source == 0 ? 0x30 : 0x20);
+ if (state->radio) {
+ v4l_dbg(1, msp_debug, client, "selected radio modus\n");
+ return 0x0001;
+ }
- v4l_dbg(1, msp_debug, client, "set source to %d (0x%x)\n", source, value);
- msp_set_source(client, value);
- /*
- * set identification threshold. Personally, I
- * I set it to a higher value that the default
- * of 0x190 to ignore noisy stereo signals.
- * this needs tuning. (recommended range 0x00a0-0x03c0)
- * 0x7f0 = forced mono mode
- */
- /* a2 threshold for stereo/bilingual */
- msp_write_dem(client, 0x22, msp_stereo_thresh);
- state->source = source;
+ if (state->v4l2_std & V4L2_STD_PAL) {
+ v4l_dbg(1, msp_debug, client, "selected PAL modus\n");
+ return 0x7001;
+ }
+ if (state->v4l2_std == V4L2_STD_NTSC_M_JP) {
+ v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n");
+ return 0x4001;
+ }
+ if (state->v4l2_std == V4L2_STD_NTSC_M_KR) {
+ v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n");
+ return 0x0001;
+ }
+ if (state->v4l2_std & V4L2_STD_MN) {
+ v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n");
+ return 0x2001;
+ }
+ if (state->v4l2_std & V4L2_STD_SECAM) {
+ v4l_dbg(1, msp_debug, client, "selected SECAM modus\n");
+ return 0x6001;
+ }
+ return 0x0001;
}
-/* (re-)initialize the msp34xxg, according to the current norm in state->norm
- * return 0 if it worked, -1 if it failed
- */
-static int msp34xxg_reset(struct i2c_client *client)
+static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
+ {
+ struct msp_state *state = i2c_get_clientdata(client);
+ int source, matrix;
+
+ switch (state->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ source = 0; /* mono only */
+ matrix = 0x30;
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ source = 3; /* stereo or A */
+ matrix = 0x00;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ source = 4; /* stereo or B */
+ matrix = 0x10;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ case V4L2_TUNER_MODE_LANG1_LANG2:
+ default:
+ source = 1; /* stereo or A|B */
+ matrix = 0x20;
+ break;
+ }
+
+ if (in == MSP_DSP_OUT_TUNER)
+ source = (source << 8) | 0x20;
+ /* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14
+ instead of 11, 12, 13. So we add one for that msp version. */
+ else if (in >= MSP_DSP_OUT_MAIN_AVC && state->has_dolby_pro_logic)
+ source = ((in + 1) << 8) | matrix;
+ else
+ source = (in << 8) | matrix;
+
+ v4l_dbg(1, msp_debug, client, "set source to %d (0x%x) for output %02x\n",
+ in, source, reg);
+ msp_write_dsp(client, reg, source);
+}
+
+static void msp34xxg_set_sources(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ u32 in = state->routing.input;
+
+ msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf);
+ /* quasi-peak detector is set to same input as the loudspeaker (MAIN) */
+ msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf);
+ msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf);
+ msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf);
+ if (state->has_scart23_in_scart2_out)
+ msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf);
+ msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf);
+}
+
+/* (re-)initialize the msp34xxg */
+static void msp34xxg_reset(struct i2c_client *client)
{
struct msp_state *state = i2c_get_clientdata(client);
- int modus, std;
+ int tuner = (state->routing.input >> 3) & 1;
+ int modus;
+
+ /* initialize std to 1 (autodetect) to signal that no standard is
+ selected yet. */
+ state->std = 1;
- if (msp_reset(client))
- return -1;
+ msp_reset(client);
/* make sure that input/output is muted (paranoid mode) */
/* ACB, mute DSP input, mute SCART 1 */
- if (msp_write_dsp(client, 0x13, 0x0f20))
- return -1;
+ msp_write_dsp(client, 0x13, 0x0f20);
if (state->has_i2s_conf)
msp_write_dem(client, 0x40, state->i2s_mode);
/* step-by-step initialisation, as described in the manual */
- modus = msp_modus(client);
- if (state->radio)
- std = 0x40;
- else
- std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1;
- modus &= ~0x03; /* STATUS_CHANGE = 0 */
- modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION = 1 */
- if (msp_write_dem(client, 0x30, modus))
- return -1;
- if (msp_write_dem(client, 0x20, std))
- return -1;
+ modus = msp34xxg_modus(client);
+ modus |= tuner ? 0x100 : 0;
+ msp_write_dem(client, 0x30, modus);
/* write the dsps that may have an influence on
standard/audio autodetection right now */
- msp34xxg_set_source(client, state->source);
-
- /* AM/FM Prescale [15:8] 75khz deviation */
- if (msp_write_dsp(client, 0x0e, 0x3000))
- return -1;
+ msp34xxg_set_sources(client);
- /* NICAM Prescale 9db gain (as recommended) */
- if (msp_write_dsp(client, 0x10, 0x5a00))
- return -1;
+ msp_write_dsp(client, 0x0d, 0x1900); /* scart */
+ msp_write_dsp(client, 0x0e, 0x3000); /* FM */
+ if (state->has_nicam)
+ msp_write_dsp(client, 0x10, 0x5a00); /* nicam */
- return 0;
+ /* set identification threshold. Personally, I
+ * I set it to a higher value than the default
+ * of 0x190 to ignore noisy stereo signals.
+ * this needs tuning. (recommended range 0x00a0-0x03c0)
+ * 0x7f0 = forced mono mode
+ *
+ * a2 threshold for stereo/bilingual.
+ * Note: this register is part of the Manual/Compatibility mode.
+ * It is supported by all 'G'-family chips.
+ */
+ msp_write_dem(client, 0x22, msp_stereo_thresh);
}
int msp34xxg_thread(void *data)
{
struct i2c_client *client = data;
struct msp_state *state = i2c_get_clientdata(client);
- int val, std, i;
+ int val, i;
v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
- state->source = 1; /* default */
for (;;) {
v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
msp_sleep(state, -1);
@@ -876,12 +942,14 @@ int msp34xxg_thread(void *data)
/* setup the chip*/
msp34xxg_reset(client);
- std = msp_standard;
- if (std != 0x01)
+ state->std = state->radio ? 0x40 : msp_standard;
+ if (state->std != 1)
goto unmute;
+ /* start autodetect */
+ msp_write_dem(client, 0x20, state->std);
/* watch autodetect */
- v4l_dbg(1, msp_debug, client, "triggered autodetect, waiting for result\n");
+ v4l_dbg(1, msp_debug, client, "started autodetect, waiting for result\n");
for (i = 0; i < 10; i++) {
if (msp_sleep(state, 100))
goto restart;
@@ -889,20 +957,19 @@ int msp34xxg_thread(void *data)
/* check results */
val = msp_read_dem(client, 0x7e);
if (val < 0x07ff) {
- std = val;
+ state->std = val;
break;
}
v4l_dbg(2, msp_debug, client, "detection still in progress\n");
}
- if (std == 1) {
+ if (state->std == 1) {
v4l_dbg(1, msp_debug, client, "detection still in progress after 10 tries. giving up.\n");
continue;
}
unmute:
- state->std = std;
- v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n",
- msp_standard_std_name(std), std);
+ v4l_dbg(1, msp_debug, client, "detected standard: %s (0x%04x)\n",
+ msp_standard_std_name(state->std), state->std);
/* unmute: dispatch sound to scart output, set scart volume */
msp_set_audio(client);
@@ -911,20 +978,33 @@ int msp34xxg_thread(void *data)
if (msp_write_dsp(client, 0x13, state->acb))
return -1;
- if (state->has_i2s_conf)
- msp_write_dem(client, 0x40, state->i2s_mode);
+ /* the periodic stereo/SAP check is only relevant for
+ the 0x20 standard (BTSC) */
+ if (state->std != 0x20)
+ continue;
+
+ state->watch_stereo = 1;
+
+ /* monitor tv audio mode, the first time don't wait
+ in order to get a quick stereo/SAP update */
+ watch_stereo(client);
+ while (state->watch_stereo) {
+ watch_stereo(client);
+ if (msp_sleep(state, 5000))
+ goto restart;
+ }
}
v4l_dbg(1, msp_debug, client, "thread: exit\n");
return 0;
}
-static void msp34xxg_detect_stereo(struct i2c_client *client)
+static int msp34xxg_detect_stereo(struct i2c_client *client)
{
struct msp_state *state = i2c_get_clientdata(client);
-
int status = msp_read_dem(client, 0x0200);
int is_bilingual = status & 0x100;
int is_stereo = status & 0x40;
+ int oldrx = state->rxsubchans;
state->rxsubchans = 0;
if (is_stereo)
@@ -932,42 +1012,31 @@ static void msp34xxg_detect_stereo(struct i2c_client *client)
else
state->rxsubchans = V4L2_TUNER_SUB_MONO;
if (is_bilingual) {
- state->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
- /* I'm supposed to check whether it's SAP or not
- * and set only LANG2/SAP in this case. Yet, the MSP
- * does a lot of work to hide this and handle everything
- * the same way. I don't want to work around it so unless
- * this is a problem, I'll handle SAP just like lang1/lang2.
- */
+ if (state->std == 0x20)
+ state->rxsubchans |= V4L2_TUNER_SUB_SAP;
+ else
+ state->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
}
v4l_dbg(1, msp_debug, client, "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n",
status, is_stereo, is_bilingual, state->rxsubchans);
+ return (oldrx != state->rxsubchans);
}
static void msp34xxg_set_audmode(struct i2c_client *client)
{
struct msp_state *state = i2c_get_clientdata(client);
- int source;
- switch (state->audmode) {
- case V4L2_TUNER_MODE_MONO:
- source = 0; /* mono only */
- break;
- case V4L2_TUNER_MODE_STEREO:
- source = 1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */
- /* problem: that could also mean 2 (scart input) */
- break;
- case V4L2_TUNER_MODE_LANG1:
- source = 3; /* stereo or A */
- break;
- case V4L2_TUNER_MODE_LANG2:
- source = 4; /* stereo or B */
- break;
- default:
- source = 1;
- break;
+ if (state->std == 0x20) {
+ if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) &&
+ (state->audmode == V4L2_TUNER_MODE_STEREO ||
+ state->audmode == V4L2_TUNER_MODE_LANG2)) {
+ msp_write_dem(client, 0x20, 0x21);
+ } else {
+ msp_write_dem(client, 0x20, 0x20);
+ }
}
- msp34xxg_set_source(client, source);
+
+ msp34xxg_set_sources(client);
}
void msp_set_audmode(struct i2c_client *client)
@@ -977,7 +1046,6 @@ void msp_set_audmode(struct i2c_client *client)
switch (state->opmode) {
case OPMODE_MANUAL:
case OPMODE_AUTODETECT:
- state->watch_stereo = 0;
msp3400c_set_audmode(client);
break;
case OPMODE_AUTOSELECT:
@@ -986,18 +1054,17 @@ void msp_set_audmode(struct i2c_client *client)
}
}
-void msp_detect_stereo(struct i2c_client *client)
+int msp_detect_stereo(struct i2c_client *client)
{
struct msp_state *state = i2c_get_clientdata(client);
switch (state->opmode) {
case OPMODE_MANUAL:
case OPMODE_AUTODETECT:
- msp3400c_detect_stereo(client);
- break;
+ return msp3400c_detect_stereo(client);
case OPMODE_AUTOSELECT:
- msp34xxg_detect_stereo(client);
- break;
+ return msp34xxg_detect_stereo(client);
}
+ return 0;
}
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
index eb3b3186749..b0aea4002d1 100644
--- a/drivers/media/video/mxb.c
+++ b/drivers/media/video/mxb.c
@@ -198,13 +198,13 @@ static int mxb_probe(struct saa7146_dev* dev)
/* loop through all i2c-devices on the bus and look who is there */
list_for_each(item,&mxb->i2c_adapter.clients) {
client = list_entry(item, struct i2c_client, list);
- if( I2C_TEA6420_1 == client->addr )
+ if( I2C_ADDR_TEA6420_1 == client->addr )
mxb->tea6420_1 = client;
- if( I2C_TEA6420_2 == client->addr )
+ if( I2C_ADDR_TEA6420_2 == client->addr )
mxb->tea6420_2 = client;
if( I2C_TEA6415C_2 == client->addr )
mxb->tea6415c = client;
- if( I2C_TDA9840 == client->addr )
+ if( I2C_ADDR_TDA9840 == client->addr )
mxb->tda9840 = client;
if( I2C_SAA7111 == client->addr )
mxb->saa7111a = client;
@@ -790,6 +790,12 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"));
break;
}
+ case V4L2_TUNER_MODE_LANG1_LANG2: {
+ mxb->cur_mode = V4L2_TUNER_MODE_LANG1_LANG2;
+ byte = TDA9840_SET_BOTH;
+ DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n"));
+ break;
+ }
case V4L2_TUNER_MODE_LANG1: {
mxb->cur_mode = V4L2_TUNER_MODE_LANG1;
byte = TDA9840_SET_LANG1;
diff --git a/drivers/usb/media/ov511.c b/drivers/media/video/ov511.c
index da44579d6f2..fdc8e3f1393 100644
--- a/drivers/usb/media/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -15,7 +15,7 @@
*
* Based on the Linux CPiA driver written by Peter Pregler,
* Scott J. Bertin and Johannes Erdfelt.
- *
+ *
* Please see the file: Documentation/usb/ov511.txt
* and the website at: http://alpha.dyndns.org/ov511
* for more info.
@@ -433,7 +433,7 @@ reg_w_mask(struct usb_ov511 *ov,
return (reg_w(ov, reg, newval));
}
-/*
+/*
* Writes multiple (n) byte value to a single register. Only valid with certain
* registers (0x30 and 0xc4 - 0xce).
*/
@@ -629,7 +629,7 @@ ov511_i2c_write_internal(struct usb_ov511 *ov,
/* Retry until idle */
do
rc = reg_r(ov, R511_I2C_CTL);
- while (rc > 0 && ((rc&1) == 0));
+ while (rc > 0 && ((rc&1) == 0));
if (rc < 0)
break;
@@ -1752,7 +1752,7 @@ sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p)
ov->whiteness = p->whiteness;
/* Don't return error if a setting is unsupported, or rest of settings
- * will not be performed */
+ * will not be performed */
rc = sensor_set_contrast(ov, p->contrast);
if (FATAL_ERROR(rc))
@@ -1781,7 +1781,7 @@ sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p)
PDEBUG(4, "sensor_get_picture");
/* Don't return error if a setting is unsupported, or rest of settings
- * will not be performed */
+ * will not be performed */
rc = sensor_get_contrast(ov, &(p->contrast));
if (FATAL_ERROR(rc))
@@ -2251,7 +2251,7 @@ mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height,
/******** Clock programming ********/
- /* The OV6620 needs special handling. This prevents the
+ /* The OV6620 needs special handling. This prevents the
* severe banding that normally occurs */
if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630)
{
@@ -2326,7 +2326,7 @@ set_ov_sensor_window(struct usb_ov511 *ov, int width, int height, int mode,
int sub_flag)
{
int ret;
- int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize;
+ int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize;
int hoffset, voffset, hwscale = 0, vwscale = 0;
/* The different sensor ICs handle setting up of window differently.
@@ -2575,7 +2575,7 @@ ov518_mode_init_regs(struct usb_ov511 *ov,
/* OV518 needs U and V swapped */
i2c_w_mask(ov, 0x15, 0x00, 0x01);
- if (mode == VIDEO_PALETTE_GREY) {
+ if (mode == VIDEO_PALETTE_GREY) {
/* Set 16-bit input format (UV data are ignored) */
reg_w_mask(ov, 0x20, 0x00, 0x08);
@@ -2894,7 +2894,7 @@ make_8x8(unsigned char *pIn, unsigned char *pOut, int w)
* ... ... ...
* 56 57 ... 63 120 121 ... 127 248 249 ... 255
*
- */
+ */
static void
yuv400raw_to_yuv400p(struct ov511_frame *frame,
unsigned char *pIn0, unsigned char *pOut0)
@@ -2923,7 +2923,7 @@ yuv400raw_to_yuv400p(struct ov511_frame *frame,
*
* 0 1 ... 7
* 8 9 ... 15
- * ...
+ * ...
* 56 57 ... 63
*
* U and V are shipped at half resolution (1 U,V sample -> one 2x2 block).
@@ -3034,7 +3034,7 @@ decompress(struct usb_ov511 *ov, struct ov511_frame *frame,
*/
static void
deinterlace(struct ov511_frame *frame, int rawformat,
- unsigned char *pIn0, unsigned char *pOut0)
+ unsigned char *pIn0, unsigned char *pOut0)
{
const int fieldheight = frame->rawheight / 2;
const int fieldpix = fieldheight * frame->rawwidth;
@@ -3112,7 +3112,7 @@ ov51x_postprocess_grey(struct usb_ov511 *ov, struct ov511_frame *frame)
frame->tempdata);
deinterlace(frame, RAWFMT_YUV400, frame->tempdata,
- frame->data);
+ frame->data);
} else {
if (frame->compressed)
decompress(ov, frame, frame->rawdata,
@@ -3136,7 +3136,7 @@ ov51x_postprocess_yuv420(struct usb_ov511 *ov, struct ov511_frame *frame)
frame->tempdata);
deinterlace(frame, RAWFMT_YUV420, frame->tempdata,
- frame->data);
+ frame->data);
} else {
if (frame->compressed)
decompress(ov, frame, frame->rawdata, frame->data);
@@ -3226,7 +3226,7 @@ ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
frame->rawwidth = ((int)(in[9]) + 1) * 8;
frame->rawheight = ((int)(in[10]) + 1) * 8;
- PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d",
+ PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d",
ov->curframe, pnum, frame->rawwidth, frame->rawheight,
frame->bytes_recvd);
@@ -3527,10 +3527,10 @@ ov51x_isoc_irq(struct urb *urb, struct pt_regs *regs)
return;
}
- if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
- PDEBUG(4, "URB unlinked");
- return;
- }
+ if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
+ PDEBUG(4, "URB unlinked");
+ return;
+ }
if (urb->status != -EINPROGRESS && urb->status != 0) {
err("ERROR: urb->status=%d: %s", urb->status,
@@ -4627,8 +4627,8 @@ ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma)
PDEBUG(4, "mmap: %ld (%lX) bytes", size, size);
if (size > (((OV511_NUMFRAMES
- * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)
- + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))))
+ * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)
+ + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))))
return -EINVAL;
if (mutex_lock_interruptible(&ov->lock))
@@ -5062,7 +5062,7 @@ ov6xx0_configure(struct usb_ov511 *ov)
}
/* This initializes the KS0127 and KS0127B video decoders. */
-static int
+static int
ks0127_configure(struct usb_ov511 *ov)
{
int rc;
@@ -5193,7 +5193,7 @@ saa7111a_configure(struct usb_ov511 *ov)
return -1;
/* Detect version of decoder. This must be done after writing the
- * initial regs or the decoder will lock up. */
+ * initial regs or the decoder will lock up. */
rc = i2c_r(ov, 0x00);
if (rc < 0) {
@@ -5216,13 +5216,13 @@ saa7111a_configure(struct usb_ov511 *ov)
}
/* This initializes the OV511/OV511+ and the sensor */
-static int
+static int
ov511_configure(struct usb_ov511 *ov)
{
static struct ov511_regvals aRegvalsInit511[] = {
{ OV511_REG_BUS, R51x_SYS_RESET, 0x7f },
- { OV511_REG_BUS, R51x_SYS_INIT, 0x01 },
- { OV511_REG_BUS, R51x_SYS_RESET, 0x7f },
+ { OV511_REG_BUS, R51x_SYS_INIT, 0x01 },
+ { OV511_REG_BUS, R51x_SYS_RESET, 0x7f },
{ OV511_REG_BUS, R51x_SYS_INIT, 0x01 },
{ OV511_REG_BUS, R51x_SYS_RESET, 0x3f },
{ OV511_REG_BUS, R51x_SYS_INIT, 0x01 },
@@ -5269,7 +5269,7 @@ ov511_configure(struct usb_ov511 *ov)
err("Please notify " EMAIL " of the name,");
err("manufacturer, model, and this number of your camera.");
err("Also include the output of the detection process.");
- }
+ }
if (ov->customid == 70) /* USB Life TV (PAL/SECAM) */
ov->pal = 1;
@@ -5336,17 +5336,17 @@ ov511_configure(struct usb_ov511 *ov)
if (i2c_w(ov, 0x10, 0x00) < 0) {
err("Can't determine sensor slave IDs");
- goto error;
+ goto error;
} else {
if (ks0127_configure(ov) < 0) {
err("Failed to configure KS0127");
- goto error;
+ goto error;
}
}
} else {
if (saa7111a_configure(ov) < 0) {
err("Failed to configure SAA7111A");
- goto error;
+ goto error;
}
}
} else {
@@ -5356,13 +5356,13 @@ ov511_configure(struct usb_ov511 *ov)
} else {
if (ov6xx0_configure(ov) < 0) {
err("Failed to configure OV6xx0");
- goto error;
+ goto error;
}
}
} else {
if (ov7xx0_configure(ov) < 0) {
err("Failed to configure OV7xx0");
- goto error;
+ goto error;
}
}
@@ -5381,12 +5381,12 @@ ov518_configure(struct usb_ov511 *ov)
/* For 518 and 518+ */
static struct ov511_regvals aRegvalsInit518[] = {
{ OV511_REG_BUS, R51x_SYS_RESET, 0x40 },
- { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 },
- { OV511_REG_BUS, R51x_SYS_RESET, 0x3e },
+ { OV511_REG_BUS, R51x_SYS_INIT, 0xe1 },
+ { OV511_REG_BUS, R51x_SYS_RESET, 0x3e },
{ OV511_REG_BUS, R51x_SYS_INIT, 0xe1 },
{ OV511_REG_BUS, R51x_SYS_RESET, 0x00 },
{ OV511_REG_BUS, R51x_SYS_INIT, 0xe1 },
- { OV511_REG_BUS, 0x46, 0x00 },
+ { OV511_REG_BUS, 0x46, 0x00 },
{ OV511_REG_BUS, 0x5d, 0x03 },
{ OV511_DONE_BUS, 0x0, 0x00},
};
@@ -5517,7 +5517,7 @@ ov518_configure(struct usb_ov511 *ov)
if (init_ov_sensor(ov) < 0) {
err("Can't determine sensor slave IDs");
- goto error;
+ goto error;
} else {
err("Detected unsupported OV8xx0 sensor");
goto error;
@@ -5525,13 +5525,13 @@ ov518_configure(struct usb_ov511 *ov)
} else {
if (ov6xx0_configure(ov) < 0) {
err("Failed to configure OV6xx0");
- goto error;
+ goto error;
}
}
} else {
if (ov7xx0_configure(ov) < 0) {
err("Failed to configure OV7xx0");
- goto error;
+ goto error;
}
}
@@ -5564,28 +5564,28 @@ static ssize_t show_custom_id(struct class_device *cd, char *buf)
{
struct usb_ov511 *ov = cd_to_ov(cd);
return sprintf(buf, "%d\n", ov->customid);
-}
+}
static CLASS_DEVICE_ATTR(custom_id, S_IRUGO, show_custom_id, NULL);
static ssize_t show_model(struct class_device *cd, char *buf)
{
struct usb_ov511 *ov = cd_to_ov(cd);
return sprintf(buf, "%s\n", ov->desc);
-}
+}
static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
static ssize_t show_bridge(struct class_device *cd, char *buf)
{
struct usb_ov511 *ov = cd_to_ov(cd);
return sprintf(buf, "%s\n", symbolic(brglist, ov->bridge));
-}
+}
static CLASS_DEVICE_ATTR(bridge, S_IRUGO, show_bridge, NULL);
static ssize_t show_sensor(struct class_device *cd, char *buf)
{
struct usb_ov511 *ov = cd_to_ov(cd);
return sprintf(buf, "%s\n", symbolic(senlist, ov->sensor));
-}
+}
static CLASS_DEVICE_ATTR(sensor, S_IRUGO, show_sensor, NULL);
static ssize_t show_brightness(struct class_device *cd, char *buf)
@@ -5597,7 +5597,7 @@ static ssize_t show_brightness(struct class_device *cd, char *buf)
return -ENODEV;
sensor_get_brightness(ov, &x);
return sprintf(buf, "%d\n", x >> 8);
-}
+}
static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
static ssize_t show_saturation(struct class_device *cd, char *buf)
@@ -5609,7 +5609,7 @@ static ssize_t show_saturation(struct class_device *cd, char *buf)
return -ENODEV;
sensor_get_saturation(ov, &x);
return sprintf(buf, "%d\n", x >> 8);
-}
+}
static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
static ssize_t show_contrast(struct class_device *cd, char *buf)
@@ -5621,7 +5621,7 @@ static ssize_t show_contrast(struct class_device *cd, char *buf)
return -ENODEV;
sensor_get_contrast(ov, &x);
return sprintf(buf, "%d\n", x >> 8);
-}
+}
static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
static ssize_t show_hue(struct class_device *cd, char *buf)
@@ -5633,7 +5633,7 @@ static ssize_t show_hue(struct class_device *cd, char *buf)
return -ENODEV;
sensor_get_hue(ov, &x);
return sprintf(buf, "%d\n", x >> 8);
-}
+}
static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
static ssize_t show_exposure(struct class_device *cd, char *buf)
@@ -5645,7 +5645,7 @@ static ssize_t show_exposure(struct class_device *cd, char *buf)
return -ENODEV;
sensor_get_exposure(ov, &exp);
return sprintf(buf, "%d\n", exp >> 8);
-}
+}
static CLASS_DEVICE_ATTR(exposure, S_IRUGO, show_exposure, NULL);
static void ov_create_sysfs(struct video_device *vdev)
diff --git a/drivers/usb/media/ov511.h b/drivers/media/video/ov511.h
index bce9b363388..12b3d51e1c3 100644
--- a/drivers/usb/media/ov511.h
+++ b/drivers/media/video/ov511.h
@@ -130,7 +130,7 @@
#define R511_COMP_QVY 0x76
#define R511_COMP_QVUV 0x77
#define R511_COMP_EN 0x78
-#define R511_COMP_LUT_EN 0x79
+#define R511_COMP_LUT_EN 0x79
#define R511_COMP_LUT_BEGIN 0x80
/* --------------------------------- */
@@ -459,14 +459,14 @@ struct usb_ov511 {
int subh; /* Pix Array subcapture height */
int curframe; /* Current receiving sbuf */
- struct ov511_frame frame[OV511_NUMFRAMES];
+ struct ov511_frame frame[OV511_NUMFRAMES];
struct ov511_sbuf sbuf[OV511_NUMSBUF];
wait_queue_head_t wq; /* Processes waiting */
int snap_enabled; /* Snapshot mode enabled */
-
+
int bridge; /* Type of bridge (BRG_*) */
int bclass; /* Class of bridge (BCL_*) */
int sensor; /* Type of image sensor chip (SEN_*) */
@@ -512,7 +512,7 @@ struct symbolic_list {
/* Returns the name of the matching element in the symbolic_list array. The
* end of the list must be marked with an element that has a NULL name.
*/
-static inline char *
+static inline char *
symbolic(struct symbolic_list list[], int num)
{
int i;
diff --git a/drivers/media/video/ovcamchip/Makefile b/drivers/media/video/ovcamchip/Makefile
index bca41ad93de..cba4cdf20f4 100644
--- a/drivers/media/video/ovcamchip/Makefile
+++ b/drivers/media/video/ovcamchip/Makefile
@@ -1,4 +1,4 @@
ovcamchip-objs := ovcamchip_core.o ov6x20.o ov6x30.o ov7x10.o ov7x20.o \
- ov76be.o
+ ov76be.o
obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip.o
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index e76b53d5909..3fe9fa04cd8 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -266,17 +266,17 @@ static int ovcamchip_detect(struct i2c_client *c)
PDEBUG(3, "Testing for 0V6xx0");
c->addr = OV6xx0_SID;
if (init_camchip(c) < 0) {
- return -ENODEV;
+ return -ENODEV;
} else {
if (ov6xx0_detect(c) < 0) {
PERROR("Failed to init OV6xx0");
- return -EIO;
+ return -EIO;
}
}
} else {
if (ov7xx0_detect(c) < 0) {
PERROR("Failed to init OV7xx0");
- return -EIO;
+ return -EIO;
}
}
diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h
index 575e612a554..1231335a9f4 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_priv.h
+++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h
@@ -82,6 +82,6 @@ extern int ov_write_regvals(struct i2c_client *c,
struct ovcamchip_regvals *rvals);
extern int ov_write_mask(struct i2c_client *c, unsigned char reg,
- unsigned char value, unsigned char mask);
+ unsigned char value, unsigned char mask);
#endif
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index 15fd85acabd..d9e3cada52f 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -1,4 +1,4 @@
-/*
+/*
planb - PlanB frame grabber driver
PlanB is used in the 7x00/8x00 series of PowerMacintosh
@@ -584,7 +584,7 @@ finish:
wake_up_interruptible(&pb->suspendq);
}
-static void add_clip(struct planb *pb, struct video_clip *clip)
+static void add_clip(struct planb *pb, struct video_clip *clip)
{
volatile unsigned char *base;
int xc = clip->x, yc = clip->y;
@@ -758,7 +758,7 @@ static void cmd_buff(struct planb *pb)
PLANB_SET(CH_SYNC));
tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
PLANB_SET(DMA_ABORT));
-
+
/* odd field data: */
jump = virt_to_bus(c1 + nlines / 2);
for (i=1; i < nlines; i += stepsize, c1++)
@@ -1247,7 +1247,7 @@ static volatile struct dbdma_cmd *setup_grab_cmd(int fr, struct planb *pb)
tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;
tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
PLANB_SET(DMA_ABORT));
-
+
/* odd field data: */
jump_addr = c1 + TAB_FACTOR * nlines / 2;
jump = virt_to_bus(jump_addr);
@@ -1383,7 +1383,7 @@ static int planb_open(struct video_device *dev, int mode)
pb->user++;
DEBUG("PlanB: device opened\n");
- return 0;
+ return 0;
}
static void planb_close(struct video_device *dev)
@@ -1424,9 +1424,9 @@ static long planb_write(struct video_device *v, const char *buf,
static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
{
struct planb *pb=(struct planb *)dev;
-
+
switch (cmd)
- {
+ {
case VIDIOCGCAP:
{
struct video_capability b;
@@ -1440,26 +1440,26 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
b.channels = 2; /* composite & svhs */
b.audios = 0;
b.maxwidth = PLANB_MAXPIXELS;
- b.maxheight = PLANB_MAXLINES;
- b.minwidth = 32; /* wild guess */
- b.minheight = 32;
- if (copy_to_user(arg,&b,sizeof(b)))
- return -EFAULT;
+ b.maxheight = PLANB_MAXLINES;
+ b.minwidth = 32; /* wild guess */
+ b.minheight = 32;
+ if (copy_to_user(arg,&b,sizeof(b)))
+ return -EFAULT;
return 0;
}
case VIDIOCSFBUF:
{
- struct video_buffer v;
+ struct video_buffer v;
unsigned short bpp;
unsigned int fmt;
DEBUG("PlanB: IOCTL VIDIOCSFBUF\n");
- if (!capable(CAP_SYS_ADMIN)
+ if (!capable(CAP_SYS_ADMIN)
|| !capable(CAP_SYS_RAWIO))
- return -EPERM;
- if (copy_from_user(&v, arg,sizeof(v)))
- return -EFAULT;
+ return -EPERM;
+ if (copy_from_user(&v, arg,sizeof(v)))
+ return -EFAULT;
planb_lock(pb);
switch(v.depth) {
case 8:
@@ -1478,7 +1478,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
break;
default:
planb_unlock(pb);
- return -EINVAL;
+ return -EINVAL;
}
if (bpp * v.width > v.bytesperline) {
planb_unlock(pb);
@@ -1493,7 +1493,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
pb->win.bpl = pb->win.bpp * pb->win.swidth;
pb->win.pad = v.bytesperline - pb->win.bpl;
- DEBUG("PlanB: Display at %p is %d by %d, bytedepth %d,"
+ DEBUG("PlanB: Display at %p is %d by %d, bytedepth %d,"
" bpl %d (+ %d)\n", v.base, v.width,v.height,
pb->win.bpp, pb->win.bpl, pb->win.pad);
@@ -1504,11 +1504,11 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
resume_overlay(pb);
}
planb_unlock(pb);
- return 0;
+ return 0;
}
case VIDIOCGFBUF:
{
- struct video_buffer v;
+ struct video_buffer v;
DEBUG("PlanB: IOCTL VIDIOCGFBUF\n");
@@ -1518,15 +1518,15 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
v.depth = pb->win.depth;
v.bytesperline = pb->win.bpl + pb->win.pad;
if (copy_to_user(arg, &v, sizeof(v)))
- return -EFAULT;
+ return -EFAULT;
return 0;
}
case VIDIOCCAPTURE:
{
int i;
- if(copy_from_user(&i, arg, sizeof(i)))
- return -EFAULT;
+ if(copy_from_user(&i, arg, sizeof(i)))
+ return -EFAULT;
if(i==0) {
DEBUG("PlanB: IOCTL VIDIOCCAPTURE Stop\n");
@@ -1695,7 +1695,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
struct video_window vw;
struct video_clip clip;
int i;
-
+
DEBUG("PlanB: IOCTL VIDIOCSWIN\n");
if(copy_from_user(&vw,arg,sizeof(vw)))
@@ -1749,7 +1749,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return -EFAULT;
return 0;
}
- case VIDIOCSYNC: {
+ case VIDIOCSYNC: {
int i;
IDEBUG("PlanB: IOCTL VIDIOCSYNC\n");
@@ -1759,42 +1759,42 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
IDEBUG("PlanB: sync to frame %d\n", i);
- if(i > (MAX_GBUFFERS - 1) || i < 0)
- return -EINVAL;
+ if(i > (MAX_GBUFFERS - 1) || i < 0)
+ return -EINVAL;
chk_grab:
- switch (pb->frame_stat[i]) {
- case GBUFFER_UNUSED:
- return -EINVAL;
+ switch (pb->frame_stat[i]) {
+ case GBUFFER_UNUSED:
+ return -EINVAL;
case GBUFFER_GRABBING:
IDEBUG("PlanB: waiting for grab"
" done (%d)\n", i);
- interruptible_sleep_on(&pb->capq);
+ interruptible_sleep_on(&pb->capq);
if(signal_pending(current))
return -EINTR;
goto chk_grab;
- case GBUFFER_DONE:
- pb->frame_stat[i] = GBUFFER_UNUSED;
- break;
- }
- return 0;
+ case GBUFFER_DONE:
+ pb->frame_stat[i] = GBUFFER_UNUSED;
+ break;
+ }
+ return 0;
}
- case VIDIOCMCAPTURE:
+ case VIDIOCMCAPTURE:
{
- struct video_mmap vm;
+ struct video_mmap vm;
volatile unsigned int status;
IDEBUG("PlanB: IOCTL VIDIOCMCAPTURE\n");
if(copy_from_user((void *) &vm,(void *)arg,sizeof(vm)))
return -EFAULT;
- status = pb->frame_stat[vm.frame];
- if (status != GBUFFER_UNUSED)
- return -EBUSY;
+ status = pb->frame_stat[vm.frame];
+ if (status != GBUFFER_UNUSED)
+ return -EBUSY;
- return vgrab(pb, &vm);
+ return vgrab(pb, &vm);
}
-
+
case VIDIOCGMBUF:
{
int i;
@@ -1811,7 +1811,7 @@ chk_grab:
return -EFAULT;
return 0;
}
-
+
case PLANBIOCGSAAREGS:
{
struct planb_saa_regs preg;
@@ -1828,7 +1828,7 @@ chk_grab:
return -EFAULT;
return 0;
}
-
+
case PLANBIOCSSAAREGS:
{
struct planb_saa_regs preg;
@@ -1842,7 +1842,7 @@ chk_grab:
saa_set (preg.addr, preg.val, pb);
return 0;
}
-
+
case PLANBIOCGSTAT:
{
struct planb_stat_regs pstat;
@@ -1859,7 +1859,7 @@ chk_grab:
return -EFAULT;
return 0;
}
-
+
case PLANBIOCSMODE: {
int v;
@@ -1985,10 +1985,10 @@ static int planb_mmap(struct vm_area_struct *vma, struct video_device *dev, cons
{
int i;
struct planb *pb = (struct planb *)dev;
- unsigned long start = (unsigned long)adr;
+ unsigned long start = (unsigned long)adr;
if (size > MAX_GBUFFERS * PLANB_MAX_FBUF)
- return -EINVAL;
+ return -EINVAL;
if (!pb->rawbuf) {
int err;
if((err=grabbuf_alloc(pb)))
@@ -2091,10 +2091,10 @@ static int init_planb(struct planb *pb)
/* clear interrupt mask */
pb->intr_mask = PLANB_CLR_IRQ;
- result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb);
- if (result < 0) {
- if (result==-EINVAL)
- printk(KERN_ERR "PlanB: Bad irq number (%d) "
+ result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb);
+ if (result < 0) {
+ if (result==-EINVAL)
+ printk(KERN_ERR "PlanB: Bad irq number (%d) "
"or handler\n", (int)pb->irq);
else if (result==-EBUSY)
printk(KERN_ERR "PlanB: I don't know why, "
@@ -2102,7 +2102,7 @@ static int init_planb(struct planb *pb)
return result;
}
disable_irq(pb->irq);
-
+
/* Now add the template and register the device unit. */
memcpy(&pb->video_dev,&planb_template,sizeof(planb_template));
@@ -2143,7 +2143,7 @@ static int init_planb(struct planb *pb)
}
/*
- * Scan for a PlanB controller, request the irq and map the io memory
+ * Scan for a PlanB controller, request the irq and map the io memory
*/
static int find_planb(void)
@@ -2156,7 +2156,7 @@ static int find_planb(void)
struct pci_dev *pdev;
int rc;
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return 0;
planb_devices = find_devices("planb");
@@ -2171,9 +2171,9 @@ static int find_planb(void)
pb = &planbs[0];
planb_num = 1;
- if (planb_devices->n_addrs != 1) {
- printk (KERN_WARNING "PlanB: expecting 1 address for planb "
- "(got %d)", planb_devices->n_addrs);
+ if (planb_devices->n_addrs != 1) {
+ printk (KERN_WARNING "PlanB: expecting 1 address for planb "
+ "(got %d)", planb_devices->n_addrs);
return 0;
}
@@ -2236,7 +2236,7 @@ static int find_planb(void)
pb->planb_base = planb_regs;
pb->planb_base_phys = (struct planb_registers *)new_base;
pb->irq = irq;
-
+
return planb_num;
err_out_disable:
@@ -2251,7 +2251,7 @@ static void release_planb(void)
int i;
struct planb *pb;
- for (i=0;i<planb_num; i++)
+ for (i=0;i<planb_num; i++)
{
pb=&planbs[i];
@@ -2278,7 +2278,7 @@ static void release_planb(void)
static int __init init_planbs(void)
{
int i;
-
+
if (find_planb()<=0)
return -EIO;
@@ -2288,9 +2288,9 @@ static int __init init_planbs(void)
" with v4l\n", i);
release_planb();
return -EIO;
- }
+ }
printk(KERN_INFO "PlanB: registered device %d with v4l\n", i);
- }
+ }
return 0;
}
diff --git a/drivers/media/video/planb.h b/drivers/media/video/planb.h
index 79b6b561426..92823211d0c 100644
--- a/drivers/media/video/planb.h
+++ b/drivers/media/video/planb.h
@@ -1,4 +1,4 @@
-/*
+/*
planb - PlanB frame grabber driver
PlanB is used in the 7x00/8x00 series of PowerMacintosh
@@ -167,7 +167,7 @@ struct planb {
struct video_device video_dev;
struct video_picture picture; /* Current picture params */
struct video_audio audio_dev; /* Current audio params */
-
+
volatile struct planb_registers *planb_base; /* virt base of planb */
struct planb_registers *planb_base_phys; /* phys base of planb */
void *priv_space; /* Org. alloc. mem for kfree */
@@ -209,7 +209,7 @@ struct planb {
int gwidth[MAX_GBUFFERS], gheight[MAX_GBUFFERS];
unsigned int gfmt[MAX_GBUFFERS];
int gnorm_switch[MAX_GBUFFERS];
- volatile unsigned int *frame_stat;
+ volatile unsigned int *frame_stat;
#define GBUFFER_UNUSED 0x00U
#define GBUFFER_GRABBING 0x01U
#define GBUFFER_DONE 0x02U
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
index 05ca55939e7..09835ca098b 100644
--- a/drivers/media/video/pms.c
+++ b/drivers/media/video/pms.c
@@ -12,10 +12,10 @@
* Most of this code is directly derived from his userspace driver.
* His driver works so send any reports to alan@redhat.com unless the
* userspace driver also doesn't work for you...
- *
+ *
* Changes:
* 08/07/2003 Daniele Bellucci <bellucda@tiscali.it>
- * - pms_capture: report back -EFAULT
+ * - pms_capture: report back -EFAULT
*/
#include <linux/module.h>
@@ -66,14 +66,14 @@ static int standard = 0; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
/*
* I/O ports and Shared Memory
*/
-
+
static int io_port = 0x250;
static int data_port = 0x251;
static int mem_base = 0xC8000;
static void __iomem *mem;
static int video_nr = -1;
-
+
static inline void mvv_write(u8 index, u8 value)
{
@@ -90,9 +90,9 @@ static int pms_i2c_stat(u8 slave)
{
int counter;
int i;
-
+
outb(0x28, io_port);
-
+
counter=0;
while((inb(data_port)&0x01)==0)
if(counter++==256)
@@ -101,9 +101,9 @@ static int pms_i2c_stat(u8 slave)
while((inb(data_port)&0x01)!=0)
if(counter++==256)
break;
-
+
outb(slave, io_port);
-
+
counter=0;
while((inb(data_port)&0x01)==0)
if(counter++==256)
@@ -112,7 +112,7 @@ static int pms_i2c_stat(u8 slave)
while((inb(data_port)&0x01)!=0)
if(counter++==256)
break;
-
+
for(i=0;i<12;i++)
{
char st=inb(data_port);
@@ -122,7 +122,7 @@ static int pms_i2c_stat(u8 slave)
break;
}
outb(0x29, io_port);
- return inb(data_port);
+ return inb(data_port);
}
static int pms_i2c_write(u16 slave, u16 sub, u16 data)
@@ -130,19 +130,19 @@ static int pms_i2c_write(u16 slave, u16 sub, u16 data)
int skip=0;
int count;
int i;
-
+
for(i=0;i<i2c_count;i++)
{
if((i2cinfo[i].slave==slave) &&
(i2cinfo[i].sub == sub))
{
- if(i2cinfo[i].data==data)
- skip=1;
- i2cinfo[i].data=data;
- i=i2c_count+1;
+ if(i2cinfo[i].data==data)
+ skip=1;
+ i2cinfo[i].data=data;
+ i=i2c_count+1;
}
}
-
+
if(i==i2c_count && i2c_count<64)
{
i2cinfo[i2c_count].slave=slave;
@@ -150,16 +150,16 @@ static int pms_i2c_write(u16 slave, u16 sub, u16 data)
i2cinfo[i2c_count].data=data;
i2c_count++;
}
-
+
if(skip)
return 0;
-
+
mvv_write(0x29, sub);
mvv_write(0x2A, data);
mvv_write(0x28, slave);
-
+
outb(0x28, io_port);
-
+
count=0;
while((inb(data_port)&1)==0)
if(count>255)
@@ -167,9 +167,9 @@ static int pms_i2c_write(u16 slave, u16 sub, u16 data)
while((inb(data_port)&1)!=0)
if(count>255)
break;
-
+
count=inb(data_port);
-
+
if(count&2)
return -1;
return count;
@@ -189,8 +189,8 @@ static int pms_i2c_read(int slave, int sub)
static void pms_i2c_andor(int slave, int sub, int and, int or)
{
- u8 tmp;
-
+ u8 tmp;
+
tmp=pms_i2c_read(slave, sub);
tmp = (tmp&and)|or;
pms_i2c_write(slave, sub, tmp);
@@ -199,7 +199,7 @@ static void pms_i2c_andor(int slave, int sub, int and, int or)
/*
* Control functions
*/
-
+
static void pms_videosource(short source)
{
@@ -234,8 +234,8 @@ static void pms_colour(short colour)
break;
}
}
-
-
+
+
static void pms_contrast(short contrast)
{
switch(decoder)
@@ -269,14 +269,14 @@ static void pms_format(short format)
{
int target;
standard = format;
-
+
if(decoder==PHILIPS1)
target=0x42;
else if(decoder==PHILIPS2)
target=0x8A;
else
return;
-
+
switch(format)
{
case 0: /* Auto */
@@ -302,7 +302,7 @@ static void pms_format(short format)
/*
* These features of the PMS card are not currently exposes. They
- * could become a private v4l ioctl for PMSCONFIG or somesuch if
+ * could become a private v4l ioctl for PMSCONFIG or somesuch if
* people need it. We also don't yet use the PMS interrupt.
*/
@@ -324,7 +324,7 @@ static void pms_hstart(short start)
/*
* Bandpass filters
*/
-
+
static void pms_bandpass(short pass)
{
if(decoder==PHILIPS2)
@@ -493,7 +493,7 @@ static void pms_vert(u8 deciden, u8 decinum)
/*
* Turn 16bit ratios into best small ratio the chipset can grok
*/
-
+
static void pms_vertdeci(unsigned short decinum, unsigned short deciden)
{
/* Knock it down by /5 once */
@@ -546,7 +546,7 @@ static void pms_horzdeci(short decinum, short deciden)
decinum=512;
deciden=640; /* 768 would be ideal */
}
-
+
while(((decinum|deciden)&1)==0)
{
decinum>>=1;
@@ -559,7 +559,7 @@ static void pms_horzdeci(short decinum, short deciden)
}
if(deciden==32)
deciden--;
-
+
mvv_write(0x24, 0x80|deciden);
mvv_write(0x25, decinum);
}
@@ -567,14 +567,14 @@ static void pms_horzdeci(short decinum, short deciden)
static void pms_resolution(short width, short height)
{
int fg_height;
-
+
fg_height=height;
if(fg_height>280)
fg_height=280;
-
+
mvv_write(0x18, fg_height);
mvv_write(0x19, fg_height>>8);
-
+
if(standard==1)
{
mvv_write(0x1A, 0xFC);
@@ -598,7 +598,7 @@ static void pms_resolution(short width, short height)
mvv_write(0x42, 0x00);
mvv_write(0x43, 0x00);
mvv_write(0x44, MVVMEMORYWIDTH);
-
+
mvv_write(0x22, width+8);
mvv_write(0x23, (width+8)>> 8);
@@ -618,7 +618,7 @@ static void pms_resolution(short width, short height)
/*
* Set Input
*/
-
+
static void pms_vcrinput(short input)
{
if(decoder==PHILIPS2)
@@ -643,20 +643,20 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int
mvv_write(0x08,r8); /* capture rgb555/565, init DRAM, PC enable */
/* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
-
- for (y = 0; y < dev->height; y++ )
+
+ for (y = 0; y < dev->height; y++ )
{
writeb(0, mem); /* synchronisiert neue Zeile */
-
+
/*
* This is in truth a fifo, be very careful as if you
* forgot this odd things will occur 8)
*/
-
+
memcpy_fromio(tmp, mem, dw+32); /* discard 16 word */
cnt -= dev->height;
- while (cnt <= 0)
- {
+ while (cnt <= 0)
+ {
/*
* Don't copy too far
*/
@@ -666,7 +666,7 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int
cnt += dev->height;
if (copy_to_user(buf, tmp+32, dt))
return len ? len : -EFAULT;
- buf += dt;
+ buf += dt;
len += dt;
}
}
@@ -683,7 +683,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file,
{
struct video_device *dev = video_devdata(file);
struct pms_device *pd=(struct pms_device *)dev;
-
+
switch(cmd)
{
case VIDIOCGCAP:
@@ -806,7 +806,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file,
||(p->palette==VIDEO_PALETTE_RGB555 && p->depth==15)))
return -EINVAL;
pd->picture= *p;
-
+
/*
* Now load the card.
*/
@@ -815,7 +815,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file,
pms_brightness(p->brightness>>8);
pms_hue(p->hue>>8);
pms_colour(p->colour>>8);
- pms_contrast(p->contrast>>8);
+ pms_contrast(p->contrast>>8);
mutex_unlock(&pd->lock);
return 0;
}
@@ -873,7 +873,7 @@ static ssize_t pms_read(struct file *file, char __user *buf,
struct video_device *v = video_devdata(file);
struct pms_device *pd=(struct pms_device *)v;
int len;
-
+
mutex_lock(&pd->lock);
len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count);
mutex_unlock(&pd->lock);
@@ -905,13 +905,13 @@ static struct pms_device pms_device;
/*
* Probe for and initialise the Mediavision PMS
*/
-
+
static int init_mediavision(void)
{
int id;
int idec, decst;
int i;
-
+
unsigned char i2c_defs[]={
0x4C,0x30,0x00,0xE8,
0xB6,0xE2,0x00,0x00,
@@ -925,7 +925,7 @@ static int init_mediavision(void)
mem = ioremap(mem_base, 0x800);
if (!mem)
return -ENOMEM;
-
+
if (!request_region(0x9A01, 1, "Mediavision PMS config"))
{
printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n");
@@ -941,18 +941,18 @@ static int init_mediavision(void)
}
outb(0xB8, 0x9A01); /* Unlock */
outb(io_port>>4, 0x9A01); /* Set IO port */
-
-
+
+
id=mvv_read(3);
decst=pms_i2c_stat(0x43);
-
+
if(decst!=-1)
idec=2;
else if(pms_i2c_stat(0xb9)!=-1)
idec=3;
else if(pms_i2c_stat(0x8b)!=-1)
idec=1;
- else
+ else
idec=0;
printk(KERN_INFO "PMS type is %d\n", idec);
@@ -966,11 +966,11 @@ static int init_mediavision(void)
/*
* Ok we have a PMS of some sort
*/
-
+
mvv_write(0x04, mem_base>>12); /* Set the memory area */
-
+
/* Ok now load the defaults */
-
+
for(i=0;i<0x19;i++)
{
if(i2c_defs[i]==0xFF)
@@ -978,7 +978,7 @@ static int init_mediavision(void)
else
pms_i2c_write(0x8A, i, i2c_defs[i]);
}
-
+
pms_i2c_write(0xB8,0x00,0x12);
pms_i2c_write(0xB8,0x04,0x00);
pms_i2c_write(0xB8,0x07,0x00);
@@ -987,18 +987,18 @@ static int init_mediavision(void)
pms_i2c_write(0xB8,0x0A,0x00);
pms_i2c_write(0xB8,0x0B,0x10);
pms_i2c_write(0xB8,0x10,0x03);
-
+
mvv_write(0x01, 0x00);
mvv_write(0x05, 0xA0);
mvv_write(0x08, 0x25);
mvv_write(0x09, 0x00);
- mvv_write(0x0A, 0x20|MVVMEMORYWIDTH);
-
+ mvv_write(0x0A, 0x20|MVVMEMORYWIDTH);
+
mvv_write(0x10, 0x02);
mvv_write(0x1E, 0x0C);
mvv_write(0x1F, 0x03);
mvv_write(0x26, 0x06);
-
+
mvv_write(0x2B, 0x00);
mvv_write(0x2C, 0x20);
mvv_write(0x2D, 0x00);
@@ -1018,13 +1018,13 @@ static int init_mediavision(void)
/*
* Initialization and module stuff
*/
-
+
static int __init init_pms_cards(void)
{
printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n");
-
+
data_port = io_port +1;
-
+
if(init_mediavision())
{
printk(KERN_INFO "Board not found.\n");
diff --git a/drivers/usb/media/pwc/Makefile b/drivers/media/video/pwc/Makefile
index 2d93a775011..8326684f49f 100644
--- a/drivers/usb/media/pwc/Makefile
+++ b/drivers/media/video/pwc/Makefile
@@ -15,6 +15,6 @@ default:
endif
clean:
- rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c
+ rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c
rm -rf .tmp_versions
diff --git a/drivers/usb/media/pwc/philips.txt b/drivers/media/video/pwc/philips.txt
index 04a640d723e..11f751a6bda 100644
--- a/drivers/usb/media/pwc/philips.txt
+++ b/drivers/media/video/pwc/philips.txt
@@ -47,17 +47,17 @@ don't know how to set it properly in the driver. The options are:
size
Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
'vga', for an image size of resp. 128x96, 160x120, 176x144,
- 320x240, 352x288 and 640x480 (of course, only for those cameras that
+ 320x240, 352x288 and 640x480 (of course, only for those cameras that
support these resolutions).
fps
Specifies the desired framerate. Is an integer in the range of 4-30.
fbufs
- This paramter specifies the number of internal buffers to use for storing
- frames from the cam. This will help if the process that reads images from
- the cam is a bit slow or momentarely busy. However, on slow machines it
- only introduces lag, so choose carefully. The default is 3, which is
+ This paramter specifies the number of internal buffers to use for storing
+ frames from the cam. This will help if the process that reads images from
+ the cam is a bit slow or momentarely busy. However, on slow machines it
+ only introduces lag, so choose carefully. The default is 3, which is
reasonable. You can set it between 2 and 5.
mbufs
@@ -65,9 +65,9 @@ mbufs
buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
The default is 2, which is adequate for most applications (double
buffering).
-
+
Should you experience a lot of 'Dumping frame...' messages during
- grabbing with a tool that uses mmap(), you might want to increase if.
+ grabbing with a tool that uses mmap(), you might want to increase if.
However, it doesn't really buffer images, it just gives you a bit more
slack when your program is behind. But you need a multi-threaded or
forked program to really take advantage of these buffers.
@@ -88,15 +88,15 @@ power_save
compression (only useful with the plugin)
With this option you can control the compression factor that the camera
- uses to squeeze the image through the USB bus. You can set the
+ uses to squeeze the image through the USB bus. You can set the
parameter between 0 and 3:
0 = prefer uncompressed images; if the requested mode is not available
- in an uncompressed format, the driver will silently switch to low
- compression.
+ in an uncompressed format, the driver will silently switch to low
+ compression.
1 = low compression.
2 = medium compression.
3 = high compression.
-
+
High compression takes less bandwidth of course, but it could also
introduce some unwanted artefacts. The default is 2, medium compression.
See the FAQ on the website for an overview of which modes require
@@ -112,7 +112,7 @@ leds
this is let the LED blink while the camera is in use. This:
leds=500,500
-
+
will blink the LED once every second. But with:
leds=0,0
@@ -123,7 +123,7 @@ leds
when the camera is not used anymore.
This parameter works only with the ToUCam range of cameras (720, 730, 740,
- 750) and OEMs. For other cameras this command is silently ignored, and
+ 750) and OEMs. For other cameras this command is silently ignored, and
the LED cannot be controlled.
Finally: this parameters does not take effect UNTIL the first time you
@@ -144,35 +144,35 @@ dev_hint
format:
[type[.serialnumber]:]node
-
+
The square brackets mean that both the type and the serialnumber are
optional, but a serialnumber cannot be specified without a type (which
would be rather pointless). The serialnumber is separated from the type
by a '.'; the node number by a ':'.
-
+
This somewhat cryptic syntax is best explained by a few examples:
dev_hint=3,5 The first detected cam gets assigned
- /dev/video3, the second /dev/video5. Any
- other cameras will get the first free
- available slot (see below).
+ /dev/video3, the second /dev/video5. Any
+ other cameras will get the first free
+ available slot (see below).
dev_hint=645:1,680:2 The PCA645 camera will get /dev/video1,
- and a PCVC680 /dev/video2.
-
- dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber
- 0123 goes to /dev/video3, the same
- camera model with the 4567 serial
- gets /dev/video0.
+ and a PCVC680 /dev/video2.
+
+ dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber
+ 0123 goes to /dev/video3, the same
+ camera model with the 4567 serial
+ gets /dev/video0.
- dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the
- next 3 Philips cams will use /dev/video4
- through /dev/video6.
+ dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the
+ next 3 Philips cams will use /dev/video4
+ through /dev/video6.
Some points worth knowing:
- - Serialnumbers are case sensitive and must be written full, including
+ - Serialnumbers are case sensitive and must be written full, including
leading zeroes (it's treated as a string).
- - If a device node is already occupied, registration will fail and
+ - If a device node is already occupied, registration will fail and
the webcam is not available.
- You can have up to 64 video devices; be sure to make enough device
nodes in /dev if you want to spread the numbers (this does not apply
@@ -186,13 +186,13 @@ trace
kernel log at debug level.
The trace variable is a bitmask; each bit represents a certain feature.
- If you want to trace something, look up the bit value(s) in the table
+ If you want to trace something, look up the bit value(s) in the table
below, add the values together and supply that to the trace variable.
Value Value Description Default
(dec) (hex)
1 0x1 Module initialization; this will log messages On
- while loading and unloading the module
+ while loading and unloading the module
2 0x2 probe() and disconnect() traces On
@@ -203,7 +203,7 @@ trace
16 0x10 Memory allocation of buffers, etc. Off
32 0x20 Showing underflow, overflow and Dumping frame On
- messages
+ messages
64 0x40 Show viewport and image sizes Off
@@ -217,7 +217,7 @@ trace
Example:
-
+
# modprobe pwc size=cif fps=15 power_save=1
The fbufs, mbufs and trace parameters are global and apply to all connected
diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index 0398b812e0c..4ba549bfa0e 100644
--- a/drivers/usb/media/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -31,17 +31,17 @@
/*
Changes
- 2001/08/03 Alvarado Added methods for changing white balance and
- red/green gains
+ 2001/08/03 Alvarado Added methods for changing white balance and
+ red/green gains
*/
/* Control functions for the cam; brightness, contrast, video mode, etc. */
#ifdef __KERNEL__
-#include <asm/uaccess.h>
+#include <asm/uaccess.h>
#endif
#include <asm/errno.h>
-
+
#include "pwc.h"
#include "pwc-ioctl.h"
#include "pwc-uncompress.h"
@@ -116,13 +116,13 @@ static const char *size2name[PSZ_MAX] =
"SIF",
"CIF",
"VGA",
-};
+};
/********/
-/* Entries for the Nala (645/646) camera; the Nala doesn't have compression
+/* Entries for the Nala (645/646) camera; the Nala doesn't have compression
preferences, so you either get compressed or non-compressed streams.
-
+
An alternate value of 0 means this mode is not available at all.
*/
@@ -205,13 +205,13 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
{ /* closest match of framerate */
0, 0, 0, 0, 4, /* 0-4 */
5, 5, 7, 7, 10, /* 5-9 */
- 10, 10, 12, 12, 15, /* 10-14 */
- 15, 15, 15, 20, 20, /* 15-19 */
- 20, 20, 20, 24, 24, /* 20-24 */
- 24, 24, 24, 24, 24, /* 25-29 */
- 24 /* 30 */
+ 10, 10, 12, 12, 15, /* 10-14 */
+ 15, 15, 15, 20, 20, /* 15-19 */
+ 20, 20, 20, 24, 24, /* 20-24 */
+ 24, 24, 24, 24, 24, /* 25-29 */
+ 24 /* 30 */
};
- int frames2table[31] =
+ int frames2table[31] =
{ 0, 0, 0, 0, 0, /* 0-4 */
1, 1, 1, 2, 2, /* 5-9 */
3, 3, 4, 4, 4, /* 10-14 */
@@ -220,7 +220,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
7, 7, 7, 7, 7, /* 25-29 */
7 /* 30 */
};
-
+
if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
return -EINVAL;
frames = frames2frames[frames];
@@ -232,7 +232,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
if (pEntry->compressed)
return -ENOENT; /* Not supported. */
- memcpy(buf, pEntry->mode, 3);
+ memcpy(buf, pEntry->mode, 3);
ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
if (ret < 0) {
Debug("Failed to send video command... %d\n", ret);
@@ -257,7 +257,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
break;
}
}
-
+
pdev->cmd_len = 3;
memcpy(pdev->cmd_buf, buf, 3);
@@ -352,13 +352,13 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
/* special case: VGA @ 5 fps and snapshot is raw bayer mode */
if (size == PSZ_VGA && frames == 5 && snapshot)
{
- /* Only available in case the raw palette is selected or
- we have the decompressor available. This mode is
- only available in compressed form
+ /* Only available in case the raw palette is selected or
+ we have the decompressor available. This mode is
+ only available in compressed form
*/
if (pdev->vpalette == VIDEO_PALETTE_RAW)
{
- Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette);
+ Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette);
pChoose = &RawEntry;
}
else
@@ -368,9 +368,9 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
}
else
{
- /* Find a supported framerate with progressively higher compression ratios
+ /* Find a supported framerate with progressively higher compression ratios
if the preferred ratio is not available.
- Skip this step when using RAW modes.
+ Skip this step when using RAW modes.
*/
while (compression <= 3) {
pChoose = &Kiara_table[size][fps][compression];
@@ -383,7 +383,7 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
return -ENOENT; /* Not supported. */
Debug("Using alternate setting %d.\n", pChoose->alternate);
-
+
/* usb_control_msg won't take staticly allocated arrays as argument?? */
memcpy(buf, pChoose->mode, 12);
if (snapshot)
@@ -463,9 +463,9 @@ static void pwc_set_image_buffer_size(struct pwc_device *pdev)
*/
int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
{
- int ret, size;
+ int ret, size;
- Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
+ Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
size = pwc_decode_size(pdev, width, height);
if (size < 0) {
Debug("Could not find suitable size.\n");
@@ -473,7 +473,7 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
}
Debug("decode_size = %d.\n", size);
- ret = -EINVAL;
+ ret = -EINVAL;
switch(pdev->type) {
case 645:
case 646:
@@ -485,7 +485,7 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
case 690:
ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
break;
-
+
case 720:
case 730:
case 740:
@@ -517,7 +517,7 @@ int pwc_get_brightness(struct pwc_device *pdev)
char buf;
int ret;
- ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);
+ ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);
if (ret < 0)
return ret;
return buf << 9;
@@ -566,7 +566,7 @@ int pwc_get_gamma(struct pwc_device *pdev)
{
char buf;
int ret;
-
+
ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1);
if (ret < 0)
return ret;
@@ -622,14 +622,14 @@ static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
{
char buf;
int ret;
-
+
if (mode)
buf = 0x0; /* auto */
else
buf = 0xff; /* fixed */
ret = SendControlMsg(SET_LUM_CTL, AGC_MODE_FORMATTER, 1);
-
+
if (!mode && ret >= 0) {
if (value < 0)
value = 0;
@@ -647,7 +647,7 @@ static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
{
unsigned char buf;
int ret;
-
+
ret = RecvControlMsg(GET_LUM_CTL, AGC_MODE_FORMATTER, 1);
if (ret < 0)
return ret;
@@ -658,7 +658,7 @@ static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
return ret;
if (buf > 0x3F)
buf = 0x3F;
- *value = (buf << 10);
+ *value = (buf << 10);
}
else { /* auto */
ret = RecvControlMsg(GET_STATUS_CTL, READ_AGC_FORMATTER, 1);
@@ -683,7 +683,7 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v
buf[0] = 0x0; /* auto */
else
buf[0] = 0xff; /* fixed */
-
+
ret = SendControlMsg(SET_LUM_CTL, SHUTTER_MODE_FORMATTER, 1);
if (!mode && ret >= 0) {
@@ -713,7 +713,7 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v
ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2);
}
return ret;
-}
+}
/* POWER */
@@ -765,22 +765,22 @@ static inline int pwc_restore_factory(struct pwc_device *pdev)
* 02: fluorescent lighting
* 03: manual
* 04: auto
- */
+ */
static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
{
char buf;
int ret;
-
+
if (mode < 0)
mode = 0;
-
+
if (mode > 4)
mode = 4;
-
+
buf = mode & 0x07; /* just the lowest three bits */
-
+
ret = SendControlMsg(SET_CHROM_CTL, WB_MODE_FORMATTER, 1);
-
+
if (ret < 0)
return ret;
return 0;
@@ -790,17 +790,17 @@ static inline int pwc_get_awb(struct pwc_device *pdev)
{
unsigned char buf;
int ret;
-
+
ret = RecvControlMsg(GET_CHROM_CTL, WB_MODE_FORMATTER, 1);
- if (ret < 0)
+ if (ret < 0)
return ret;
return buf;
}
static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
{
- unsigned char buf;
+ unsigned char buf;
if (value < 0)
value = 0;
@@ -815,7 +815,7 @@ static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value)
{
unsigned char buf;
int ret;
-
+
ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
if (ret < 0)
return ret;
@@ -841,7 +841,7 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
{
unsigned char buf;
int ret;
-
+
ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
if (ret < 0)
return ret;
@@ -851,14 +851,14 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
/* The following two functions are different, since they only read the
- internal red/blue gains, which may be different from the manual
+ internal red/blue gains, which may be different from the manual
gains set or read above.
- */
+ */
static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value)
{
unsigned char buf;
int ret;
-
+
ret = RecvControlMsg(GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, 1);
if (ret < 0)
return ret;
@@ -870,7 +870,7 @@ static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
{
unsigned char buf;
int ret;
-
+
ret = RecvControlMsg(GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, 1);
if (ret < 0)
return ret;
@@ -882,7 +882,7 @@ static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
{
unsigned char buf;
-
+
/* useful range is 0x01..0x20 */
buf = speed / 0x7f0;
return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
@@ -892,7 +892,7 @@ static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
{
unsigned char buf;
int ret;
-
+
ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
if (ret < 0)
return ret;
@@ -904,7 +904,7 @@ static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
{
unsigned char buf;
-
+
/* useful range is 0x01..0x3F */
buf = (delay >> 10);
return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
@@ -914,7 +914,7 @@ static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
{
unsigned char buf;
int ret;
-
+
ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
if (ret < 0)
return ret;
@@ -950,7 +950,7 @@ static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
{
unsigned char buf[2];
int ret;
-
+
if (pdev->type < 730) {
*on_value = -1;
*off_value = -1;
@@ -969,7 +969,7 @@ static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
{
unsigned char buf;
int ret;
-
+
if (contour < 0)
buf = 0xff; /* auto contour on */
else
@@ -977,16 +977,16 @@ static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
ret = SendControlMsg(SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1);
if (ret < 0)
return ret;
-
+
if (contour < 0)
return 0;
if (contour > 0xffff)
contour = 0xffff;
-
+
buf = (contour >> 10); /* contour preset is [0..3f] */
ret = SendControlMsg(SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1);
- if (ret < 0)
- return ret;
+ if (ret < 0)
+ return ret;
return 0;
}
@@ -994,7 +994,7 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
{
unsigned char buf;
int ret;
-
+
ret = RecvControlMsg(GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1);
if (ret < 0)
return ret;
@@ -1002,7 +1002,7 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
if (buf == 0) {
/* auto mode off, query current preset value */
ret = RecvControlMsg(GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1);
- if (ret < 0)
+ if (ret < 0)
return ret;
*contour = buf << 10;
}
@@ -1015,7 +1015,7 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
{
unsigned char buf;
-
+
if (backlight)
buf = 0xff;
else
@@ -1027,7 +1027,7 @@ static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
{
int ret;
unsigned char buf;
-
+
ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
if (ret < 0)
return ret;
@@ -1039,7 +1039,7 @@ static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
{
unsigned char buf;
-
+
if (flicker)
buf = 0xff;
else
@@ -1051,7 +1051,7 @@ static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
{
int ret;
unsigned char buf;
-
+
ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
if (ret < 0)
return ret;
@@ -1076,7 +1076,7 @@ static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
{
int ret;
unsigned char buf;
-
+
ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
if (ret < 0)
return ret;
@@ -1087,7 +1087,7 @@ static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
static int pwc_mpt_reset(struct pwc_device *pdev, int flags)
{
unsigned char buf;
-
+
buf = flags & 0x03; // only lower two bits are currently used
return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);
}
@@ -1095,7 +1095,7 @@ static int pwc_mpt_reset(struct pwc_device *pdev, int flags)
static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
{
unsigned char buf[4];
-
+
/* set new relative angle; angles are expressed in degrees * 100,
but cam as .5 degree resolution, hence divide by 200. Also
the angle must be multiplied by 64 before it's send to
@@ -1114,7 +1114,7 @@ static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_sta
{
int ret;
unsigned char buf[5];
-
+
ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5);
if (ret < 0)
return ret;
@@ -1129,14 +1129,14 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
{
unsigned char buf;
int ret = -1, request;
-
+
if (pdev->type < 675)
request = SENSOR_TYPE_FORMATTER1;
else if (pdev->type < 730)
return -1; /* The Vesta series doesn't have this call */
else
request = SENSOR_TYPE_FORMATTER2;
-
+
ret = RecvControlMsg(GET_STATUS_CTL, request, 1);
if (ret < 0)
return ret;
@@ -1163,23 +1163,23 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = -EINVAL;
break;
}
-
+
case VIDIOCPWCSUSER:
{
if (pwc_save_user(pdev))
ret = -EINVAL;
break;
}
-
+
case VIDIOCPWCFACTORY:
{
if (pwc_restore_factory(pdev))
ret = -EINVAL;
break;
}
-
+
case VIDIOCPWCSCQUAL:
- {
+ {
int *qual = arg;
if (*qual < 0 || *qual > 3)
@@ -1190,14 +1190,14 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
pdev->vcompression = *qual;
break;
}
-
+
case VIDIOCPWCGCQUAL:
{
int *qual = arg;
*qual = pdev->vcompression;
break;
}
-
+
case VIDIOCPWCPROBE:
{
struct pwc_probe *probe = arg;
@@ -1220,27 +1220,27 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = -EINVAL;
break;
}
-
+
case VIDIOCPWCGAGC:
{
int *agc = arg;
-
+
if (pwc_get_agc(pdev, agc))
ret = -EINVAL;
break;
}
-
+
case VIDIOCPWCSSHUTTER:
{
int *shutter_speed = arg;
ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed);
break;
}
-
- case VIDIOCPWCSAWB:
+
+ case VIDIOCPWCSAWB:
{
struct pwc_whitebalance *wb = arg;
-
+
ret = pwc_set_awb(pdev, wb->mode);
if (ret >= 0 && wb->mode == PWC_WB_MANUAL) {
pwc_set_red_gain(pdev, wb->manual_red);
@@ -1270,18 +1270,18 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = pwc_read_red_gain(pdev, &wb->read_red);
if (ret < 0)
break;
- ret = pwc_read_blue_gain(pdev, &wb->read_blue);
- if (ret < 0)
- break;
+ ret = pwc_read_blue_gain(pdev, &wb->read_blue);
+ if (ret < 0)
+ break;
}
}
break;
}
-
+
case VIDIOCPWCSAWBSPEED:
{
struct pwc_wb_speed *wbs = arg;
-
+
if (wbs->control_speed > 0) {
ret = pwc_set_wb_speed(pdev, wbs->control_speed);
}
@@ -1290,11 +1290,11 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
}
break;
}
-
+
case VIDIOCPWCGAWBSPEED:
{
struct pwc_wb_speed *wbs = arg;
-
+
ret = pwc_get_wb_speed(pdev, &wbs->control_speed);
if (ret < 0)
break;
@@ -1304,7 +1304,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
break;
}
- case VIDIOCPWCSLED:
+ case VIDIOCPWCSLED:
{
struct pwc_leds *leds = arg;
ret = pwc_set_leds(pdev, leds->led_on, leds->led_off);
@@ -1325,14 +1325,14 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = pwc_set_contour(pdev, *contour);
break;
}
-
+
case VIDIOCPWCGCONTOUR:
{
int *contour = arg;
ret = pwc_get_contour(pdev, contour);
break;
}
-
+
case VIDIOCPWCSBACKLIGHT:
{
int *backlight = arg;
@@ -1346,7 +1346,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = pwc_get_backlight(pdev, backlight);
break;
}
-
+
case VIDIOCPWCSFLICKER:
{
int *flicker = arg;
@@ -1360,14 +1360,14 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = pwc_get_flicker(pdev, flicker);
break;
}
-
+
case VIDIOCPWCSDYNNOISE:
{
int *dynnoise = arg;
ret = pwc_set_dynamic_noise(pdev, *dynnoise);
break;
}
-
+
case VIDIOCPWCGDYNNOISE:
{
int *dynnoise = arg;
@@ -1381,61 +1381,61 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
size->width = pdev->image.x;
size->height = pdev->image.y;
break;
- }
-
- case VIDIOCPWCMPTRESET:
- {
- if (pdev->features & FEATURE_MOTOR_PANTILT)
- {
- int *flags = arg;
+ }
+
+ case VIDIOCPWCMPTRESET:
+ {
+ if (pdev->features & FEATURE_MOTOR_PANTILT)
+ {
+ int *flags = arg;
ret = pwc_mpt_reset(pdev, *flags);
- if (ret >= 0)
- {
- pdev->pan_angle = 0;
- pdev->tilt_angle = 0;
- }
- }
- else
- {
- ret = -ENXIO;
- }
- break;
- }
-
- case VIDIOCPWCMPTGRANGE:
- {
- if (pdev->features & FEATURE_MOTOR_PANTILT)
- {
- struct pwc_mpt_range *range = arg;
- *range = pdev->angle_range;
- }
- else
- {
- ret = -ENXIO;
- }
- break;
- }
-
- case VIDIOCPWCMPTSANGLE:
- {
- int new_pan, new_tilt;
-
- if (pdev->features & FEATURE_MOTOR_PANTILT)
- {
- struct pwc_mpt_angles *angles = arg;
+ if (ret >= 0)
+ {
+ pdev->pan_angle = 0;
+ pdev->tilt_angle = 0;
+ }
+ }
+ else
+ {
+ ret = -ENXIO;
+ }
+ break;
+ }
+
+ case VIDIOCPWCMPTGRANGE:
+ {
+ if (pdev->features & FEATURE_MOTOR_PANTILT)
+ {
+ struct pwc_mpt_range *range = arg;
+ *range = pdev->angle_range;
+ }
+ else
+ {
+ ret = -ENXIO;
+ }
+ break;
+ }
+
+ case VIDIOCPWCMPTSANGLE:
+ {
+ int new_pan, new_tilt;
+
+ if (pdev->features & FEATURE_MOTOR_PANTILT)
+ {
+ struct pwc_mpt_angles *angles = arg;
/* The camera can only set relative angles, so
do some calculations when getting an absolute angle .
*/
if (angles->absolute)
{
- new_pan = angles->pan;
- new_tilt = angles->tilt;
- }
- else
- {
- new_pan = pdev->pan_angle + angles->pan;
- new_tilt = pdev->tilt_angle + angles->tilt;
+ new_pan = angles->pan;
+ new_tilt = angles->tilt;
+ }
+ else
+ {
+ new_pan = pdev->pan_angle + angles->pan;
+ new_tilt = pdev->tilt_angle + angles->tilt;
}
/* check absolute ranges */
if (new_pan < pdev->angle_range.pan_min ||
@@ -1463,53 +1463,53 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
pdev->tilt_angle += new_tilt;
}
if (ret == -EPIPE) /* stall -> out of range */
- ret = -ERANGE;
+ ret = -ERANGE;
}
- }
- else
- {
- ret = -ENXIO;
- }
- break;
- }
-
- case VIDIOCPWCMPTGANGLE:
- {
-
- if (pdev->features & FEATURE_MOTOR_PANTILT)
- {
- struct pwc_mpt_angles *angles = arg;
-
- angles->absolute = 1;
- angles->pan = pdev->pan_angle;
- angles->tilt = pdev->tilt_angle;
- }
- else
- {
- ret = -ENXIO;
- }
- break;
- }
-
- case VIDIOCPWCMPTSTATUS:
- {
- if (pdev->features & FEATURE_MOTOR_PANTILT)
- {
- struct pwc_mpt_status *status = arg;
- ret = pwc_mpt_get_status(pdev, status);
- }
- else
- {
- ret = -ENXIO;
- }
- break;
+ }
+ else
+ {
+ ret = -ENXIO;
+ }
+ break;
+ }
+
+ case VIDIOCPWCMPTGANGLE:
+ {
+
+ if (pdev->features & FEATURE_MOTOR_PANTILT)
+ {
+ struct pwc_mpt_angles *angles = arg;
+
+ angles->absolute = 1;
+ angles->pan = pdev->pan_angle;
+ angles->tilt = pdev->tilt_angle;
+ }
+ else
+ {
+ ret = -ENXIO;
+ }
+ break;
+ }
+
+ case VIDIOCPWCMPTSTATUS:
+ {
+ if (pdev->features & FEATURE_MOTOR_PANTILT)
+ {
+ struct pwc_mpt_status *status = arg;
+ ret = pwc_mpt_get_status(pdev, status);
+ }
+ else
+ {
+ ret = -ENXIO;
+ }
+ break;
}
case VIDIOCPWCGVIDCMD:
{
struct pwc_video_command *cmd = arg;
-
- cmd->type = pdev->type;
+
+ cmd->type = pdev->type;
cmd->release = pdev->release;
cmd->command_len = pdev->cmd_len;
memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len);
@@ -1531,7 +1531,7 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret = -ENOIOCTLCMD;
break;
}
-
+
if (ret > 0)
return 0;
return ret;
diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 90eb2604281..41418294a32 100644
--- a/drivers/usb/media/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -25,18 +25,18 @@
*/
-/*
+/*
This code forms the interface between the USB layers and the Philips
specific stuff. Some adanved stuff of the driver falls under an
NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
- is thus not distributed in source form. The binary pwcx.o module
+ is thus not distributed in source form. The binary pwcx.o module
contains the code that falls under the NDA.
-
- In case you're wondering: 'pwc' stands for "Philips WebCam", but
+
+ In case you're wondering: 'pwc' stands for "Philips WebCam", but
I really didn't want to type 'philips_web_cam' every time (I'm lazy as
any Linux kernel hacker, but I don't like uncomprehensible abbreviations
without explanation).
-
+
Oh yes, convention: to disctinguish between all the various pointers to
device-structures, I use these names for the pointer variables:
udev: struct usb_device *
@@ -170,14 +170,14 @@ static struct video_device pwc_template = {
/* Okay, this is some magic that I worked out and the reasoning behind it...
- The biggest problem with any USB device is of course: "what to do
+ The biggest problem with any USB device is of course: "what to do
when the user unplugs the device while it is in use by an application?"
We have several options:
1) Curse them with the 7 plagues when they do (requires divine intervention)
2) Tell them not to (won't work: they'll do it anyway)
3) Oops the kernel (this will have a negative effect on a user's uptime)
4) Do something sensible.
-
+
Of course, we go for option 4.
It happens that this device will be linked to two times, once from
@@ -185,15 +185,15 @@ static struct video_device pwc_template = {
pointers. This is done when the device is probed() and all initialization
succeeded. The pwc_device struct links back to both structures.
- When a device is unplugged while in use it will be removed from the
- list of known USB devices; I also de-register it as a V4L device, but
+ When a device is unplugged while in use it will be removed from the
+ list of known USB devices; I also de-register it as a V4L device, but
unfortunately I can't free the memory since the struct is still in use
by the file descriptor. This free-ing is then deferend until the first
opportunity. Crude, but it works.
-
+
A small 'advantage' is that if a user unplugs the cam and plugs it back
in, it should get assigned the same video device minor, but unfortunately
- it's non-trivial to re-link the cam back to the video device... (that
+ it's non-trivial to re-link the cam back to the video device... (that
would surely be magic! :))
*/
@@ -203,14 +203,14 @@ static struct video_device pwc_template = {
/* Here we want the physical address of the memory.
* This is used when initializing the contents of the area.
*/
-static inline unsigned long kvirt_to_pa(unsigned long adr)
+static inline unsigned long kvirt_to_pa(unsigned long adr)
{
- unsigned long kva, ret;
+ unsigned long kva, ret;
kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
kva |= adr & (PAGE_SIZE-1); /* restore the offset */
ret = __pa(kva);
- return ret;
+ return ret;
}
static void * rvmalloc(unsigned long size)
@@ -219,13 +219,13 @@ static void * rvmalloc(unsigned long size)
unsigned long adr;
size=PAGE_ALIGN(size);
- mem=vmalloc_32(size);
- if (mem)
+ mem=vmalloc_32(size);
+ if (mem)
{
memset(mem, 0, size); /* Clear the ram out, no junk to the user */
- adr=(unsigned long) mem;
- while (size > 0)
- {
+ adr=(unsigned long) mem;
+ while (size > 0)
+ {
SetPageReserved(vmalloc_to_page((void *)adr));
adr+=PAGE_SIZE;
size-=PAGE_SIZE;
@@ -236,13 +236,13 @@ static void * rvmalloc(unsigned long size)
static void rvfree(void * mem, unsigned long size)
{
- unsigned long adr;
+ unsigned long adr;
- if (mem)
+ if (mem)
{
- adr=(unsigned long) mem;
- while ((long) size > 0)
- {
+ adr=(unsigned long) mem;
+ while ((long) size > 0)
+ {
ClearPageReserved(vmalloc_to_page((void *)adr));
adr+=PAGE_SIZE;
size-=PAGE_SIZE;
@@ -263,13 +263,13 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
if (pdev == NULL)
return -ENXIO;
-
+
#ifdef PWC_MAGIC
if (pdev->magic != PWC_MAGIC) {
Err("allocate_buffers(): magic failed.\n");
return -ENXIO;
}
-#endif
+#endif
/* Allocate Isochronous pipe buffers */
for (i = 0; i < MAX_ISO_BUFS; i++) {
if (pdev->sbuf[i].data == NULL) {
@@ -308,7 +308,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
memset(kbuf, 128, PWC_FRAME_SIZE);
}
}
-
+
/* Allocate decompressor table space */
kbuf = NULL;
switch (pdev->type)
@@ -320,7 +320,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
case 730:
case 740:
case 750:
-#if 0
+#if 0
Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private));
kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); /* Timon & Kiara */
break;
@@ -329,11 +329,11 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
/* TODO & FIXME */
kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
break;
-#endif
+#endif
;
}
pdev->decompress_data = kbuf;
-
+
/* Allocate image buffer; double buffer for mmap() */
kbuf = rvmalloc(default_mbufs * pdev->len_per_image);
if (kbuf == NULL) {
@@ -348,7 +348,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
pdev->image_ptr[i] = NULL;
kbuf = NULL;
-
+
Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n");
return 0;
}
@@ -366,7 +366,7 @@ static void pwc_free_buffers(struct pwc_device *pdev)
Err("free_buffers(): magic failed.\n");
return;
}
-#endif
+#endif
/* Release Iso-pipe buffers */
for (i = 0; i < MAX_ISO_BUFS; i++)
@@ -403,17 +403,17 @@ static void pwc_free_buffers(struct pwc_device *pdev)
rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
}
pdev->image_data = NULL;
-
+
Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
}
-/* The frame & image buffer mess.
+/* The frame & image buffer mess.
Yes, this is a mess. Well, it used to be simple, but alas... In this
module, 3 buffers schemes are used to get the data from the USB bus to
the user program. The first scheme involves the ISO buffers (called thus
since they transport ISO data from the USB controller), and not really
- interesting. Suffices to say the data from this buffer is quickly
+ interesting. Suffices to say the data from this buffer is quickly
gathered in an interrupt handler (pwc_isoc_handler) and placed into the
frame buffer.
@@ -443,8 +443,8 @@ static void pwc_free_buffers(struct pwc_device *pdev)
and a 'full' frame list:
* Initially, all frame buffers but one are on the 'empty' list; the one
remaining buffer is our initial fill frame.
- * If a frame is needed for filling, we try to take it from the 'empty'
- list, unless that list is empty, in which case we take the buffer at
+ * If a frame is needed for filling, we try to take it from the 'empty'
+ list, unless that list is empty, in which case we take the buffer at
the head of the 'full' list.
* When our fill buffer has been filled, it is appended to the 'full'
list.
@@ -646,7 +646,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break;
}
Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
- /* Give up after a number of contiguous errors on the USB bus.
+ /* Give up after a number of contiguous errors on the USB bus.
Appearantly something is wrong so we simulate an unplug event.
*/
if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
@@ -673,8 +673,8 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
pdev->visoc_errors = 0;
/* vsync: 0 = don't copy data
- 1 = sync-hunt
- 2 = synched
+ 1 = sync-hunt
+ 2 = synched
*/
/* Compact data */
for (i = 0; i < urb->number_of_packets; i++) {
@@ -701,18 +701,18 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
} /* ..flen > 0 */
if (flen < pdev->vlast_packet_size) {
- /* Shorter packet... We probably have the end of an image-frame;
+ /* Shorter packet... We probably have the end of an image-frame;
wake up read() process and let select()/poll() do something.
Decompression is done in user time over there.
*/
if (pdev->vsync == 2) {
- /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
- frames on the USB wire after an exposure change. This conditition is
+ /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
+ frames on the USB wire after an exposure change. This conditition is
however detected in the cam and a bit is set in the header.
*/
if (pdev->type == 730) {
unsigned char *ptr = (unsigned char *)fbuf->data;
-
+
if (ptr[1] == 1 && ptr[0] & 0x10) {
#if PWC_DEBUG
Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
@@ -733,13 +733,13 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
Info("Image is normal.\n");
}
pdev->vmirror = ptr[0] & 0x03;
- /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
+ /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
after a short frame; this condition is filtered out specifically. A 4 byte
frame doesn't make sense anyway.
- So we get either this sequence:
- drop_bit set -> 4 byte frame -> short frame -> good frame
+ So we get either this sequence:
+ drop_bit set -> 4 byte frame -> short frame -> good frame
Or this one:
- drop_bit set -> short frame -> good frame
+ drop_bit set -> short frame -> good frame
So we drop either 3 or 2 frames in all!
*/
if (fbuf->filled == 4)
@@ -830,7 +830,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
intf = usb_ifnum_to_if(udev, 0);
if (intf)
idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
-
+
if (!idesc)
return -EFAULT;
@@ -841,7 +841,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
break;
}
-
+
if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
Err("Failed to find packet size for video endpoint in current alternate setting.\n");
return -ENFILE; /* Odd error, that should be noticeable */
@@ -875,18 +875,18 @@ static int pwc_isoc_init(struct pwc_device *pdev)
return ret;
}
- /* init URB structure */
+ /* init URB structure */
for (i = 0; i < MAX_ISO_BUFS; i++) {
urb = pdev->sbuf[i].urb;
urb->interval = 1; // devik
urb->dev = udev;
- urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
+ urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
urb->transfer_flags = URB_ISO_ASAP;
- urb->transfer_buffer = pdev->sbuf[i].data;
- urb->transfer_buffer_length = ISO_BUFFER_SIZE;
- urb->complete = pwc_isoc_handler;
- urb->context = pdev;
+ urb->transfer_buffer = pdev->sbuf[i].data;
+ urb->transfer_buffer_length = ISO_BUFFER_SIZE;
+ urb->complete = pwc_isoc_handler;
+ urb->context = pdev;
urb->start_frame = 0;
urb->number_of_packets = ISO_FRAMES_PER_DESC;
for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
@@ -935,7 +935,7 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev)
}
/* Stop camera, but only if we are sure the camera is still there (unplug
- is signalled by EPIPE)
+ is signalled by EPIPE)
*/
if (pdev->error_status && pdev->error_status != EPIPE) {
Trace(TRACE_OPEN, "Setting alternate interface 0.\n");
@@ -956,12 +956,12 @@ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_f
pwc_reset_buffers(pdev);
/* Try to set video mode... */
start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
- if (ret) {
- Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n");
+ if (ret) {
+ Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n");
/* That failed... restore old mode (we know that worked) */
start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
if (start) {
- Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n");
+ Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n");
}
}
if (start == 0)
@@ -987,18 +987,18 @@ static int pwc_video_open(struct inode *inode, struct file *file)
struct pwc_device *pdev;
Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev);
-
+
pdev = (struct pwc_device *)vdev->priv;
if (pdev == NULL)
BUG();
if (pdev->vopen)
return -EBUSY;
-
+
down(&pdev->modlock);
if (!pdev->usb_init) {
Trace(TRACE_OPEN, "Doing first time initialization.\n");
pdev->usb_init = 1;
-
+
if (pwc_trace & TRACE_OPEN)
{
/* Query sensor type */
@@ -1036,7 +1036,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
/* Set LED on/off time */
if (pwc_set_leds(pdev, led_on, led_off) < 0)
Info("Failed to set LED on/off time.\n");
-
+
pwc_construct(pdev); /* set min/max sizes correct */
/* So far, so good. Allocate memory. */
@@ -1046,7 +1046,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
up(&pdev->modlock);
return i;
}
-
+
/* Reset buffers & parameters */
pwc_reset_buffers(pdev);
for (i = 0; i < default_mbufs; i++)
@@ -1081,7 +1081,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
up(&pdev->modlock);
return i;
}
-
+
i = pwc_isoc_init(pdev);
if (i) {
Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
@@ -1155,13 +1155,13 @@ static int pwc_video_close(struct inode *inode, struct file *file)
/*
* FIXME: what about two parallel reads ????
* ANSWER: Not supported. You can't open the device more than once,
- despite what the V4L1 interface says. First, I don't see
- the need, second there's no mechanism of alerting the
- 2nd/3rd/... process of events like changing image size.
- And I don't see the point of blocking that for the
- 2nd/3rd/... process.
- In multi-threaded environments reading parallel from any
- device is tricky anyhow.
+ despite what the V4L1 interface says. First, I don't see
+ the need, second there's no mechanism of alerting the
+ 2nd/3rd/... process of events like changing image size.
+ And I don't see the point of blocking that for the
+ 2nd/3rd/... process.
+ In multi-threaded environments reading parallel from any
+ device is tricky anyhow.
*/
static ssize_t pwc_video_read(struct file *file, char __user * buf,
@@ -1171,7 +1171,7 @@ static ssize_t pwc_video_read(struct file *file, char __user * buf,
struct pwc_device *pdev;
int noblock = file->f_flags & O_NONBLOCK;
DECLARE_WAITQUEUE(wait, current);
- int bytes_to_read;
+ int bytes_to_read;
Trace(TRACE_READ, "video_read(0x%p, %p, %zu) called.\n", vdev, buf, count);
if (vdev == NULL)
@@ -1193,22 +1193,22 @@ static ssize_t pwc_video_read(struct file *file, char __user * buf,
set_current_state(TASK_RUNNING);
return -pdev->error_status ;
}
- if (noblock) {
- remove_wait_queue(&pdev->frameq, &wait);
- set_current_state(TASK_RUNNING);
- return -EWOULDBLOCK;
- }
- if (signal_pending(current)) {
- remove_wait_queue(&pdev->frameq, &wait);
- set_current_state(TASK_RUNNING);
- return -ERESTARTSYS;
- }
- schedule();
- set_current_state(TASK_INTERRUPTIBLE);
+ if (noblock) {
+ remove_wait_queue(&pdev->frameq, &wait);
+ set_current_state(TASK_RUNNING);
+ return -EWOULDBLOCK;
+ }
+ if (signal_pending(current)) {
+ remove_wait_queue(&pdev->frameq, &wait);
+ set_current_state(TASK_RUNNING);
+ return -ERESTARTSYS;
+ }
+ schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
}
remove_wait_queue(&pdev->frameq, &wait);
set_current_state(TASK_RUNNING);
-
+
/* Decompress and release frame */
if (pwc_handle_frame(pdev))
return -EFAULT;
@@ -1218,7 +1218,7 @@ static ssize_t pwc_video_read(struct file *file, char __user * buf,
if (pdev->vpalette == VIDEO_PALETTE_RAW)
bytes_to_read = pdev->frame_size;
else
- bytes_to_read = pdev->view.size;
+ bytes_to_read = pdev->view.size;
/* copy bytes to user space; we allow for partial reads */
if (count + pdev->image_read_pos > bytes_to_read)
@@ -1348,11 +1348,11 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
struct video_picture *p = arg;
/*
* FIXME: Suppose we are mid read
- ANSWER: No problem: the firmware of the camera
- can handle brightness/contrast/etc
- changes at _any_ time, and the palette
- is used exactly once in the uncompress
- routine.
+ ANSWER: No problem: the firmware of the camera
+ can handle brightness/contrast/etc
+ changes at _any_ time, and the palette
+ is used exactly once in the uncompress
+ routine.
*/
pwc_set_brightness(pdev, p->brightness);
pwc_set_contrast(pdev, p->contrast);
@@ -1373,21 +1373,21 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
break;
}
- /* Window/size parameters */
+ /* Window/size parameters */
case VIDIOCGWIN:
{
struct video_window *vw = arg;
-
+
vw->x = 0;
vw->y = 0;
vw->width = pdev->view.x;
vw->height = pdev->view.y;
vw->chromakey = 0;
- vw->flags = (pdev->vframes << PWC_FPS_SHIFT) |
- (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
+ vw->flags = (pdev->vframes << PWC_FPS_SHIFT) |
+ (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
break;
}
-
+
case VIDIOCSWIN:
{
struct video_window *vw = arg;
@@ -1402,9 +1402,9 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
if (ret)
return ret;
- break;
+ break;
}
-
+
/* We don't have overlay support (yet) */
case VIDIOCGFBUF:
{
@@ -1471,8 +1471,8 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
return -EBUSY; /* buffer wasn't available. Bummer */
pdev->image_used[vm->frame] = 1;
- /* Okay, we're done here. In the SYNC call we wait until a
- frame comes available, then expand image into the given
+ /* Okay, we're done here. In the SYNC call we wait until a
+ frame comes available, then expand image into the given
buffer.
In contrast to the CPiA cam the Philips cams deliver a
constant stream, almost like a grabber card. Also,
@@ -1487,16 +1487,16 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
{
/* The doc says: "Whenever a buffer is used it should
call VIDIOCSYNC to free this frame up and continue."
-
- The only odd thing about this whole procedure is
+
+ The only odd thing about this whole procedure is
that MCAPTURE flags the buffer as "in use", and
- SYNC immediately unmarks it, while it isn't
+ SYNC immediately unmarks it, while it isn't
after SYNC that you know that the buffer actually
got filled! So you better not start a CAPTURE in
- the same frame immediately (use double buffering).
- This is not a problem for this cam, since it has
- extra intermediate buffers, but a hardware
- grabber card will then overwrite the buffer
+ the same frame immediately (use double buffering).
+ This is not a problem for this cam, since it has
+ extra intermediate buffers, but a hardware
+ grabber card will then overwrite the buffer
you're working on.
*/
int *mbuf = arg;
@@ -1512,10 +1512,10 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
/* Add ourselves to the frame wait-queue.
-
+
FIXME: needs auditing for safety.
QUESTION: In what respect? I think that using the
- frameq is safe now.
+ frameq is safe now.
*/
add_wait_queue(&pdev->frameq, &wait);
while (pdev->full_frames == NULL) {
@@ -1524,21 +1524,21 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
set_current_state(TASK_RUNNING);
return -pdev->error_status;
}
-
- if (signal_pending(current)) {
- remove_wait_queue(&pdev->frameq, &wait);
- set_current_state(TASK_RUNNING);
- return -ERESTARTSYS;
- }
- schedule();
- set_current_state(TASK_INTERRUPTIBLE);
+
+ if (signal_pending(current)) {
+ remove_wait_queue(&pdev->frameq, &wait);
+ set_current_state(TASK_RUNNING);
+ return -ERESTARTSYS;
+ }
+ schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
}
remove_wait_queue(&pdev->frameq, &wait);
set_current_state(TASK_RUNNING);
-
- /* The frame is ready. Expand in the image buffer
- requested by the user. I don't care if you
- mmap() 5 buffers and request data in this order:
+
+ /* The frame is ready. Expand in the image buffer
+ requested by the user. I don't care if you
+ mmap() 5 buffers and request data in this order:
buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
Grabber hardware may not be so forgiving.
*/
@@ -1551,11 +1551,11 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
break;
}
-
+
case VIDIOCGAUDIO:
{
struct video_audio *v = arg;
-
+
strcpy(v->name, "Microphone");
v->audio = -1; /* unknown audio minor */
v->flags = 0;
@@ -1565,19 +1565,19 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
v->treble = 0;
v->balance = 0x8000;
v->step = 1;
- break;
+ break;
}
-
+
case VIDIOCSAUDIO:
{
/* Dummy: nothing can be set */
break;
}
-
+
case VIDIOCGUNIT:
{
struct video_unit *vu = arg;
-
+
vu->video = pdev->vdev->minor & 0x3F;
vu->audio = -1; /* not known yet */
vu->vbi = -1;
@@ -1589,7 +1589,7 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
return pwc_ioctl(pdev, cmd, arg);
} /* ..switch */
return 0;
-}
+}
static int pwc_video_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
@@ -1605,10 +1605,10 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
unsigned long start = vma->vm_start;
unsigned long size = vma->vm_end-vma->vm_start;
unsigned long page, pos;
-
+
Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
pdev = vdev->priv;
-
+
vma->vm_flags |= VM_IO;
pos = (unsigned long)pdev->image_data;
@@ -1646,7 +1646,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
char serial_number[30], *name;
/* Check if we can handle this device */
- Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n",
+ Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n",
le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct),
intf->altsetting->desc.bInterfaceNumber);
@@ -1770,11 +1770,11 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
name = "Logitech QuickCam (res.)";
type_id = 730; /* Assuming CMOS */
break;
- default:
+ default:
return -ENODEV;
- break;
- }
- }
+ break;
+ }
+ }
else if (vendor_id == 0x055d) {
/* I don't know the difference between the C10 and the C30;
I suppose the difference is the sensor, but both cameras
@@ -1837,7 +1837,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
return -ENODEV;
break;
}
-
+
}
else if (vendor_id == 0x0d81) {
switch(product_id) {
@@ -1856,7 +1856,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
break;
}
}
- else
+ else
return -ENODEV; /* Not any of the know types; but the list keeps growing. */
memset(serial_number, 0, 30);
@@ -1880,9 +1880,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
if (vendor_id == 0x046D && product_id == 0x08B5)
{
/* Logitech QuickCam Orbit
- The ranges have been determined experimentally; they may differ from cam to cam.
- Also, the exact ranges left-right and up-down are different for my cam
- */
+ The ranges have been determined experimentally; they may differ from cam to cam.
+ Also, the exact ranges left-right and up-down are different for my cam
+ */
pdev->angle_range.pan_min = -7000;
pdev->angle_range.pan_max = 7000;
pdev->angle_range.tilt_min = -3000;
@@ -1939,7 +1939,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
}
/* occupy slot */
- if (hint < MAX_DEV_HINTS)
+ if (hint < MAX_DEV_HINTS)
device_hint[hint].pdev = pdev;
Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
@@ -1968,13 +1968,13 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
goto disconnect_out;
}
-#ifdef PWC_MAGIC
+#ifdef PWC_MAGIC
if (pdev->magic != PWC_MAGIC) {
Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n");
goto disconnect_out;
}
#endif
-
+
/* We got unplugged; this is signalled by an EPIPE error code */
if (pdev->vopen) {
Info("Disconnected while webcam is in use!\n");
@@ -2017,8 +2017,8 @@ static int pwc_atoi(const char *s)
}
-/*
- * Initialization code & module stuff
+/*
+ * Initialization code & module stuff
*/
static char size[10];
@@ -2168,7 +2168,7 @@ static int __init usb_pwc_init(void)
if (*dot != '\0') {
/* There's a serial number as well */
int k;
-
+
dot++;
k = 0;
while (*dot != ':' && k < 29) {
@@ -2178,18 +2178,18 @@ static int __init usb_pwc_init(void)
device_hint[i].serial_number[k] = '\0';
}
}
-#if PWC_DEBUG
+#if PWC_DEBUG
Debug("device_hint[%d]:\n", i);
Debug(" type : %d\n", device_hint[i].type);
Debug(" serial# : %s\n", device_hint[i].serial_number);
Debug(" node : %d\n", device_hint[i].device_node);
-#endif
+#endif
}
else
device_hint[i].type = 0; /* not filled */
} /* ..for MAX_DEV_HINTS */
- Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
+ Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
return usb_register(&pwc_driver);
}
diff --git a/drivers/usb/media/pwc/pwc-ioctl.h b/drivers/media/video/pwc/pwc-ioctl.h
index 5f9cb08bc02..784bc72521f 100644
--- a/drivers/usb/media/pwc/pwc-ioctl.h
+++ b/drivers/media/video/pwc/pwc-ioctl.h
@@ -33,10 +33,10 @@
/*
Changes
2001/08/03 Alvarado Added ioctl constants to access methods for
- changing white balance and red/blue gains
+ changing white balance and red/blue gains
2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE
2003/12/13 Nemosft Unv. Some modifications to make interfacing to
- PWCX easier
+ PWCX easier
*/
/* These are private ioctl() commands, specific for the Philips webcams.
@@ -45,10 +45,10 @@
The #define names are built up like follows:
VIDIOC VIDeo IOCtl prefix
- PWC Philps WebCam
- G optional: Get
- S optional: Set
- ... the function
+ PWC Philps WebCam
+ G optional: Get
+ S optional: Set
+ ... the function
*/
@@ -94,7 +94,7 @@ struct pwc_serial
{
char serial[30]; /* String with serial number. Contains terminating 0 */
};
-
+
/* pwc_whitebalance.mode values */
#define PWC_WB_INDOOR 0
#define PWC_WB_OUTDOOR 1
@@ -102,14 +102,14 @@ struct pwc_serial
#define PWC_WB_MANUAL 3
#define PWC_WB_AUTO 4
-/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
+/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
Set mode to one of the PWC_WB_* values above.
- *red and *blue are the respective gains of these colour components inside
+ *red and *blue are the respective gains of these colour components inside
the camera; range 0..65535
- When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
+ When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
otherwise undefined.
'read_red' and 'read_blue' are read-only.
-*/
+*/
struct pwc_whitebalance
{
int mode;
@@ -117,9 +117,9 @@ struct pwc_whitebalance
int read_red, read_blue; /* R/O */
};
-/*
+/*
'control_speed' and 'control_delay' are used in automatic whitebalance mode,
- and tell the camera how fast it should react to changes in lighting, and
+ and tell the camera how fast it should react to changes in lighting, and
with how much delay. Valid values are 0..65535.
*/
struct pwc_wb_speed
@@ -148,11 +148,11 @@ struct pwc_imagesize
#define PWC_MPT_TILT 0x02
#define PWC_MPT_TIMEOUT 0x04 /* for status */
-/* Set angles; when absolute != 0, the angle is absolute and the
+/* Set angles; when absolute != 0, the angle is absolute and the
driver calculates the relative offset for you. This can only
be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
absolute angles.
- */
+ */
struct pwc_mpt_angles
{
int absolute; /* write-only */
@@ -179,14 +179,14 @@ struct pwc_mpt_status
/* This is used for out-of-kernel decompression. With it, you can get
all the necessary information to initialize and use the decompressor
routines in standalone applications.
- */
+ */
struct pwc_video_command
{
int type; /* camera type (645, 675, 730, etc.) */
int release; /* release number */
- int size; /* one of PSZ_* */
- int alternate;
+ int size; /* one of PSZ_* */
+ int alternate;
int command_len; /* length of USB video command */
unsigned char command_buf[13]; /* Actual USB video command */
int bandlength; /* >0 = compressed */
@@ -264,7 +264,7 @@ struct pwc_video_command
/* Flickerless mode; = 0 off, otherwise on */
#define VIDIOCPWCSFLICKER _IOW('v', 208, int)
-#define VIDIOCPWCGFLICKER _IOR('v', 208, int)
+#define VIDIOCPWCGFLICKER _IOR('v', 208, int)
/* Dynamic noise reduction; 0 off, 3 = high noise reduction */
#define VIDIOCPWCSDYNNOISE _IOW('v', 209, int)
@@ -273,7 +273,7 @@ struct pwc_video_command
/* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
#define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize)
- /* Motorized pan & tilt functions */
+ /* Motorized pan & tilt functions */
#define VIDIOCPWCMPTRESET _IOW('v', 211, int)
#define VIDIOCPWCMPTGRANGE _IOR('v', 211, struct pwc_mpt_range)
#define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles)
diff --git a/drivers/media/video/pwc/pwc-kiara.c b/drivers/media/video/pwc/pwc-kiara.c
new file mode 100644
index 00000000000..4c96037f7be
--- /dev/null
+++ b/drivers/media/video/pwc/pwc-kiara.c
@@ -0,0 +1,318 @@
+/* Linux driver for Philips webcam
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+/* This tables contains entries for the 730/740/750 (Kiara) camera, with
+ 4 different qualities (no compression, low, medium, high).
+ It lists the bandwidth requirements for said mode by its alternate interface
+ number. An alternate of 0 means that the mode is unavailable.
+
+ There are 6 * 4 * 4 entries:
+ 6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+ 6 framerates: 5, 10, 15, 20, 25, 30
+ 4 compression modi: none, low, medium, high
+
+ When an uncompressed mode is not available, the next available compressed mode
+ will be chosen (unless the decompressor is absent). Sometimes there are only
+ 1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+
+#include "pwc-kiara.h"
+#include "pwc-uncompress.h"
+
+const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
+{
+ /* SQCIF */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+ /* QSIF */
+ {
+ /* 5 fps */
+ {
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ },
+ /* 10 fps */
+ {
+ {2, 291, 0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
+ {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+ {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+ {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+ },
+ /* 15 fps */
+ {
+ {3, 437, 0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
+ {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+ {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+ {1, 192, 420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+ },
+ /* 20 fps */
+ {
+ {4, 589, 0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
+ {3, 448, 730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
+ {2, 292, 476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
+ {1, 192, 312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+ },
+ /* 25 fps */
+ {
+ {5, 703, 0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
+ {3, 447, 610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
+ {2, 292, 398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+ {1, 193, 262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
+ },
+ /* 30 fps */
+ {
+ {8, 874, 0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
+ {5, 704, 730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
+ {3, 448, 492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
+ {2, 292, 320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+ },
+ },
+ /* QCIF */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+ /* SIF */
+ {
+ /* 5 fps */
+ {
+ {4, 582, 0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
+ {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
+ {2, 291, 960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
+ {1, 191, 630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
+ {3, 447, 736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
+ {2, 292, 480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
+ {4, 592, 650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
+ {3, 448, 492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {9, 958, 782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
+ {5, 703, 574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
+ {3, 446, 364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {9, 958, 654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
+ {6, 776, 530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
+ {4, 592, 404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
+ {6, 775, 426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
+ {4, 590, 324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
+ },
+ },
+ /* CIF */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+ /* VGA */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
+ {4, 592, 976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
+ {3, 448, 738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {9, 956, 788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
+ {6, 776, 640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
+ {4, 592, 488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+ {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+ {8, 895, 492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+};
+
diff --git a/drivers/usb/media/pwc/pwc-kiara.h b/drivers/media/video/pwc/pwc-kiara.h
index 12929abbb1f..12929abbb1f 100644
--- a/drivers/usb/media/pwc/pwc-kiara.h
+++ b/drivers/media/video/pwc/pwc-kiara.h
diff --git a/drivers/usb/media/pwc/pwc-misc.c b/drivers/media/video/pwc/pwc-misc.c
index b7a4bd3524c..58fe7974799 100644
--- a/drivers/usb/media/pwc/pwc-misc.c
+++ b/drivers/media/video/pwc/pwc-misc.c
@@ -1,4 +1,4 @@
-/* Linux driver for Philips webcam
+/* Linux driver for Philips webcam
Various miscellaneous functions and tables.
(C) 1999-2003 Nemosoft Unv.
(C) 2004 Luc Saillard (luc@saillard.org)
@@ -44,17 +44,17 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height)
int i, find;
/* Make sure we don't go beyond our max size.
- NB: we have different limits for RAW and normal modes. In case
- you don't have the decompressor loaded or use RAW mode,
- the maximum viewable size is smaller.
- */
+ NB: we have different limits for RAW and normal modes. In case
+ you don't have the decompressor loaded or use RAW mode,
+ the maximum viewable size is smaller.
+ */
if (pdev->vpalette == VIDEO_PALETTE_RAW)
{
if (width > pdev->abs_max.x || height > pdev->abs_max.y)
{
Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
- return -1;
- }
+ return -1;
+ }
}
else
{
@@ -88,8 +88,8 @@ void pwc_construct(struct pwc_device *pdev)
pdev->view_min.y = 96;
pdev->view_max.x = 352;
pdev->view_max.y = 288;
- pdev->abs_max.x = 352;
- pdev->abs_max.y = 288;
+ pdev->abs_max.x = 352;
+ pdev->abs_max.y = 288;
pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
pdev->vcinterface = 2;
pdev->vendpoint = 4;
@@ -105,8 +105,8 @@ void pwc_construct(struct pwc_device *pdev)
pdev->view_max.x = 640;
pdev->view_max.y = 480;
pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
- pdev->abs_max.x = 640;
- pdev->abs_max.y = 480;
+ pdev->abs_max.x = 640;
+ pdev->abs_max.y = 480;
pdev->vcinterface = 3;
pdev->vendpoint = 4;
pdev->frame_header_size = 0;
@@ -121,8 +121,8 @@ void pwc_construct(struct pwc_device *pdev)
pdev->view_max.x = 640;
pdev->view_max.y = 480;
pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
- pdev->abs_max.x = 640;
- pdev->abs_max.y = 480;
+ pdev->abs_max.x = 640;
+ pdev->abs_max.y = 480;
pdev->vcinterface = 3;
pdev->vendpoint = 5;
pdev->frame_header_size = TOUCAM_HEADER_SIZE;
diff --git a/drivers/usb/media/pwc/pwc-nala.h b/drivers/media/video/pwc/pwc-nala.h
index e6c5cb69d03..168c73ef75d 100644
--- a/drivers/usb/media/pwc/pwc-nala.h
+++ b/drivers/media/video/pwc/pwc-nala.h
@@ -54,7 +54,7 @@
{0},
},
/* VGA */
- {
+ {
{0},
{0},
{0},
diff --git a/drivers/media/video/pwc/pwc-timon.c b/drivers/media/video/pwc/pwc-timon.c
new file mode 100644
index 00000000000..175250d089c
--- /dev/null
+++ b/drivers/media/video/pwc/pwc-timon.c
@@ -0,0 +1,316 @@
+/* Linux driver for Philips webcam
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+/* This tables contains entries for the 675/680/690 (Timon) camera, with
+ 4 different qualities (no compression, low, medium, high).
+ It lists the bandwidth requirements for said mode by its alternate interface
+ number. An alternate of 0 means that the mode is unavailable.
+
+ There are 6 * 4 * 4 entries:
+ 6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+ 6 framerates: 5, 10, 15, 20, 25, 30
+ 4 compression modi: none, low, medium, high
+
+ When an uncompressed mode is not available, the next available compressed mode
+ will be chosen (unless the decompressor is absent). Sometimes there are only
+ 1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+#include "pwc-timon.h"
+
+const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] =
+{
+ /* SQCIF */
+ {
+ /* 5 fps */
+ {
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ },
+ },
+ /* QSIF */
+ {
+ /* 5 fps */
+ {
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {2, 291, 0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}},
+ {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {3, 437, 0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}},
+ {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {1, 191, 420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {4, 588, 0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}},
+ {3, 447, 730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+ {1, 192, 312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {5, 703, 0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}},
+ {3, 447, 610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+ {1, 192, 262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {8, 873, 0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}},
+ {5, 704, 774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}},
+ {3, 448, 492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}},
+ {2, 291, 320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+ },
+ },
+ /* QCIF */
+ {
+ /* 5 fps */
+ {
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {3, 385, 0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}},
+ {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {1, 194, 532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {4, 577, 0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}},
+ {3, 447, 818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}},
+ {1, 195, 356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {6, 776, 0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}},
+ {4, 591, 804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}},
+ {3, 447, 608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 291, 396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {9, 928, 0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}},
+ {5, 703, 800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}},
+ {3, 447, 508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 956, 876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}},
+ {4, 592, 542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}},
+ {2, 291, 266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}},
+ },
+ },
+ /* SIF */
+ {
+ /* 5 fps */
+ {
+ {4, 582, 0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}},
+ {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}},
+ {2, 291, 960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}},
+ {1, 191, 630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}},
+ {3, 447, 736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}},
+ {2, 291, 480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}},
+ {4, 591, 650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}},
+ {3, 448, 492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {9, 958, 782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}},
+ {5, 703, 574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}},
+ {3, 446, 364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {9, 958, 654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}},
+ {6, 776, 530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}},
+ {4, 592, 404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}},
+ {6, 775, 426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}},
+ {4, 590, 324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}},
+ },
+ },
+ /* CIF */
+ {
+ /* 5 fps */
+ {
+ {6, 771, 0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}},
+ {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}},
+ {2, 291, 800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}},
+ {1, 193, 528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}},
+ {4, 591, 812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}},
+ {2, 291, 400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 956, 876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}},
+ {5, 703, 644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}},
+ {3, 448, 410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {9, 956, 650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}},
+ {6, 776, 528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}},
+ {4, 591, 402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}},
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {9, 956, 544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}},
+ {7, 840, 478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}},
+ {5, 703, 400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 956, 438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}},
+ {7, 838, 384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}},
+ {6, 773, 354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}},
+ },
+ },
+ /* VGA */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}},
+ {4, 592, 976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}},
+ {3, 448, 738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {9, 956, 788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}},
+ {6, 776, 640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}},
+ {4, 592, 488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+ {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+ {8, 895, 492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+};
+
diff --git a/drivers/usb/media/pwc/pwc-timon.h b/drivers/media/video/pwc/pwc-timon.h
index a86b3782a08..a86b3782a08 100644
--- a/drivers/usb/media/pwc/pwc-timon.h
+++ b/drivers/media/video/pwc/pwc-timon.h
diff --git a/drivers/usb/media/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c
index ef4204eab6c..b37a89a163f 100644
--- a/drivers/usb/media/pwc/pwc-uncompress.c
+++ b/drivers/media/video/pwc/pwc-uncompress.c
@@ -109,9 +109,9 @@ int pwc_decompress(struct pwc_device *pdev)
in planar format immediately.
*/
int flags;
-
- flags = PWCX_FLAG_PLANAR;
- if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot)
+
+ flags = PWCX_FLAG_PLANAR;
+ if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot)
{
printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n");
flags |= PWCX_FLAG_BAYER;
diff --git a/drivers/usb/media/pwc/pwc-uncompress.h b/drivers/media/video/pwc/pwc-uncompress.h
index d3b9250e4ed..f75e1b6cbe1 100644
--- a/drivers/usb/media/pwc/pwc-uncompress.h
+++ b/drivers/media/video/pwc/pwc-uncompress.h
@@ -24,7 +24,7 @@
/* This file is the bridge between the kernel module and the plugin; it
describes the structures and datatypes used in both modules. Any
- significant change should be reflected by increasing the
+ significant change should be reflected by increasing the
pwc_decompressor_version major number.
*/
#ifndef PWC_UNCOMPRESS_H
diff --git a/drivers/usb/media/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index 6dd76bb3dff..1b0ee0ced0e 100644
--- a/drivers/usb/media/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -123,7 +123,7 @@ struct pwc_device
#endif
/* Pointer to our usb_device */
struct usb_device *udev;
-
+
int type; /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
int release; /* release number */
int features; /* feature bits */
@@ -149,7 +149,7 @@ struct pwc_device
char vsnapshot; /* snapshot mode */
char vsync; /* used by isoc handler */
char vmirror; /* for ToUCaM series */
-
+
int cmd_len;
unsigned char cmd_buf[13];
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index a9f3cf0b1e3..531e9461cb6 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -71,7 +71,7 @@
#define NUM_BUFS 8
#define IF_NAME "SAA5249"
-static const int disp_modes[8][3] =
+static const int disp_modes[8][3] =
{
{ 0x46, 0x03, 0x03 }, /* DISPOFF */
{ 0x46, 0xcc, 0xcc }, /* DISPNORM */
@@ -150,8 +150,8 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind)
client=kmalloc(sizeof(*client), GFP_KERNEL);
if(client==NULL)
return -ENOMEM;
- client_template.adapter = adap;
- client_template.addr = addr;
+ client_template.adapter = adap;
+ client_template.addr = addr;
memcpy(client, &client_template, sizeof(*client));
t = kzalloc(sizeof(*t), GFP_KERNEL);
if(t==NULL)
@@ -161,11 +161,11 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind)
}
strlcpy(client->name, IF_NAME, I2C_NAME_SIZE);
mutex_init(&t->lock);
-
+
/*
* Now create a video4linux device
*/
-
+
vd = kmalloc(sizeof(struct video_device), GFP_KERNEL);
if(vd==NULL)
{
@@ -175,8 +175,8 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind)
}
i2c_set_clientdata(client, vd);
memcpy(vd, &saa_template, sizeof(*vd));
-
- for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++)
+
+ for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++)
{
memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
@@ -186,9 +186,9 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind)
t->vdau[pgbuf].stopped = TRUE;
t->is_searching[pgbuf] = FALSE;
}
- vd->priv=t;
-
-
+ vd->priv=t;
+
+
/*
* Register it
*/
@@ -208,7 +208,7 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind)
/*
* We do most of the hard work when we become a device on the i2c.
*/
-
+
static int saa5249_probe(struct i2c_adapter *adap)
{
if (adap->class & I2C_CLASS_TV_ANALOG)
@@ -229,7 +229,7 @@ static int saa5249_detach(struct i2c_client *client)
/* new I2C driver support */
-static struct i2c_driver i2c_driver_videotext =
+static struct i2c_driver i2c_driver_videotext =
{
.driver = {
.name = IF_NAME, /* name */
@@ -249,7 +249,7 @@ static struct i2c_client client_template = {
* delay may be longer.
*/
-static void jdelay(unsigned long delay)
+static void jdelay(unsigned long delay)
{
sigset_t oldblocked = current->blocked;
@@ -269,14 +269,14 @@ static void jdelay(unsigned long delay)
/*
* I2C interfaces
*/
-
-static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data)
+
+static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data)
{
char buf[64];
-
+
buf[0] = reg;
memcpy(buf+1, data, count);
-
+
if(i2c_master_send(t->client, buf, count+1)==count+1)
return 0;
return -1;
@@ -289,7 +289,7 @@ static int i2c_senddata(struct saa5249_device *t, ...)
int ct=0;
va_list argp;
va_start(argp,t);
-
+
while((v=va_arg(argp,int))!=-1)
buf[ct++]=v;
return i2c_sendbuf(t, buf[0], ct-1, buf+1);
@@ -301,7 +301,7 @@ static int i2c_senddata(struct saa5249_device *t, ...)
* Returns -1 if I²C-device didn't send acknowledge, 0 otherwise
*/
-static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf)
+static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf)
{
if(i2c_master_recv(t->client, buf, count)!=count)
return -1;
@@ -320,9 +320,9 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
struct video_device *vd = video_devdata(file);
struct saa5249_device *t=vd->priv;
- switch(cmd)
+ switch(cmd)
{
- case VTXIOCGETINFO:
+ case VTXIOCGETINFO:
{
vtx_info_t *info = arg;
info->version_major = VTX_VER_MAJ;
@@ -332,10 +332,10 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
return 0;
}
- case VTXIOCCLRPAGE:
+ case VTXIOCCLRPAGE:
{
vtx_pagereq_t *req = arg;
-
+
if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
return -EINVAL;
memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
@@ -343,17 +343,17 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
return 0;
}
- case VTXIOCCLRFOUND:
+ case VTXIOCCLRFOUND:
{
vtx_pagereq_t *req = arg;
-
+
if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
return -EINVAL;
t->vdau[req->pgbuf].clrfound = TRUE;
return 0;
}
- case VTXIOCPAGEREQ:
+ case VTXIOCPAGEREQ:
{
vtx_pagereq_t *req = arg;
if (!(req->pagemask & PGMASK_PAGE))
@@ -381,7 +381,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
return 0;
}
- case VTXIOCGETSTAT:
+ case VTXIOCGETSTAT:
{
vtx_pagereq_t *req = arg;
u8 infobits[10];
@@ -390,7 +390,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
return -EINVAL;
- if (!t->vdau[req->pgbuf].stopped)
+ if (!t->vdau[req->pgbuf].stopped)
{
if (i2c_senddata(t, 2, 0, -1) ||
i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req->pgbuf].sregs) ||
@@ -403,7 +403,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
return -EIO;
if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */
- (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) ||
+ (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) ||
time_after_eq(jiffies, t->vdau[req->pgbuf].expire)))
{ /* check if new page arrived */
if (i2c_senddata(t, 8, 0, 0, 0, -1) ||
@@ -411,7 +411,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
return -EIO;
t->vdau[req->pgbuf].expire = jiffies + PGBUF_EXPIRE;
memset(t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE);
- if (t->virtual_mode)
+ if (t->virtual_mode)
{
/* Packet X/24 */
if (i2c_senddata(t, 8, 0, 0x20, 0, -1) ||
@@ -459,9 +459,9 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
info.notfound = !!(infobits[8] & 0x10);
info.pblf = !!(infobits[9] & 0x20);
info.hamming = 0;
- for (a = 0; a <= 7; a++)
+ for (a = 0; a <= 7; a++)
{
- if (infobits[a] & 0xf0)
+ if (infobits[a] & 0xf0)
{
info.hamming = 1;
break;
@@ -471,14 +471,14 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
info.notfound = 1;
if(copy_to_user(req->buffer, &info, sizeof(vtx_pageinfo_t)))
return -EFAULT;
- if (!info.hamming && !info.notfound)
+ if (!info.hamming && !info.notfound)
{
t->is_searching[req->pgbuf] = FALSE;
}
return 0;
}
- case VTXIOCGETPAGE:
+ case VTXIOCGETPAGE:
{
vtx_pagereq_t *req = arg;
int start, end;
@@ -488,15 +488,15 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
if(copy_to_user(req->buffer, &t->vdau[req->pgbuf].pgbuf[req->start], req->end - req->start + 1))
return -EFAULT;
-
- /*
+
+ /*
* Always read the time directly from SAA5249
*/
-
- if (req->start <= 39 && req->end >= 32)
+
+ if (req->start <= 39 && req->end >= 32)
{
int len;
- char buf[16];
+ char buf[16];
start = max(req->start, 32);
end = min(req->end, 39);
len=end-start+1;
@@ -507,7 +507,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
}
/* Insert the current header if DAU is still searching for a page */
- if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf])
+ if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf])
{
char buf[32];
int len;
@@ -523,7 +523,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
return 0;
}
- case VTXIOCSTOPDAU:
+ case VTXIOCSTOPDAU:
{
vtx_pagereq_t *req = arg;
@@ -534,12 +534,12 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
return 0;
}
- case VTXIOCPUTPAGE:
- case VTXIOCSETDISP:
- case VTXIOCPUTSTAT:
+ case VTXIOCPUTPAGE:
+ case VTXIOCSETDISP:
+ case VTXIOCPUTSTAT:
return 0;
-
- case VTXIOCCLRCACHE:
+
+ case VTXIOCCLRCACHE:
{
if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11,
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
@@ -551,7 +551,7 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
return 0;
}
- case VTXIOCSETVIRT:
+ case VTXIOCSETVIRT:
{
/* The SAA5249 has virtual-row reception turned on always */
t->virtual_mode = (int)(long)arg;
@@ -612,14 +612,14 @@ static inline unsigned int vtx_fix_command(unsigned int cmd)
/*
* Handle the locking
*/
-
+
static int saa5249_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct video_device *vd = video_devdata(file);
struct saa5249_device *t=vd->priv;
int err;
-
+
cmd = vtx_fix_command(cmd);
mutex_lock(&t->lock);
err = video_usercopy(inode,file,cmd,arg,do_saa5249_ioctl);
@@ -627,7 +627,7 @@ static int saa5249_ioctl(struct inode *inode, struct file *file,
return err;
}
-static int saa5249_open(struct inode *inode, struct file *file)
+static int saa5249_open(struct inode *inode, struct file *file)
{
struct video_device *vd = video_devdata(file);
struct saa5249_device *t=vd->priv;
@@ -636,7 +636,7 @@ static int saa5249_open(struct inode *inode, struct file *file)
err = video_exclusive_open(inode,file);
if (err < 0)
return err;
-
+
if (t->client==NULL) {
err = -ENODEV;
goto fail;
@@ -647,13 +647,13 @@ static int saa5249_open(struct inode *inode, struct file *file)
i2c_senddata(t, 1, disp_modes[t->disp_mode][0], 0, -1) ||
/* Display TV-picture, no virtual rows */
i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1)) /* Set display to page 4 */
-
+
{
err = -EIO;
goto fail;
}
- for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++)
+ for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++)
{
memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
@@ -673,7 +673,7 @@ static int saa5249_open(struct inode *inode, struct file *file)
-static int saa5249_release(struct inode *inode, struct file *file)
+static int saa5249_release(struct inode *inode, struct file *file)
{
struct video_device *vd = video_devdata(file);
struct saa5249_device *t=vd->priv;
@@ -690,7 +690,7 @@ static int __init init_saa_5249 (void)
return i2c_add_driver(&i2c_driver_videotext);
}
-static void __exit cleanup_saa_5249 (void)
+static void __exit cleanup_saa_5249 (void)
{
i2c_del_driver(&i2c_driver_videotext);
}
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
index d17395c4f55..a81285ca7d5 100644
--- a/drivers/media/video/saa6588.c
+++ b/drivers/media/video/saa6588.c
@@ -32,7 +32,7 @@
#include <asm/uaccess.h>
-#include "rds.h"
+#include <media/rds.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = {
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index e18ea268384..41d951db6ec 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -139,7 +139,7 @@ saa7110_read (struct i2c_client *client)
static int
saa7110_selmux (struct i2c_client *client,
- int chan)
+ int chan)
{
static const unsigned char modes[9][8] = {
/* mode 0 */
@@ -457,7 +457,7 @@ static unsigned short normal_i2c[] = {
};
static unsigned short ignore = I2C_CLIENT_END;
-
+
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index f9ba0c943ad..686fd474620 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -1,4 +1,4 @@
-/*
+/*
* saa7111 - Philips SAA7111A video decoder driver version 0.0.3
*
* Copyright (C) 1998 Dave Perks <dperks@ibm.net>
@@ -482,7 +482,7 @@ saa7111_command (struct i2c_client *client,
static unsigned short normal_i2c[] = { I2C_SAA7111 >> 1, I2C_CLIENT_END };
static unsigned short ignore = I2C_CLIENT_END;
-
+
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index 4a1f841d0c7..90398ab8252 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -1,4 +1,4 @@
-/*
+/*
* saa7114 - Philips SAA7114H video decoder driver version 0.0.1
*
* Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
@@ -300,7 +300,7 @@ static const unsigned char init[] = {
0x55, 0xff,
0x56, 0xff,
0x57, 0xff,
- 0x58, 0x40, // framing code
+ 0x58, 0x40, // framing code
0x59, 0x47, // horizontal offset
0x5a, 0x06, // vertical offset
0x5b, 0x83, // field offset
@@ -345,7 +345,7 @@ static const unsigned char init[] = {
0x82, 0x00,
0x83, 0x00,
0x84, 0xc5,
- 0x85, 0x0d, // hsync and vsync ?
+ 0x85, 0x0d, // hsync and vsync ?
0x86, 0x40,
0x87, 0x01,
0x88, 0x00,
@@ -434,7 +434,7 @@ static const unsigned char init[] = {
0xd9, 0x04,
0xda, 0x00, // horizontal luminance phase offset
0xdb, 0x00,
- 0xdc, 0x00, // horizontal chrominance scaling increment
+ 0xdc, 0x00, // horizontal chrominance scaling increment
0xdd, 0x02,
0xde, 0x00, // horizontal chrominance phase offset
0xdf, 0x00,
@@ -754,7 +754,7 @@ saa7114_command (struct i2c_client *client,
saa7114_write(client, 0x87,
decoder->reg[REG_ADDR(0x87)]);
saa7114_write(client, 0x88, 0xd8); // sw reset scaler
- saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
+ saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
saa7114_write(client, 0x80, 0x36);
}
@@ -813,7 +813,7 @@ static unsigned short normal_i2c[] =
{ I2C_SAA7114 >> 1, I2C_SAA7114A >> 1, I2C_CLIENT_END };
static unsigned short ignore = I2C_CLIENT_END;
-
+
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index b184fd00b4e..b0501528260 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -40,7 +40,6 @@
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
-#include <media/audiochip.h>
#include <asm/div64.h>
MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver");
diff --git a/drivers/media/video/saa7121.h b/drivers/media/video/saa7121.h
index 74e37d40520..66967ae3749 100644
--- a/drivers/media/video/saa7121.h
+++ b/drivers/media/video/saa7121.h
@@ -64,7 +64,7 @@
#define PAL_MSB_VERTICAL 0x40 /* 7c */
/* Initialization Sequence */
-
+
static __u8 init7121ntsc[] = {
0x26, 0x0, 0x27, 0x0,
0x28, NTSC_BURST_START, 0x29, NTSC_BURST_END,
@@ -95,7 +95,7 @@ static __u8 init7121ntsc[] = {
0x78, 0x0, 0x79, 0x0, 0x7a, NTSC_FIRST_ACTIVE,
0x7b, NTSC_LAST_ACTIVE, 0x7c, NTSC_MSB_VERTICAL,
0x7d, 0x0, 0x7e, 0x0, 0x7f, 0x0
-};
+};
#define INIT7121LEN (sizeof(init7121ntsc)/2)
static __u8 init7121pal[] = {
@@ -128,5 +128,5 @@ static __u8 init7121pal[] = {
0x78, 0x0, 0x79, 0x0, 0x7a, PAL_FIRST_ACTIVE,
0x7b, PAL_LAST_ACTIVE, 0x7c, PAL_MSB_VERTICAL,
0x7d, 0x0, 0x7e, 0x0, 0x7f, 0x0
-};
+};
#endif
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index aca84d2f982..bb3e0ba946d 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -507,7 +507,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
/* release the old buffer */
if (substream->runtime->dma_area) {
saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
- videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
+ videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
dsp_buffer_free(dev);
substream->runtime->dma_area = NULL;
}
@@ -523,12 +523,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
return err;
}
- if (0 != (err = videobuf_dma_pci_map(dev->pci, &dev->dmasound.dma))) {
+ if (0 != (err = videobuf_pci_dma_map(dev->pci, &dev->dmasound.dma))) {
dsp_buffer_free(dev);
return err;
}
if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) {
- videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
+ videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
dsp_buffer_free(dev);
return err;
}
@@ -537,7 +537,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
dev->dmasound.dma.sglen,
0))) {
saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
- videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
+ videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
dsp_buffer_free(dev);
return err;
}
@@ -571,7 +571,7 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream)
if (substream->runtime->dma_area) {
saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
- videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
+ videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
dsp_buffer_free(dev);
substream->runtime->dma_area = NULL;
}
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 58e568d7d2e..c98571c9d5a 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -254,12 +254,12 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt)
/* ------------------------------------------------------------------ */
-void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf)
+void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf)
{
BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb,0,0);
- videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma);
+ videobuf_dma_unmap(q, &buf->vb.dma);
videobuf_dma_free(&buf->vb.dma);
buf->vb.state = STATE_NEEDS_INIT;
}
@@ -960,7 +960,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
if (saa7134_no_overlay <= 0) {
saa7134_video_template.type |= VID_TYPE_OVERLAY;
} else {
- printk("bttv: Overlay support disabled.\n");
+ printk("%s: Overlay support disabled.\n",dev->name);
}
dev->video_dev = vdev_init(dev,&saa7134_video_template,"video");
err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index d79d05f8870..7aa02b34e01 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -124,7 +124,7 @@ static int dsp_rec_start(struct saa7134_dev *dev)
unsigned long flags;
/* prepare buffer */
- if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->dmasound.dma)))
+ if (0 != (err = videobuf_pci_dma_map(dev->pci,&dev->dmasound.dma)))
return err;
if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt)))
goto fail1;
@@ -213,7 +213,7 @@ static int dsp_rec_start(struct saa7134_dev *dev)
fail2:
saa7134_pgtable_free(dev->pci,&dev->dmasound.pt);
fail1:
- videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma);
+ videobuf_pci_dma_unmap(dev->pci,&dev->dmasound.dma);
return err;
}
@@ -231,7 +231,7 @@ static int dsp_rec_stop(struct saa7134_dev *dev)
/* unlock buffer */
saa7134_pgtable_free(dev->pci,&dev->dmasound.pt);
- videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma);
+ videobuf_pci_dma_unmap(dev->pci,&dev->dmasound.dma);
return 0;
}
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
index 470903e2f5e..60a90a2617a 100644
--- a/drivers/media/video/saa7134/saa7134-ts.c
+++ b/drivers/media/video/saa7134/saa7134-ts.c
@@ -89,7 +89,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
return -EINVAL;
if (buf->vb.size != size) {
- saa7134_dma_free(dev,buf);
+ saa7134_dma_free(q,buf);
}
if (STATE_NEEDS_INIT == buf->vb.state) {
@@ -98,7 +98,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
buf->vb.size = size;
buf->pt = &dev->ts.pt_ts;
- err = videobuf_iolock(dev->pci,&buf->vb,NULL);
+ err = videobuf_iolock(q,&buf->vb,NULL);
if (err)
goto oops;
err = saa7134_pgtable_build(dev->pci,buf->pt,
@@ -126,7 +126,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
return 0;
oops:
- saa7134_dma_free(dev,buf);
+ saa7134_dma_free(q,buf);
return err;
}
@@ -152,10 +152,9 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct saa7134_dev *dev = q->priv_data;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
- saa7134_dma_free(dev,buf);
+ saa7134_dma_free(q,buf);
}
struct videobuf_queue_ops saa7134_ts_qops = {
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 3043233a8b6..0db53d192b2 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -482,12 +482,14 @@ static int tvaudio_setstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au
[ V4L2_TUNER_MODE_STEREO ] = "stereo",
[ V4L2_TUNER_MODE_LANG1 ] = "lang1",
[ V4L2_TUNER_MODE_LANG2 ] = "lang2",
+ [ V4L2_TUNER_MODE_LANG1_LANG2 ] = "lang1+lang2",
};
static u32 fm[] = {
[ V4L2_TUNER_MODE_MONO ] = 0x00, /* ch1 */
[ V4L2_TUNER_MODE_STEREO ] = 0x80, /* auto */
[ V4L2_TUNER_MODE_LANG1 ] = 0x00, /* ch1 */
[ V4L2_TUNER_MODE_LANG2 ] = 0x01, /* ch2 */
+ [ V4L2_TUNER_MODE_LANG1_LANG2 ] = 0x80, /* auto */
};
u32 reg;
diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c
index f4aee0af80e..f38366a470f 100644
--- a/drivers/media/video/saa7134/saa7134-vbi.c
+++ b/drivers/media/video/saa7134/saa7134-vbi.c
@@ -135,7 +135,7 @@ static int buffer_prepare(struct videobuf_queue *q,
return -EINVAL;
if (buf->vb.size != size)
- saa7134_dma_free(dev,buf);
+ saa7134_dma_free(q,buf);
if (STATE_NEEDS_INIT == buf->vb.state) {
buf->vb.width = llength;
@@ -143,7 +143,7 @@ static int buffer_prepare(struct videobuf_queue *q,
buf->vb.size = size;
buf->pt = &fh->pt_vbi;
- err = videobuf_iolock(dev->pci,&buf->vb,NULL);
+ err = videobuf_iolock(q,&buf->vb,NULL);
if (err)
goto oops;
err = saa7134_pgtable_build(dev->pci,buf->pt,
@@ -159,7 +159,7 @@ static int buffer_prepare(struct videobuf_queue *q,
return 0;
oops:
- saa7134_dma_free(dev,buf);
+ saa7134_dma_free(q,buf);
return err;
}
@@ -190,11 +190,9 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct saa7134_fh *fh = q->priv_data;
- struct saa7134_dev *dev = fh->dev;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
- saa7134_dma_free(dev,buf);
+ saa7134_dma_free(q,buf);
}
struct videobuf_queue_ops saa7134_vbi_qops = {
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 57a11e71d99..aeef80f88a6 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -993,7 +993,7 @@ static int buffer_prepare(struct videobuf_queue *q,
buf->vb.size != size ||
buf->vb.field != field ||
buf->fmt != fh->fmt) {
- saa7134_dma_free(dev,buf);
+ saa7134_dma_free(q,buf);
}
if (STATE_NEEDS_INIT == buf->vb.state) {
@@ -1004,7 +1004,7 @@ static int buffer_prepare(struct videobuf_queue *q,
buf->fmt = fh->fmt;
buf->pt = &fh->pt_cap;
- err = videobuf_iolock(dev->pci,&buf->vb,&dev->ovbuf);
+ err = videobuf_iolock(q,&buf->vb,&dev->ovbuf);
if (err)
goto oops;
err = saa7134_pgtable_build(dev->pci,buf->pt,
@@ -1019,7 +1019,7 @@ static int buffer_prepare(struct videobuf_queue *q,
return 0;
oops:
- saa7134_dma_free(dev,buf);
+ saa7134_dma_free(q,buf);
return err;
}
@@ -1045,10 +1045,9 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct saa7134_fh *fh = q->priv_data;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
- saa7134_dma_free(fh->dev,buf);
+ saa7134_dma_free(q,buf);
}
static struct videobuf_queue_ops video_qops = {
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index ce1c2e0b065..31ba293854c 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -34,7 +34,6 @@
#include <asm/io.h>
#include <media/tuner.h>
-#include <media/audiochip.h>
#include <media/ir-common.h>
#include <media/ir-kbd-i2c.h>
#include <media/video-buf.h>
@@ -579,7 +578,7 @@ void saa7134_buffer_finish(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
unsigned int state);
void saa7134_buffer_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q);
void saa7134_buffer_timeout(unsigned long data);
-void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf);
+void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf);
int saa7134_set_dmabits(struct saa7134_dev *dev);
diff --git a/drivers/media/video/saa7146.h b/drivers/media/video/saa7146.h
index 756963f01bb..2830b5e33ae 100644
--- a/drivers/media/video/saa7146.h
+++ b/drivers/media/video/saa7146.h
@@ -1,7 +1,7 @@
-/*
+/*
saa7146.h - definitions philips saa7146 based cards
Copyright (C) 1999 Nathan Laredo (laredo@gnu.org)
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -27,7 +27,7 @@
#include <linux/videodev.h>
-#ifndef O_NONCAP
+#ifndef O_NONCAP
#define O_NONCAP O_TRUNC
#endif
@@ -36,7 +36,7 @@
#ifdef __KERNEL__
-struct saa7146_window
+struct saa7146_window
{
int x, y;
ushort width, height;
@@ -70,7 +70,7 @@ struct saa7146
int irqstate; /* irq routine is state driven */
int writemode;
int playmode;
- unsigned int nr;
+ unsigned int nr;
unsigned long irq; /* IRQ used by SAA7146 card */
unsigned short id;
unsigned char revision;
diff --git a/drivers/media/video/saa7146reg.h b/drivers/media/video/saa7146reg.h
index 6cc910f50a4..80ec2c146b4 100644
--- a/drivers/media/video/saa7146reg.h
+++ b/drivers/media/video/saa7146reg.h
@@ -1,7 +1,7 @@
-/*
+/*
saa7146.h - definitions philips saa7146 based cards
Copyright (C) 1999 Nathan Laredo (laredo@gnu.org)
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 9f99ee1303e..9c308410856 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -1,4 +1,4 @@
-/*
+/*
* saa7185 - Philips SAA7185B video encoder driver version 0.0.3
*
* Copyright (C) 1998 Dave Perks <dperks@ibm.net>
@@ -377,7 +377,7 @@ saa7185_command (struct i2c_client *client,
static unsigned short normal_i2c[] = { I2C_SAA7185 >> 1, I2C_CLIENT_END };
static unsigned short ignore = I2C_CLIENT_END;
-
+
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
diff --git a/drivers/media/video/saa7196.h b/drivers/media/video/saa7196.h
index f92f21cfbca..cd4b6354a7b 100644
--- a/drivers/media/video/saa7196.h
+++ b/drivers/media/video/saa7196.h
@@ -2,14 +2,14 @@
Definitions for the Philips SAA7196 digital video decoder,
scaler, and clock generator circuit (DESCpro), as used in
the PlanB video input of the Powermac 7x00/8x00 series.
-
+
Copyright (C) 1998 Michel Lanners (mlan@cpu.lu)
The register defines are shamelessly copied from the meteor
driver out of NetBSD (with permission),
and are copyrighted (c) 1995 Mark Tinguely and Jim Lowe
(Thanks !)
-
+
Additional debugging and coding by Takashi Oe (toe@unlinfo.unl.edu)
The default values used for PlanB are my mistakes.
diff --git a/drivers/usb/media/se401.c b/drivers/media/video/se401.c
index f03ea7f8959..a846ebc78cd 100644
--- a/drivers/usb/media/se401.c
+++ b/drivers/media/video/se401.c
@@ -4,7 +4,7 @@
* Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
*
* Still somewhat based on the Linux ov511 driver.
- *
+ *
* 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
@@ -114,16 +114,16 @@ static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req,
unsigned short value, unsigned char *cp, int size)
{
return usb_control_msg (
- se401->dev,
- set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0),
- req,
- (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value,
- 0,
- cp,
- size,
- 1000
- );
+ se401->dev,
+ set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0),
+ req,
+ (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value,
+ 0,
+ cp,
+ size,
+ 1000
+ );
}
static int se401_set_feature(struct usb_se401 *se401, unsigned short selector,
@@ -140,30 +140,30 @@ static int se401_set_feature(struct usb_se401 *se401, unsigned short selector,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
param,
selector,
- NULL,
- 0,
- 1000
- );
+ NULL,
+ 0,
+ 1000
+ );
}
-static unsigned short se401_get_feature(struct usb_se401 *se401,
- unsigned short selector)
+static unsigned short se401_get_feature(struct usb_se401 *se401,
+ unsigned short selector)
{
/* For 'set' the selecetor should be in index, not sure if the spec is
wrong here to....
*/
unsigned char cp[2];
- usb_control_msg (
- se401->dev,
- usb_rcvctrlpipe(se401->dev, 0),
- SE401_REQ_GET_EXT_FEATURE,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0,
- selector,
- cp,
- 2,
- 1000
- );
+ usb_control_msg (
+ se401->dev,
+ usb_rcvctrlpipe(se401->dev, 0),
+ SE401_REQ_GET_EXT_FEATURE,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0,
+ selector,
+ cp,
+ 2,
+ 1000
+ );
return cp[0]+cp[1]*256;
}
@@ -183,14 +183,14 @@ static int se401_send_pict(struct usb_se401 *se401)
se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */
se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */
se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */
-
+
return 0;
}
static void se401_set_exposure(struct usb_se401 *se401, int brightness)
{
int integration=brightness<<5;
-
+
if (flickerless==50) {
integration=integration-integration%106667;
}
@@ -255,11 +255,11 @@ static void se401_auto_resetlevel(struct usb_se401 *se401)
/* For some reason this normally read-only register doesn't get reset
to zero after reading them just once...
*/
- se401_get_feature(se401, HV7131_REG_HIREFNOH);
+ se401_get_feature(se401, HV7131_REG_HIREFNOH);
se401_get_feature(se401, HV7131_REG_HIREFNOL);
se401_get_feature(se401, HV7131_REG_LOREFNOH);
se401_get_feature(se401, HV7131_REG_LOREFNOL);
- ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) +
+ ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) +
se401_get_feature(se401, HV7131_REG_HIREFNOL);
alrc=256*se401_get_feature(se401, HV7131_REG_LOREFNOH) +
se401_get_feature(se401, HV7131_REG_LOREFNOL);
@@ -287,12 +287,12 @@ static void se401_button_irq(struct urb *urb, struct pt_regs *regs)
{
struct usb_se401 *se401 = urb->context;
int status;
-
+
if (!se401->dev) {
info("ohoh: device vapourished");
return;
}
-
+
switch (urb->status) {
case 0:
/* success */
@@ -368,7 +368,7 @@ static void se401_video_irq(struct urb *urb, struct pt_regs *regs)
if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
if (waitqueue_active(&se401->wq)) {
wake_up_interruptible(&se401->wq);
- }
+ }
}
}
@@ -433,8 +433,8 @@ static int se401_start_stream(struct usb_se401 *se401)
int err=0, i;
se401->streaming=1;
- se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
- se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
+ se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
+ se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
/* Set picture settings */
se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */
@@ -571,7 +571,7 @@ static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data)
}
/* First three are absolute, all others relative.
- * Format is rgb from right to left (mirrorred image),
+ * Format is rgb from right to left (mirrorred image),
* we flip it to get bgr from left to right. */
if (frame->curlinepix < 3) {
*(frame->curline-frame->curlinepix)=1+data*4;
@@ -703,7 +703,7 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *
int width=se401->cwidth;
int blineoffset=0, bline;
int linelength=width*3, i;
-
+
if (frame->curpix==0) {
if (frame->grabstate==FRAME_READY) {
@@ -831,7 +831,7 @@ static int se401_newframe(struct usb_se401 *se401, int framenr)
se401->nullpackets=0;
info("to many null length packets, restarting capture");
se401_stop_stream(se401);
- se401_start_stream(se401);
+ se401_start_stream(se401);
} else {
if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) {
se401->frame[framenr].grabstate=FRAME_ERROR;
@@ -866,7 +866,7 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401)
{
int i;
- se401->dev = NULL;
+ se401->dev = NULL;
for (i=0; i<SE401_NUMSBUF; i++)
if (se401->urb[i]) {
@@ -882,9 +882,9 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401)
usb_kill_urb(se401->inturb);
usb_free_urb(se401->inturb);
}
- info("%s disconnected", se401->camera_name);
+ info("%s disconnected", se401->camera_name);
- /* Free the memory */
+ /* Free the memory */
kfree(se401->width);
kfree(se401->height);
kfree(se401);
@@ -910,7 +910,7 @@ static int se401_open(struct inode *inode, struct file *file)
se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
if (se401->fbuf)
file->private_data = dev;
- else
+ else
err = -ENOMEM;
se401->user = !err;
@@ -920,11 +920,11 @@ static int se401_open(struct inode *inode, struct file *file)
static int se401_close(struct inode *inode, struct file *file)
{
struct video_device *dev = file->private_data;
- struct usb_se401 *se401 = (struct usb_se401 *)dev;
+ struct usb_se401 *se401 = (struct usb_se401 *)dev;
int i;
rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
- if (se401->removed) {
+ if (se401->removed) {
usb_se401_remove_disconnected(se401);
info("device unregistered");
} else {
@@ -942,12 +942,12 @@ static int se401_do_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *arg)
{
struct video_device *vdev = file->private_data;
- struct usb_se401 *se401 = (struct usb_se401 *)vdev;
+ struct usb_se401 *se401 = (struct usb_se401 *)vdev;
- if (!se401->dev)
- return -EIO;
+ if (!se401->dev)
+ return -EIO;
- switch (cmd) {
+ switch (cmd) {
case VIDIOCGCAP:
{
struct video_capability *b = arg;
@@ -981,8 +981,8 @@ static int se401_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
return 0;
}
- case VIDIOCGPICT:
- {
+ case VIDIOCGPICT:
+ {
struct video_picture *p = arg;
se401_get_pict(se401, p);
@@ -1007,7 +1007,7 @@ static int se401_do_ioctl(struct inode *inode, struct file *file,
if (se401_set_size(se401, vw->width, vw->height))
return -EINVAL;
return 0;
- }
+ }
case VIDIOCGWIN:
{
struct video_window *vw = arg;
@@ -1095,11 +1095,11 @@ static int se401_do_ioctl(struct inode *inode, struct file *file,
case VIDIOCGAUDIO:
case VIDIOCSAUDIO:
return -EINVAL;
- default:
- return -ENOIOCTLCMD;
- } /* end switch */
+ default:
+ return -ENOIOCTLCMD;
+ } /* end switch */
- return 0;
+ return 0;
}
static int se401_ioctl(struct inode *inode, struct file *file,
@@ -1142,7 +1142,7 @@ static ssize_t se401_read(struct file *file, char __user *buf,
se401->frame[0].grabstate=FRAME_UNUSED;
if (ret)
- return ret;
+ return ret;
if (copy_to_user(buf, se401->frame[0].data, realcount))
return -EFAULT;
@@ -1183,24 +1183,24 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma)
}
mutex_unlock(&se401->lock);
- return 0;
+ return 0;
}
static struct file_operations se401_fops = {
.owner = THIS_MODULE,
- .open = se401_open,
- .release = se401_close,
- .read = se401_read,
- .mmap = se401_mmap,
+ .open = se401_open,
+ .release = se401_close,
+ .read = se401_read,
+ .mmap = se401_mmap,
.ioctl = se401_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
static struct video_device se401_template = {
.owner = THIS_MODULE,
- .name = "se401 USB camera",
- .type = VID_TYPE_CAPTURE,
- .hardware = VID_HARDWARE_SE401,
+ .name = "se401 USB camera",
+ .type = VID_TYPE_CAPTURE,
+ .hardware = VID_HARDWARE_SE401,
.fops = &se401_fops,
};
@@ -1209,12 +1209,12 @@ static struct video_device se401_template = {
/***************************/
static int se401_init(struct usb_se401 *se401, int button)
{
- int i=0, rc;
- unsigned char cp[0x40];
+ int i=0, rc;
+ unsigned char cp[0x40];
char temp[200];
/* led on */
- se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
+ se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
/* get camera descriptor */
rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp));
@@ -1254,7 +1254,7 @@ static int se401_init(struct usb_se401 *se401, int button)
return 1;
}
/* set output mode (BAYER) */
- se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0);
+ se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0);
rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
se401->brightness=cp[0]+cp[1]*256;
@@ -1292,71 +1292,71 @@ static int se401_init(struct usb_se401 *se401, int button)
} else
se401->inturb=NULL;
- /* Flash the led */
- se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
- se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
- se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
+ /* Flash the led */
+ se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
+ se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
+ se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
- return 0;
+ return 0;
}
static int se401_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
- struct usb_interface_descriptor *interface;
- struct usb_se401 *se401;
- char *camera_name=NULL;
+ struct usb_interface_descriptor *interface;
+ struct usb_se401 *se401;
+ char *camera_name=NULL;
int button=1;
- /* We don't handle multi-config cameras */
- if (dev->descriptor.bNumConfigurations != 1)
- return -ENODEV;
+ /* We don't handle multi-config cameras */
+ if (dev->descriptor.bNumConfigurations != 1)
+ return -ENODEV;
- interface = &intf->cur_altsetting->desc;
+ interface = &intf->cur_altsetting->desc;
- /* Is it an se401? */
- if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x0004) {
- camera_name="Endpoints/Aox SE401";
- } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x030b) {
- camera_name="Philips PCVC665K";
- } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
+ /* Is it an se401? */
+ if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x0004) {
+ camera_name="Endpoints/Aox SE401";
+ } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x030b) {
+ camera_name="Philips PCVC665K";
+ } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
le16_to_cpu(dev->descriptor.idProduct) == 0x5001) {
camera_name="Kensington VideoCAM 67014";
- } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
+ } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
le16_to_cpu(dev->descriptor.idProduct) == 0x5002) {
camera_name="Kensington VideoCAM 6701(5/7)";
- } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
+ } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
le16_to_cpu(dev->descriptor.idProduct) == 0x5003) {
camera_name="Kensington VideoCAM 67016";
button=0;
} else
return -ENODEV;
- /* Checking vendor/product should be enough, but what the hell */
- if (interface->bInterfaceClass != 0x00)
+ /* Checking vendor/product should be enough, but what the hell */
+ if (interface->bInterfaceClass != 0x00)
return -ENODEV;
- if (interface->bInterfaceSubClass != 0x00)
+ if (interface->bInterfaceSubClass != 0x00)
return -ENODEV;
- /* We found one */
- info("SE401 camera found: %s", camera_name);
+ /* We found one */
+ info("SE401 camera found: %s", camera_name);
- if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
- err("couldn't kmalloc se401 struct");
+ if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
+ err("couldn't kmalloc se401 struct");
return -ENOMEM;
- }
+ }
- se401->dev = dev;
- se401->iface = interface->bInterfaceNumber;
- se401->camera_name = camera_name;
+ se401->dev = dev;
+ se401->iface = interface->bInterfaceNumber;
+ se401->camera_name = camera_name;
info("firmware version: %02x", le16_to_cpu(dev->descriptor.bcdDevice) & 255);
- if (se401_init(se401, button)) {
+ if (se401_init(se401, button)) {
kfree(se401);
return -EIO;
}
@@ -1375,7 +1375,7 @@ static int se401_probe(struct usb_interface *intf,
info("registered new video device: video%d", se401->vdev.minor);
usb_set_intfdata (intf, se401);
- return 0;
+ return 0;
}
static void se401_disconnect(struct usb_interface *intf)
@@ -1400,10 +1400,10 @@ static void se401_disconnect(struct usb_interface *intf)
}
static struct usb_driver se401_driver = {
- .name = "se401",
- .id_table = device_table,
+ .name = "se401",
+ .id_table = device_table,
.probe = se401_probe,
- .disconnect = se401_disconnect,
+ .disconnect = se401_disconnect,
};
diff --git a/drivers/usb/media/se401.h b/drivers/media/video/se401.h
index e88a40d4c86..a7a216bd441 100644
--- a/drivers/usb/media/se401.h
+++ b/drivers/media/video/se401.h
@@ -177,7 +177,7 @@ struct usb_se401 {
int expose_m;
int expose_l;
int resetlevel;
-
+
int enhance;
int format;
@@ -200,12 +200,12 @@ struct usb_se401 {
struct urb *urb[SE401_NUMSBUF];
struct urb *inturb;
-
+
int button;
int buttonpressed;
int curframe; /* Current receiving frame */
- struct se401_frame frame[SE401_NUMFRAMES];
+ struct se401_frame frame[SE401_NUMFRAMES];
int readcount;
int framecount;
int error;
diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/video/sn9c102/Makefile
new file mode 100644
index 00000000000..536ad3098da
--- /dev/null
+++ b/drivers/media/video/sn9c102/Makefile
@@ -0,0 +1,7 @@
+sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \
+ sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \
+ sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \
+ sn9c102_tas5130d1b.o
+
+obj-$(CONFIG_USB_SN9C102) += sn9c102.o
+
diff --git a/drivers/usb/media/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h
index 1d70a62b9f2..2c6ff396daf 100644
--- a/drivers/usb/media/sn9c102.h
+++ b/drivers/media/video/sn9c102/sn9c102.h
@@ -164,7 +164,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
void
sn9c102_attach_sensor(struct sn9c102_device* cam,
- struct sn9c102_sensor* sensor)
+ struct sn9c102_sensor* sensor)
{
memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
}
@@ -183,7 +183,7 @@ do { \
dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
else if ((level) >= 3) \
dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args); \
+ __FUNCTION__, __LINE__ , ## args); \
} \
} while (0)
# define V4LDBG(level, name, cmd) \
@@ -198,7 +198,7 @@ do { \
pr_info("sn9c102: " fmt "\n", ## args); \
else if ((level) == 3) \
pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__, \
- __LINE__ , ## args); \
+ __LINE__ , ## args); \
} \
} while (0)
#else
@@ -210,7 +210,7 @@ do { \
#undef PDBG
#define PDBG(fmt, args...) \
dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args)
+ __FUNCTION__, __LINE__ , ## args)
#undef PDBGG
#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 4c6cc639572..ea4394dc941 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -62,53 +62,53 @@ MODULE_LICENSE(SN9C102_MODULE_LICENSE);
static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1};
module_param_array(video_nr, short, NULL, 0444);
MODULE_PARM_DESC(video_nr,
- "\n<-1|n[,...]> Specify V4L2 minor mode number."
- "\n -1 = use next available (default)"
- "\n n = use minor number n (integer >= 0)"
- "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES)
- " cameras this way."
- "\nFor example:"
- "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
- "\nthe second camera and use auto for the first"
- "\none and for every other camera."
- "\n");
-
-static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
- SN9C102_FORCE_MUNMAP};
+ "\n<-1|n[,...]> Specify V4L2 minor mode number."
+ "\n -1 = use next available (default)"
+ "\n n = use minor number n (integer >= 0)"
+ "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES)
+ " cameras this way."
+ "\nFor example:"
+ "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
+ "\nthe second camera and use auto for the first"
+ "\none and for every other camera."
+ "\n");
+
+static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
+ SN9C102_FORCE_MUNMAP};
module_param_array(force_munmap, bool, NULL, 0444);
MODULE_PARM_DESC(force_munmap,
- "\n<0|1[,...]> Force the application to unmap previously"
- "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
- "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
- "\nthis feature. This parameter is specific for each"
- "\ndetected camera."
- "\n 0 = do not force memory unmapping"
- "\n 1 = force memory unmapping (save memory)"
- "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
- "\n");
+ "\n<0|1[,...]> Force the application to unmap previously"
+ "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
+ "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
+ "\nthis feature. This parameter is specific for each"
+ "\ndetected camera."
+ "\n 0 = do not force memory unmapping"
+ "\n 1 = force memory unmapping (save memory)"
+ "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+ "\n");
static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
- SN9C102_FRAME_TIMEOUT};
+ SN9C102_FRAME_TIMEOUT};
module_param_array(frame_timeout, uint, NULL, 0644);
MODULE_PARM_DESC(frame_timeout,
- "\n<n[,...]> Timeout for a video frame in seconds."
- "\nThis parameter is specific for each detected camera."
- "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
- "\n");
+ "\n<n[,...]> Timeout for a video frame in seconds."
+ "\nThis parameter is specific for each detected camera."
+ "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
+ "\n");
#ifdef SN9C102_DEBUG
static unsigned short debug = SN9C102_DEBUG_LEVEL;
module_param(debug, ushort, 0644);
MODULE_PARM_DESC(debug,
- "\n<n> Debugging information level, from 0 to 3:"
- "\n0 = none (use carefully)"
- "\n1 = critical errors"
- "\n2 = significant informations"
- "\n3 = more verbose messages"
- "\nLevel 3 is useful for testing only, when only "
- "one device is used."
- "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
- "\n");
+ "\n<n> Debugging information level, from 0 to 3:"
+ "\n0 = none (use carefully)"
+ "\n1 = critical errors"
+ "\n2 = significant informations"
+ "\n3 = more verbose messages"
+ "\nLevel 3 is useful for testing only, when only "
+ "one device is used."
+ "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
+ "\n");
#endif
/*****************************************************************************/
@@ -131,16 +131,16 @@ static sn9c102_eof_header_t sn9c102_eof_header[] = {
/*****************************************************************************/
-static u32
-sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
- enum sn9c102_io_method io)
+static u32
+sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
+ enum sn9c102_io_method io)
{
struct v4l2_pix_format* p = &(cam->sensor.pix_format);
struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
const size_t imagesize = cam->module_param.force_munmap ||
- io == IO_READ ?
- (p->width * p->height * p->priv) / 8 :
- (r->width * r->height * p->priv) / 8;
+ io == IO_READ ?
+ (p->width * p->height * p->priv) / 8 :
+ (r->width * r->height * p->priv) / 8;
void* buff = NULL;
u32 i;
@@ -232,8 +232,8 @@ int sn9c102_write_regs(struct sn9c102_device* cam, u8* buff, u16 index)
return -1;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
- index, 0, buff, sizeof(buff),
- SN9C102_CTRL_TIMEOUT*sizeof(buff));
+ index, 0, buff, sizeof(buff),
+ SN9C102_CTRL_TIMEOUT*sizeof(buff));
if (res < 0) {
DBG(3, "Failed to write registers (index 0x%02X, error %d)",
index, res);
@@ -259,7 +259,7 @@ int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index)
*buff = value;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
- index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
+ index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
if (res < 0) {
DBG(3, "Failed to write a register (value 0x%02X, index "
"0x%02X, error %d)", value, index, res);
@@ -280,7 +280,7 @@ static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
int res;
res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
- index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
+ index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
if (res < 0)
DBG(3, "Failed to read a register (index 0x%02X, error %d)",
index, res);
@@ -319,8 +319,8 @@ sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor)
static int
-sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
- struct sn9c102_sensor* sensor)
+sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
+ struct sn9c102_sensor* sensor)
{
int r;
r = sn9c102_read_reg(cam, 0x08);
@@ -329,8 +329,8 @@ sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
static int
-sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
- struct sn9c102_sensor* sensor)
+sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
+ struct sn9c102_sensor* sensor)
{
int r;
r = sn9c102_read_reg(cam, 0x08);
@@ -338,10 +338,10 @@ sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
}
-int
+int
sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
- struct sn9c102_sensor* sensor, u8 data0, u8 data1,
- u8 n, u8 buffer[])
+ struct sn9c102_sensor* sensor, u8 data0, u8 data1,
+ u8 n, u8 buffer[])
{
struct usb_device* udev = cam->usbdev;
u8* data = cam->control_buffer;
@@ -349,12 +349,12 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
/* Write cycle */
data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
- ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10;
+ ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10;
data[1] = data0; /* I2C slave id */
data[2] = data1; /* address */
data[7] = 0x10;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
- 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
+ 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
if (res < 0)
err += res;
@@ -362,12 +362,12 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
/* Read cycle - n bytes */
data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
- ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) |
- (n << 4) | 0x02;
+ ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) |
+ (n << 4) | 0x02;
data[1] = data0;
data[7] = 0x10;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
- 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
+ 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
if (res < 0)
err += res;
@@ -375,7 +375,7 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
/* The first read byte will be placed in data[4] */
res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
- 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT);
+ 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT);
if (res < 0)
err += res;
@@ -396,10 +396,10 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
}
-int
+int
sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
- struct sn9c102_sensor* sensor, u8 n, u8 data0,
- u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
+ struct sn9c102_sensor* sensor, u8 n, u8 data0,
+ u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
{
struct usb_device* udev = cam->usbdev;
u8* data = cam->control_buffer;
@@ -407,8 +407,8 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
/* Write cycle. It usually is address + value */
data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
- ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0)
- | ((n - 1) << 4);
+ ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0)
+ | ((n - 1) << 4);
data[1] = data0;
data[2] = data1;
data[3] = data2;
@@ -417,7 +417,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
data[6] = data5;
data[7] = 0x14;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
- 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
+ 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
if (res < 0)
err += res;
@@ -437,20 +437,20 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
int
sn9c102_i2c_try_read(struct sn9c102_device* cam,
- struct sn9c102_sensor* sensor, u8 address)
+ struct sn9c102_sensor* sensor, u8 address)
{
return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id,
- address, 1, NULL);
+ address, 1, NULL);
}
int
sn9c102_i2c_try_write(struct sn9c102_device* cam,
- struct sn9c102_sensor* sensor, u8 address, u8 value)
+ struct sn9c102_sensor* sensor, u8 address, u8 value)
{
- return sn9c102_i2c_try_raw_write(cam, sensor, 3,
- sensor->i2c_slave_id, address,
- value, 0, 0, 0);
+ return sn9c102_i2c_try_raw_write(cam, sensor, 3,
+ sensor->i2c_slave_id, address,
+ value, 0, 0, 0);
}
@@ -484,7 +484,7 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
n = sizeof(sn9c103_sof_header) / soflen;
}
- for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
+ for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
for (j = 0; j < n; j++)
/* The invariable part of the header is 6 bytes long */
if ((cam->bridge != BRIDGE_SN9C103 &&
@@ -552,15 +552,15 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
if (!(*f))
(*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t,
- frame);
+ frame);
imagesize = (cam->sensor.pix_format.width *
- cam->sensor.pix_format.height *
- cam->sensor.pix_format.priv) / 8;
+ cam->sensor.pix_format.height *
+ cam->sensor.pix_format.priv) / 8;
soflen = (cam->bridge) == BRIDGE_SN9C103 ?
- sizeof(sn9c103_sof_header_t) :
- sizeof(sn9c102_sof_header_t);
+ sizeof(sn9c103_sof_header_t) :
+ sizeof(sn9c102_sof_header_t);
for (i = 0; i < urb->number_of_packets; i++) {
unsigned int img, len, status;
@@ -611,19 +611,19 @@ end_of_frame:
if ((*f)->buf.bytesused == imagesize ||
(cam->sensor.pix_format.pixelformat ==
- V4L2_PIX_FMT_SN9C10X && eof)) {
+ V4L2_PIX_FMT_SN9C10X && eof)) {
u32 b;
b = (*f)->buf.bytesused;
(*f)->state = F_DONE;
(*f)->buf.sequence= ++cam->frame_count;
spin_lock(&cam->queue_lock);
list_move_tail(&(*f)->frame,
- &cam->outqueue);
+ &cam->outqueue);
if (!list_empty(&cam->inqueue))
(*f) = list_entry(
- cam->inqueue.next,
- struct sn9c102_frame_t,
- frame );
+ cam->inqueue.next,
+ struct sn9c102_frame_t,
+ frame );
else
(*f) = NULL;
spin_unlock(&cam->queue_lock);
@@ -638,7 +638,7 @@ end_of_frame:
} else if (eof) {
(*f)->state = F_ERROR;
DBG(3, "Not expected EOF after %lu "
- "bytes of image data",
+ "bytes of image data",
(unsigned long)
((*f)->buf.bytesused));
}
@@ -676,7 +676,7 @@ start_of_frame:
goto end_of_frame;
} else {
DBG(3, "SOF before expected EOF after "
- "%lu bytes of image data",
+ "%lu bytes of image data",
(unsigned long)
((*f)->buf.bytesused));
goto start_of_frame;
@@ -702,18 +702,18 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
struct usb_device *udev = cam->usbdev;
struct urb* urb;
const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512,
- 680, 800, 900, 1023};
+ 680, 800, 900, 1023};
const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512,
- 680, 800, 900, 1003};
+ 680, 800, 900, 1003};
const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ?
- sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] :
- sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING];
+ sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] :
+ sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING];
s8 i, j;
int err = 0;
for (i = 0; i < SN9C102_URBS; i++) {
cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz,
- GFP_KERNEL);
+ GFP_KERNEL);
if (!cam->transfer_buffer[i]) {
err = -ENOMEM;
DBG(1, "Not enough memory");
@@ -815,9 +815,9 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
cam->stream = STREAM_INTERRUPT;
timeout = wait_event_timeout(cam->wait_stream,
- (cam->stream == STREAM_OFF) ||
- (cam->state & DEV_DISCONNECTED),
- SN9C102_URB_TIMEOUT);
+ (cam->stream == STREAM_OFF) ||
+ (cam->state & DEV_DISCONNECTED),
+ SN9C102_URB_TIMEOUT);
if (cam->state & DEV_DISCONNECTED)
return -ENODEV;
else if (cam->stream != STREAM_OFF) {
@@ -861,7 +861,7 @@ static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count)
/*
NOTE 1: being inside one of the following methods implies that the v4l
- device exists for sure (see kobjects and reference counters)
+ device exists for sure (see kobjects and reference counters)
NOTE 2: buffers are PAGE_SIZE long
*/
@@ -884,10 +884,10 @@ static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf)
mutex_unlock(&sn9c102_sysfs_lock);
return count;
-}
+}
-static ssize_t
+static ssize_t
sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len)
{
struct sn9c102_device* cam;
@@ -947,7 +947,7 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)
mutex_unlock(&sn9c102_sysfs_lock);
return count;
-}
+}
static ssize_t
@@ -1013,7 +1013,7 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf)
}
-static ssize_t
+static ssize_t
sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
{
struct sn9c102_device* cam;
@@ -1078,7 +1078,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
mutex_unlock(&sn9c102_sysfs_lock);
return count;
-}
+}
static ssize_t
@@ -1222,22 +1222,22 @@ static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf)
DBG(3, "Frame header, read bytes: %zd", count);
return count;
-}
+}
static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,
- sn9c102_show_reg, sn9c102_store_reg);
+ sn9c102_show_reg, sn9c102_store_reg);
static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR,
- sn9c102_show_val, sn9c102_store_val);
+ sn9c102_show_val, sn9c102_store_val);
static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
- sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
+ sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
- sn9c102_show_i2c_val, sn9c102_store_i2c_val);
+ sn9c102_show_i2c_val, sn9c102_store_i2c_val);
static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
static CLASS_DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue);
static CLASS_DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red);
static CLASS_DEVICE_ATTR(frame_header, S_IRUGO,
- sn9c102_show_frame_header, NULL);
+ sn9c102_show_frame_header, NULL);
static void sn9c102_create_sysfs(struct sn9c102_device* cam)
@@ -1278,7 +1278,7 @@ sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix)
static int
sn9c102_set_compression(struct sn9c102_device* cam,
- struct v4l2_jpegcompression* compression)
+ struct v4l2_jpegcompression* compression)
{
int err = 0;
@@ -1469,8 +1469,8 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
}
mutex_unlock(&cam->dev_mutex);
err = wait_event_interruptible_exclusive(cam->open,
- cam->state & DEV_DISCONNECTED
- || !cam->users);
+ cam->state & DEV_DISCONNECTED
+ || !cam->users);
if (err) {
up_read(&sn9c102_disconnect);
return err;
@@ -1600,12 +1600,12 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
return -EAGAIN;
}
timeout = wait_event_interruptible_timeout
- ( cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED),
- cam->module_param.frame_timeout *
- 1000 * msecs_to_jiffies(1) );
+ ( cam->wait_frame,
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED),
+ cam->module_param.frame_timeout *
+ 1000 * msecs_to_jiffies(1) );
if (timeout < 0) {
mutex_unlock(&cam->fileop_mutex);
return timeout;
@@ -1672,7 +1672,7 @@ static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
if (cam->io == IO_NONE) {
if (!sn9c102_request_buffers(cam, cam->nreadbuffers,
- IO_READ)) {
+ IO_READ)) {
DBG(1, "poll() failed, not enough memory");
goto error;
}
@@ -1729,7 +1729,7 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
{
struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
unsigned long size = vma->vm_end - vma->vm_start,
- start = vma->vm_start;
+ start = vma->vm_start;
void *pos;
u32 i;
@@ -1797,13 +1797,13 @@ sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg)
.driver = "sn9c102",
.version = SN9C102_MODULE_VERSION_CODE,
.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
- V4L2_CAP_STREAMING,
+ V4L2_CAP_STREAMING,
};
strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
- sizeof(cap.bus_info));
+ sizeof(cap.bus_info));
if (copy_to_user(arg, &cap, sizeof(cap)))
return -EFAULT;
@@ -2138,7 +2138,7 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
return -EINVAL;
pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X)
- ? 0 : (pfmt->width * pfmt->priv) / 8;
+ ? 0 : (pfmt->width * pfmt->priv) / 8;
pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
pfmt->field = V4L2_FIELD_NONE;
memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
@@ -2152,7 +2152,7 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
static int
sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
- void __user * arg)
+ void __user * arg)
{
struct sn9c102_sensor* s = &cam->sensor;
struct v4l2_format format;
@@ -2214,7 +2214,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
pix->priv = pfmt->priv; /* bpp */
pix->colorspace = pfmt->colorspace;
pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
- ? 0 : (pix->width * pix->priv) / 8;
+ ? 0 : (pix->width * pix->priv) / 8;
pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
pix->field = V4L2_FIELD_NONE;
@@ -2287,7 +2287,7 @@ static int
sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg)
{
if (copy_to_user(arg, &cam->compression,
- sizeof(cam->compression)))
+ sizeof(cam->compression)))
return -EFAULT;
return 0;
@@ -2436,7 +2436,7 @@ sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg)
static int
sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
- void __user * arg)
+ void __user * arg)
{
struct v4l2_buffer b;
struct sn9c102_frame_t *f;
@@ -2455,12 +2455,12 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
timeout = wait_event_interruptible_timeout
- ( cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED),
- cam->module_param.frame_timeout *
- 1000 * msecs_to_jiffies(1) );
+ ( cam->wait_frame,
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED),
+ cam->module_param.frame_timeout *
+ 1000 * msecs_to_jiffies(1) );
if (timeout < 0)
return timeout;
if (cam->state & DEV_DISCONNECTED)
@@ -2584,7 +2584,7 @@ sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg)
static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
- unsigned int cmd, void __user * arg)
+ unsigned int cmd, void __user * arg)
{
struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
@@ -2678,7 +2678,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
static int sn9c102_ioctl(struct inode* inode, struct file* filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
int err = 0;
@@ -2761,7 +2761,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
}
cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ?
- BRIDGE_SN9C103 : BRIDGE_SN9C102;
+ BRIDGE_SN9C103 : BRIDGE_SN9C102;
switch (cam->bridge) {
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
@@ -2807,7 +2807,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
mutex_lock(&cam->dev_mutex);
err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
- video_nr[dev_nr]);
+ video_nr[dev_nr]);
if (err) {
DBG(1, "V4L2 device registration failed");
if (err == -ENFILE && video_nr[dev_nr] == -1)
diff --git a/drivers/usb/media/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
index 46c12ec3ca6..c4117bf64b6 100644
--- a/drivers/usb/media/sn9c102_hv7131d.c
+++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
@@ -44,8 +44,8 @@ static int hv7131d_init(struct sn9c102_device* cam)
}
-static int hv7131d_get_ctrl(struct sn9c102_device* cam,
- struct v4l2_control* ctrl)
+static int hv7131d_get_ctrl(struct sn9c102_device* cam,
+ struct v4l2_control* ctrl)
{
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
@@ -88,8 +88,8 @@ static int hv7131d_get_ctrl(struct sn9c102_device* cam,
}
-static int hv7131d_set_ctrl(struct sn9c102_device* cam,
- const struct v4l2_control* ctrl)
+static int hv7131d_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
{
int err = 0;
@@ -121,8 +121,8 @@ static int hv7131d_set_ctrl(struct sn9c102_device* cam,
}
-static int hv7131d_set_crop(struct sn9c102_device* cam,
- const struct v4l2_rect* rect)
+static int hv7131d_set_crop(struct sn9c102_device* cam,
+ const struct v4l2_rect* rect)
{
struct sn9c102_sensor* s = &hv7131d;
int err = 0;
@@ -136,8 +136,8 @@ static int hv7131d_set_crop(struct sn9c102_device* cam,
}
-static int hv7131d_set_pix_format(struct sn9c102_device* cam,
- const struct v4l2_pix_format* pix)
+static int hv7131d_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
{
int err = 0;
diff --git a/drivers/usb/media/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c
index d9aa7a61095..4169ea4a2e2 100644
--- a/drivers/usb/media/sn9c102_mi0343.c
+++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c
@@ -39,64 +39,64 @@ static int mi0343_init(struct sn9c102_device* cam)
err += sn9c102_write_reg(cam, 0xa0, 0x19);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x0d, 0x00, 0x01, 0, 0);
+ 0x0d, 0x00, 0x01, 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x0d, 0x00, 0x00, 0, 0);
+ 0x0d, 0x00, 0x00, 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x03, 0x01, 0xe1, 0, 0);
+ 0x03, 0x01, 0xe1, 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x04, 0x02, 0x81, 0, 0);
+ 0x04, 0x02, 0x81, 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x05, 0x00, 0x17, 0, 0);
+ 0x05, 0x00, 0x17, 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x06, 0x00, 0x11, 0, 0);
+ 0x06, 0x00, 0x11, 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x62, 0x04, 0x9a, 0, 0);
+ 0x62, 0x04, 0x9a, 0, 0);
return err;
}
-static int mi0343_get_ctrl(struct sn9c102_device* cam,
- struct v4l2_control* ctrl)
+static int mi0343_get_ctrl(struct sn9c102_device* cam,
+ struct v4l2_control* ctrl)
{
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x09, 2+1, mi0343_i2c_data) < 0)
+ 0x09, 2+1, mi0343_i2c_data) < 0)
return -EIO;
ctrl->value = mi0343_i2c_data[2];
return 0;
case V4L2_CID_GAIN:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x35, 2+1, mi0343_i2c_data) < 0)
+ 0x35, 2+1, mi0343_i2c_data) < 0)
return -EIO;
break;
case V4L2_CID_HFLIP:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x20, 2+1, mi0343_i2c_data) < 0)
+ 0x20, 2+1, mi0343_i2c_data) < 0)
return -EIO;
ctrl->value = mi0343_i2c_data[3] & 0x20 ? 1 : 0;
return 0;
case V4L2_CID_VFLIP:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x20, 2+1, mi0343_i2c_data) < 0)
+ 0x20, 2+1, mi0343_i2c_data) < 0)
return -EIO;
ctrl->value = mi0343_i2c_data[3] & 0x80 ? 1 : 0;
return 0;
case V4L2_CID_RED_BALANCE:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x2d, 2+1, mi0343_i2c_data) < 0)
+ 0x2d, 2+1, mi0343_i2c_data) < 0)
return -EIO;
break;
case V4L2_CID_BLUE_BALANCE:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x2c, 2+1, mi0343_i2c_data) < 0)
+ 0x2c, 2+1, mi0343_i2c_data) < 0)
return -EIO;
break;
case SN9C102_V4L2_CID_GREEN_BALANCE:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x2e, 2+1, mi0343_i2c_data) < 0)
+ 0x2e, 2+1, mi0343_i2c_data) < 0)
return -EIO;
break;
default:
@@ -121,8 +121,8 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
}
-static int mi0343_set_ctrl(struct sn9c102_device* cam,
- const struct v4l2_control* ctrl)
+static int mi0343_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
{
u16 reg = 0;
int err = 0;
@@ -144,51 +144,51 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam,
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
- 0x09, ctrl->value, 0x00,
- 0, 0);
+ mi0343.i2c_slave_id,
+ 0x09, ctrl->value, 0x00,
+ 0, 0);
break;
case V4L2_CID_GAIN:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
- 0x35, reg >> 8, reg & 0xff,
- 0, 0);
+ mi0343.i2c_slave_id,
+ 0x35, reg >> 8, reg & 0xff,
+ 0, 0);
break;
case V4L2_CID_HFLIP:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
- 0x20, ctrl->value ? 0x40:0x00,
- ctrl->value ? 0x20:0x00,
- 0, 0);
+ mi0343.i2c_slave_id,
+ 0x20, ctrl->value ? 0x40:0x00,
+ ctrl->value ? 0x20:0x00,
+ 0, 0);
break;
case V4L2_CID_VFLIP:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
- 0x20, ctrl->value ? 0x80:0x00,
- ctrl->value ? 0x80:0x00,
- 0, 0);
+ mi0343.i2c_slave_id,
+ 0x20, ctrl->value ? 0x80:0x00,
+ ctrl->value ? 0x80:0x00,
+ 0, 0);
break;
case V4L2_CID_RED_BALANCE:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
- 0x2d, reg >> 8, reg & 0xff,
- 0, 0);
+ mi0343.i2c_slave_id,
+ 0x2d, reg >> 8, reg & 0xff,
+ 0, 0);
break;
case V4L2_CID_BLUE_BALANCE:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
- 0x2c, reg >> 8, reg & 0xff,
- 0, 0);
+ mi0343.i2c_slave_id,
+ 0x2c, reg >> 8, reg & 0xff,
+ 0, 0);
break;
case SN9C102_V4L2_CID_GREEN_BALANCE:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
- 0x2b, reg >> 8, reg & 0xff,
- 0, 0);
+ mi0343.i2c_slave_id,
+ 0x2b, reg >> 8, reg & 0xff,
+ 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
- 0x2e, reg >> 8, reg & 0xff,
- 0, 0);
+ mi0343.i2c_slave_id,
+ 0x2e, reg >> 8, reg & 0xff,
+ 0, 0);
break;
default:
return -EINVAL;
@@ -198,8 +198,8 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam,
}
-static int mi0343_set_crop(struct sn9c102_device* cam,
- const struct v4l2_rect* rect)
+static int mi0343_set_crop(struct sn9c102_device* cam,
+ const struct v4l2_rect* rect)
{
struct sn9c102_sensor* s = &mi0343;
int err = 0;
@@ -213,20 +213,20 @@ static int mi0343_set_crop(struct sn9c102_device* cam,
}
-static int mi0343_set_pix_format(struct sn9c102_device* cam,
- const struct v4l2_pix_format* pix)
+static int mi0343_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
{
int err = 0;
if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
- 0x0a, 0x00, 0x03, 0, 0);
+ mi0343.i2c_slave_id,
+ 0x0a, 0x00, 0x03, 0, 0);
err += sn9c102_write_reg(cam, 0x20, 0x19);
} else {
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
- 0x0a, 0x00, 0x05, 0, 0);
+ mi0343.i2c_slave_id,
+ 0x0a, 0x00, 0x05, 0, 0);
err += sn9c102_write_reg(cam, 0xa0, 0x19);
}
@@ -351,7 +351,7 @@ int sn9c102_probe_mi0343(struct sn9c102_device* cam)
return -EIO;
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
- 2, mi0343_i2c_data) < 0)
+ 2, mi0343_i2c_data) < 0)
return -EIO;
if (mi0343_i2c_data[4] != 0x32 && mi0343_i2c_data[3] != 0xe3)
diff --git a/drivers/usb/media/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c
index 42852b7cb04..3da04202178 100644
--- a/drivers/usb/media/sn9c102_ov7630.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c
@@ -69,7 +69,7 @@ static int ov7630_init(struct sn9c102_device* cam)
static int ov7630_set_ctrl(struct sn9c102_device* cam,
- const struct v4l2_control* ctrl)
+ const struct v4l2_control* ctrl)
{
int err = 0;
@@ -89,8 +89,8 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam,
break;
case V4L2_CID_CONTRAST:
err += ctrl->value ? sn9c102_i2c_write(cam, 0x05,
- (ctrl->value-1) | 0x20)
- : sn9c102_i2c_write(cam, 0x05, 0x00);
+ (ctrl->value-1) | 0x20)
+ : sn9c102_i2c_write(cam, 0x05, 0x00);
break;
case V4L2_CID_BRIGHTNESS:
err += sn9c102_i2c_write(cam, 0x06, ctrl->value);
@@ -100,8 +100,8 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam,
break;
case V4L2_CID_HUE:
err += ctrl->value ? sn9c102_i2c_write(cam, 0x04,
- (ctrl->value-1) | 0x20)
- : sn9c102_i2c_write(cam, 0x04, 0x00);
+ (ctrl->value-1) | 0x20)
+ : sn9c102_i2c_write(cam, 0x04, 0x00);
break;
case V4L2_CID_DO_WHITE_BALANCE:
err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
@@ -139,7 +139,7 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam,
static int ov7630_set_crop(struct sn9c102_device* cam,
- const struct v4l2_rect* rect)
+ const struct v4l2_rect* rect)
{
struct sn9c102_sensor* s = &ov7630;
int err = 0;
@@ -152,7 +152,7 @@ static int ov7630_set_crop(struct sn9c102_device* cam,
static int ov7630_set_pix_format(struct sn9c102_device* cam,
- const struct v4l2_pix_format* pix)
+ const struct v4l2_pix_format* pix)
{
int err = 0;
diff --git a/drivers/usb/media/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c
index b1dee78abe0..9915944235e 100644
--- a/drivers/usb/media/sn9c102_pas106b.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c
@@ -53,8 +53,8 @@ static int pas106b_init(struct sn9c102_device* cam)
}
-static int pas106b_get_ctrl(struct sn9c102_device* cam,
- struct v4l2_control* ctrl)
+static int pas106b_get_ctrl(struct sn9c102_device* cam,
+ struct v4l2_control* ctrl)
{
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
@@ -102,8 +102,8 @@ static int pas106b_get_ctrl(struct sn9c102_device* cam,
}
-static int pas106b_set_ctrl(struct sn9c102_device* cam,
- const struct v4l2_control* ctrl)
+static int pas106b_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
{
int err = 0;
@@ -140,8 +140,8 @@ static int pas106b_set_ctrl(struct sn9c102_device* cam,
}
-static int pas106b_set_crop(struct sn9c102_device* cam,
- const struct v4l2_rect* rect)
+static int pas106b_set_crop(struct sn9c102_device* cam,
+ const struct v4l2_rect* rect)
{
struct sn9c102_sensor* s = &pas106b;
int err = 0;
@@ -155,8 +155,8 @@ static int pas106b_set_crop(struct sn9c102_device* cam,
}
-static int pas106b_set_pix_format(struct sn9c102_device* cam,
- const struct v4l2_pix_format* pix)
+static int pas106b_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
{
int err = 0;
diff --git a/drivers/usb/media/sn9c102_pas202bca.c b/drivers/media/video/sn9c102/sn9c102_pas202bca.c
index 3453237055b..c8f1ae2152b 100644
--- a/drivers/usb/media/sn9c102_pas202bca.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas202bca.c
@@ -54,7 +54,7 @@ static int pas202bca_init(struct sn9c102_device* cam)
static int pas202bca_set_pix_format(struct sn9c102_device* cam,
- const struct v4l2_pix_format* pix)
+ const struct v4l2_pix_format* pix)
{
int err = 0;
@@ -68,7 +68,7 @@ static int pas202bca_set_pix_format(struct sn9c102_device* cam,
static int pas202bca_set_ctrl(struct sn9c102_device* cam,
- const struct v4l2_control* ctrl)
+ const struct v4l2_control* ctrl)
{
int err = 0;
@@ -102,7 +102,7 @@ static int pas202bca_set_ctrl(struct sn9c102_device* cam,
static int pas202bca_set_crop(struct sn9c102_device* cam,
- const struct v4l2_rect* rect)
+ const struct v4l2_rect* rect)
{
struct sn9c102_sensor* s = &pas202bca;
int err = 0;
diff --git a/drivers/usb/media/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
index d068616ab33..e3c1178e339 100644
--- a/drivers/usb/media/sn9c102_pas202bcb.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
@@ -58,8 +58,8 @@ static int pas202bcb_init(struct sn9c102_device* cam)
}
-static int pas202bcb_get_ctrl(struct sn9c102_device* cam,
- struct v4l2_control* ctrl)
+static int pas202bcb_get_ctrl(struct sn9c102_device* cam,
+ struct v4l2_control* ctrl)
{
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
@@ -101,8 +101,8 @@ static int pas202bcb_get_ctrl(struct sn9c102_device* cam,
}
-static int pas202bcb_set_pix_format(struct sn9c102_device* cam,
- const struct v4l2_pix_format* pix)
+static int pas202bcb_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
{
int err = 0;
@@ -115,8 +115,8 @@ static int pas202bcb_set_pix_format(struct sn9c102_device* cam,
}
-static int pas202bcb_set_ctrl(struct sn9c102_device* cam,
- const struct v4l2_control* ctrl)
+static int pas202bcb_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
{
int err = 0;
@@ -149,8 +149,8 @@ static int pas202bcb_set_ctrl(struct sn9c102_device* cam,
}
-static int pas202bcb_set_crop(struct sn9c102_device* cam,
- const struct v4l2_rect* rect)
+static int pas202bcb_set_crop(struct sn9c102_device* cam,
+ const struct v4l2_rect* rect)
{
struct sn9c102_sensor* s = &pas202bcb;
int err = 0;
@@ -167,7 +167,7 @@ static int pas202bcb_set_crop(struct sn9c102_device* cam,
static struct sn9c102_sensor pas202bcb = {
.name = "PAS202BCB",
.maintainer = "Carlos Eduardo Medaglia Dyonisio "
- "<medaglia@undl.org.br>",
+ "<medaglia@undl.org.br>",
.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES,
diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h
index 2afd9e9d09b..2a874ee6f9f 100644
--- a/drivers/usb/media/sn9c102_sensor.h
+++ b/drivers/media/video/sn9c102/sn9c102_sensor.h
@@ -58,7 +58,7 @@ struct sn9c102_sensor;
Probing functions: on success, you must attach the sensor to the camera
by calling sn9c102_attach_sensor() provided below.
To enable the I2C communication, you might need to perform a really basic
- initialization of the SN9C10X chip by using the write function declared
+ initialization of the SN9C10X chip by using the write function declared
ahead.
Functions must return 0 on success, the appropriate error otherwise.
*/
@@ -73,7 +73,7 @@ extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
/*
Add the above entries to this table. Be sure to add the entry in the right
- place, since, on failure, the next probing routine is called according to
+ place, since, on failure, the next probing routine is called according to
the order of the list below, from top to bottom.
*/
#define SN9C102_SENSOR_TABLE \
@@ -94,9 +94,9 @@ extern struct sn9c102_device*
sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id);
/* Attach a probed sensor to the camera. */
-extern void
+extern void
sn9c102_attach_sensor(struct sn9c102_device* cam,
- struct sn9c102_sensor* sensor);
+ struct sn9c102_sensor* sensor);
/*
Each SN9C10x camera has proper PID/VID identifiers.
@@ -105,7 +105,7 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
*/
#define SN9C102_USB_DEVICE(vend, prod, intclass) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
- USB_DEVICE_ID_MATCH_INT_CLASS, \
+ USB_DEVICE_ID_MATCH_INT_CLASS, \
.idVendor = (vend), \
.idProduct = (prod), \
.bInterfaceClass = (intclass)
@@ -162,19 +162,19 @@ static const struct usb_device_id sn9c102_id_table[] = { \
Read/write routines: they always return -1 on error, 0 or the read value
otherwise. NOTE that a real read operation is not supported by the SN9C10X
chip for some of its registers. To work around this problem, a pseudo-read
- call is provided instead: it returns the last successfully written value
+ call is provided instead: it returns the last successfully written value
on the register (0 if it has never been written), the usual -1 on error.
*/
/* The "try" I2C I/O versions are used when probing the sensor */
extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*,
- u8 address, u8 value);
+ u8 address, u8 value);
extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
- u8 address);
+ u8 address);
/*
These must be used if and only if the sensor doesn't implement the standard
- I2C protocol. There are a number of good reasons why you must use the
+ I2C protocol. There are a number of good reasons why you must use the
single-byte versions of these functions: do not abuse. The first function
writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C10X
chip. The second one programs the registers 0x09 and 0x10 with data0 and
@@ -184,12 +184,12 @@ extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
byte.
*/
extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
- struct sn9c102_sensor* sensor, u8 n,
- u8 data0, u8 data1, u8 data2, u8 data3,
- u8 data4, u8 data5);
+ struct sn9c102_sensor* sensor, u8 n,
+ u8 data0, u8 data1, u8 data2, u8 data3,
+ u8 data4, u8 data5);
extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
- struct sn9c102_sensor* sensor, u8 data0,
- u8 data1, u8 n, u8 buffer[]);
+ struct sn9c102_sensor* sensor, u8 data0,
+ u8 data1, u8 n, u8 buffer[]);
/* To be used after the sensor struct has been attached to the camera struct */
extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value);
@@ -252,17 +252,17 @@ struct sn9c102_sensor {
/*
NOTE: Where not noted,most of the functions below are not mandatory.
- Set to null if you do not implement them. If implemented,
- they must return 0 on success, the proper error otherwise.
+ Set to null if you do not implement them. If implemented,
+ they must return 0 on success, the proper error otherwise.
*/
int (*init)(struct sn9c102_device* cam);
/*
- This function will be called after the sensor has been attached.
+ This function will be called after the sensor has been attached.
It should be used to initialize the sensor only, but may also
configure part of the SN9C10X chip if necessary. You don't need to
setup picture settings like brightness, contrast, etc.. here, if
- the corrisponding controls are implemented (see below), since
+ the corrisponding controls are implemented (see below), since
they are adjusted in the core driver by calling the set_ctrl()
method after init(), where the arguments are the default values
specified in the v4l2_queryctrl list of supported controls;
@@ -273,13 +273,13 @@ struct sn9c102_sensor {
struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS];
/*
- Optional list of default controls, defined as indicated in the
+ Optional list of default controls, defined as indicated in the
V4L2 API. Menu type controls are not handled by this interface.
*/
int (*get_ctrl)(struct sn9c102_device* cam, struct v4l2_control* ctrl);
int (*set_ctrl)(struct sn9c102_device* cam,
- const struct v4l2_control* ctrl);
+ const struct v4l2_control* ctrl);
/*
You must implement at least the set_ctrl method if you have defined
the list above. The returned value must follow the V4L2
@@ -306,7 +306,7 @@ struct sn9c102_sensor {
specified in the cropcap substructures 'bounds' and 'defrect'.
By default, the source rectangle should cover the largest possible
area. Again, it is not always true that the largest source rectangle
- can cover the entire active window, although it is a rare case for
+ can cover the entire active window, although it is a rare case for
the hardware we have. The bounds of the source rectangle _must_ be
multiple of 16 and must use the same coordinate system as indicated
before; their centers shall align initially.
@@ -317,13 +317,13 @@ struct sn9c102_sensor {
defined the correct default bounds in the structures.
See the V4L2 API for further details.
NOTE: once you have defined the bounds of the active window
- (struct cropcap.bounds) you must not change them.anymore.
+ (struct cropcap.bounds) you must not change them.anymore.
Only 'bounds' and 'defrect' fields are mandatory, other fields
will be ignored.
*/
int (*set_crop)(struct sn9c102_device* cam,
- const struct v4l2_rect* rect);
+ const struct v4l2_rect* rect);
/*
To be called on VIDIOC_C_SETCROP. The core module always calls a
default routine which configures the appropriate SN9C10X regs (also
@@ -332,12 +332,12 @@ struct sn9c102_sensor {
case you override the default function, you always have to program
the chip to match those values; on error return the corresponding
error code without rolling back.
- NOTE: in case, you must program the SN9C10X chip to get rid of
- blank pixels or blank lines at the _start_ of each line or
- frame after each HSYNC or VSYNC, so that the image starts with
- real RGB data (see regs 0x12, 0x13) (having set H_SIZE and,
- V_SIZE you don't have to care about blank pixels or blank
- lines at the end of each line or frame).
+ NOTE: in case, you must program the SN9C10X chip to get rid of
+ blank pixels or blank lines at the _start_ of each line or
+ frame after each HSYNC or VSYNC, so that the image starts with
+ real RGB data (see regs 0x12, 0x13) (having set H_SIZE and,
+ V_SIZE you don't have to care about blank pixels or blank
+ lines at the end of each line or frame).
*/
struct v4l2_pix_format pix_format;
@@ -349,17 +349,17 @@ struct sn9c102_sensor {
number of bits per pixel for uncompressed video, 8 or 9 (despite the
current value of 'pixelformat').
NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4
- of cropcap.defrect.width and cropcap.defrect.height. I
- suggest 1/1.
+ of cropcap.defrect.width and cropcap.defrect.height. I
+ suggest 1/1.
NOTE 2: The initial compression quality is defined by the first bit
- of reg 0x17 during the initialization of the image sensor.
+ of reg 0x17 during the initialization of the image sensor.
NOTE 3: as said above, you have to program the SN9C10X chip to get
- rid of any blank pixels, so that the output of the sensor
- matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
+ rid of any blank pixels, so that the output of the sensor
+ matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
*/
int (*set_pix_format)(struct sn9c102_device* cam,
- const struct v4l2_pix_format* pix);
+ const struct v4l2_pix_format* pix);
/*
To be called on VIDIOC_S_FMT, when switching from the SBGGR8 to
SN9C10X pixel format or viceversa. On error return the corresponding
diff --git a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
index 2e08c552f40..294eb02fbd8 100644
--- a/drivers/usb/media/sn9c102_tas5110c1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
@@ -44,8 +44,8 @@ static int tas5110c1b_init(struct sn9c102_device* cam)
}
-static int tas5110c1b_set_ctrl(struct sn9c102_device* cam,
- const struct v4l2_control* ctrl)
+static int tas5110c1b_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
{
int err = 0;
@@ -61,8 +61,8 @@ static int tas5110c1b_set_ctrl(struct sn9c102_device* cam,
}
-static int tas5110c1b_set_crop(struct sn9c102_device* cam,
- const struct v4l2_rect* rect)
+static int tas5110c1b_set_crop(struct sn9c102_device* cam,
+ const struct v4l2_rect* rect)
{
struct sn9c102_sensor* s = &tas5110c1b;
int err = 0;
@@ -81,8 +81,8 @@ static int tas5110c1b_set_crop(struct sn9c102_device* cam,
}
-static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
- const struct v4l2_pix_format* pix)
+static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
{
int err = 0;
diff --git a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
index c7b339740bb..9ecb09032b6 100644
--- a/drivers/usb/media/sn9c102_tas5130d1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
@@ -42,8 +42,8 @@ static int tas5130d1b_init(struct sn9c102_device* cam)
}
-static int tas5130d1b_set_ctrl(struct sn9c102_device* cam,
- const struct v4l2_control* ctrl)
+static int tas5130d1b_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
{
int err = 0;
@@ -62,8 +62,8 @@ static int tas5130d1b_set_ctrl(struct sn9c102_device* cam,
}
-static int tas5130d1b_set_crop(struct sn9c102_device* cam,
- const struct v4l2_rect* rect)
+static int tas5130d1b_set_crop(struct sn9c102_device* cam,
+ const struct v4l2_rect* rect)
{
struct sn9c102_sensor* s = &tas5130d1b;
u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104,
@@ -82,8 +82,8 @@ static int tas5130d1b_set_crop(struct sn9c102_device* cam,
}
-static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
- const struct v4l2_pix_format* pix)
+static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
{
int err = 0;
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index 9d769264a32..07476c71174 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -1,4 +1,4 @@
-/*
+/*
* stradis.c - stradis 4:2:2 mpeg decoder driver
*
* Stradis 4:2:2 MPEG-2 Decoder Driver
@@ -1191,9 +1191,9 @@ static void saa7146_set_winsize(struct saa7146 *saa)
}
/* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area
- * bitmap is fixed width, 128 bytes (1024 pixels represented)
- * arranged most-sigificant-bit-left in 32-bit words
- * based on saa7146 clipping hardware, it swaps bytes if LE
+ * bitmap is fixed width, 128 bytes (1024 pixels represented)
+ * arranged most-sigificant-bit-left in 32-bit words
+ * based on saa7146 clipping hardware, it swaps bytes if LE
* much of this makes up for egcs brain damage -- so if you
* are wondering "why did he do this?" it is because the C
* was adjusted to generate the optimal asm output without
@@ -1259,7 +1259,7 @@ static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr)
clip_draw_rectangle(clipmap, cr[i].x, cr[i].y,
cr[i].width, cr[i].height);
}
- /* clip against viewing window AND screen
+ /* clip against viewing window AND screen
so we do not have to rely on the user program
*/
clip_draw_rectangle(clipmap, (saa->win.x + width > saa->win.swidth) ?
diff --git a/drivers/usb/media/stv680.c b/drivers/media/video/stv680.c
index 9636da20748..b38bda83a7c 100644
--- a/drivers/usb/media/stv680.c
+++ b/drivers/media/video/stv680.c
@@ -1,16 +1,16 @@
/*
* STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net)
- *
- * Thanks to STMicroelectronics for information on the usb commands, and
- * to Steve Miller at STM for his help and encouragement while I was
+ *
+ * Thanks to STMicroelectronics for information on the usb commands, and
+ * to Steve Miller at STM for his help and encouragement while I was
* writing this driver.
*
- * This driver is based heavily on the
+ * This driver is based heavily on the
* Endpoints (formerly known as AOX) se401 USB Camera Driver
* Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
*
* Still somewhat based on the Linux ov511 driver.
- *
+ *
* 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
@@ -25,18 +25,18 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * History:
- * ver 0.1 October, 2001. Initial attempt.
+ * History:
+ * ver 0.1 October, 2001. Initial attempt.
*
* ver 0.2 November, 2001. Fixed asbility to resize, added brightness
* function, made more stable (?)
*
- * ver 0.21 Nov, 2001. Added gamma correction and white balance,
- * due to Alexander Schwartz. Still trying to
+ * ver 0.21 Nov, 2001. Added gamma correction and white balance,
+ * due to Alexander Schwartz. Still trying to
* improve stablility. Moved stuff into stv680.h
*
- * ver 0.22 Nov, 2001. Added sharpen function (by Michael Sweet,
- * mike@easysw.com) from GIMP, also used in pencam.
+ * ver 0.22 Nov, 2001. Added sharpen function (by Michael Sweet,
+ * mike@easysw.com) from GIMP, also used in pencam.
* Simple, fast, good integer math routine.
*
* ver 0.23 Dec, 2001 (gkh)
@@ -44,11 +44,11 @@
* Lindent, and did other minor tweaks to get
* things to work properly with 2.5.1
*
- * ver 0.24 Jan, 2002 (kjs)
+ * ver 0.24 Jan, 2002 (kjs)
* Fixed the problem with webcam crashing after
- * two pictures. Changed the way pic is halved to
- * improve quality. Got rid of green line around
- * frame. Fix brightness reset when changing size
+ * two pictures. Changed the way pic is halved to
+ * improve quality. Got rid of green line around
+ * frame. Fix brightness reset when changing size
* bug. Adjusted gamma filters slightly.
*
* ver 0.25 Jan, 2002 (kjs)
@@ -484,7 +484,7 @@ exit:
PDEBUG (1, "STV(i): swapRGB is (forced) ON");
else if (swapRGB_on == -1)
PDEBUG (1, "STV(i): swapRGB is (forced) OFF");
-
+
if (stv_set_video_mode (stv680) < 0) {
PDEBUG (0, "STV(e): Could not set video mode in stv_init");
return -1;
@@ -570,7 +570,7 @@ static int stv680_set_pict (struct usb_stv *stv680, struct video_picture *p)
if (stv680->brightness != p->brightness) {
stv680->chgbright = 1;
stv680->brightness = p->brightness;
- }
+ }
stv680->whiteness = p->whiteness; /* greyscale */
stv680->colour = p->colour;
@@ -612,7 +612,7 @@ static void stv680_video_irq (struct urb *urb, struct pt_regs *regs)
case BUFFER_UNUSED:
memcpy (stv680->scratch[stv680->scratch_next].data,
- (unsigned char *) urb->transfer_buffer, length);
+ (unsigned char *) urb->transfer_buffer, length);
stv680->scratch[stv680->scratch_next].state = BUFFER_READY;
stv680->scratch[stv680->scratch_next].length = length;
if (waitqueue_active (&stv680->wq)) {
@@ -752,7 +752,7 @@ static int stv680_set_size (struct usb_stv *stv680, int width, int height)
PDEBUG (1, "STV(e): request for non-supported size: request: v.width = %i, v.height = %i actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight);
return 1;
}
-
+
/* Stop a current stream and start it again at the new size */
if (wasstreaming)
stv680_stop_stream (stv680);
@@ -773,7 +773,7 @@ static int stv680_set_size (struct usb_stv *stv680, int width, int height)
/*
* STV0680 Vision Camera Chipset Driver
- * Copyright (C) 2000 Adam Harrison <adam@antispin.org>
+ * Copyright (C) 2000 Adam Harrison <adam@antispin.org>
*/
#define RED 0
@@ -842,7 +842,7 @@ static void bayer_unshuffle (struct usb_stv *stv680, struct stv680_scratch *buff
colour = 2;
break;
}
- i = (y * vw + x) * 3;
+ i = (y * vw + x) * 3;
*(output + i + colour) = (unsigned char) p;
} /* for x */
@@ -850,9 +850,9 @@ static void bayer_unshuffle (struct usb_stv *stv680, struct stv680_scratch *buff
/****** gamma correction plus hardcoded white balance */
/* Thanks to Alexander Schwartx <alexander.schwartx@gmx.net> for this code.
- Correction values red[], green[], blue[], are generated by
- (pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1<i<255.
- White balance (RGB)= 1.0, 1.17, 1.48. Values are calculated as double float and
+ Correction values red[], green[], blue[], are generated by
+ (pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1<i<255.
+ White balance (RGB)= 1.0, 1.17, 1.48. Values are calculated as double float and
converted to unsigned char. Values are in stv680.h */
for (y = 0; y < vh; y++) {
diff --git a/drivers/usb/media/stv680.h b/drivers/media/video/stv680.h
index ea46e0001e6..a08f1b08a4b 100644
--- a/drivers/usb/media/stv680.h
+++ b/drivers/media/video/stv680.h
@@ -9,12 +9,12 @@
* 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.
@@ -152,76 +152,76 @@ struct usb_stv {
static const unsigned char red[256] = {
- 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42,
- 44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69,
- 71, 71, 73, 75, 77, 78, 80, 81, 82, 84, 85, 87,
- 88, 89, 90, 91, 93, 94, 95, 97, 98, 98, 99, 101,
- 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
- 114, 115, 116, 116, 117, 118, 119, 120, 121, 122, 123, 124,
- 125, 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134,
- 134, 135, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143,
- 143, 143, 144, 145, 146, 147, 147, 148, 149, 150, 150, 151,
- 152, 152, 152, 153, 154, 154, 155, 156, 157, 157, 158, 159,
- 159, 160, 161, 161, 161, 162, 163, 163, 164, 165, 165, 166,
- 167, 167, 168, 168, 169, 170, 170, 170, 171, 171, 172, 173,
- 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 179, 179,
- 180, 180, 181, 181, 182, 183, 183, 184, 184, 185, 185, 186,
- 187, 187, 188, 188, 188, 188, 189, 190, 190, 191, 191, 192,
- 192, 193, 193, 194, 195, 195, 196, 196, 197, 197, 197, 197,
- 198, 198, 199, 199, 200, 201, 201, 202, 202, 203, 203, 204,
- 204, 205, 205, 206, 206, 206, 206, 207, 207, 208, 208, 209,
- 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215,
- 215, 215, 215, 216, 216, 217, 217, 218, 218, 218, 219, 219,
- 220, 220, 221, 221
-};
+ 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42,
+ 44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69,
+ 71, 71, 73, 75, 77, 78, 80, 81, 82, 84, 85, 87,
+ 88, 89, 90, 91, 93, 94, 95, 97, 98, 98, 99, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134,
+ 134, 135, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143,
+ 143, 143, 144, 145, 146, 147, 147, 148, 149, 150, 150, 151,
+ 152, 152, 152, 153, 154, 154, 155, 156, 157, 157, 158, 159,
+ 159, 160, 161, 161, 161, 162, 163, 163, 164, 165, 165, 166,
+ 167, 167, 168, 168, 169, 170, 170, 170, 171, 171, 172, 173,
+ 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 179, 179,
+ 180, 180, 181, 181, 182, 183, 183, 184, 184, 185, 185, 186,
+ 187, 187, 188, 188, 188, 188, 189, 190, 190, 191, 191, 192,
+ 192, 193, 193, 194, 195, 195, 196, 196, 197, 197, 197, 197,
+ 198, 198, 199, 199, 200, 201, 201, 202, 202, 203, 203, 204,
+ 204, 205, 205, 206, 206, 206, 206, 207, 207, 208, 208, 209,
+ 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215,
+ 215, 215, 215, 216, 216, 217, 217, 218, 218, 218, 219, 219,
+ 220, 220, 221, 221
+};
static const unsigned char green[256] = {
- 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47,
- 50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77,
- 79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97,
- 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113,
- 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126,
- 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
- 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149,
- 150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159,
- 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168,
- 169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177,
- 177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185,
- 186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193,
- 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200,
- 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207,
- 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214,
- 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220,
- 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,
- 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233,
- 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
- 239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244,
- 245, 245, 246, 246
-};
+ 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47,
+ 50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77,
+ 79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97,
+ 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113,
+ 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149,
+ 150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159,
+ 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168,
+ 169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177,
+ 177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185,
+ 186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193,
+ 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200,
+ 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207,
+ 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214,
+ 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220,
+ 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,
+ 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233,
+ 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
+ 239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244,
+ 245, 245, 246, 246
+};
static const unsigned char blue[256] = {
- 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51,
- 55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84,
- 86, 88, 90, 92, 94, 95, 97, 100, 101, 103, 104, 106,
- 107, 110, 111, 112, 114, 115, 116, 118, 119, 121, 122, 124,
- 125, 126, 127, 128, 129, 132, 133, 134, 135, 136, 137, 138,
- 139, 140, 141, 143, 144, 145, 146, 147, 148, 149, 150, 151,
- 152, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163,
- 165, 166, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174,
- 176, 176, 177, 178, 179, 180, 180, 181, 182, 183, 183, 184,
- 185, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194,
- 194, 195, 196, 196, 198, 199, 200, 200, 201, 202, 202, 203,
- 204, 204, 205, 205, 206, 207, 207, 209, 210, 210, 211, 212,
- 212, 213, 213, 214, 215, 215, 216, 217, 217, 218, 218, 220,
- 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,
- 228, 228, 229, 229, 231, 231, 232, 233, 233, 234, 234, 235,
- 235, 236, 236, 237, 238, 238, 239, 239, 240, 240, 242, 242,
- 243, 243, 244, 244, 245, 246, 246, 247, 247, 248, 248, 249,
- 249, 250, 250, 251, 251, 253, 253, 254, 254, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255
-};
+ 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51,
+ 55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84,
+ 86, 88, 90, 92, 94, 95, 97, 100, 101, 103, 104, 106,
+ 107, 110, 111, 112, 114, 115, 116, 118, 119, 121, 122, 124,
+ 125, 126, 127, 128, 129, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163,
+ 165, 166, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174,
+ 176, 176, 177, 178, 179, 180, 180, 181, 182, 183, 183, 184,
+ 185, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194,
+ 194, 195, 196, 196, 198, 199, 200, 200, 201, 202, 202, 203,
+ 204, 204, 205, 205, 206, 207, 207, 209, 210, 210, 211, 212,
+ 212, 213, 213, 214, 215, 215, 216, 217, 217, 218, 218, 220,
+ 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,
+ 228, 228, 229, 229, 231, 231, 232, 233, 233, 234, 234, 235,
+ 235, 236, 236, 237, 238, 238, 239, 239, 240, 240, 242, 242,
+ 243, 243, 244, 244, 245, 246, 246, 247, 247, 248, 248, 249,
+ 249, 250, 250, 251, 251, 253, 253, 254, 254, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255
+};
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index fc3d5824eff..78e043ac9ea 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -48,9 +48,8 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
-#include "bttv.h"
-#include <media/audiochip.h>
#include <media/v4l2-common.h>
+#include <media/i2c-addr.h>
#ifndef VIDEO_AUDIO_BALANCE
# define VIDEO_AUDIO_BALANCE 32
@@ -71,7 +70,7 @@ module_param(maxvol, int, S_IRUGO | S_IWUSR);
/* Address to scan (I2C address of this chip) */
static unsigned short normal_i2c[] = {
- I2C_TDA7432 >> 1,
+ I2C_ADDR_TDA7432 >> 1,
I2C_CLIENT_END,
};
I2C_CLIENT_INSMOD;
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index 0243700f58a..ef494febb5e 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -35,7 +35,7 @@ static int debug = 0; /* insmod parameter */
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
#define SWITCH 0x00
#define LEVEL_ADJUST 0x02
@@ -43,7 +43,7 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#define TEST 0x04
/* addresses to scan, found only at 0x42 (7-Bit) */
-static unsigned short normal_i2c[] = { I2C_TDA9840, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END };
/* magic definition of all other variables and things */
I2C_CLIENT_INSMOD;
diff --git a/drivers/media/video/tda9840.h b/drivers/media/video/tda9840.h
index 28021053bd0..7da8432cdca 100644
--- a/drivers/media/video/tda9840.h
+++ b/drivers/media/video/tda9840.h
@@ -1,7 +1,7 @@
#ifndef __INCLUDED_TDA9840__
#define __INCLUDED_TDA9840__
-#define I2C_TDA9840 0x42
+#define I2C_ADDR_TDA9840 0x42
#define TDA9840_DETECT _IOR('v',1,int)
/* return values for TDA9840_DETCT */
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index ef98c498225..103ccb91929 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -30,24 +30,22 @@
#include <linux/i2c-algo-bit.h>
#include <linux/init.h>
-#include "bttv.h"
-#include <media/audiochip.h>
+
+#include <media/i2c-addr.h>
static int debug; /* insmod parameter */
module_param(debug, int, S_IRUGO | S_IWUSR);
MODULE_LICENSE("GPL");
-
/* Addresses to scan */
static unsigned short normal_i2c[] = {
- I2C_TDA9875 >> 1,
+ I2C_ADDR_TDA9875 >> 1,
I2C_CLIENT_END
};
I2C_CLIENT_INSMOD;
/* This is a superset of the TDA9875 */
struct tda9875 {
- int mode;
int rvol, lvol;
int bass, treble;
struct i2c_client c;
@@ -197,7 +195,6 @@ static void do_tda9875_init(struct i2c_client *client)
tda9875_write(client, TDA9875_MUT, 0xcc ); /* General mute */
- t->mode=AUDIO_UNMUTE;
t->lvol=t->rvol =0; /* 0dB */
t->bass=0; /* 0dB */
t->treble=0; /* 0dB */
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index 774ed0dbc56..523df0b8cc6 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -37,7 +37,7 @@ static int debug = 0; /* insmod parameter */
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
#define TEA6415C_NUM_INPUTS 8
#define TEA6415C_NUM_OUTPUTS 6
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index ad7d2872cfb..e0ff811fab6 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -37,10 +37,10 @@ static int debug = 0; /* insmod parameter */
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
/* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
-static unsigned short normal_i2c[] = { I2C_TEA6420_1, I2C_TEA6420_2, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END };
/* magic definition of all other variables and things */
I2C_CLIENT_INSMOD;
diff --git a/drivers/media/video/tea6420.h b/drivers/media/video/tea6420.h
index ea664df15ad..5ef7c18e0c5 100644
--- a/drivers/media/video/tea6420.h
+++ b/drivers/media/video/tea6420.h
@@ -2,8 +2,8 @@
#define __INCLUDED_TEA6420__
/* possible addresses */
-#define I2C_TEA6420_1 0x4c
-#define I2C_TEA6420_2 0x4d
+#define I2C_ADDR_TEA6420_1 0x4c
+#define I2C_ADDR_TEA6420_2 0x4d
struct tea6420_multiplex
{
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
index c4a78e7a5a5..74ab48c09c6 100644
--- a/drivers/media/video/tuner-3036.c
+++ b/drivers/media/video/tuner-3036.c
@@ -5,7 +5,7 @@
*
* The SAB3036 is just about different enough from the chips that
* tuner.c copes with to make it not worth the effort to crowbar
- * the support into that file. So instead we have a separate driver.
+ * the support into that file. So instead we have a separate driver.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -56,15 +56,15 @@ tuner_getstatus (struct i2c_client *c)
#define TUNER_FL 0x80
-static int
+static int
tuner_islocked (struct i2c_client *c)
{
- return (tuner_getstatus(c) & TUNER_FL);
+ return (tuner_getstatus(c) & TUNER_FL);
}
/* ---------------------------------------------------------------------- */
-static void
+static void
set_tv_freq(struct i2c_client *c, int freq)
{
u16 div = ((freq * 20) / 16);
@@ -73,26 +73,26 @@ set_tv_freq(struct i2c_client *c, int freq)
if (debug)
printk(KERN_DEBUG "tuner: setting frequency %dMHz, divisor %x\n", freq / 16, div);
-
+
/* Select high tuning current */
buffer[0] = 0x29;
buffer[1] = 0x3e;
if (i2c_master_send(c, buffer, 2) != 2)
printk("tuner: i2c i/o error 1\n");
-
+
buffer[0] = 0x80 | ((div>>8) & 0x7f);
buffer[1] = div & 0xff;
if (i2c_master_send(c, buffer, 2) != 2)
printk("tuner: i2c i/o error 2\n");
-
+
while (!tuner_islocked(c) && time_before(jiffies, give_up))
schedule();
-
+
if (!tuner_islocked(c))
printk(KERN_WARNING "tuner: failed to achieve PLL lock\n");
-
+
/* Select low tuning current and engage AFC */
buffer[0] = 0x29;
buffer[1] = 0xb2;
@@ -106,7 +106,7 @@ set_tv_freq(struct i2c_client *c, int freq)
/* ---------------------------------------------------------------------- */
-static int
+static int
tuner_attach(struct i2c_adapter *adap, int addr, int kind)
{
static unsigned char buffer[] = { 0x29, 0x32, 0x2a, 0, 0x2b, 0 };
@@ -116,18 +116,18 @@ tuner_attach(struct i2c_adapter *adap, int addr, int kind)
if (this_adap > 0)
return -1;
this_adap++;
-
- client_template.adapter = adap;
- client_template.addr = addr;
+
+ client_template.adapter = adap;
+ client_template.addr = addr;
client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == NULL)
- return -ENOMEM;
- memcpy(client, &client_template, sizeof(struct i2c_client));
+ if (client == NULL)
+ return -ENOMEM;
+ memcpy(client, &client_template, sizeof(struct i2c_client));
printk("tuner: SAB3036 found, status %02x\n", tuner_getstatus(client));
- i2c_attach_client(client);
+ i2c_attach_client(client);
if (i2c_master_send(client, buffer, 2) != 2)
printk("tuner: i2c i/o error 1\n");
@@ -138,30 +138,30 @@ tuner_attach(struct i2c_adapter *adap, int addr, int kind)
return 0;
}
-static int
+static int
tuner_detach(struct i2c_client *c)
{
return 0;
}
-static int
+static int
tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
int *iarg = (int*)arg;
- switch (cmd)
+ switch (cmd)
{
case VIDIOCSFREQ:
set_tv_freq(client, *iarg);
break;
-
+
default:
return -EINVAL;
}
return 0;
}
-static int
+static int
tuner_probe(struct i2c_adapter *adap)
{
this_adap = 0;
@@ -172,8 +172,8 @@ tuner_probe(struct i2c_adapter *adap)
/* ----------------------------------------------------------------------- */
-static struct i2c_driver
-i2c_driver_tuner =
+static struct i2c_driver
+i2c_driver_tuner =
{
.driver = {
.name = "sab3036",
@@ -186,7 +186,7 @@ i2c_driver_tuner =
static struct i2c_client client_template =
{
- .driver = &i2c_driver_tuner,
+ .driver = &i2c_driver_tuner,
.name = "SAB3036",
};
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 32e1849441f..df195c90536 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -21,7 +21,6 @@
#include <media/tuner.h>
#include <media/v4l2-common.h>
-#include <media/audiochip.h>
#define UNSET (-1U)
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 4efb01bb44a..356bff455ad 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -30,10 +30,10 @@
#include <linux/init.h>
#include <linux/smp_lock.h>
-#include <media/audiochip.h>
+#include <media/tvaudio.h>
#include <media/v4l2-common.h>
-#include "tvaudio.h"
+#include <media/i2c-addr.h>
/* ---------------------------------------------------------------------- */
/* insmod args */
@@ -102,7 +102,7 @@ struct CHIPDESC {
/* input switch register + values for v4l inputs */
int inputreg;
- int inputmap[8];
+ int inputmap[4];
int inputmute;
int inputmask;
};
@@ -119,9 +119,10 @@ struct CHIPSTATE {
audiocmd shadow;
/* current settings */
- __u16 left,right,treble,bass,mode;
+ __u16 left,right,treble,bass,muted,mode;
int prevmode;
int radio;
+ int input;
/* thread */
pid_t tpid;
@@ -137,14 +138,14 @@ struct CHIPSTATE {
/* i2c addresses */
static unsigned short normal_i2c[] = {
- I2C_TDA8425 >> 1,
- I2C_TEA6300 >> 1,
- I2C_TEA6420 >> 1,
- I2C_TDA9840 >> 1,
- I2C_TDA985x_L >> 1,
- I2C_TDA985x_H >> 1,
- I2C_TDA9874 >> 1,
- I2C_PIC16C54 >> 1,
+ I2C_ADDR_TDA8425 >> 1,
+ I2C_ADDR_TEA6300 >> 1,
+ I2C_ADDR_TEA6420 >> 1,
+ I2C_ADDR_TDA9840 >> 1,
+ I2C_ADDR_TDA985x_L >> 1,
+ I2C_ADDR_TDA985x_H >> 1,
+ I2C_ADDR_TDA9874 >> 1,
+ I2C_ADDR_PIC16C54 >> 1,
I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
@@ -1101,9 +1102,8 @@ static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; }
static int tda8425_initialize(struct CHIPSTATE *chip)
{
struct CHIPDESC *desc = chiplist + chip->type;
- int inputmap[8] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1,
- /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF,
- /* off */ TDA8425_S1_OFF, /* on */ TDA8425_S1_CH2};
+ int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1,
+ /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF};
if (chip->c.adapter->id == I2C_HW_B_RIVA) {
memcpy (desc->inputmap, inputmap, sizeof (inputmap));
@@ -1269,8 +1269,8 @@ static struct CHIPDESC chiplist[] = {
.name = "tda9840",
.id = I2C_DRIVERID_TDA9840,
.insmodopt = &tda9840,
- .addr_lo = I2C_TDA9840 >> 1,
- .addr_hi = I2C_TDA9840 >> 1,
+ .addr_lo = I2C_ADDR_TDA9840 >> 1,
+ .addr_hi = I2C_ADDR_TDA9840 >> 1,
.registers = 5,
.checkit = tda9840_checkit,
@@ -1286,8 +1286,8 @@ static struct CHIPDESC chiplist[] = {
.id = I2C_DRIVERID_TDA9873,
.checkit = tda9873_checkit,
.insmodopt = &tda9873,
- .addr_lo = I2C_TDA985x_L >> 1,
- .addr_hi = I2C_TDA985x_H >> 1,
+ .addr_lo = I2C_ADDR_TDA985x_L >> 1,
+ .addr_hi = I2C_ADDR_TDA985x_H >> 1,
.registers = 3,
.flags = CHIP_HAS_INPUTSEL,
@@ -1298,7 +1298,7 @@ static struct CHIPDESC chiplist[] = {
.init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } },
.inputreg = TDA9873_SW,
.inputmute = TDA9873_MUTE | TDA9873_AUTOMUTE,
- .inputmap = {0xa0, 0xa2, 0xa0, 0xa0, 0xc0},
+ .inputmap = {0xa0, 0xa2, 0xa0, 0xa0},
.inputmask = TDA9873_INP_MASK|TDA9873_MUTE|TDA9873_AUTOMUTE,
},
@@ -1308,8 +1308,8 @@ static struct CHIPDESC chiplist[] = {
.checkit = tda9874a_checkit,
.initialize = tda9874a_initialize,
.insmodopt = &tda9874a,
- .addr_lo = I2C_TDA9874 >> 1,
- .addr_hi = I2C_TDA9874 >> 1,
+ .addr_lo = I2C_ADDR_TDA9874 >> 1,
+ .addr_hi = I2C_ADDR_TDA9874 >> 1,
.getmode = tda9874a_getmode,
.setmode = tda9874a_setmode,
@@ -1319,8 +1319,8 @@ static struct CHIPDESC chiplist[] = {
.name = "tda9850",
.id = I2C_DRIVERID_TDA9850,
.insmodopt = &tda9850,
- .addr_lo = I2C_TDA985x_L >> 1,
- .addr_hi = I2C_TDA985x_H >> 1,
+ .addr_lo = I2C_ADDR_TDA985x_L >> 1,
+ .addr_hi = I2C_ADDR_TDA985x_H >> 1,
.registers = 11,
.getmode = tda985x_getmode,
@@ -1332,8 +1332,8 @@ static struct CHIPDESC chiplist[] = {
.name = "tda9855",
.id = I2C_DRIVERID_TDA9855,
.insmodopt = &tda9855,
- .addr_lo = I2C_TDA985x_L >> 1,
- .addr_hi = I2C_TDA985x_H >> 1,
+ .addr_lo = I2C_ADDR_TDA985x_L >> 1,
+ .addr_hi = I2C_ADDR_TDA985x_H >> 1,
.registers = 11,
.flags = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE,
@@ -1357,8 +1357,8 @@ static struct CHIPDESC chiplist[] = {
.name = "tea6300",
.id = I2C_DRIVERID_TEA6300,
.insmodopt = &tea6300,
- .addr_lo = I2C_TEA6300 >> 1,
- .addr_hi = I2C_TEA6300 >> 1,
+ .addr_lo = I2C_ADDR_TEA6300 >> 1,
+ .addr_hi = I2C_ADDR_TEA6300 >> 1,
.registers = 6,
.flags = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL,
@@ -1379,8 +1379,8 @@ static struct CHIPDESC chiplist[] = {
.id = I2C_DRIVERID_TEA6300,
.initialize = tea6320_initialize,
.insmodopt = &tea6320,
- .addr_lo = I2C_TEA6300 >> 1,
- .addr_hi = I2C_TEA6300 >> 1,
+ .addr_lo = I2C_ADDR_TEA6300 >> 1,
+ .addr_hi = I2C_ADDR_TEA6300 >> 1,
.registers = 8,
.flags = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL,
@@ -1400,8 +1400,8 @@ static struct CHIPDESC chiplist[] = {
.name = "tea6420",
.id = I2C_DRIVERID_TEA6420,
.insmodopt = &tea6420,
- .addr_lo = I2C_TEA6420 >> 1,
- .addr_hi = I2C_TEA6420 >> 1,
+ .addr_lo = I2C_ADDR_TEA6420 >> 1,
+ .addr_hi = I2C_ADDR_TEA6420 >> 1,
.registers = 1,
.flags = CHIP_HAS_INPUTSEL,
@@ -1413,8 +1413,8 @@ static struct CHIPDESC chiplist[] = {
.name = "tda8425",
.id = I2C_DRIVERID_TDA8425,
.insmodopt = &tda8425,
- .addr_lo = I2C_TDA8425 >> 1,
- .addr_hi = I2C_TDA8425 >> 1,
+ .addr_lo = I2C_ADDR_TDA8425 >> 1,
+ .addr_hi = I2C_ADDR_TDA8425 >> 1,
.registers = 9,
.flags = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL,
@@ -1437,8 +1437,8 @@ static struct CHIPDESC chiplist[] = {
.name = "pic16c54 (PV951)",
.id = I2C_DRIVERID_PIC16C54_PV9,
.insmodopt = &pic16c54,
- .addr_lo = I2C_PIC16C54 >> 1,
- .addr_hi = I2C_PIC16C54>> 1,
+ .addr_lo = I2C_ADDR_PIC16C54 >> 1,
+ .addr_hi = I2C_ADDR_PIC16C54>> 1,
.registers = 2,
.flags = CHIP_HAS_INPUTSEL,
@@ -1446,8 +1446,7 @@ static struct CHIPDESC chiplist[] = {
.inputmap = {PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_TUNER,
PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,
PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,
- PIC16C54_MISC_SND_MUTE,PIC16C54_MISC_SND_MUTE,
- PIC16C54_MISC_SND_NOTMUTE},
+ PIC16C54_MISC_SND_MUTE},
.inputmute = PIC16C54_MISC_SND_MUTE,
},
{
@@ -1456,8 +1455,8 @@ static struct CHIPDESC chiplist[] = {
/*.id = I2C_DRIVERID_TA8874Z, */
.checkit = ta8874z_checkit,
.insmodopt = &ta8874z,
- .addr_lo = I2C_TDA9840 >> 1,
- .addr_hi = I2C_TDA9840 >> 1,
+ .addr_lo = I2C_ADDR_TDA9840 >> 1,
+ .addr_hi = I2C_ADDR_TDA9840 >> 1,
.registers = 2,
.getmode = ta8874z_getmode,
@@ -1583,28 +1582,40 @@ static int chip_detach(struct i2c_client *client)
return 0;
}
+static int tvaudio_set_ctrl(struct CHIPSTATE *chip, struct v4l2_control *ctrl)
+{
+ struct CHIPDESC *desc = chiplist + chip->type;
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ if (ctrl->value < 0 || ctrl->value >= 2)
+ return -ERANGE;
+ chip->muted = ctrl->value;
+ if (chip->muted)
+ chip_write_masked(chip,desc->inputreg,desc->inputmute,desc->inputmask);
+ else
+ chip_write_masked(chip,desc->inputreg,
+ desc->inputmap[chip->input],desc->inputmask);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
/* ---------------------------------------------------------------------- */
/* video4linux interface */
static int chip_command(struct i2c_client *client,
unsigned int cmd, void *arg)
{
- __u16 *sarg = arg;
struct CHIPSTATE *chip = i2c_get_clientdata(client);
struct CHIPDESC *desc = chiplist + chip->type;
v4l_dbg(1, debug, &chip->c, "%s: chip_command 0x%x\n", chip->c.name, cmd);
switch (cmd) {
- case AUDC_SET_INPUT:
- if (desc->flags & CHIP_HAS_INPUTSEL) {
- if (*sarg & 0x80)
- chip_write_masked(chip,desc->inputreg,desc->inputmute,desc->inputmask);
- else
- chip_write_masked(chip,desc->inputreg,desc->inputmap[*sarg],desc->inputmask);
- }
- break;
-
case AUDC_SET_RADIO:
chip->radio = 1;
chip->watch_stereo = 0;
@@ -1668,6 +1679,48 @@ static int chip_command(struct i2c_client *client,
break;
}
+ case VIDIOC_S_CTRL:
+ return tvaudio_set_ctrl(chip, arg);
+
+ case VIDIOC_INT_G_AUDIO_ROUTING:
+ {
+ struct v4l2_routing *rt = arg;
+
+ rt->input = chip->input;
+ rt->output = 0;
+ break;
+ }
+
+ case VIDIOC_INT_S_AUDIO_ROUTING:
+ {
+ struct v4l2_routing *rt = arg;
+
+ if (!(desc->flags & CHIP_HAS_INPUTSEL) || rt->input >= 4)
+ return -EINVAL;
+ /* There are four inputs: tuner, radio, extern and intern. */
+ chip->input = rt->input;
+ if (chip->muted)
+ break;
+ chip_write_masked(chip, desc->inputreg,
+ desc->inputmap[chip->input], desc->inputmask);
+ break;
+ }
+
+ case VIDIOC_S_AUDIO:
+ {
+ struct v4l2_audio *sarg = arg;
+
+ if (!(desc->flags & CHIP_HAS_INPUTSEL) || sarg->index >= 4)
+ return -EINVAL;
+ /* There are four inputs: tuner, radio, extern and intern. */
+ chip->input = sarg->index;
+ if (chip->muted)
+ break;
+ chip_write_masked(chip, desc->inputreg,
+ desc->inputmap[chip->input], desc->inputmask);
+ break;
+ }
+
case VIDIOC_S_TUNER:
{
struct v4l2_tuner *vt = arg;
@@ -1680,6 +1733,7 @@ static int chip_command(struct i2c_client *client,
mode = VIDEO_SOUND_MONO;
break;
case V4L2_TUNER_MODE_STEREO:
+ case V4L2_TUNER_MODE_LANG1_LANG2:
mode = VIDEO_SOUND_STEREO;
break;
case V4L2_TUNER_MODE_LANG1:
diff --git a/drivers/media/video/tvaudio.h b/drivers/media/video/tvaudio.h
deleted file mode 100644
index af7e116af9a..00000000000
--- a/drivers/media/video/tvaudio.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * i2c bus addresses for the chips supported by tvaudio.c
- */
-
-#define I2C_TDA8425 0x82
-#define I2C_TDA9840 0x84 /* also used by TA8874Z */
-#define I2C_TDA985x_L 0xb4 /* also used by 9873 */
-#define I2C_TDA985x_H 0xb6
-#define I2C_TDA9874 0xb0 /* also used by 9875 */
-
-#define I2C_TEA6300 0x80 /* also used by 6320 */
-#define I2C_TEA6420 0x98
-
-#define I2C_PIC16C54 0x96 /* PV951 */
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 582551b0969..e0d2ff83fc9 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -248,32 +248,32 @@ audioIC[] =
{AUDIO_CHIP_MSP34XX, "MSP3410D"},
{AUDIO_CHIP_MSP34XX, "MSP3415"},
{AUDIO_CHIP_MSP34XX, "MSP3430"},
- {AUDIO_CHIP_UNKNOWN, "MSP3438"},
+ {AUDIO_CHIP_MSP34XX, "MSP3438"},
{AUDIO_CHIP_UNKNOWN, "CS5331"},
/* 10-14 */
{AUDIO_CHIP_MSP34XX, "MSP3435"},
{AUDIO_CHIP_MSP34XX, "MSP3440"},
{AUDIO_CHIP_MSP34XX, "MSP3445"},
- {AUDIO_CHIP_UNKNOWN, "MSP3411"},
- {AUDIO_CHIP_UNKNOWN, "MSP3416"},
+ {AUDIO_CHIP_MSP34XX, "MSP3411"},
+ {AUDIO_CHIP_MSP34XX, "MSP3416"},
/* 15-19 */
{AUDIO_CHIP_MSP34XX, "MSP3425"},
- {AUDIO_CHIP_UNKNOWN, "MSP3451"},
- {AUDIO_CHIP_UNKNOWN, "MSP3418"},
+ {AUDIO_CHIP_MSP34XX, "MSP3451"},
+ {AUDIO_CHIP_MSP34XX, "MSP3418"},
{AUDIO_CHIP_UNKNOWN, "Type 0x12"},
{AUDIO_CHIP_UNKNOWN, "OKI7716"},
/* 20-24 */
- {AUDIO_CHIP_UNKNOWN, "MSP4410"},
- {AUDIO_CHIP_UNKNOWN, "MSP4420"},
- {AUDIO_CHIP_UNKNOWN, "MSP4440"},
- {AUDIO_CHIP_UNKNOWN, "MSP4450"},
- {AUDIO_CHIP_UNKNOWN, "MSP4408"},
+ {AUDIO_CHIP_MSP34XX, "MSP4410"},
+ {AUDIO_CHIP_MSP34XX, "MSP4420"},
+ {AUDIO_CHIP_MSP34XX, "MSP4440"},
+ {AUDIO_CHIP_MSP34XX, "MSP4450"},
+ {AUDIO_CHIP_MSP34XX, "MSP4408"},
/* 25-29 */
- {AUDIO_CHIP_UNKNOWN, "MSP4418"},
- {AUDIO_CHIP_UNKNOWN, "MSP4428"},
- {AUDIO_CHIP_UNKNOWN, "MSP4448"},
- {AUDIO_CHIP_UNKNOWN, "MSP4458"},
- {AUDIO_CHIP_UNKNOWN, "Type 0x1d"},
+ {AUDIO_CHIP_MSP34XX, "MSP4418"},
+ {AUDIO_CHIP_MSP34XX, "MSP4428"},
+ {AUDIO_CHIP_MSP34XX, "MSP4448"},
+ {AUDIO_CHIP_MSP34XX, "MSP4458"},
+ {AUDIO_CHIP_MSP34XX, "Type 0x1d"},
/* 30-34 */
{AUDIO_CHIP_INTERNAL, "CX880"},
{AUDIO_CHIP_INTERNAL, "CX881"},
diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile
new file mode 100644
index 00000000000..ed410a5ee8c
--- /dev/null
+++ b/drivers/media/video/usbvideo/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o
+obj-$(CONFIG_USB_KONICAWC) += konicawc.o usbvideo.o
+obj-$(CONFIG_USB_VICAM) += vicam.o usbvideo.o
+
diff --git a/drivers/usb/media/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c
index a42c2229412..76f771b6a32 100644
--- a/drivers/usb/media/ibmcam.c
+++ b/drivers/media/video/usbvideo/ibmcam.c
@@ -1300,11 +1300,11 @@ static void ibmcam_model2_Packet1(struct uvd *uvd, unsigned short v1, unsigned s
/*
* ibmcam_model3_Packet1()
*
- * 00_0078_012d
+ * 00_0078_012d
* 00_0097_012f
- * 00_d141_0124
+ * 00_d141_0124
* 00_0096_0127
- * 00_fea8_0124
+ * 00_fea8_0124
*/
static void ibmcam_model3_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2)
{
@@ -2687,7 +2687,7 @@ static void ibmcam_model4_setup_after_video_if(struct uvd *uvd)
ibmcam_veio(uvd, 0, 0x0004, 0x0127);
ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
- break;
+ break;
}
usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
}
@@ -3238,7 +3238,7 @@ static void ibmcam_model3_setup_after_video_if(struct uvd *uvd)
{0, 0x0062, 0x0107},
{0, 0x0003, 0x0111},
};
-#define NUM_INIT_DATA
+#define NUM_INIT_DATA
unsigned short compression = 0; /* 0=none, 7=best frame rate */
int f_rate; /* 0=Fastest 7=slowest */
diff --git a/drivers/usb/media/konicawc.c b/drivers/media/video/usbvideo/konicawc.c
index e2ede583518..c11f5d46b11 100644
--- a/drivers/usb/media/konicawc.c
+++ b/drivers/media/video/usbvideo/konicawc.c
@@ -36,7 +36,7 @@
enum ctrl_req {
SetWhitebal = 0x01,
SetBrightness = 0x02,
- SetSharpness = 0x03,
+ SetSharpness = 0x03,
SetContrast = 0x04,
SetSaturation = 0x05,
};
@@ -47,7 +47,7 @@ enum frame_sizes {
SIZE_160X136 = 1,
SIZE_176X144 = 2,
SIZE_320X240 = 3,
-
+
};
#define MAX_FRAME_SIZE SIZE_320X240
@@ -69,7 +69,7 @@ static const int debug = 0;
/* Some default values for initial camera settings,
can be set by modprobe */
-static int size;
+static int size;
static int speed = 6; /* Speed (fps) 0 (slowest) to 6 (fastest) */
static int brightness = MAX_BRIGHTNESS/2;
static int contrast = MAX_CONTRAST/2;
@@ -132,24 +132,24 @@ struct konicawc {
static int konicawc_ctrl_msg(struct uvd *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len)
{
- int retval = usb_control_msg(uvd->dev,
+ int retval = usb_control_msg(uvd->dev,
dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0),
request, 0x40 | dir, value, index, buf, len, 1000);
- return retval < 0 ? retval : 0;
+ return retval < 0 ? retval : 0;
}
static inline void konicawc_camera_on(struct uvd *uvd)
{
- DEBUG(0, "camera on");
- konicawc_set_misc(uvd, 0x2, 1, 0x0b);
+ DEBUG(0, "camera on");
+ konicawc_set_misc(uvd, 0x2, 1, 0x0b);
}
static inline void konicawc_camera_off(struct uvd *uvd)
{
- DEBUG(0, "camera off");
- konicawc_set_misc(uvd, 0x2, 0, 0x0b);
+ DEBUG(0, "camera off");
+ konicawc_set_misc(uvd, 0x2, 0, 0x0b);
}
@@ -317,7 +317,7 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur
button = !!(sts & 0x40);
sts &= ~0x40;
}
-
+
/* work out the button status, but don't do
anything with it for now */
@@ -331,7 +331,7 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur
discard++;
continue;
}
-
+
if((sts > 0x01) && (sts < 0x80)) {
info("unknown status %2.2x", sts);
bad++;
@@ -350,7 +350,7 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur
DEBUG(2, "found initial image");
cam->lastframe = -1;
}
-
+
marker[3] = sts & 0x7F;
RingQueue_Enqueue(&uvd->dp, marker, 4);
totlen += 4;
@@ -367,16 +367,16 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur
static void resubmit_urb(struct uvd *uvd, struct urb *urb)
{
- int i, ret;
- for (i = 0; i < FRAMES_PER_DESC; i++) {
- urb->iso_frame_desc[i].status = 0;
- }
- urb->dev = uvd->dev;
- urb->status = 0;
+ int i, ret;
+ for (i = 0; i < FRAMES_PER_DESC; i++) {
+ urb->iso_frame_desc[i].status = 0;
+ }
+ urb->dev = uvd->dev;
+ urb->status = 0;
ret = usb_submit_urb(urb, GFP_ATOMIC);
DEBUG(3, "submitting urb of length %d", urb->transfer_buffer_length);
- if(ret)
- err("usb_submit_urb error (%d)", ret);
+ if(ret)
+ err("usb_submit_urb error (%d)", ret);
}
@@ -490,7 +490,7 @@ static int konicawc_start_data(struct uvd *uvd)
}
cam->last_data_urb = NULL;
-
+
/* Submit all URBs */
for (i=0; i < USBVIDEO_NUMSBUF; i++) {
errFlag = usb_submit_urb(cam->sts_urb[i], GFP_KERNEL);
@@ -539,7 +539,7 @@ static void konicawc_stop_data(struct uvd *uvd)
static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame)
-{
+{
struct konicawc *cam = (struct konicawc *)uvd->user_data;
int maxline = cam->maxline;
int yplanesz = cam->yplanesz;
@@ -583,13 +583,13 @@ static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame)
if(frame->scanstate == ScanState_Scanning)
return;
-
+
/* Try to move data from queue into frame buffer
* We get data in blocks of 384 bytes made up of:
* 256 Y, 64 U, 64 V.
* This needs to be written out as a Y plane, a U plane and a V plane.
*/
-
+
while ( frame->curline < maxline && (RingQueue_GetLength(&uvd->dp) >= 384)) {
/* Y */
RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256);
diff --git a/drivers/usb/media/ultracam.c b/drivers/media/video/usbvideo/ultracam.c
index 75ff755224d..10c58b4a2e5 100644
--- a/drivers/usb/media/ultracam.c
+++ b/drivers/media/video/usbvideo/ultracam.c
@@ -23,7 +23,7 @@
typedef struct {
int initialized; /* Had we already sent init sequence? */
int camera_model; /* What type of IBM camera we got? */
- int has_hdr;
+ int has_hdr;
} ultracam_t;
#define ULTRACAM_T(uvd) ((ultracam_t *)((uvd)->user_data))
diff --git a/drivers/usb/media/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
index 0b51fae720a..13b37c8c0d5 100644
--- a/drivers/usb/media/usbvideo.c
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -574,7 +574,7 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode)
} else {
/* Just the blue screen */
}
-
+
*f++ = cb;
*f++ = cg;
*f++ = cr;
@@ -1243,7 +1243,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
#if USBVIDEO_REPORT_STATS
usbvideo_ReportStatistics(uvd);
-#endif
+#endif
uvd->user--;
if (uvd->remove_pending) {
@@ -1290,7 +1290,7 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
return 0;
}
case VIDIOCSCHAN:
- {
+ {
struct video_channel *v = arg;
if (v->channel != 0)
return -EINVAL;
@@ -1347,7 +1347,7 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
vw->chromakey = 0;
if (VALID_CALLBACK(uvd, getFPS))
vw->flags = GET_CALLBACK(uvd, getFPS)(uvd);
- else
+ else
vw->flags = 10; /* FIXME: do better! */
return 0;
}
@@ -1359,7 +1359,7 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
memset(vm, 0, sizeof(*vm));
vm->size = uvd->max_frame_size * USBVIDEO_NUMFRAMES;
vm->frames = USBVIDEO_NUMFRAMES;
- for(i = 0; i < USBVIDEO_NUMFRAMES; i++)
+ for(i = 0; i < USBVIDEO_NUMFRAMES; i++)
vm->offsets[i] = i * uvd->max_frame_size;
return 0;
@@ -1425,7 +1425,7 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
if (*frameNum < 0 || *frameNum >= USBVIDEO_NUMFRAMES)
return -EINVAL;
-
+
if (uvd->debug >= 1)
info("VIDIOCSYNC: syncing to frame %d.", *frameNum);
if (uvd->flags & FLAGS_NO_DECODING)
@@ -1454,8 +1454,8 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
struct video_buffer *vb = arg;
memset(vb, 0, sizeof(*vb));
- return 0;
- }
+ return 0;
+ }
case VIDIOCKEY:
return 0;
@@ -1704,7 +1704,7 @@ static void usbvideo_IsocIrq(struct urb *urb, struct pt_regs *regs)
info("Not streaming, but interrupt!");
return;
}
-
+
uvd->stats.urb_count++;
if (urb->actual_length <= 0)
goto urb_done_with;
@@ -1763,7 +1763,7 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
}
if (VALID_CALLBACK(uvd, videoStart))
GET_CALLBACK(uvd, videoStart)(uvd);
- else
+ else
err("%s: videoStart not set", __FUNCTION__);
/* We double buffer the Iso lists */
@@ -1830,7 +1830,7 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
/* Invoke minidriver's magic to stop the camera */
if (VALID_CALLBACK(uvd, videoStop))
GET_CALLBACK(uvd, videoStop)(uvd);
- else
+ else
err("%s: videoStop not set", __FUNCTION__);
/* Set packet size to 0 */
@@ -1963,14 +1963,14 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
info("%s($%p,%d.)", __FUNCTION__, uvd, frameNum);
switch (frame->frameState) {
- case FrameState_Unused:
+ case FrameState_Unused:
if (uvd->debug >= 2)
info("%s: FrameState_Unused", __FUNCTION__);
return -EINVAL;
- case FrameState_Ready:
- case FrameState_Grabbing:
- case FrameState_Error:
- {
+ case FrameState_Ready:
+ case FrameState_Grabbing:
+ case FrameState_Error:
+ {
int ntries, signalPending;
redo:
if (!CAMERA_IS_OPERATIONAL(uvd)) {
@@ -1978,7 +1978,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
info("%s: Camera is not operational (1)", __FUNCTION__);
return -EIO;
}
- ntries = 0;
+ ntries = 0;
do {
RingQueue_InterruptibleSleepOn(&uvd->dp);
signalPending = signal_pending(current);
@@ -2010,7 +2010,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
usbvideo_CollectRawData(uvd, frame);
else if (VALID_CALLBACK(uvd, processData))
GET_CALLBACK(uvd, processData)(uvd, frame);
- else
+ else
err("%s: processData not set", __FUNCTION__);
}
} while (frame->frameState == FrameState_Grabbing);
@@ -2027,8 +2027,8 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
goto redo;
}
/* Note that we fall through to meet our destiny below */
- }
- case FrameState_Done:
+ }
+ case FrameState_Done:
/*
* Do all necessary postprocessing of data prepared in
* "interrupt" code and the collecting code above. The
@@ -2157,7 +2157,7 @@ EXPORT_SYMBOL(usbvideo_DeinterlaceFrame);
* History:
* 09-Feb-2001 Created.
*/
-static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
+static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
struct usbvideo_frame *frame)
{
int i, j, v4l_linesize;
diff --git a/drivers/usb/media/usbvideo.h b/drivers/media/video/usbvideo/usbvideo.h
index 135433c2680..3cbf4fc499a 100644
--- a/drivers/usb/media/usbvideo.h
+++ b/drivers/media/video/usbvideo/usbvideo.h
@@ -189,11 +189,11 @@ struct usbvideo_frame {
/* Statistics that can be overlaid on screen */
struct usbvideo_statistics {
- unsigned long frame_num; /* Sequential number of the frame */
- unsigned long urb_count; /* How many URBs we received so far */
- unsigned long urb_length; /* Length of last URB */
- unsigned long data_count; /* How many bytes we received */
- unsigned long header_count; /* How many frame headers we found */
+ unsigned long frame_num; /* Sequential number of the frame */
+ unsigned long urb_count; /* How many URBs we received so far */
+ unsigned long urb_length; /* Length of last URB */
+ unsigned long data_count; /* How many bytes we received */
+ unsigned long header_count; /* How many frame headers we found */
unsigned long iso_skip_count; /* How many empty ISO packets received */
unsigned long iso_err_count; /* How many bad ISO packets received */
};
diff --git a/drivers/usb/media/vicam.c b/drivers/media/video/usbvideo/vicam.c
index 1d06e53ec7c..90d48e8510b 100644
--- a/drivers/usb/media/vicam.c
+++ b/drivers/media/video/usbvideo/vicam.c
@@ -69,10 +69,10 @@
#define VICAM_HEADER_SIZE 64
#define clamp( x, l, h ) max_t( __typeof__( x ), \
- ( l ), \
- min_t( __typeof__( x ), \
- ( h ), \
- ( x ) ) )
+ ( l ), \
+ min_t( __typeof__( x ), \
+ ( h ), \
+ ( x ) ) )
/* Not sure what all the bytes in these char
* arrays do, but they're necessary to make
@@ -357,7 +357,7 @@ static unsigned char setup5[] = {
* Not sure why these are not yet non-statics which I can reference through
* usbvideo.h the same as it is in 2.4.20. I bet this will get fixed sometime
* in the future.
- *
+ *
*/
static void *rvmalloc(unsigned long size)
{
@@ -603,12 +603,12 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign
case VIDIOCSPICT:
{
struct video_picture vp;
-
+
if (copy_from_user(&vp, user_arg, sizeof(vp))) {
retval = -EFAULT;
break;
}
-
+
DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth,
vp.palette);
@@ -655,7 +655,7 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign
}
DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height);
-
+
if ( vw.width != 320 || vw.height != 240 )
retval = -EFAULT;
@@ -809,12 +809,12 @@ vicam_open(struct inode *inode, struct file *file)
cam->needsDummyRead = 1;
cam->open_count++;
- file->private_data = cam;
-
+ file->private_data = cam;
+
return 0;
}
-static int
+static int
vicam_close(struct inode *inode, struct file *file)
{
struct vicam_camera *cam = file->private_data;
@@ -1187,7 +1187,7 @@ vicam_create_proc_entry(struct vicam_camera *cam)
if ( !cam->proc_dir )
return; // FIXME: We should probably return an error here
-
+
ent = create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR,
cam->proc_dir);
if (ent) {
@@ -1282,7 +1282,7 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
const struct usb_host_interface *interface;
const struct usb_endpoint_descriptor *endpoint;
struct vicam_camera *cam;
-
+
printk(KERN_INFO "ViCam based webcam connected\n");
interface = intf->cur_altsetting;
@@ -1331,7 +1331,7 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
usb_set_intfdata (intf, cam);
-
+
return 0;
}
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 95a6e47c99f..11a97f30b87 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -312,8 +312,6 @@ static const char *v4l2_int_ioctls[] = {
[_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP",
#endif
[_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO",
- [_IOC_NR(AUDC_SET_INPUT)] = "AUDC_SET_INPUT",
- [_IOC_NR(MSP_SET_MATRIX)] = "MSP_SET_MATRIX",
[_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR",
[_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY",
@@ -419,7 +417,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
case TUNER_SET_TYPE_ADDR:
case TUNER_SET_STANDBY:
case TDA9887_SET_CONFIG:
- case AUDC_SET_INPUT:
case VIDIOC_OVERLAY_OLD:
case VIDIOC_STREAMOFF:
case VIDIOC_G_OUTPUT:
@@ -433,12 +430,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
printk ("%s: value=%d\n", s, *p);
break;
}
- case MSP_SET_MATRIX:
- {
- struct msp_matrix *p=arg;
- printk ("%s: input=%d, output=%d\n", s, p->input, p->output);
- break;
- }
case VIDIOC_G_AUDIO:
case VIDIOC_S_AUDIO:
case VIDIOC_ENUMAUDIO:
@@ -467,7 +458,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
struct v4l2_buffer *p=arg;
struct v4l2_timecode *tc=&p->timecode;
printk ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%s, "
- "bytesused=%d, flags=0x%08d, "
+ "bytesused=%d, flags=0x%08x, "
"field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n",
s,
(p->timestamp.tv_sec/3600),
@@ -481,16 +472,16 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
prt_names(p->memory,v4l2_memory_names),
p->m.userptr);
printk ("%s: timecode= %02d:%02d:%02d type=%d, "
- "flags=0x%08d, frames=%d, userbits=0x%08x",
+ "flags=0x%08x, frames=%d, userbits=0x%p\n",
s,tc->hours,tc->minutes,tc->seconds,
- tc->type, tc->flags, tc->frames, (__u32) tc->userbits);
+ tc->type, tc->flags, tc->frames, tc->userbits);
break;
}
case VIDIOC_QUERYCAP:
{
struct v4l2_capability *p=arg;
- printk ("%s: driver=%s, card=%s, bus=%s, version=%d, "
- "capabilities=%d\n", s,
+ printk ("%s: driver=%s, card=%s, bus=%s, version=0x%08x, "
+ "capabilities=0x%08x\n", s,
p->driver,p->card,p->bus_info,
p->version,
p->capabilities);
@@ -574,9 +565,10 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
{
struct v4l2_input *p=arg;
printk ("%s: index=%d, name=%s, type=%d, audioset=%d, "
- "tuner=%d, std=%lld, status=%d\n", s,
+ "tuner=%d, std=%Ld, status=%d\n", s,
p->index,p->name,p->type,p->audioset,
- p->tuner,p->std,
+ p->tuner,
+ (unsigned long long)p->std,
p->status);
break;
}
@@ -620,9 +612,10 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
{
struct v4l2_output *p=arg;
printk ("%s: index=%d, name=%s,type=%d, audioset=%d, "
- "modulator=%d, std=%lld\n",
+ "modulator=%d, std=%Ld\n",
s,p->index,p->name,p->type,p->audioset,
- p->modulator,p->std);
+ p->modulator,
+ (unsigned long long)p->std);
break;
}
case VIDIOC_QUERYCTRL:
@@ -665,7 +658,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
case VIDIOC_INT_G_VIDEO_ROUTING:
{
struct v4l2_routing *p=arg;
- printk ("%s: input=%d, output=%d\n", s, p->input, p->output);
+ printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output);
break;
}
case VIDIOC_G_SLICED_VBI_CAP:
@@ -686,8 +679,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
case VIDIOC_ENUMSTD:
{
struct v4l2_standard *p=arg;
- printk ("%s: index=%d, id=%lld, name=%s, fps=%d/%d, framelines=%d\n", s,
- p->index, p->id, p->name,
+ printk ("%s: index=%d, id=%Ld, name=%s, fps=%d/%d, "
+ "framelines=%d\n", s, p->index,
+ (unsigned long long)p->id, p->name,
p->frameperiod.numerator,
p->frameperiod.denominator,
p->framelines);
@@ -907,7 +901,7 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
{
v4l2_std_id *p=arg;
- printk ("%s: value=%llu\n", s, *p);
+ printk ("%s: value=%Lu\n", s, (unsigned long long)*p);
break;
}
}
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index 87e937581d5..d2ca0f08d0d 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -1,15 +1,20 @@
/*
*
* generic helper functions for video4linux capture buffers, to handle
- * memory management and PCI DMA. Right now bttv + saa7134 use it.
+ * memory management and PCI DMA.
+ * Right now, bttv, saa7134, saa7146 and cx88 use it.
*
* The functions expect the hardware being able to scatter gatter
* (i.e. the buffers are not linear in physical memory, but fragmented
* into PAGE_SIZE chunks). They also assume the driver does not need
- * to touch the video data (thus it is probably not useful for USB 1.1
- * as data often must be uncompressed by the drivers).
+ * to touch the video data.
+ *
+ * device specific map/unmap/sync stuff now are mapped as operations
+ * to allow its usage by USB and virtual devices.
*
* (c) 2001-2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
+ * (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ * (c) 2006 Ted Walther and John Sokol
*
* 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
@@ -167,6 +172,9 @@ int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
dprintk(1,"vmalloc_32(%d pages) failed\n",nr_pages);
return -ENOMEM;
}
+ dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n",
+ (unsigned long)dma->vmalloc,
+ nr_pages << PAGE_SHIFT);
memset(dma->vmalloc,0,nr_pages << PAGE_SHIFT);
dma->nr_pages = nr_pages;
return 0;
@@ -186,8 +194,10 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
return 0;
}
-int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
+int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
{
+ void *dev=q->dev;
+
MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
BUG_ON(0 == dma->nr_pages);
@@ -197,7 +207,7 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
}
if (dma->vmalloc) {
dma->sglist = videobuf_vmalloc_to_sg
- (dma->vmalloc,dma->nr_pages);
+ (dma->vmalloc,dma->nr_pages);
}
if (dma->bus_addr) {
dma->sglist = kmalloc(sizeof(struct scatterlist), GFP_KERNEL);
@@ -212,13 +222,14 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
dprintk(1,"scatterlist is NULL\n");
return -ENOMEM;
}
-
if (!dma->bus_addr) {
- dma->sglen = pci_map_sg(dev,dma->sglist,dma->nr_pages,
- dma->direction);
+ if (q->ops->vb_map_sg) {
+ dma->sglen = q->ops->vb_map_sg(dev,dma->sglist,
+ dma->nr_pages, dma->direction);
+ }
if (0 == dma->sglen) {
printk(KERN_WARNING
- "%s: pci_map_sg failed\n",__FUNCTION__);
+ "%s: videobuf_map_sg failed\n",__FUNCTION__);
kfree(dma->sglist);
dma->sglist = NULL;
dma->sglen = 0;
@@ -228,24 +239,31 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
return 0;
}
-int videobuf_dma_pci_sync(struct pci_dev *dev, struct videobuf_dmabuf *dma)
+int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
{
+ void *dev=q->dev;
+
MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
BUG_ON(!dma->sglen);
- if (!dma->bus_addr)
- pci_dma_sync_sg_for_cpu(dev,dma->sglist,dma->nr_pages,dma->direction);
+ if (!dma->bus_addr && q->ops->vb_dma_sync_sg)
+ q->ops->vb_dma_sync_sg(dev,dma->sglist,dma->nr_pages,
+ dma->direction);
+
return 0;
}
-int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma)
+int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
{
+ void *dev=q->dev;
+
MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
if (!dma->sglen)
return 0;
- if (!dma->bus_addr)
- pci_unmap_sg(dev,dma->sglist,dma->nr_pages,dma->direction);
+ if (!dma->bus_addr && q->ops->vb_unmap_sg)
+ q->ops->vb_unmap_sg(dev,dma->sglist,dma->nr_pages,
+ dma->direction);
kfree(dma->sglist);
dma->sglist = NULL;
dma->sglen = 0;
@@ -318,7 +336,7 @@ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr)
}
int
-videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb,
+videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
struct v4l2_framebuffer *fbuf)
{
int err,pages;
@@ -357,7 +375,7 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb,
default:
BUG();
}
- err = videobuf_dma_pci_map(pci,&vb->dma);
+ err = videobuf_dma_map(q,&vb->dma);
if (0 != err)
return err;
@@ -366,9 +384,41 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb,
/* --------------------------------------------------------------------- */
+void videobuf_queue_pci(struct videobuf_queue* q)
+{
+ /* If not specified, defaults to PCI map sg */
+ if (!q->ops->vb_map_sg)
+ q->ops->vb_map_sg=(vb_map_sg_t *)pci_map_sg;
+
+ if (!q->ops->vb_dma_sync_sg)
+ q->ops->vb_dma_sync_sg=(vb_map_sg_t *)pci_dma_sync_sg_for_cpu;
+ if (!q->ops->vb_unmap_sg)
+ q->ops->vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
+}
+
+int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma)
+{
+ struct videobuf_queue q;
+
+ q.dev=pci;
+ q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg;
+
+ return (videobuf_dma_unmap(&q,dma));
+}
+
+int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma)
+{
+ struct videobuf_queue q;
+
+ q.dev=pci;
+ q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg;
+
+ return (videobuf_dma_unmap(&q,dma));
+}
+
void videobuf_queue_init(struct videobuf_queue* q,
struct videobuf_queue_ops *ops,
- struct pci_dev *pci,
+ void *dev,
spinlock_t *irqlock,
enum v4l2_buf_type type,
enum v4l2_field field,
@@ -377,13 +427,15 @@ void videobuf_queue_init(struct videobuf_queue* q,
{
memset(q,0,sizeof(*q));
q->irqlock = irqlock;
- q->pci = pci;
+ q->dev = dev;
q->type = type;
q->field = field;
q->msize = msize;
q->ops = ops;
q->priv_data = priv;
+ videobuf_queue_pci(q);
+
mutex_init(&q->lock);
INIT_LIST_HEAD(&q->stream);
}
@@ -431,7 +483,8 @@ videobuf_queue_cancel(struct videobuf_queue *q)
int i;
/* remove queued buffers from list */
- spin_lock_irqsave(q->irqlock,flags);
+ if (q->irqlock)
+ spin_lock_irqsave(q->irqlock,flags);
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
if (NULL == q->bufs[i])
continue;
@@ -440,7 +493,8 @@ videobuf_queue_cancel(struct videobuf_queue *q)
q->bufs[i]->state = STATE_ERROR;
}
}
- spin_unlock_irqrestore(q->irqlock,flags);
+ if (q->irqlock)
+ spin_unlock_irqrestore(q->irqlock,flags);
/* free all buffers + clear queue */
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
@@ -534,19 +588,29 @@ videobuf_reqbufs(struct videobuf_queue *q,
unsigned int size,count;
int retval;
- if (req->type != q->type)
+ if (req->type != q->type) {
+ dprintk(1,"reqbufs: queue type invalid\n");
return -EINVAL;
- if (req->count < 1)
+ }
+ if (req->count < 1) {
+ dprintk(1,"reqbufs: count invalid (%d)\n",req->count);
return -EINVAL;
+ }
if (req->memory != V4L2_MEMORY_MMAP &&
req->memory != V4L2_MEMORY_USERPTR &&
- req->memory != V4L2_MEMORY_OVERLAY)
+ req->memory != V4L2_MEMORY_OVERLAY) {
+ dprintk(1,"reqbufs: memory type invalid\n");
return -EINVAL;
+ }
- if (q->streaming)
+ if (q->streaming) {
+ dprintk(1,"reqbufs: streaming already exists\n");
return -EBUSY;
- if (!list_empty(&q->stream))
+ }
+ if (!list_empty(&q->stream)) {
+ dprintk(1,"reqbufs: stream running\n");
return -EBUSY;
+ }
mutex_lock(&q->lock);
count = req->count;
@@ -559,8 +623,10 @@ videobuf_reqbufs(struct videobuf_queue *q,
count, size, (count*size)>>PAGE_SHIFT);
retval = videobuf_mmap_setup(q,count,size,req->memory);
- if (retval < 0)
+ if (retval < 0) {
+ dprintk(1,"reqbufs: mmap setup returned %d\n",retval);
goto done;
+ }
req->count = count;
@@ -572,12 +638,18 @@ videobuf_reqbufs(struct videobuf_queue *q,
int
videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b)
{
- if (unlikely(b->type != q->type))
+ if (unlikely(b->type != q->type)) {
+ dprintk(1,"querybuf: Wrong type.\n");
return -EINVAL;
- if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME))
+ }
+ if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) {
+ dprintk(1,"querybuf: index out of range.\n");
return -EINVAL;
- if (unlikely(NULL == q->bufs[b->index]))
+ }
+ if (unlikely(NULL == q->bufs[b->index])) {
+ dprintk(1,"querybuf: buffer is null.\n");
return -EINVAL;
+ }
videobuf_status(b,q->bufs[b->index],q->type);
return 0;
}
@@ -593,26 +665,40 @@ videobuf_qbuf(struct videobuf_queue *q,
mutex_lock(&q->lock);
retval = -EBUSY;
- if (q->reading)
+ if (q->reading) {
+ dprintk(1,"qbuf: Reading running...\n");
goto done;
+ }
retval = -EINVAL;
- if (b->type != q->type)
+ if (b->type != q->type) {
+ dprintk(1,"qbuf: Wrong type.\n");
goto done;
- if (b->index < 0 || b->index >= VIDEO_MAX_FRAME)
+ }
+ if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) {
+ dprintk(1,"qbuf: index out of range.\n");
goto done;
+ }
buf = q->bufs[b->index];
- if (NULL == buf)
+ if (NULL == buf) {
+ dprintk(1,"qbuf: buffer is null.\n");
goto done;
+ }
MAGIC_CHECK(buf->magic,MAGIC_BUFFER);
- if (buf->memory != b->memory)
+ if (buf->memory != b->memory) {
+ dprintk(1,"qbuf: memory type is wrong.\n");
goto done;
+ }
if (buf->state == STATE_QUEUED ||
- buf->state == STATE_ACTIVE)
+ buf->state == STATE_ACTIVE) {
+ dprintk(1,"qbuf: buffer is already queued or active.\n");
goto done;
+ }
if (b->flags & V4L2_BUF_FLAG_INPUT) {
- if (b->input >= q->inputs)
+ if (b->input >= q->inputs) {
+ dprintk(1,"qbuf: wrong input.\n");
goto done;
+ }
buf->input = b->input;
} else {
buf->input = UNSET;
@@ -620,12 +706,16 @@ videobuf_qbuf(struct videobuf_queue *q,
switch (b->memory) {
case V4L2_MEMORY_MMAP:
- if (0 == buf->baddr)
+ if (0 == buf->baddr) {
+ dprintk(1,"qbuf: mmap requested but buffer addr is zero!\n");
goto done;
+ }
break;
case V4L2_MEMORY_USERPTR:
- if (b->length < buf->bsize)
+ if (b->length < buf->bsize) {
+ dprintk(1,"qbuf: buffer length is not enough\n");
goto done;
+ }
if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr)
q->ops->buf_release(q,buf);
buf->baddr = b->m.userptr;
@@ -634,20 +724,27 @@ videobuf_qbuf(struct videobuf_queue *q,
buf->boff = b->m.offset;
break;
default:
+ dprintk(1,"qbuf: wrong memory type\n");
goto done;
}
+ dprintk(1,"qbuf: requesting next field\n");
field = videobuf_next_field(q);
retval = q->ops->buf_prepare(q,buf,field);
- if (0 != retval)
+ if (0 != retval) {
+ dprintk(1,"qbuf: buffer_prepare returned %d\n",retval);
goto done;
+ }
list_add_tail(&buf->stream,&q->stream);
if (q->streaming) {
- spin_lock_irqsave(q->irqlock,flags);
+ if (q->irqlock)
+ spin_lock_irqsave(q->irqlock,flags);
q->ops->buf_queue(q,buf);
- spin_unlock_irqrestore(q->irqlock,flags);
+ if (q->irqlock)
+ spin_unlock_irqrestore(q->irqlock,flags);
}
+ dprintk(1,"qbuf: succeded\n");
retval = 0;
done:
@@ -664,26 +761,39 @@ videobuf_dqbuf(struct videobuf_queue *q,
mutex_lock(&q->lock);
retval = -EBUSY;
- if (q->reading)
+ if (q->reading) {
+ dprintk(1,"dqbuf: Reading running...\n");
goto done;
+ }
retval = -EINVAL;
- if (b->type != q->type)
+ if (b->type != q->type) {
+ dprintk(1,"dqbuf: Wrong type.\n");
goto done;
- if (list_empty(&q->stream))
+ }
+ if (list_empty(&q->stream)) {
+ dprintk(1,"dqbuf: stream running\n");
goto done;
+ }
buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
retval = videobuf_waiton(buf, nonblocking, 1);
- if (retval < 0)
+ if (retval < 0) {
+ dprintk(1,"dqbuf: waiton returned %d\n",retval);
goto done;
+ }
switch (buf->state) {
case STATE_ERROR:
+ dprintk(1,"dqbuf: state is error\n");
retval = -EIO;
- /* fall through */
+ videobuf_dma_sync(q,&buf->dma);
+ buf->state = STATE_IDLE;
+ break;
case STATE_DONE:
- videobuf_dma_pci_sync(q->pci,&buf->dma);
+ dprintk(1,"dqbuf: state is done\n");
+ videobuf_dma_sync(q,&buf->dma);
buf->state = STATE_IDLE;
break;
default:
+ dprintk(1,"dqbuf: state invalid\n");
retval = -EINVAL;
goto done;
}
@@ -711,13 +821,15 @@ int videobuf_streamon(struct videobuf_queue *q)
if (q->streaming)
goto done;
q->streaming = 1;
- spin_lock_irqsave(q->irqlock,flags);
+ if (q->irqlock)
+ spin_lock_irqsave(q->irqlock,flags);
list_for_each(list,&q->stream) {
buf = list_entry(list, struct videobuf_buffer, stream);
if (buf->state == STATE_PREPARED)
q->ops->buf_queue(q,buf);
}
- spin_unlock_irqrestore(q->irqlock,flags);
+ if (q->irqlock)
+ spin_unlock_irqrestore(q->irqlock,flags);
done:
mutex_unlock(&q->lock);
@@ -762,12 +874,14 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data,
goto done;
/* start capture & wait */
- spin_lock_irqsave(q->irqlock,flags);
+ if (q->irqlock)
+ spin_lock_irqsave(q->irqlock,flags);
q->ops->buf_queue(q,q->read_buf);
- spin_unlock_irqrestore(q->irqlock,flags);
+ if (q->irqlock)
+ spin_unlock_irqrestore(q->irqlock,flags);
retval = videobuf_waiton(q->read_buf,0,0);
if (0 == retval) {
- videobuf_dma_pci_sync(q->pci,&q->read_buf->dma);
+ videobuf_dma_sync(q,&q->read_buf->dma);
if (STATE_ERROR == q->read_buf->state)
retval = -EIO;
else
@@ -809,6 +923,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
/* need to capture a new frame */
retval = -ENOMEM;
q->read_buf = videobuf_alloc(q->msize);
+ dprintk(1,"video alloc=0x%08x\n",(unsigned int) q->read_buf);
if (NULL == q->read_buf)
goto done;
q->read_buf->memory = V4L2_MEMORY_USERPTR;
@@ -820,9 +935,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
q->read_buf = NULL;
goto done;
}
- spin_lock_irqsave(q->irqlock,flags);
+ if (q->irqlock)
+ spin_lock_irqsave(q->irqlock,flags);
q->ops->buf_queue(q,q->read_buf);
- spin_unlock_irqrestore(q->irqlock,flags);
+ if (q->irqlock)
+ spin_unlock_irqrestore(q->irqlock,flags);
q->read_off = 0;
}
@@ -830,7 +947,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
retval = videobuf_waiton(q->read_buf, nonblocking, 1);
if (0 != retval)
goto done;
- videobuf_dma_pci_sync(q->pci,&q->read_buf->dma);
+ videobuf_dma_sync(q,&q->read_buf->dma);
if (STATE_ERROR == q->read_buf->state) {
/* catch I/O errors */
@@ -887,10 +1004,12 @@ int videobuf_read_start(struct videobuf_queue *q)
return err;
list_add_tail(&q->bufs[i]->stream, &q->stream);
}
- spin_lock_irqsave(q->irqlock,flags);
+ if (q->irqlock)
+ spin_lock_irqsave(q->irqlock,flags);
for (i = 0; i < count; i++)
q->ops->buf_queue(q,q->bufs[i]);
- spin_unlock_irqrestore(q->irqlock,flags);
+ if (q->irqlock)
+ spin_unlock_irqrestore(q->irqlock,flags);
q->reading = 1;
return 0;
}
@@ -985,9 +1104,11 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
if (q->read_off == q->read_buf->size) {
list_add_tail(&q->read_buf->stream,
&q->stream);
- spin_lock_irqsave(q->irqlock,flags);
+ if (q->irqlock)
+ spin_lock_irqsave(q->irqlock,flags);
q->ops->buf_queue(q,q->read_buf);
- spin_unlock_irqrestore(q->irqlock,flags);
+ if (q->irqlock)
+ spin_unlock_irqrestore(q->irqlock,flags);
q->read_buf = NULL;
}
if (retval < 0)
@@ -1249,11 +1370,14 @@ EXPORT_SYMBOL_GPL(videobuf_dma_init);
EXPORT_SYMBOL_GPL(videobuf_dma_init_user);
EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel);
EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay);
-EXPORT_SYMBOL_GPL(videobuf_dma_pci_map);
-EXPORT_SYMBOL_GPL(videobuf_dma_pci_sync);
-EXPORT_SYMBOL_GPL(videobuf_dma_pci_unmap);
+EXPORT_SYMBOL_GPL(videobuf_dma_map);
+EXPORT_SYMBOL_GPL(videobuf_dma_sync);
+EXPORT_SYMBOL_GPL(videobuf_dma_unmap);
EXPORT_SYMBOL_GPL(videobuf_dma_free);
+EXPORT_SYMBOL_GPL(videobuf_pci_dma_map);
+EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap);
+
EXPORT_SYMBOL_GPL(videobuf_alloc);
EXPORT_SYMBOL_GPL(videobuf_waiton);
EXPORT_SYMBOL_GPL(videobuf_iolock);
diff --git a/drivers/media/video/videocodec.h b/drivers/media/video/videocodec.h
index b1239ac7f37..8c233720b6a 100644
--- a/drivers/media/video/videocodec.h
+++ b/drivers/media/video/videocodec.h
@@ -57,7 +57,7 @@
therfor they may not be initialized.
The other fuctions are just for convenience, as they are for sure used by
- most/all of the codecs. The last ones may be ommited, too.
+ most/all of the codecs. The last ones may be ommited, too.
See the structure declaration below for more information and which data has
to be set up for the master and the slave.
@@ -75,52 +75,52 @@
/* ========================================== */
/*
- ==== master setup ====
+ ==== master setup ====
name -> name of the device structure for reference and debugging
master_data -> data ref. for the master (e.g. the zr36055,57,67)
readreg -> ref. to read-fn from register (setup by master, used by slave)
writereg -> ref. to write-fn to register (setup by master, used by slave)
- this two functions do the lowlevel I/O job
+ this two functions do the lowlevel I/O job
- ==== slave functionality setup ====
- slave_data -> data ref. for the slave (e.g. the zr36050,60)
+ ==== slave functionality setup ====
+ slave_data -> data ref. for the slave (e.g. the zr36050,60)
check -> fn-ref. checks availability of an device, returns -EIO on failure or
- the type on success
- this makes espcecially sense if a driver module supports more than
- one codec which may be quite similar to access, nevertheless it
- is good for a first functionality check
+ the type on success
+ this makes espcecially sense if a driver module supports more than
+ one codec which may be quite similar to access, nevertheless it
+ is good for a first functionality check
- -- main functions you always need for compression/decompression --
+ -- main functions you always need for compression/decompression --
set_mode -> this fn-ref. resets the entire codec, and sets up the mode
- with the last defined norm/size (or device default if not
- available) - it returns 0 if the mode is possible
+ with the last defined norm/size (or device default if not
+ available) - it returns 0 if the mode is possible
set_size -> this fn-ref. sets the norm and image size for
- compression/decompression (returns 0 on success)
- the norm param is defined in videodev.h (VIDEO_MODE_*)
+ compression/decompression (returns 0 on success)
+ the norm param is defined in videodev.h (VIDEO_MODE_*)
additional setup may be available, too - but the codec should work with
- some default values even without this
+ some default values even without this
- set_data -> sets device-specific data (tables, quality etc.)
- get_data -> query device-specific data (tables, quality etc.)
+ set_data -> sets device-specific data (tables, quality etc.)
+ get_data -> query device-specific data (tables, quality etc.)
- if the device delivers interrupts, they may be setup/handled here
- setup_interrupt -> codec irq setup (not needed for 36050/60)
- handle_interrupt -> codec irq handling (not needed for 36050/60)
+ if the device delivers interrupts, they may be setup/handled here
+ setup_interrupt -> codec irq setup (not needed for 36050/60)
+ handle_interrupt -> codec irq handling (not needed for 36050/60)
- if the device delivers pictures, they may be handled here
- put_image -> puts image data to the codec (not needed for 36050/60)
- get_image -> gets image data from the codec (not needed for 36050/60)
- the calls include frame numbers and flags (even/odd/...)
- if needed and a flag which allows blocking until its ready
+ if the device delivers pictures, they may be handled here
+ put_image -> puts image data to the codec (not needed for 36050/60)
+ get_image -> gets image data from the codec (not needed for 36050/60)
+ the calls include frame numbers and flags (even/odd/...)
+ if needed and a flag which allows blocking until its ready
*/
/* ============== */
/* user interface */
/* ============== */
-/*
+/*
Currently there is only a information display planned, as the layer
is not visible for the user space at all.
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 75e3d41382f..5f87dd5f1d0 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -97,7 +97,7 @@ static int video_open(struct inode *inode, struct file *file)
unsigned int minor = iminor(inode);
int err = 0;
struct video_device *vfl;
- struct file_operations *old_fops;
+ const struct file_operations *old_fops;
if(minor>=VIDEO_NUM_DEVICES)
return -ENODEV;
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index 0229819d0aa..a8c101494cf 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -1555,12 +1555,12 @@ static void vino_update_line_size(struct vino_channel_settings *vcs)
unsigned int w = vcs->clipping.right - vcs->clipping.left;
unsigned int d = vcs->decimation;
unsigned int bpp = vino_data_formats[vcs->data_format].bpp;
- unsigned int lsize;
+ unsigned int lsize;
dprintk("update_line_size(): before: w = %d, d = %d, "
"line_size = %d\n", w, d, vcs->line_size);
- /* line size must be multiple of 8 bytes */
+ /* line size must be multiple of 8 bytes */
lsize = (bpp * (w / d)) & ~7;
w = (lsize / bpp) * d;
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
new file mode 100644
index 00000000000..5e813404d06
--- /dev/null
+++ b/drivers/media/video/vivi.c
@@ -0,0 +1,1454 @@
+/*
+ * Virtual Video driver - This code emulates a real video device with v4l2 api
+ *
+ * Copyright (c) 2006 by:
+ * Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
+ * Ted Walther <ted--a.t--enumera.com>
+ * John Sokol <sokol--a.t--videotechnology.com>
+ * http://v4l.videotechnology.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the BSD Licence, GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version
+ */
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/random.h>
+#include <linux/version.h>
+#include <linux/videodev2.h>
+#include <linux/interrupt.h>
+#include <media/video-buf.h>
+#include <media/v4l2-common.h>
+#include <linux/kthread.h>
+#include <linux/highmem.h>
+
+/* Wake up at about 30 fps */
+#define WAKE_NUMERATOR 30
+#define WAKE_DENOMINATOR 1001
+#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
+
+/* These timers are for 1 fps - used only for testing */
+//#define WAKE_DENOMINATOR 30 /* hack for testing purposes */
+//#define BUFFER_TIMEOUT msecs_to_jiffies(5000) /* 5 seconds */
+
+#include "font.h"
+
+#ifndef kzalloc
+#define kzalloc(size, flags) \
+({ \
+ void *__ret = kmalloc(size, flags); \
+ if (__ret) \
+ memset(__ret, 0, size); \
+ __ret; \
+})
+#endif
+
+MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
+MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define VIVI_MAJOR_VERSION 0
+#define VIVI_MINOR_VERSION 4
+#define VIVI_RELEASE 0
+#define VIVI_VERSION KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
+
+static int video_nr = -1; /* /dev/videoN, -1 for autodetect */
+module_param(video_nr, int, 0);
+
+static int debug = 0;
+module_param(debug, int, 0);
+
+static unsigned int vid_limit = 16;
+module_param(vid_limit,int,0644);
+MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
+
+/* supported controls */
+static struct v4l2_queryctrl vivi_qctrl[] = {
+ {
+ .id = V4L2_CID_AUDIO_VOLUME,
+ .name = "Volume",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 65535,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 127,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 0x1,
+ .default_value = 0x10,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 0x1,
+ .default_value = 127,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_HUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hue",
+ .minimum = -128,
+ .maximum = 127,
+ .step = 0x1,
+ .default_value = 0,
+ .flags = 0,
+ }
+};
+
+static int qctl_regs[ARRAY_SIZE(vivi_qctrl)];
+
+#define dprintk(level,fmt, arg...) \
+ do { \
+ if (debug >= (level)) \
+ printk(KERN_DEBUG "vivi: " fmt , ## arg); \
+ } while (0)
+
+/* ------------------------------------------------------------------
+ Basic structures
+ ------------------------------------------------------------------*/
+
+struct vivi_fmt {
+ char *name;
+ u32 fourcc; /* v4l2 format id */
+ int depth;
+};
+
+static struct vivi_fmt format = {
+ .name = "4:2:2, packed, YUYV",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .depth = 16,
+};
+
+struct sg_to_addr {
+ int pos;
+ struct scatterlist *sg;
+};
+
+/* buffer for one video frame */
+struct vivi_buffer {
+ /* common v4l buffer stuff -- must be first */
+ struct videobuf_buffer vb;
+
+ struct vivi_fmt *fmt;
+
+ struct sg_to_addr *to_addr;
+};
+
+struct vivi_dmaqueue {
+ struct list_head active;
+ struct list_head queued;
+ struct timer_list timeout;
+
+ /* thread for generating video stream*/
+ struct task_struct *kthread;
+ wait_queue_head_t wq;
+ /* Counters to control fps rate */
+ int frame;
+ int ini_jiffies;
+};
+
+static LIST_HEAD(vivi_devlist);
+
+struct vivi_dev {
+ struct list_head vivi_devlist;
+
+ struct semaphore lock;
+
+ int users;
+
+ /* various device info */
+ unsigned int resources;
+ struct video_device video_dev;
+
+ struct vivi_dmaqueue vidq;
+
+ /* Several counters */
+ int h,m,s,us,jiffies;
+ char timestr[13];
+};
+
+struct vivi_fh {
+ struct vivi_dev *dev;
+
+ /* video capture */
+ struct vivi_fmt *fmt;
+ unsigned int width,height;
+ struct videobuf_queue vb_vidq;
+
+ enum v4l2_buf_type type;
+};
+
+/* ------------------------------------------------------------------
+ DMA and thread functions
+ ------------------------------------------------------------------*/
+
+/* Bars and Colors should match positions */
+
+enum colors {
+ WHITE,
+ AMBAR,
+ CYAN,
+ GREEN,
+ MAGENTA,
+ RED,
+ BLUE
+};
+
+static u8 bars[8][3] = {
+ /* R G B */
+ {204,204,204}, /* white */
+ {208,208, 0}, /* ambar */
+ { 0,206,206}, /* cyan */
+ { 0,239, 0}, /* green */
+ {239, 0,239}, /* magenta */
+ {205, 0, 0}, /* red */
+ { 0, 0,255}, /* blue */
+ { 0, 0, 0}
+};
+
+#define TO_Y(r,g,b) (((16829*r +33039*g +6416*b + 32768)>>16)+16)
+/* RGB to V(Cr) Color transform */
+#define TO_V(r,g,b) (((28784*r -24103*g -4681*b + 32768)>>16)+128)
+/* RGB to U(Cb) Color transform */
+#define TO_U(r,g,b) (((-9714*r -19070*g +28784*b + 32768)>>16)+128)
+
+#define TSTAMP_MIN_Y 24
+#define TSTAMP_MAX_Y TSTAMP_MIN_Y+15
+#define TSTAMP_MIN_X 64
+
+void prep_to_addr(struct sg_to_addr to_addr[],struct videobuf_buffer *vb)
+{
+ int i, pos=0;
+
+ for (i=0;i<vb->dma.nr_pages;i++) {
+ to_addr[i].sg=&vb->dma.sglist[i];
+ to_addr[i].pos=pos;
+ pos += vb->dma.sglist[i].length;
+ }
+}
+
+inline int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[])
+{
+ int p1=0,p2=pages-1,p3=pages/2;
+
+ /* Sanity test */
+ BUG_ON (pos>=to_addr[p2].pos+to_addr[p2].sg->length);
+
+ while (p1+1<p2) {
+ if (pos < to_addr[p3].pos) {
+ p2=p3;
+ } else {
+ p1=p3;
+ }
+ p3=(p1+p2)/2;
+ }
+ if (pos >= to_addr[p2].pos)
+ p1=p2;
+
+ return (p1);
+}
+
+void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
+ int hmax, int line, char *timestr)
+{
+ int w,i,j,pos=inipos,pgpos,oldpg,y;
+ char *p,*s,*basep;
+ struct page *pg;
+ u8 chr,r,g,b,color;
+
+ /* Get first addr pointed to pixel position */
+ oldpg=get_addr_pos(pos,pages,to_addr);
+ pg=pfn_to_page(to_addr[oldpg].sg->dma_address >> PAGE_SHIFT);
+ basep = kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[oldpg].sg->offset;
+
+ /* We will just duplicate the second pixel at the packet */
+ wmax/=2;
+
+ /* Generate a standard color bar pattern */
+ for (w=0;w<wmax;w++) {
+ r=bars[w*7/wmax][0];
+ g=bars[w*7/wmax][1];
+ b=bars[w*7/wmax][2];
+
+ for (color=0;color<4;color++) {
+ pgpos=get_addr_pos(pos,pages,to_addr);
+ if (pgpos!=oldpg) {
+ pg=pfn_to_page(to_addr[pgpos].sg->dma_address >> PAGE_SHIFT);
+ kunmap_atomic(basep, KM_BOUNCE_READ);
+ basep= kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[pgpos].sg->offset;
+ oldpg=pgpos;
+ }
+ p=basep+pos-to_addr[pgpos].pos;
+
+ switch (color) {
+ case 0:
+ case 2:
+ *p=TO_Y(r,g,b); /* Luminance */
+ break;
+ case 1:
+ *p=TO_U(r,g,b); /* Cb */
+ break;
+ case 3:
+ *p=TO_V(r,g,b); /* Cr */
+ break;
+ }
+ pos++;
+ }
+ }
+
+ /* Checks if it is possible to show timestamp */
+ if (TSTAMP_MAX_Y>=hmax)
+ goto end;
+ if (TSTAMP_MIN_X+strlen(timestr)>=wmax)
+ goto end;
+
+ /* Print stream time */
+ if (line>=TSTAMP_MIN_Y && line<=TSTAMP_MAX_Y) {
+ j=TSTAMP_MIN_X;
+ for (s=timestr;*s;s++) {
+ chr=rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y];
+ for (i=0;i<7;i++) {
+ if (chr&1<<(7-i)) { /* Font color*/
+ r=bars[BLUE][0];
+ g=bars[BLUE][1];
+ b=bars[BLUE][2];
+ r=g=b=0;
+ g=198;
+ } else { /* Background color */
+ r=bars[WHITE][0];
+ g=bars[WHITE][1];
+ b=bars[WHITE][2];
+ r=g=b=0;
+ }
+
+ pos=inipos+j*2;
+ for (color=0;color<4;color++) {
+ pgpos=get_addr_pos(pos,pages,to_addr);
+ if (pgpos!=oldpg) {
+ pg=pfn_to_page(to_addr[pgpos].
+ sg->dma_address
+ >> PAGE_SHIFT);
+ kunmap_atomic(basep,
+ KM_BOUNCE_READ);
+ basep= kmap_atomic(pg,
+ KM_BOUNCE_READ)+
+ to_addr[pgpos].sg->offset;
+ oldpg=pgpos;
+ }
+ p=basep+pos-to_addr[pgpos].pos;
+
+ y=TO_Y(r,g,b);
+
+ switch (color) {
+ case 0:
+ case 2:
+ *p=TO_Y(r,g,b); /* Luminance */
+ break;
+ case 1:
+ *p=TO_U(r,g,b); /* Cb */
+ break;
+ case 3:
+ *p=TO_V(r,g,b); /* Cr */
+ break;
+ }
+ pos++;
+ }
+ j++;
+ }
+ }
+ }
+
+
+end:
+ kunmap_atomic(basep, KM_BOUNCE_READ);
+}
+static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf)
+{
+ int h,pos=0;
+ int hmax = buf->vb.height;
+ int wmax = buf->vb.width;
+ struct videobuf_buffer *vb=&buf->vb;
+ struct sg_to_addr *to_addr=buf->to_addr;
+ struct timeval ts;
+
+ /* Test if DMA mapping is ready */
+ if (!vb->dma.sglist[0].dma_address)
+ return;
+
+ prep_to_addr(to_addr,vb);
+
+ /* Check if there is enough memory */
+ BUG_ON(buf->vb.dma.nr_pages << PAGE_SHIFT < (buf->vb.width*buf->vb.height)*2);
+
+ for (h=0;h<hmax;h++) {
+ gen_line(to_addr,pos,vb->dma.nr_pages,wmax,hmax,h,dev->timestr);
+ pos += wmax*2;
+ }
+
+ /* Updates stream time */
+
+ dev->us+=jiffies_to_usecs(jiffies-dev->jiffies);
+ dev->jiffies=jiffies;
+ if (dev->us>=1000000) {
+ dev->us-=1000000;
+ dev->s++;
+ if (dev->s>=60) {
+ dev->s-=60;
+ dev->m++;
+ if (dev->m>60) {
+ dev->m-=60;
+ dev->h++;
+ if (dev->h>24)
+ dev->h-=24;
+ }
+ }
+ }
+ sprintf(dev->timestr,"%02d:%02d:%02d:%03d",
+ dev->h,dev->m,dev->s,(dev->us+500)/1000);
+
+ dprintk(2,"vivifill at %s: Buffer 0x%08lx size= %d\n",dev->timestr,
+ (unsigned long)buf->vb.dma.vmalloc,pos);
+
+ /* Advice that buffer was filled */
+ buf->vb.state = STATE_DONE;
+ buf->vb.field_count++;
+ do_gettimeofday(&ts);
+ buf->vb.ts = ts;
+
+ list_del(&buf->vb.queue);
+ wake_up(&buf->vb.done);
+}
+
+static int restart_video_queue(struct vivi_dmaqueue *dma_q);
+
+static void vivi_thread_tick(struct vivi_dmaqueue *dma_q)
+{
+ struct vivi_buffer *buf;
+ struct vivi_dev *dev= container_of(dma_q,struct vivi_dev,vidq);
+
+ int bc;
+
+ /* Announces videobuf that all went ok */
+ for (bc = 0;; bc++) {
+ if (list_empty(&dma_q->active)) {
+ dprintk(1,"No active queue to serve\n");
+ break;
+ }
+
+ buf = list_entry(dma_q->active.next,
+ struct vivi_buffer, vb.queue);
+
+ /* Nobody is waiting something to be done, just return */
+ if (!waitqueue_active(&buf->vb.done)) {
+ mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+ return;
+ }
+
+ do_gettimeofday(&buf->vb.ts);
+ dprintk(2,"[%p/%d] wakeup\n",buf,buf->vb.i);
+
+ /* Fill buffer */
+ vivi_fillbuff(dev,buf);
+ }
+ if (list_empty(&dma_q->active)) {
+ del_timer(&dma_q->timeout);
+ } else {
+ mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+ }
+ if (bc != 1)
+ dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
+}
+
+void vivi_sleep(struct vivi_dmaqueue *dma_q)
+{
+ int timeout;
+ DECLARE_WAITQUEUE(wait, current);
+
+ dprintk(1,"%s dma_q=0x%08lx\n",__FUNCTION__,(unsigned long)dma_q);
+
+ add_wait_queue(&dma_q->wq, &wait);
+ if (!kthread_should_stop()) {
+ dma_q->frame++;
+
+ /* Calculate time to wake up */
+ timeout=dma_q->ini_jiffies+msecs_to_jiffies((dma_q->frame*WAKE_NUMERATOR*1000)/WAKE_DENOMINATOR)-jiffies;
+
+ if (timeout <= 0) {
+ int old=dma_q->frame;
+ dma_q->frame=(jiffies_to_msecs(jiffies-dma_q->ini_jiffies)*WAKE_DENOMINATOR)/(WAKE_NUMERATOR*1000)+1;
+
+ timeout=dma_q->ini_jiffies+msecs_to_jiffies((dma_q->frame*WAKE_NUMERATOR*1000)/WAKE_DENOMINATOR)-jiffies;
+
+ dprintk(1,"underrun, losed %d frames. "
+ "Now, frame is %d. Waking on %d jiffies\n",
+ dma_q->frame-old,dma_q->frame,timeout);
+ } else
+ dprintk(1,"will sleep for %i jiffies\n",timeout);
+
+ vivi_thread_tick(dma_q);
+
+ schedule_timeout_interruptible (timeout);
+ }
+
+ remove_wait_queue(&dma_q->wq, &wait);
+ try_to_freeze();
+}
+
+int vivi_thread(void *data)
+{
+ struct vivi_dmaqueue *dma_q=data;
+
+ dprintk(1,"thread started\n");
+
+ for (;;) {
+ vivi_sleep(dma_q);
+
+ if (kthread_should_stop())
+ break;
+ }
+ dprintk(1, "thread: exit\n");
+ return 0;
+}
+
+int vivi_start_thread(struct vivi_dmaqueue *dma_q)
+{
+ dma_q->frame=0;
+ dma_q->ini_jiffies=jiffies;
+
+ dprintk(1,"%s\n",__FUNCTION__);
+ init_waitqueue_head(&dma_q->wq);
+
+ dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi");
+
+ if (dma_q->kthread == NULL) {
+ printk(KERN_ERR "vivi: kernel_thread() failed\n");
+ return -EINVAL;
+ }
+ dprintk(1,"returning from %s\n",__FUNCTION__);
+ return 0;
+}
+
+void vivi_stop_thread(struct vivi_dmaqueue *dma_q)
+{
+ dprintk(1,"%s\n",__FUNCTION__);
+ /* shutdown control thread */
+ if (dma_q->kthread) {
+ kthread_stop(dma_q->kthread);
+ dma_q->kthread=NULL;
+ }
+}
+
+static int restart_video_queue(struct vivi_dmaqueue *dma_q)
+{
+ struct vivi_buffer *buf, *prev;
+ struct list_head *item;
+
+ dprintk(1,"%s dma_q=0x%08lx\n",__FUNCTION__,(unsigned long)dma_q);
+
+ if (!list_empty(&dma_q->active)) {
+ buf = list_entry(dma_q->active.next, struct vivi_buffer, vb.queue);
+ dprintk(2,"restart_queue [%p/%d]: restart dma\n",
+ buf, buf->vb.i);
+
+ dprintk(1,"Restarting video dma\n");
+ vivi_stop_thread(dma_q);
+// vivi_start_thread(dma_q);
+
+ /* cancel all outstanding capture / vbi requests */
+ list_for_each(item,&dma_q->active) {
+ buf = list_entry(item, struct vivi_buffer, vb.queue);
+
+ list_del(&buf->vb.queue);
+ buf->vb.state = STATE_ERROR;
+ wake_up(&buf->vb.done);
+ }
+ mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+
+ return 0;
+ }
+
+ prev = NULL;
+ for (;;) {
+ if (list_empty(&dma_q->queued))
+ return 0;
+ buf = list_entry(dma_q->queued.next, struct vivi_buffer, vb.queue);
+ if (NULL == prev) {
+ list_del(&buf->vb.queue);
+ list_add_tail(&buf->vb.queue,&dma_q->active);
+
+ dprintk(1,"Restarting video dma\n");
+ vivi_stop_thread(dma_q);
+ vivi_start_thread(dma_q);
+
+ buf->vb.state = STATE_ACTIVE;
+ mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+ dprintk(2,"[%p/%d] restart_queue - first active\n",
+ buf,buf->vb.i);
+
+ } else if (prev->vb.width == buf->vb.width &&
+ prev->vb.height == buf->vb.height &&
+ prev->fmt == buf->fmt) {
+ list_del(&buf->vb.queue);
+ list_add_tail(&buf->vb.queue,&dma_q->active);
+ buf->vb.state = STATE_ACTIVE;
+ dprintk(2,"[%p/%d] restart_queue - move to active\n",
+ buf,buf->vb.i);
+ } else {
+ return 0;
+ }
+ prev = buf;
+ }
+}
+
+static void vivi_vid_timeout(unsigned long data)
+{
+ struct vivi_dev *dev = (struct vivi_dev*)data;
+ struct vivi_dmaqueue *vidq = &dev->vidq;
+ struct vivi_buffer *buf;
+
+ while (!list_empty(&vidq->active)) {
+ buf = list_entry(vidq->active.next, struct vivi_buffer, vb.queue);
+ list_del(&buf->vb.queue);
+ buf->vb.state = STATE_ERROR;
+ wake_up(&buf->vb.done);
+ printk("vivi/0: [%p/%d] timeout\n", buf, buf->vb.i);
+ }
+
+ restart_video_queue(vidq);
+}
+
+/* ------------------------------------------------------------------
+ Videobuf operations
+ ------------------------------------------------------------------*/
+static int
+buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+{
+ struct vivi_fh *fh = vq->priv_data;
+
+ *size = fh->width*fh->height*2;
+
+ if (0 == *count)
+ *count = 32;
+ while (*size * *count > vid_limit * 1024 * 1024)
+ (*count)--;
+ return 0;
+}
+
+void
+free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
+{
+ dprintk(1,"%s\n",__FUNCTION__);
+
+ if (in_interrupt())
+ BUG();
+
+ /*FIXME: Maybe a spinlock is required here */
+ kfree(buf->to_addr);
+ buf->to_addr=NULL;
+
+ videobuf_waiton(&buf->vb,0,0);
+ videobuf_dma_unmap(vq, &buf->vb.dma);
+ videobuf_dma_free(&buf->vb.dma);
+ buf->vb.state = STATE_NEEDS_INIT;
+}
+
+#define norm_maxw() 1024
+#define norm_maxh() 768
+static int
+buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+ enum v4l2_field field)
+{
+ struct vivi_fh *fh = vq->priv_data;
+ struct vivi_buffer *buf = container_of(vb,struct vivi_buffer,vb);
+ int rc, init_buffer = 0;
+
+// dprintk(1,"%s, field=%d\n",__FUNCTION__,field);
+
+ BUG_ON(NULL == fh->fmt);
+ if (fh->width < 48 || fh->width > norm_maxw() ||
+ fh->height < 32 || fh->height > norm_maxh())
+ return -EINVAL;
+ buf->vb.size = fh->width*fh->height*2;
+ if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+ return -EINVAL;
+
+ if (buf->fmt != fh->fmt ||
+ buf->vb.width != fh->width ||
+ buf->vb.height != fh->height ||
+ buf->vb.field != field) {
+ buf->fmt = fh->fmt;
+ buf->vb.width = fh->width;
+ buf->vb.height = fh->height;
+ buf->vb.field = field;
+ init_buffer = 1;
+ }
+
+ if (STATE_NEEDS_INIT == buf->vb.state) {
+ if (0 != (rc = videobuf_iolock(vq,&buf->vb,NULL)))
+ goto fail;
+ }
+
+ buf->vb.state = STATE_PREPARED;
+
+ if (NULL == (buf->to_addr = kmalloc(sizeof(*buf->to_addr) * vb->dma.nr_pages,GFP_KERNEL))) {
+ rc=-ENOMEM;
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ free_buffer(vq,buf);
+ return rc;
+}
+
+static void
+buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct vivi_buffer *buf = container_of(vb,struct vivi_buffer,vb);
+ struct vivi_fh *fh = vq->priv_data;
+ struct vivi_dev *dev = fh->dev;
+ struct vivi_dmaqueue *vidq = &dev->vidq;
+ struct vivi_buffer *prev;
+
+ if (!list_empty(&vidq->queued)) {
+ dprintk(1,"adding vb queue=0x%08lx\n",(unsigned long)&buf->vb.queue);
+ list_add_tail(&buf->vb.queue,&vidq->queued);
+ buf->vb.state = STATE_QUEUED;
+ dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
+ buf, buf->vb.i);
+ } else if (list_empty(&vidq->active)) {
+ list_add_tail(&buf->vb.queue,&vidq->active);
+
+ buf->vb.state = STATE_ACTIVE;
+ mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
+ dprintk(2,"[%p/%d] buffer_queue - first active\n",
+ buf, buf->vb.i);
+
+ vivi_start_thread(vidq);
+ } else {
+ prev = list_entry(vidq->active.prev, struct vivi_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width &&
+ prev->vb.height == buf->vb.height &&
+ prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue,&vidq->active);
+ buf->vb.state = STATE_ACTIVE;
+ dprintk(2,"[%p/%d] buffer_queue - append to active\n",
+ buf, buf->vb.i);
+
+ } else {
+ list_add_tail(&buf->vb.queue,&vidq->queued);
+ buf->vb.state = STATE_QUEUED;
+ dprintk(2,"[%p/%d] buffer_queue - first queued\n",
+ buf, buf->vb.i);
+ }
+ }
+}
+
+static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+ struct vivi_buffer *buf = container_of(vb,struct vivi_buffer,vb);
+ struct vivi_fh *fh = vq->priv_data;
+ struct vivi_dev *dev = (struct vivi_dev*)fh->dev;
+ struct vivi_dmaqueue *vidq = &dev->vidq;
+
+ dprintk(1,"%s\n",__FUNCTION__);
+
+ vivi_stop_thread(vidq);
+
+ free_buffer(vq,buf);
+}
+
+int vivi_map_sg (void *dev, struct scatterlist *sg, int nents,
+ int direction)
+{
+ int i;
+
+ dprintk(1,"%s, number of pages=%d\n",__FUNCTION__,nents);
+ BUG_ON(direction == DMA_NONE);
+
+ for (i = 0; i < nents; i++ ) {
+ BUG_ON(!sg[i].page);
+
+ sg[i].dma_address = page_to_phys(sg[i].page) + sg[i].offset;
+ }
+
+ return nents;
+}
+
+int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages,
+ int direction)
+{
+ dprintk(1,"%s\n",__FUNCTION__);
+ return 0;
+}
+
+int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist,int nr_pages,
+ int direction)
+{
+// dprintk(1,"%s\n",__FUNCTION__);
+
+// flush_write_buffers();
+ return 0;
+}
+
+static struct videobuf_queue_ops vivi_video_qops = {
+ .buf_setup = buffer_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_queue = buffer_queue,
+ .buf_release = buffer_release,
+
+ /* Non-pci handling routines */
+ .vb_map_sg = vivi_map_sg,
+ .vb_dma_sync_sg = vivi_dma_sync_sg,
+ .vb_unmap_sg = vivi_unmap_sg,
+};
+
+/* ------------------------------------------------------------------
+ IOCTL handling
+ ------------------------------------------------------------------*/
+
+static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh,
+ struct v4l2_format *f)
+{
+ struct vivi_fmt *fmt;
+ enum v4l2_field field;
+ unsigned int maxw, maxh;
+
+ if (format.fourcc != f->fmt.pix.pixelformat) {
+ dprintk(1,"Fourcc format invalid.\n");
+ return -EINVAL;
+ }
+ fmt=&format;
+
+ field = f->fmt.pix.field;
+
+ if (field == V4L2_FIELD_ANY) {
+// field=V4L2_FIELD_INTERLACED;
+ field=V4L2_FIELD_SEQ_TB;
+ } else if (V4L2_FIELD_INTERLACED != field) {
+ dprintk(1,"Field type invalid.\n");
+ return -EINVAL;
+ }
+
+ maxw = norm_maxw();
+ maxh = norm_maxh();
+
+ f->fmt.pix.field = field;
+ if (f->fmt.pix.height < 32)
+ f->fmt.pix.height = 32;
+ if (f->fmt.pix.height > maxh)
+ f->fmt.pix.height = maxh;
+ if (f->fmt.pix.width < 48)
+ f->fmt.pix.width = 48;
+ if (f->fmt.pix.width > maxw)
+ f->fmt.pix.width = maxw;
+ f->fmt.pix.width &= ~0x03;
+ f->fmt.pix.bytesperline =
+ (f->fmt.pix.width * fmt->depth) >> 3;
+ f->fmt.pix.sizeimage =
+ f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+ return 0;
+}
+
+static int res_get(struct vivi_dev *dev, struct vivi_fh *fh)
+{
+ /* is it free? */
+ down(&dev->lock);
+ if (dev->resources) {
+ /* no, someone else uses it */
+ up(&dev->lock);
+ return 0;
+ }
+ /* it's free, grab it */
+ dev->resources =1;
+ dprintk(1,"res: get\n");
+ up(&dev->lock);
+ return 1;
+}
+
+static inline int res_locked(struct vivi_dev *dev)
+{
+ return (dev->resources);
+}
+
+static void res_free(struct vivi_dev *dev, struct vivi_fh *fh)
+{
+ down(&dev->lock);
+ dev->resources = 0;
+ dprintk(1,"res: put\n");
+ up(&dev->lock);
+}
+
+static int vivi_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg)
+{
+ struct vivi_fh *fh = file->private_data;
+ struct vivi_dev *dev = fh->dev;
+ int ret=0;
+
+ if (debug) {
+ if (_IOC_DIR(cmd) & _IOC_WRITE)
+ v4l_printk_ioctl_arg("vivi(w)",cmd, arg);
+ else if (!_IOC_DIR(cmd) & _IOC_READ) {
+ v4l_print_ioctl("vivi", cmd);
+ }
+ }
+
+ switch(cmd) {
+ /* --- capabilities ------------------------------------------ */
+ case VIDIOC_QUERYCAP:
+ {
+ struct v4l2_capability *cap = (struct v4l2_capability*)arg;
+
+ memset(cap, 0, sizeof(*cap));
+
+ strcpy(cap->driver, "vivi");
+ strcpy(cap->card, "vivi");
+ cap->version = VIVI_VERSION;
+ cap->capabilities =
+ V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_STREAMING |
+ V4L2_CAP_READWRITE;
+ break;
+ }
+ /* --- capture ioctls ---------------------------------------- */
+ case VIDIOC_ENUM_FMT:
+ {
+ struct v4l2_fmtdesc *f = arg;
+ enum v4l2_buf_type type;
+ unsigned int index;
+
+ index = f->index;
+ type = f->type;
+
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret=-EINVAL;
+ break;
+ }
+
+ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (index > 0){
+ ret=-EINVAL;
+ break;
+ }
+ memset(f,0,sizeof(*f));
+
+ f->index = index;
+ f->type = type;
+ strlcpy(f->description,format.name,sizeof(f->description));
+ f->pixelformat = format.fourcc;
+ break;
+ default:
+ ret=-EINVAL;
+ }
+ break;
+ }
+ case VIDIOC_G_FMT:
+ {
+ struct v4l2_format *f = (struct v4l2_format *)arg;
+
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret=-EINVAL;
+ break;
+ }
+
+ memset(&f->fmt.pix,0,sizeof(f->fmt.pix));
+ f->fmt.pix.width = fh->width;
+ f->fmt.pix.height = fh->height;
+ f->fmt.pix.field = fh->vb_vidq.field;
+ f->fmt.pix.pixelformat = fh->fmt->fourcc;
+ f->fmt.pix.bytesperline =
+ (f->fmt.pix.width * fh->fmt->depth) >> 3;
+ f->fmt.pix.sizeimage =
+ f->fmt.pix.height * f->fmt.pix.bytesperline;
+ break;
+ }
+ case VIDIOC_S_FMT:
+ {
+ struct v4l2_format *f = arg;
+
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ dprintk(1,"Only capture supported.\n");
+ ret=-EINVAL;
+ break;
+ }
+
+ ret = vivi_try_fmt(dev,fh,f);
+ if (ret < 0)
+ break;
+
+ fh->fmt = &format;
+ fh->width = f->fmt.pix.width;
+ fh->height = f->fmt.pix.height;
+ fh->vb_vidq.field = f->fmt.pix.field;
+ fh->type = f->type;
+
+ break;
+ }
+ case VIDIOC_TRY_FMT:
+ {
+ struct v4l2_format *f = arg;
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret=-EINVAL;
+ break;
+ }
+
+ ret=vivi_try_fmt(dev,fh,f);
+ break;
+ }
+ case VIDIOC_REQBUFS:
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret=-EINVAL;
+ break;
+ }
+ ret=videobuf_reqbufs(&fh->vb_vidq, arg);
+ break;
+ case VIDIOC_QUERYBUF:
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret=-EINVAL;
+ break;
+ }
+ ret=videobuf_querybuf(&fh->vb_vidq, arg);
+ break;
+ case VIDIOC_QBUF:
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret=-EINVAL;
+ break;
+ }
+ ret=videobuf_qbuf(&fh->vb_vidq, arg);
+ break;
+ case VIDIOC_DQBUF:
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret=-EINVAL;
+ break;
+ }
+ ret=videobuf_dqbuf(&fh->vb_vidq, arg,
+ file->f_flags & O_NONBLOCK);
+ break;
+#ifdef HAVE_V4L1
+ /* --- streaming capture ------------------------------------- */
+ case VIDIOCGMBUF:
+ {
+ struct video_mbuf *mbuf = arg;
+ struct videobuf_queue *q=&fh->vb_vidq;
+ struct v4l2_requestbuffers req;
+ unsigned int i;
+
+ memset(&req,0,sizeof(req));
+ req.type = q->type;
+ req.count = 8;
+ req.memory = V4L2_MEMORY_MMAP;
+ ret = videobuf_reqbufs(q,&req);
+ if (ret < 0)
+ break;
+ memset(mbuf,0,sizeof(*mbuf));
+ mbuf->frames = req.count;
+ mbuf->size = 0;
+ for (i = 0; i < mbuf->frames; i++) {
+ mbuf->offsets[i] = q->bufs[i]->boff;
+ mbuf->size += q->bufs[i]->bsize;
+ }
+ break;
+ }
+#endif
+ case VIDIOC_STREAMON:
+ {
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (!res_get(dev,fh))
+ return -EBUSY;
+ ret=videobuf_streamon(&fh->vb_vidq);
+ break;
+ }
+ case VIDIOC_STREAMOFF:
+ {
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret=-EINVAL;
+ break;
+ }
+ ret = videobuf_streamoff(&fh->vb_vidq);
+ if (ret < 0)
+ break;
+ res_free(dev,fh);
+ break;
+ }
+ /* ---------- tv norms ---------- */
+ case VIDIOC_ENUMSTD:
+ {
+ struct v4l2_standard *e = arg;
+
+ if (e->index>0) {
+ ret=-EINVAL;
+ break;
+ }
+ ret = v4l2_video_std_construct(e, V4L2_STD_NTSC_M, "NTSC-M");
+
+ /* Allows vivi to use different fps from video std */
+ e->frameperiod.numerator = WAKE_NUMERATOR;
+ e->frameperiod.denominator = WAKE_DENOMINATOR;
+
+ break;
+ }
+ case VIDIOC_G_STD:
+ {
+ v4l2_std_id *id = arg;
+
+ *id = V4L2_STD_NTSC_M;
+ break;
+ }
+ case VIDIOC_S_STD:
+ {
+ break;
+ }
+ /* ------ input switching ---------- */
+ case VIDIOC_ENUMINPUT:
+ { /* only one input in this sample driver */
+ struct v4l2_input *inp = arg;
+
+ if (inp->index != 0) {
+ ret=-EINVAL;
+ break;
+ }
+ memset(inp, 0, sizeof(*inp));
+
+ inp->index = 0;
+ inp->type = V4L2_INPUT_TYPE_CAMERA;
+ inp->std = V4L2_STD_NTSC_M;
+ strcpy(inp->name,"Camera");
+ break;
+ }
+ case VIDIOC_G_INPUT:
+ {
+ unsigned int *i = arg;
+
+ *i = 0;
+ break;
+ }
+ case VIDIOC_S_INPUT:
+ {
+ unsigned int *i = arg;
+
+ if (*i > 0)
+ ret=-EINVAL;
+ break;
+ }
+
+ /* --- controls ---------------------------------------------- */
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *qc = arg;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
+ if (qc->id && qc->id == vivi_qctrl[i].id) {
+ memcpy(qc, &(vivi_qctrl[i]),
+ sizeof(*qc));
+ break;
+ }
+
+ ret=-EINVAL;
+ break;
+ }
+ case VIDIOC_G_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
+ if (ctrl->id == vivi_qctrl[i].id) {
+ ctrl->value=qctl_regs[i];
+ break;
+ }
+
+ ret=-EINVAL;
+ break;
+ }
+ case VIDIOC_S_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
+ if (ctrl->id == vivi_qctrl[i].id) {
+ if (ctrl->value <
+ vivi_qctrl[i].minimum
+ || ctrl->value >
+ vivi_qctrl[i].maximum) {
+ ret=-ERANGE;
+ break;
+ }
+ qctl_regs[i]=ctrl->value;
+ break;
+ }
+ ret=-EINVAL;
+ break;
+ }
+ default:
+ ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,vivi_do_ioctl);
+ }
+
+ if (debug) {
+ if (ret<0) {
+ v4l_print_ioctl("vivi(err)", cmd);
+ dprintk(1,"errcode=%d\n",ret);
+ } else if (_IOC_DIR(cmd) & _IOC_READ)
+ v4l_printk_ioctl_arg("vivi(r)",cmd, arg);
+ }
+
+ return ret;
+}
+
+static int vivi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return video_usercopy(inode, file, cmd, arg, vivi_do_ioctl);
+}
+
+/* ------------------------------------------------------------------
+ File operations for the device
+ ------------------------------------------------------------------*/
+
+#define line_buf_size(norm) (norm_maxw(norm)*(format.depth+7)/8)
+
+static int vivi_open(struct inode *inode, struct file *file)
+{
+ int minor = iminor(inode);
+ struct vivi_dev *h,*dev = NULL;
+ struct vivi_fh *fh;
+ struct list_head *list;
+ enum v4l2_buf_type type = 0;
+ int i;
+
+ printk(KERN_DEBUG "vivi: open called (minor=%d)\n",minor);
+
+ list_for_each(list,&vivi_devlist) {
+ h = list_entry(list, struct vivi_dev, vivi_devlist);
+ if (h->video_dev.minor == minor) {
+ dev = h;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ }
+ if (NULL == dev)
+ return -ENODEV;
+
+
+ /* If more than one user, mutex should be added */
+ dev->users++;
+
+ dprintk(1,"open minor=%d type=%s users=%d\n",
+ minor,v4l2_type_names[type],dev->users);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh),GFP_KERNEL);
+ if (NULL == fh) {
+ dev->users--;
+ return -ENOMEM;
+ }
+
+ file->private_data = fh;
+ fh->dev = dev;
+ fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fh->fmt = &format;
+ fh->width = 640;
+ fh->height = 480;
+
+ /* Put all controls at a sane state */
+ for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
+ qctl_regs[i] =vivi_qctrl[i].default_value;
+
+ dprintk(1,"Open: fh=0x%08lx, dev=0x%08lx, dev->vidq=0x%08lx\n",
+ (unsigned long)fh,(unsigned long)dev,(unsigned long)&dev->vidq);
+ dprintk(1,"Open: list_empty queued=%d\n",list_empty(&dev->vidq.queued));
+ dprintk(1,"Open: list_empty active=%d\n",list_empty(&dev->vidq.active));
+
+ /* Resets frame counters */
+ dev->h=0;
+ dev->m=0;
+ dev->s=0;
+ dev->us=0;
+ dev->jiffies=jiffies;
+ sprintf(dev->timestr,"%02d:%02d:%02d:%03d",
+ dev->h,dev->m,dev->s,(dev->us+500)/1000);
+
+ videobuf_queue_init(&fh->vb_vidq, &vivi_video_qops,
+ NULL, NULL,
+ fh->type,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct vivi_buffer),fh);
+
+ return 0;
+}
+
+static ssize_t
+vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+ struct vivi_fh *fh = file->private_data;
+
+ if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ if (res_locked(fh->dev))
+ return -EBUSY;
+ return videobuf_read_one(&fh->vb_vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+ }
+ return 0;
+}
+
+static unsigned int
+vivi_poll(struct file *file, struct poll_table_struct *wait)
+{
+ struct vivi_fh *fh = file->private_data;
+ struct vivi_buffer *buf;
+
+ dprintk(1,"%s\n",__FUNCTION__);
+
+ if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
+ return POLLERR;
+
+ if (res_get(fh->dev,fh)) {
+ dprintk(1,"poll: mmap interface\n");
+ /* streaming capture */
+ if (list_empty(&fh->vb_vidq.stream))
+ return POLLERR;
+ buf = list_entry(fh->vb_vidq.stream.next,struct vivi_buffer,vb.stream);
+ } else {
+ dprintk(1,"poll: read() interface\n");
+ /* read() capture */
+ buf = (struct vivi_buffer*)fh->vb_vidq.read_buf;
+ if (NULL == buf)
+ return POLLERR;
+ }
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == STATE_DONE ||
+ buf->vb.state == STATE_ERROR)
+ return POLLIN|POLLRDNORM;
+ return 0;
+}
+
+static int vivi_release(struct inode *inode, struct file *file)
+{
+ struct vivi_fh *fh = file->private_data;
+ struct vivi_dev *dev = fh->dev;
+ struct vivi_dmaqueue *vidq = &dev->vidq;
+
+ int minor = iminor(inode);
+
+ vivi_stop_thread(vidq);
+ videobuf_mmap_free(&fh->vb_vidq);
+
+ kfree (fh);
+
+ dev->users--;
+
+ printk(KERN_DEBUG "vivi: close called (minor=%d, users=%d)\n",minor,dev->users);
+
+ return 0;
+}
+
+static int
+vivi_mmap(struct file *file, struct vm_area_struct * vma)
+{
+ struct vivi_fh *fh = file->private_data;
+ int ret;
+
+ dprintk (1,"mmap called, vma=0x%08lx\n",(unsigned long)vma);
+
+ ret=videobuf_mmap_mapper(&fh->vb_vidq, vma);
+
+ dprintk (1,"vma start=0x%08lx, size=%ld, ret=%d\n",
+ (unsigned long)vma->vm_start,
+ (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
+ ret);
+
+ return ret;
+}
+
+static struct file_operations vivi_fops = {
+ .owner = THIS_MODULE,
+ .open = vivi_open,
+ .release = vivi_release,
+ .read = vivi_read,
+ .poll = vivi_poll,
+ .ioctl = vivi_ioctl,
+ .mmap = vivi_mmap,
+ .llseek = no_llseek,
+};
+
+static struct video_device vivi = {
+ .name = "VTM Virtual Video Capture Board",
+ .type = VID_TYPE_CAPTURE,
+ .hardware = 0,
+ .fops = &vivi_fops,
+ .minor = -1,
+// .release = video_device_release,
+};
+/* ------------------------------------------------------------------
+ Initialization and module stuff
+ ------------------------------------------------------------------*/
+
+static int __init vivi_init(void)
+{
+ int ret;
+ struct vivi_dev *dev;
+
+ dev = kzalloc(sizeof(*dev),GFP_KERNEL);
+ if (NULL == dev)
+ return -ENOMEM;
+ list_add_tail(&dev->vivi_devlist,&vivi_devlist);
+
+ /* init video dma queues */
+ INIT_LIST_HEAD(&dev->vidq.active);
+ INIT_LIST_HEAD(&dev->vidq.queued);
+
+ /* initialize locks */
+ init_MUTEX(&dev->lock);
+
+ dev->vidq.timeout.function = vivi_vid_timeout;
+ dev->vidq.timeout.data = (unsigned long)dev;
+ init_timer(&dev->vidq.timeout);
+
+ ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr);
+ printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret);
+ return ret;
+}
+
+static void __exit vivi_exit(void)
+{
+ struct vivi_dev *h;
+ struct list_head *list;
+
+ list_for_each(list,&vivi_devlist) {
+ h = list_entry(list, struct vivi_dev, vivi_devlist);
+ kfree (h);
+ }
+ video_unregister_device(&vivi);
+}
+
+module_init(vivi_init);
+module_exit(vivi_exit);
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 4cd57996748..40b205b9148 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -1,4 +1,4 @@
-/*
+/*
* vpx3220a, vpx3216b & vpx3214c video decoder driver version 0.0.1
*
* Copyright (C) 2001 Laurent Pinchart <lpinchart@freegates.be>
@@ -176,8 +176,8 @@ vpx3220_write_block (struct i2c_client *client,
static int
vpx3220_write_fp_block (struct i2c_client *client,
- const u16 *data,
- unsigned int len)
+ const u16 *data,
+ unsigned int len)
{
u8 reg;
int ret = 0;
@@ -316,7 +316,7 @@ vpx3220_command (struct i2c_client *client,
vpx3220_write_fp_block(client, init_fp,
sizeof(init_fp) >> 1);
switch (decoder->norm) {
-
+
case VIDEO_MODE_NTSC:
vpx3220_write_fp_block(client, init_ntsc,
sizeof(init_ntsc) >> 1);
@@ -324,7 +324,7 @@ vpx3220_command (struct i2c_client *client,
case VIDEO_MODE_PAL:
vpx3220_write_fp_block(client, init_pal,
- sizeof(init_pal) >> 1);
+ sizeof(init_pal) >> 1);
break;
case VIDEO_MODE_SECAM:
vpx3220_write_fp_block(client, init_secam,
@@ -332,10 +332,10 @@ vpx3220_command (struct i2c_client *client,
break;
default:
vpx3220_write_fp_block(client, init_pal,
- sizeof(init_pal) >> 1);
+ sizeof(init_pal) >> 1);
break;
}
- }
+ }
break;
case DECODER_DUMP:
@@ -411,7 +411,7 @@ vpx3220_command (struct i2c_client *client,
/* Here we back up the input selection because it gets
overwritten when we fill the registers with the
- choosen video norm */
+ choosen video norm */
temp_input = vpx3220_fp_read(client, 0xf2);
dprintk(1, KERN_DEBUG "%s: DECODER_SET_NORM %d\n",
@@ -578,7 +578,7 @@ static unsigned short normal_i2c[] =
};
static unsigned short ignore = I2C_CLIENT_END;
-
+
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
.probe = &ignore,
@@ -661,7 +661,7 @@ vpx3220_detect_client (struct i2c_adapter *adapter,
break;
default:
dprintk(1,
- KERN_INFO
+ KERN_INFO
"%s: Wrong part number (0x%04x)\n",
__func__, pn);
kfree(client);
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
index b7b0afffd21..80ef8a1b8f6 100644
--- a/drivers/media/video/w9966.c
+++ b/drivers/media/video/w9966.c
@@ -26,7 +26,7 @@
Does any other model using the w9966 interface chip exist ?
Todo:
-
+
*Add a working EPP mode, since DMA ECP read isn't implemented
in the parport drivers. (That's why it's so sloow)
@@ -47,9 +47,9 @@
*Probably some bugs that I don't know of
Please support me by sending feedback!
-
+
Changes:
-
+
Alan Cox: Removed RGB mode for kernel merge, added THIS_MODULE
and owner support for newer module locks
*/
@@ -204,7 +204,7 @@ static struct video_device w9966_template = {
*/
-// Set camera phase flags, so we know what to uninit when terminating
+// Set camera phase flags, so we know what to uninit when terminating
static inline void w9966_setState(struct w9966_dev* cam, int mask, int val)
{
cam->dev_state = (cam->dev_state & ~mask) ^ val;
@@ -233,7 +233,7 @@ static inline void w9966_pdev_release(struct w9966_dev* cam)
parport_release(cam->pdev);
w9966_setState(cam, W9966_STATE_CLAIMED, 0);
}
-
+
// Read register from W9966 interface-chip
// Expects a claimed pdev
// -1 on error, else register data (byte)
@@ -242,7 +242,7 @@ static int w9966_rReg(struct w9966_dev* cam, int reg)
// ECP, read, regtransfer, REG, REG, REG, REG, REG
const unsigned char addr = 0x80 | (reg & 0x1f);
unsigned char val;
-
+
if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
return -1;
if (parport_write(cam->pport, &addr, 1) != 1)
@@ -263,7 +263,7 @@ static int w9966_wReg(struct w9966_dev* cam, int reg, int data)
// ECP, write, regtransfer, REG, REG, REG, REG, REG
const unsigned char addr = 0xc0 | (reg & 0x1f);
const unsigned char val = data;
-
+
if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
return -1;
if (parport_write(cam->pport, &addr, 1) != 1)
@@ -284,7 +284,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port)
{
if (cam->dev_state != 0)
return -1;
-
+
cam->pport = port;
cam->brightness = 128;
cam->contrast = 64;
@@ -302,7 +302,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port)
cam->ppmode = IEEE1284_MODE_EPP;
else
cam->ppmode = IEEE1284_MODE_ECP;
- break;
+ break;
case 1: // hw- or sw-ecp
cam->ppmode = IEEE1284_MODE_ECP;
break;
@@ -310,7 +310,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port)
cam->ppmode = IEEE1284_MODE_EPP;
break;
}
-
+
// Tell the parport driver that we exists
cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL);
if (cam->pdev == NULL) {
@@ -320,7 +320,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port)
w9966_setState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV);
w9966_pdev_claim(cam);
-
+
// Setup a default capture mode
if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) {
DPRINTF("w9966_setup() failed.\n");
@@ -333,11 +333,11 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port)
memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device));
cam->vdev.priv = cam;
- if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) == -1)
+ if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) == -1)
return -1;
-
+
w9966_setState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);
-
+
// All ok
printk(
"w9966cf: Found and initialized a webcam on %s.\n",
@@ -391,7 +391,7 @@ static int w9966_findlen(int near, int size, int maxlen)
// Only continue as long as we keep getting better values
if (err > besterr)
break;
-
+
besterr = err;
bestlen = len;
}
@@ -399,7 +399,7 @@ static int w9966_findlen(int near, int size, int maxlen)
return bestlen;
}
-// Modify capture window (if necessary)
+// Modify capture window (if necessary)
// and calculate downscaling
// Return -1 on error
static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsigned char* factor)
@@ -407,7 +407,7 @@ static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsig
int maxlen = max - min;
int len = *end - *beg + 1;
int newlen = w9966_findlen(len, size, maxlen);
- int err = newlen - len;
+ int err = newlen - len;
// Check for bad format
if (newlen > maxlen || newlen < size)
@@ -452,8 +452,8 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in
0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x71, 0xe7, 0x00, 0x00, 0xc0
};
-
-
+
+
if (w*h*2 > W9966_SRAMSIZE)
{
DPRINTF("capture window exceeds SRAM size!.\n");
@@ -469,9 +469,9 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in
cam->width = w;
cam->height = h;
- enh_s = 0;
+ enh_s = 0;
enh_e = w*h*2;
-
+
// Modify capture window if necessary and calculate downscaling
if (
w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 ||
@@ -482,14 +482,14 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in
"%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n",
w, h, x1, x2, y1, y2, scale_x&~0x80, scale_y&~0x80
);
-
+
// Setup registers
regs[0x00] = 0x00; // Set normal operation
regs[0x01] = 0x18; // Capture mode
regs[0x02] = scale_y; // V-scaling
regs[0x03] = scale_x; // H-scaling
-
- // Capture window
+
+ // Capture window
regs[0x04] = (x1 & 0x0ff); // X-start (8 low bits)
regs[0x05] = (x1 & 0x300)>>8; // X-start (2 high bits)
regs[0x06] = (y1 & 0x0ff); // Y-start (8 low bits)
@@ -499,7 +499,7 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in
regs[0x0a] = (y2 & 0x0ff); // Y-end (8 low bits)
regs[0x0c] = W9966_SRAMID; // SRAM-banks (1x 128kb)
-
+
// Enhancement layer
regs[0x0d] = (enh_s& 0x000ff); // Enh. start (0-7)
regs[0x0e] = (enh_s& 0x0ff00)>>8; // Enh. start (8-15)
@@ -515,7 +515,7 @@ static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, in
regs[0x19] = 0xff; // I/O port direction control
regs[0x1a] = 0xff; // I/O port data register
regs[0x1b] = 0x10; // ???
-
+
// SAA7111 chip settings
saa7111_regs[0x0a] = cam->brightness;
saa7111_regs[0x0b] = cam->contrast;
@@ -551,7 +551,7 @@ static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state)
cam->i2c_state |= W9966_I2C_W_DATA;
else
cam->i2c_state &= ~W9966_I2C_W_DATA;
-
+
w9966_wReg(cam, 0x18, cam->i2c_state);
udelay(5);
}
@@ -577,7 +577,7 @@ static inline int w9966_i2c_setscl(struct w9966_dev* cam, int state)
w9966_wReg(cam, 0x18, cam->i2c_state);
udelay(5);
-
+
// we go to high, we also expect the peripheral to ack.
if (state) {
timeout = jiffies + 100;
@@ -607,16 +607,16 @@ static int w9966_i2c_wbyte(struct w9966_dev* cam, int data)
w9966_i2c_setsda(cam, (data >> i) & 0x01);
if (w9966_i2c_setscl(cam, 1) == -1)
- return -1;
+ return -1;
w9966_i2c_setscl(cam, 0);
}
w9966_i2c_setsda(cam, 1);
-
+
if (w9966_i2c_setscl(cam, 1) == -1)
return -1;
w9966_i2c_setscl(cam, 0);
-
+
return 0;
}
@@ -626,8 +626,8 @@ static int w9966_i2c_wbyte(struct w9966_dev* cam, int data)
static int w9966_i2c_rbyte(struct w9966_dev* cam)
{
unsigned char data = 0x00;
- int i;
-
+ int i;
+
w9966_i2c_setsda(cam, 1);
for (i = 0; i < 8; i++)
@@ -637,7 +637,7 @@ static int w9966_i2c_rbyte(struct w9966_dev* cam)
data = data << 1;
if (w9966_i2c_getsda(cam))
data |= 0x01;
-
+
w9966_i2c_setscl(cam, 0);
}
return data;
@@ -673,11 +673,11 @@ static int w9966_rReg_i2c(struct w9966_dev* cam, int reg)
return -1;
w9966_i2c_setsda(cam, 0);
-
+
if (w9966_i2c_setscl(cam, 1) == -1)
return -1;
w9966_i2c_setsda(cam, 1);
-
+
return data;
}
#endif
@@ -699,7 +699,7 @@ static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data)
w9966_i2c_setsda(cam, 0);
if (w9966_i2c_setscl(cam, 1) == -1)
return -1;
-
+
w9966_i2c_setsda(cam, 1);
return 0;
@@ -714,7 +714,7 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file,
{
struct video_device *vdev = video_devdata(file);
struct w9966_dev *cam = vdev->priv;
-
+
switch(cmd)
{
case VIDIOCGCAP:
@@ -790,14 +790,14 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file,
struct video_picture *vpic = arg;
if (vpic->depth != 16 || vpic->palette != VIDEO_PALETTE_YUV422)
return -EINVAL;
-
+
cam->brightness = vpic->brightness >> 8;
cam->hue = (vpic->hue >> 8) - 128;
cam->color = vpic->colour >> 9;
cam->contrast = vpic->contrast >> 9;
w9966_pdev_claim(cam);
-
+
if (
w9966_wReg_i2c(cam, 0x0a, cam->brightness) == -1 ||
w9966_wReg_i2c(cam, 0x0b, cam->contrast) == -1 ||
@@ -807,7 +807,7 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file,
w9966_pdev_release(cam);
return -EIO;
}
-
+
w9966_pdev_release(cam);
return 0;
}
@@ -815,13 +815,13 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file,
{
int ret;
struct video_window *vwin = arg;
-
+
if (vwin->flags != 0)
return -EINVAL;
if (vwin->clipcount != 0)
return -EINVAL;
if (vwin->width < 2 || vwin->width > W9966_WND_MAX_W)
- return -EINVAL;
+ return -EINVAL;
if (vwin->height < 1 || vwin->height > W9966_WND_MAX_H)
return -EINVAL;
@@ -829,12 +829,12 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file,
w9966_pdev_claim(cam);
ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin->width, vwin->height);
w9966_pdev_release(cam);
-
+
if (ret != 0) {
DPRINTF("VIDIOCSWIN: w9966_setup() failed.\n");
return -EIO;
}
-
+
return 0;
}
case VIDIOCGWIN:
@@ -846,7 +846,7 @@ static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file,
return 0;
}
// Unimplemented
- case VIDIOCCAPTURE:
+ case VIDIOCCAPTURE:
case VIDIOCGFBUF:
case VIDIOCSFBUF:
case VIDIOCKEY:
@@ -877,17 +877,17 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf,
unsigned char __user *dest = (unsigned char __user *)buf;
unsigned long dleft = count;
unsigned char *tbuf;
-
+
// Why would anyone want more than this??
if (count > cam->width * cam->height * 2)
return -EINVAL;
-
+
w9966_pdev_claim(cam);
w9966_wReg(cam, 0x00, 0x02); // Reset ECP-FIFO buffer
w9966_wReg(cam, 0x00, 0x00); // Return to normal operation
w9966_wReg(cam, 0x01, 0x98); // Enable capture
- // write special capture-addr and negotiate into data transfer
+ // write special capture-addr and negotiate into data transfer
if (
(parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0 )||
(parport_write(cam->pport, &addr, 1) != 1 )||
@@ -906,7 +906,7 @@ static ssize_t w9966_v4l_read(struct file *file, char __user *buf,
while(dleft > 0)
{
unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft;
-
+
if (parport_read(cam->pport, tbuf, tsize) < tsize) {
count = -EFAULT;
goto out;
@@ -933,7 +933,7 @@ out:
static void w9966_attach(struct parport *port)
{
int i;
-
+
for (i = 0; i < W9966_MAXCAMS; i++)
{
if (w9966_cams[i].dev_state != 0) // Cam is already assigned
diff --git a/drivers/usb/media/w9968cf.c b/drivers/media/video/w9968cf.c
index b57dec3782e..20f211b55ad 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -71,39 +71,39 @@ MODULE_SUPPORTED_DEVICE("Video");
static int ovmod_load = W9968CF_OVMOD_LOAD;
static unsigned short simcams = W9968CF_SIMCAMS;
static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/
-static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] =
- W9968CF_PACKET_SIZE};
-static unsigned short max_buffers[] = {[0 ... W9968CF_MAX_DEVICES-1] =
- W9968CF_BUFFERS};
-static int double_buffer[] = {[0 ... W9968CF_MAX_DEVICES-1] =
- W9968CF_DOUBLE_BUFFER};
+static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] =
+ W9968CF_PACKET_SIZE};
+static unsigned short max_buffers[] = {[0 ... W9968CF_MAX_DEVICES-1] =
+ W9968CF_BUFFERS};
+static int double_buffer[] = {[0 ... W9968CF_MAX_DEVICES-1] =
+ W9968CF_DOUBLE_BUFFER};
static int clamping[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLAMPING};
-static unsigned short filter_type[]= {[0 ... W9968CF_MAX_DEVICES-1] =
- W9968CF_FILTER_TYPE};
+static unsigned short filter_type[]= {[0 ... W9968CF_MAX_DEVICES-1] =
+ W9968CF_FILTER_TYPE};
static int largeview[]= {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_LARGEVIEW};
-static unsigned short decompression[] = {[0 ... W9968CF_MAX_DEVICES-1] =
- W9968CF_DECOMPRESSION};
+static unsigned short decompression[] = {[0 ... W9968CF_MAX_DEVICES-1] =
+ W9968CF_DECOMPRESSION};
static int upscaling[]= {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_UPSCALING};
static unsigned short force_palette[] = {[0 ... W9968CF_MAX_DEVICES-1] = 0};
static int force_rgb[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_FORCE_RGB};
static int autobright[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_AUTOBRIGHT};
static int autoexp[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_AUTOEXP};
-static unsigned short lightfreq[] = {[0 ... W9968CF_MAX_DEVICES-1] =
- W9968CF_LIGHTFREQ};
+static unsigned short lightfreq[] = {[0 ... W9968CF_MAX_DEVICES-1] =
+ W9968CF_LIGHTFREQ};
static int bandingfilter[] = {[0 ... W9968CF_MAX_DEVICES-1]=
- W9968CF_BANDINGFILTER};
+ W9968CF_BANDINGFILTER};
static short clockdiv[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_CLOCKDIV};
static int backlight[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_BACKLIGHT};
static int mirror[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_MIRROR};
static int monochrome[] = {[0 ... W9968CF_MAX_DEVICES-1]=W9968CF_MONOCHROME};
-static unsigned int brightness[] = {[0 ... W9968CF_MAX_DEVICES-1] =
- W9968CF_BRIGHTNESS};
+static unsigned int brightness[] = {[0 ... W9968CF_MAX_DEVICES-1] =
+ W9968CF_BRIGHTNESS};
static unsigned int hue[] = {[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_HUE};
static unsigned int colour[]={[0 ... W9968CF_MAX_DEVICES-1] = W9968CF_COLOUR};
-static unsigned int contrast[] = {[0 ... W9968CF_MAX_DEVICES-1] =
- W9968CF_CONTRAST};
-static unsigned int whiteness[] = {[0 ... W9968CF_MAX_DEVICES-1] =
- W9968CF_WHITENESS};
+static unsigned int contrast[] = {[0 ... W9968CF_MAX_DEVICES-1] =
+ W9968CF_CONTRAST};
+static unsigned int whiteness[] = {[0 ... W9968CF_MAX_DEVICES-1] =
+ W9968CF_WHITENESS};
#ifdef W9968CF_DEBUG
static unsigned short debug = W9968CF_DEBUG_LEVEL;
static int specific_debug = W9968CF_SPECIFIC_DEBUG;
@@ -145,251 +145,251 @@ module_param(specific_debug, bool, 0644);
#endif
#ifdef CONFIG_KMOD
-MODULE_PARM_DESC(ovmod_load,
- "\n<0|1> Automatic 'ovcamchip' module loading."
- "\n0 disabled, 1 enabled."
- "\nIf enabled,'insmod' searches for the required 'ovcamchip'"
- "\nmodule in the system, according to its configuration, and"
- "\nattempts to load that module automatically. This action is"
- "\nperformed once as soon as the 'w9968cf' module is loaded"
- "\ninto memory."
- "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"."
- "\n");
+MODULE_PARM_DESC(ovmod_load,
+ "\n<0|1> Automatic 'ovcamchip' module loading."
+ "\n0 disabled, 1 enabled."
+ "\nIf enabled,'insmod' searches for the required 'ovcamchip'"
+ "\nmodule in the system, according to its configuration, and"
+ "\nattempts to load that module automatically. This action is"
+ "\nperformed once as soon as the 'w9968cf' module is loaded"
+ "\ninto memory."
+ "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"."
+ "\n");
#endif
-MODULE_PARM_DESC(simcams,
- "\n<n> Number of cameras allowed to stream simultaneously."
- "\nn may vary from 0 to "
- __MODULE_STRING(W9968CF_MAX_DEVICES)"."
- "\nDefault value is "__MODULE_STRING(W9968CF_SIMCAMS)"."
- "\n");
+MODULE_PARM_DESC(simcams,
+ "\n<n> Number of cameras allowed to stream simultaneously."
+ "\nn may vary from 0 to "
+ __MODULE_STRING(W9968CF_MAX_DEVICES)"."
+ "\nDefault value is "__MODULE_STRING(W9968CF_SIMCAMS)"."
+ "\n");
MODULE_PARM_DESC(video_nr,
- "\n<-1|n[,...]> Specify V4L minor mode number."
- "\n -1 = use next available (default)"
- "\n n = use minor number n (integer >= 0)"
- "\nYou can specify up to "__MODULE_STRING(W9968CF_MAX_DEVICES)
- " cameras this way."
- "\nFor example:"
- "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
- "\nthe second camera and use auto for the first"
- "\none and for every other camera."
- "\n");
+ "\n<-1|n[,...]> Specify V4L minor mode number."
+ "\n -1 = use next available (default)"
+ "\n n = use minor number n (integer >= 0)"
+ "\nYou can specify up to "__MODULE_STRING(W9968CF_MAX_DEVICES)
+ " cameras this way."
+ "\nFor example:"
+ "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
+ "\nthe second camera and use auto for the first"
+ "\none and for every other camera."
+ "\n");
MODULE_PARM_DESC(packet_size,
- "\n<n[,...]> Specify the maximum data payload"
- "\nsize in bytes for alternate settings, for each device."
- "\nn is scaled between 63 and 1023 "
- "(default is "__MODULE_STRING(W9968CF_PACKET_SIZE)")."
- "\n");
+ "\n<n[,...]> Specify the maximum data payload"
+ "\nsize in bytes for alternate settings, for each device."
+ "\nn is scaled between 63 and 1023 "
+ "(default is "__MODULE_STRING(W9968CF_PACKET_SIZE)")."
+ "\n");
MODULE_PARM_DESC(max_buffers,
- "\n<n[,...]> For advanced users."
- "\nSpecify the maximum number of video frame buffers"
- "\nto allocate for each device, from 2 to "
- __MODULE_STRING(W9968CF_MAX_BUFFERS)
- ". (default is "__MODULE_STRING(W9968CF_BUFFERS)")."
- "\n");
-MODULE_PARM_DESC(double_buffer,
- "\n<0|1[,...]> "
- "Hardware double buffering: 0 disabled, 1 enabled."
- "\nIt should be enabled if you want smooth video output: if"
- "\nyou obtain out of sync. video, disable it, or try to"
- "\ndecrease the 'clockdiv' module parameter value."
- "\nDefault value is "__MODULE_STRING(W9968CF_DOUBLE_BUFFER)
- " for every device."
- "\n");
-MODULE_PARM_DESC(clamping,
- "\n<0|1[,...]> Video data clamping: 0 disabled, 1 enabled."
- "\nDefault value is "__MODULE_STRING(W9968CF_CLAMPING)
- " for every device."
- "\n");
-MODULE_PARM_DESC(filter_type,
- "\n<0|1|2[,...]> Video filter type."
- "\n0 none, 1 (1-2-1) 3-tap filter, "
- "2 (2-3-6-3-2) 5-tap filter."
- "\nDefault value is "__MODULE_STRING(W9968CF_FILTER_TYPE)
- " for every device."
- "\nThe filter is used to reduce noise and aliasing artifacts"
- "\nproduced by the CCD or CMOS image sensor, and the scaling"
- " process."
- "\n");
-MODULE_PARM_DESC(largeview,
- "\n<0|1[,...]> Large view: 0 disabled, 1 enabled."
- "\nDefault value is "__MODULE_STRING(W9968CF_LARGEVIEW)
- " for every device."
- "\n");
-MODULE_PARM_DESC(upscaling,
- "\n<0|1[,...]> Software scaling (for non-compressed video):"
- "\n0 disabled, 1 enabled."
- "\nDisable it if you have a slow CPU or you don't have"
- " enough memory."
- "\nDefault value is "__MODULE_STRING(W9968CF_UPSCALING)
- " for every device."
- "\nIf 'w9968cf-vpp' is not present, this parameter is"
- " set to 0."
- "\n");
+ "\n<n[,...]> For advanced users."
+ "\nSpecify the maximum number of video frame buffers"
+ "\nto allocate for each device, from 2 to "
+ __MODULE_STRING(W9968CF_MAX_BUFFERS)
+ ". (default is "__MODULE_STRING(W9968CF_BUFFERS)")."
+ "\n");
+MODULE_PARM_DESC(double_buffer,
+ "\n<0|1[,...]> "
+ "Hardware double buffering: 0 disabled, 1 enabled."
+ "\nIt should be enabled if you want smooth video output: if"
+ "\nyou obtain out of sync. video, disable it, or try to"
+ "\ndecrease the 'clockdiv' module parameter value."
+ "\nDefault value is "__MODULE_STRING(W9968CF_DOUBLE_BUFFER)
+ " for every device."
+ "\n");
+MODULE_PARM_DESC(clamping,
+ "\n<0|1[,...]> Video data clamping: 0 disabled, 1 enabled."
+ "\nDefault value is "__MODULE_STRING(W9968CF_CLAMPING)
+ " for every device."
+ "\n");
+MODULE_PARM_DESC(filter_type,
+ "\n<0|1|2[,...]> Video filter type."
+ "\n0 none, 1 (1-2-1) 3-tap filter, "
+ "2 (2-3-6-3-2) 5-tap filter."
+ "\nDefault value is "__MODULE_STRING(W9968CF_FILTER_TYPE)
+ " for every device."
+ "\nThe filter is used to reduce noise and aliasing artifacts"
+ "\nproduced by the CCD or CMOS image sensor, and the scaling"
+ " process."
+ "\n");
+MODULE_PARM_DESC(largeview,
+ "\n<0|1[,...]> Large view: 0 disabled, 1 enabled."
+ "\nDefault value is "__MODULE_STRING(W9968CF_LARGEVIEW)
+ " for every device."
+ "\n");
+MODULE_PARM_DESC(upscaling,
+ "\n<0|1[,...]> Software scaling (for non-compressed video):"
+ "\n0 disabled, 1 enabled."
+ "\nDisable it if you have a slow CPU or you don't have"
+ " enough memory."
+ "\nDefault value is "__MODULE_STRING(W9968CF_UPSCALING)
+ " for every device."
+ "\nIf 'w9968cf-vpp' is not present, this parameter is"
+ " set to 0."
+ "\n");
MODULE_PARM_DESC(decompression,
- "\n<0|1|2[,...]> Software video decompression:"
- "\n- 0 disables decompression (doesn't allow formats needing"
- " decompression)"
- "\n- 1 forces decompression (allows formats needing"
- " decompression only);"
- "\n- 2 allows any permitted formats."
- "\nFormats supporting compressed video are YUV422P and"
- " YUV420P/YUV420 "
- "\nin any resolutions where both width and height are "
- "a multiple of 16."
- "\nDefault value is "__MODULE_STRING(W9968CF_DECOMPRESSION)
- " for every device."
- "\nIf 'w9968cf-vpp' is not present, forcing decompression is "
- "\nnot allowed; in this case this parameter is set to 2."
- "\n");
+ "\n<0|1|2[,...]> Software video decompression:"
+ "\n- 0 disables decompression (doesn't allow formats needing"
+ " decompression)"
+ "\n- 1 forces decompression (allows formats needing"
+ " decompression only);"
+ "\n- 2 allows any permitted formats."
+ "\nFormats supporting compressed video are YUV422P and"
+ " YUV420P/YUV420 "
+ "\nin any resolutions where both width and height are "
+ "a multiple of 16."
+ "\nDefault value is "__MODULE_STRING(W9968CF_DECOMPRESSION)
+ " for every device."
+ "\nIf 'w9968cf-vpp' is not present, forcing decompression is "
+ "\nnot allowed; in this case this parameter is set to 2."
+ "\n");
MODULE_PARM_DESC(force_palette,
- "\n<0"
- "|" __MODULE_STRING(VIDEO_PALETTE_UYVY)
- "|" __MODULE_STRING(VIDEO_PALETTE_YUV420)
- "|" __MODULE_STRING(VIDEO_PALETTE_YUV422P)
- "|" __MODULE_STRING(VIDEO_PALETTE_YUV420P)
- "|" __MODULE_STRING(VIDEO_PALETTE_YUYV)
- "|" __MODULE_STRING(VIDEO_PALETTE_YUV422)
- "|" __MODULE_STRING(VIDEO_PALETTE_GREY)
- "|" __MODULE_STRING(VIDEO_PALETTE_RGB555)
- "|" __MODULE_STRING(VIDEO_PALETTE_RGB565)
- "|" __MODULE_STRING(VIDEO_PALETTE_RGB24)
- "|" __MODULE_STRING(VIDEO_PALETTE_RGB32)
- "[,...]>"
- " Force picture palette."
- "\nIn order:"
- "\n- 0 allows any of the following formats:"
- "\n- UYVY 16 bpp - Original video, compression disabled"
- "\n- YUV420 12 bpp - Original video, compression enabled"
- "\n- YUV422P 16 bpp - Original video, compression enabled"
- "\n- YUV420P 12 bpp - Original video, compression enabled"
- "\n- YUVY 16 bpp - Software conversion from UYVY"
- "\n- YUV422 16 bpp - Software conversion from UYVY"
- "\n- GREY 8 bpp - Software conversion from UYVY"
- "\n- RGB555 16 bpp - Software conversion from UYVY"
- "\n- RGB565 16 bpp - Software conversion from UYVY"
- "\n- RGB24 24 bpp - Software conversion from UYVY"
- "\n- RGB32 32 bpp - Software conversion from UYVY"
- "\nWhen not 0, this parameter will override 'decompression'."
- "\nDefault value is 0 for every device."
- "\nInitial palette is "
- __MODULE_STRING(W9968CF_PALETTE_DECOMP_ON)"."
- "\nIf 'w9968cf-vpp' is not present, this parameter is"
- " set to 9 (UYVY)."
- "\n");
-MODULE_PARM_DESC(force_rgb,
- "\n<0|1[,...]> Read RGB video data instead of BGR:"
- "\n 1 = use RGB component ordering."
- "\n 0 = use BGR component ordering."
- "\nThis parameter has effect when using RGBX palettes only."
- "\nDefault value is "__MODULE_STRING(W9968CF_FORCE_RGB)
- " for every device."
- "\n");
+ "\n<0"
+ "|" __MODULE_STRING(VIDEO_PALETTE_UYVY)
+ "|" __MODULE_STRING(VIDEO_PALETTE_YUV420)
+ "|" __MODULE_STRING(VIDEO_PALETTE_YUV422P)
+ "|" __MODULE_STRING(VIDEO_PALETTE_YUV420P)
+ "|" __MODULE_STRING(VIDEO_PALETTE_YUYV)
+ "|" __MODULE_STRING(VIDEO_PALETTE_YUV422)
+ "|" __MODULE_STRING(VIDEO_PALETTE_GREY)
+ "|" __MODULE_STRING(VIDEO_PALETTE_RGB555)
+ "|" __MODULE_STRING(VIDEO_PALETTE_RGB565)
+ "|" __MODULE_STRING(VIDEO_PALETTE_RGB24)
+ "|" __MODULE_STRING(VIDEO_PALETTE_RGB32)
+ "[,...]>"
+ " Force picture palette."
+ "\nIn order:"
+ "\n- 0 allows any of the following formats:"
+ "\n- UYVY 16 bpp - Original video, compression disabled"
+ "\n- YUV420 12 bpp - Original video, compression enabled"
+ "\n- YUV422P 16 bpp - Original video, compression enabled"
+ "\n- YUV420P 12 bpp - Original video, compression enabled"
+ "\n- YUVY 16 bpp - Software conversion from UYVY"
+ "\n- YUV422 16 bpp - Software conversion from UYVY"
+ "\n- GREY 8 bpp - Software conversion from UYVY"
+ "\n- RGB555 16 bpp - Software conversion from UYVY"
+ "\n- RGB565 16 bpp - Software conversion from UYVY"
+ "\n- RGB24 24 bpp - Software conversion from UYVY"
+ "\n- RGB32 32 bpp - Software conversion from UYVY"
+ "\nWhen not 0, this parameter will override 'decompression'."
+ "\nDefault value is 0 for every device."
+ "\nInitial palette is "
+ __MODULE_STRING(W9968CF_PALETTE_DECOMP_ON)"."
+ "\nIf 'w9968cf-vpp' is not present, this parameter is"
+ " set to 9 (UYVY)."
+ "\n");
+MODULE_PARM_DESC(force_rgb,
+ "\n<0|1[,...]> Read RGB video data instead of BGR:"
+ "\n 1 = use RGB component ordering."
+ "\n 0 = use BGR component ordering."
+ "\nThis parameter has effect when using RGBX palettes only."
+ "\nDefault value is "__MODULE_STRING(W9968CF_FORCE_RGB)
+ " for every device."
+ "\n");
MODULE_PARM_DESC(autobright,
- "\n<0|1[,...]> Image sensor automatically changes brightness:"
- "\n 0 = no, 1 = yes"
- "\nDefault value is "__MODULE_STRING(W9968CF_AUTOBRIGHT)
- " for every device."
- "\n");
+ "\n<0|1[,...]> Image sensor automatically changes brightness:"
+ "\n 0 = no, 1 = yes"
+ "\nDefault value is "__MODULE_STRING(W9968CF_AUTOBRIGHT)
+ " for every device."
+ "\n");
MODULE_PARM_DESC(autoexp,
- "\n<0|1[,...]> Image sensor automatically changes exposure:"
- "\n 0 = no, 1 = yes"
- "\nDefault value is "__MODULE_STRING(W9968CF_AUTOEXP)
- " for every device."
- "\n");
+ "\n<0|1[,...]> Image sensor automatically changes exposure:"
+ "\n 0 = no, 1 = yes"
+ "\nDefault value is "__MODULE_STRING(W9968CF_AUTOEXP)
+ " for every device."
+ "\n");
MODULE_PARM_DESC(lightfreq,
- "\n<50|60[,...]> Light frequency in Hz:"
- "\n 50 for European and Asian lighting,"
- " 60 for American lighting."
- "\nDefault value is "__MODULE_STRING(W9968CF_LIGHTFREQ)
- " for every device."
- "\n");
+ "\n<50|60[,...]> Light frequency in Hz:"
+ "\n 50 for European and Asian lighting,"
+ " 60 for American lighting."
+ "\nDefault value is "__MODULE_STRING(W9968CF_LIGHTFREQ)
+ " for every device."
+ "\n");
MODULE_PARM_DESC(bandingfilter,
- "\n<0|1[,...]> Banding filter to reduce effects of"
- " fluorescent lighting:"
- "\n 0 disabled, 1 enabled."
- "\nThis filter tries to reduce the pattern of horizontal"
- "\nlight/dark bands caused by some (usually fluorescent)"
- " lighting."
- "\nDefault value is "__MODULE_STRING(W9968CF_BANDINGFILTER)
- " for every device."
- "\n");
+ "\n<0|1[,...]> Banding filter to reduce effects of"
+ " fluorescent lighting:"
+ "\n 0 disabled, 1 enabled."
+ "\nThis filter tries to reduce the pattern of horizontal"
+ "\nlight/dark bands caused by some (usually fluorescent)"
+ " lighting."
+ "\nDefault value is "__MODULE_STRING(W9968CF_BANDINGFILTER)
+ " for every device."
+ "\n");
MODULE_PARM_DESC(clockdiv,
- "\n<-1|n[,...]> "
- "Force pixel clock divisor to a specific value (for experts):"
- "\n n may vary from 0 to 127."
- "\n -1 for automatic value."
- "\nSee also the 'double_buffer' module parameter."
- "\nDefault value is "__MODULE_STRING(W9968CF_CLOCKDIV)
- " for every device."
- "\n");
+ "\n<-1|n[,...]> "
+ "Force pixel clock divisor to a specific value (for experts):"
+ "\n n may vary from 0 to 127."
+ "\n -1 for automatic value."
+ "\nSee also the 'double_buffer' module parameter."
+ "\nDefault value is "__MODULE_STRING(W9968CF_CLOCKDIV)
+ " for every device."
+ "\n");
MODULE_PARM_DESC(backlight,
- "\n<0|1[,...]> Objects are lit from behind:"
- "\n 0 = no, 1 = yes"
- "\nDefault value is "__MODULE_STRING(W9968CF_BACKLIGHT)
- " for every device."
- "\n");
+ "\n<0|1[,...]> Objects are lit from behind:"
+ "\n 0 = no, 1 = yes"
+ "\nDefault value is "__MODULE_STRING(W9968CF_BACKLIGHT)
+ " for every device."
+ "\n");
MODULE_PARM_DESC(mirror,
- "\n<0|1[,...]> Reverse image horizontally:"
- "\n 0 = no, 1 = yes"
- "\nDefault value is "__MODULE_STRING(W9968CF_MIRROR)
- " for every device."
- "\n");
+ "\n<0|1[,...]> Reverse image horizontally:"
+ "\n 0 = no, 1 = yes"
+ "\nDefault value is "__MODULE_STRING(W9968CF_MIRROR)
+ " for every device."
+ "\n");
MODULE_PARM_DESC(monochrome,
- "\n<0|1[,...]> Use image sensor as monochrome sensor:"
- "\n 0 = no, 1 = yes"
- "\nNot all the sensors support monochrome color."
- "\nDefault value is "__MODULE_STRING(W9968CF_MONOCHROME)
- " for every device."
- "\n");
-MODULE_PARM_DESC(brightness,
- "\n<n[,...]> Set picture brightness (0-65535)."
- "\nDefault value is "__MODULE_STRING(W9968CF_BRIGHTNESS)
- " for every device."
- "\nThis parameter has no effect if 'autobright' is enabled."
- "\n");
-MODULE_PARM_DESC(hue,
- "\n<n[,...]> Set picture hue (0-65535)."
- "\nDefault value is "__MODULE_STRING(W9968CF_HUE)
- " for every device."
- "\n");
-MODULE_PARM_DESC(colour,
- "\n<n[,...]> Set picture saturation (0-65535)."
- "\nDefault value is "__MODULE_STRING(W9968CF_COLOUR)
- " for every device."
- "\n");
-MODULE_PARM_DESC(contrast,
- "\n<n[,...]> Set picture contrast (0-65535)."
- "\nDefault value is "__MODULE_STRING(W9968CF_CONTRAST)
- " for every device."
- "\n");
-MODULE_PARM_DESC(whiteness,
- "\n<n[,...]> Set picture whiteness (0-65535)."
- "\nDefault value is "__MODULE_STRING(W9968CF_WHITENESS)
- " for every device."
- "\n");
+ "\n<0|1[,...]> Use image sensor as monochrome sensor:"
+ "\n 0 = no, 1 = yes"
+ "\nNot all the sensors support monochrome color."
+ "\nDefault value is "__MODULE_STRING(W9968CF_MONOCHROME)
+ " for every device."
+ "\n");
+MODULE_PARM_DESC(brightness,
+ "\n<n[,...]> Set picture brightness (0-65535)."
+ "\nDefault value is "__MODULE_STRING(W9968CF_BRIGHTNESS)
+ " for every device."
+ "\nThis parameter has no effect if 'autobright' is enabled."
+ "\n");
+MODULE_PARM_DESC(hue,
+ "\n<n[,...]> Set picture hue (0-65535)."
+ "\nDefault value is "__MODULE_STRING(W9968CF_HUE)
+ " for every device."
+ "\n");
+MODULE_PARM_DESC(colour,
+ "\n<n[,...]> Set picture saturation (0-65535)."
+ "\nDefault value is "__MODULE_STRING(W9968CF_COLOUR)
+ " for every device."
+ "\n");
+MODULE_PARM_DESC(contrast,
+ "\n<n[,...]> Set picture contrast (0-65535)."
+ "\nDefault value is "__MODULE_STRING(W9968CF_CONTRAST)
+ " for every device."
+ "\n");
+MODULE_PARM_DESC(whiteness,
+ "\n<n[,...]> Set picture whiteness (0-65535)."
+ "\nDefault value is "__MODULE_STRING(W9968CF_WHITENESS)
+ " for every device."
+ "\n");
#ifdef W9968CF_DEBUG
MODULE_PARM_DESC(debug,
- "\n<n> Debugging information level, from 0 to 6:"
- "\n0 = none (use carefully)"
- "\n1 = critical errors"
- "\n2 = significant informations"
- "\n3 = configuration or general messages"
- "\n4 = warnings"
- "\n5 = called functions"
- "\n6 = function internals"
- "\nLevel 5 and 6 are useful for testing only, when only "
- "one device is used."
- "\nDefault value is "__MODULE_STRING(W9968CF_DEBUG_LEVEL)"."
- "\n");
+ "\n<n> Debugging information level, from 0 to 6:"
+ "\n0 = none (use carefully)"
+ "\n1 = critical errors"
+ "\n2 = significant informations"
+ "\n3 = configuration or general messages"
+ "\n4 = warnings"
+ "\n5 = called functions"
+ "\n6 = function internals"
+ "\nLevel 5 and 6 are useful for testing only, when only "
+ "one device is used."
+ "\nDefault value is "__MODULE_STRING(W9968CF_DEBUG_LEVEL)"."
+ "\n");
MODULE_PARM_DESC(specific_debug,
- "\n<0|1> Enable or disable specific debugging messages:"
- "\n0 = print messages concerning every level"
- " <= 'debug' level."
- "\n1 = print messages concerning the level"
- " indicated by 'debug'."
- "\nDefault value is "
- __MODULE_STRING(W9968CF_SPECIFIC_DEBUG)"."
- "\n");
+ "\n<0|1> Enable or disable specific debugging messages:"
+ "\n0 = print messages concerning every level"
+ " <= 'debug' level."
+ "\n1 = print messages concerning the level"
+ " indicated by 'debug'."
+ "\nDefault value is "
+ __MODULE_STRING(W9968CF_SPECIFIC_DEBUG)"."
+ "\n");
#endif /* W9968CF_DEBUG */
@@ -406,7 +406,7 @@ static int w9968cf_mmap(struct file*, struct vm_area_struct*);
static int w9968cf_ioctl(struct inode*, struct file*, unsigned, unsigned long);
static ssize_t w9968cf_read(struct file*, char __user *, size_t, loff_t*);
static int w9968cf_v4l_ioctl(struct inode*, struct file*, unsigned int,
- void __user *);
+ void __user *);
/* USB-specific */
static int w9968cf_start_transfer(struct w9968cf_device*);
@@ -428,25 +428,25 @@ static int w9968cf_smbus_write_ack(struct w9968cf_device*);
static int w9968cf_smbus_read_ack(struct w9968cf_device*);
static int w9968cf_smbus_refresh_bus(struct w9968cf_device*);
static int w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam,
- u16 address, u8* value);
-static int w9968cf_i2c_adap_read_byte_data(struct w9968cf_device*, u16 address,
- u8 subaddress, u8* value);
+ u16 address, u8* value);
+static int w9968cf_i2c_adap_read_byte_data(struct w9968cf_device*, u16 address,
+ u8 subaddress, u8* value);
static int w9968cf_i2c_adap_write_byte(struct w9968cf_device*,
- u16 address, u8 subaddress);
+ u16 address, u8 subaddress);
static int w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device*,
- u16 address, u8 subaddress,
- u8 value);
+ u16 address, u8 subaddress,
+ u8 value);
/* I2C interface to kernel */
static int w9968cf_i2c_init(struct w9968cf_device*);
-static int w9968cf_i2c_smbus_xfer(struct i2c_adapter*, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size, union i2c_smbus_data*);
+static int w9968cf_i2c_smbus_xfer(struct i2c_adapter*, u16 addr,
+ unsigned short flags, char read_write,
+ u8 command, int size, union i2c_smbus_data*);
static u32 w9968cf_i2c_func(struct i2c_adapter*);
static int w9968cf_i2c_attach_inform(struct i2c_client*);
static int w9968cf_i2c_detach_inform(struct i2c_client*);
static int w9968cf_i2c_control(struct i2c_adapter*, unsigned int cmd,
- unsigned long arg);
+ unsigned long arg);
/* Memory management */
static void* rvmalloc(unsigned long size);
@@ -458,17 +458,17 @@ static int w9968cf_allocate_memory(struct w9968cf_device*);
static int w9968cf_sensor_set_control(struct w9968cf_device*,int cid,int val);
static int w9968cf_sensor_get_control(struct w9968cf_device*,int cid,int *val);
static int w9968cf_sensor_cmd(struct w9968cf_device*,
- unsigned int cmd, void *arg);
+ unsigned int cmd, void *arg);
static int w9968cf_sensor_init(struct w9968cf_device*);
static int w9968cf_sensor_update_settings(struct w9968cf_device*);
static int w9968cf_sensor_get_picture(struct w9968cf_device*);
-static int w9968cf_sensor_update_picture(struct w9968cf_device*,
- struct video_picture pict);
+static int w9968cf_sensor_update_picture(struct w9968cf_device*,
+ struct video_picture pict);
/* Other helper functions */
static void w9968cf_configure_camera(struct w9968cf_device*,struct usb_device*,
- enum w9968cf_model_id,
- const unsigned short dev_nr);
+ enum w9968cf_model_id,
+ const unsigned short dev_nr);
static void w9968cf_adjust_configuration(struct w9968cf_device*);
static int w9968cf_turn_on_led(struct w9968cf_device*);
static int w9968cf_init_chip(struct w9968cf_device*);
@@ -477,8 +477,8 @@ static inline u16 w9968cf_valid_depth(u16 palette);
static inline u8 w9968cf_need_decompression(u16 palette);
static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture);
static int w9968cf_set_window(struct w9968cf_device*, struct video_window);
-static int w9968cf_postprocess_frame(struct w9968cf_device*,
- struct w9968cf_frame_t*);
+static int w9968cf_postprocess_frame(struct w9968cf_device*,
+ struct w9968cf_frame_t*);
static int w9968cf_adjust_window_size(struct w9968cf_device*, u16* w, u16* h);
static void w9968cf_init_framelist(struct w9968cf_device*);
static void w9968cf_push_frame(struct w9968cf_device*, u8 f_num);
@@ -497,11 +497,11 @@ struct w9968cf_symbolic_list {
const char *name;
};
-/*--------------------------------------------------------------------------
+/*--------------------------------------------------------------------------
Returns the name of the matching element in the symbolic_list array. The
end of the list must be marked with an element that has a NULL name.
--------------------------------------------------------------------------*/
-static inline const char *
+static inline const char *
symbolic(struct w9968cf_symbolic_list list[], const int num)
{
int i;
@@ -568,7 +568,7 @@ static struct w9968cf_symbolic_list v4l1_plist[] = {
static struct w9968cf_symbolic_list decoder_errlist[] = {
{ W9968CF_DEC_ERR_CORRUPTED_DATA, "Corrupted data" },
{ W9968CF_DEC_ERR_BUF_OVERFLOW, "Buffer overflow" },
- { W9968CF_DEC_ERR_NO_SOI, "SOI marker not found" },
+ { W9968CF_DEC_ERR_NO_SOI, "SOI marker not found" },
{ W9968CF_DEC_ERR_NO_SOF0, "SOF0 marker not found" },
{ W9968CF_DEC_ERR_NO_SOS, "SOS marker not found" },
{ W9968CF_DEC_ERR_NO_EOI, "EOI marker not found" },
@@ -695,7 +695,7 @@ static int w9968cf_allocate_memory(struct w9968cf_device* cam)
bpp = (w9968cf_vpp) ? 4 : 2;
if (cam->upscaling)
vpp_bufsize = max(W9968CF_MAX_WIDTH*W9968CF_MAX_HEIGHT*bpp,
- cam->maxwidth*cam->maxheight*bpp);
+ cam->maxwidth*cam->maxheight*bpp);
else
vpp_bufsize = cam->maxwidth*cam->maxheight*bpp;
@@ -704,7 +704,7 @@ static int w9968cf_allocate_memory(struct w9968cf_device* cam)
if (!(cam->transfer_buffer[i] =
kzalloc(W9968CF_ISO_PACKETS*p_size, GFP_KERNEL))) {
DBG(1, "Couldn't allocate memory for the isochronous "
- "transfer buffers (%u bytes)",
+ "transfer buffers (%u bytes)",
p_size * W9968CF_ISO_PACKETS)
return -ENOMEM;
}
@@ -780,7 +780,7 @@ static int w9968cf_allocate_memory(struct w9968cf_device* cam)
of the next video frame; if an error is encountered in a packet, the entire
video frame is discarded and grabbed again.
If there are no requested frames in the FIFO list, packets are collected into
- a temporary buffer.
+ a temporary buffer.
--------------------------------------------------------------------------*/
static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs)
{
@@ -799,7 +799,7 @@ static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs)
/* "(*f)" will be used instead of "cam->frame_current" */
f = &cam->frame_current;
- /* If a frame has been requested and we are grabbing into
+ /* If a frame has been requested and we are grabbing into
the temporary frame, we'll switch to that requested frame */
if ((*f) == &cam->frame_tmp && *cam->requested_frame) {
if (cam->frame_tmp.status == F_GRABBING) {
@@ -808,7 +808,7 @@ static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs)
(*f)->length = cam->frame_tmp.length;
memcpy((*f)->buffer, cam->frame_tmp.buffer,
(*f)->length);
- DBG(6, "Switched from temp. frame to frame #%d",
+ DBG(6, "Switched from temp. frame to frame #%d",
(*f)->number)
}
}
@@ -850,7 +850,7 @@ static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs)
if (cam->vpp_flag & VPP_DECOMPRESSION) {
err = w9968cf_vpp->check_headers((*f)->buffer,
- (*f)->length);
+ (*f)->length);
if (err) {
DBG(4, "Skip corrupted frame: %s",
symbolic(decoder_errlist, err))
@@ -975,7 +975,7 @@ static int w9968cf_start_transfer(struct w9968cf_device* cam)
cam->frame_current = &cam->frame_tmp;
if (!(cam->vpp_flag & VPP_DECOMPRESSION))
- DBG(5, "Isochronous transfer size: %lu bytes/frame",
+ DBG(5, "Isochronous transfer size: %lu bytes/frame",
(unsigned long)t_size*2)
DBG(5, "Starting the isochronous transfer...")
@@ -992,7 +992,7 @@ static int w9968cf_start_transfer(struct w9968cf_device* cam)
usb_free_urb(cam->urb[j]);
}
DBG(1, "Couldn't send a transfer request to the "
- "USB core (error #%d, %s)", err,
+ "USB core (error #%d, %s)", err,
symbolic(urb_errlist, err))
return err;
}
@@ -1016,7 +1016,7 @@ static int w9968cf_stop_transfer(struct w9968cf_device* cam)
if (!cam->streaming)
return 0;
- /* This avoids race conditions with usb_submit_urb()
+ /* This avoids race conditions with usb_submit_urb()
in the URB completition handler */
spin_lock_irqsave(&cam->urb_lock, lock_flags);
cam->streaming = 0;
@@ -1050,7 +1050,7 @@ exit:
/*--------------------------------------------------------------------------
- Write a W9968CF register.
+ Write a W9968CF register.
Return 0 on success, -1 otherwise.
--------------------------------------------------------------------------*/
static int w9968cf_write_reg(struct w9968cf_device* cam, u16 value, u16 index)
@@ -1059,8 +1059,8 @@ static int w9968cf_write_reg(struct w9968cf_device* cam, u16 value, u16 index)
int res;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0,
- USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
- value, index, NULL, 0, W9968CF_USB_CTRL_TIMEOUT);
+ USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+ value, index, NULL, 0, W9968CF_USB_CTRL_TIMEOUT);
if (res < 0)
DBG(4, "Failed to write a register "
@@ -1072,7 +1072,7 @@ static int w9968cf_write_reg(struct w9968cf_device* cam, u16 value, u16 index)
/*--------------------------------------------------------------------------
- Read a W9968CF register.
+ Read a W9968CF register.
Return the register value on success, -1 otherwise.
--------------------------------------------------------------------------*/
static int w9968cf_read_reg(struct w9968cf_device* cam, u16 index)
@@ -1082,8 +1082,8 @@ static int w9968cf_read_reg(struct w9968cf_device* cam, u16 index)
int res;
res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 1,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, index, buff, 2, W9968CF_USB_CTRL_TIMEOUT);
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, index, buff, 2, W9968CF_USB_CTRL_TIMEOUT);
if (res < 0)
DBG(4, "Failed to read a register "
@@ -1107,8 +1107,8 @@ static int w9968cf_write_fsb(struct w9968cf_device* cam, u16* data)
value = *data++;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0,
- USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
- value, 0x06, data, 6, W9968CF_USB_CTRL_TIMEOUT);
+ USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+ value, 0x06, data, 6, W9968CF_USB_CTRL_TIMEOUT);
if (res < 0)
DBG(4, "Failed to write the FSB registers "
@@ -1287,9 +1287,9 @@ static int w9968cf_smbus_refresh_bus(struct w9968cf_device* cam)
/* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */
-static int
-w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam,
- u16 address, u8 subaddress,u8 value)
+static int
+w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam,
+ u16 address, u8 subaddress,u8 value)
{
u16* data = cam->data_buffer;
int err = 0;
@@ -1348,7 +1348,7 @@ w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam,
"value 0x%02X", address, subaddress, value)
else
DBG(5, "I2C write byte data failed, addr.0x%04X, "
- "subaddr.0x%02X, value 0x%02X",
+ "subaddr.0x%02X, value 0x%02X",
address, subaddress, value)
return err;
@@ -1356,10 +1356,10 @@ w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam,
/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */
-static int
-w9968cf_i2c_adap_read_byte_data(struct w9968cf_device* cam,
- u16 address, u8 subaddress,
- u8* value)
+static int
+w9968cf_i2c_adap_read_byte_data(struct w9968cf_device* cam,
+ u16 address, u8 subaddress,
+ u8* value)
{
int err = 0;
@@ -1384,7 +1384,7 @@ w9968cf_i2c_adap_read_byte_data(struct w9968cf_device* cam,
if (!err)
DBG(5, "I2C read byte data done, addr.0x%04X, "
- "subaddr.0x%02X, value 0x%02X",
+ "subaddr.0x%02X, value 0x%02X",
address, subaddress, *value)
else
DBG(5, "I2C read byte data failed, addr.0x%04X, "
@@ -1396,9 +1396,9 @@ w9968cf_i2c_adap_read_byte_data(struct w9968cf_device* cam,
/* SMBus protocol: S Addr+1 Rd [A] [Value] NA P */
-static int
+static int
w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam,
- u16 address, u8* value)
+ u16 address, u8* value)
{
int err = 0;
@@ -1411,7 +1411,7 @@ w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam,
err += w9968cf_smbus_read_byte(cam, value);
err += w9968cf_smbus_write_ack(cam);
err += w9968cf_smbus_stop(cam);
-
+
/* Serial data disable */
err += w9968cf_write_sb(cam, 0x0000);
@@ -1427,9 +1427,9 @@ w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam,
/* SMBus protocol: S Addr Wr [A] Value [A] P */
-static int
+static int
w9968cf_i2c_adap_write_byte(struct w9968cf_device* cam,
- u16 address, u8 value)
+ u16 address, u8 value)
{
DBG(4, "i2c_write_byte() is an unsupported transfer mode")
return -EINVAL;
@@ -1442,13 +1442,13 @@ w9968cf_i2c_adap_write_byte(struct w9968cf_device* cam,
****************************************************************************/
static int
-w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
- unsigned short flags, char read_write, u8 command,
- int size, union i2c_smbus_data *data)
+w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char read_write, u8 command,
+ int size, union i2c_smbus_data *data)
{
struct w9968cf_device* cam = i2c_get_adapdata(adapter);
u8 i;
- int err = 0;
+ int err = 0;
switch (addr) {
case OV6xx0_SID:
@@ -1464,20 +1464,20 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
addr <<= 1;
if (read_write == I2C_SMBUS_WRITE)
- err = w9968cf_i2c_adap_write_byte(cam, addr, command);
- else if (read_write == I2C_SMBUS_READ)
+ err = w9968cf_i2c_adap_write_byte(cam, addr, command);
+ else if (read_write == I2C_SMBUS_READ)
err = w9968cf_i2c_adap_read_byte(cam,addr,&data->byte);
} else if (size == I2C_SMBUS_BYTE_DATA) {
addr <<= 1;
if (read_write == I2C_SMBUS_WRITE)
- err = w9968cf_i2c_adap_fastwrite_byte_data(cam, addr,
- command, data->byte);
+ err = w9968cf_i2c_adap_fastwrite_byte_data(cam, addr,
+ command, data->byte);
else if (read_write == I2C_SMBUS_READ) {
for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) {
err = w9968cf_i2c_adap_read_byte_data(cam,addr,
- command, &data->byte);
+ command, &data->byte);
if (err) {
if (w9968cf_smbus_refresh_bus(cam)) {
err = -EIO;
@@ -1520,7 +1520,7 @@ static int w9968cf_i2c_attach_inform(struct i2c_client* client)
return err;
}
} else {
- DBG(4, "Rejected client [%s] with driver [%s]",
+ DBG(4, "Rejected client [%s] with driver [%s]",
client->name, client->driver->driver.name)
return -EINVAL;
}
@@ -1545,9 +1545,9 @@ static int w9968cf_i2c_detach_inform(struct i2c_client* client)
}
-static int
+static int
w9968cf_i2c_control(struct i2c_adapter* adapter, unsigned int cmd,
- unsigned long arg)
+ unsigned long arg)
{
return 0;
}
@@ -1625,12 +1625,12 @@ static int w9968cf_turn_on_led(struct w9968cf_device* cam)
static int w9968cf_init_chip(struct w9968cf_device* cam)
{
unsigned long hw_bufsize = cam->maxwidth*cam->maxheight*2,
- y0 = 0x0000,
- u0 = y0 + hw_bufsize/2,
- v0 = u0 + hw_bufsize/4,
- y1 = v0 + hw_bufsize/4,
- u1 = y1 + hw_bufsize/2,
- v1 = u1 + hw_bufsize/4;
+ y0 = 0x0000,
+ u0 = y0 + hw_bufsize/2,
+ v0 = u0 + hw_bufsize/4,
+ y1 = v0 + hw_bufsize/4,
+ u1 = y1 + hw_bufsize/2,
+ v1 = u1 + hw_bufsize/4;
int err = 0;
err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power off */
@@ -1762,7 +1762,7 @@ w9968cf_set_picture(struct w9968cf_device* cam, struct video_picture pict)
cam->vpp_flag = VPP_SWAP_YUV_BYTES;
hw_palette = VIDEO_PALETTE_UYVY;
break;
- /* Original video is used instead of RGBX palettes.
+ /* Original video is used instead of RGBX palettes.
Software conversion later. */
case VIDEO_PALETTE_GREY:
case VIDEO_PALETTE_RGB555:
@@ -1777,7 +1777,7 @@ w9968cf_set_picture(struct w9968cf_device* cam, struct video_picture pict)
}
/* NOTE: due to memory issues, it is better to disable the hardware
- double buffering during compression */
+ double buffering during compression */
if (cam->double_buffer && !(cam->vpp_flag & VPP_DECOMPRESSION))
reg_v |= 0x0080;
@@ -1832,8 +1832,8 @@ w9968cf_set_window(struct w9968cf_device* cam, struct video_window win)
#define __UNSC(x) ((x) >> 10)
/* Make sure we are using a supported resolution */
- if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width,
- (u16*)&win.height)))
+ if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width,
+ (u16*)&win.height)))
goto error;
/* Scaling factors */
@@ -1962,7 +1962,7 @@ w9968cf_set_window(struct w9968cf_device* cam, struct video_window win)
/* Settings changed, so we clear the frame buffers */
memset(cam->frame[0].buffer, 0, cam->nbuffers*cam->frame[0].size);
- DBG(4, "The capture area is %dx%d, Offset (x,y)=(%u,%u)",
+ DBG(4, "The capture area is %dx%d, Offset (x,y)=(%u,%u)",
win.width, win.height, win.x, win.y)
PDBGG("x=%u ,y=%u, w=%u, h=%u, ax=%u, ay=%u, s_win.x=%u, s_win.y=%u, "
@@ -1978,11 +1978,11 @@ error:
}
-/*--------------------------------------------------------------------------
+/*--------------------------------------------------------------------------
Adjust the asked values for window width and height.
Return 0 on success, -1 otherwise.
--------------------------------------------------------------------------*/
-static int
+static int
w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height)
{
u16 maxw, maxh;
@@ -1992,10 +1992,10 @@ w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height)
maxw = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) &&
w9968cf_vpp ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth)
- : cam->maxwidth;
+ : cam->maxwidth;
maxh = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) &&
w9968cf_vpp ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight)
- : cam->maxheight;
+ : cam->maxheight;
if (*width > maxw)
*width = maxw;
@@ -2054,7 +2054,7 @@ static void w9968cf_push_frame(struct w9968cf_device* cam, u8 f_num)
Read, store and remove the first pointer in the FIFO list of requested
frames. This function is called in interrupt context.
--------------------------------------------------------------------------*/
-static void
+static void
w9968cf_pop_frame(struct w9968cf_device* cam, struct w9968cf_frame_t** framep)
{
u8 i;
@@ -2078,9 +2078,9 @@ w9968cf_pop_frame(struct w9968cf_device* cam, struct w9968cf_frame_t** framep)
High-level video post-processing routine on grabbed frames.
Return 0 on success, a negative number otherwise.
--------------------------------------------------------------------------*/
-static int
-w9968cf_postprocess_frame(struct w9968cf_device* cam,
- struct w9968cf_frame_t* fr)
+static int
+w9968cf_postprocess_frame(struct w9968cf_device* cam,
+ struct w9968cf_frame_t* fr)
{
void *pIn = fr->buffer, *pOut = cam->frame_vpp.buffer, *tmp;
u16 w = cam->window.width,
@@ -2127,7 +2127,7 @@ w9968cf_postprocess_frame(struct w9968cf_device* cam,
w9968cf_vpp->uyvy_to_rgbx(pIn, fr->length, pOut, fmt, rgb);
fr->length = (w*h*d)/8;
_PSWAP(pIn, pOut)
- DBG(6, "UYVY-16bit to %s conversion done",
+ DBG(6, "UYVY-16bit to %s conversion done",
symbolic(v4l1_plist, fmt))
}
@@ -2143,7 +2143,7 @@ w9968cf_postprocess_frame(struct w9968cf_device* cam,
* Image sensor control routines *
****************************************************************************/
-static int
+static int
w9968cf_sensor_set_control(struct w9968cf_device* cam, int cid, int val)
{
struct ovcamchip_control ctl;
@@ -2158,7 +2158,7 @@ w9968cf_sensor_set_control(struct w9968cf_device* cam, int cid, int val)
}
-static int
+static int
w9968cf_sensor_get_control(struct w9968cf_device* cam, int cid, int* val)
{
struct ovcamchip_control ctl;
@@ -2198,38 +2198,38 @@ static int w9968cf_sensor_update_settings(struct w9968cf_device* cam)
int err = 0;
/* Auto brightness */
- err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOBRIGHT,
- cam->auto_brt);
+ err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOBRIGHT,
+ cam->auto_brt);
if (err)
return err;
/* Auto exposure */
- err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOEXP,
- cam->auto_exp);
+ err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_AUTOEXP,
+ cam->auto_exp);
if (err)
return err;
/* Banding filter */
- err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BANDFILT,
- cam->bandfilt);
+ err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BANDFILT,
+ cam->bandfilt);
if (err)
return err;
/* Light frequency */
err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_FREQ,
- cam->lightfreq);
+ cam->lightfreq);
if (err)
return err;
/* Back light */
err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BACKLIGHT,
- cam->backlight);
+ cam->backlight);
if (err)
return err;
/* Mirror */
err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_MIRROR,
- cam->mirror);
+ cam->mirror);
if (err)
return err;
@@ -2281,15 +2281,15 @@ static int w9968cf_sensor_get_picture(struct w9968cf_device* cam)
Returns: 0 on success, a negative number otherwise.
--------------------------------------------------------------------------*/
static int
-w9968cf_sensor_update_picture(struct w9968cf_device* cam,
- struct video_picture pict)
+w9968cf_sensor_update_picture(struct w9968cf_device* cam,
+ struct video_picture pict)
{
int err = 0;
if ((!cam->sensor_initialized)
|| pict.contrast != cam->picture.contrast) {
err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_CONT,
- pict.contrast);
+ pict.contrast);
if (err)
goto fail;
DBG(4, "Contrast changed from %u to %u",
@@ -2297,10 +2297,10 @@ w9968cf_sensor_update_picture(struct w9968cf_device* cam,
cam->picture.contrast = pict.contrast;
}
- if (((!cam->sensor_initialized) ||
+ if (((!cam->sensor_initialized) ||
pict.brightness != cam->picture.brightness) && (!cam->auto_brt)) {
- err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BRIGHT,
- pict.brightness);
+ err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_BRIGHT,
+ pict.brightness);
if (err)
goto fail;
DBG(4, "Brightness changed from %u to %u",
@@ -2309,8 +2309,8 @@ w9968cf_sensor_update_picture(struct w9968cf_device* cam,
}
if ((!cam->sensor_initialized) || pict.colour != cam->picture.colour) {
- err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_SAT,
- pict.colour);
+ err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_SAT,
+ pict.colour);
if (err)
goto fail;
DBG(4, "Colour changed from %u to %u",
@@ -2319,8 +2319,8 @@ w9968cf_sensor_update_picture(struct w9968cf_device* cam,
}
if ((!cam->sensor_initialized) || pict.hue != cam->picture.hue) {
- err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_HUE,
- pict.hue);
+ err = w9968cf_sensor_set_control(cam, OVCAMCHIP_CID_HUE,
+ pict.hue);
if (err)
goto fail;
DBG(4, "Hue changed from %u to %u",
@@ -2349,12 +2349,12 @@ static int w9968cf_sensor_init(struct w9968cf_device* cam)
{
int err = 0;
- if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_INITIALIZE,
- &cam->monochrome)))
+ if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_INITIALIZE,
+ &cam->monochrome)))
goto error;
- if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_Q_SUBTYPE,
- &cam->sensor)))
+ if ((err = w9968cf_sensor_cmd(cam, OVCAMCHIP_CMD_Q_SUBTYPE,
+ &cam->sensor)))
goto error;
/* NOTE: Make sure width and height are a multiple of 16 */
@@ -2416,14 +2416,14 @@ error:
/*--------------------------------------------------------------------------
Fill some basic fields in the main device data structure.
- This function is called once on w9968cf_usb_probe() for each recognized
+ This function is called once on w9968cf_usb_probe() for each recognized
camera.
--------------------------------------------------------------------------*/
static void
w9968cf_configure_camera(struct w9968cf_device* cam,
- struct usb_device* udev,
- enum w9968cf_model_id mod_id,
- const unsigned short dev_nr)
+ struct usb_device* udev,
+ enum w9968cf_model_id mod_id,
+ const unsigned short dev_nr)
{
mutex_init(&cam->fileop_mutex);
init_waitqueue_head(&cam->open);
@@ -2444,60 +2444,60 @@ w9968cf_configure_camera(struct w9968cf_device* cam,
packet_size[dev_nr] < wMaxPacketSize[cam->altsetting-1];
cam->altsetting++);
- cam->max_buffers = (max_buffers[dev_nr] < 2 ||
- max_buffers[dev_nr] > W9968CF_MAX_BUFFERS)
- ? W9968CF_BUFFERS : (u8)max_buffers[dev_nr];
+ cam->max_buffers = (max_buffers[dev_nr] < 2 ||
+ max_buffers[dev_nr] > W9968CF_MAX_BUFFERS)
+ ? W9968CF_BUFFERS : (u8)max_buffers[dev_nr];
- cam->double_buffer = (double_buffer[dev_nr] == 0 ||
- double_buffer[dev_nr] == 1)
- ? (u8)double_buffer[dev_nr]:W9968CF_DOUBLE_BUFFER;
+ cam->double_buffer = (double_buffer[dev_nr] == 0 ||
+ double_buffer[dev_nr] == 1)
+ ? (u8)double_buffer[dev_nr]:W9968CF_DOUBLE_BUFFER;
cam->clamping = (clamping[dev_nr] == 0 || clamping[dev_nr] == 1)
- ? (u8)clamping[dev_nr] : W9968CF_CLAMPING;
-
+ ? (u8)clamping[dev_nr] : W9968CF_CLAMPING;
+
cam->filter_type = (filter_type[dev_nr] == 0 ||
- filter_type[dev_nr] == 1 ||
- filter_type[dev_nr] == 2)
- ? (u8)filter_type[dev_nr] : W9968CF_FILTER_TYPE;
+ filter_type[dev_nr] == 1 ||
+ filter_type[dev_nr] == 2)
+ ? (u8)filter_type[dev_nr] : W9968CF_FILTER_TYPE;
cam->capture = 1;
cam->largeview = (largeview[dev_nr] == 0 || largeview[dev_nr] == 1)
- ? (u8)largeview[dev_nr] : W9968CF_LARGEVIEW;
+ ? (u8)largeview[dev_nr] : W9968CF_LARGEVIEW;
- cam->decompression = (decompression[dev_nr] == 0 ||
- decompression[dev_nr] == 1 ||
- decompression[dev_nr] == 2)
- ? (u8)decompression[dev_nr]:W9968CF_DECOMPRESSION;
+ cam->decompression = (decompression[dev_nr] == 0 ||
+ decompression[dev_nr] == 1 ||
+ decompression[dev_nr] == 2)
+ ? (u8)decompression[dev_nr]:W9968CF_DECOMPRESSION;
- cam->upscaling = (upscaling[dev_nr] == 0 ||
- upscaling[dev_nr] == 1)
- ? (u8)upscaling[dev_nr] : W9968CF_UPSCALING;
+ cam->upscaling = (upscaling[dev_nr] == 0 ||
+ upscaling[dev_nr] == 1)
+ ? (u8)upscaling[dev_nr] : W9968CF_UPSCALING;
cam->auto_brt = (autobright[dev_nr] == 0 || autobright[dev_nr] == 1)
- ? (u8)autobright[dev_nr] : W9968CF_AUTOBRIGHT;
+ ? (u8)autobright[dev_nr] : W9968CF_AUTOBRIGHT;
cam->auto_exp = (autoexp[dev_nr] == 0 || autoexp[dev_nr] == 1)
- ? (u8)autoexp[dev_nr] : W9968CF_AUTOEXP;
+ ? (u8)autoexp[dev_nr] : W9968CF_AUTOEXP;
cam->lightfreq = (lightfreq[dev_nr] == 50 || lightfreq[dev_nr] == 60)
- ? (u8)lightfreq[dev_nr] : W9968CF_LIGHTFREQ;
+ ? (u8)lightfreq[dev_nr] : W9968CF_LIGHTFREQ;
- cam->bandfilt = (bandingfilter[dev_nr] == 0 ||
- bandingfilter[dev_nr] == 1)
- ? (u8)bandingfilter[dev_nr] : W9968CF_BANDINGFILTER;
+ cam->bandfilt = (bandingfilter[dev_nr] == 0 ||
+ bandingfilter[dev_nr] == 1)
+ ? (u8)bandingfilter[dev_nr] : W9968CF_BANDINGFILTER;
cam->backlight = (backlight[dev_nr] == 0 || backlight[dev_nr] == 1)
- ? (u8)backlight[dev_nr] : W9968CF_BACKLIGHT;
+ ? (u8)backlight[dev_nr] : W9968CF_BACKLIGHT;
cam->clockdiv = (clockdiv[dev_nr] == -1 || clockdiv[dev_nr] >= 0)
- ? (s8)clockdiv[dev_nr] : W9968CF_CLOCKDIV;
+ ? (s8)clockdiv[dev_nr] : W9968CF_CLOCKDIV;
cam->mirror = (mirror[dev_nr] == 0 || mirror[dev_nr] == 1)
- ? (u8)mirror[dev_nr] : W9968CF_MIRROR;
+ ? (u8)mirror[dev_nr] : W9968CF_MIRROR;
cam->monochrome = (monochrome[dev_nr] == 0 || monochrome[dev_nr] == 1)
- ? monochrome[dev_nr] : W9968CF_MONOCHROME;
+ ? monochrome[dev_nr] : W9968CF_MONOCHROME;
cam->picture.brightness = (u16)brightness[dev_nr];
cam->picture.hue = (u16)hue[dev_nr];
@@ -2519,7 +2519,7 @@ w9968cf_configure_camera(struct w9968cf_device* cam,
cam->picture.depth = w9968cf_valid_depth(cam->picture.palette);
cam->force_rgb = (force_rgb[dev_nr] == 0 || force_rgb[dev_nr] == 1)
- ? (u8)force_rgb[dev_nr] : W9968CF_FORCE_RGB;
+ ? (u8)force_rgb[dev_nr] : W9968CF_FORCE_RGB;
cam->window.x = 0;
cam->window.y = 0;
@@ -2531,16 +2531,16 @@ w9968cf_configure_camera(struct w9968cf_device* cam,
DBG(3, "%s configured with settings #%u:",
symbolic(camlist, cam->id), dev_nr)
-
+
DBG(3, "- Data packet size for USB isochrnous transfer: %u bytes",
wMaxPacketSize[cam->altsetting-1])
-
+
DBG(3, "- Number of requested video frame buffers: %u",
cam->max_buffers)
if (cam->double_buffer)
DBG(3, "- Hardware double buffering enabled")
- else
+ else
DBG(3, "- Hardware double buffering disabled")
if (cam->filter_type == 0)
@@ -2648,7 +2648,7 @@ static void w9968cf_adjust_configuration(struct w9968cf_device* cam)
/*--------------------------------------------------------------------------
Release the resources used by the driver.
- This function is called on disconnect
+ This function is called on disconnect
(or on close if deallocation has been deferred)
--------------------------------------------------------------------------*/
static void w9968cf_release_resources(struct w9968cf_device* cam)
@@ -2706,8 +2706,8 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
}
mutex_unlock(&cam->dev_mutex);
err = wait_event_interruptible_exclusive(cam->open,
- cam->disconnected ||
- !cam->users);
+ cam->disconnected ||
+ !cam->users);
if (err) {
up_read(&w9968cf_disconnect);
return err;
@@ -2820,9 +2820,9 @@ w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
w9968cf_push_frame(cam, 1);
err = wait_event_interruptible(cam->wait_queue,
- cam->frame[0].status == F_READY ||
- cam->frame[1].status == F_READY ||
- cam->disconnected);
+ cam->frame[0].status == F_READY ||
+ cam->frame[1].status == F_READY ||
+ cam->disconnected);
if (err) {
mutex_unlock(&cam->fileop_mutex);
return err;
@@ -2859,12 +2859,12 @@ w9968cf_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma)
{
struct w9968cf_device* cam = (struct w9968cf_device*)
- video_get_drvdata(video_devdata(filp));
+ video_get_drvdata(video_devdata(filp));
unsigned long vsize = vma->vm_end - vma->vm_start,
- psize = cam->nbuffers * cam->frame[0].size,
- start = vma->vm_start,
- pos = (unsigned long)cam->frame[0].buffer,
- page;
+ psize = cam->nbuffers * cam->frame[0].size,
+ start = vma->vm_start,
+ pos = (unsigned long)cam->frame[0].buffer,
+ page;
if (cam->disconnected) {
DBG(2, "Device not present")
@@ -2898,7 +2898,7 @@ static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma)
static int
w9968cf_ioctl(struct inode* inode, struct file* filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct w9968cf_device* cam;
int err;
@@ -2928,21 +2928,21 @@ w9968cf_ioctl(struct inode* inode, struct file* filp,
static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
- unsigned int cmd, void __user * arg)
+ unsigned int cmd, void __user * arg)
{
struct w9968cf_device* cam;
const char* v4l1_ioctls[] = {
- "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER",
+ "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER",
"GPICT", "SPICT", "CCAPTURE", "GWIN", "SWIN", "GFBUF",
"SFBUF", "KEY", "GFREQ", "SFREQ", "GAUDIO", "SAUDIO",
"SYNC", "MCAPTURE", "GMBUF", "GUNIT", "GCAPTURE", "SCAPTURE",
- "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", "SMICROCODE",
- "GVBIFMT", "SVBIFMT"
+ "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", "SMICROCODE",
+ "GVBIFMT", "SVBIFMT"
};
#define V4L1_IOCTL(cmd) \
- ((_IOC_NR((cmd)) < ARRAY_SIZE(v4l1_ioctls)) ? \
- v4l1_ioctls[_IOC_NR((cmd))] : "?")
+ ((_IOC_NR((cmd)) < ARRAY_SIZE(v4l1_ioctls)) ? \
+ v4l1_ioctls[_IOC_NR((cmd))] : "?")
cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
@@ -2957,14 +2957,14 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
.minwidth = cam->minwidth,
.minheight = cam->minheight,
};
- sprintf(cap.name, "W996[87]CF USB Camera #%d",
- cam->v4ldev->minor);
+ sprintf(cap.name, "W996[87]CF USB Camera #%d",
+ cam->v4ldev->minor);
cap.maxwidth = (cam->upscaling && w9968cf_vpp)
- ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth)
- : cam->maxwidth;
+ ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth)
+ : cam->maxwidth;
cap.maxheight = (cam->upscaling && w9968cf_vpp)
- ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight)
- : cam->maxheight;
+ ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight)
+ : cam->maxheight;
if (copy_to_user(arg, &cap, sizeof(cap)))
return -EFAULT;
@@ -3029,7 +3029,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
if (copy_from_user(&pict, arg, sizeof(pict)))
return -EFAULT;
- if ( (cam->force_palette || !w9968cf_vpp)
+ if ( (cam->force_palette || !w9968cf_vpp)
&& pict.palette != cam->picture.palette ) {
DBG(4, "Palette %s rejected: only %s is allowed",
symbolic(v4l1_plist, pict.palette),
@@ -3046,24 +3046,24 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
if (!cam->force_palette) {
if (cam->decompression == 0) {
if (w9968cf_need_decompression(pict.palette)) {
- DBG(4, "Decompression disabled: palette %s is not "
- "allowed. VIDIOCSPICT failed",
- symbolic(v4l1_plist, pict.palette))
- return -EINVAL;
+ DBG(4, "Decompression disabled: palette %s is not "
+ "allowed. VIDIOCSPICT failed",
+ symbolic(v4l1_plist, pict.palette))
+ return -EINVAL;
}
} else if (cam->decompression == 1) {
if (!w9968cf_need_decompression(pict.palette)) {
- DBG(4, "Decompression forced: palette %s is not "
- "allowed. VIDIOCSPICT failed",
- symbolic(v4l1_plist, pict.palette))
- return -EINVAL;
+ DBG(4, "Decompression forced: palette %s is not "
+ "allowed. VIDIOCSPICT failed",
+ symbolic(v4l1_plist, pict.palette))
+ return -EINVAL;
}
}
}
if (pict.depth != w9968cf_valid_depth(pict.palette)) {
DBG(4, "Requested depth %u bpp is not valid for %s "
- "palette: ignored and changed to %u bpp",
+ "palette: ignored and changed to %u bpp",
pict.depth, symbolic(v4l1_plist, pict.palette),
w9968cf_valid_depth(pict.palette))
pict.depth = w9968cf_valid_depth(pict.palette);
@@ -3074,9 +3074,9 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
|| cam->frame_current->queued) {
err = wait_event_interruptible
( cam->wait_queue,
- cam->disconnected ||
- (!*cam->requested_frame &&
- !cam->frame_current->queued) );
+ cam->disconnected ||
+ (!*cam->requested_frame &&
+ !cam->frame_current->queued) );
if (err)
return err;
if (cam->disconnected)
@@ -3116,7 +3116,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
return -EINVAL;
if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width,
- (u16*)&win.height))) {
+ (u16*)&win.height))) {
DBG(4, "Resolution not supported (%ux%u). "
"VIDIOCSWIN failed", win.width, win.height)
return err;
@@ -3130,9 +3130,9 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
|| cam->frame_current->queued) {
err = wait_event_interruptible
( cam->wait_queue,
- cam->disconnected ||
- (!*cam->requested_frame &&
- !cam->frame_current->queued) );
+ cam->disconnected ||
+ (!*cam->requested_frame &&
+ !cam->frame_current->queued) );
if (err)
return err;
if (cam->disconnected)
@@ -3175,7 +3175,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
mbuf.frames = cam->nbuffers;
for (i = 0; i < cam->nbuffers; i++)
mbuf.offsets[i] = (unsigned long)cam->frame[i].buffer -
- (unsigned long)cam->frame[0].buffer;
+ (unsigned long)cam->frame[0].buffer;
if (copy_to_user(arg, &mbuf, sizeof(mbuf)))
return -EFAULT;
@@ -3194,7 +3194,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
return -EFAULT;
DBG(6, "VIDIOCMCAPTURE called: frame #%u, format=%s, %dx%d",
- mmap.frame, symbolic(v4l1_plist, mmap.format),
+ mmap.frame, symbolic(v4l1_plist, mmap.format),
mmap.width, mmap.height)
if (mmap.frame >= cam->nbuffers) {
@@ -3203,7 +3203,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
return -EINVAL;
}
- if (mmap.format!=cam->picture.palette &&
+ if (mmap.format!=cam->picture.palette &&
(cam->force_palette || !w9968cf_vpp)) {
DBG(4, "Palette %s rejected: only %s is allowed",
symbolic(v4l1_plist, mmap.format),
@@ -3213,7 +3213,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
if (!w9968cf_valid_palette(mmap.format)) {
DBG(4, "Palette %s not supported. "
- "VIDIOCMCAPTURE failed",
+ "VIDIOCMCAPTURE failed",
symbolic(v4l1_plist, mmap.format))
return -EINVAL;
}
@@ -3221,23 +3221,23 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
if (!cam->force_palette) {
if (cam->decompression == 0) {
if (w9968cf_need_decompression(mmap.format)) {
- DBG(4, "Decompression disabled: palette %s is not "
- "allowed. VIDIOCSPICT failed",
- symbolic(v4l1_plist, mmap.format))
- return -EINVAL;
+ DBG(4, "Decompression disabled: palette %s is not "
+ "allowed. VIDIOCSPICT failed",
+ symbolic(v4l1_plist, mmap.format))
+ return -EINVAL;
}
} else if (cam->decompression == 1) {
if (!w9968cf_need_decompression(mmap.format)) {
- DBG(4, "Decompression forced: palette %s is not "
- "allowed. VIDIOCSPICT failed",
- symbolic(v4l1_plist, mmap.format))
- return -EINVAL;
+ DBG(4, "Decompression forced: palette %s is not "
+ "allowed. VIDIOCSPICT failed",
+ symbolic(v4l1_plist, mmap.format))
+ return -EINVAL;
}
}
}
- if ((err = w9968cf_adjust_window_size(cam, (u16*)&mmap.width,
- (u16*)&mmap.height))) {
+ if ((err = w9968cf_adjust_window_size(cam, (u16*)&mmap.width,
+ (u16*)&mmap.height))) {
DBG(4, "Resolution not supported (%dx%d). "
"VIDIOCMCAPTURE failed",
mmap.width, mmap.height)
@@ -3258,12 +3258,12 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
DBG(6, "VIDIOCMCAPTURE. Change settings for "
"frame #%u: %dx%d, format %s. Wait...",
mmap.frame, mmap.width, mmap.height,
- symbolic(v4l1_plist, mmap.format))
+ symbolic(v4l1_plist, mmap.format))
err = wait_event_interruptible
( cam->wait_queue,
- cam->disconnected ||
- (!*cam->requested_frame &&
- !cam->frame_current->queued) );
+ cam->disconnected ||
+ (!*cam->requested_frame &&
+ !cam->frame_current->queued) );
if (err)
return err;
if (cam->disconnected)
@@ -3280,7 +3280,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
goto ioctl_fail;
/* This before set_window */
- if (w9968cf_set_picture(cam, pict))
+ if (w9968cf_set_picture(cam, pict))
goto ioctl_fail;
if (w9968cf_set_window(cam, win))
@@ -3292,10 +3292,10 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
} else if (fr->queued) {
DBG(6, "Wait until frame #%u is free", mmap.frame)
-
- err = wait_event_interruptible(cam->wait_queue,
- cam->disconnected ||
- (!fr->queued));
+
+ err = wait_event_interruptible(cam->wait_queue,
+ cam->disconnected ||
+ (!fr->queued));
if (err)
return err;
if (cam->disconnected)
@@ -3335,9 +3335,9 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
}
case F_ERROR:
case F_GRABBING:
- err = wait_event_interruptible(cam->wait_queue,
- (fr->status == F_READY)
- || cam->disconnected);
+ err = wait_event_interruptible(cam->wait_queue,
+ (fr->status == F_READY)
+ || cam->disconnected);
if (err)
return err;
if (cam->disconnected)
@@ -3439,7 +3439,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
DBG(4, "Unsupported V4L1 IOCtl: VIDIOC%s "
"(type 0x%01X, "
"n. 0x%01X, "
- "dir. 0x%01X, "
+ "dir. 0x%01X, "
"size 0x%02X)",
V4L1_IOCTL(cmd),
_IOC_TYPE(cmd),_IOC_NR(cmd),_IOC_DIR(cmd),_IOC_SIZE(cmd))
@@ -3499,13 +3499,13 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct)
mod_id = W9968CF_MOD_CLVBWGP; /* see camlist[] table */
else if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[1].idVendor &&
- le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[1].idProduct)
+ le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[1].idProduct)
mod_id = W9968CF_MOD_GENERIC; /* see camlist[] table */
else
return -ENODEV;
cam = (struct w9968cf_device*)
- kzalloc(sizeof(struct w9968cf_device), GFP_KERNEL);
+ kzalloc(sizeof(struct w9968cf_device), GFP_KERNEL);
if (!cam)
return -ENOMEM;
@@ -3569,7 +3569,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
cam->v4ldev->dev = &cam->dev;
err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
- video_nr[dev_nr]);
+ video_nr[dev_nr]);
if (err) {
DBG(1, "V4L device registration failed")
if (err == -ENFILE && video_nr[dev_nr] == -1)
@@ -3611,7 +3611,7 @@ fail: /* Free unused memory */
static void w9968cf_usb_disconnect(struct usb_interface* intf)
{
- struct w9968cf_device* cam =
+ struct w9968cf_device* cam =
(struct w9968cf_device*)usb_get_intfdata(intf);
down_write(&w9968cf_disconnect);
diff --git a/drivers/usb/media/w9968cf.h b/drivers/media/video/w9968cf.h
index a87be719a28..2836b45ec20 100644
--- a/drivers/usb/media/w9968cf.h
+++ b/drivers/media/video/w9968cf.h
@@ -61,7 +61,7 @@
/* Maximum data payload sizes in bytes for alternate settings */
static const u16 wMaxPacketSize[] = {1023, 959, 895, 831, 767, 703, 639, 575,
- 511, 447, 383, 319, 255, 191, 127, 63};
+ 511, 447, 383, 319, 255, 191, 127, 63};
#define W9968CF_PACKET_SIZE 1023 /* according to wMaxPacketSizes[] */
#define W9968CF_MIN_PACKET_SIZE 63 /* minimum value */
#define W9968CF_ISO_PACKETS 5 /* n.of packets for isochronous transfers */
@@ -134,7 +134,7 @@ static const struct w9968cf_format w9968cf_formatlist[] = {
****************************************************************************/
#define W9968CF_MODULE_NAME "V4L driver for W996[87]CF JPEG USB " \
- "Dual Mode Camera Chip"
+ "Dual Mode Camera Chip"
#define W9968CF_MODULE_VERSION "1:1.33-basic"
#define W9968CF_MODULE_AUTHOR "(C) 2002-2004 Luca Risolia"
#define W9968CF_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
@@ -270,9 +270,9 @@ struct w9968cf_device {
/* Locks */
struct mutex dev_mutex, /* for probe, disconnect,open and close */
- fileop_mutex; /* for read and ioctl */
+ fileop_mutex; /* for read and ioctl */
spinlock_t urb_lock, /* for submit_urb() and unlink_urb() */
- flist_lock; /* for requested frame list accesses */
+ flist_lock; /* for requested frame list accesses */
wait_queue_head_t open, wait_queue;
char command[16]; /* name of the program holding the device */
@@ -299,7 +299,7 @@ struct w9968cf_device {
dev_warn(&cam->dev, fmt "\n", ## args); \
else if ((level) >= 5) \
dev_info(&cam->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args); \
+ __FUNCTION__, __LINE__ , ## args); \
} \
}
/* For generic kernel (not device specific) messages */
@@ -311,7 +311,7 @@ struct w9968cf_device {
pr_info("w9968cf: " fmt "\n", ## args); \
else if ((level) >= 5) \
pr_debug("w9968cf: [%s:%d] " fmt "\n", __FUNCTION__, \
- __LINE__ , ## args); \
+ __LINE__ , ## args); \
} \
}
#else
diff --git a/drivers/usb/media/w9968cf_decoder.h b/drivers/media/video/w9968cf_decoder.h
index 31faccbe8f0..59decbfc540 100644
--- a/drivers/usb/media/w9968cf_decoder.h
+++ b/drivers/media/video/w9968cf_decoder.h
@@ -78,9 +78,9 @@ static const unsigned char UV_QUANTABLE[64] = {
#define W9968CF_DEC_ERR_NO_EOI -6
extern void w9968cf_init_decoder(void);
-extern int w9968cf_check_headers(const unsigned char* Pin,
- const unsigned long BUF_SIZE);
-extern int w9968cf_decode(const char* Pin, const unsigned long BUF_SIZE,
- const unsigned W, const unsigned H, char* Pout);
+extern int w9968cf_check_headers(const unsigned char* Pin,
+ const unsigned long BUF_SIZE);
+extern int w9968cf_decode(const char* Pin, const unsigned long BUF_SIZE,
+ const unsigned W, const unsigned H, char* Pout);
#endif /* _W9968CF_DECODER_H_ */
diff --git a/drivers/usb/media/w9968cf_vpp.h b/drivers/media/video/w9968cf_vpp.h
index f3b91b78267..88c9b6c0cc3 100644
--- a/drivers/usb/media/w9968cf_vpp.h
+++ b/drivers/media/video/w9968cf_vpp.h
@@ -29,7 +29,7 @@ struct w9968cf_vpp_t {
struct module* owner;
int (*check_headers)(const unsigned char*, const unsigned long);
int (*decode)(const char*, const unsigned long, const unsigned,
- const unsigned, char*);
+ const unsigned, char*);
void (*swap_yuvbytes)(void*, unsigned long);
void (*uyvy_to_rgbx)(u8*, unsigned long, u8*, u16, u8);
void (*scale_up)(u8*, u8*, u16, u16, u16, u16, u16);
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c
index 8cb64f8a8a9..d81a88bbe43 100644
--- a/drivers/media/video/wm8775.c
+++ b/drivers/media/video/wm8775.c
@@ -79,21 +79,26 @@ static int wm8775_command(struct i2c_client *client, unsigned int cmd,
void *arg)
{
struct wm8775_state *state = i2c_get_clientdata(client);
- struct v4l2_audio *input = arg;
+ struct v4l2_routing *route = arg;
struct v4l2_control *ctrl = arg;
switch (cmd) {
- case VIDIOC_S_AUDIO:
+ case VIDIOC_INT_G_AUDIO_ROUTING:
+ route->input = state->input;
+ route->output = 0;
+ break;
+
+ case VIDIOC_INT_S_AUDIO_ROUTING:
/* There are 4 inputs and one output. Zero or more inputs
are multiplexed together to the output. Hence there are
16 combinations.
If only one input is active (the normal case) then the
input values 1, 2, 4 or 8 should be used. */
- if (input->index > 15) {
- v4l_err(client, "Invalid input %d.\n", input->index);
+ if (route->input > 15) {
+ v4l_err(client, "Invalid input %d.\n", route->input);
return -EINVAL;
}
- state->input = input->index;
+ state->input = route->input;
if (state->muted)
break;
wm8775_write(client, R21, 0x0c0);
@@ -102,11 +107,6 @@ static int wm8775_command(struct i2c_client *client, unsigned int cmd,
wm8775_write(client, R21, 0x100 + state->input);
break;
- case VIDIOC_G_AUDIO:
- memset(input, 0, sizeof(*input));
- input->index = state->input;
- break;
-
case VIDIOC_G_CTRL:
if (ctrl->id != V4L2_CID_AUDIO_MUTE)
return -EINVAL;
diff --git a/drivers/media/video/zc0301/Makefile b/drivers/media/video/zc0301/Makefile
new file mode 100644
index 00000000000..d749199d8f0
--- /dev/null
+++ b/drivers/media/video/zc0301/Makefile
@@ -0,0 +1,3 @@
+zc0301-objs := zc0301_core.o zc0301_pas202bcb.o
+
+obj-$(CONFIG_USB_ZC0301) += zc0301.o
diff --git a/drivers/usb/media/zc0301.h b/drivers/media/video/zc0301/zc0301.h
index 8e0655140e6..b9c93b8c16f 100644
--- a/drivers/usb/media/zc0301.h
+++ b/drivers/media/video/zc0301/zc0301.h
@@ -157,7 +157,7 @@ do { \
dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
else if ((level) >= 3) \
dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args); \
+ __FUNCTION__, __LINE__ , ## args); \
} \
} while (0)
# define KDBG(level, fmt, args...) \
@@ -167,7 +167,7 @@ do { \
pr_info("zc0301: " fmt "\n", ## args); \
else if ((level) == 3) \
pr_debug("zc0301: [%s:%d] " fmt "\n", __FUNCTION__, \
- __LINE__ , ## args); \
+ __LINE__ , ## args); \
} \
} while (0)
# define V4LDBG(level, name, cmd) \
@@ -184,7 +184,7 @@ do { \
#undef PDBG
#define PDBG(fmt, args...) \
dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args)
+ __FUNCTION__, __LINE__ , ## args)
#undef PDBGG
#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
diff --git a/drivers/usb/media/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
index 4036c6268bf..0fad39754f7 100644
--- a/drivers/usb/media/zc0301_core.c
+++ b/drivers/media/video/zc0301/zc0301_core.c
@@ -48,7 +48,7 @@
/*****************************************************************************/
#define ZC0301_MODULE_NAME "V4L2 driver for ZC0301 " \
- "Image Processor and Control Chip"
+ "Image Processor and Control Chip"
#define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia"
#define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define ZC0301_MODULE_LICENSE "GPL"
@@ -67,67 +67,67 @@ MODULE_LICENSE(ZC0301_MODULE_LICENSE);
static short video_nr[] = {[0 ... ZC0301_MAX_DEVICES-1] = -1};
module_param_array(video_nr, short, NULL, 0444);
MODULE_PARM_DESC(video_nr,
- "\n<-1|n[,...]> Specify V4L2 minor mode number."
- "\n -1 = use next available (default)"
- "\n n = use minor number n (integer >= 0)"
- "\nYou can specify up to "
- __MODULE_STRING(ZC0301_MAX_DEVICES) " cameras this way."
- "\nFor example:"
- "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
- "\nthe second registered camera and use auto for the first"
- "\none and for every other camera."
- "\n");
+ "\n<-1|n[,...]> Specify V4L2 minor mode number."
+ "\n -1 = use next available (default)"
+ "\n n = use minor number n (integer >= 0)"
+ "\nYou can specify up to "
+ __MODULE_STRING(ZC0301_MAX_DEVICES) " cameras this way."
+ "\nFor example:"
+ "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
+ "\nthe second registered camera and use auto for the first"
+ "\none and for every other camera."
+ "\n");
static short force_munmap[] = {[0 ... ZC0301_MAX_DEVICES-1] =
- ZC0301_FORCE_MUNMAP};
+ ZC0301_FORCE_MUNMAP};
module_param_array(force_munmap, bool, NULL, 0444);
MODULE_PARM_DESC(force_munmap,
- "\n<0|1[,...]> Force the application to unmap previously"
- "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
- "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
- "\nthis feature. This parameter is specific for each"
- "\ndetected camera."
- "\n 0 = do not force memory unmapping"
- "\n 1 = force memory unmapping (save memory)"
- "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
- "\n");
+ "\n<0|1[,...]> Force the application to unmap previously"
+ "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
+ "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
+ "\nthis feature. This parameter is specific for each"
+ "\ndetected camera."
+ "\n 0 = do not force memory unmapping"
+ "\n 1 = force memory unmapping (save memory)"
+ "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+ "\n");
static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] =
- ZC0301_FRAME_TIMEOUT};
+ ZC0301_FRAME_TIMEOUT};
module_param_array(frame_timeout, uint, NULL, 0644);
MODULE_PARM_DESC(frame_timeout,
- "\n<n[,...]> Timeout for a video frame in seconds."
- "\nThis parameter is specific for each detected camera."
- "\nDefault value is "__MODULE_STRING(ZC0301_FRAME_TIMEOUT)"."
- "\n");
+ "\n<n[,...]> Timeout for a video frame in seconds."
+ "\nThis parameter is specific for each detected camera."
+ "\nDefault value is "__MODULE_STRING(ZC0301_FRAME_TIMEOUT)"."
+ "\n");
#ifdef ZC0301_DEBUG
static unsigned short debug = ZC0301_DEBUG_LEVEL;
module_param(debug, ushort, 0644);
MODULE_PARM_DESC(debug,
- "\n<n> Debugging information level, from 0 to 3:"
- "\n0 = none (use carefully)"
- "\n1 = critical errors"
- "\n2 = significant informations"
- "\n3 = more verbose messages"
- "\nLevel 3 is useful for testing only, when only "
- "one device is used."
- "\nDefault value is "__MODULE_STRING(ZC0301_DEBUG_LEVEL)"."
- "\n");
+ "\n<n> Debugging information level, from 0 to 3:"
+ "\n0 = none (use carefully)"
+ "\n1 = critical errors"
+ "\n2 = significant informations"
+ "\n3 = more verbose messages"
+ "\nLevel 3 is useful for testing only, when only "
+ "one device is used."
+ "\nDefault value is "__MODULE_STRING(ZC0301_DEBUG_LEVEL)"."
+ "\n");
#endif
/*****************************************************************************/
static u32
zc0301_request_buffers(struct zc0301_device* cam, u32 count,
- enum zc0301_io_method io)
+ enum zc0301_io_method io)
{
struct v4l2_pix_format* p = &(cam->sensor.pix_format);
struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
const size_t imagesize = cam->module_param.force_munmap ||
- io == IO_READ ?
- (p->width * p->height * p->priv) / 8 :
- (r->width * r->height * p->priv) / 8;
+ io == IO_READ ?
+ (p->width * p->height * p->priv) / 8 :
+ (r->width * r->height * p->priv) / 8;
void* buff = NULL;
u32 i;
@@ -216,7 +216,7 @@ int zc0301_write_reg(struct zc0301_device* cam, u16 index, u16 value)
int res;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0xa0, 0x40,
- value, index, NULL, 0, ZC0301_CTRL_TIMEOUT);
+ value, index, NULL, 0, ZC0301_CTRL_TIMEOUT);
if (res < 0) {
DBG(3, "Failed to write a register (index 0x%04X, "
"value 0x%02X, error %d)",index, value, res);
@@ -234,7 +234,7 @@ int zc0301_read_reg(struct zc0301_device* cam, u16 index)
int res;
res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0xa1, 0xc0,
- 0x0001, index, buff, 1, ZC0301_CTRL_TIMEOUT);
+ 0x0001, index, buff, 1, ZC0301_CTRL_TIMEOUT);
if (res < 0)
DBG(3, "Failed to read a register (index 0x%04X, error %d)",
index, res);
@@ -337,11 +337,11 @@ static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs)
if (!(*f))
(*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t,
- frame);
+ frame);
imagesize = (cam->sensor.pix_format.width *
- cam->sensor.pix_format.height *
- cam->sensor.pix_format.priv) / 8;
+ cam->sensor.pix_format.height *
+ cam->sensor.pix_format.priv) / 8;
for (i = 0; i < urb->number_of_packets; i++) {
unsigned int len, status;
@@ -395,8 +395,8 @@ end_of_frame:
list_move_tail(&(*f)->frame, &cam->outqueue);
if (!list_empty(&cam->inqueue))
(*f) = list_entry(cam->inqueue.next,
- struct zc0301_frame_t,
- frame);
+ struct zc0301_frame_t,
+ frame);
else
(*f) = NULL;
spin_unlock(&cam->queue_lock);
@@ -429,14 +429,14 @@ static int zc0301_start_transfer(struct zc0301_device* cam)
struct usb_device *udev = cam->usbdev;
struct urb* urb;
const unsigned int wMaxPacketSize[] = {0, 128, 192, 256, 384,
- 512, 768, 1023};
+ 512, 768, 1023};
const unsigned int psz = wMaxPacketSize[ZC0301_ALTERNATE_SETTING];
s8 i, j;
int err = 0;
for (i = 0; i < ZC0301_URBS; i++) {
cam->transfer_buffer[i] = kzalloc(ZC0301_ISO_PACKETS * psz,
- GFP_KERNEL);
+ GFP_KERNEL);
if (!cam->transfer_buffer[i]) {
err = -ENOMEM;
DBG(1, "Not enough memory");
@@ -528,9 +528,9 @@ static int zc0301_stream_interrupt(struct zc0301_device* cam)
cam->stream = STREAM_INTERRUPT;
timeout = wait_event_timeout(cam->wait_stream,
- (cam->stream == STREAM_OFF) ||
- (cam->state & DEV_DISCONNECTED),
- ZC0301_URB_TIMEOUT);
+ (cam->stream == STREAM_OFF) ||
+ (cam->state & DEV_DISCONNECTED),
+ ZC0301_URB_TIMEOUT);
if (cam->state & DEV_DISCONNECTED)
return -ENODEV;
else if (cam->stream != STREAM_OFF) {
@@ -548,7 +548,7 @@ static int zc0301_stream_interrupt(struct zc0301_device* cam)
static int
zc0301_set_compression(struct zc0301_device* cam,
- struct v4l2_jpegcompression* compression)
+ struct v4l2_jpegcompression* compression)
{
int r, err = 0;
@@ -670,8 +670,8 @@ static int zc0301_open(struct inode* inode, struct file* filp)
}
mutex_unlock(&cam->dev_mutex);
err = wait_event_interruptible_exclusive(cam->open,
- cam->state & DEV_DISCONNECTED
- || !cam->users);
+ cam->state & DEV_DISCONNECTED
+ || !cam->users);
if (err) {
up_read(&zc0301_disconnect);
return err;
@@ -802,12 +802,12 @@ zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
return -EAGAIN;
}
timeout = wait_event_interruptible_timeout
- ( cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED),
- cam->module_param.frame_timeout *
- 1000 * msecs_to_jiffies(1) );
+ ( cam->wait_frame,
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED),
+ cam->module_param.frame_timeout *
+ 1000 * msecs_to_jiffies(1) );
if (timeout < 0) {
mutex_unlock(&cam->fileop_mutex);
return timeout;
@@ -930,7 +930,7 @@ static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma)
{
struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
unsigned long size = vma->vm_end - vma->vm_start,
- start = vma->vm_start;
+ start = vma->vm_start;
void *pos;
u32 i;
@@ -998,13 +998,13 @@ zc0301_vidioc_querycap(struct zc0301_device* cam, void __user * arg)
.driver = "zc0301",
.version = ZC0301_MODULE_VERSION_CODE,
.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
- V4L2_CAP_STREAMING,
+ V4L2_CAP_STREAMING,
};
strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
- sizeof(cap.bus_info));
+ sizeof(cap.bus_info));
if (copy_to_user(arg, &cap, sizeof(cap)))
return -EFAULT;
@@ -1337,7 +1337,7 @@ zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg)
static int
zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd,
- void __user * arg)
+ void __user * arg)
{
struct zc0301_sensor* s = &cam->sensor;
struct v4l2_format format;
@@ -1600,7 +1600,7 @@ zc0301_vidioc_qbuf(struct zc0301_device* cam, void __user * arg)
static int
zc0301_vidioc_dqbuf(struct zc0301_device* cam, struct file* filp,
- void __user * arg)
+ void __user * arg)
{
struct v4l2_buffer b;
struct zc0301_frame_t *f;
@@ -1619,12 +1619,12 @@ zc0301_vidioc_dqbuf(struct zc0301_device* cam, struct file* filp,
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
timeout = wait_event_interruptible_timeout
- ( cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED),
- cam->module_param.frame_timeout *
- 1000 * msecs_to_jiffies(1) );
+ ( cam->wait_frame,
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED),
+ cam->module_param.frame_timeout *
+ 1000 * msecs_to_jiffies(1) );
if (timeout < 0)
return timeout;
if (cam->state & DEV_DISCONNECTED)
@@ -1748,7 +1748,7 @@ zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg)
static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
- unsigned int cmd, void __user * arg)
+ unsigned int cmd, void __user * arg)
{
struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
@@ -1842,7 +1842,7 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
static int zc0301_ioctl(struct inode* inode, struct file* filp,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
int err = 0;
@@ -1948,7 +1948,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
mutex_lock(&cam->dev_mutex);
err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
- video_nr[dev_nr]);
+ video_nr[dev_nr]);
if (err) {
DBG(1, "V4L2 device registration failed");
if (err == -ENFILE && video_nr[dev_nr] == -1)
diff --git a/drivers/usb/media/zc0301_pas202bcb.c b/drivers/media/video/zc0301/zc0301_pas202bcb.c
index 9d282a22c15..eaadf025204 100644
--- a/drivers/usb/media/zc0301_pas202bcb.c
+++ b/drivers/media/video/zc0301/zc0301_pas202bcb.c
@@ -24,10 +24,10 @@
/*
NOTE: Sensor controls are disabled for now, becouse changing them while
- streaming sometimes results in out-of-sync video frames. We'll use
- the default initialization, until we know how to stop and start video
- in the chip. However, the image quality still looks good under various
- light conditions.
+ streaming sometimes results in out-of-sync video frames. We'll use
+ the default initialization, until we know how to stop and start video
+ in the chip. However, the image quality still looks good under various
+ light conditions.
*/
#include <linux/delay.h>
@@ -165,7 +165,7 @@ static int pas202bcb_init(struct zc0301_device* cam)
static int pas202bcb_get_ctrl(struct zc0301_device* cam,
- struct v4l2_control* ctrl)
+ struct v4l2_control* ctrl)
{
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
@@ -208,7 +208,7 @@ static int pas202bcb_get_ctrl(struct zc0301_device* cam,
static int pas202bcb_set_ctrl(struct zc0301_device* cam,
- const struct v4l2_control* ctrl)
+ const struct v4l2_control* ctrl)
{
int err = 0;
diff --git a/drivers/usb/media/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h
index cf0965a81d0..1f95c28b101 100644
--- a/drivers/usb/media/zc0301_sensor.h
+++ b/drivers/media/video/zc0301/zc0301_sensor.h
@@ -51,7 +51,7 @@ zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor);
#define ZC0301_USB_DEVICE(vend, prod, intclass) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
- USB_DEVICE_ID_MATCH_INT_CLASS, \
+ USB_DEVICE_ID_MATCH_INT_CLASS, \
.idVendor = (vend), \
.idProduct = (prod), \
.bInterfaceClass = (intclass)
@@ -92,7 +92,7 @@ struct zc0301_sensor {
int (*init)(struct zc0301_device*);
int (*get_ctrl)(struct zc0301_device*, struct v4l2_control* ctrl);
int (*set_ctrl)(struct zc0301_device*,
- const struct v4l2_control* ctrl);
+ const struct v4l2_control* ctrl);
int (*set_crop)(struct zc0301_device*, const struct v4l2_rect* rect);
/* Private */
diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h
index ad04a129499..0166f555a5c 100644
--- a/drivers/media/video/zoran.h
+++ b/drivers/media/video/zoran.h
@@ -1,4 +1,4 @@
-/*
+/*
* zoran - Iomega Buz driver
*
* Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index b22dbb6d18f..0a85c9e7fb4 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -4,7 +4,7 @@
* Media Labs LML33/LML33R10.
*
* This part handles card-specific data and detection
- *
+ *
* Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
*
* Currently maintained by:
diff --git a/drivers/media/video/zoran_card.h b/drivers/media/video/zoran_card.h
index e5b6acd3eed..ad997c30bee 100644
--- a/drivers/media/video/zoran_card.h
+++ b/drivers/media/video/zoran_card.h
@@ -4,7 +4,7 @@
* Media Labs LML33/LML33R10.
*
* This part handles card-specific data and detection
- *
+ *
* Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
*
* Currently maintained by:
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c
index 4e15afdec4c..c690b2ee880 100644
--- a/drivers/media/video/zoran_device.c
+++ b/drivers/media/video/zoran_device.c
@@ -4,7 +4,7 @@
* Media Labs LML33/LML33R10.
*
* This part handles device access (PCI/I2C/codec/...)
- *
+ *
* Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
*
* Currently maintained by:
@@ -492,7 +492,7 @@ zr36057_set_vfe (struct zoran *zr,
/* (Ronald) don't write this if overlay_mask = NULL */
if (zr->overlay_mask) {
/* Write overlay clipping mask data, but don't enable overlay clipping */
- /* RJ: since this makes only sense on the screen, we use
+ /* RJ: since this makes only sense on the screen, we use
* zr->overlay_settings.width instead of video_width */
mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
@@ -819,12 +819,12 @@ zr36057_set_jpg (struct zoran *zr,
if (zr->card.vfe_pol.hsync_pol)
btor(ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR);
else
- btand(~ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR);
+ btand(~ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR);
reg = ((tvn->HSyncStart) << ZR36057_HSP_HsyncStart) |
(tvn->Wt << ZR36057_HSP_LineTot);
btwrite(reg, ZR36057_HSP);
reg = ((zr->jpg_settings.img_x +
- tvn->HStart + 4) << ZR36057_FHAP_NAX) |
+ tvn->HStart + 4) << ZR36057_FHAP_NAX) |
(zr->jpg_settings.img_width << ZR36057_FHAP_PAX);
btwrite(reg, ZR36057_FHAP);
@@ -1272,15 +1272,15 @@ error_handler (struct zoran *zr,
if (zr->JPEG_error != 1) {
/*
* First entry: error just happened during normal operation
- *
+ *
* In BUZ_MODE_MOTION_COMPRESS:
- *
+ *
* Possible glitch in TV signal. In this case we should
* stop the codec and wait for good quality signal before
* restarting it to avoid further problems
- *
+ *
* In BUZ_MODE_MOTION_DECOMPRESS:
- *
+ *
* Bad JPEG frame: we have to mark it as processed (codec crashed
* and was not able to do it itself), and to remove it from queue.
*/
diff --git a/drivers/media/video/zoran_device.h b/drivers/media/video/zoran_device.h
index f315203d710..f19705cbdb3 100644
--- a/drivers/media/video/zoran_device.h
+++ b/drivers/media/video/zoran_device.h
@@ -4,7 +4,7 @@
* Media Labs LML33/LML33R10.
*
* This part handles card-specific data and detection
- *
+ *
* Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
*
* Currently maintained by:
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index b2c6e01e392..b5a576a37fd 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -94,7 +94,7 @@
V4L2_CAP_VIDEO_CAPTURE |\
V4L2_CAP_VIDEO_OUTPUT |\
V4L2_CAP_VIDEO_OVERLAY \
- )
+ )
#endif
#include <asm/byteorder.h>
@@ -165,7 +165,7 @@ const struct zoran_format zoran_formats[] = {
#endif
.depth = 16,
.flags = ZORAN_FORMAT_CAPTURE |
- ZORAN_FORMAT_OVERLAY,
+ ZORAN_FORMAT_OVERLAY,
}, {
.name = "Hardware-encoded Motion-JPEG",
.palette = -1,
@@ -670,7 +670,7 @@ jpg_fbuffer_free (struct file *file)
j]))));
free_page((unsigned long)
bus_to_virt
- (le32_to_cpu
+ (le32_to_cpu
(fh->jpg_buffers.
buffer[i].
frag_tab[2 * j])));
@@ -1871,7 +1871,7 @@ zoran_v4l2_buffer_status (struct file *file,
static int
zoran_set_norm (struct zoran *zr,
- int norm) /* VIDEO_MODE_* */
+ int norm) /* VIDEO_MODE_* */
{
int norm_encoder, on;
@@ -2006,9 +2006,9 @@ zoran_set_input (struct zoran *zr,
static int
zoran_do_ioctl (struct inode *inode,
- struct file *file,
- unsigned int cmd,
- void *arg)
+ struct file *file,
+ unsigned int cmd,
+ void *arg)
{
struct zoran_fh *fh = file->private_data;
struct zoran *zr = fh->zr;
@@ -2095,7 +2095,7 @@ zoran_do_ioctl (struct inode *inode,
break;
/* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says:
- *
+ *
* * "The VIDIOCSCHAN ioctl takes an integer argument and switches the capture to this input."
* * ^^^^^^^
* * The famos BTTV driver has it implemented with a struct video_channel argument
diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c
index f0d9b13c3c6..a00fae90229 100644
--- a/drivers/media/video/zoran_procfs.c
+++ b/drivers/media/video/zoran_procfs.c
@@ -4,7 +4,7 @@
* Media Labs LML33/LML33R10.
*
* This part handles the procFS entries (/proc/ZORAN[%d])
- *
+ *
* Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
*
* Currently maintained by:
diff --git a/drivers/media/video/zoran_procfs.h b/drivers/media/video/zoran_procfs.h
index 8904fc95955..f2d5b1ba448 100644
--- a/drivers/media/video/zoran_procfs.h
+++ b/drivers/media/video/zoran_procfs.h
@@ -4,7 +4,7 @@
* Media Labs LML33/LML33R10.
*
* This part handles card-specific data and detection
- *
+ *
* Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
*
* Currently maintained by:
diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c
index 10130ef67ea..62f77584fb8 100644
--- a/drivers/media/video/zr36016.c
+++ b/drivers/media/video/zr36016.c
@@ -34,7 +34,7 @@
#include <linux/types.h>
#include <linux/wait.h>
-/* includes for structures and defines regarding video
+/* includes for structures and defines regarding video
#include<linux/videodev.h> */
/* I/O commands, error codes */
@@ -143,8 +143,8 @@ zr36016_readi (struct zr36016 *ptr,
static void
zr36016_writei (struct zr36016 *ptr,
- u16 reg,
- u8 value)
+ u16 reg,
+ u8 value)
{
dprintk(4, "%s: writing indirect 0x%02x to 0x%04x\n", ptr->name,
value, reg);
@@ -192,7 +192,7 @@ zr36016_basic_test (struct zr36016 *ptr)
dprintk(1, "\n");
}
// for testing just write 0, then the default value to a register and read
- // it back in both cases
+ // it back in both cases
zr36016_writei(ptr, ZR016I_PAX_LO, 0x00);
if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0) {
dprintk(1,
@@ -232,17 +232,17 @@ zr36016_basic_test (struct zr36016 *ptr)
static int zr36016_pushit (struct zr36016 *ptr,
u16 startreg,
u16 len,
- const char *data)
+ const char *data)
{
- int i=0;
+ int i=0;
- dprintk(4, "%s: write data block to 0x%04x (len=%d)\n",
+ dprintk(4, "%s: write data block to 0x%04x (len=%d)\n",
ptr->name, startreg,len);
- while (i<len) {
- zr36016_writei(ptr, startreg++, data[i++]);
- }
+ while (i<len) {
+ zr36016_writei(ptr, startreg++, data[i++]);
+ }
- return i;
+ return i;
}
#endif
diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c
index 6699725be60..a6bbd125631 100644
--- a/drivers/media/video/zr36050.c
+++ b/drivers/media/video/zr36050.c
@@ -34,7 +34,7 @@
#include <linux/types.h>
#include <linux/wait.h>
-/* includes for structures and defines regarding video
+/* includes for structures and defines regarding video
#include<linux/videodev.h> */
/* I/O commands, error codes */
@@ -171,7 +171,7 @@ zr36050_wait_end (struct zr36050 *ptr)
/* =========================================================================
Local helper function:
- basic test of "connectivity", writes/reads to/from memory the SOF marker
+ basic test of "connectivity", writes/reads to/from memory the SOF marker
========================================================================= */
static int
@@ -218,9 +218,9 @@ zr36050_basic_test (struct zr36050 *ptr)
static int
zr36050_pushit (struct zr36050 *ptr,
- u16 startreg,
- u16 len,
- const char *data)
+ u16 startreg,
+ u16 len,
+ const char *data)
{
int i = 0;
@@ -345,7 +345,7 @@ static const char zr36050_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
/* ------------------------------------------------------------------------- */
/* SOF (start of frame) segment depends on width, height and sampling ratio
- of each color component */
+ of each color component */
static int
zr36050_set_sof (struct zr36050 *ptr)
@@ -376,8 +376,8 @@ zr36050_set_sof (struct zr36050 *ptr)
/* ------------------------------------------------------------------------- */
-/* SOS (start of scan) segment depends on the used scan components
- of each color component */
+/* SOS (start of scan) segment depends on the used scan components
+ of each color component */
static int
zr36050_set_sos (struct zr36050 *ptr)
diff --git a/drivers/media/video/zr36057.h b/drivers/media/video/zr36057.h
index 159abfa034d..54c9362aa98 100644
--- a/drivers/media/video/zr36057.h
+++ b/drivers/media/video/zr36057.h
@@ -1,4 +1,4 @@
-/*
+/*
* zr36057.h - zr36057 register offsets
*
* Copyright (C) 1998 Dave Perks <dperks@ibm.net>
@@ -27,14 +27,14 @@
#define ZR36057_VFEHCR 0x000 /* Video Front End, Horizontal Configuration Register */
#define ZR36057_VFEHCR_HSPol (1<<30)
#define ZR36057_VFEHCR_HStart 10
-#define ZR36057_VFEHCR_HEnd 0
-#define ZR36057_VFEHCR_Hmask 0x3ff
+#define ZR36057_VFEHCR_HEnd 0
+#define ZR36057_VFEHCR_Hmask 0x3ff
#define ZR36057_VFEVCR 0x004 /* Video Front End, Vertical Configuration Register */
#define ZR36057_VFEVCR_VSPol (1<<30)
#define ZR36057_VFEVCR_VStart 10
-#define ZR36057_VFEVCR_VEnd 0
-#define ZR36057_VFEVCR_Vmask 0x3ff
+#define ZR36057_VFEVCR_VEnd 0
+#define ZR36057_VFEVCR_Vmask 0x3ff
#define ZR36057_VFESPFR 0x008 /* Video Front End, Scaler and Pixel Format Register */
#define ZR36057_VFESPFR_ExtFl (1<<26)
diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c
index d8dd003a7aa..97c8f9b9dc1 100644
--- a/drivers/media/video/zr36060.c
+++ b/drivers/media/video/zr36060.c
@@ -34,7 +34,7 @@
#include <linux/types.h>
#include <linux/wait.h>
-/* includes for structures and defines regarding video
+/* includes for structures and defines regarding video
#include<linux/videodev.h> */
/* I/O commands, error codes */
@@ -173,7 +173,7 @@ zr36060_wait_end (struct zr36060 *ptr)
/* =========================================================================
Local helper function:
- basic test of "connectivity", writes/reads to/from memory the SOF marker
+ basic test of "connectivity", writes/reads to/from memory the SOF marker
========================================================================= */
static int
@@ -208,9 +208,9 @@ zr36060_basic_test (struct zr36060 *ptr)
static int
zr36060_pushit (struct zr36060 *ptr,
- u16 startreg,
- u16 len,
- const char *data)
+ u16 startreg,
+ u16 len,
+ const char *data)
{
int i = 0;
@@ -335,7 +335,7 @@ static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
/* ------------------------------------------------------------------------- */
/* SOF (start of frame) segment depends on width, height and sampling ratio
- of each color component */
+ of each color component */
static int
zr36060_set_sof (struct zr36060 *ptr)
@@ -367,8 +367,8 @@ zr36060_set_sof (struct zr36060 *ptr)
/* ------------------------------------------------------------------------- */
-/* SOS (start of scan) segment depends on the used scan components
- of each color component */
+/* SOS (start of scan) segment depends on the used scan components
+ of each color component */
static int
zr36060_set_sos (struct zr36060 *ptr)
@@ -385,7 +385,7 @@ zr36060_set_sos (struct zr36060 *ptr)
for (i = 0; i < NO_OF_COMPONENTS; i++) {
sos_data[5 + (i * 2)] = i; // index
sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
- zr36060_ta[i]; // AC/DC tbl.sel.
+ zr36060_ta[i]; // AC/DC tbl.sel.
}
sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00; // scan start
sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f;
@@ -999,7 +999,7 @@ zr36060_cleanup_module (void)
dprintk(1,
"zr36060: something's wrong - %d codecs left somehow.\n",
zr36060_codecs);
- }
+ }
/* however, we can't just stay alive */
videocodec_unregister(&zr36060_codec);
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
index d4c633b8a7f..6ac3b674008 100644
--- a/drivers/media/video/zr36120.c
+++ b/drivers/media/video/zr36120.c
@@ -70,10 +70,10 @@ MODULE_AUTHOR("Pauline Middelink <middelin@polyware.nl>");
MODULE_DESCRIPTION("Zoran ZR36120 based framegrabber");
MODULE_LICENSE("GPL");
-MODULE_PARM(triton1,"i");
-MODULE_PARM(cardtype,"1-" __MODULE_STRING(ZORAN_MAX) "i");
-MODULE_PARM(video_nr,"i");
-MODULE_PARM(vbi_nr,"i");
+module_param(triton1, uint, 0);
+module_param_array(cardtype, uint, NULL, 0);
+module_param(video_nr, int, 0);
+module_param(vbi_nr, int, 0);
static int zoran_cards;
static struct zoran zorans[ZORAN_MAX];
@@ -316,7 +316,7 @@ DEBUG(printk(CARD_DEBUG "%p added to queue\n",CARD,item));
item->status = FBUFFER_BUSY;
if (!lastitem)
ztv->workqueue = item;
- else
+ else
lastitem->next = item;
lastitem = item;
}
@@ -516,7 +516,7 @@ DEBUG(printk(KERN_DEBUG " %d: clip(%d,%d,%d,%d)\n", i,vp->x,vp->y,vp->widt
zraor((ztv->vidInterlace*ystep)<<0,~ZORAN_OCR_MASKSTRIDE,ZORAN_OCR);
}
-struct tvnorm
+struct tvnorm
{
u16 Wt, Wa, Ht, Ha, HStart, VStart;
};
@@ -660,7 +660,7 @@ DEBUG(printk(KERN_DEBUG " Y: scale=0, start=%d, end=%d\n", Hstart, Hend));
int HorDcm = 64-X;
int hcrop1 = 2*(Wa-We)/4;
/*
- * BUGFIX: Juha Nurmela <junki@qn-lpr2-165.quicknet.inet.fi>
+ * BUGFIX: Juha Nurmela <junki@qn-lpr2-165.quicknet.inet.fi>
* found the solution to the color phase shift.
* See ChangeLog for the full explanation)
*/
@@ -812,12 +812,12 @@ void zoran_close(struct video_device* dev)
zoran_common_close(ztv);
- /*
- * This is sucky but right now I can't find a good way to
- * be sure its safe to free the buffer. We wait 5-6 fields
- * which is more than sufficient to be sure.
- */
- msleep(100); /* Wait 1/10th of a second */
+ /*
+ * This is sucky but right now I can't find a good way to
+ * be sure its safe to free the buffer. We wait 5-6 fields
+ * which is more than sufficient to be sure.
+ */
+ msleep(100); /* Wait 1/10th of a second */
/* free the allocated framebuffer */
bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE);
@@ -1436,7 +1436,7 @@ int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg)
/* Why isn't this in the API?
* And why doesn't it take a buffer number?
- case BTTV_FIELDNR:
+ case BTTV_FIELDNR:
{
unsigned long v = ztv->lastfieldnr;
if (copy_to_user(arg,&v,sizeof(v)))
@@ -1557,12 +1557,12 @@ void vbi_close(struct video_device *dev)
zoran_common_close(ztv);
- /*
- * This is sucky but right now I can't find a good way to
- * be sure its safe to free the buffer. We wait 5-6 fields
- * which is more than sufficient to be sure.
- */
- msleep(100); /* Wait 1/10th of a second */
+ /*
+ * This is sucky but right now I can't find a good way to
+ * be sure its safe to free the buffer. We wait 5-6 fields
+ * which is more than sufficient to be sure.
+ */
+ msleep(100); /* Wait 1/10th of a second */
for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++)
{
@@ -1620,7 +1620,7 @@ long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonb
write_unlock_irq(&ztv->lock);
return -EWOULDBLOCK;
}
-
+
/* mark the unused buffer as wanted */
unused->status = FBUFFER_BUSY;
unused->next = 0;
@@ -1671,7 +1671,7 @@ long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonb
if (count == 2*19*2048) {
/*
* Extreme HACK, old VBI programs expect 2048 points
- * of data, and we only got 864 orso. Double each
+ * of data, and we only got 864 orso. Double each
* datapoint and clear the rest of the line.
* This way we have appear to have a
* sample_frequency of 29.5 Mc.
@@ -1956,7 +1956,7 @@ int __init init_zoran(int card)
zrand(~ZORAN_VDC_TRICOM, ZORAN_VDC);
/* external FL determines TOP frame */
- zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC);
+ zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC);
/* set HSpol */
if (ztv->card->hsync_pos)
@@ -2012,7 +2012,7 @@ void release_zoran(int max)
struct zoran *ztv;
int i;
- for (i=0;i<max; i++)
+ for (i=0;i<max; i++)
{
ztv = &zorans[i];
@@ -2029,7 +2029,7 @@ void release_zoran(int max)
/* free it */
free_irq(ztv->dev->irq,ztv);
-
+
/* unregister i2c_bus */
i2c_unregister_bus((&ztv->i2c));
@@ -2050,7 +2050,7 @@ void __exit zr36120_exit(void)
int __init zr36120_init(void)
{
int card;
-
+
handle_chipset();
zoran_cards = find_zoran();
if (zoran_cards<0)
@@ -2063,7 +2063,7 @@ int __init zr36120_init(void)
/* only release the zorans we have registered */
release_zoran(card);
return -EIO;
- }
+ }
}
return 0;
}
diff --git a/drivers/media/video/zr36120.h b/drivers/media/video/zr36120.h
index 571f8e84b58..a71e485b0f9 100644
--- a/drivers/media/video/zr36120.h
+++ b/drivers/media/video/zr36120.h
@@ -1,4 +1,4 @@
-/*
+/*
zr36120.h - Zoran 36120/36125 based framegrabbers
Copyright (C) 1998-1999 Pauline Middelink (middelin@polyware.nl)
@@ -89,7 +89,7 @@ struct vidinfo {
ulong* overlay; /* kernel addr of overlay mask */
};
-struct zoran
+struct zoran
{
struct video_device video_dev;
#define CARD_DEBUG KERN_DEBUG "%s(%lu): "
@@ -106,7 +106,7 @@ struct zoran
uint norm; /* 0=PAL, 1=NTSC, 2=SECAM */
uint tuner_freq; /* Current freq in kHz */
struct video_picture picture; /* Current picture params */
-
+
/* videocard details */
uint swidth; /* screen width */
uint sheight; /* screen height */
diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c
index 40d4ea898db..5a6cca8e8c4 100644
--- a/drivers/message/i2o/debug.c
+++ b/drivers/message/i2o/debug.c
@@ -419,58 +419,53 @@ void i2o_dump_hrt(struct i2o_controller *c)
d = (u8 *) (rows + 2);
state = p[1] << 8 | p[0];
- printk(KERN_DEBUG "TID %04X:[", state & 0xFFF);
+ printk("TID %04X:[", state & 0xFFF);
state >>= 12;
if (state & (1 << 0))
- printk(KERN_DEBUG "H"); /* Hidden */
+ printk("H"); /* Hidden */
if (state & (1 << 2)) {
- printk(KERN_DEBUG "P"); /* Present */
+ printk("P"); /* Present */
if (state & (1 << 1))
- printk(KERN_DEBUG "C"); /* Controlled */
+ printk("C"); /* Controlled */
}
if (state > 9)
- printk(KERN_DEBUG "*"); /* Hard */
+ printk("*"); /* Hard */
- printk(KERN_DEBUG "]:");
+ printk("]:");
switch (p[3] & 0xFFFF) {
case 0:
/* Adapter private bus - easy */
- printk(KERN_DEBUG
- "Local bus %d: I/O at 0x%04X Mem 0x%08X", p[2],
+ printk("Local bus %d: I/O at 0x%04X Mem 0x%08X", p[2],
d[1] << 8 | d[0], *(u32 *) (d + 4));
break;
case 1:
/* ISA bus */
- printk(KERN_DEBUG
- "ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X", p[2],
+ printk("ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X", p[2],
d[2], d[1] << 8 | d[0], *(u32 *) (d + 4));
break;
case 2: /* EISA bus */
- printk(KERN_DEBUG
- "EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X",
+ printk("EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X",
p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4));
break;
case 3: /* MCA bus */
- printk(KERN_DEBUG
- "MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2],
+ printk("MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2],
d[3], d[1] << 8 | d[0], *(u32 *) (d + 4));
break;
case 4: /* PCI bus */
- printk(KERN_DEBUG
- "PCI %d: Bus %d Device %d Function %d", p[2],
+ printk("PCI %d: Bus %d Device %d Function %d", p[2],
d[2], d[1], d[0]);
break;
case 0x80: /* Other */
default:
- printk(KERN_DEBUG "Unsupported bus type.");
+ printk("Unsupported bus type.");
break;
}
- printk(KERN_DEBUG "\n");
+ printk("\n");
rows += length;
}
}
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index b09fb630715..7d4c5497785 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -1179,10 +1179,9 @@ static int __init i2o_block_init(void)
goto exit;
}
- i2o_blk_req_pool.pool = mempool_create(I2O_BLOCK_REQ_MEMPOOL_SIZE,
- mempool_alloc_slab,
- mempool_free_slab,
- i2o_blk_req_pool.slab);
+ i2o_blk_req_pool.pool =
+ mempool_create_slab_pool(I2O_BLOCK_REQ_MEMPOOL_SIZE,
+ i2o_blk_req_pool.slab);
if (!i2o_blk_req_pool.pool) {
osm_err("can't init request mempool\n");
rc = -ENOMEM;
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index 2a0c42b8cda..3d2e76eea93 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -56,7 +56,7 @@
typedef struct _i2o_proc_entry_t {
char *name; /* entry name */
mode_t mode; /* mode */
- struct file_operations *fops; /* open function */
+ const struct file_operations *fops; /* open function */
} i2o_proc_entry;
/* global I2O /proc/i2o entry */
diff --git a/drivers/misc/ibmasm/heartbeat.c b/drivers/misc/ibmasm/heartbeat.c
index f295401fac2..7fd7a43e38d 100644
--- a/drivers/misc/ibmasm/heartbeat.c
+++ b/drivers/misc/ibmasm/heartbeat.c
@@ -52,12 +52,13 @@ static struct notifier_block panic_notifier = { panic_happened, NULL, 1 };
void ibmasm_register_panic_notifier(void)
{
- notifier_chain_register(&panic_notifier_list, &panic_notifier);
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier);
}
void ibmasm_unregister_panic_notifier(void)
{
- notifier_chain_unregister(&panic_notifier_list, &panic_notifier);
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &panic_notifier);
}
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index 5c550fcac2c..26a230b6ff8 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -101,7 +101,7 @@ static struct super_operations ibmasmfs_s_ops = {
.drop_inode = generic_delete_inode,
};
-static struct file_operations *ibmasmfs_dir_ops = &simple_dir_operations;
+static const struct file_operations *ibmasmfs_dir_ops = &simple_dir_operations;
static struct file_system_type ibmasmfs_type = {
.owner = THIS_MODULE,
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
index 8d84b045bc8..85e89c77bde 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/au1xmmc.c
@@ -87,7 +87,7 @@ struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
static int dma = 1;
#ifdef MODULE
-MODULE_PARM(dma, "i");
+module_param(dma, bool, 0);
MODULE_PARM_DESC(dma, "Use DMA engine for data transfers (0 = disabled)");
#endif
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index 205bb708333..0f6bb2e625d 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -25,9 +25,8 @@ config MTD_JEDECPROBE
compatible with the Common Flash Interface, but will use the common
CFI-targetted flash drivers for any chips which are identified which
are in fact compatible in all but the probe method. This actually
- covers most AMD/Fujitsu-compatible chips, and will shortly cover also
- non-CFI Intel chips (that code is in MTD CVS and should shortly be sent
- for inclusion in Linus' tree)
+ covers most AMD/Fujitsu-compatible chips and also non-CFI
+ Intel chips.
config MTD_GEN_PROBE
tristate
diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c
index b51c757817d..efb22169264 100644
--- a/drivers/mtd/maps/dilnetpc.c
+++ b/drivers/mtd/maps/dilnetpc.c
@@ -218,8 +218,8 @@ static void dnp_set_vpp(struct map_info *not_used, int on)
{
if(--vpp_counter == 0)
setcsc(CSC_RBWR, getcsc(CSC_RBWR) | 0x4);
- else if(vpp_counter < 0)
- BUG();
+ else
+ BUG_ON(vpp_counter < 0);
}
spin_unlock_irq(&dnpc_spin);
}
@@ -240,8 +240,8 @@ static void adnp_set_vpp(struct map_info *not_used, int on)
{
if(--vpp_counter == 0)
setcsc(CSC_RBWR, getcsc(CSC_RBWR) | 0x8);
- else if(vpp_counter < 0)
- BUG();
+ else
+ BUG_ON(vpp_counter < 0);
}
spin_unlock_irq(&dnpc_spin);
}
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index f0f8916da7a..f988c817e19 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -28,7 +28,7 @@
#ifdef CONFIG_MTD_DEBUG
static int debug = CONFIG_MTD_DEBUG_VERBOSE;
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy");
#undef DEBUG
#define DEBUG(n, format, arg...) \
@@ -89,17 +89,17 @@ static int mem_type;
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_PARM(bankwidth, "i");
+module_param(bankwidth, int, 0);
MODULE_PARM_DESC(bankwidth, "Set bankwidth (1=8 bit, 2=16 bit, default=2)");
-MODULE_PARM(mem_speed, "i");
+module_param(mem_speed, int, 0);
MODULE_PARM_DESC(mem_speed, "Set memory access speed in ns");
-MODULE_PARM(force_size, "i");
+module_param(force_size, int, 0);
MODULE_PARM_DESC(force_size, "Force size of card in MiB (1-64)");
-MODULE_PARM(setvpp, "i");
+module_param(setvpp, int, 0);
MODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)");
-MODULE_PARM(vpp, "i");
+module_param(vpp, int, 0);
MODULE_PARM_DESC(vpp, "Vpp value in 1/10ths eg 33=3.3V 120=12V (Dangerous)");
-MODULE_PARM(mem_type, "i");
+module_param(mem_type, int, 0);
MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)");
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 7f3ff500b68..840dd66ce2d 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -450,8 +450,7 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr)
kfree(tr->blkcore_priv);
- if (!list_empty(&tr->devs))
- BUG();
+ BUG_ON(!list_empty(&tr->devs));
return 0;
}
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index b1bf8c411de..9af840364a7 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -477,8 +477,7 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
}
/* must never happen since size limit has been verified above */
- if (i >= concat->num_subdev)
- BUG();
+ BUG_ON(i >= concat->num_subdev);
/* now do the erase: */
err = 0;
@@ -500,8 +499,7 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
if ((err = concat_dev_erase(subdev, erase))) {
/* sanity check: should never happen since
* block alignment has been checked above */
- if (err == -EINVAL)
- BUG();
+ BUG_ON(err == -EINVAL);
if (erase->fail_addr != 0xffffffff)
instr->fail_addr = erase->fail_addr + offset;
break;
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 5d11a06ecb2..70f63891b19 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -196,8 +196,6 @@
#define DRV_NAME "3c59x"
-#define DRV_VERSION "LK1.1.19"
-#define DRV_RELDATE "10 Nov 2002"
@@ -275,10 +273,8 @@ static char version[] __devinitdata =
DRV_NAME ": Donald Becker and others. www.scyld.com/network/vortex.html\n";
MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
-MODULE_DESCRIPTION("3Com 3c59x/3c9xx ethernet driver "
- DRV_VERSION " " DRV_RELDATE);
+MODULE_DESCRIPTION("3Com 3c59x/3c9xx ethernet driver ");
MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
/* Operational parameter that usually are not changed. */
@@ -904,7 +900,6 @@ static void acpi_set_WOL(struct net_device *dev);
static struct ethtool_ops vortex_ethtool_ops;
static void set_8021q_mode(struct net_device *dev, int enable);
-
/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
/* Option count limit only -- unlimited interfaces are supported. */
#define MAX_UNITS 8
@@ -919,8 +914,6 @@ static int global_full_duplex = -1;
static int global_enable_wol = -1;
static int global_use_mmio = -1;
-/* #define dev_alloc_skb dev_alloc_skb_debug */
-
/* Variables to work-around the Compaq PCI BIOS32 problem. */
static int compaq_ioaddr, compaq_irq, compaq_device_id = 0x5900;
static struct net_device *compaq_net_device;
@@ -976,7 +969,7 @@ static void poll_vortex(struct net_device *dev)
#ifdef CONFIG_PM
-static int vortex_suspend (struct pci_dev *pdev, pm_message_t state)
+static int vortex_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -994,7 +987,7 @@ static int vortex_suspend (struct pci_dev *pdev, pm_message_t state)
return 0;
}
-static int vortex_resume (struct pci_dev *pdev)
+static int vortex_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct vortex_private *vp = netdev_priv(dev);
@@ -1027,8 +1020,8 @@ static struct eisa_device_id vortex_eisa_ids[] = {
{ "" }
};
-static int vortex_eisa_probe (struct device *device);
-static int vortex_eisa_remove (struct device *device);
+static int vortex_eisa_probe(struct device *device);
+static int vortex_eisa_remove(struct device *device);
static struct eisa_driver vortex_eisa_driver = {
.id_table = vortex_eisa_ids,
@@ -1039,12 +1032,12 @@ static struct eisa_driver vortex_eisa_driver = {
}
};
-static int vortex_eisa_probe (struct device *device)
+static int vortex_eisa_probe(struct device *device)
{
void __iomem *ioaddr;
struct eisa_device *edev;
- edev = to_eisa_device (device);
+ edev = to_eisa_device(device);
if (!request_region(edev->base_addr, VORTEX_TOTAL_SIZE, DRV_NAME))
return -EBUSY;
@@ -1053,7 +1046,7 @@ static int vortex_eisa_probe (struct device *device)
if (vortex_probe1(device, ioaddr, ioread16(ioaddr + 0xC88) >> 12,
edev->id.driver_data, vortex_cards_found)) {
- release_region (edev->base_addr, VORTEX_TOTAL_SIZE);
+ release_region(edev->base_addr, VORTEX_TOTAL_SIZE);
return -ENODEV;
}
@@ -1062,15 +1055,15 @@ static int vortex_eisa_probe (struct device *device)
return 0;
}
-static int vortex_eisa_remove (struct device *device)
+static int vortex_eisa_remove(struct device *device)
{
struct eisa_device *edev;
struct net_device *dev;
struct vortex_private *vp;
void __iomem *ioaddr;
- edev = to_eisa_device (device);
- dev = eisa_get_drvdata (edev);
+ edev = to_eisa_device(device);
+ dev = eisa_get_drvdata(edev);
if (!dev) {
printk("vortex_eisa_remove called for Compaq device!\n");
@@ -1080,30 +1073,34 @@ static int vortex_eisa_remove (struct device *device)
vp = netdev_priv(dev);
ioaddr = vp->ioaddr;
- unregister_netdev (dev);
- iowrite16 (TotalReset|0x14, ioaddr + EL3_CMD);
- release_region (dev->base_addr, VORTEX_TOTAL_SIZE);
+ unregister_netdev(dev);
+ iowrite16(TotalReset|0x14, ioaddr + EL3_CMD);
+ release_region(dev->base_addr, VORTEX_TOTAL_SIZE);
- free_netdev (dev);
+ free_netdev(dev);
return 0;
}
#endif
/* returns count found (>= 0), or negative on error */
-static int __init vortex_eisa_init (void)
+static int __init vortex_eisa_init(void)
{
int eisa_found = 0;
int orig_cards_found = vortex_cards_found;
#ifdef CONFIG_EISA
- if (eisa_driver_register (&vortex_eisa_driver) >= 0) {
- /* Because of the way EISA bus is probed, we cannot assume
- * any device have been found when we exit from
- * eisa_driver_register (the bus root driver may not be
- * initialized yet). So we blindly assume something was
- * found, and let the sysfs magic happend... */
-
- eisa_found = 1;
+ int err;
+
+ err = eisa_driver_register (&vortex_eisa_driver);
+ if (!err) {
+ /*
+ * Because of the way EISA bus is probed, we cannot assume
+ * any device have been found when we exit from
+ * eisa_driver_register (the bus root driver may not be
+ * initialized yet). So we blindly assume something was
+ * found, and let the sysfs magic happend...
+ */
+ eisa_found = 1;
}
#endif
@@ -1117,7 +1114,7 @@ static int __init vortex_eisa_init (void)
}
/* returns count (>= 0), or negative on error */
-static int __devinit vortex_init_one (struct pci_dev *pdev,
+static int __devinit vortex_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int rc, unit, pci_bar;
@@ -1125,7 +1122,7 @@ static int __devinit vortex_init_one (struct pci_dev *pdev,
void __iomem *ioaddr;
/* wake up and enable device */
- rc = pci_enable_device (pdev);
+ rc = pci_enable_device(pdev);
if (rc < 0)
goto out;
@@ -1147,7 +1144,7 @@ static int __devinit vortex_init_one (struct pci_dev *pdev,
rc = vortex_probe1(&pdev->dev, ioaddr, pdev->irq,
ent->driver_data, unit);
if (rc < 0) {
- pci_disable_device (pdev);
+ pci_disable_device(pdev);
goto out;
}
@@ -1232,7 +1229,7 @@ static int __devinit vortex_probe1(struct device *gendev,
if (print_info)
printk (KERN_INFO "See Documentation/networking/vortex.txt\n");
- printk(KERN_INFO "%s: 3Com %s %s at %p. Vers " DRV_VERSION "\n",
+ printk(KERN_INFO "%s: 3Com %s %s at %p.\n",
print_name,
pdev ? "PCI" : "EISA",
vci->name,
@@ -1262,7 +1259,7 @@ static int __devinit vortex_probe1(struct device *gendev,
/* enable bus-mastering if necessary */
if (vci->flags & PCI_USES_MASTER)
- pci_set_master (pdev);
+ pci_set_master(pdev);
if (vci->drv_flags & IS_VORTEX) {
u8 pci_latency;
@@ -1306,7 +1303,7 @@ static int __devinit vortex_probe1(struct device *gendev,
if (pdev)
pci_set_drvdata(pdev, dev);
if (edev)
- eisa_set_drvdata (edev, dev);
+ eisa_set_drvdata(edev, dev);
vp->media_override = 7;
if (option >= 0) {
@@ -1331,7 +1328,7 @@ static int __devinit vortex_probe1(struct device *gendev,
vp->enable_wol = 1;
}
- vp->force_fd = vp->full_duplex;
+ vp->mii.force_media = vp->full_duplex;
vp->options = option;
/* Read the station address from the EEPROM. */
EL3WINDOW(0);
@@ -1621,6 +1618,46 @@ issue_and_wait(struct net_device *dev, int cmd)
}
static void
+vortex_set_duplex(struct net_device *dev)
+{
+ struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
+
+ printk(KERN_INFO "%s: setting %s-duplex.\n",
+ dev->name, (vp->full_duplex) ? "full" : "half");
+
+ EL3WINDOW(3);
+ /* Set the full-duplex bit. */
+ iowrite16(((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
+ (vp->large_frames ? 0x40 : 0) |
+ ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ?
+ 0x100 : 0),
+ ioaddr + Wn3_MAC_Ctrl);
+
+ issue_and_wait(dev, TxReset);
+ /*
+ * Don't reset the PHY - that upsets autonegotiation during DHCP operations.
+ */
+ issue_and_wait(dev, RxReset|0x04);
+}
+
+static void vortex_check_media(struct net_device *dev, unsigned int init)
+{
+ struct vortex_private *vp = netdev_priv(dev);
+ unsigned int ok_to_print = 0;
+
+ if (vortex_debug > 3)
+ ok_to_print = 1;
+
+ if (mii_check_media(&vp->mii, ok_to_print, init)) {
+ vp->full_duplex = vp->mii.full_duplex;
+ vortex_set_duplex(dev);
+ } else if (init) {
+ vortex_set_duplex(dev);
+ }
+}
+
+static void
vortex_up(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
@@ -1680,53 +1717,20 @@ vortex_up(struct net_device *dev)
printk(KERN_DEBUG "%s: Initial media type %s.\n",
dev->name, media_tbl[dev->if_port].name);
- vp->full_duplex = vp->force_fd;
+ vp->full_duplex = vp->mii.force_media;
config = BFINS(config, dev->if_port, 20, 4);
if (vortex_debug > 6)
printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n", config);
iowrite32(config, ioaddr + Wn3_Config);
+ netif_carrier_off(dev);
if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
- int mii_reg1, mii_reg5;
EL3WINDOW(4);
- /* Read BMSR (reg1) only to clear old status. */
- mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR);
- mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA);
- if (mii_reg5 == 0xffff || mii_reg5 == 0x0000) {
- netif_carrier_off(dev); /* No MII device or no link partner report */
- } else {
- mii_reg5 &= vp->advertising;
- if ((mii_reg5 & 0x0100) != 0 /* 100baseTx-FD */
- || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */
- vp->full_duplex = 1;
- netif_carrier_on(dev);
- }
- vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0);
- if (vortex_debug > 1)
- printk(KERN_INFO "%s: MII #%d status %4.4x, link partner capability %4.4x,"
- " info1 %04x, setting %s-duplex.\n",
- dev->name, vp->phys[0],
- mii_reg1, mii_reg5,
- vp->info1, ((vp->info1 & 0x8000) || vp->full_duplex) ? "full" : "half");
- EL3WINDOW(3);
- }
-
- /* Set the full-duplex bit. */
- iowrite16( ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
- (vp->large_frames ? 0x40 : 0) |
- ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
- ioaddr + Wn3_MAC_Ctrl);
-
- if (vortex_debug > 1) {
- printk(KERN_DEBUG "%s: vortex_up() InternalConfig %8.8x.\n",
- dev->name, config);
+ vortex_check_media(dev, 1);
}
+ else
+ vortex_set_duplex(dev);
- issue_and_wait(dev, TxReset);
- /*
- * Don't reset the PHY - that upsets autonegotiation during DHCP operations.
- */
- issue_and_wait(dev, RxReset|0x04);
iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
@@ -1801,7 +1805,6 @@ vortex_up(struct net_device *dev)
set_8021q_mode(dev, 1);
iowrite16(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
-// issue_and_wait(dev, SetTxStart|0x07ff);
iowrite16(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
iowrite16(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
/* Allow status bits to be seen. */
@@ -1888,7 +1891,7 @@ vortex_timer(unsigned long data)
void __iomem *ioaddr = vp->ioaddr;
int next_tick = 60*HZ;
int ok = 0;
- int media_status, mii_status, old_window;
+ int media_status, old_window;
if (vortex_debug > 2) {
printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n",
@@ -1896,8 +1899,6 @@ vortex_timer(unsigned long data)
printk(KERN_DEBUG "dev->watchdog_timeo=%d\n", dev->watchdog_timeo);
}
- if (vp->medialock)
- goto leave_media_alone;
disable_irq(dev->irq);
old_window = ioread16(ioaddr + EL3_CMD) >> 13;
EL3WINDOW(4);
@@ -1920,44 +1921,9 @@ 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], MII_BMSR);
- if (!(mii_status & BMSR_LSTATUS)) {
- /* Re-read to get actual link status */
- mii_status = mdio_read(dev, vp->phys[0], MII_BMSR);
- }
ok = 1;
- if (vortex_debug > 2)
- printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",
- dev->name, mii_status);
- if (mii_status & BMSR_LSTATUS) {
- int mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA);
- if (! vp->force_fd && mii_reg5 != 0xffff) {
- int duplex;
-
- mii_reg5 &= vp->advertising;
- duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040;
- if (vp->full_duplex != duplex) {
- vp->full_duplex = duplex;
- printk(KERN_INFO "%s: Setting %s-duplex based on MII "
- "#%d link partner capability of %4.4x.\n",
- dev->name, vp->full_duplex ? "full" : "half",
- vp->phys[0], mii_reg5);
- /* Set the full-duplex bit. */
- EL3WINDOW(3);
- iowrite16( (vp->full_duplex ? 0x20 : 0) |
- (vp->large_frames ? 0x40 : 0) |
- ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
- ioaddr + Wn3_MAC_Ctrl);
- if (vortex_debug > 1)
- printk(KERN_DEBUG "Setting duplex in Wn3_MAC_Ctrl\n");
- /* AKPM: bug: should reset Tx and Rx after setting Duplex. Page 180 */
- }
- }
- netif_carrier_on(dev);
- } else {
- netif_carrier_off(dev);
- }
+ spin_lock_bh(&vp->lock);
+ vortex_check_media(dev, 0);
spin_unlock_bh(&vp->lock);
}
break;
@@ -1967,7 +1933,14 @@ vortex_timer(unsigned long data)
dev->name, media_tbl[dev->if_port].name, media_status);
ok = 1;
}
- if ( ! ok) {
+
+ if (!netif_carrier_ok(dev))
+ next_tick = 5*HZ;
+
+ if (vp->medialock)
+ goto leave_media_alone;
+
+ if (!ok) {
unsigned int config;
do {
@@ -2000,14 +1973,14 @@ vortex_timer(unsigned long data)
printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", config);
/* AKPM: FIXME: Should reset Rx & Tx here. P60 of 3c90xc.pdf */
}
- EL3WINDOW(old_window);
- enable_irq(dev->irq);
leave_media_alone:
if (vortex_debug > 2)
printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n",
dev->name, media_tbl[dev->if_port].name);
+ EL3WINDOW(old_window);
+ enable_irq(dev->irq);
mod_timer(&vp->timer, RUN_AT(next_tick));
if (vp->deferred)
iowrite16(FakeIntr, ioaddr + EL3_CMD);
@@ -2202,7 +2175,7 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (vp->bus_master) {
/* Set the bus-master controller to transfer the packet. */
int len = (skb->len + 3) & ~3;
- iowrite32( vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len, PCI_DMA_TODEVICE),
+ iowrite32(vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len, PCI_DMA_TODEVICE),
ioaddr + Wn7_MasterAddr);
iowrite16(len, ioaddr + Wn7_MasterLen);
vp->tx_skb = skb;
@@ -2979,20 +2952,6 @@ static int vortex_nway_reset(struct net_device *dev)
return rc;
}
-static u32 vortex_get_link(struct net_device *dev)
-{
- struct vortex_private *vp = netdev_priv(dev);
- void __iomem *ioaddr = vp->ioaddr;
- 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);
@@ -3073,7 +3032,6 @@ static void vortex_get_drvinfo(struct net_device *dev,
struct vortex_private *vp = netdev_priv(dev);
strcpy(info->driver, DRV_NAME);
- strcpy(info->version, DRV_VERSION);
if (VORTEX_PCI(vp)) {
strcpy(info->bus_info, pci_name(VORTEX_PCI(vp)));
} else {
@@ -3094,9 +3052,9 @@ static struct ethtool_ops vortex_ethtool_ops = {
.get_stats_count = vortex_get_stats_count,
.get_settings = vortex_get_settings,
.set_settings = vortex_set_settings,
- .get_link = vortex_get_link,
+ .get_link = ethtool_op_get_link,
.nway_reset = vortex_nway_reset,
- .get_perm_addr = ethtool_op_get_perm_addr,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
#ifdef CONFIG_PCI
@@ -3297,7 +3255,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
}
return;
}
-
+
/* ACPI: Advanced Configuration and Power Interface. */
/* Set Wake-On-LAN mode and put the board into D3 (power-down) state. */
static void acpi_set_WOL(struct net_device *dev)
@@ -3321,7 +3279,7 @@ static void acpi_set_WOL(struct net_device *dev)
}
-static void __devexit vortex_remove_one (struct pci_dev *pdev)
+static void __devexit vortex_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct vortex_private *vp;
@@ -3377,7 +3335,7 @@ static int vortex_have_pci;
static int vortex_have_eisa;
-static int __init vortex_init (void)
+static int __init vortex_init(void)
{
int pci_rc, eisa_rc;
@@ -3393,14 +3351,14 @@ static int __init vortex_init (void)
}
-static void __exit vortex_eisa_cleanup (void)
+static void __exit vortex_eisa_cleanup(void)
{
struct vortex_private *vp;
void __iomem *ioaddr;
#ifdef CONFIG_EISA
/* Take care of the EISA devices */
- eisa_driver_unregister (&vortex_eisa_driver);
+ eisa_driver_unregister(&vortex_eisa_driver);
#endif
if (compaq_net_device) {
@@ -3408,33 +3366,24 @@ static void __exit vortex_eisa_cleanup (void)
ioaddr = ioport_map(compaq_net_device->base_addr,
VORTEX_TOTAL_SIZE);
- unregister_netdev (compaq_net_device);
- iowrite16 (TotalReset, ioaddr + EL3_CMD);
+ unregister_netdev(compaq_net_device);
+ iowrite16(TotalReset, ioaddr + EL3_CMD);
release_region(compaq_net_device->base_addr,
VORTEX_TOTAL_SIZE);
- free_netdev (compaq_net_device);
+ free_netdev(compaq_net_device);
}
}
-static void __exit vortex_cleanup (void)
+static void __exit vortex_cleanup(void)
{
if (vortex_have_pci)
- pci_unregister_driver (&vortex_driver);
+ pci_unregister_driver(&vortex_driver);
if (vortex_have_eisa)
- vortex_eisa_cleanup ();
+ vortex_eisa_cleanup();
}
module_init(vortex_init);
module_exit(vortex_cleanup);
-
-
-/*
- * Local variables:
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index 8e538a6d7d9..79bb56b8dce 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -829,7 +829,7 @@ static void __devexit a2065_remove_one(struct zorro_dev *z)
static int __init a2065_init_module(void)
{
- return zorro_module_init(&a2065_driver);
+ return zorro_register_driver(&a2065_driver);
}
static void __exit a2065_cleanup_module(void)
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index 9fe93acfc8e..d1b6b1f794e 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -864,7 +864,7 @@ static void __devexit ariadne_remove_one(struct zorro_dev *z)
static int __init ariadne_init_module(void)
{
- return zorro_module_init(&ariadne_driver);
+ return zorro_register_driver(&ariadne_driver);
}
static void __exit ariadne_cleanup_module(void)
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index 625184b65e3..77fe20dbea3 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -31,3 +31,11 @@ config ARM_ETHERH
help
If you have an Acorn system with one of these network cards, you
should say Y to this option if you wish to use it with Linux.
+
+config ARM_AT91_ETHER
+ tristate "AT91RM9200 Ethernet support"
+ depends on NET_ETHERNET && ARM && ARCH_AT91RM9200
+ select MII
+ help
+ If you wish to compile a kernel for the AT91RM9200 and enable
+ ethernet support, then you should always answer Y to this.
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile
index bc263edf06a..42c95b79c26 100644
--- a/drivers/net/arm/Makefile
+++ b/drivers/net/arm/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
obj-$(CONFIG_ARM_ETHERH) += etherh.o
obj-$(CONFIG_ARM_ETHER3) += ether3.o
obj-$(CONFIG_ARM_ETHER1) += ether1.o
+obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
new file mode 100644
index 00000000000..5503dc8a66e
--- /dev/null
+++ b/drivers/net/arm/at91_ether.c
@@ -0,0 +1,1110 @@
+/*
+ * Ethernet driver for the Atmel AT91RM9200 (Thunder)
+ *
+ * Copyright (C) 2003 SAN People (Pty) Ltd
+ *
+ * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
+ * Initial version by Rick Bronson 01/11/2003
+ *
+ * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker
+ * (Polaroid Corporation)
+ *
+ * Realtek RTL8201(B)L PHY support by Roman Avramenko <roman@imsystems.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/mii.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
+#include <linux/ethtool.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/at91rm9200_emac.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/board.h>
+
+#include "at91_ether.h"
+
+#define DRV_NAME "at91_ether"
+#define DRV_VERSION "1.0"
+
+static struct net_device *at91_dev;
+static struct clk *ether_clk;
+
+/* ..................................................................... */
+
+/*
+ * Read from a EMAC register.
+ */
+static inline unsigned long at91_emac_read(unsigned int reg)
+{
+ void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
+
+ return __raw_readl(emac_base + reg);
+}
+
+/*
+ * Write to a EMAC register.
+ */
+static inline void at91_emac_write(unsigned int reg, unsigned long value)
+{
+ void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
+
+ __raw_writel(value, emac_base + reg);
+}
+
+/* ........................... PHY INTERFACE ........................... */
+
+/*
+ * Enable the MDIO bit in MAC control register
+ * When not called from an interrupt-handler, access to the PHY must be
+ * protected by a spinlock.
+ */
+static void enable_mdi(void)
+{
+ unsigned long ctl;
+
+ ctl = at91_emac_read(AT91_EMAC_CTL);
+ at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_MPE); /* enable management port */
+}
+
+/*
+ * Disable the MDIO bit in the MAC control register
+ */
+static void disable_mdi(void)
+{
+ unsigned long ctl;
+
+ ctl = at91_emac_read(AT91_EMAC_CTL);
+ at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE); /* disable management port */
+}
+
+/*
+ * Wait until the PHY operation is complete.
+ */
+static inline void at91_phy_wait(void) {
+ unsigned long timeout = jiffies + 2;
+
+ while (!(at91_emac_read(AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
+ if (time_after(jiffies, timeout)) {
+ printk("at91_ether: MIO timeout\n");
+ break;
+ }
+ cpu_relax();
+ }
+}
+
+/*
+ * Write value to the a PHY register
+ * Note: MDI interface is assumed to already have been enabled.
+ */
+static void write_phy(unsigned char phy_addr, unsigned char address, unsigned int value)
+{
+ at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
+ | ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA));
+
+ /* Wait until IDLE bit in Network Status register is cleared */
+ at91_phy_wait();
+}
+
+/*
+ * Read value stored in a PHY register.
+ * Note: MDI interface is assumed to already have been enabled.
+ */
+static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int *value)
+{
+ at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
+ | ((phy_addr & 0x1f) << 23) | (address << 18));
+
+ /* Wait until IDLE bit in Network Status register is cleared */
+ at91_phy_wait();
+
+ *value = at91_emac_read(AT91_EMAC_MAN) & AT91_EMAC_DATA;
+}
+
+/* ........................... PHY MANAGEMENT .......................... */
+
+/*
+ * Access the PHY to determine the current link speed and mode, and update the
+ * MAC accordingly.
+ * If no link or auto-negotiation is busy, then no changes are made.
+ */
+static void update_linkspeed(struct net_device *dev)
+{
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+ unsigned int bmsr, bmcr, lpa, mac_cfg;
+ unsigned int speed, duplex;
+
+ if (!mii_link_ok(&lp->mii)) { /* no link */
+ netif_carrier_off(dev);
+ printk(KERN_INFO "%s: Link down.\n", dev->name);
+ return;
+ }
+
+ /* Link up, or auto-negotiation still in progress */
+ read_phy(lp->phy_address, MII_BMSR, &bmsr);
+ read_phy(lp->phy_address, MII_BMCR, &bmcr);
+ if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */
+ if (!(bmsr & BMSR_ANEGCOMPLETE))
+ return; /* Do nothing - another interrupt generated when negotiation complete */
+
+ read_phy(lp->phy_address, MII_LPA, &lpa);
+ if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
+ else speed = SPEED_10;
+ if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
+ else duplex = DUPLEX_HALF;
+ } else {
+ speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
+ duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
+ }
+
+ /* Update the MAC */
+ mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD);
+ if (speed == SPEED_100) {
+ if (duplex == DUPLEX_FULL) /* 100 Full Duplex */
+ mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD;
+ else /* 100 Half Duplex */
+ mac_cfg |= AT91_EMAC_SPD;
+ } else {
+ if (duplex == DUPLEX_FULL) /* 10 Full Duplex */
+ mac_cfg |= AT91_EMAC_FD;
+ else {} /* 10 Half Duplex */
+ }
+ at91_emac_write(AT91_EMAC_CFG, mac_cfg);
+
+ printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
+ netif_carrier_on(dev);
+}
+
+/*
+ * Handle interrupts from the PHY
+ */
+static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+ unsigned int phy;
+
+ /*
+ * This hander is triggered on both edges, but the PHY chips expect
+ * level-triggering. We therefore have to check if the PHY actually has
+ * an IRQ pending.
+ */
+ enable_mdi();
+ if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
+ read_phy(lp->phy_address, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */
+ if (!(phy & (1 << 0)))
+ goto done;
+ }
+ else if (lp->phy_type == MII_LXT971A_ID) {
+ read_phy(lp->phy_address, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */
+ if (!(phy & (1 << 2)))
+ goto done;
+ }
+ else if (lp->phy_type == MII_BCM5221_ID) {
+ read_phy(lp->phy_address, MII_BCMINTR_REG, &phy); /* ack interrupt in Broadcom PHY */
+ if (!(phy & (1 << 0)))
+ goto done;
+ }
+ else if (lp->phy_type == MII_KS8721_ID) {
+ read_phy(lp->phy_address, MII_TPISTATUS, &phy); /* ack interrupt in Micrel PHY */
+ if (!(phy & ((1 << 2) | 1)))
+ goto done;
+ }
+
+ update_linkspeed(dev);
+
+done:
+ disable_mdi();
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Initialize and enable the PHY interrupt for link-state changes
+ */
+static void enable_phyirq(struct net_device *dev)
+{
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+ unsigned int dsintr, irq_number;
+ int status;
+
+ if (lp->phy_type == MII_RTL8201_ID) /* RTL8201 does not have an interrupt */
+ return;
+ if (lp->phy_type == MII_DP83847_ID) /* DP83847 does not have an interrupt */
+ return;
+ if (lp->phy_type == MII_AC101L_ID) /* AC101L interrupt not supported yet */
+ return;
+
+ irq_number = lp->board_data.phy_irq_pin;
+ status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev);
+ if (status) {
+ printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status);
+ return;
+ }
+
+ spin_lock_irq(&lp->lock);
+ enable_mdi();
+
+ if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */
+ read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
+ dsintr = dsintr & ~0xf00; /* clear bits 8..11 */
+ write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
+ }
+ else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
+ read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
+ dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */
+ write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
+ }
+ else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */
+ dsintr = (1 << 15) | ( 1 << 14);
+ write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
+ }
+ else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */
+ dsintr = (1 << 10) | ( 1 << 8);
+ write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
+ }
+
+ disable_mdi();
+ spin_unlock_irq(&lp->lock);
+}
+
+/*
+ * Disable the PHY interrupt
+ */
+static void disable_phyirq(struct net_device *dev)
+{
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+ unsigned int dsintr;
+ unsigned int irq_number;
+
+ if (lp->phy_type == MII_RTL8201_ID) /* RTL8201 does not have an interrupt */
+ return;
+ if (lp->phy_type == MII_DP83847_ID) /* DP83847 does not have an interrupt */
+ return;
+ if (lp->phy_type == MII_AC101L_ID) /* AC101L interrupt not supported yet */
+ return;
+
+ spin_lock_irq(&lp->lock);
+ enable_mdi();
+
+ if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */
+ read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
+ dsintr = dsintr | 0xf00; /* set bits 8..11 */
+ write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
+ }
+ else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
+ read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
+ dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */
+ write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
+ }
+ else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */
+ read_phy(lp->phy_address, MII_BCMINTR_REG, &dsintr);
+ dsintr = ~(1 << 14);
+ write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
+ }
+ else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */
+ read_phy(lp->phy_address, MII_TPISTATUS, &dsintr);
+ dsintr = ~((1 << 10) | (1 << 8));
+ write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
+ }
+
+ disable_mdi();
+ spin_unlock_irq(&lp->lock);
+
+ irq_number = lp->board_data.phy_irq_pin;
+ free_irq(irq_number, dev); /* Free interrupt handler */
+}
+
+/*
+ * Perform a software reset of the PHY.
+ */
+#if 0
+static void reset_phy(struct net_device *dev)
+{
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+ unsigned int bmcr;
+
+ spin_lock_irq(&lp->lock);
+ enable_mdi();
+
+ /* Perform PHY reset */
+ write_phy(lp->phy_address, MII_BMCR, BMCR_RESET);
+
+ /* Wait until PHY reset is complete */
+ do {
+ read_phy(lp->phy_address, MII_BMCR, &bmcr);
+ } while (!(bmcr && BMCR_RESET));
+
+ disable_mdi();
+ spin_unlock_irq(&lp->lock);
+}
+#endif
+
+/* ......................... ADDRESS MANAGEMENT ........................ */
+
+/*
+ * NOTE: Your bootloader must always set the MAC address correctly before
+ * booting into Linux.
+ *
+ * - It must always set the MAC address after reset, even if it doesn't
+ * happen to access the Ethernet while it's booting. Some versions of
+ * U-Boot on the AT91RM9200-DK do not do this.
+ *
+ * - Likewise it must store the addresses in the correct byte order.
+ * MicroMonitor (uMon) on the CSB337 does this incorrectly (and
+ * continues to do so, for bug-compatibility).
+ */
+
+static short __init unpack_mac_address(struct net_device *dev, unsigned int hi, unsigned int lo)
+{
+ char addr[6];
+
+ if (machine_is_csb337()) {
+ addr[5] = (lo & 0xff); /* The CSB337 bootloader stores the MAC the wrong-way around */
+ addr[4] = (lo & 0xff00) >> 8;
+ addr[3] = (lo & 0xff0000) >> 16;
+ addr[2] = (lo & 0xff000000) >> 24;
+ addr[1] = (hi & 0xff);
+ addr[0] = (hi & 0xff00) >> 8;
+ }
+ else {
+ addr[0] = (lo & 0xff);
+ addr[1] = (lo & 0xff00) >> 8;
+ addr[2] = (lo & 0xff0000) >> 16;
+ addr[3] = (lo & 0xff000000) >> 24;
+ addr[4] = (hi & 0xff);
+ addr[5] = (hi & 0xff00) >> 8;
+ }
+
+ if (is_valid_ether_addr(addr)) {
+ memcpy(dev->dev_addr, &addr, 6);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Set the ethernet MAC address in dev->dev_addr
+ */
+static void __init get_mac_address(struct net_device *dev)
+{
+ /* Check Specific-Address 1 */
+ if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA1H), at91_emac_read(AT91_EMAC_SA1L)))
+ return;
+ /* Check Specific-Address 2 */
+ if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA2H), at91_emac_read(AT91_EMAC_SA2L)))
+ return;
+ /* Check Specific-Address 3 */
+ if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA3H), at91_emac_read(AT91_EMAC_SA3L)))
+ return;
+ /* Check Specific-Address 4 */
+ if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA4H), at91_emac_read(AT91_EMAC_SA4L)))
+ return;
+
+ printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n");
+}
+
+/*
+ * Program the hardware MAC address from dev->dev_addr.
+ */
+static void update_mac_address(struct net_device *dev)
+{
+ at91_emac_write(AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
+ at91_emac_write(AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
+
+ at91_emac_write(AT91_EMAC_SA2L, 0);
+ at91_emac_write(AT91_EMAC_SA2H, 0);
+}
+
+/*
+ * Store the new hardware address in dev->dev_addr, and update the MAC.
+ */
+static int set_mac_address(struct net_device *dev, void* addr)
+{
+ struct sockaddr *address = addr;
+
+ if (!is_valid_ether_addr(address->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
+ update_mac_address(dev);
+
+ printk("%s: Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+
+ return 0;
+}
+
+static int inline hash_bit_value(int bitnr, __u8 *addr)
+{
+ if (addr[bitnr / 8] & (1 << (bitnr % 8)))
+ return 1;
+ return 0;
+}
+
+/*
+ * The hash address register is 64 bits long and takes up two locations in the memory map.
+ * The least significant bits are stored in EMAC_HSL and the most significant
+ * bits in EMAC_HSH.
+ *
+ * The unicast hash enable and the multicast hash enable bits in the network configuration
+ * register enable the reception of hash matched frames. The destination address is
+ * reduced to a 6 bit index into the 64 bit hash register using the following hash function.
+ * The hash function is an exclusive or of every sixth bit of the destination address.
+ * hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
+ * hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
+ * hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
+ * hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
+ * hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
+ * hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]
+ * da[0] represents the least significant bit of the first byte received, that is, the multicast/
+ * unicast indicator, and da[47] represents the most significant bit of the last byte
+ * received.
+ * If the hash index points to a bit that is set in the hash register then the frame will be
+ * matched according to whether the frame is multicast or unicast.
+ * A multicast match will be signalled if the multicast hash enable bit is set, da[0] is 1 and
+ * the hash index points to a bit set in the hash register.
+ * A unicast match will be signalled if the unicast hash enable bit is set, da[0] is 0 and the
+ * hash index points to a bit set in the hash register.
+ * To receive all multicast frames, the hash register should be set with all ones and the
+ * multicast hash enable bit should be set in the network configuration register.
+ */
+
+/*
+ * Return the hash index value for the specified address.
+ */
+static int hash_get_index(__u8 *addr)
+{
+ int i, j, bitval;
+ int hash_index = 0;
+
+ for (j = 0; j < 6; j++) {
+ for (i = 0, bitval = 0; i < 8; i++)
+ bitval ^= hash_bit_value(i*6 + j, addr);
+
+ hash_index |= (bitval << j);
+ }
+
+ return hash_index;
+}
+
+/*
+ * Add multicast addresses to the internal multicast-hash table.
+ */
+static void at91ether_sethashtable(struct net_device *dev)
+{
+ struct dev_mc_list *curr;
+ unsigned long mc_filter[2];
+ unsigned int i, bitnr;
+
+ mc_filter[0] = mc_filter[1] = 0;
+
+ curr = dev->mc_list;
+ for (i = 0; i < dev->mc_count; i++, curr = curr->next) {
+ if (!curr) break; /* unexpected end of list */
+
+ bitnr = hash_get_index(curr->dmi_addr);
+ mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
+ }
+
+ at91_emac_write(AT91_EMAC_HSH, mc_filter[0]);
+ at91_emac_write(AT91_EMAC_HSL, mc_filter[1]);
+}
+
+/*
+ * Enable/Disable promiscuous and multicast modes.
+ */
+static void at91ether_set_rx_mode(struct net_device *dev)
+{
+ unsigned long cfg;
+
+ cfg = at91_emac_read(AT91_EMAC_CFG);
+
+ if (dev->flags & IFF_PROMISC) /* Enable promiscuous mode */
+ cfg |= AT91_EMAC_CAF;
+ else if (dev->flags & (~IFF_PROMISC)) /* Disable promiscuous mode */
+ cfg &= ~AT91_EMAC_CAF;
+
+ if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */
+ at91_emac_write(AT91_EMAC_HSH, -1);
+ at91_emac_write(AT91_EMAC_HSL, -1);
+ cfg |= AT91_EMAC_MTI;
+ } else if (dev->mc_count > 0) { /* Enable specific multicasts */
+ at91ether_sethashtable(dev);
+ cfg |= AT91_EMAC_MTI;
+ } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */
+ at91_emac_write(AT91_EMAC_HSH, 0);
+ at91_emac_write(AT91_EMAC_HSL, 0);
+ cfg &= ~AT91_EMAC_MTI;
+ }
+
+ at91_emac_write(AT91_EMAC_CFG, cfg);
+}
+
+
+/* ......................... ETHTOOL SUPPORT ........................... */
+
+
+static int mdio_read(struct net_device *dev, int phy_id, int location)
+{
+ unsigned int value;
+
+ read_phy(phy_id, location, &value);
+ return value;
+}
+
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
+{
+ write_phy(phy_id, location, value);
+}
+
+static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+ int ret;
+
+ spin_lock_irq(&lp->lock);
+ enable_mdi();
+
+ ret = mii_ethtool_gset(&lp->mii, cmd);
+
+ disable_mdi();
+ spin_unlock_irq(&lp->lock);
+
+ if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */
+ cmd->supported = SUPPORTED_FIBRE;
+ cmd->port = PORT_FIBRE;
+ }
+
+ return ret;
+}
+
+static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+ int ret;
+
+ spin_lock_irq(&lp->lock);
+ enable_mdi();
+
+ ret = mii_ethtool_sset(&lp->mii, cmd);
+
+ disable_mdi();
+ spin_unlock_irq(&lp->lock);
+
+ return ret;
+}
+
+static int at91ether_nwayreset(struct net_device *dev)
+{
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+ int ret;
+
+ spin_lock_irq(&lp->lock);
+ enable_mdi();
+
+ ret = mii_nway_restart(&lp->mii);
+
+ disable_mdi();
+ spin_unlock_irq(&lp->lock);
+
+ return ret;
+}
+
+static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+ strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+ strlcpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info));
+}
+
+static struct ethtool_ops at91ether_ethtool_ops = {
+ .get_settings = at91ether_get_settings,
+ .set_settings = at91ether_set_settings,
+ .get_drvinfo = at91ether_get_drvinfo,
+ .nway_reset = at91ether_nwayreset,
+ .get_link = ethtool_op_get_link,
+};
+
+
+/* ................................ MAC ................................ */
+
+/*
+ * Initialize and start the Receiver and Transmit subsystems
+ */
+static void at91ether_start(struct net_device *dev)
+{
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+ struct recv_desc_bufs *dlist, *dlist_phys;
+ int i;
+ unsigned long ctl;
+
+ dlist = lp->dlist;
+ dlist_phys = lp->dlist_phys;
+
+ for (i = 0; i < MAX_RX_DESCR; i++) {
+ dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0];
+ dlist->descriptors[i].size = 0;
+ }
+
+ /* Set the Wrap bit on the last descriptor */
+ dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP;
+
+ /* Reset buffer index */
+ lp->rxBuffIndex = 0;
+
+ /* Program address of descriptor list in Rx Buffer Queue register */
+ at91_emac_write(AT91_EMAC_RBQP, (unsigned long) dlist_phys);
+
+ /* Enable Receive and Transmit */
+ ctl = at91_emac_read(AT91_EMAC_CTL);
+ at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
+}
+
+/*
+ * Open the ethernet interface
+ */
+static int at91ether_open(struct net_device *dev)
+{
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+ unsigned long ctl;
+
+ if (!is_valid_ether_addr(dev->dev_addr))
+ return -EADDRNOTAVAIL;
+
+ clk_enable(ether_clk); /* Re-enable Peripheral clock */
+
+ /* Clear internal statistics */
+ ctl = at91_emac_read(AT91_EMAC_CTL);
+ at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
+
+ /* Update the MAC address (incase user has changed it) */
+ update_mac_address(dev);
+
+ /* Enable PHY interrupt */
+ enable_phyirq(dev);
+
+ /* Enable MAC interrupts */
+ at91_emac_write(AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
+ | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
+ | AT91_EMAC_ROVR | AT91_EMAC_ABT);
+
+ /* Determine current link speed */
+ spin_lock_irq(&lp->lock);
+ enable_mdi();
+ update_linkspeed(dev);
+ disable_mdi();
+ spin_unlock_irq(&lp->lock);
+
+ at91ether_start(dev);
+ netif_start_queue(dev);
+ return 0;
+}
+
+/*
+ * Close the interface
+ */
+static int at91ether_close(struct net_device *dev)
+{
+ unsigned long ctl;
+
+ /* Disable Receiver and Transmitter */
+ ctl = at91_emac_read(AT91_EMAC_CTL);
+ at91_emac_write(AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
+
+ /* Disable PHY interrupt */
+ disable_phyirq(dev);
+
+ /* Disable MAC interrupts */
+ at91_emac_write(AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
+ | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
+ | AT91_EMAC_ROVR | AT91_EMAC_ABT);
+
+ netif_stop_queue(dev);
+
+ clk_disable(ether_clk); /* Disable Peripheral clock */
+
+ return 0;
+}
+
+/*
+ * Transmit packet.
+ */
+static int at91ether_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+
+ if (at91_emac_read(AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
+ netif_stop_queue(dev);
+
+ /* Store packet information (to free when Tx completed) */
+ lp->skb = skb;
+ lp->skb_length = skb->len;
+ lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE);
+ lp->stats.tx_bytes += skb->len;
+
+ /* Set address of the data in the Transmit Address register */
+ at91_emac_write(AT91_EMAC_TAR, lp->skb_physaddr);
+ /* Set length of the packet in the Transmit Control register */
+ at91_emac_write(AT91_EMAC_TCR, skb->len);
+
+ dev->trans_start = jiffies;
+ } else {
+ printk(KERN_ERR "at91_ether.c: at91ether_tx() called, but device is busy!\n");
+ return 1; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb)
+ on this skb, he also reports -ENETDOWN and printk's, so either
+ we free and return(0) or don't free and return 1 */
+ }
+
+ return 0;
+}
+
+/*
+ * Update the current statistics from the internal statistics registers.
+ */
+static struct net_device_stats *at91ether_stats(struct net_device *dev)
+{
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+ int ale, lenerr, seqe, lcol, ecol;
+
+ if (netif_running(dev)) {
+ lp->stats.rx_packets += at91_emac_read(AT91_EMAC_OK); /* Good frames received */
+ ale = at91_emac_read(AT91_EMAC_ALE);
+ lp->stats.rx_frame_errors += ale; /* Alignment errors */
+ lenerr = at91_emac_read(AT91_EMAC_ELR) + at91_emac_read(AT91_EMAC_USF);
+ lp->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */
+ seqe = at91_emac_read(AT91_EMAC_SEQE);
+ lp->stats.rx_crc_errors += seqe; /* CRC error */
+ lp->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC); /* Receive buffer not available */
+ lp->stats.rx_errors += (ale + lenerr + seqe
+ + at91_emac_read(AT91_EMAC_CDE) + at91_emac_read(AT91_EMAC_RJB));
+
+ lp->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA); /* Frames successfully transmitted */
+ lp->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE); /* Transmit FIFO underruns */
+ lp->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE); /* Carrier Sense errors */
+ lp->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */
+
+ lcol = at91_emac_read(AT91_EMAC_LCOL);
+ ecol = at91_emac_read(AT91_EMAC_ECOL);
+ lp->stats.tx_window_errors += lcol; /* Late collisions */
+ lp->stats.tx_aborted_errors += ecol; /* 16 collisions */
+
+ lp->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol);
+ }
+ return &lp->stats;
+}
+
+/*
+ * Extract received frame from buffer descriptors and sent to upper layers.
+ * (Called from interrupt context)
+ */
+static void at91ether_rx(struct net_device *dev)
+{
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+ struct recv_desc_bufs *dlist;
+ unsigned char *p_recv;
+ struct sk_buff *skb;
+ unsigned int pktlen;
+
+ dlist = lp->dlist;
+ while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
+ p_recv = dlist->recv_buf[lp->rxBuffIndex];
+ pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */
+ skb = alloc_skb(pktlen + 2, GFP_ATOMIC);
+ if (skb != NULL) {
+ skb_reserve(skb, 2);
+ memcpy(skb_put(skb, pktlen), p_recv, pktlen);
+
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->len = pktlen;
+ dev->last_rx = jiffies;
+ lp->stats.rx_bytes += pktlen;
+ netif_rx(skb);
+ }
+ else {
+ lp->stats.rx_dropped += 1;
+ printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+ }
+
+ if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
+ lp->stats.multicast++;
+
+ dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */
+ if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */
+ lp->rxBuffIndex = 0;
+ else
+ lp->rxBuffIndex++;
+ }
+}
+
+/*
+ * MAC interrupt handler
+ */
+static irqreturn_t at91ether_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct at91_private *lp = (struct at91_private *) dev->priv;
+ unsigned long intstatus, ctl;
+
+ /* MAC Interrupt Status register indicates what interrupts are pending.
+ It is automatically cleared once read. */
+ intstatus = at91_emac_read(AT91_EMAC_ISR);
+
+ if (intstatus & AT91_EMAC_RCOM) /* Receive complete */
+ at91ether_rx(dev);
+
+ if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */
+ /* The TCOM bit is set even if the transmission failed. */
+ if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY))
+ lp->stats.tx_errors += 1;
+
+ if (lp->skb) {
+ dev_kfree_skb_irq(lp->skb);
+ lp->skb = NULL;
+ dma_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE);
+ }
+ netif_wake_queue(dev);
+ }
+
+ /* Work-around for Errata #11 */
+ if (intstatus & AT91_EMAC_RBNA) {
+ ctl = at91_emac_read(AT91_EMAC_CTL);
+ at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
+ at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
+ }
+
+ if (intstatus & AT91_EMAC_ROVR)
+ printk("%s: ROVR error\n", dev->name);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Initialize the ethernet interface
+ */
+static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address, struct platform_device *pdev)
+{
+ struct at91_eth_data *board_data = pdev->dev.platform_data;
+ struct net_device *dev;
+ struct at91_private *lp;
+ unsigned int val;
+ int res;
+
+ if (at91_dev) /* already initialized */
+ return 0;
+
+ dev = alloc_etherdev(sizeof(struct at91_private));
+ if (!dev)
+ return -ENOMEM;
+
+ dev->base_addr = AT91_VA_BASE_EMAC;
+ dev->irq = AT91_ID_EMAC;
+ SET_MODULE_OWNER(dev);
+
+ /* Install the interrupt handler */
+ if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) {
+ free_netdev(dev);
+ return -EBUSY;
+ }
+
+ /* Allocate memory for DMA Receive descriptors */
+ lp = (struct at91_private *)dev->priv;
+ lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL);
+ if (lp->dlist == NULL) {
+ free_irq(dev->irq, dev);
+ free_netdev(dev);
+ return -ENOMEM;
+ }
+ lp->board_data = *board_data;
+ platform_set_drvdata(pdev, dev);
+
+ spin_lock_init(&lp->lock);
+
+ ether_setup(dev);
+ dev->open = at91ether_open;
+ dev->stop = at91ether_close;
+ dev->hard_start_xmit = at91ether_tx;
+ dev->get_stats = at91ether_stats;
+ dev->set_multicast_list = at91ether_set_rx_mode;
+ dev->set_mac_address = set_mac_address;
+ dev->ethtool_ops = &at91ether_ethtool_ops;
+
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */
+ update_mac_address(dev); /* Program ethernet address into MAC */
+
+ at91_emac_write(AT91_EMAC_CTL, 0);
+
+ if (lp->board_data.is_rmii)
+ at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII);
+ else
+ at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG);
+
+ /* Perform PHY-specific initialization */
+ spin_lock_irq(&lp->lock);
+ enable_mdi();
+ if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
+ read_phy(phy_address, MII_DSCR_REG, &val);
+ if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */
+ lp->phy_media = PORT_FIBRE;
+ } else if (machine_is_csb337()) {
+ /* mix link activity status into LED2 link state */
+ write_phy(phy_address, MII_LEDCTRL_REG, 0x0d22);
+ }
+ disable_mdi();
+ spin_unlock_irq(&lp->lock);
+
+ lp->mii.dev = dev; /* Support for ethtool */
+ lp->mii.mdio_read = mdio_read;
+ lp->mii.mdio_write = mdio_write;
+
+ lp->phy_type = phy_type; /* Type of PHY connected */
+ lp->phy_address = phy_address; /* MDI address of PHY */
+
+ /* Register the network interface */
+ res = register_netdev(dev);
+ if (res) {
+ free_irq(dev->irq, dev);
+ free_netdev(dev);
+ dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
+ return res;
+ }
+ at91_dev = dev;
+
+ /* Determine current link speed */
+ spin_lock_irq(&lp->lock);
+ enable_mdi();
+ update_linkspeed(dev);
+ disable_mdi();
+ spin_unlock_irq(&lp->lock);
+ netif_carrier_off(dev); /* will be enabled in open() */
+
+ /* Display ethernet banner */
+ printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%02x:%02x:%02x:%02x:%02x:%02x)\n",
+ dev->name, (uint) dev->base_addr, dev->irq,
+ at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
+ at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+ if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
+ printk(KERN_INFO "%s: Davicom 9196 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
+ else if (phy_type == MII_LXT971A_ID)
+ printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
+ else if (phy_type == MII_RTL8201_ID)
+ printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name);
+ else if (phy_type == MII_BCM5221_ID)
+ printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name);
+ else if (phy_type == MII_DP83847_ID)
+ printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name);
+ else if (phy_type == MII_AC101L_ID)
+ printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name);
+ else if (phy_type == MII_KS8721_ID)
+ printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name);
+
+ return 0;
+}
+
+/*
+ * Detect MAC and PHY and perform initialization
+ */
+static int __init at91ether_probe(struct platform_device *pdev)
+{
+ unsigned int phyid1, phyid2;
+ int detected = -1;
+ unsigned long phy_id;
+ unsigned short phy_address = 0;
+
+ ether_clk = clk_get(&pdev->dev, "ether_clk");
+ if (!ether_clk) {
+ printk(KERN_ERR "at91_ether: no clock defined\n");
+ return -ENODEV;
+ }
+ clk_enable(ether_clk); /* Enable Peripheral clock */
+
+ while ((detected != 0) && (phy_address < 32)) {
+ /* Read the PHY ID registers */
+ enable_mdi();
+ read_phy(phy_address, MII_PHYSID1, &phyid1);
+ read_phy(phy_address, MII_PHYSID2, &phyid2);
+ disable_mdi();
+
+ phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
+ switch (phy_id) {
+ case MII_DM9161_ID: /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */
+ case MII_DM9161A_ID: /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
+ case MII_LXT971A_ID: /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
+ case MII_RTL8201_ID: /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
+ case MII_BCM5221_ID: /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
+ case MII_DP83847_ID: /* National Semiconductor DP83847: */
+ case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
+ case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
+ detected = at91ether_setup(phy_id, phy_address, pdev);
+ break;
+ }
+
+ phy_address++;
+ }
+
+ clk_disable(ether_clk); /* Disable Peripheral clock */
+
+ return detected;
+}
+
+static int __devexit at91ether_remove(struct platform_device *pdev)
+{
+ struct at91_private *lp = (struct at91_private *) at91_dev->priv;
+
+ unregister_netdev(at91_dev);
+ free_irq(at91_dev->irq, at91_dev);
+ dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
+ clk_put(ether_clk);
+
+ free_netdev(at91_dev);
+ at91_dev = NULL;
+ return 0;
+}
+
+static struct platform_driver at91ether_driver = {
+ .probe = at91ether_probe,
+ .remove = __devexit_p(at91ether_remove),
+ /* FIXME: support suspend and resume */
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init at91ether_init(void)
+{
+ return platform_driver_register(&at91ether_driver);
+}
+
+static void __exit at91ether_exit(void)
+{
+ platform_driver_unregister(&at91ether_driver);
+}
+
+module_init(at91ether_init)
+module_exit(at91ether_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
+MODULE_AUTHOR("Andrew Victor");
diff --git a/drivers/net/arm/at91_ether.h b/drivers/net/arm/at91_ether.h
new file mode 100644
index 00000000000..9885735c9c8
--- /dev/null
+++ b/drivers/net/arm/at91_ether.h
@@ -0,0 +1,101 @@
+/*
+ * Ethernet driver for the Atmel AT91RM9200 (Thunder)
+ *
+ * Copyright (C) SAN People (Pty) Ltd
+ *
+ * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
+ * Initial version by Rick Bronson.
+ *
+ * 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.
+ */
+
+#ifndef AT91_ETHERNET
+#define AT91_ETHERNET
+
+
+/* Davicom 9161 PHY */
+#define MII_DM9161_ID 0x0181b880
+#define MII_DM9161A_ID 0x0181b8a0
+
+/* Davicom specific registers */
+#define MII_DSCR_REG 16
+#define MII_DSCSR_REG 17
+#define MII_DSINTR_REG 21
+
+/* Intel LXT971A PHY */
+#define MII_LXT971A_ID 0x001378E0
+
+/* Intel specific registers */
+#define MII_ISINTE_REG 18
+#define MII_ISINTS_REG 19
+#define MII_LEDCTRL_REG 20
+
+/* Realtek RTL8201 PHY */
+#define MII_RTL8201_ID 0x00008200
+
+/* Broadcom BCM5221 PHY */
+#define MII_BCM5221_ID 0x004061e0
+
+/* Broadcom specific registers */
+#define MII_BCMINTR_REG 26
+
+/* National Semiconductor DP83847 */
+#define MII_DP83847_ID 0x20005c30
+
+/* Altima AC101L PHY */
+#define MII_AC101L_ID 0x00225520
+
+/* Micrel KS8721 PHY */
+#define MII_KS8721_ID 0x00221610
+
+/* ........................................................................ */
+
+#define MAX_RBUFF_SZ 0x600 /* 1518 rounded up */
+#define MAX_RX_DESCR 9 /* max number of receive buffers */
+
+#define EMAC_DESC_DONE 0x00000001 /* bit for if DMA is done */
+#define EMAC_DESC_WRAP 0x00000002 /* bit for wrap */
+
+#define EMAC_BROADCAST 0x80000000 /* broadcast address */
+#define EMAC_MULTICAST 0x40000000 /* multicast address */
+#define EMAC_UNICAST 0x20000000 /* unicast address */
+
+struct rbf_t
+{
+ unsigned int addr;
+ unsigned long size;
+};
+
+struct recv_desc_bufs
+{
+ struct rbf_t descriptors[MAX_RX_DESCR]; /* must be on sizeof (rbf_t) boundary */
+ char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ]; /* must be on long boundary */
+};
+
+struct at91_private
+{
+ struct net_device_stats stats;
+ struct mii_if_info mii; /* ethtool support */
+ struct at91_eth_data board_data; /* board-specific configuration */
+
+ /* PHY */
+ unsigned long phy_type; /* type of PHY (PHY_ID) */
+ spinlock_t lock; /* lock for MDI interface */
+ short phy_media; /* media interface type */
+ unsigned short phy_address; /* 5-bit MDI address of PHY (0..31) */
+
+ /* Transmit */
+ struct sk_buff *skb; /* holds skb until xmit interrupt completes */
+ dma_addr_t skb_physaddr; /* phys addr from pci_map_single */
+ int skb_length; /* saved skb length for pci_unmap_single */
+
+ /* Receive */
+ int rxBuffIndex; /* index into receive descriptor list */
+ struct recv_desc_bufs *dlist; /* descriptor list address */
+ struct recv_desc_bufs *dlist_phys; /* descriptor list physical address */
+};
+
+#endif
diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c
index 0095384ff45..5e5f80b99b9 100644
--- a/drivers/net/atari_bionet.c
+++ b/drivers/net/atari_bionet.c
@@ -123,7 +123,7 @@ static char version[] =
* Global variable 'bionet_debug'. Can be set at load time by 'insmod'
*/
unsigned int bionet_debug = NET_DEBUG;
-MODULE_PARM(bionet_debug, "i");
+module_param(bionet_debug, int, 0);
MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c
index 8b997809f9d..d6039e62d83 100644
--- a/drivers/net/atari_pamsnet.c
+++ b/drivers/net/atari_pamsnet.c
@@ -119,7 +119,7 @@ static char *version =
* Global variable 'pamsnet_debug'. Can be set at load time by 'insmod'
*/
unsigned int pamsnet_debug = NET_DEBUG;
-MODULE_PARM(pamsnet_debug, "i");
+module_param(pamsnet_debug, int, 0);
MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index e01b6a78ec6..442b2cbeb58 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -78,7 +78,7 @@ static int lance_debug = LANCE_DEBUG;
#else
static int lance_debug = 1;
#endif
-MODULE_PARM(lance_debug, "i");
+module_param(lance_debug, int, 0);
MODULE_PARM_DESC(lance_debug, "atarilance debug level (0-3)");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 2d0ac169a86..f13a539dc16 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3159,7 +3159,7 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave
* bond_netdev_event: handle netdev notifier chain events.
*
* This function receives events for the netdev chain. The caller (an
- * ioctl handler calling notifier_call_chain) holds the necessary
+ * ioctl handler calling blocking_notifier_call_chain) holds the necessary
* locks for us to safely manipulate the slave devices (RTNL lock,
* dev_probe_lock).
*/
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 8f1573e658a..ac48f754350 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -192,12 +192,15 @@
static char version[] __devinitdata =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+static int cassini_debug = -1; /* -1 == use CAS_DEF_MSG_ENABLE as value */
+static int link_mode;
+
MODULE_AUTHOR("Adrian Sun (asun@darksunrising.com)");
MODULE_DESCRIPTION("Sun Cassini(+) ethernet driver");
MODULE_LICENSE("GPL");
-MODULE_PARM(cassini_debug, "i");
+module_param(cassini_debug, int, 0);
MODULE_PARM_DESC(cassini_debug, "Cassini bitmapped debugging message enable value");
-MODULE_PARM(link_mode, "i");
+module_param(link_mode, int, 0);
MODULE_PARM_DESC(link_mode, "default link mode");
/*
@@ -209,7 +212,7 @@ MODULE_PARM_DESC(link_mode, "default link mode");
* Value in seconds, for user input.
*/
static int linkdown_timeout = DEFAULT_LINKDOWN_TIMEOUT;
-MODULE_PARM(linkdown_timeout, "i");
+module_param(linkdown_timeout, int, 0);
MODULE_PARM_DESC(linkdown_timeout,
"min reset interval in sec. for PCS linkdown issue; disabled if not positive");
@@ -221,8 +224,6 @@ MODULE_PARM_DESC(linkdown_timeout,
static int link_transition_timeout;
-static int cassini_debug = -1; /* -1 == use CAS_DEF_MSG_ENABLE as value */
-static int link_mode;
static u16 link_modes[] __devinitdata = {
BMCR_ANENABLE, /* 0 : autoneg */
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index 349ebe783ed..7fe2638ae06 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -124,7 +124,7 @@ MODULE_LICENSE("GPL");
static int dflt_msg_enable = DFLT_MSG_ENABLE;
-MODULE_PARM(dflt_msg_enable, "i");
+module_param(dflt_msg_enable, int, 0);
MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 message enable bitmap");
diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c
index 32d13166c6e..e175d487668 100644
--- a/drivers/net/dgrs.c
+++ b/drivers/net/dgrs.c
@@ -1551,7 +1551,7 @@ MODULE_PARM_DESC(nicmode, "Digi RightSwitch operating mode (1: switch, 2: multi-
static int __init dgrs_init_module (void)
{
int i;
- int cardcount = 0;
+ int err;
/*
* Command line variable overrides
@@ -1593,13 +1593,13 @@ static int __init dgrs_init_module (void)
* Find and configure all the cards
*/
#ifdef CONFIG_EISA
- cardcount = eisa_driver_register(&dgrs_eisa_driver);
- if (cardcount < 0)
- return cardcount;
+ err = eisa_driver_register(&dgrs_eisa_driver);
+ if (err)
+ return err;
#endif
- cardcount = pci_register_driver(&dgrs_pci_driver);
- if (cardcount)
- return cardcount;
+ err = pci_register_driver(&dgrs_pci_driver);
+ if (err)
+ return err;
return 0;
}
diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c
index b4f3a9f8a53..7e433809713 100644
--- a/drivers/net/fec_8xx/fec_main.c
+++ b/drivers/net/fec_8xx/fec_main.c
@@ -55,11 +55,11 @@ MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
MODULE_DESCRIPTION("Motorola 8xx FEC ethernet driver");
MODULE_LICENSE("GPL");
-MODULE_PARM(fec_8xx_debug, "i");
+int fec_8xx_debug = -1; /* -1 == use FEC_8XX_DEF_MSG_ENABLE as value */
+module_param(fec_8xx_debug, int, 0);
MODULE_PARM_DESC(fec_8xx_debug,
"FEC 8xx bitmapped debugging message enable value");
-int fec_8xx_debug = -1; /* -1 == use FEC_8XX_DEF_MSG_ENABLE as value */
/*************************************************/
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index e7fc28b07e5..7627a75f4f7 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -134,6 +134,7 @@
#include <linux/random.h>
#include <linux/init.h>
#include <linux/if_vlan.h>
+#include <linux/dma-mapping.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -2932,7 +2933,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (id->driver_data & DEV_HAS_HIGH_DMA) {
/* packet format 3: supports 40-bit addressing */
np->desc_ver = DESC_VER_3;
- if (pci_set_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
+ if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) {
printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
pci_name(pci_dev));
} else {
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index f5d49a11065..196298f33db 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -58,11 +58,11 @@ MODULE_DESCRIPTION("Freescale Ethernet Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
-MODULE_PARM(fs_enet_debug, "i");
+int fs_enet_debug = -1; /* -1 == use FS_ENET_DEF_MSG_ENABLE as value */
+module_param(fs_enet_debug, int, 0);
MODULE_PARM_DESC(fs_enet_debug,
"Freescale bitmapped debugging message enable value");
-int fs_enet_debug = -1; /* -1 == use FS_ENET_DEF_MSG_ENABLE as value */
static void fs_set_multicast_list(struct net_device *dev)
{
diff --git a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c
index 5958a631472..2d243540461 100644
--- a/drivers/net/gt96100eth.c
+++ b/drivers/net/gt96100eth.c
@@ -114,8 +114,8 @@ static int max_interrupt_work = 32;
static char mac0[18] = "00.02.03.04.05.06";
static char mac1[18] = "00.01.02.03.04.05";
-MODULE_PARM(mac0, "c18");
-MODULE_PARM(mac1, "c18");
+module_param_string(mac0, mac0, 18, 0);
+module_param_string(mac1, mac0, 18, 0);
MODULE_PARM_DESC(mac0, "MAC address for GT96100 ethernet port 0");
MODULE_PARM_DESC(mac1, "MAC address for GT96100 ethernet port 1");
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index c8dc40214a0..79a8fbcf5f9 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -280,7 +280,7 @@ static unsigned long rand;
MODULE_AUTHOR("Klaus Kudielka");
MODULE_DESCRIPTION("Driver for high-speed SCC boards");
-MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NUM_DEVS) "i");
+module_param_array(io, int, NULL, 0);
MODULE_LICENSE("GPL");
static void __exit dmascc_exit(void)
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index dc5e9d59dee..d81a8e1eeb8 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -1012,7 +1012,7 @@ static void __exit mkiss_exit_driver(void)
MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");
MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
-MODULE_PARM(crc_force, "i");
+module_param(crc_force, int, 0);
MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");
MODULE_LICENSE("GPL");
MODULE_ALIAS_LDISC(N_AX25);
diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c
index d8410634bca..68569346460 100644
--- a/drivers/net/hplance.c
+++ b/drivers/net/hplance.c
@@ -217,7 +217,7 @@ static int hplance_close(struct net_device *dev)
int __init hplance_init_module(void)
{
- return dio_module_init(&hplance_driver);
+ return dio_register_driver(&hplance_driver);
}
void __exit hplance_cleanup_module(void)
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c
index 6e0ca7340a8..d9fb8e74e63 100644
--- a/drivers/net/hydra.c
+++ b/drivers/net/hydra.c
@@ -242,7 +242,7 @@ static void __devexit hydra_remove_one(struct zorro_dev *z)
static int __init hydra_init_module(void)
{
- return zorro_module_init(&hydra_driver);
+ return zorro_register_driver(&hydra_driver);
}
static void __exit hydra_cleanup_module(void)
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index 9b8295ee06e..ae71ed57c12 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -44,6 +44,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
+#include <linux/dma-mapping.h>
#ifdef CONFIG_SERIAL_8250
#include <linux/serial_core.h>
@@ -1195,17 +1196,17 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int err, pci_using_dac;
/* Configure DMA attributes. */
- err = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+ err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
if (!err) {
pci_using_dac = 1;
- err = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+ err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
if (err < 0) {
printk(KERN_ERR "%s: Unable to obtain 64 bit DMA "
"for consistent allocations\n", pci_name(pdev));
goto out;
}
} else {
- err = pci_set_dma_mask(pdev, 0xffffffffULL);
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (err) {
printk(KERN_ERR "%s: No usable DMA configuration, "
"aborting.\n", pci_name(pdev));
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index 6070195b87b..98fa5319e5c 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -1118,9 +1118,9 @@ static void __exit irport_cleanup(void)
}
}
-MODULE_PARM(io, "1-4i");
+module_param_array(io, int, NULL, 0);
MODULE_PARM_DESC(io, "Base I/O addresses");
-MODULE_PARM(irq, "1-4i");
+module_param_array(irq, int, NULL, 0);
MODULE_PARM_DESC(irq, "IRQ lines");
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 83141a3ff54..cc7ff8f00e4 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -207,7 +207,7 @@ static int __init nsc_ircc_init(void)
/* Register with PnP subsystem to detect disable ports */
ret = pnp_register_driver(&nsc_ircc_pnp_driver);
- if (ret >= 0)
+ if (!ret)
pnp_registered = 1;
ret = -ENODEV;
@@ -812,7 +812,7 @@ static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info)
int cfg_base = info->cfg_base;
int enabled;
- /* User is shure about his config... accept it. */
+ /* User is sure about his config... accept it. */
IRDA_DEBUG(2, "%s(): nsc_ircc_init_39x (user settings): "
"io=0x%04x, irq=%d, dma=%d\n",
__FUNCTION__, info->fir_base, info->irq, info->dma);
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index f7b7238d835..957888de3d7 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -177,7 +177,7 @@ static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
MODULE_AUTHOR("Richard Hirst");
MODULE_DESCRIPTION("i82596 driver");
MODULE_LICENSE("GPL");
-MODULE_PARM(i596_debug, "i");
+module_param(i596_debug, int, 0);
MODULE_PARM_DESC(i596_debug, "lasi_82596 debug mask");
/* Copy frames shorter than rx_copybreak, otherwise pass on up in
@@ -1520,9 +1520,9 @@ static void set_multicast_list(struct net_device *dev)
}
}
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "lasi_82596 debug mask");
static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "lasi_82596 debug mask");
static int num_drivers;
static struct net_device *netdevs[MAX_DRIVERS];
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 0c13795dca3..b79d6e8d304 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -172,7 +172,7 @@ static struct net_device_stats *get_stats(struct net_device *dev)
memset(stats, 0, sizeof(struct net_device_stats));
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
struct net_device_stats *lb_stats;
lb_stats = &per_cpu(loopback_stats, i);
diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c
index f65b0db111b..cd3c9a5a98b 100644
--- a/drivers/net/mac89x0.c
+++ b/drivers/net/mac89x0.c
@@ -629,7 +629,7 @@ static int set_mac_address(struct net_device *dev, void *addr)
static struct net_device *dev_cs89x0;
static int debug;
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "CS89[02]0 debug level (0-5)");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index 2a5add257b8..77792b28602 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -1042,7 +1042,7 @@ static void __exit mace_cleanup(void)
MODULE_AUTHOR("Paul Mackerras");
MODULE_DESCRIPTION("PowerMac MACE driver.");
-MODULE_PARM(port_aaui, "i");
+module_param(port_aaui, int, 0);
MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index e23655f5049..d644bf3a933 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -62,7 +62,7 @@ MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver");
#ifdef HAVE_TX_TIMEOUT
static int timeout = TX_TIMEOUT;
-MODULE_PARM(timeout, "i");
+module_param(timeout, int, 0);
#endif
/*
diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c
index aaebd28a192..7ea3d596ac3 100644
--- a/drivers/net/ne-h8300.c
+++ b/drivers/net/ne-h8300.c
@@ -601,9 +601,9 @@ static int io[MAX_NE_CARDS];
static int irq[MAX_NE_CARDS];
static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
-MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
-MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(bad, int, NULL, 0);
MODULE_PARM_DESC(io, "I/O base address(es)");
MODULE_PARM_DESC(irq, "IRQ number(s)");
MODULE_DESCRIPTION("H8/300 NE2000 Ethernet driver");
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index e3ebb5803b0..d11821dd86e 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -117,7 +117,7 @@ enum ne2k_pci_chipsets {
};
-static const struct {
+static struct {
char *name;
int flags;
} pci_clone_list[] __devinitdata = {
diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c
index 2ab01a5d1d2..a68bf474f6e 100644
--- a/drivers/net/ni5010.c
+++ b/drivers/net/ni5010.c
@@ -766,8 +766,8 @@ static void ni5010_show_registers(struct net_device *dev)
#ifdef MODULE
static struct net_device *dev_ni5010;
-MODULE_PARM(io, "i");
-MODULE_PARM(irq, "i");
+module_param(io, int, 0);
+module_param(irq, int, 0);
MODULE_PARM_DESC(io, "ni5010 I/O base address");
MODULE_PARM_DESC(irq, "ni5010 IRQ number");
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 0fede50abd3..8e9b1a537de 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -1828,10 +1828,10 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
int using_dac = 0;
/* See if we can set the dma mask early on; failure is fatal. */
- if (sizeof(dma_addr_t) == 8 &&
- !pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) {
+ if (sizeof(dma_addr_t) == 8 &&
+ !pci_set_dma_mask(pci_dev, DMA_64BIT_MASK)) {
using_dac = 1;
- } else if (!pci_set_dma_mask(pci_dev, 0xffffffff)) {
+ } else if (!pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) {
using_dac = 0;
} else {
printk(KERN_WARNING "ns83820.c: pci_set_dma_mask failed!\n");
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 253440a9802..b82191d2bee 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -1693,7 +1693,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance, struct pt_regs
*
* Process receive interrupt events,
* put buffer to higher layer and refill buffer pool
- * Note: This fucntion is called by interrupt handler,
+ * Note: This function is called by interrupt handler,
* don't do "too much" work here
*/
@@ -1840,7 +1840,7 @@ static int sis900_rx(struct net_device *net_dev)
*
* Check for error condition and free socket buffer etc
* schedule for more transmission as needed
- * Note: This fucntion is called by interrupt handler,
+ * Note: This function is called by interrupt handler,
* don't do "too much" work here
*/
@@ -2283,7 +2283,7 @@ static void set_rx_mode(struct net_device *net_dev)
int i, table_entries;
u32 rx_mode;
- /* 635 Hash Table entires = 256(2^16) */
+ /* 635 Hash Table entries = 256(2^16) */
if((sis_priv->chipset_rev >= SIS635A_900_REV) ||
(sis_priv->chipset_rev == SIS900B_900_REV))
table_entries = 16;
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 01bdb233405..d4c0002b43d 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -71,7 +71,7 @@ static int lance_debug = LANCE_DEBUG;
#else
static int lance_debug = 1;
#endif
-MODULE_PARM(lance_debug, "i");
+module_param(lance_debug, int, 0);
MODULE_PARM_DESC(lance_debug, "SUN3 Lance debug level (0-3)");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index b5473325bff..964c0964483 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,8 +69,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.54"
-#define DRV_MODULE_RELDATE "Mar 23, 2006"
+#define DRV_MODULE_VERSION "3.55"
+#define DRV_MODULE_RELDATE "Mar 27, 2006"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -497,21 +497,20 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
unsigned long flags;
spin_lock_irqsave(&tp->indirect_lock, flags);
- pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
- pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+ if (tp->write32 != tg3_write_indirect_reg32) {
+ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+ tw32_f(TG3PCI_MEM_WIN_DATA, val);
- /* Always leave this as zero. */
- pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
- spin_unlock_irqrestore(&tp->indirect_lock, flags);
-}
+ /* Always leave this as zero. */
+ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+ } else {
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
-static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val)
-{
- /* If no workaround is needed, write to mem space directly */
- if (tp->write32 != tg3_write_indirect_reg32)
- tw32(NIC_SRAM_WIN_BASE + off, val);
- else
- tg3_write_mem(tp, off, val);
+ /* Always leave this as zero. */
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+ }
+ spin_unlock_irqrestore(&tp->indirect_lock, flags);
}
static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
@@ -519,11 +518,19 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
unsigned long flags;
spin_lock_irqsave(&tp->indirect_lock, flags);
- pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
- pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+ if (tp->write32 != tg3_write_indirect_reg32) {
+ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+ *val = tr32(TG3PCI_MEM_WIN_DATA);
- /* Always leave this as zero. */
- pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+ /* Always leave this as zero. */
+ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+ } else {
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+ pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+
+ /* Always leave this as zero. */
+ pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+ }
spin_unlock_irqrestore(&tp->indirect_lock, flags);
}
@@ -1367,12 +1374,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
}
}
+ tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
+
/* Finally, set the new power state. */
pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
udelay(100); /* Delay after power state change */
- tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
-
return 0;
}
@@ -3600,7 +3607,7 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping,
int len)
{
#if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64)
- if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
+ if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG)
return (((u64) mapping + len) > DMA_40BIT_MASK);
return 0;
#else
@@ -6461,6 +6468,9 @@ static void tg3_timer(unsigned long __opaque)
{
struct tg3 *tp = (struct tg3 *) __opaque;
+ if (tp->irq_sync)
+ goto restart_timer;
+
spin_lock(&tp->lock);
if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
@@ -6537,11 +6547,11 @@ static void tg3_timer(unsigned long __opaque)
if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
u32 val;
- tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX,
- FWCMD_NICDRV_ALIVE2);
- tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
+ FWCMD_NICDRV_ALIVE2);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
/* 5 seconds timeout */
- tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
val = tr32(GRC_RX_CPU_EVENT);
val |= (1 << 14);
tw32(GRC_RX_CPU_EVENT, val);
@@ -6551,6 +6561,7 @@ static void tg3_timer(unsigned long __opaque)
spin_unlock(&tp->lock);
+restart_timer:
tp->timer.expires = jiffies + tp->timer_offset;
add_timer(&tp->timer);
}
@@ -8399,8 +8410,11 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
}
mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
- if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
+ if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ tg3_writephy(tp, MII_TG3_EXT_CTRL,
+ MII_TG3_EXT_CTRL_LNK3_LED_MODE);
+ }
tw32(MAC_MODE, mac_mode);
}
else
@@ -10531,6 +10545,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
{
struct net_device *dev = tp->dev;
u32 hi, lo, mac_offset;
+ int addr_ok = 0;
#ifdef CONFIG_SPARC64
if (!tg3_get_macaddr_sparc(tp))
@@ -10560,29 +10575,34 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
dev->dev_addr[3] = (lo >> 16) & 0xff;
dev->dev_addr[4] = (lo >> 8) & 0xff;
dev->dev_addr[5] = (lo >> 0) & 0xff;
- }
- /* Next, try NVRAM. */
- else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
- !tg3_nvram_read(tp, mac_offset + 0, &hi) &&
- !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
- dev->dev_addr[0] = ((hi >> 16) & 0xff);
- dev->dev_addr[1] = ((hi >> 24) & 0xff);
- dev->dev_addr[2] = ((lo >> 0) & 0xff);
- dev->dev_addr[3] = ((lo >> 8) & 0xff);
- dev->dev_addr[4] = ((lo >> 16) & 0xff);
- dev->dev_addr[5] = ((lo >> 24) & 0xff);
- }
- /* Finally just fetch it out of the MAC control regs. */
- else {
- hi = tr32(MAC_ADDR_0_HIGH);
- lo = tr32(MAC_ADDR_0_LOW);
- dev->dev_addr[5] = lo & 0xff;
- dev->dev_addr[4] = (lo >> 8) & 0xff;
- dev->dev_addr[3] = (lo >> 16) & 0xff;
- dev->dev_addr[2] = (lo >> 24) & 0xff;
- dev->dev_addr[1] = hi & 0xff;
- dev->dev_addr[0] = (hi >> 8) & 0xff;
+ /* Some old bootcode may report a 0 MAC address in SRAM */
+ addr_ok = is_valid_ether_addr(&dev->dev_addr[0]);
+ }
+ if (!addr_ok) {
+ /* Next, try NVRAM. */
+ if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
+ !tg3_nvram_read(tp, mac_offset + 0, &hi) &&
+ !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
+ dev->dev_addr[0] = ((hi >> 16) & 0xff);
+ dev->dev_addr[1] = ((hi >> 24) & 0xff);
+ dev->dev_addr[2] = ((lo >> 0) & 0xff);
+ dev->dev_addr[3] = ((lo >> 8) & 0xff);
+ dev->dev_addr[4] = ((lo >> 16) & 0xff);
+ dev->dev_addr[5] = ((lo >> 24) & 0xff);
+ }
+ /* Finally just fetch it out of the MAC control regs. */
+ else {
+ hi = tr32(MAC_ADDR_0_HIGH);
+ lo = tr32(MAC_ADDR_0_LOW);
+
+ dev->dev_addr[5] = lo & 0xff;
+ dev->dev_addr[4] = (lo >> 8) & 0xff;
+ dev->dev_addr[3] = (lo >> 16) & 0xff;
+ dev->dev_addr[2] = (lo >> 24) & 0xff;
+ dev->dev_addr[1] = hi & 0xff;
+ dev->dev_addr[0] = (hi >> 8) & 0xff;
+ }
}
if (!is_valid_ether_addr(&dev->dev_addr[0])) {
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index ee48bfd6734..f5609410204 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -513,7 +513,7 @@ struct mii_phy {
u_char *rst; /* Start of reset sequence in SROM */
u_int mc; /* Media Capabilities */
u_int ana; /* NWay Advertisement */
- u_int fdx; /* Full DupleX capabilites for each media */
+ u_int fdx; /* Full DupleX capabilities for each media */
u_int ttm; /* Transmit Threshold Mode for each media */
u_int mci; /* 21142 MII Connector Interrupt info */
};
@@ -4160,7 +4160,7 @@ get_hw_addr(struct net_device *dev)
** If the address starts with 00 a0, we have to bit-reverse
** each byte of the address.
*/
- if ( (_machine & _MACH_Pmac) &&
+ if ( machine_is(powermac) &&
(dev->dev_addr[0] == 0) &&
(dev->dev_addr[1] == 0xa0) )
{
diff --git a/drivers/net/tulip/pnic2.c b/drivers/net/tulip/pnic2.c
index 55f4a9a631b..ab985023fcc 100644
--- a/drivers/net/tulip/pnic2.c
+++ b/drivers/net/tulip/pnic2.c
@@ -199,7 +199,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5)
/* negotiation ended successfully */
/* get the link partners reply and mask out all but
- * bits 24-21 which show the partners capabilites
+ * bits 24-21 which show the partners capabilities
* and match those to what we advertised
*
* then begin to interpret the results of the negotiation.
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index cde35dd8790..c1ce87a5f8d 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -208,7 +208,7 @@ static const struct typhoon_card_info typhoon_card_info[] __devinitdata = {
};
/* Notes on the new subsystem numbering scheme:
- * bits 0-1 indicate crypto capabilites: (0) variable, (1) DES, or (2) 3DES
+ * bits 0-1 indicate crypto capabilities: (0) variable, (1) DES, or (2) 3DES
* bit 4 indicates if this card has secured firmware (we don't support it)
* bit 8 indicates if this is a (0) copper or (1) fiber card
* bits 12-16 indicate card type: (0) client and (1) server
@@ -788,7 +788,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
/* we have two rings to choose from, but we only use txLo for now
* If we start using the Hi ring as well, we'll need to update
* typhoon_stop_runtime(), typhoon_interrupt(), typhoon_num_free_tx(),
- * and TXHI_ENTIRES to match, as well as update the TSO code below
+ * and TXHI_ENTRIES to match, as well as update the TSO code below
* to get the right DMA address
*/
txRing = &tp->txLoRing;
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 1ff5de076d2..4505540e3c5 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -105,6 +105,7 @@
#include <linux/delay.h>
#include <net/syncppp.h>
#include <linux/hdlc.h>
+#include <linux/mutex.h>
/* Version */
static const char version[] = "$Id: dscc4.c,v 1.173 2003/09/20 23:55:34 romieu Exp $ for Linux\n";
@@ -112,7 +113,7 @@ static int debug;
static int quartz;
#ifdef CONFIG_DSCC4_PCI_RST
-static DECLARE_MUTEX(dscc4_sem);
+static DEFINE_MUTEX(dscc4_mutex);
static u32 dscc4_pci_config_store[16];
#endif
@@ -1018,7 +1019,7 @@ static void dscc4_pci_reset(struct pci_dev *pdev, void __iomem *ioaddr)
{
int i;
- down(&dscc4_sem);
+ mutex_lock(&dscc4_mutex);
for (i = 0; i < 16; i++)
pci_read_config_dword(pdev, i << 2, dscc4_pci_config_store + i);
@@ -1039,7 +1040,7 @@ static void dscc4_pci_reset(struct pci_dev *pdev, void __iomem *ioaddr)
for (i = 0; i < 16; i++)
pci_write_config_dword(pdev, i << 2, dscc4_pci_config_store[i]);
- up(&dscc4_sem);
+ mutex_unlock(&dscc4_mutex);
}
#else
#define dscc4_pci_reset(pdev,ioaddr) do {} while (0)
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index 9d3b51c3ef5..29a756dd979 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -577,8 +577,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
We set both dma_mask and consistent_dma_mask to 28 bits
and pray pci_alloc_consistent() will use this info. It should
work on most platforms */
- if (pci_set_consistent_dma_mask(pdev, 0x0FFFFFFF) ||
- pci_set_dma_mask(pdev, 0x0FFFFFFF)) {
+ if (pci_set_consistent_dma_mask(pdev, DMA_28BIT_MASK) ||
+ pci_set_dma_mask(pdev, DMA_28BIT_MASK)) {
printk(KERN_ERR "wanXL: No usable DMA configuration\n");
return -EIO;
}
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 6a1033ec06c..fd17aa8491b 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -27,6 +27,7 @@ config NET_RADIO
config NET_WIRELESS_RTNETLINK
bool "Wireless Extension API over RtNetlink"
+ depends on NET_RADIO
---help---
Support the Wireless Extension API over the RtNetlink socket
in addition to the traditional ioctl interface (selected above).
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 6fd0bf73683..8dfdfbd5966 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -3858,7 +3858,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
unsigned long flags;
/* Note : you may have realised that, as this is a SET operation,
- * this is priviledged and therefore a normal user can't
+ * this is privileged and therefore a normal user can't
* perform scanning.
* This is not an error, while the device perform scanning,
* traffic doesn't flow, so it's a perfect DoS...
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index e5bb9f5ae42..989599ad33e 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -747,7 +747,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info,
if (essid->length) {
dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */
- /* if it is to big, trunk it */
+ /* if it is too big, trunk it */
dwrq->length = min((u8)IW_ESSID_MAX_SIZE, essid->length);
} else {
dwrq->flags = 0;
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index b41d666fea3..bfa0cc319a0 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -22,6 +22,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/init.h> /* For __init, __exit */
+#include <linux/dma-mapping.h>
#include "prismcompat.h"
#include "islpci_dev.h"
@@ -124,7 +125,7 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
/* enable PCI DMA */
- if (pci_set_dma_mask(pdev, 0xffffffff)) {
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_ERR "%s: 32-bit PCI DMA not supported", DRV_NAME);
goto do_pci_disable_device;
}
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
index 76102160359..8037e5806d0 100644
--- a/drivers/net/zorro8390.c
+++ b/drivers/net/zorro8390.c
@@ -426,7 +426,7 @@ static void __devexit zorro8390_remove_one(struct zorro_dev *z)
static int __init zorro8390_init_module(void)
{
- return zorro_module_init(&zorro8390_driver);
+ return zorro_register_driver(&zorro8390_driver);
}
static void __exit zorro8390_cleanup_module(void)
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index 330d3869b41..fc4bc9b94c7 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -217,11 +217,10 @@ static void oprofile_end_trace(struct oprofile_cpu_buffer * cpu_buf)
cpu_buf->tracing = 0;
}
-void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
+void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
+ unsigned long event, int is_kernel)
{
struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
- unsigned long pc = profile_pc(regs);
- int is_kernel = !user_mode(regs);
if (!backtrace_depth) {
log_sample(cpu_buf, pc, is_kernel, event);
@@ -238,6 +237,14 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
oprofile_end_trace(cpu_buf);
}
+void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
+{
+ int is_kernel = !user_mode(regs);
+ unsigned long pc = profile_pc(regs);
+
+ oprofile_add_ext_sample(pc, regs, event, is_kernel);
+}
+
void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
{
struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c
index e94b1e4a2a8..f0acb661c25 100644
--- a/drivers/oprofile/oprofile_stats.c
+++ b/drivers/oprofile/oprofile_stats.c
@@ -22,7 +22,7 @@ void oprofile_reset_stats(void)
struct oprofile_cpu_buffer * cpu_buf;
int i;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
cpu_buf = &cpu_buffer[i];
cpu_buf->sample_received = 0;
cpu_buf->sample_lost_overflow = 0;
@@ -46,7 +46,7 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root)
if (!dir)
return;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
cpu_buf = &cpu_buffer[i];
snprintf(buf, 10, "cpu%d", i);
cpudir = oprofilefs_mkdir(sb, dir, buf);
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index d6bae699749..b62da9b0cbf 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -130,7 +130,7 @@ static struct file_operations ulong_ro_fops = {
static struct dentry * __oprofilefs_create_file(struct super_block * sb,
- struct dentry * root, char const * name, struct file_operations * fops,
+ struct dentry * root, char const * name, const struct file_operations * fops,
int perm)
{
struct dentry * dentry;
@@ -203,7 +203,7 @@ int oprofilefs_create_ro_atomic(struct super_block * sb, struct dentry * root,
int oprofilefs_create_file(struct super_block * sb, struct dentry * root,
- char const * name, struct file_operations * fops)
+ char const * name, const struct file_operations * fops)
{
if (!__oprofilefs_create_file(sb, root, name, fops, 0644))
return -EFAULT;
@@ -212,7 +212,7 @@ int oprofilefs_create_file(struct super_block * sb, struct dentry * root,
int oprofilefs_create_file_perm(struct super_block * sb, struct dentry * root,
- char const * name, struct file_operations * fops, int perm)
+ char const * name, const struct file_operations * fops, int perm)
{
if (!__oprofilefs_create_file(sb, root, name, fops, perm))
return -EFAULT;
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 3627a2d7f79..298f2ddb2c1 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -499,11 +499,16 @@ static int led_halt(struct notifier_block *, unsigned long, void *);
static struct notifier_block led_notifier = {
.notifier_call = led_halt,
};
+static int notifier_disabled = 0;
static int led_halt(struct notifier_block *nb, unsigned long event, void *buf)
{
char *txt;
-
+
+ if (notifier_disabled)
+ return NOTIFY_OK;
+
+ notifier_disabled = 1;
switch (event) {
case SYS_RESTART: txt = "SYSTEM RESTART";
break;
@@ -527,7 +532,6 @@ static int led_halt(struct notifier_block *nb, unsigned long event, void *buf)
if (led_func_ptr)
led_func_ptr(0xff); /* turn all LEDs ON */
- unregister_reboot_notifier(&led_notifier);
return NOTIFY_OK;
}
@@ -758,6 +762,12 @@ not_found:
return 1;
}
+static void __exit led_exit(void)
+{
+ unregister_reboot_notifier(&led_notifier);
+ return;
+}
+
#ifdef CONFIG_PROC_FS
module_init(led_create_procfs)
#endif
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
index 54b2b7f20b9..0bcab83b408 100644
--- a/drivers/parisc/power.c
+++ b/drivers/parisc/power.c
@@ -251,7 +251,8 @@ static int __init power_init(void)
}
/* Register a call for panic conditions. */
- notifier_chain_register(&panic_notifier_list, &parisc_panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &parisc_panic_block);
tasklet_enable(&power_tasklet);
@@ -264,7 +265,8 @@ static void __exit power_exit(void)
return;
tasklet_disable(&power_tasklet);
- notifier_chain_unregister(&panic_notifier_list, &parisc_panic_block);
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &parisc_panic_block);
power_tasklet.func = NULL;
pdc_soft_power_button(0);
}
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 5d47c5965c5..0821747e44c 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -1724,9 +1724,7 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
sba_dev->chip_resv.start = PCI_F_EXTEND | 0xfef00000UL;
sba_dev->chip_resv.end = PCI_F_EXTEND | (0xff000000UL - 1) ;
err = request_resource(&iomem_resource, &(sba_dev->chip_resv));
- if (err < 0) {
- BUG();
- }
+ BUG_ON(err < 0);
} else if (IS_PLUTO(sba_dev->iodc)) {
int err;
@@ -2185,8 +2183,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r)
int i;
int rope = (pci_hba->hw_path & (ROPES_PER_IOC-1)); /* rope # */
- if ((t!=HPHW_IOA) && (t!=HPHW_BCPORT))
- BUG();
+ BUG_ON((t!=HPHW_IOA) && (t!=HPHW_BCPORT));
r->start = r->end = 0;
@@ -2228,8 +2225,7 @@ void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r )
int base, size;
int rope = (pci_hba->hw_path & (ROPES_PER_IOC-1)); /* rope # */
- if ((t!=HPHW_IOA) && (t!=HPHW_BCPORT))
- BUG();
+ BUG_ON((t!=HPHW_IOA) && (t!=HPHW_BCPORT));
r->start = r->end = 0;
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index ba971fecd0d..ad6d3b28a3a 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -157,8 +157,8 @@ superio_init(struct pci_dev *pcidev)
if (sio->suckyio_irq_enabled)
return;
- if (!pdev) BUG();
- if (!sio->usb_pdev) BUG();
+ BUG_ON(!pdev);
+ BUG_ON(!sio->usb_pdev);
/* use the IRQ iosapic found for USB INT D... */
pdev->irq = sio->usb_pdev->irq;
@@ -474,8 +474,7 @@ superio_probe(struct pci_dev *dev, const struct pci_device_id *id)
dev->subsystem_vendor, dev->subsystem_device,
dev->class);
- if (!sio->suckyio_irq_enabled)
- BUG(); /* Enabled by PCI_FIXUP_FINAL */
+ BUG_ON(!sio->suckyio_irq_enabled); /* Enabled by PCI_FIXUP_FINAL */
if (dev->device == PCI_DEVICE_ID_NS_87560_LIO) { /* Function 1 */
superio_parport_init();
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 9302b8fd746..d5890027f8a 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -3126,9 +3126,9 @@ parport_pc_find_isa_ports (int autoirq, int autodma)
* autoirq is PARPORT_IRQ_NONE, PARPORT_IRQ_AUTO, or PARPORT_IRQ_PROBEONLY
* autodma is PARPORT_DMA_NONE or PARPORT_DMA_AUTO
*/
-static int __init parport_pc_find_ports (int autoirq, int autodma)
+static void __init parport_pc_find_ports (int autoirq, int autodma)
{
- int count = 0, r;
+ int count = 0, err;
#ifdef CONFIG_PARPORT_PC_SUPERIO
detect_and_report_winbond ();
@@ -3140,23 +3140,17 @@ static int __init parport_pc_find_ports (int autoirq, int autodma)
/* PnP ports, skip detection if SuperIO already found them */
if (!count) {
- r = pnp_register_driver (&parport_pc_pnp_driver);
- if (r >= 0) {
+ err = pnp_register_driver (&parport_pc_pnp_driver);
+ if (!err)
pnp_registered_parport = 1;
- count += r;
- }
}
/* ISA ports and whatever (see asm/parport.h). */
- count += parport_pc_find_nonpci_ports (autoirq, autodma);
-
- r = pci_register_driver (&parport_pc_pci_driver);
- if (r)
- return r;
- pci_registered_parport = 1;
- count += 1;
+ parport_pc_find_nonpci_ports (autoirq, autodma);
- return count;
+ err = pci_register_driver (&parport_pc_pci_driver);
+ if (!err)
+ pci_registered_parport = 1;
}
/*
@@ -3381,8 +3375,6 @@ __setup("parport_init_mode=",parport_init_mode_setup);
static int __init parport_pc_init(void)
{
- int count = 0;
-
if (parse_parport_params())
return -EINVAL;
@@ -3395,12 +3387,11 @@ static int __init parport_pc_init(void)
break;
if ((io_hi[i]) == PARPORT_IOHI_AUTO)
io_hi[i] = 0x400 + io[i];
- if (parport_pc_probe_port(io[i], io_hi[i],
- irqval[i], dmaval[i], NULL))
- count++;
+ parport_pc_probe_port(io[i], io_hi[i],
+ irqval[i], dmaval[i], NULL);
}
} else
- count += parport_pc_find_ports (irqval[0], dmaval[0]);
+ parport_pc_find_ports (irqval[0], dmaval[0]);
return 0;
}
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index ea62bed6bc8..bbbfd79adba 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -32,6 +32,7 @@
#include <linux/kmod.h>
#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <asm/irq.h>
#undef PARPORT_PARANOID
@@ -50,7 +51,7 @@ static DEFINE_SPINLOCK(full_list_lock);
static LIST_HEAD(drivers);
-static DECLARE_MUTEX(registration_lock);
+static DEFINE_MUTEX(registration_lock);
/* What you can do to a port that's gone away.. */
static void dead_write_lines (struct parport *p, unsigned char b){}
@@ -158,11 +159,11 @@ int parport_register_driver (struct parport_driver *drv)
if (list_empty(&portlist))
get_lowlevel_driver ();
- down(&registration_lock);
+ mutex_lock(&registration_lock);
list_for_each_entry(port, &portlist, list)
drv->attach(port);
list_add(&drv->list, &drivers);
- up(&registration_lock);
+ mutex_unlock(&registration_lock);
return 0;
}
@@ -188,11 +189,11 @@ void parport_unregister_driver (struct parport_driver *drv)
{
struct parport *port;
- down(&registration_lock);
+ mutex_lock(&registration_lock);
list_del_init(&drv->list);
list_for_each_entry(port, &portlist, list)
drv->detach(port);
- up(&registration_lock);
+ mutex_unlock(&registration_lock);
}
static void free_port (struct parport *port)
@@ -366,7 +367,7 @@ void parport_announce_port (struct parport *port)
#endif
parport_proc_register(port);
- down(&registration_lock);
+ mutex_lock(&registration_lock);
spin_lock_irq(&parportlist_lock);
list_add_tail(&port->list, &portlist);
for (i = 1; i < 3; i++) {
@@ -383,7 +384,7 @@ void parport_announce_port (struct parport *port)
if (slave)
attach_driver_chain(slave);
}
- up(&registration_lock);
+ mutex_unlock(&registration_lock);
}
/**
@@ -409,7 +410,7 @@ void parport_remove_port(struct parport *port)
{
int i;
- down(&registration_lock);
+ mutex_lock(&registration_lock);
/* Spread the word. */
detach_driver_chain (port);
@@ -436,7 +437,7 @@ void parport_remove_port(struct parport *port)
}
spin_unlock(&parportlist_lock);
- up(&registration_lock);
+ mutex_unlock(&registration_lock);
parport_proc_unregister(port);
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 3eefe2cec72..46825fee3ae 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -19,7 +19,7 @@
#include <linux/string.h>
#include <asm/pci-bridge.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <asm/rtas.h>
#include <asm/vio.h>
@@ -27,7 +27,7 @@
#include "rpaphp.h"
#include "rpadlpar.h"
-static DECLARE_MUTEX(rpadlpar_sem);
+static DEFINE_MUTEX(rpadlpar_mutex);
#define DLPAR_MODULE_NAME "rpadlpar_io"
@@ -300,7 +300,7 @@ int dlpar_add_slot(char *drc_name)
int node_type;
int rc = -EIO;
- if (down_interruptible(&rpadlpar_sem))
+ if (mutex_lock_interruptible(&rpadlpar_mutex))
return -ERESTARTSYS;
/* Find newly added node */
@@ -324,7 +324,7 @@ int dlpar_add_slot(char *drc_name)
printk(KERN_INFO "%s: slot %s added\n", DLPAR_MODULE_NAME, drc_name);
exit:
- up(&rpadlpar_sem);
+ mutex_unlock(&rpadlpar_mutex);
return rc;
}
@@ -417,7 +417,7 @@ int dlpar_remove_slot(char *drc_name)
int node_type;
int rc = 0;
- if (down_interruptible(&rpadlpar_sem))
+ if (mutex_lock_interruptible(&rpadlpar_mutex))
return -ERESTARTSYS;
dn = find_dlpar_node(drc_name, &node_type);
@@ -439,7 +439,7 @@ int dlpar_remove_slot(char *drc_name)
}
printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name);
exit:
- up(&rpadlpar_sem);
+ mutex_unlock(&rpadlpar_mutex);
return rc;
}
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index c402da8e78a..8cb9abde736 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -15,6 +15,7 @@
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/types.h>
+#include <linux/mutex.h>
#include <asm/sn/addrs.h>
#include <asm/sn/l1.h>
@@ -81,7 +82,7 @@ static struct hotplug_slot_ops sn_hotplug_slot_ops = {
.get_power_status = get_power_status,
};
-static DECLARE_MUTEX(sn_hotplug_sem);
+static DEFINE_MUTEX(sn_hotplug_mutex);
static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot,
char *buf)
@@ -346,7 +347,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
int rc;
/* Serialize the Linux PCI infrastructure */
- down(&sn_hotplug_sem);
+ mutex_lock(&sn_hotplug_mutex);
/*
* Power-on and initialize the slot in the SN
@@ -354,7 +355,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
*/
rc = sn_slot_enable(bss_hotplug_slot, slot->device_num);
if (rc) {
- up(&sn_hotplug_sem);
+ mutex_unlock(&sn_hotplug_mutex);
return rc;
}
@@ -362,7 +363,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
PCI_DEVFN(slot->device_num + 1, 0));
if (!num_funcs) {
dev_dbg(slot->pci_bus->self, "no device in slot\n");
- up(&sn_hotplug_sem);
+ mutex_unlock(&sn_hotplug_mutex);
return -ENODEV;
}
@@ -402,7 +403,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
if (new_ppb)
pci_bus_add_devices(new_bus);
- up(&sn_hotplug_sem);
+ mutex_unlock(&sn_hotplug_mutex);
if (rc == 0)
dev_dbg(slot->pci_bus->self,
@@ -422,7 +423,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
int rc;
/* Acquire update access to the bus */
- down(&sn_hotplug_sem);
+ mutex_lock(&sn_hotplug_mutex);
/* is it okay to bring this slot down? */
rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,
@@ -450,7 +451,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
PCI_REQ_SLOT_DISABLE);
leaving:
/* Release the bus lock */
- up(&sn_hotplug_sem);
+ mutex_unlock(&sn_hotplug_mutex);
return rc;
}
@@ -462,9 +463,9 @@ static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot,
struct pcibus_info *pcibus_info;
pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
- down(&sn_hotplug_sem);
+ mutex_lock(&sn_hotplug_mutex);
*value = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
- up(&sn_hotplug_sem);
+ mutex_unlock(&sn_hotplug_mutex);
return 0;
}
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index b68eef25161..bb19c64073c 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -47,7 +47,7 @@ static void card_remove(struct pnp_dev * dev)
{
dev->card_link = NULL;
}
-
+
static void card_remove_first(struct pnp_dev * dev)
{
struct pnp_card_driver * drv = to_pnp_card_driver(dev->driver);
@@ -361,7 +361,7 @@ static int card_resume(struct pnp_dev *dev)
int pnp_register_card_driver(struct pnp_card_driver * drv)
{
- int count;
+ int error;
struct list_head *pos, *temp;
drv->link.name = drv->name;
@@ -372,21 +372,19 @@ int pnp_register_card_driver(struct pnp_card_driver * drv)
drv->link.suspend = drv->suspend ? card_suspend : NULL;
drv->link.resume = drv->resume ? card_resume : NULL;
- count = pnp_register_driver(&drv->link);
- if (count < 0)
- return count;
+ error = pnp_register_driver(&drv->link);
+ if (error < 0)
+ return error;
spin_lock(&pnp_lock);
list_add_tail(&drv->global_list, &pnp_card_drivers);
spin_unlock(&pnp_lock);
- count = 0;
-
list_for_each_safe(pos,temp,&pnp_cards){
struct pnp_card *card = list_entry(pos, struct pnp_card, global_list);
- count += card_probe(card,drv);
+ card_probe(card,drv);
}
- return count;
+ return 0;
}
/**
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index 7cafacdd12b..e54c1538319 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -201,31 +201,14 @@ struct bus_type pnp_bus_type = {
.resume = pnp_bus_resume,
};
-
-static int count_devices(struct device * dev, void * c)
-{
- int * count = c;
- (*count)++;
- return 0;
-}
-
int pnp_register_driver(struct pnp_driver *drv)
{
- int count;
-
pnp_dbg("the driver '%s' has been registered", drv->name);
drv->driver.name = drv->name;
drv->driver.bus = &pnp_bus_type;
- count = driver_register(&drv->driver);
-
- /* get the number of initial matches */
- if (count >= 0){
- count = 0;
- driver_for_each_device(&drv->driver, NULL, &count, count_devices);
- }
- return count;
+ return driver_register(&drv->driver);
}
void pnp_unregister_driver(struct pnp_driver *drv)
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 57fd60314d5..ac7c2bb6c69 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -42,6 +42,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/isapnp.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#if 0
@@ -92,7 +93,7 @@ MODULE_LICENSE("GPL");
#define _LTAG_FIXEDMEM32RANGE 0x86
static unsigned char isapnp_checksum_value;
-static DECLARE_MUTEX(isapnp_cfg_mutex);
+static DEFINE_MUTEX(isapnp_cfg_mutex);
static int isapnp_detected;
static int isapnp_csn_count;
@@ -646,8 +647,10 @@ static int __init isapnp_create_device(struct pnp_card *card,
size = 0;
skip = 0;
option = pnp_register_independent_option(dev);
- if (!option)
+ if (!option) {
+ kfree(dev);
return 1;
+ }
pnp_add_card_device(card,dev);
} else {
skip = 1;
@@ -901,7 +904,7 @@ int isapnp_cfg_begin(int csn, int logdev)
{
if (csn < 1 || csn > isapnp_csn_count || logdev > 10)
return -EINVAL;
- down(&isapnp_cfg_mutex);
+ mutex_lock(&isapnp_cfg_mutex);
isapnp_wait();
isapnp_key();
isapnp_wake(csn);
@@ -927,7 +930,7 @@ int isapnp_cfg_begin(int csn, int logdev)
int isapnp_cfg_end(void)
{
isapnp_wait();
- up(&isapnp_cfg_mutex);
+ mutex_unlock(&isapnp_cfg_mutex);
return 0;
}
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
new file mode 100644
index 00000000000..929dd809057
--- /dev/null
+++ b/drivers/rtc/Kconfig
@@ -0,0 +1,165 @@
+\#
+# RTC class/drivers configuration
+#
+
+menu "Real Time Clock"
+
+config RTC_LIB
+ tristate
+
+config RTC_CLASS
+ tristate "RTC class"
+ depends on EXPERIMENTAL
+ default n
+ select RTC_LIB
+ help
+ Generic RTC class support. If you say yes here, you will
+ be allowed to plug one or more RTCs to your system. You will
+ probably want to enable one of more of the interfaces below.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-class.
+
+config RTC_HCTOSYS
+ bool "Set system time from RTC on startup"
+ depends on RTC_CLASS = y
+ default y
+ help
+ If you say yes here, the system time will be set using
+ the value read from the specified RTC device. This is useful
+ in order to avoid unnecessary fschk runs.
+
+config RTC_HCTOSYS_DEVICE
+ string "The RTC to read the time from"
+ depends on RTC_HCTOSYS = y
+ default "rtc0"
+ help
+ The RTC device that will be used as the source for
+ the system time, usually rtc0.
+
+comment "RTC interfaces"
+ depends on RTC_CLASS
+
+config RTC_INTF_SYSFS
+ tristate "sysfs"
+ depends on RTC_CLASS && SYSFS
+ default RTC_CLASS
+ help
+ Say yes here if you want to use your RTC using the sysfs
+ interface, /sys/class/rtc/rtcX .
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-sysfs.
+
+config RTC_INTF_PROC
+ tristate "proc"
+ depends on RTC_CLASS && PROC_FS
+ default RTC_CLASS
+ help
+ Say yes here if you want to use your RTC using the proc
+ interface, /proc/driver/rtc .
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-proc.
+
+config RTC_INTF_DEV
+ tristate "dev"
+ depends on RTC_CLASS
+ default RTC_CLASS
+ help
+ Say yes here if you want to use your RTC using the dev
+ interface, /dev/rtc .
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-dev.
+
+comment "RTC drivers"
+ depends on RTC_CLASS
+
+config RTC_DRV_X1205
+ tristate "Xicor/Intersil X1205"
+ depends on RTC_CLASS && I2C
+ help
+ If you say yes here you get support for the
+ Xicor/Intersil X1205 RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-x1205.
+
+config RTC_DRV_DS1672
+ tristate "Dallas/Maxim DS1672"
+ depends on RTC_CLASS && I2C
+ help
+ If you say yes here you get support for the
+ Dallas/Maxim DS1672 timekeeping chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ds1672.
+
+config RTC_DRV_PCF8563
+ tristate "Philips PCF8563/Epson RTC8564"
+ depends on RTC_CLASS && I2C
+ help
+ If you say yes here you get support for the
+ Philips PCF8563 RTC chip. The Epson RTC8564
+ should work as well.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-pcf8563.
+
+config RTC_DRV_RS5C372
+ tristate "Ricoh RS5C372A/B"
+ depends on RTC_CLASS && I2C
+ help
+ If you say yes here you get support for the
+ Ricoh RS5C372A and RS5C372B RTC chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-rs5c372.
+
+config RTC_DRV_M48T86
+ tristate "ST M48T86/Dallas DS12887"
+ depends on RTC_CLASS
+ help
+ If you say Y here you will get support for the
+ ST M48T86 and Dallas DS12887 RTC chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-m48t86.
+
+config RTC_DRV_EP93XX
+ tristate "Cirrus Logic EP93XX"
+ depends on RTC_CLASS && ARCH_EP93XX
+ help
+ If you say yes here you get support for the
+ RTC embedded in the Cirrus Logic EP93XX processors.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ep93xx.
+
+config RTC_DRV_SA1100
+ tristate "SA11x0/PXA2xx"
+ depends on RTC_CLASS && (ARCH_SA1100 || ARCH_PXA)
+ help
+ If you say Y here you will get access to the real time clock
+ built into your SA11x0 or PXA2xx CPU.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rtc-sa1100.
+
+config RTC_DRV_TEST
+ tristate "Test driver/device"
+ depends on RTC_CLASS
+ help
+ If you say yes here you get support for the
+ RTC test driver. It's a software RTC which can be
+ used to test the RTC subsystem APIs. It gets
+ the time from the system clock.
+ You want this driver only if you are doing development
+ on the RTC subsystem. Please read the source code
+ for further details.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-test.
+
+endmenu
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
new file mode 100644
index 00000000000..8d4c7fe88d5
--- /dev/null
+++ b/drivers/rtc/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for RTC class/drivers.
+#
+
+obj-$(CONFIG_RTC_LIB) += rtc-lib.o
+obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o
+obj-$(CONFIG_RTC_CLASS) += rtc-core.o
+rtc-core-y := class.o interface.o
+
+obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
+obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
+obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o
+
+obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
+obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
+obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o
+obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
+obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
+obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
+obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
+obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
new file mode 100644
index 00000000000..8533936d50d
--- /dev/null
+++ b/drivers/rtc/class.c
@@ -0,0 +1,145 @@
+/*
+ * RTC subsystem, base class
+ *
+ * Copyright (C) 2005 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * class skeleton from drivers/hwmon/hwmon.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/module.h>
+#include <linux/rtc.h>
+#include <linux/kdev_t.h>
+#include <linux/idr.h>
+
+static DEFINE_IDR(rtc_idr);
+static DEFINE_MUTEX(idr_lock);
+struct class *rtc_class;
+
+static void rtc_device_release(struct class_device *class_dev)
+{
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+ mutex_lock(&idr_lock);
+ idr_remove(&rtc_idr, rtc->id);
+ mutex_unlock(&idr_lock);
+ kfree(rtc);
+}
+
+/**
+ * rtc_device_register - register w/ RTC class
+ * @dev: the device to register
+ *
+ * rtc_device_unregister() must be called when the class device is no
+ * longer needed.
+ *
+ * Returns the pointer to the new struct class device.
+ */
+struct rtc_device *rtc_device_register(const char *name, struct device *dev,
+ struct rtc_class_ops *ops,
+ struct module *owner)
+{
+ struct rtc_device *rtc;
+ int id, err;
+
+ if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+
+ mutex_lock(&idr_lock);
+ err = idr_get_new(&rtc_idr, NULL, &id);
+ mutex_unlock(&idr_lock);
+
+ if (err < 0)
+ goto exit;
+
+ id = id & MAX_ID_MASK;
+
+ rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL);
+ if (rtc == NULL) {
+ err = -ENOMEM;
+ goto exit_idr;
+ }
+
+ rtc->id = id;
+ rtc->ops = ops;
+ rtc->owner = owner;
+ rtc->class_dev.dev = dev;
+ rtc->class_dev.class = rtc_class;
+ rtc->class_dev.release = rtc_device_release;
+
+ mutex_init(&rtc->ops_lock);
+ spin_lock_init(&rtc->irq_lock);
+ spin_lock_init(&rtc->irq_task_lock);
+
+ strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
+ snprintf(rtc->class_dev.class_id, BUS_ID_SIZE, "rtc%d", id);
+
+ err = class_device_register(&rtc->class_dev);
+ if (err)
+ goto exit_kfree;
+
+ dev_info(dev, "rtc core: registered %s as %s\n",
+ rtc->name, rtc->class_dev.class_id);
+
+ return rtc;
+
+exit_kfree:
+ kfree(rtc);
+
+exit_idr:
+ idr_remove(&rtc_idr, id);
+
+exit:
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(rtc_device_register);
+
+
+/**
+ * rtc_device_unregister - removes the previously registered RTC class device
+ *
+ * @rtc: the RTC class device to destroy
+ */
+void rtc_device_unregister(struct rtc_device *rtc)
+{
+ mutex_lock(&rtc->ops_lock);
+ rtc->ops = NULL;
+ mutex_unlock(&rtc->ops_lock);
+ class_device_unregister(&rtc->class_dev);
+}
+EXPORT_SYMBOL_GPL(rtc_device_unregister);
+
+int rtc_interface_register(struct class_interface *intf)
+{
+ intf->class = rtc_class;
+ return class_interface_register(intf);
+}
+EXPORT_SYMBOL_GPL(rtc_interface_register);
+
+static int __init rtc_init(void)
+{
+ rtc_class = class_create(THIS_MODULE, "rtc");
+ if (IS_ERR(rtc_class)) {
+ printk(KERN_ERR "%s: couldn't create class\n", __FILE__);
+ return PTR_ERR(rtc_class);
+ }
+ return 0;
+}
+
+static void __exit rtc_exit(void)
+{
+ class_destroy(rtc_class);
+}
+
+module_init(rtc_init);
+module_exit(rtc_exit);
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towerteh.it>");
+MODULE_DESCRIPTION("RTC class support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c
new file mode 100644
index 00000000000..d02fe9a0001
--- /dev/null
+++ b/drivers/rtc/hctosys.c
@@ -0,0 +1,69 @@
+/*
+ * RTC subsystem, initialize system time on startup
+ *
+ * Copyright (C) 2005 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * 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/rtc.h>
+
+/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
+ * whether it stores the most close value or the value with partial
+ * seconds truncated. However, it is important that we use it to store
+ * the truncated value. This is because otherwise it is necessary,
+ * in an rtc sync function, to read both xtime.tv_sec and
+ * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read
+ * of >32bits is not possible. So storing the most close value would
+ * slow down the sync API. So here we have the truncated value and
+ * the best guess is to add 0.5s.
+ */
+
+static int __init rtc_hctosys(void)
+{
+ int err;
+ struct rtc_time tm;
+ struct class_device *class_dev = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
+
+ if (class_dev == NULL) {
+ printk("%s: unable to open rtc device (%s)\n",
+ __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
+ return -ENODEV;
+ }
+
+ err = rtc_read_time(class_dev, &tm);
+ if (err == 0) {
+ err = rtc_valid_tm(&tm);
+ if (err == 0) {
+ struct timespec tv;
+
+ tv.tv_nsec = NSEC_PER_SEC >> 1;
+
+ rtc_tm_to_time(&tm, &tv.tv_sec);
+
+ do_settimeofday(&tv);
+
+ dev_info(class_dev->dev,
+ "setting the system clock to "
+ "%d-%02d-%02d %02d:%02d:%02d (%u)\n",
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec,
+ (unsigned int) tv.tv_sec);
+ }
+ else
+ dev_err(class_dev->dev,
+ "hctosys: invalid date/time\n");
+ }
+ else
+ dev_err(class_dev->dev,
+ "hctosys: unable to read the hardware clock\n");
+
+ rtc_class_close(class_dev);
+
+ return 0;
+}
+
+late_initcall(rtc_hctosys);
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
new file mode 100644
index 00000000000..56e490709b8
--- /dev/null
+++ b/drivers/rtc/interface.c
@@ -0,0 +1,277 @@
+/*
+ * RTC subsystem, interface functions
+ *
+ * Copyright (C) 2005 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * based on arch/arm/common/rtctime.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/rtc.h>
+
+int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm)
+{
+ int err;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return -EBUSY;
+
+ if (!rtc->ops)
+ err = -ENODEV;
+ else if (!rtc->ops->read_time)
+ err = -EINVAL;
+ else {
+ memset(tm, 0, sizeof(struct rtc_time));
+ err = rtc->ops->read_time(class_dev->dev, tm);
+ }
+
+ mutex_unlock(&rtc->ops_lock);
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_read_time);
+
+int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm)
+{
+ int err;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ err = rtc_valid_tm(tm);
+ if (err != 0)
+ return err;
+
+ err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return -EBUSY;
+
+ if (!rtc->ops)
+ err = -ENODEV;
+ else if (!rtc->ops->set_time)
+ err = -EINVAL;
+ else
+ err = rtc->ops->set_time(class_dev->dev, tm);
+
+ mutex_unlock(&rtc->ops_lock);
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_set_time);
+
+int rtc_set_mmss(struct class_device *class_dev, unsigned long secs)
+{
+ int err;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return -EBUSY;
+
+ if (!rtc->ops)
+ err = -ENODEV;
+ else if (rtc->ops->set_mmss)
+ err = rtc->ops->set_mmss(class_dev->dev, secs);
+ else if (rtc->ops->read_time && rtc->ops->set_time) {
+ struct rtc_time new, old;
+
+ err = rtc->ops->read_time(class_dev->dev, &old);
+ if (err == 0) {
+ rtc_time_to_tm(secs, &new);
+
+ /*
+ * avoid writing when we're going to change the day of
+ * the month. We will retry in the next minute. This
+ * basically means that if the RTC must not drift
+ * by more than 1 minute in 11 minutes.
+ */
+ if (!((old.tm_hour == 23 && old.tm_min == 59) ||
+ (new.tm_hour == 23 && new.tm_min == 59)))
+ err = rtc->ops->set_time(class_dev->dev, &new);
+ }
+ }
+ else
+ err = -EINVAL;
+
+ mutex_unlock(&rtc->ops_lock);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_set_mmss);
+
+int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
+{
+ int err;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return -EBUSY;
+
+ if (rtc->ops == NULL)
+ err = -ENODEV;
+ else if (!rtc->ops->read_alarm)
+ err = -EINVAL;
+ else {
+ memset(alarm, 0, sizeof(struct rtc_wkalrm));
+ err = rtc->ops->read_alarm(class_dev->dev, alarm);
+ }
+
+ mutex_unlock(&rtc->ops_lock);
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_read_alarm);
+
+int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
+{
+ int err;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return -EBUSY;
+
+ if (!rtc->ops)
+ err = -ENODEV;
+ else if (!rtc->ops->set_alarm)
+ err = -EINVAL;
+ else
+ err = rtc->ops->set_alarm(class_dev->dev, alarm);
+
+ mutex_unlock(&rtc->ops_lock);
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_set_alarm);
+
+void rtc_update_irq(struct class_device *class_dev,
+ unsigned long num, unsigned long events)
+{
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ spin_lock(&rtc->irq_lock);
+ rtc->irq_data = (rtc->irq_data + (num << 8)) | events;
+ spin_unlock(&rtc->irq_lock);
+
+ spin_lock(&rtc->irq_task_lock);
+ if (rtc->irq_task)
+ rtc->irq_task->func(rtc->irq_task->private_data);
+ spin_unlock(&rtc->irq_task_lock);
+
+ wake_up_interruptible(&rtc->irq_queue);
+ kill_fasync(&rtc->async_queue, SIGIO, POLL_IN);
+}
+EXPORT_SYMBOL_GPL(rtc_update_irq);
+
+struct class_device *rtc_class_open(char *name)
+{
+ struct class_device *class_dev = NULL,
+ *class_dev_tmp;
+
+ down(&rtc_class->sem);
+ list_for_each_entry(class_dev_tmp, &rtc_class->children, node) {
+ if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) {
+ class_dev = class_dev_tmp;
+ break;
+ }
+ }
+
+ if (class_dev) {
+ if (!try_module_get(to_rtc_device(class_dev)->owner))
+ class_dev = NULL;
+ }
+ up(&rtc_class->sem);
+
+ return class_dev;
+}
+EXPORT_SYMBOL_GPL(rtc_class_open);
+
+void rtc_class_close(struct class_device *class_dev)
+{
+ module_put(to_rtc_device(class_dev)->owner);
+}
+EXPORT_SYMBOL_GPL(rtc_class_close);
+
+int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task)
+{
+ int retval = -EBUSY;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ if (task == NULL || task->func == NULL)
+ return -EINVAL;
+
+ spin_lock(&rtc->irq_task_lock);
+ if (rtc->irq_task == NULL) {
+ rtc->irq_task = task;
+ retval = 0;
+ }
+ spin_unlock(&rtc->irq_task_lock);
+
+ return retval;
+}
+EXPORT_SYMBOL_GPL(rtc_irq_register);
+
+void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task)
+{
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ spin_lock(&rtc->irq_task_lock);
+ if (rtc->irq_task == task)
+ rtc->irq_task = NULL;
+ spin_unlock(&rtc->irq_task_lock);
+}
+EXPORT_SYMBOL_GPL(rtc_irq_unregister);
+
+int rtc_irq_set_state(struct class_device *class_dev, struct rtc_task *task, int enabled)
+{
+ int err = 0;
+ unsigned long flags;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ spin_lock_irqsave(&rtc->irq_task_lock, flags);
+ if (rtc->irq_task != task)
+ err = -ENXIO;
+ spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+
+ if (err == 0)
+ err = rtc->ops->irq_set_state(class_dev->dev, enabled);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_irq_set_state);
+
+int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int freq)
+{
+ int err = 0, tmp = 0;
+ unsigned long flags;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ /* allowed range is 2-8192 */
+ if (freq < 2 || freq > 8192)
+ return -EINVAL;
+/*
+ FIXME: this does not belong here, will move where appropriate
+ at a later stage. It cannot hurt right now, trust me :)
+ if ((freq > rtc_max_user_freq) && (!capable(CAP_SYS_RESOURCE)))
+ return -EACCES;
+*/
+ /* check if freq is a power of 2 */
+ while (freq > (1 << tmp))
+ tmp++;
+
+ if (freq != (1 << tmp))
+ return -EINVAL;
+
+ spin_lock_irqsave(&rtc->irq_task_lock, flags);
+ if (rtc->irq_task != task)
+ err = -ENXIO;
+ spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+
+ if (err == 0) {
+ err = rtc->ops->irq_set_freq(class_dev->dev, freq);
+ if (err == 0)
+ rtc->irq_freq = freq;
+ }
+ return err;
+}
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
new file mode 100644
index 00000000000..b1e3e6179e5
--- /dev/null
+++ b/drivers/rtc/rtc-dev.c
@@ -0,0 +1,382 @@
+/*
+ * RTC subsystem, dev interface
+ *
+ * Copyright (C) 2005 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * based on arch/arm/common/rtctime.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/module.h>
+#include <linux/rtc.h>
+
+static struct class *rtc_dev_class;
+static dev_t rtc_devt;
+
+#define RTC_DEV_MAX 16 /* 16 RTCs should be enough for everyone... */
+
+static int rtc_dev_open(struct inode *inode, struct file *file)
+{
+ int err;
+ struct rtc_device *rtc = container_of(inode->i_cdev,
+ struct rtc_device, char_dev);
+ struct rtc_class_ops *ops = rtc->ops;
+
+ /* We keep the lock as long as the device is in use
+ * and return immediately if busy
+ */
+ if (!(mutex_trylock(&rtc->char_lock)))
+ return -EBUSY;
+
+ file->private_data = &rtc->class_dev;
+
+ err = ops->open ? ops->open(rtc->class_dev.dev) : 0;
+ if (err == 0) {
+ spin_lock_irq(&rtc->irq_lock);
+ rtc->irq_data = 0;
+ spin_unlock_irq(&rtc->irq_lock);
+
+ return 0;
+ }
+
+ /* something has gone wrong, release the lock */
+ mutex_unlock(&rtc->char_lock);
+ return err;
+}
+
+
+static ssize_t
+rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ struct rtc_device *rtc = to_rtc_device(file->private_data);
+
+ DECLARE_WAITQUEUE(wait, current);
+ unsigned long data;
+ ssize_t ret;
+
+ if (count < sizeof(unsigned long))
+ return -EINVAL;
+
+ add_wait_queue(&rtc->irq_queue, &wait);
+ do {
+ __set_current_state(TASK_INTERRUPTIBLE);
+
+ spin_lock_irq(&rtc->irq_lock);
+ data = rtc->irq_data;
+ rtc->irq_data = 0;
+ spin_unlock_irq(&rtc->irq_lock);
+
+ if (data != 0) {
+ ret = 0;
+ break;
+ }
+ if (file->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+ schedule();
+ } while (1);
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&rtc->irq_queue, &wait);
+
+ if (ret == 0) {
+ /* Check for any data updates */
+ if (rtc->ops->read_callback)
+ data = rtc->ops->read_callback(rtc->class_dev.dev, data);
+
+ ret = put_user(data, (unsigned long __user *)buf);
+ if (ret == 0)
+ ret = sizeof(unsigned long);
+ }
+ return ret;
+}
+
+static unsigned int rtc_dev_poll(struct file *file, poll_table *wait)
+{
+ struct rtc_device *rtc = to_rtc_device(file->private_data);
+ unsigned long data;
+
+ poll_wait(file, &rtc->irq_queue, wait);
+
+ data = rtc->irq_data;
+
+ return (data != 0) ? (POLLIN | POLLRDNORM) : 0;
+}
+
+static int rtc_dev_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int err = 0;
+ struct class_device *class_dev = file->private_data;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+ struct rtc_class_ops *ops = rtc->ops;
+ struct rtc_time tm;
+ struct rtc_wkalrm alarm;
+ void __user *uarg = (void __user *) arg;
+
+ /* avoid conflicting IRQ users */
+ if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) {
+ spin_lock(&rtc->irq_task_lock);
+ if (rtc->irq_task)
+ err = -EBUSY;
+ spin_unlock(&rtc->irq_task_lock);
+
+ if (err < 0)
+ return err;
+ }
+
+ /* try the driver's ioctl interface */
+ if (ops->ioctl) {
+ err = ops->ioctl(class_dev->dev, cmd, arg);
+ if (err != -EINVAL)
+ return err;
+ }
+
+ /* if the driver does not provide the ioctl interface
+ * or if that particular ioctl was not implemented
+ * (-EINVAL), we will try to emulate here.
+ */
+
+ switch (cmd) {
+ case RTC_ALM_READ:
+ err = rtc_read_alarm(class_dev, &alarm);
+ if (err < 0)
+ return err;
+
+ if (copy_to_user(uarg, &alarm.time, sizeof(tm)))
+ return -EFAULT;
+ break;
+
+ case RTC_ALM_SET:
+ if (copy_from_user(&alarm.time, uarg, sizeof(tm)))
+ return -EFAULT;
+
+ alarm.enabled = 0;
+ alarm.pending = 0;
+ alarm.time.tm_mday = -1;
+ alarm.time.tm_mon = -1;
+ alarm.time.tm_year = -1;
+ alarm.time.tm_wday = -1;
+ alarm.time.tm_yday = -1;
+ alarm.time.tm_isdst = -1;
+ err = rtc_set_alarm(class_dev, &alarm);
+ break;
+
+ case RTC_RD_TIME:
+ err = rtc_read_time(class_dev, &tm);
+ if (err < 0)
+ return err;
+
+ if (copy_to_user(uarg, &tm, sizeof(tm)))
+ return -EFAULT;
+ break;
+
+ case RTC_SET_TIME:
+ if (!capable(CAP_SYS_TIME))
+ return -EACCES;
+
+ if (copy_from_user(&tm, uarg, sizeof(tm)))
+ return -EFAULT;
+
+ err = rtc_set_time(class_dev, &tm);
+ break;
+#if 0
+ case RTC_EPOCH_SET:
+#ifndef rtc_epoch
+ /*
+ * There were no RTC clocks before 1900.
+ */
+ if (arg < 1900) {
+ err = -EINVAL;
+ break;
+ }
+ if (!capable(CAP_SYS_TIME)) {
+ err = -EACCES;
+ break;
+ }
+ rtc_epoch = arg;
+ err = 0;
+#endif
+ break;
+
+ case RTC_EPOCH_READ:
+ err = put_user(rtc_epoch, (unsigned long __user *)uarg);
+ break;
+#endif
+ case RTC_WKALM_SET:
+ if (copy_from_user(&alarm, uarg, sizeof(alarm)))
+ return -EFAULT;
+
+ err = rtc_set_alarm(class_dev, &alarm);
+ break;
+
+ case RTC_WKALM_RD:
+ err = rtc_read_alarm(class_dev, &alarm);
+ if (err < 0)
+ return err;
+
+ if (copy_to_user(uarg, &alarm, sizeof(alarm)))
+ return -EFAULT;
+ break;
+
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+static int rtc_dev_release(struct inode *inode, struct file *file)
+{
+ struct rtc_device *rtc = to_rtc_device(file->private_data);
+
+ if (rtc->ops->release)
+ rtc->ops->release(rtc->class_dev.dev);
+
+ mutex_unlock(&rtc->char_lock);
+ return 0;
+}
+
+static int rtc_dev_fasync(int fd, struct file *file, int on)
+{
+ struct rtc_device *rtc = to_rtc_device(file->private_data);
+ return fasync_helper(fd, file, on, &rtc->async_queue);
+}
+
+static struct file_operations rtc_dev_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = rtc_dev_read,
+ .poll = rtc_dev_poll,
+ .ioctl = rtc_dev_ioctl,
+ .open = rtc_dev_open,
+ .release = rtc_dev_release,
+ .fasync = rtc_dev_fasync,
+};
+
+/* insertion/removal hooks */
+
+static int rtc_dev_add_device(struct class_device *class_dev,
+ struct class_interface *class_intf)
+{
+ int err = 0;
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ if (rtc->id >= RTC_DEV_MAX) {
+ dev_err(class_dev->dev, "too many RTCs\n");
+ return -EINVAL;
+ }
+
+ mutex_init(&rtc->char_lock);
+ spin_lock_init(&rtc->irq_lock);
+ init_waitqueue_head(&rtc->irq_queue);
+
+ cdev_init(&rtc->char_dev, &rtc_dev_fops);
+ rtc->char_dev.owner = rtc->owner;
+
+ if (cdev_add(&rtc->char_dev, MKDEV(MAJOR(rtc_devt), rtc->id), 1)) {
+ cdev_del(&rtc->char_dev);
+ dev_err(class_dev->dev,
+ "failed to add char device %d:%d\n",
+ MAJOR(rtc_devt), rtc->id);
+ return -ENODEV;
+ }
+
+ rtc->rtc_dev = class_device_create(rtc_dev_class, NULL,
+ MKDEV(MAJOR(rtc_devt), rtc->id),
+ class_dev->dev, "rtc%d", rtc->id);
+ if (IS_ERR(rtc->rtc_dev)) {
+ dev_err(class_dev->dev, "cannot create rtc_dev device\n");
+ err = PTR_ERR(rtc->rtc_dev);
+ goto err_cdev_del;
+ }
+
+ dev_info(class_dev->dev, "rtc intf: dev (%d:%d)\n",
+ MAJOR(rtc->rtc_dev->devt),
+ MINOR(rtc->rtc_dev->devt));
+
+ return 0;
+
+err_cdev_del:
+
+ cdev_del(&rtc->char_dev);
+ return err;
+}
+
+static void rtc_dev_remove_device(struct class_device *class_dev,
+ struct class_interface *class_intf)
+{
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ if (rtc->rtc_dev) {
+ dev_dbg(class_dev->dev, "removing char %d:%d\n",
+ MAJOR(rtc->rtc_dev->devt),
+ MINOR(rtc->rtc_dev->devt));
+
+ class_device_unregister(rtc->rtc_dev);
+ cdev_del(&rtc->char_dev);
+ }
+}
+
+/* interface registration */
+
+static struct class_interface rtc_dev_interface = {
+ .add = &rtc_dev_add_device,
+ .remove = &rtc_dev_remove_device,
+};
+
+static int __init rtc_dev_init(void)
+{
+ int err;
+
+ rtc_dev_class = class_create(THIS_MODULE, "rtc-dev");
+ if (IS_ERR(rtc_dev_class))
+ return PTR_ERR(rtc_dev_class);
+
+ err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc");
+ if (err < 0) {
+ printk(KERN_ERR "%s: failed to allocate char dev region\n",
+ __FILE__);
+ goto err_destroy_class;
+ }
+
+ err = rtc_interface_register(&rtc_dev_interface);
+ if (err < 0) {
+ printk(KERN_ERR "%s: failed to register the interface\n",
+ __FILE__);
+ goto err_unregister_chrdev;
+ }
+
+ return 0;
+
+err_unregister_chrdev:
+ unregister_chrdev_region(rtc_devt, RTC_DEV_MAX);
+
+err_destroy_class:
+ class_destroy(rtc_dev_class);
+
+ return err;
+}
+
+static void __exit rtc_dev_exit(void)
+{
+ class_interface_unregister(&rtc_dev_interface);
+ class_destroy(rtc_dev_class);
+ unregister_chrdev_region(rtc_devt, RTC_DEV_MAX);
+}
+
+module_init(rtc_dev_init);
+module_exit(rtc_dev_exit);
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("RTC class dev interface");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
new file mode 100644
index 00000000000..358695a416f
--- /dev/null
+++ b/drivers/rtc/rtc-ds1672.c
@@ -0,0 +1,233 @@
+/*
+ * An rtc/i2c driver for the Dallas DS1672
+ * Copyright 2005 Alessandro Zummo
+ *
+ * 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/i2c.h>
+#include <linux/rtc.h>
+
+#define DRV_VERSION "0.2"
+
+/* Addresses to scan: none. This chip cannot be detected. */
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD;
+
+/* Registers */
+
+#define DS1672_REG_CNT_BASE 0
+#define DS1672_REG_CONTROL 4
+#define DS1672_REG_TRICKLE 5
+
+
+/* Prototypes */
+static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind);
+
+/*
+ * In the routines that deal directly with the ds1672 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
+ * Epoch is initialized as 2000. Time is set to UTC.
+ */
+static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ unsigned long time;
+ unsigned char addr = DS1672_REG_CNT_BASE;
+ unsigned char buf[4];
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 1, &addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 4, buf }, /* read date */
+ };
+
+ /* read date registers */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev,
+ "%s: raw read data - counters=%02x,%02x,%02x,%02x\n"
+ __FUNCTION__,
+ buf[0], buf[1], buf[2], buf[3]);
+
+ time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+ rtc_time_to_tm(time, tm);
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ return 0;
+}
+
+static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs)
+{
+ int xfer;
+ unsigned char buf[5];
+
+ buf[0] = DS1672_REG_CNT_BASE;
+ buf[1] = secs & 0x000000FF;
+ buf[2] = (secs & 0x0000FF00) >> 8;
+ buf[3] = (secs & 0x00FF0000) >> 16;
+ buf[4] = (secs & 0xFF000000) >> 24;
+
+ xfer = i2c_master_send(client, buf, 5);
+ if (xfer != 5) {
+ dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int ds1672_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ unsigned long secs;
+
+ dev_dbg(&client->dev,
+ "%s: secs=%d, mins=%d, hours=%d, ",
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ rtc_tm_to_time(tm, &secs);
+
+ return ds1672_set_mmss(client, secs);
+}
+
+static int ds1672_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ return ds1672_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int ds1672_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return ds1672_set_datetime(to_i2c_client(dev), tm);
+}
+
+static int ds1672_rtc_set_mmss(struct device *dev, unsigned long secs)
+{
+ return ds1672_set_mmss(to_i2c_client(dev), secs);
+}
+
+static struct rtc_class_ops ds1672_rtc_ops = {
+ .read_time = ds1672_rtc_read_time,
+ .set_time = ds1672_rtc_set_time,
+ .set_mmss = ds1672_rtc_set_mmss,
+};
+
+static int ds1672_attach(struct i2c_adapter *adapter)
+{
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+ return i2c_probe(adapter, &addr_data, ds1672_probe);
+}
+
+static int ds1672_detach(struct i2c_client *client)
+{
+ int err;
+ struct rtc_device *rtc = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "%s\n", __FUNCTION__);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ if ((err = i2c_detach_client(client)))
+ return err;
+
+ kfree(client);
+
+ return 0;
+}
+
+static struct i2c_driver ds1672_driver = {
+ .driver = {
+ .name = "ds1672",
+ },
+ .id = I2C_DRIVERID_DS1672,
+ .attach_adapter = &ds1672_attach,
+ .detach_client = &ds1672_detach,
+};
+
+static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
+{
+ int err = 0;
+ struct i2c_client *client;
+ struct rtc_device *rtc;
+
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ err = -ENODEV;
+ goto exit;
+ }
+
+ if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ /* I2C client */
+ client->addr = address;
+ client->driver = &ds1672_driver;
+ client->adapter = adapter;
+
+ strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE);
+
+ /* Inform the i2c layer */
+ if ((err = i2c_attach_client(client)))
+ goto exit_kfree;
+
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+ rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev,
+ &ds1672_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc)) {
+ err = PTR_ERR(rtc);
+ dev_err(&client->dev,
+ "unable to register the class device\n");
+ goto exit_detach;
+ }
+
+ i2c_set_clientdata(client, rtc);
+
+ return 0;
+
+exit_detach:
+ i2c_detach_client(client);
+
+exit_kfree:
+ kfree(client);
+
+exit:
+ return err;
+}
+
+static int __init ds1672_init(void)
+{
+ return i2c_add_driver(&ds1672_driver);
+}
+
+static void __exit ds1672_exit(void)
+{
+ i2c_del_driver(&ds1672_driver);
+}
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("Dallas/Maxim DS1672 timekeeper driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ds1672_init);
+module_exit(ds1672_exit);
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c
new file mode 100644
index 00000000000..0dd80ea686a
--- /dev/null
+++ b/drivers/rtc/rtc-ep93xx.c
@@ -0,0 +1,162 @@
+/*
+ * A driver for the RTC embedded in the Cirrus Logic EP93XX processors
+ * Copyright (c) 2006 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * 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/rtc.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+
+#define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x))
+#define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000)
+#define EP93XX_RTC_LOAD EP93XX_RTC_REG(0x000C)
+#define EP93XX_RTC_SWCOMP EP93XX_RTC_REG(0x0108)
+
+#define DRV_VERSION "0.2"
+
+static int ep93xx_get_swcomp(struct device *dev, unsigned short *preload,
+ unsigned short *delete)
+{
+ unsigned short comp = __raw_readl(EP93XX_RTC_SWCOMP);
+
+ if (preload)
+ *preload = comp & 0xffff;
+
+ if (delete)
+ *delete = (comp >> 16) & 0x1f;
+
+ return 0;
+}
+
+static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned long time = __raw_readl(EP93XX_RTC_DATA);
+
+ rtc_time_to_tm(time, tm);
+ return 0;
+}
+
+static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs)
+{
+ __raw_writel(secs + 1, EP93XX_RTC_LOAD);
+ return 0;
+}
+
+static int ep93xx_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ int err;
+ unsigned long secs;
+
+ err = rtc_tm_to_time(tm, &secs);
+ if (err != 0)
+ return err;
+
+ return ep93xx_rtc_set_mmss(dev, secs);
+}
+
+static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ unsigned short preload, delete;
+
+ ep93xx_get_swcomp(dev, &preload, &delete);
+
+ seq_printf(seq, "24hr\t\t: yes\n");
+ seq_printf(seq, "preload\t\t: %d\n", preload);
+ seq_printf(seq, "delete\t\t: %d\n", delete);
+
+ return 0;
+}
+
+static struct rtc_class_ops ep93xx_rtc_ops = {
+ .read_time = ep93xx_rtc_read_time,
+ .set_time = ep93xx_rtc_set_time,
+ .set_mmss = ep93xx_rtc_set_mmss,
+ .proc = ep93xx_rtc_proc,
+};
+
+static ssize_t ep93xx_sysfs_show_comp_preload(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned short preload;
+
+ ep93xx_get_swcomp(dev, &preload, NULL);
+
+ return sprintf(buf, "%d\n", preload);
+}
+static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_sysfs_show_comp_preload, NULL);
+
+static ssize_t ep93xx_sysfs_show_comp_delete(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned short delete;
+
+ ep93xx_get_swcomp(dev, NULL, &delete);
+
+ return sprintf(buf, "%d\n", delete);
+}
+static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_sysfs_show_comp_delete, NULL);
+
+
+static int __devinit ep93xx_rtc_probe(struct platform_device *dev)
+{
+ struct rtc_device *rtc = rtc_device_register("ep93xx",
+ &dev->dev, &ep93xx_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc)) {
+ dev_err(&dev->dev, "unable to register\n");
+ return PTR_ERR(rtc);
+ }
+
+ platform_set_drvdata(dev, rtc);
+
+ device_create_file(&dev->dev, &dev_attr_comp_preload);
+ device_create_file(&dev->dev, &dev_attr_comp_delete);
+
+ return 0;
+}
+
+static int __devexit ep93xx_rtc_remove(struct platform_device *dev)
+{
+ struct rtc_device *rtc = platform_get_drvdata(dev);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ platform_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver ep93xx_rtc_platform_driver = {
+ .driver = {
+ .name = "ep93xx-rtc",
+ .owner = THIS_MODULE,
+ },
+ .probe = ep93xx_rtc_probe,
+ .remove = __devexit_p(ep93xx_rtc_remove),
+};
+
+static int __init ep93xx_rtc_init(void)
+{
+ return platform_driver_register(&ep93xx_rtc_platform_driver);
+}
+
+static void __exit ep93xx_rtc_exit(void)
+{
+ platform_driver_unregister(&ep93xx_rtc_platform_driver);
+}
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("EP93XX RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ep93xx_rtc_init);
+module_exit(ep93xx_rtc_exit);
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
new file mode 100644
index 00000000000..cfedc1d28ee
--- /dev/null
+++ b/drivers/rtc/rtc-lib.c
@@ -0,0 +1,101 @@
+/*
+ * rtc and date/time utility functions
+ *
+ * Copyright (C) 2005-06 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * based on arch/arm/common/rtctime.c and other bits
+ *
+ * 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/rtc.h>
+
+static const unsigned char rtc_days_in_month[] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
+#define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400))
+
+int rtc_month_days(unsigned int month, unsigned int year)
+{
+ return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 1);
+}
+EXPORT_SYMBOL(rtc_month_days);
+
+/*
+ * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
+ */
+void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
+{
+ register int days, month, year;
+
+ days = time / 86400;
+ time -= days * 86400;
+
+ /* day of the week, 1970-01-01 was a Thursday */
+ tm->tm_wday = (days + 4) % 7;
+
+ year = 1970 + days / 365;
+ days -= (year - 1970) * 365
+ + LEAPS_THRU_END_OF(year - 1)
+ - LEAPS_THRU_END_OF(1970 - 1);
+ if (days < 0) {
+ year -= 1;
+ days += 365 + LEAP_YEAR(year);
+ }
+ tm->tm_year = year - 1900;
+ tm->tm_yday = days + 1;
+
+ for (month = 0; month < 11; month++) {
+ int newdays;
+
+ newdays = days - rtc_month_days(month, year);
+ if (newdays < 0)
+ break;
+ days = newdays;
+ }
+ tm->tm_mon = month;
+ tm->tm_mday = days + 1;
+
+ tm->tm_hour = time / 3600;
+ time -= tm->tm_hour * 3600;
+ tm->tm_min = time / 60;
+ tm->tm_sec = time - tm->tm_min * 60;
+}
+EXPORT_SYMBOL(rtc_time_to_tm);
+
+/*
+ * Does the rtc_time represent a valid date/time?
+ */
+int rtc_valid_tm(struct rtc_time *tm)
+{
+ if (tm->tm_year < 70
+ || tm->tm_mon >= 12
+ || tm->tm_mday < 1
+ || tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + 1900)
+ || tm->tm_hour >= 24
+ || tm->tm_min >= 60
+ || tm->tm_sec >= 60)
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL(rtc_valid_tm);
+
+/*
+ * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
+ */
+int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
+{
+ *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ return 0;
+}
+EXPORT_SYMBOL(rtc_tm_to_time);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
new file mode 100644
index 00000000000..db445c872b1
--- /dev/null
+++ b/drivers/rtc/rtc-m48t86.c
@@ -0,0 +1,209 @@
+/*
+ * ST M48T86 / Dallas DS12887 RTC driver
+ * Copyright (c) 2006 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This drivers only supports the clock running in BCD and 24H mode.
+ * If it will be ever adapted to binary and 12H mode, care must be taken
+ * to not introduce bugs.
+ */
+
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/m48t86.h>
+#include <linux/bcd.h>
+
+#define M48T86_REG_SEC 0x00
+#define M48T86_REG_SECALRM 0x01
+#define M48T86_REG_MIN 0x02
+#define M48T86_REG_MINALRM 0x03
+#define M48T86_REG_HOUR 0x04
+#define M48T86_REG_HOURALRM 0x05
+#define M48T86_REG_DOW 0x06 /* 1 = sunday */
+#define M48T86_REG_DOM 0x07
+#define M48T86_REG_MONTH 0x08 /* 1 - 12 */
+#define M48T86_REG_YEAR 0x09 /* 0 - 99 */
+#define M48T86_REG_A 0x0A
+#define M48T86_REG_B 0x0B
+#define M48T86_REG_C 0x0C
+#define M48T86_REG_D 0x0D
+
+#define M48T86_REG_B_H24 (1 << 1)
+#define M48T86_REG_B_DM (1 << 2)
+#define M48T86_REG_B_SET (1 << 7)
+#define M48T86_REG_D_VRT (1 << 7)
+
+#define DRV_VERSION "0.1"
+
+
+static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned char reg;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t86_ops *ops = pdev->dev.platform_data;
+
+ reg = ops->readb(M48T86_REG_B);
+
+ if (reg & M48T86_REG_B_DM) {
+ /* data (binary) mode */
+ tm->tm_sec = ops->readb(M48T86_REG_SEC);
+ tm->tm_min = ops->readb(M48T86_REG_MIN);
+ tm->tm_hour = ops->readb(M48T86_REG_HOUR) & 0x3F;
+ tm->tm_mday = ops->readb(M48T86_REG_DOM);
+ /* tm_mon is 0-11 */
+ tm->tm_mon = ops->readb(M48T86_REG_MONTH) - 1;
+ tm->tm_year = ops->readb(M48T86_REG_YEAR) + 100;
+ tm->tm_wday = ops->readb(M48T86_REG_DOW);
+ } else {
+ /* bcd mode */
+ tm->tm_sec = BCD2BIN(ops->readb(M48T86_REG_SEC));
+ tm->tm_min = BCD2BIN(ops->readb(M48T86_REG_MIN));
+ tm->tm_hour = BCD2BIN(ops->readb(M48T86_REG_HOUR) & 0x3F);
+ tm->tm_mday = BCD2BIN(ops->readb(M48T86_REG_DOM));
+ /* tm_mon is 0-11 */
+ tm->tm_mon = BCD2BIN(ops->readb(M48T86_REG_MONTH)) - 1;
+ tm->tm_year = BCD2BIN(ops->readb(M48T86_REG_YEAR)) + 100;
+ tm->tm_wday = BCD2BIN(ops->readb(M48T86_REG_DOW));
+ }
+
+ /* correct the hour if the clock is in 12h mode */
+ if (!(reg & M48T86_REG_B_H24))
+ if (ops->readb(M48T86_REG_HOUR) & 0x80)
+ tm->tm_hour += 12;
+
+ return 0;
+}
+
+static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned char reg;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t86_ops *ops = pdev->dev.platform_data;
+
+ reg = ops->readb(M48T86_REG_B);
+
+ /* update flag and 24h mode */
+ reg |= M48T86_REG_B_SET | M48T86_REG_B_H24;
+ ops->writeb(reg, M48T86_REG_B);
+
+ if (reg & M48T86_REG_B_DM) {
+ /* data (binary) mode */
+ ops->writeb(tm->tm_sec, M48T86_REG_SEC);
+ ops->writeb(tm->tm_min, M48T86_REG_MIN);
+ ops->writeb(tm->tm_hour, M48T86_REG_HOUR);
+ ops->writeb(tm->tm_mday, M48T86_REG_DOM);
+ ops->writeb(tm->tm_mon + 1, M48T86_REG_MONTH);
+ ops->writeb(tm->tm_year % 100, M48T86_REG_YEAR);
+ ops->writeb(tm->tm_wday, M48T86_REG_DOW);
+ } else {
+ /* bcd mode */
+ ops->writeb(BIN2BCD(tm->tm_sec), M48T86_REG_SEC);
+ ops->writeb(BIN2BCD(tm->tm_min), M48T86_REG_MIN);
+ ops->writeb(BIN2BCD(tm->tm_hour), M48T86_REG_HOUR);
+ ops->writeb(BIN2BCD(tm->tm_mday), M48T86_REG_DOM);
+ ops->writeb(BIN2BCD(tm->tm_mon + 1), M48T86_REG_MONTH);
+ ops->writeb(BIN2BCD(tm->tm_year % 100), M48T86_REG_YEAR);
+ ops->writeb(BIN2BCD(tm->tm_wday), M48T86_REG_DOW);
+ }
+
+ /* update ended */
+ reg &= ~M48T86_REG_B_SET;
+ ops->writeb(reg, M48T86_REG_B);
+
+ return 0;
+}
+
+static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ unsigned char reg;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct m48t86_ops *ops = pdev->dev.platform_data;
+
+ reg = ops->readb(M48T86_REG_B);
+
+ seq_printf(seq, "24hr\t\t: %s\n",
+ (reg & M48T86_REG_B_H24) ? "yes" : "no");
+
+ seq_printf(seq, "mode\t\t: %s\n",
+ (reg & M48T86_REG_B_DM) ? "binary" : "bcd");
+
+ reg = ops->readb(M48T86_REG_D);
+
+ seq_printf(seq, "battery\t\t: %s\n",
+ (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
+
+ return 0;
+}
+
+static struct rtc_class_ops m48t86_rtc_ops = {
+ .read_time = m48t86_rtc_read_time,
+ .set_time = m48t86_rtc_set_time,
+ .proc = m48t86_rtc_proc,
+};
+
+static int __devinit m48t86_rtc_probe(struct platform_device *dev)
+{
+ unsigned char reg;
+ struct m48t86_ops *ops = dev->dev.platform_data;
+ struct rtc_device *rtc = rtc_device_register("m48t86",
+ &dev->dev, &m48t86_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc)) {
+ dev_err(&dev->dev, "unable to register\n");
+ return PTR_ERR(rtc);
+ }
+
+ platform_set_drvdata(dev, rtc);
+
+ /* read battery status */
+ reg = ops->readb(M48T86_REG_D);
+ dev_info(&dev->dev, "battery %s\n",
+ (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
+
+ return 0;
+}
+
+static int __devexit m48t86_rtc_remove(struct platform_device *dev)
+{
+ struct rtc_device *rtc = platform_get_drvdata(dev);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ platform_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver m48t86_rtc_platform_driver = {
+ .driver = {
+ .name = "rtc-m48t86",
+ .owner = THIS_MODULE,
+ },
+ .probe = m48t86_rtc_probe,
+ .remove = __devexit_p(m48t86_rtc_remove),
+};
+
+static int __init m48t86_rtc_init(void)
+{
+ return platform_driver_register(&m48t86_rtc_platform_driver);
+}
+
+static void __exit m48t86_rtc_exit(void)
+{
+ platform_driver_unregister(&m48t86_rtc_platform_driver);
+}
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("M48T86 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(m48t86_rtc_init);
+module_exit(m48t86_rtc_exit);
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
new file mode 100644
index 00000000000..d857d45bdbe
--- /dev/null
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -0,0 +1,353 @@
+/*
+ * An I2C driver for the Philips PCF8563 RTC
+ * Copyright 2005-06 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ * based on the other drivers in this same directory.
+ *
+ * http://www.semiconductors.philips.com/acrobat/datasheets/PCF8563-04.pdf
+ *
+ * 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/i2c.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+
+#define DRV_VERSION "0.4.2"
+
+/* Addresses to scan: none
+ * This chip cannot be reliably autodetected. An empty eeprom
+ * located at 0x51 will pass the validation routine due to
+ * the way the registers are implemented.
+ */
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Module parameters */
+I2C_CLIENT_INSMOD;
+
+#define PCF8563_REG_ST1 0x00 /* status */
+#define PCF8563_REG_ST2 0x01
+
+#define PCF8563_REG_SC 0x02 /* datetime */
+#define PCF8563_REG_MN 0x03
+#define PCF8563_REG_HR 0x04
+#define PCF8563_REG_DM 0x05
+#define PCF8563_REG_DW 0x06
+#define PCF8563_REG_MO 0x07
+#define PCF8563_REG_YR 0x08
+
+#define PCF8563_REG_AMN 0x09 /* alarm */
+#define PCF8563_REG_AHR 0x0A
+#define PCF8563_REG_ADM 0x0B
+#define PCF8563_REG_ADW 0x0C
+
+#define PCF8563_REG_CLKO 0x0D /* clock out */
+#define PCF8563_REG_TMRC 0x0E /* timer control */
+#define PCF8563_REG_TMR 0x0F /* timer */
+
+#define PCF8563_SC_LV 0x80 /* low voltage */
+#define PCF8563_MO_C 0x80 /* century */
+
+static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind);
+static int pcf8563_detach(struct i2c_client *client);
+
+/*
+ * In the routines that deal directly with the pcf8563 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
+ */
+static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ unsigned char buf[13] = { PCF8563_REG_ST1 };
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 1, buf }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 13, buf }, /* read status + date */
+ };
+
+ /* read registers */
+ if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)
+ dev_info(&client->dev,
+ "low voltage detected, date/time is not reliable.\n");
+
+ dev_dbg(&client->dev,
+ "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
+ "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
+ __FUNCTION__,
+ buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6], buf[7],
+ buf[8]);
+
+
+ tm->tm_sec = BCD2BIN(buf[PCF8563_REG_SC] & 0x7F);
+ tm->tm_min = BCD2BIN(buf[PCF8563_REG_MN] & 0x7F);
+ tm->tm_hour = BCD2BIN(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
+ tm->tm_mday = BCD2BIN(buf[PCF8563_REG_DM] & 0x3F);
+ tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
+ tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
+ tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR])
+ + (buf[PCF8563_REG_MO] & PCF8563_MO_C ? 100 : 0);
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ /* the clock can give out invalid datetime, but we cannot return
+ * -EINVAL otherwise hwclock will refuse to set the time on bootup.
+ */
+ if (rtc_valid_tm(tm) < 0)
+ dev_err(&client->dev, "retrieved date/time is not valid.\n");
+
+ return 0;
+}
+
+static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ int i, err;
+ unsigned char buf[9];
+
+ dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ /* hours, minutes and seconds */
+ buf[PCF8563_REG_SC] = BIN2BCD(tm->tm_sec);
+ buf[PCF8563_REG_MN] = BIN2BCD(tm->tm_min);
+ buf[PCF8563_REG_HR] = BIN2BCD(tm->tm_hour);
+
+ buf[PCF8563_REG_DM] = BIN2BCD(tm->tm_mday);
+
+ /* month, 1 - 12 */
+ buf[PCF8563_REG_MO] = BIN2BCD(tm->tm_mon + 1);
+
+ /* year and century */
+ buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100);
+ if (tm->tm_year / 100)
+ buf[PCF8563_REG_MO] |= PCF8563_MO_C;
+
+ buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
+
+ /* write register's data */
+ for (i = 0; i < 7; i++) {
+ unsigned char data[2] = { PCF8563_REG_SC + i,
+ buf[PCF8563_REG_SC + i] };
+
+ err = i2c_master_send(client, data, sizeof(data));
+ if (err != sizeof(data)) {
+ dev_err(&client->dev,
+ "%s: err=%d addr=%02x, data=%02x\n",
+ __FUNCTION__, err, data[0], data[1]);
+ return -EIO;
+ }
+ };
+
+ return 0;
+}
+
+struct pcf8563_limit
+{
+ unsigned char reg;
+ unsigned char mask;
+ unsigned char min;
+ unsigned char max;
+};
+
+static int pcf8563_validate_client(struct i2c_client *client)
+{
+ int i;
+
+ static const struct pcf8563_limit pattern[] = {
+ /* register, mask, min, max */
+ { PCF8563_REG_SC, 0x7F, 0, 59 },
+ { PCF8563_REG_MN, 0x7F, 0, 59 },
+ { PCF8563_REG_HR, 0x3F, 0, 23 },
+ { PCF8563_REG_DM, 0x3F, 0, 31 },
+ { PCF8563_REG_MO, 0x1F, 0, 12 },
+ };
+
+ /* check limits (only registers with bcd values) */
+ for (i = 0; i < ARRAY_SIZE(pattern); i++) {
+ int xfer;
+ unsigned char value;
+ unsigned char buf = pattern[i].reg;
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 1, &buf },
+ { client->addr, I2C_M_RD, 1, &buf },
+ };
+
+ xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+
+ if (xfer != ARRAY_SIZE(msgs)) {
+ dev_err(&client->adapter->dev,
+ "%s: could not read register 0x%02X\n",
+ __FUNCTION__, pattern[i].reg);
+
+ return -EIO;
+ }
+
+ value = BCD2BIN(buf & pattern[i].mask);
+
+ if (value > pattern[i].max ||
+ value < pattern[i].min) {
+ dev_dbg(&client->adapter->dev,
+ "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, "
+ "max=%d, value=%d, raw=0x%02X\n",
+ __FUNCTION__, i, pattern[i].reg, pattern[i].mask,
+ pattern[i].min, pattern[i].max,
+ value, buf);
+
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ return pcf8563_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return pcf8563_set_datetime(to_i2c_client(dev), tm);
+}
+
+static int pcf8563_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ seq_printf(seq, "24hr\t\t: yes\n");
+ return 0;
+}
+
+static struct rtc_class_ops pcf8563_rtc_ops = {
+ .proc = pcf8563_rtc_proc,
+ .read_time = pcf8563_rtc_read_time,
+ .set_time = pcf8563_rtc_set_time,
+};
+
+static int pcf8563_attach(struct i2c_adapter *adapter)
+{
+ return i2c_probe(adapter, &addr_data, pcf8563_probe);
+}
+
+static struct i2c_driver pcf8563_driver = {
+ .driver = {
+ .name = "pcf8563",
+ },
+ .id = I2C_DRIVERID_PCF8563,
+ .attach_adapter = &pcf8563_attach,
+ .detach_client = &pcf8563_detach,
+};
+
+static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct rtc_device *rtc;
+
+ int err = 0;
+
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ err = -ENODEV;
+ goto exit;
+ }
+
+ if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ client->addr = address;
+ client->driver = &pcf8563_driver;
+ client->adapter = adapter;
+
+ strlcpy(client->name, pcf8563_driver.driver.name, I2C_NAME_SIZE);
+
+ /* Verify the chip is really an PCF8563 */
+ if (kind < 0) {
+ if (pcf8563_validate_client(client) < 0) {
+ err = -ENODEV;
+ goto exit_kfree;
+ }
+ }
+
+ /* Inform the i2c layer */
+ if ((err = i2c_attach_client(client)))
+ goto exit_kfree;
+
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+ rtc = rtc_device_register(pcf8563_driver.driver.name, &client->dev,
+ &pcf8563_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc)) {
+ err = PTR_ERR(rtc);
+ dev_err(&client->dev,
+ "unable to register the class device\n");
+ goto exit_detach;
+ }
+
+ i2c_set_clientdata(client, rtc);
+
+ return 0;
+
+exit_detach:
+ i2c_detach_client(client);
+
+exit_kfree:
+ kfree(client);
+
+exit:
+ return err;
+}
+
+static int pcf8563_detach(struct i2c_client *client)
+{
+ int err;
+ struct rtc_device *rtc = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "%s\n", __FUNCTION__);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ if ((err = i2c_detach_client(client)))
+ return err;
+
+ kfree(client);
+
+ return 0;
+}
+
+static int __init pcf8563_init(void)
+{
+ return i2c_add_driver(&pcf8563_driver);
+}
+
+static void __exit pcf8563_exit(void)
+{
+ i2c_del_driver(&pcf8563_driver);
+}
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(pcf8563_init);
+module_exit(pcf8563_exit);
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
new file mode 100644
index 00000000000..90b8a97a091
--- /dev/null
+++ b/drivers/rtc/rtc-proc.c
@@ -0,0 +1,162 @@
+/*
+ * RTC subsystem, proc interface
+ *
+ * Copyright (C) 2005-06 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * based on arch/arm/common/rtctime.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/module.h>
+#include <linux/rtc.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+static struct class_device *rtc_dev = NULL;
+static DEFINE_MUTEX(rtc_lock);
+
+static int rtc_proc_show(struct seq_file *seq, void *offset)
+{
+ int err;
+ struct class_device *class_dev = seq->private;
+ struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops;
+ struct rtc_wkalrm alrm;
+ struct rtc_time tm;
+
+ err = rtc_read_time(class_dev, &tm);
+ if (err == 0) {
+ seq_printf(seq,
+ "rtc_time\t: %02d:%02d:%02d\n"
+ "rtc_date\t: %04d-%02d-%02d\n",
+ tm.tm_hour, tm.tm_min, tm.tm_sec,
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
+ }
+
+ err = rtc_read_alarm(class_dev, &alrm);
+ if (err == 0) {
+ seq_printf(seq, "alrm_time\t: ");
+ if ((unsigned int)alrm.time.tm_hour <= 24)
+ seq_printf(seq, "%02d:", alrm.time.tm_hour);
+ else
+ seq_printf(seq, "**:");
+ if ((unsigned int)alrm.time.tm_min <= 59)
+ seq_printf(seq, "%02d:", alrm.time.tm_min);
+ else
+ seq_printf(seq, "**:");
+ if ((unsigned int)alrm.time.tm_sec <= 59)
+ seq_printf(seq, "%02d\n", alrm.time.tm_sec);
+ else
+ seq_printf(seq, "**\n");
+
+ seq_printf(seq, "alrm_date\t: ");
+ if ((unsigned int)alrm.time.tm_year <= 200)
+ seq_printf(seq, "%04d-", alrm.time.tm_year + 1900);
+ else
+ seq_printf(seq, "****-");
+ if ((unsigned int)alrm.time.tm_mon <= 11)
+ seq_printf(seq, "%02d-", alrm.time.tm_mon + 1);
+ else
+ seq_printf(seq, "**-");
+ if ((unsigned int)alrm.time.tm_mday <= 31)
+ seq_printf(seq, "%02d\n", alrm.time.tm_mday);
+ else
+ seq_printf(seq, "**\n");
+ seq_printf(seq, "alrm_wakeup\t: %s\n",
+ alrm.enabled ? "yes" : "no");
+ seq_printf(seq, "alrm_pending\t: %s\n",
+ alrm.pending ? "yes" : "no");
+ }
+
+ if (ops->proc)
+ ops->proc(class_dev->dev, seq);
+
+ return 0;
+}
+
+static int rtc_proc_open(struct inode *inode, struct file *file)
+{
+ struct class_device *class_dev = PDE(inode)->data;
+
+ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
+
+ return single_open(file, rtc_proc_show, class_dev);
+}
+
+static int rtc_proc_release(struct inode *inode, struct file *file)
+{
+ int res = single_release(inode, file);
+ module_put(THIS_MODULE);
+ return res;
+}
+
+static struct file_operations rtc_proc_fops = {
+ .open = rtc_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = rtc_proc_release,
+};
+
+static int rtc_proc_add_device(struct class_device *class_dev,
+ struct class_interface *class_intf)
+{
+ mutex_lock(&rtc_lock);
+ if (rtc_dev == NULL) {
+ struct proc_dir_entry *ent;
+
+ rtc_dev = class_dev;
+
+ ent = create_proc_entry("driver/rtc", 0, NULL);
+ if (ent) {
+ struct rtc_device *rtc = to_rtc_device(class_dev);
+
+ ent->proc_fops = &rtc_proc_fops;
+ ent->owner = rtc->owner;
+ ent->data = class_dev;
+
+ dev_info(class_dev->dev, "rtc intf: proc\n");
+ }
+ else
+ rtc_dev = NULL;
+ }
+ mutex_unlock(&rtc_lock);
+
+ return 0;
+}
+
+static void rtc_proc_remove_device(struct class_device *class_dev,
+ struct class_interface *class_intf)
+{
+ mutex_lock(&rtc_lock);
+ if (rtc_dev == class_dev) {
+ remove_proc_entry("driver/rtc", NULL);
+ rtc_dev = NULL;
+ }
+ mutex_unlock(&rtc_lock);
+}
+
+static struct class_interface rtc_proc_interface = {
+ .add = &rtc_proc_add_device,
+ .remove = &rtc_proc_remove_device,
+};
+
+static int __init rtc_proc_init(void)
+{
+ return rtc_interface_register(&rtc_proc_interface);
+}
+
+static void __exit rtc_proc_exit(void)
+{
+ class_interface_unregister(&rtc_proc_interface);
+}
+
+module_init(rtc_proc_init);
+module_exit(rtc_proc_exit);
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("RTC class proc interface");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
new file mode 100644
index 00000000000..396c8681f66
--- /dev/null
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -0,0 +1,294 @@
+/*
+ * An I2C driver for the Ricoh RS5C372 RTC
+ *
+ * Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net>
+ * Copyright (C) 2006 Tower Technologies
+ *
+ * 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/i2c.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+#define DRV_VERSION "0.2"
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD;
+
+#define RS5C372_REG_SECS 0
+#define RS5C372_REG_MINS 1
+#define RS5C372_REG_HOURS 2
+#define RS5C372_REG_WDAY 3
+#define RS5C372_REG_DAY 4
+#define RS5C372_REG_MONTH 5
+#define RS5C372_REG_YEAR 6
+#define RS5C372_REG_TRIM 7
+
+#define RS5C372_TRIM_XSL 0x80
+#define RS5C372_TRIM_MASK 0x7F
+
+#define RS5C372_REG_BASE 0
+
+static int rs5c372_attach(struct i2c_adapter *adapter);
+static int rs5c372_detach(struct i2c_client *client);
+static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind);
+
+static struct i2c_driver rs5c372_driver = {
+ .driver = {
+ .name = "rs5c372",
+ },
+ .attach_adapter = &rs5c372_attach,
+ .detach_client = &rs5c372_detach,
+};
+
+static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ unsigned char buf[7] = { RS5C372_REG_BASE };
+
+ /* this implements the 1st reading method, according
+ * to the datasheet. buf[0] is initialized with
+ * address ptr and transmission format register.
+ */
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 1, buf },
+ { client->addr, I2C_M_RD, 7, buf },
+ };
+
+ if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ tm->tm_sec = BCD2BIN(buf[RS5C372_REG_SECS] & 0x7f);
+ tm->tm_min = BCD2BIN(buf[RS5C372_REG_MINS] & 0x7f);
+ tm->tm_hour = BCD2BIN(buf[RS5C372_REG_HOURS] & 0x3f);
+ tm->tm_wday = BCD2BIN(buf[RS5C372_REG_WDAY] & 0x07);
+ tm->tm_mday = BCD2BIN(buf[RS5C372_REG_DAY] & 0x3f);
+
+ /* tm->tm_mon is zero-based */
+ tm->tm_mon = BCD2BIN(buf[RS5C372_REG_MONTH] & 0x1f) - 1;
+
+ /* year is 1900 + tm->tm_year */
+ tm->tm_year = BCD2BIN(buf[RS5C372_REG_YEAR]) + 100;
+
+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ return 0;
+}
+
+static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ unsigned char buf[8] = { RS5C372_REG_BASE };
+
+ dev_dbg(&client->dev,
+ "%s: secs=%d, mins=%d, hours=%d ",
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ buf[1] = BIN2BCD(tm->tm_sec);
+ buf[2] = BIN2BCD(tm->tm_min);
+ buf[3] = BIN2BCD(tm->tm_hour);
+ buf[4] = BIN2BCD(tm->tm_wday);
+ buf[5] = BIN2BCD(tm->tm_mday);
+ buf[6] = BIN2BCD(tm->tm_mon + 1);
+ buf[7] = BIN2BCD(tm->tm_year - 100);
+
+ if ((i2c_master_send(client, buf, 8)) != 8) {
+ dev_err(&client->dev, "%s: write error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim)
+{
+ unsigned char buf = RS5C372_REG_TRIM;
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 1, &buf },
+ { client->addr, I2C_M_RD, 1, &buf },
+ };
+
+ if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, trim);
+
+ if (osc)
+ *osc = (buf & RS5C372_TRIM_XSL) ? 32000 : 32768;
+
+ if (trim)
+ *trim = buf & RS5C372_TRIM_MASK;
+
+ return 0;
+}
+
+static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ return rs5c372_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return rs5c372_set_datetime(to_i2c_client(dev), tm);
+}
+
+static int rs5c372_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ int err, osc, trim;
+
+ seq_printf(seq, "24hr\t\t: yes\n");
+
+ if ((err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim)) == 0) {
+ seq_printf(seq, "%d.%03d KHz\n", osc / 1000, osc % 1000);
+ seq_printf(seq, "trim\t: %d\n", trim);
+ }
+
+ return 0;
+}
+
+static struct rtc_class_ops rs5c372_rtc_ops = {
+ .proc = rs5c372_rtc_proc,
+ .read_time = rs5c372_rtc_read_time,
+ .set_time = rs5c372_rtc_set_time,
+};
+
+static ssize_t rs5c372_sysfs_show_trim(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int trim;
+
+ if (rs5c372_get_trim(to_i2c_client(dev), NULL, &trim) == 0)
+ return sprintf(buf, "0x%2x\n", trim);
+
+ return 0;
+}
+static DEVICE_ATTR(trim, S_IRUGO, rs5c372_sysfs_show_trim, NULL);
+
+static ssize_t rs5c372_sysfs_show_osc(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int osc;
+
+ if (rs5c372_get_trim(to_i2c_client(dev), &osc, NULL) == 0)
+ return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000);
+
+ return 0;
+}
+static DEVICE_ATTR(osc, S_IRUGO, rs5c372_sysfs_show_osc, NULL);
+
+static int rs5c372_attach(struct i2c_adapter *adapter)
+{
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+ return i2c_probe(adapter, &addr_data, rs5c372_probe);
+}
+
+static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
+{
+ int err = 0;
+ struct i2c_client *client;
+ struct rtc_device *rtc;
+
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ err = -ENODEV;
+ goto exit;
+ }
+
+ if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ /* I2C client */
+ client->addr = address;
+ client->driver = &rs5c372_driver;
+ client->adapter = adapter;
+
+ strlcpy(client->name, rs5c372_driver.driver.name, I2C_NAME_SIZE);
+
+ /* Inform the i2c layer */
+ if ((err = i2c_attach_client(client)))
+ goto exit_kfree;
+
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+ rtc = rtc_device_register(rs5c372_driver.driver.name, &client->dev,
+ &rs5c372_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc)) {
+ err = PTR_ERR(rtc);
+ dev_err(&client->dev,
+ "unable to register the class device\n");
+ goto exit_detach;
+ }
+
+ i2c_set_clientdata(client, rtc);
+
+ device_create_file(&client->dev, &dev_attr_trim);
+ device_create_file(&client->dev, &dev_attr_osc);
+
+ return 0;
+
+exit_detach:
+ i2c_detach_client(client);
+
+exit_kfree:
+ kfree(client);
+
+exit:
+ return err;
+}
+
+static int rs5c372_detach(struct i2c_client *client)
+{
+ int err;
+ struct rtc_device *rtc = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "%s\n", __FUNCTION__);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ if ((err = i2c_detach_client(client)))
+ return err;
+
+ kfree(client);
+
+ return 0;
+}
+
+static __init int rs5c372_init(void)
+{
+ return i2c_add_driver(&rs5c372_driver);
+}
+
+static __exit void rs5c372_exit(void)
+{
+ i2c_del_driver(&rs5c372_driver);
+}
+
+module_init(rs5c372_init);
+module_exit(rs5c372_exit);
+
+MODULE_AUTHOR(
+ "Pavel Mironchik <pmironchik@optifacio.net>, "
+ "Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
new file mode 100644
index 00000000000..83b2bb480a1
--- /dev/null
+++ b/drivers/rtc/rtc-sa1100.c
@@ -0,0 +1,388 @@
+/*
+ * Real Time Clock interface for StrongARM SA1x00 and XScale PXA2xx
+ *
+ * Copyright (c) 2000 Nils Faerber
+ *
+ * Based on rtc.c by Paul Gortmaker
+ *
+ * Original Driver by Nils Faerber <nils@kernelconcepts.de>
+ *
+ * Modifications from:
+ * CIH <cih@coventive.com>
+ * Nicolas Pitre <nico@cam.org>
+ * Andrew Christian <andrew.christian@hp.com>
+ *
+ * Converted to the RTC subsystem and Driver Model
+ * by Richard Purdie <rpurdie@rpsys.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 of the License, or (at your option) any later version.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/pm.h>
+
+#include <asm/bitops.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/rtc.h>
+
+#ifdef CONFIG_ARCH_PXA
+#include <asm/arch/pxa-regs.h>
+#endif
+
+#define TIMER_FREQ CLOCK_TICK_RATE
+#define RTC_DEF_DIVIDER 32768 - 1
+#define RTC_DEF_TRIM 0
+
+static unsigned long rtc_freq = 1024;
+static struct rtc_time rtc_alarm;
+static spinlock_t sa1100_rtc_lock = SPIN_LOCK_UNLOCKED;
+
+static int rtc_update_alarm(struct rtc_time *alrm)
+{
+ struct rtc_time alarm_tm, now_tm;
+ unsigned long now, time;
+ int ret;
+
+ do {
+ now = RCNR;
+ rtc_time_to_tm(now, &now_tm);
+ rtc_next_alarm_time(&alarm_tm, &now_tm, alrm);
+ ret = rtc_tm_to_time(&alarm_tm, &time);
+ if (ret != 0)
+ break;
+
+ RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
+ RTAR = time;
+ } while (now != RCNR);
+
+ return ret;
+}
+
+static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ struct platform_device *pdev = to_platform_device(dev_id);
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+ unsigned int rtsr;
+ unsigned long events = 0;
+
+ spin_lock(&sa1100_rtc_lock);
+
+ rtsr = RTSR;
+ /* clear interrupt sources */
+ RTSR = 0;
+ RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
+
+ /* clear alarm interrupt if it has occurred */
+ if (rtsr & RTSR_AL)
+ rtsr &= ~RTSR_ALE;
+ RTSR = rtsr & (RTSR_ALE | RTSR_HZE);
+
+ /* update irq data & counter */
+ if (rtsr & RTSR_AL)
+ events |= RTC_AF | RTC_IRQF;
+ if (rtsr & RTSR_HZ)
+ events |= RTC_UF | RTC_IRQF;
+
+ rtc_update_irq(&rtc->class_dev, 1, events);
+
+ if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm))
+ rtc_update_alarm(&rtc_alarm);
+
+ spin_unlock(&sa1100_rtc_lock);
+
+ return IRQ_HANDLED;
+}
+
+static int rtc_timer1_count;
+
+static irqreturn_t timer1_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ struct platform_device *pdev = to_platform_device(dev_id);
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+ /*
+ * If we match for the first time, rtc_timer1_count will be 1.
+ * Otherwise, we wrapped around (very unlikely but
+ * still possible) so compute the amount of missed periods.
+ * The match reg is updated only when the data is actually retrieved
+ * to avoid unnecessary interrupts.
+ */
+ OSSR = OSSR_M1; /* clear match on timer1 */
+
+ rtc_update_irq(&rtc->class_dev, rtc_timer1_count, RTC_PF | RTC_IRQF);
+
+ if (rtc_timer1_count == 1)
+ rtc_timer1_count = (rtc_freq * ((1<<30)/(TIMER_FREQ>>2)));
+
+ return IRQ_HANDLED;
+}
+
+static int sa1100_rtc_read_callback(struct device *dev, int data)
+{
+ if (data & RTC_PF) {
+ /* interpolate missed periods and set match for the next */
+ unsigned long period = TIMER_FREQ/rtc_freq;
+ unsigned long oscr = OSCR;
+ unsigned long osmr1 = OSMR1;
+ unsigned long missed = (oscr - osmr1)/period;
+ data += missed << 8;
+ OSSR = OSSR_M1; /* clear match on timer 1 */
+ OSMR1 = osmr1 + (missed + 1)*period;
+ /* Ensure we didn't miss another match in the mean time.
+ * Here we compare (match - OSCR) 8 instead of 0 --
+ * see comment in pxa_timer_interrupt() for explanation.
+ */
+ while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) {
+ data += 0x100;
+ OSSR = OSSR_M1; /* clear match on timer 1 */
+ OSMR1 = osmr1 + period;
+ }
+ }
+ return data;
+}
+
+static int sa1100_rtc_open(struct device *dev)
+{
+ int ret;
+
+ ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, SA_INTERRUPT,
+ "rtc 1Hz", dev);
+ if (ret) {
+ printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTC1Hz);
+ goto fail_ui;
+ }
+ ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, SA_INTERRUPT,
+ "rtc Alrm", dev);
+ if (ret) {
+ printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTCAlrm);
+ goto fail_ai;
+ }
+ ret = request_irq(IRQ_OST1, timer1_interrupt, SA_INTERRUPT,
+ "rtc timer", dev);
+ if (ret) {
+ printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_OST1);
+ goto fail_pi;
+ }
+ return 0;
+
+ fail_pi:
+ free_irq(IRQ_RTCAlrm, NULL);
+ fail_ai:
+ free_irq(IRQ_RTC1Hz, NULL);
+ fail_ui:
+ return ret;
+}
+
+static void sa1100_rtc_release(struct device *dev)
+{
+ spin_lock_irq(&sa1100_rtc_lock);
+ RTSR = 0;
+ OIER &= ~OIER_E1;
+ OSSR = OSSR_M1;
+ spin_unlock_irq(&sa1100_rtc_lock);
+
+ free_irq(IRQ_OST1, dev);
+ free_irq(IRQ_RTCAlrm, dev);
+ free_irq(IRQ_RTC1Hz, dev);
+}
+
+
+static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
+ unsigned long arg)
+{
+ switch(cmd) {
+ case RTC_AIE_OFF:
+ spin_lock_irq(&sa1100_rtc_lock);
+ RTSR &= ~RTSR_ALE;
+ spin_unlock_irq(&sa1100_rtc_lock);
+ return 0;
+ case RTC_AIE_ON:
+ spin_lock_irq(&sa1100_rtc_lock);
+ RTSR |= RTSR_ALE;
+ spin_unlock_irq(&sa1100_rtc_lock);
+ return 0;
+ case RTC_UIE_OFF:
+ spin_lock_irq(&sa1100_rtc_lock);
+ RTSR &= ~RTSR_HZE;
+ spin_unlock_irq(&sa1100_rtc_lock);
+ return 0;
+ case RTC_UIE_ON:
+ spin_lock_irq(&sa1100_rtc_lock);
+ RTSR |= RTSR_HZE;
+ spin_unlock_irq(&sa1100_rtc_lock);
+ return 0;
+ case RTC_PIE_OFF:
+ spin_lock_irq(&sa1100_rtc_lock);
+ OIER &= ~OIER_E1;
+ spin_unlock_irq(&sa1100_rtc_lock);
+ return 0;
+ case RTC_PIE_ON:
+ if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE))
+ return -EACCES;
+ spin_lock_irq(&sa1100_rtc_lock);
+ OSMR1 = TIMER_FREQ/rtc_freq + OSCR;
+ OIER |= OIER_E1;
+ rtc_timer1_count = 1;
+ spin_unlock_irq(&sa1100_rtc_lock);
+ return 0;
+ case RTC_IRQP_READ:
+ return put_user(rtc_freq, (unsigned long *)arg);
+ case RTC_IRQP_SET:
+ if (arg < 1 || arg > TIMER_FREQ)
+ return -EINVAL;
+ if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
+ return -EACCES;
+ rtc_freq = arg;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ rtc_time_to_tm(RCNR, tm);
+ return 0;
+}
+
+static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned long time;
+ int ret;
+
+ ret = rtc_tm_to_time(tm, &time);
+ if (ret == 0)
+ RCNR = time;
+ return ret;
+}
+
+static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time));
+ alrm->pending = RTSR & RTSR_AL ? 1 : 0;
+ return 0;
+}
+
+static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ int ret;
+
+ spin_lock_irq(&sa1100_rtc_lock);
+ ret = rtc_update_alarm(&alrm->time);
+ if (ret == 0) {
+ memcpy(&rtc_alarm, &alrm->time, sizeof(struct rtc_time));
+
+ if (alrm->enabled)
+ enable_irq_wake(IRQ_RTCAlrm);
+ else
+ disable_irq_wake(IRQ_RTCAlrm);
+ }
+ spin_unlock_irq(&sa1100_rtc_lock);
+
+ return ret;
+}
+
+static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ seq_printf(seq, "trim/divider\t: 0x%08x\n", RTTR);
+ seq_printf(seq, "alarm_IRQ\t: %s\n",
+ (RTSR & RTSR_ALE) ? "yes" : "no" );
+ seq_printf(seq, "update_IRQ\t: %s\n",
+ (RTSR & RTSR_HZE) ? "yes" : "no");
+ seq_printf(seq, "periodic_IRQ\t: %s\n",
+ (OIER & OIER_E1) ? "yes" : "no");
+ seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq);
+
+ return 0;
+}
+
+static struct rtc_class_ops sa1100_rtc_ops = {
+ .open = sa1100_rtc_open,
+ .read_callback = sa1100_rtc_read_callback,
+ .release = sa1100_rtc_release,
+ .ioctl = sa1100_rtc_ioctl,
+ .read_time = sa1100_rtc_read_time,
+ .set_time = sa1100_rtc_set_time,
+ .read_alarm = sa1100_rtc_read_alarm,
+ .set_alarm = sa1100_rtc_set_alarm,
+ .proc = sa1100_rtc_proc,
+};
+
+static int sa1100_rtc_probe(struct platform_device *pdev)
+{
+ struct rtc_device *rtc;
+
+ /*
+ * According to the manual we should be able to let RTTR be zero
+ * and then a default diviser for a 32.768KHz clock is used.
+ * Apparently this doesn't work, at least for my SA1110 rev 5.
+ * If the clock divider is uninitialized then reset it to the
+ * default value to get the 1Hz clock.
+ */
+ if (RTTR == 0) {
+ RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
+ printk(KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n");
+ /* The current RTC value probably doesn't make sense either */
+ RCNR = 0;
+ }
+
+ rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
+ THIS_MODULE);
+
+ if (IS_ERR(rtc)) {
+ dev_err(&pdev->dev, "Unable to register the RTC device\n");
+ return PTR_ERR(rtc);
+ }
+
+ platform_set_drvdata(pdev, rtc);
+
+ dev_info(&pdev->dev, "SA11xx/PXA2xx RTC Registered\n");
+
+ return 0;
+}
+
+static int sa1100_rtc_remove(struct platform_device *pdev)
+{
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ return 0;
+}
+
+static struct platform_driver sa1100_rtc_driver = {
+ .probe = sa1100_rtc_probe,
+ .remove = sa1100_rtc_remove,
+ .driver = {
+ .name = "sa1100-rtc",
+ },
+};
+
+static int __init sa1100_rtc_init(void)
+{
+ return platform_driver_register(&sa1100_rtc_driver);
+}
+
+static void __exit sa1100_rtc_exit(void)
+{
+ platform_driver_unregister(&sa1100_rtc_driver);
+}
+
+module_init(sa1100_rtc_init);
+module_exit(sa1100_rtc_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
+MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
new file mode 100644
index 00000000000..7c1f3d2e53c
--- /dev/null
+++ b/drivers/rtc/rtc-sysfs.c
@@ -0,0 +1,124 @@
+/*
+ * RTC subsystem, sysfs interface
+ *
+ * Copyright (C) 2005 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * 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/rtc.h>
+
+/* device attributes */
+
+static ssize_t rtc_sysfs_show_name(struct class_device *dev, char *buf)
+{
+ return sprintf(buf, "%s\n", to_rtc_device(dev)->name);
+}
+static CLASS_DEVICE_ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL);
+
+static ssize_t rtc_sysfs_show_date(struct class_device *dev, char *buf)
+{
+ ssize_t retval;
+ struct rtc_time tm;
+
+ retval = rtc_read_time(dev, &tm);
+ if (retval == 0) {
+ retval = sprintf(buf, "%04d-%02d-%02d\n",
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
+ }
+
+ return retval;
+}
+static CLASS_DEVICE_ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL);
+
+static ssize_t rtc_sysfs_show_time(struct class_device *dev, char *buf)
+{
+ ssize_t retval;
+ struct rtc_time tm;
+
+ retval = rtc_read_time(dev, &tm);
+ if (retval == 0) {
+ retval = sprintf(buf, "%02d:%02d:%02d\n",
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ }
+
+ return retval;
+}
+static CLASS_DEVICE_ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL);
+
+static ssize_t rtc_sysfs_show_since_epoch(struct class_device *dev, char *buf)
+{
+ ssize_t retval;
+ struct rtc_time tm;
+
+ retval = rtc_read_time(dev, &tm);
+ if (retval == 0) {
+ unsigned long time;
+ rtc_tm_to_time(&tm, &time);
+ retval = sprintf(buf, "%lu\n", time);
+ }
+
+ return retval;
+}
+static CLASS_DEVICE_ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL);
+
+static struct attribute *rtc_attrs[] = {
+ &class_device_attr_name.attr,
+ &class_device_attr_date.attr,
+ &class_device_attr_time.attr,
+ &class_device_attr_since_epoch.attr,
+ NULL,
+};
+
+static struct attribute_group rtc_attr_group = {
+ .attrs = rtc_attrs,
+};
+
+static int __devinit rtc_sysfs_add_device(struct class_device *class_dev,
+ struct class_interface *class_intf)
+{
+ int err;
+
+ dev_info(class_dev->dev, "rtc intf: sysfs\n");
+
+ err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group);
+ if (err)
+ dev_err(class_dev->dev,
+ "failed to create sysfs attributes\n");
+
+ return err;
+}
+
+static void rtc_sysfs_remove_device(struct class_device *class_dev,
+ struct class_interface *class_intf)
+{
+ sysfs_remove_group(&class_dev->kobj, &rtc_attr_group);
+}
+
+/* interface registration */
+
+static struct class_interface rtc_sysfs_interface = {
+ .add = &rtc_sysfs_add_device,
+ .remove = &rtc_sysfs_remove_device,
+};
+
+static int __init rtc_sysfs_init(void)
+{
+ return rtc_interface_register(&rtc_sysfs_interface);
+}
+
+static void __exit rtc_sysfs_exit(void)
+{
+ class_interface_unregister(&rtc_sysfs_interface);
+}
+
+module_init(rtc_sysfs_init);
+module_exit(rtc_sysfs_exit);
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("RTC class sysfs interface");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
new file mode 100644
index 00000000000..43d10748782
--- /dev/null
+++ b/drivers/rtc/rtc-test.c
@@ -0,0 +1,204 @@
+/*
+ * An RTC test device/driver
+ * Copyright (C) 2005 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * 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/err.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+
+static struct platform_device *test0 = NULL, *test1 = NULL;
+
+static int test_rtc_read_alarm(struct device *dev,
+ struct rtc_wkalrm *alrm)
+{
+ return 0;
+}
+
+static int test_rtc_set_alarm(struct device *dev,
+ struct rtc_wkalrm *alrm)
+{
+ return 0;
+}
+
+static int test_rtc_read_time(struct device *dev,
+ struct rtc_time *tm)
+{
+ rtc_time_to_tm(get_seconds(), tm);
+ return 0;
+}
+
+static int test_rtc_set_time(struct device *dev,
+ struct rtc_time *tm)
+{
+ return 0;
+}
+
+static int test_rtc_set_mmss(struct device *dev, unsigned long secs)
+{
+ return 0;
+}
+
+static int test_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ struct platform_device *plat_dev = to_platform_device(dev);
+
+ seq_printf(seq, "24hr\t\t: yes\n");
+ seq_printf(seq, "test\t\t: yes\n");
+ seq_printf(seq, "id\t\t: %d\n", plat_dev->id);
+
+ return 0;
+}
+
+static int test_rtc_ioctl(struct device *dev, unsigned int cmd,
+ unsigned long arg)
+{
+ /* We do support interrupts, they're generated
+ * using the sysfs interface.
+ */
+ switch (cmd) {
+ case RTC_PIE_ON:
+ case RTC_PIE_OFF:
+ case RTC_UIE_ON:
+ case RTC_UIE_OFF:
+ case RTC_AIE_ON:
+ case RTC_AIE_OFF:
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static struct rtc_class_ops test_rtc_ops = {
+ .proc = test_rtc_proc,
+ .read_time = test_rtc_read_time,
+ .set_time = test_rtc_set_time,
+ .read_alarm = test_rtc_read_alarm,
+ .set_alarm = test_rtc_set_alarm,
+ .set_mmss = test_rtc_set_mmss,
+ .ioctl = test_rtc_ioctl,
+};
+
+static ssize_t test_irq_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", 42);
+}
+static ssize_t test_irq_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int retval;
+ struct platform_device *plat_dev = to_platform_device(dev);
+ struct rtc_device *rtc = platform_get_drvdata(plat_dev);
+
+ retval = count;
+ if (strncmp(buf, "tick", 4) == 0)
+ rtc_update_irq(&rtc->class_dev, 1, RTC_PF | RTC_IRQF);
+ else if (strncmp(buf, "alarm", 5) == 0)
+ rtc_update_irq(&rtc->class_dev, 1, RTC_AF | RTC_IRQF);
+ else if (strncmp(buf, "update", 6) == 0)
+ rtc_update_irq(&rtc->class_dev, 1, RTC_UF | RTC_IRQF);
+ else
+ retval = -EINVAL;
+
+ return retval;
+}
+static DEVICE_ATTR(irq, S_IRUGO | S_IWUSR, test_irq_show, test_irq_store);
+
+static int test_probe(struct platform_device *plat_dev)
+{
+ int err;
+ struct rtc_device *rtc = rtc_device_register("test", &plat_dev->dev,
+ &test_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ err = PTR_ERR(rtc);
+ dev_err(&plat_dev->dev,
+ "unable to register the class device\n");
+ return err;
+ }
+ device_create_file(&plat_dev->dev, &dev_attr_irq);
+
+ platform_set_drvdata(plat_dev, rtc);
+
+ return 0;
+}
+
+static int __devexit test_remove(struct platform_device *plat_dev)
+{
+ struct rtc_device *rtc = platform_get_drvdata(plat_dev);
+
+ rtc_device_unregister(rtc);
+ device_remove_file(&plat_dev->dev, &dev_attr_irq);
+
+ return 0;
+}
+
+static struct platform_driver test_drv = {
+ .probe = test_probe,
+ .remove = __devexit_p(test_remove),
+ .driver = {
+ .name = "rtc-test",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init test_init(void)
+{
+ int err;
+
+ if ((err = platform_driver_register(&test_drv)))
+ return err;
+
+ if ((test0 = platform_device_alloc("rtc-test", 0)) == NULL) {
+ err = -ENOMEM;
+ goto exit_driver_unregister;
+ }
+
+ if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) {
+ err = -ENOMEM;
+ goto exit_free_test0;
+ }
+
+ if ((err = platform_device_add(test0)))
+ goto exit_free_test1;
+
+ if ((err = platform_device_add(test1)))
+ goto exit_device_unregister;
+
+ return 0;
+
+exit_device_unregister:
+ platform_device_unregister(test0);
+
+exit_free_test1:
+ platform_device_put(test1);
+
+exit_free_test0:
+ platform_device_put(test0);
+
+exit_driver_unregister:
+ platform_driver_unregister(&test_drv);
+ return err;
+}
+
+static void __exit test_exit(void)
+{
+ platform_device_unregister(test0);
+ platform_device_unregister(test1);
+ platform_driver_unregister(&test_drv);
+}
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("RTC test driver/device");
+MODULE_LICENSE("GPL");
+
+module_init(test_init);
+module_exit(test_exit);
diff --git a/drivers/i2c/chips/x1205.c b/drivers/rtc/rtc-x1205.c
index 245fffa92db..621d17afc0d 100644
--- a/drivers/i2c/chips/x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -1,32 +1,25 @@
/*
- * x1205.c - An i2c driver for the Xicor X1205 RTC
- * Copyright 2004 Karen Spearel
- * Copyright 2005 Alessandro Zummo
+ * An i2c driver for the Xicor/Intersil X1205 RTC
+ * Copyright 2004 Karen Spearel
+ * Copyright 2005 Alessandro Zummo
*
- * please send all reports to:
- * kas11 at tampabay dot rr dot com
- * a dot zummo at towertech dot it
+ * please send all reports to:
+ * Karen Spearel <kas111 at gmail dot com>
+ * Alessandro Zummo <a.zummo@towertech.it>
*
- * based on the other drivers in this same directory.
+ * based on a lot of other RTC drivers.
*
- * 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 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/slab.h>
#include <linux/i2c.h>
-#include <linux/string.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
-#include <linux/list.h>
+#include <linux/delay.h>
-#include <linux/x1205.h>
-
-#define DRV_VERSION "0.9.9"
+#define DRV_VERSION "1.0.6"
/* Addresses to scan: none. This chip is located at
* 0x6f and uses a two bytes register addressing.
@@ -40,8 +33,6 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD;
-I2C_CLIENT_MODULE_PARM(hctosys,
- "Set the system time from the hardware clock upon initialization");
/* offsets into CCR area */
@@ -101,107 +92,35 @@ I2C_CLIENT_MODULE_PARM(hctosys,
static int x1205_attach(struct i2c_adapter *adapter);
static int x1205_detach(struct i2c_client *client);
static int x1205_probe(struct i2c_adapter *adapter, int address, int kind);
-static int x1205_command(struct i2c_client *client, unsigned int cmd,
- void *arg);
static struct i2c_driver x1205_driver = {
- .driver = {
+ .driver = {
.name = "x1205",
},
+ .id = I2C_DRIVERID_X1205,
.attach_adapter = &x1205_attach,
.detach_client = &x1205_detach,
};
-struct x1205_data {
- struct i2c_client client;
- struct list_head list;
- unsigned int epoch;
-};
-
-static const unsigned char days_in_mo[] =
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
-static LIST_HEAD(x1205_clients);
-
-/* Workaround until the I2C subsytem will allow to send
- * commands to a specific client. This function will send the command
- * to the first client.
- */
-int x1205_do_command(unsigned int cmd, void *arg)
-{
- struct list_head *walk;
- struct list_head *tmp;
- struct x1205_data *data;
-
- list_for_each_safe(walk, tmp, &x1205_clients) {
- data = list_entry(walk, struct x1205_data, list);
- return x1205_command(&data->client, cmd, arg);
- }
-
- return -ENODEV;
-}
-
-#define is_leap(year) \
- ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-
-/* make sure the rtc_time values are in bounds */
-static int x1205_validate_tm(struct rtc_time *tm)
-{
- int year = tm->tm_year + 1900;
-
- if ((tm->tm_year < 70) || (tm->tm_year > 255))
- return -EINVAL;
-
- if ((tm->tm_mon > 11) || (tm->tm_mday == 0))
- return -EINVAL;
-
- if (tm->tm_mday > days_in_mo[tm->tm_mon]
- + ((tm->tm_mon == 1) && is_leap(year)))
- return -EINVAL;
-
- if ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60))
- return -EINVAL;
-
- return 0;
-}
-
/*
* In the routines that deal directly with the x1205 hardware, we use
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
* Epoch is initialized as 2000. Time is set to UTC.
*/
static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
- u8 reg_base)
+ unsigned char reg_base)
{
unsigned char dt_addr[2] = { 0, reg_base };
- static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
- unsigned char buf[8], sr;
+ unsigned char buf[8];
struct i2c_msg msgs[] = {
- { client->addr, 0, 2, sr_addr }, /* setup read ptr */
- { client->addr, I2C_M_RD, 1, &sr }, /* read status */
{ client->addr, 0, 2, dt_addr }, /* setup read ptr */
{ client->addr, I2C_M_RD, 8, buf }, /* read date */
};
- struct x1205_data *data = i2c_get_clientdata(client);
-
- /* read status register */
- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
- return -EIO;
- }
-
- /* check for battery failure */
- if (sr & X1205_SR_RTCF) {
- dev_warn(&client->dev,
- "Clock had a power failure, you must set the date.\n");
- return -EINVAL;
- }
-
/* read date registers */
- if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) {
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
return -EIO;
}
@@ -217,9 +136,9 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
tm->tm_min = BCD2BIN(buf[CCR_MIN]);
tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
- tm->tm_mon = BCD2BIN(buf[CCR_MONTH]);
- data->epoch = BCD2BIN(buf[CCR_Y2K]) * 100;
- tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + data->epoch - 1900;
+ tm->tm_mon = BCD2BIN(buf[CCR_MONTH]) - 1; /* mon is 0-11 */
+ tm->tm_year = BCD2BIN(buf[CCR_YEAR])
+ + (BCD2BIN(buf[CCR_Y2K]) * 100) - 1900;
tm->tm_wday = buf[CCR_WDAY];
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
@@ -231,11 +150,28 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
return 0;
}
+static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
+{
+ static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
+
+ struct i2c_msg msgs[] = {
+ { client->addr, 0, 2, sr_addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 1, sr }, /* read status */
+ };
+
+ /* read status register */
+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
int datetoo, u8 reg_base)
{
- int i, err, xfer;
-
+ int i, xfer;
unsigned char buf[8];
static const unsigned char wel[3] = { 0, X1205_REG_SR,
@@ -246,17 +182,10 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
- struct x1205_data *data = i2c_get_clientdata(client);
-
- /* check if all values in the tm struct are correct */
- if ((err = x1205_validate_tm(tm)) < 0)
- return err;
-
- dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
- "mday=%d, mon=%d, year=%d, wday=%d\n",
+ dev_dbg(&client->dev,
+ "%s: secs=%d, mins=%d, hours=%d\n",
__FUNCTION__,
- tm->tm_sec, tm->tm_min, tm->tm_hour,
- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+ tm->tm_sec, tm->tm_min, tm->tm_hour);
buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
buf[CCR_MIN] = BIN2BCD(tm->tm_min);
@@ -266,26 +195,29 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
/* should we also set the date? */
if (datetoo) {
+ dev_dbg(&client->dev,
+ "%s: mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
- /* month, 0 - 11 */
- buf[CCR_MONTH] = BIN2BCD(tm->tm_mon);
+ /* month, 1 - 12 */
+ buf[CCR_MONTH] = BIN2BCD(tm->tm_mon + 1);
- /* year, since 1900 */
- buf[CCR_YEAR] = BIN2BCD(tm->tm_year + 1900 - data->epoch);
+ /* year, since the rtc epoch*/
+ buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100);
buf[CCR_WDAY] = tm->tm_wday & 0x07;
- buf[CCR_Y2K] = BIN2BCD(data->epoch / 100);
+ buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100);
}
/* this sequence is required to unlock the chip */
- xfer = i2c_master_send(client, wel, 3);
- if (xfer != 3) {
+ if ((xfer = i2c_master_send(client, wel, 3)) != 3) {
dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer);
return -EIO;
}
- xfer = i2c_master_send(client, rwel, 3);
- if (xfer != 3) {
+ if ((xfer = i2c_master_send(client, rwel, 3)) != 3) {
dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer);
return -EIO;
}
@@ -305,8 +237,7 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
};
/* disable further writes */
- xfer = i2c_master_send(client, diswe, 3);
- if (xfer != 3) {
+ if ((xfer = i2c_master_send(client, diswe, 3)) != 3) {
dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer);
return -EIO;
}
@@ -314,6 +245,20 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
return 0;
}
+static int x1205_fix_osc(struct i2c_client *client)
+{
+ int err;
+ struct rtc_time tm;
+
+ tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
+
+ if ((err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE)) < 0)
+ dev_err(&client->dev,
+ "unable to restart the oscillator\n");
+
+ return err;
+}
+
static int x1205_get_dtrim(struct i2c_client *client, int *trim)
{
unsigned char dtr;
@@ -380,60 +325,9 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim)
return 0;
}
-static int x1205_hctosys(struct i2c_client *client)
-{
- int err;
-
- struct rtc_time tm;
- struct timespec tv;
-
- err = x1205_command(client, X1205_CMD_GETDATETIME, &tm);
-
- if (err) {
- dev_err(&client->dev,
- "Unable to set the system clock\n");
- return err;
- }
-
- /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
- * whether it stores the most close value or the value with partial
- * seconds truncated. However, it is important that we use it to store
- * the truncated value. This is because otherwise it is necessary,
- * in an rtc sync function, to read both xtime.tv_sec and
- * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read
- * of >32bits is not possible. So storing the most close value would
- * slow down the sync API. So here we have the truncated value and
- * the best guess is to add 0.5s.
- */
-
- tv.tv_nsec = NSEC_PER_SEC >> 1;
-
- /* WARNING: this is not the C library 'mktime' call, it is a built in
- * inline function from include/linux/time.h. It expects (requires)
- * the month to be in the range 1-12
- */
-
- tv.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1,
- tm.tm_mday, tm.tm_hour,
- tm.tm_min, tm.tm_sec);
-
- do_settimeofday(&tv);
-
- dev_info(&client->dev,
- "setting the system clock to %d-%d-%d %d:%d:%d\n",
- tm.tm_year + 1900, tm.tm_mon + 1,
- tm.tm_mday, tm.tm_hour, tm.tm_min,
- tm.tm_sec);
-
- return 0;
-}
-
struct x1205_limit
{
- unsigned char reg;
- unsigned char mask;
- unsigned char min;
- unsigned char max;
+ unsigned char reg, mask, min, max;
};
static int x1205_validate_client(struct i2c_client *client)
@@ -477,11 +371,10 @@ static int x1205_validate_client(struct i2c_client *client)
{ client->addr, I2C_M_RD, 1, &buf },
};
- xfer = i2c_transfer(client->adapter, msgs, 2);
- if (xfer != 2) {
+ if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
dev_err(&client->adapter->dev,
"%s: could not read register %x\n",
- __FUNCTION__, addr[1]);
+ __FUNCTION__, probe_zero_pattern[i]);
return -EIO;
}
@@ -489,7 +382,7 @@ static int x1205_validate_client(struct i2c_client *client)
if ((buf & probe_zero_pattern[i+1]) != 0) {
dev_err(&client->adapter->dev,
"%s: register=%02x, zero pattern=%d, value=%x\n",
- __FUNCTION__, addr[1], i, buf);
+ __FUNCTION__, probe_zero_pattern[i], i, buf);
return -ENODEV;
}
@@ -506,12 +399,10 @@ static int x1205_validate_client(struct i2c_client *client)
{ client->addr, I2C_M_RD, 1, &reg },
};
- xfer = i2c_transfer(client->adapter, msgs, 2);
-
- if (xfer != 2) {
+ if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
dev_err(&client->adapter->dev,
"%s: could not read register %x\n",
- __FUNCTION__, addr[1]);
+ __FUNCTION__, probe_limits_pattern[i].reg);
return -EIO;
}
@@ -522,7 +413,8 @@ static int x1205_validate_client(struct i2c_client *client)
value < probe_limits_pattern[i].min) {
dev_dbg(&client->adapter->dev,
"%s: register=%x, lim pattern=%d, value=%d\n",
- __FUNCTION__, addr[1], i, value);
+ __FUNCTION__, probe_limits_pattern[i].reg,
+ i, value);
return -ENODEV;
}
@@ -531,37 +423,89 @@ static int x1205_validate_client(struct i2c_client *client)
return 0;
}
-static int x1205_attach(struct i2c_adapter *adapter)
+static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+ return x1205_get_datetime(to_i2c_client(dev),
+ &alrm->time, X1205_ALM0_BASE);
+}
- return i2c_probe(adapter, &addr_data, x1205_probe);
+static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ return x1205_set_datetime(to_i2c_client(dev),
+ &alrm->time, 1, X1205_ALM0_BASE);
}
-int x1205_direct_attach(int adapter_id,
- struct i2c_client_address_data *address_data)
+static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- int err;
- struct i2c_adapter *adapter = i2c_get_adapter(adapter_id);
+ return x1205_get_datetime(to_i2c_client(dev),
+ tm, X1205_CCR_BASE);
+}
- if (adapter) {
- err = i2c_probe(adapter,
- address_data, x1205_probe);
+static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return x1205_set_datetime(to_i2c_client(dev),
+ tm, 1, X1205_CCR_BASE);
+}
- i2c_put_adapter(adapter);
+static int x1205_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ int err, dtrim, atrim;
- return err;
- }
+ seq_printf(seq, "24hr\t\t: yes\n");
- return -ENODEV;
+ if ((err = x1205_get_dtrim(to_i2c_client(dev), &dtrim)) == 0)
+ seq_printf(seq, "digital_trim\t: %d ppm\n", dtrim);
+
+ if ((err = x1205_get_atrim(to_i2c_client(dev), &atrim)) == 0)
+ seq_printf(seq, "analog_trim\t: %d.%02d pF\n",
+ atrim / 1000, atrim % 1000);
+ return 0;
}
-static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
+static struct rtc_class_ops x1205_rtc_ops = {
+ .proc = x1205_rtc_proc,
+ .read_time = x1205_rtc_read_time,
+ .set_time = x1205_rtc_set_time,
+ .read_alarm = x1205_rtc_read_alarm,
+ .set_alarm = x1205_rtc_set_alarm,
+};
+
+static ssize_t x1205_sysfs_show_atrim(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct i2c_client *client;
- struct x1205_data *data;
+ int atrim;
+
+ if (x1205_get_atrim(to_i2c_client(dev), &atrim) == 0)
+ return sprintf(buf, "%d.%02d pF\n",
+ atrim / 1000, atrim % 1000);
+ return 0;
+}
+static DEVICE_ATTR(atrim, S_IRUGO, x1205_sysfs_show_atrim, NULL);
+
+static ssize_t x1205_sysfs_show_dtrim(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int dtrim;
+
+ if (x1205_get_dtrim(to_i2c_client(dev), &dtrim) == 0)
+ return sprintf(buf, "%d ppm\n", dtrim);
+
+ return 0;
+}
+static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL);
+static int x1205_attach(struct i2c_adapter *adapter)
+{
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+ return i2c_probe(adapter, &addr_data, x1205_probe);
+}
+
+static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
+{
int err = 0;
+ unsigned char sr;
+ struct i2c_client *client;
+ struct rtc_device *rtc;
dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
@@ -570,22 +514,17 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
goto exit;
}
- if (!(data = kzalloc(sizeof(struct x1205_data), GFP_KERNEL))) {
+ if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- /* Initialize our structures */
- data->epoch = 2000;
-
- client = &data->client;
+ /* I2C client */
client->addr = address;
client->driver = &x1205_driver;
client->adapter = adapter;
- strlcpy(client->name, "x1205", I2C_NAME_SIZE);
-
- i2c_set_clientdata(client, data);
+ strlcpy(client->name, x1205_driver.driver.name, I2C_NAME_SIZE);
/* Verify the chip is really an X1205 */
if (kind < 0) {
@@ -599,18 +538,43 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
if ((err = i2c_attach_client(client)))
goto exit_kfree;
- list_add(&data->list, &x1205_clients);
-
dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
- /* If requested, set the system time */
- if (hctosys)
- x1205_hctosys(client);
+ rtc = rtc_device_register(x1205_driver.driver.name, &client->dev,
+ &x1205_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc)) {
+ err = PTR_ERR(rtc);
+ dev_err(&client->dev,
+ "unable to register the class device\n");
+ goto exit_detach;
+ }
+
+ i2c_set_clientdata(client, rtc);
+
+ /* Check for power failures and eventualy enable the osc */
+ if ((err = x1205_get_status(client, &sr)) == 0) {
+ if (sr & X1205_SR_RTCF) {
+ dev_err(&client->dev,
+ "power failure detected, "
+ "please set the clock\n");
+ udelay(50);
+ x1205_fix_osc(client);
+ }
+ }
+ else
+ dev_err(&client->dev, "couldn't read status\n");
+
+ device_create_file(&client->dev, &dev_attr_atrim);
+ device_create_file(&client->dev, &dev_attr_dtrim);
return 0;
+exit_detach:
+ i2c_detach_client(client);
+
exit_kfree:
- kfree(data);
+ kfree(client);
exit:
return err;
@@ -619,61 +583,21 @@ exit:
static int x1205_detach(struct i2c_client *client)
{
int err;
- struct x1205_data *data = i2c_get_clientdata(client);
+ struct rtc_device *rtc = i2c_get_clientdata(client);
dev_dbg(&client->dev, "%s\n", __FUNCTION__);
+ if (rtc)
+ rtc_device_unregister(rtc);
+
if ((err = i2c_detach_client(client)))
return err;
- list_del(&data->list);
-
- kfree(data);
+ kfree(client);
return 0;
}
-static int x1205_command(struct i2c_client *client, unsigned int cmd,
- void *param)
-{
- if (param == NULL)
- return -EINVAL;
-
- if (!capable(CAP_SYS_TIME))
- return -EACCES;
-
- dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
-
- switch (cmd) {
- case X1205_CMD_GETDATETIME:
- return x1205_get_datetime(client, param, X1205_CCR_BASE);
-
- case X1205_CMD_SETTIME:
- return x1205_set_datetime(client, param, 0,
- X1205_CCR_BASE);
-
- case X1205_CMD_SETDATETIME:
- return x1205_set_datetime(client, param, 1,
- X1205_CCR_BASE);
-
- case X1205_CMD_GETALARM:
- return x1205_get_datetime(client, param, X1205_ALM0_BASE);
-
- case X1205_CMD_SETALARM:
- return x1205_set_datetime(client, param, 1,
- X1205_ALM0_BASE);
-
- case X1205_CMD_GETDTRIM:
- return x1205_get_dtrim(client, param);
-
- case X1205_CMD_GETATRIM:
- return x1205_get_atrim(client, param);
-
- default:
- return -EINVAL;
- }
-}
-
static int __init x1205_init(void)
{
return i2c_add_driver(&x1205_driver);
@@ -685,14 +609,11 @@ static void __exit x1205_exit(void)
}
MODULE_AUTHOR(
- "Karen Spearel <kas11@tampabay.rr.com>, "
+ "Karen Spearel <kas111 at gmail dot com>, "
"Alessandro Zummo <a.zummo@towertech.it>");
-MODULE_DESCRIPTION("Xicor X1205 RTC driver");
+MODULE_DESCRIPTION("Xicor/Intersil X1205 RTC driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-EXPORT_SYMBOL_GPL(x1205_do_command);
-EXPORT_SYMBOL_GPL(x1205_direct_attach);
-
module_init(x1205_init);
module_exit(x1205_exit);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index dfe542b206c..0a9f12c4e91 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -43,7 +43,6 @@ MODULE_AUTHOR("Holger Smolinski <Holger.Smolinski@de.ibm.com>");
MODULE_DESCRIPTION("Linux on S/390 DASD device driver,"
" Copyright 2000 IBM Corporation");
MODULE_SUPPORTED_DEVICE("dasd");
-MODULE_PARM(dasd, "1-" __MODULE_STRING(256) "s");
MODULE_LICENSE("GPL");
/*
@@ -542,9 +541,8 @@ dasd_kmalloc_request(char *magic, int cplength, int datasize,
struct dasd_ccw_req *cqr;
/* Sanity checks */
- if ( magic == NULL || datasize > PAGE_SIZE ||
- (cplength*sizeof(struct ccw1)) > PAGE_SIZE)
- BUG();
+ BUG_ON( magic == NULL || datasize > PAGE_SIZE ||
+ (cplength*sizeof(struct ccw1)) > PAGE_SIZE);
cqr = kzalloc(sizeof(struct dasd_ccw_req), GFP_ATOMIC);
if (cqr == NULL)
@@ -584,9 +582,8 @@ dasd_smalloc_request(char *magic, int cplength, int datasize,
int size;
/* Sanity checks */
- if ( magic == NULL || datasize > PAGE_SIZE ||
- (cplength*sizeof(struct ccw1)) > PAGE_SIZE)
- BUG();
+ BUG_ON( magic == NULL || datasize > PAGE_SIZE ||
+ (cplength*sizeof(struct ccw1)) > PAGE_SIZE);
size = (sizeof(struct dasd_ccw_req) + 7L) & -8L;
if (cplength > 0)
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index f576f243cd9..c1c6f138115 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -16,6 +16,7 @@
#include <linux/config.h>
#include <linux/ctype.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <asm/debug.h>
#include <asm/uaccess.h>
@@ -69,6 +70,8 @@ int dasd_autodetect = 0; /* is true, when autodetection is active */
* strings when running as a module.
*/
static char *dasd[256];
+module_param_array(dasd, charp, NULL, 0);
+
/*
* Single spinlock to protect devmap structures and lists.
*/
@@ -434,8 +437,7 @@ dasd_forget_ranges(void)
spin_lock(&dasd_devmap_lock);
for (i = 0; i < 256; i++) {
list_for_each_entry_safe(devmap, n, &dasd_hashlists[i], list) {
- if (devmap->device != NULL)
- BUG();
+ BUG_ON(devmap->device != NULL);
list_del(&devmap->list);
kfree(devmap);
}
@@ -544,8 +546,7 @@ dasd_delete_device(struct dasd_device *device)
/* First remove device pointer from devmap. */
devmap = dasd_find_busid(device->cdev->dev.bus_id);
- if (IS_ERR(devmap))
- BUG();
+ BUG_ON(IS_ERR(devmap));
spin_lock(&dasd_devmap_lock);
if (devmap->device != device) {
spin_unlock(&dasd_devmap_lock);
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index bd06607a5dc..eecb2afad5c 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -28,6 +28,7 @@
#include <linux/major.h>
#include <linux/kdev_t.h>
#include <linux/device.h>
+#include <linux/mutex.h>
struct class *class3270;
@@ -59,7 +60,7 @@ struct raw3270 {
#define RAW3270_FLAGS_CONSOLE 8 /* Device is the console. */
/* Semaphore to protect global data of raw3270 (devices, views, etc). */
-static DECLARE_MUTEX(raw3270_sem);
+static DEFINE_MUTEX(raw3270_mutex);
/* List of 3270 devices. */
static struct list_head raw3270_devices = LIST_HEAD_INIT(raw3270_devices);
@@ -815,7 +816,7 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
* number for it. Note: there is no device with minor 0,
* see special case for fs3270.c:fs3270_open().
*/
- down(&raw3270_sem);
+ mutex_lock(&raw3270_mutex);
/* Keep the list sorted. */
minor = RAW3270_FIRSTMINOR;
rp->minor = -1;
@@ -832,7 +833,7 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
rp->minor = minor;
list_add_tail(&rp->list, &raw3270_devices);
}
- up(&raw3270_sem);
+ mutex_unlock(&raw3270_mutex);
/* No free minor number? Then give up. */
if (rp->minor == -1)
return -EUSERS;
@@ -1003,7 +1004,7 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor)
if (minor <= 0)
return -ENODEV;
- down(&raw3270_sem);
+ mutex_lock(&raw3270_mutex);
rc = -ENODEV;
list_for_each_entry(rp, &raw3270_devices, list) {
if (rp->minor != minor)
@@ -1024,7 +1025,7 @@ raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor)
spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
break;
}
- up(&raw3270_sem);
+ mutex_unlock(&raw3270_mutex);
return rc;
}
@@ -1038,7 +1039,7 @@ raw3270_find_view(struct raw3270_fn *fn, int minor)
struct raw3270_view *view, *tmp;
unsigned long flags;
- down(&raw3270_sem);
+ mutex_lock(&raw3270_mutex);
view = ERR_PTR(-ENODEV);
list_for_each_entry(rp, &raw3270_devices, list) {
if (rp->minor != minor)
@@ -1057,7 +1058,7 @@ raw3270_find_view(struct raw3270_fn *fn, int minor)
spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
break;
}
- up(&raw3270_sem);
+ mutex_unlock(&raw3270_mutex);
return view;
}
@@ -1104,7 +1105,7 @@ raw3270_delete_device(struct raw3270 *rp)
struct ccw_device *cdev;
/* Remove from device chain. */
- down(&raw3270_sem);
+ mutex_lock(&raw3270_mutex);
if (rp->clttydev)
class_device_destroy(class3270,
MKDEV(IBM_TTY3270_MAJOR, rp->minor));
@@ -1112,7 +1113,7 @@ raw3270_delete_device(struct raw3270 *rp)
class_device_destroy(class3270,
MKDEV(IBM_FS3270_MAJOR, rp->minor));
list_del_init(&rp->list);
- up(&raw3270_sem);
+ mutex_unlock(&raw3270_mutex);
/* Disconnect from ccw_device. */
cdev = rp->cdev;
@@ -1208,13 +1209,13 @@ int raw3270_register_notifier(void (*notifier)(int, int))
if (!np)
return -ENOMEM;
np->notifier = notifier;
- down(&raw3270_sem);
+ mutex_lock(&raw3270_mutex);
list_add_tail(&np->list, &raw3270_notifier);
list_for_each_entry(rp, &raw3270_devices, list) {
get_device(&rp->cdev->dev);
notifier(rp->minor, 1);
}
- up(&raw3270_sem);
+ mutex_unlock(&raw3270_mutex);
return 0;
}
@@ -1222,14 +1223,14 @@ void raw3270_unregister_notifier(void (*notifier)(int, int))
{
struct raw3270_notifier *np;
- down(&raw3270_sem);
+ mutex_lock(&raw3270_mutex);
list_for_each_entry(np, &raw3270_notifier, list)
if (np->notifier == notifier) {
list_del(&np->list);
kfree(np);
break;
}
- up(&raw3270_sem);
+ mutex_unlock(&raw3270_mutex);
}
/*
@@ -1256,10 +1257,10 @@ raw3270_set_online (struct ccw_device *cdev)
goto failure;
raw3270_create_attributes(rp);
set_bit(RAW3270_FLAGS_READY, &rp->flags);
- down(&raw3270_sem);
+ mutex_lock(&raw3270_mutex);
list_for_each_entry(np, &raw3270_notifier, list)
np->notifier(rp->minor, 1);
- up(&raw3270_sem);
+ mutex_unlock(&raw3270_mutex);
return 0;
failure:
@@ -1307,10 +1308,10 @@ raw3270_remove (struct ccw_device *cdev)
}
spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
- down(&raw3270_sem);
+ mutex_lock(&raw3270_mutex);
list_for_each_entry(np, &raw3270_notifier, list)
np->notifier(rp->minor, 0);
- up(&raw3270_sem);
+ mutex_unlock(&raw3270_mutex);
/* Reset 3270 device. */
raw3270_reset_device(rp);
@@ -1370,13 +1371,13 @@ raw3270_init(void)
rc = ccw_driver_register(&raw3270_ccw_driver);
if (rc == 0) {
/* Create attributes for early (= console) device. */
- down(&raw3270_sem);
+ mutex_lock(&raw3270_mutex);
class3270 = class_create(THIS_MODULE, "3270");
list_for_each_entry(rp, &raw3270_devices, list) {
get_device(&rp->cdev->dev);
raw3270_create_attributes(rp);
}
- up(&raw3270_sem);
+ mutex_unlock(&raw3270_mutex);
}
return rc;
}
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 95b92f317b6..395cfc6a344 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -829,18 +829,6 @@ zfcp_unit_dequeue(struct zfcp_unit *unit)
device_unregister(&unit->sysfs_device);
}
-static void *
-zfcp_mempool_alloc(gfp_t gfp_mask, void *size)
-{
- return kmalloc((size_t) size, gfp_mask);
-}
-
-static void
-zfcp_mempool_free(void *element, void *size)
-{
- kfree(element);
-}
-
/*
* Allocates a combined QTCB/fsf_req buffer for erp actions and fcp/SCSI
* commands.
@@ -853,51 +841,39 @@ static int
zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
{
adapter->pool.fsf_req_erp =
- mempool_create(ZFCP_POOL_FSF_REQ_ERP_NR,
- zfcp_mempool_alloc, zfcp_mempool_free, (void *)
- sizeof(struct zfcp_fsf_req_pool_element));
-
- if (NULL == adapter->pool.fsf_req_erp)
+ mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_ERP_NR,
+ sizeof(struct zfcp_fsf_req_pool_element));
+ if (!adapter->pool.fsf_req_erp)
return -ENOMEM;
adapter->pool.fsf_req_scsi =
- mempool_create(ZFCP_POOL_FSF_REQ_SCSI_NR,
- zfcp_mempool_alloc, zfcp_mempool_free, (void *)
- sizeof(struct zfcp_fsf_req_pool_element));
-
- if (NULL == adapter->pool.fsf_req_scsi)
+ mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_SCSI_NR,
+ sizeof(struct zfcp_fsf_req_pool_element));
+ if (!adapter->pool.fsf_req_scsi)
return -ENOMEM;
adapter->pool.fsf_req_abort =
- mempool_create(ZFCP_POOL_FSF_REQ_ABORT_NR,
- zfcp_mempool_alloc, zfcp_mempool_free, (void *)
- sizeof(struct zfcp_fsf_req_pool_element));
-
- if (NULL == adapter->pool.fsf_req_abort)
+ mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_ABORT_NR,
+ sizeof(struct zfcp_fsf_req_pool_element));
+ if (!adapter->pool.fsf_req_abort)
return -ENOMEM;
adapter->pool.fsf_req_status_read =
- mempool_create(ZFCP_POOL_STATUS_READ_NR,
- zfcp_mempool_alloc, zfcp_mempool_free,
- (void *) sizeof(struct zfcp_fsf_req));
-
- if (NULL == adapter->pool.fsf_req_status_read)
+ mempool_create_kmalloc_pool(ZFCP_POOL_STATUS_READ_NR,
+ sizeof(struct zfcp_fsf_req));
+ if (!adapter->pool.fsf_req_status_read)
return -ENOMEM;
adapter->pool.data_status_read =
- mempool_create(ZFCP_POOL_STATUS_READ_NR,
- zfcp_mempool_alloc, zfcp_mempool_free,
- (void *) sizeof(struct fsf_status_read_buffer));
-
- if (NULL == adapter->pool.data_status_read)
+ mempool_create_kmalloc_pool(ZFCP_POOL_STATUS_READ_NR,
+ sizeof(struct fsf_status_read_buffer));
+ if (!adapter->pool.data_status_read)
return -ENOMEM;
adapter->pool.data_gid_pn =
- mempool_create(ZFCP_POOL_DATA_GID_PN_NR,
- zfcp_mempool_alloc, zfcp_mempool_free, (void *)
- sizeof(struct zfcp_gid_pn_data));
-
- if (NULL == adapter->pool.data_gid_pn)
+ mempool_create_kmalloc_pool(ZFCP_POOL_DATA_GID_PN_NR,
+ sizeof(struct zfcp_gid_pn_data));
+ if (!adapter->pool.data_gid_pn)
return -ENOMEM;
return 0;
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 0ab26d01877..0d2b447c50e 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1026,7 +1026,7 @@ static void twa_free_request_id(TW_Device_Extension *tw_dev, int request_id)
tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH;
} /* End twa_free_request_id() */
-/* This function will get parameter table entires from the firmware */
+/* This function will get parameter table entries from the firmware */
static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int table_id, int parameter_id, int parameter_size_bytes)
{
TW_Command_Full *full_command_packet;
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 1c459343292..bde3d5834ad 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -41,6 +41,8 @@
#include <linux/stat.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+#include <linux/dma-mapping.h>
#include <scsi/scsicam.h>
#include <asm/dma.h>
@@ -676,7 +678,7 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd
if (pci_enable_device(PCI_Device))
continue;
- if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff))
+ if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK ))
continue;
Bus = PCI_Device->bus->number;
@@ -831,7 +833,7 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd
if (pci_enable_device(PCI_Device))
continue;
- if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff))
+ if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK))
continue;
Bus = PCI_Device->bus->number;
@@ -885,7 +887,7 @@ static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAda
if (pci_enable_device(PCI_Device))
continue;
- if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff))
+ if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK))
continue;
Bus = PCI_Device->bus->number;
@@ -2896,7 +2898,7 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou
*/
if (HostAdapter->ActiveCommands[TargetID] == 0)
HostAdapter->LastSequencePoint[TargetID] = jiffies;
- else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4 * HZ) {
+ else if (time_after(jiffies, HostAdapter->LastSequencePoint[TargetID] + 4 * HZ)) {
HostAdapter->LastSequencePoint[TargetID] = jiffies;
QueueTag = BusLogic_OrderedQueueTag;
}
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 9f45ae1745d..3dce21c7873 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -89,6 +89,7 @@
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/slab.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -1052,7 +1053,7 @@ static int __devinit inia100_probe_one(struct pci_dev *pdev,
if (pci_enable_device(pdev))
goto out;
- if (pci_set_dma_mask(pdev, 0xffffffffULL)) {
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "Unable to set 32bit DMA "
"on inia100 adapter, ignoring.\n");
goto out_disable_device;
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index a16f8ded8f1..8df4a0ea376 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -32,6 +32,7 @@
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index c2596335549..72033077864 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -45,6 +45,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
#include <linux/syscalls.h>
#include <linux/delay.h>
#include <linux/smp_lock.h>
@@ -806,8 +807,8 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
* to driver communication memory to be allocated below 2gig
*/
if (aac_drivers[index].quirks & AAC_QUIRK_31BIT)
- if (pci_set_dma_mask(pdev, 0x7FFFFFFFULL) ||
- pci_set_consistent_dma_mask(pdev, 0x7FFFFFFFULL))
+ if (pci_set_dma_mask(pdev, DMA_31BIT_MASK) ||
+ pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK))
goto out;
pci_set_master(pdev);
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index 583d2d8c833..fad2109268b 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -550,6 +550,6 @@ module_exit(cumanascsi2_exit);
MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("Cumana SCSI-2 driver for Acorn machines");
-MODULE_PARM(term, "1-8i");
+module_param_array(term, int, NULL, 0);
MODULE_PARM_DESC(term, "SCSI bus termination");
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index 3ffec7efc9d..dcbb4b2b3fe 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -674,6 +674,6 @@ module_exit(eesox_exit);
MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("EESOX 'Fast' SCSI driver for Acorn machines");
-MODULE_PARM(term, "1-8i");
+module_param_array(term, int, NULL, 0);
MODULE_PARM_DESC(term, "SCSI bus termination");
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index 3113bdcedb1..3d69f6c45a6 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -466,6 +466,6 @@ module_exit(powertecscsi_exit);
MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("Powertec SCSI driver");
-MODULE_PARM(term, "1-8i");
+module_param_array(term, int, NULL, 0);
MODULE_PARM_DESC(term, "SCSI bus termination");
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index f4c1ca7c157..f677c5a32a6 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -239,17 +239,17 @@ static int atari_read_overruns = 0;
#endif
static int setup_can_queue = -1;
-MODULE_PARM(setup_can_queue, "i");
+module_param(setup_can_queue, int, 0);
static int setup_cmd_per_lun = -1;
-MODULE_PARM(setup_cmd_per_lun, "i");
+module_param(setup_cmd_per_lun, int, 0);
static int setup_sg_tablesize = -1;
-MODULE_PARM(setup_sg_tablesize, "i");
+module_param(setup_sg_tablesize, int, 0);
#ifdef SUPPORT_TAGS
static int setup_use_tagged_queuing = -1;
-MODULE_PARM(setup_use_tagged_queuing, "i");
+module_param(setup_use_tagged_queuing, int, 0);
#endif
static int setup_hostid = -1;
-MODULE_PARM(setup_hostid, "i");
+module_param(setup_hostid, int, 0);
#if defined(CONFIG_TT_DMA_EMUL)
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 5227a779c05..a198d86667e 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -28,6 +28,7 @@
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -2631,7 +2632,7 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pci_enable_device(pdev))
return -EIO;
- if (!pci_set_dma_mask(pdev, 0xFFFFFFFFUL)) {
+ if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
} else {
printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 6e6b293dcb2..b1b704a42ef 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -57,6 +57,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
#include <linux/reboot.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
+#include <linux/dma-mapping.h>
#include <linux/timer.h>
#include <linux/string.h>
@@ -906,8 +907,8 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
}
pci_set_master(pDev);
- if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) &&
- pci_set_dma_mask(pDev, 0xffffffffULL))
+ if (pci_set_dma_mask(pDev, DMA_64BIT_MASK) &&
+ pci_set_dma_mask(pDev, DMA_32BIT_MASK))
return -EINVAL;
base_addr0_phys = pci_resource_start(pDev,0);
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index b3f9de8f759..059eeee4b55 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -490,6 +490,7 @@
#include <linux/init.h>
#include <linux/ctype.h>
#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
#include <asm/byteorder.h>
#include <asm/dma.h>
#include <asm/io.h>
@@ -1426,7 +1427,7 @@ static int port_detect(unsigned long port_base, unsigned int j,
if (ha->pdev) {
pci_set_master(ha->pdev);
- if (pci_set_dma_mask(ha->pdev, 0xffffffff))
+ if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK))
printk("%s: warning, pci_set_dma_mask failed.\n",
ha->board_name);
}
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 62e3cda859a..d5740bbdef3 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -388,6 +388,7 @@
#include <linux/proc_fs.h>
#include <linux/time.h>
#include <linux/timer.h>
+#include <linux/dma-mapping.h>
#ifdef GDTH_RTC
#include <linux/mc146818rtc.h>
#endif
@@ -671,7 +672,7 @@ static struct file_operations gdth_fops = {
static struct notifier_block gdth_notifier = {
gdth_halt, NULL, 0
};
-
+static int notifier_disabled = 0;
static void gdth_delay(int milliseconds)
{
@@ -4527,15 +4528,15 @@ static int __init gdth_detect(struct scsi_host_template *shtp)
if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat &GDT_64BIT)||
/* 64-bit DMA only supported from FW >= x.43 */
(!ha->dma64_support)) {
- if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) {
+ if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum);
err = TRUE;
}
} else {
shp->max_cmd_len = 16;
- if (!pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffffffffffffULL)) {
+ if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) {
printk("GDT-PCI %d: 64-bit DMA enabled\n", hanum);
- } else if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) {
+ } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "GDT-PCI %d: Unable to set 64/32-bit DMA\n", hanum);
err = TRUE;
}
@@ -4595,13 +4596,13 @@ static int __init gdth_detect(struct scsi_host_template *shtp)
add_timer(&gdth_timer);
#endif
major = register_chrdev(0,"gdth",&gdth_fops);
+ notifier_disabled = 0;
register_reboot_notifier(&gdth_notifier);
}
gdth_polling = FALSE;
return gdth_ctr_vcount;
}
-
static int gdth_release(struct Scsi_Host *shp)
{
int hanum;
@@ -5632,10 +5633,14 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
char cmnd[MAX_COMMAND_SIZE];
#endif
+ if (notifier_disabled)
+ return NOTIFY_OK;
+
TRACE2(("gdth_halt() event %d\n",(int)event));
if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
return NOTIFY_DONE;
+ notifier_disabled = 1;
printk("GDT-HA: Flushing all host drives .. ");
for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
gdth_flush(hanum);
@@ -5679,7 +5684,6 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
#ifdef GDTH_STATISTICS
del_timer(&gdth_timer);
#endif
- unregister_reboot_notifier(&gdth_notifier);
return NOTIFY_OK;
}
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index ea6f3c0e05d..0cc7f65b584 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -127,6 +127,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <scsi/scsi.h>
@@ -2780,7 +2781,7 @@ static int tul_NewReturnNumberOfAdapters(void)
if (((dRegValue & 0xFF00) >> 8) == 0xFF)
dRegValue = 0;
wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
- if (pci_set_dma_mask(pDev, 0xffffffff)) {
+ if (pci_set_dma_mask(pDev, DMA_32BIT_MASK)) {
printk(KERN_WARNING
"i91u: Could not set 32 bit DMA mask\n");
continue;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 481708d527a..a4c0b04cfdb 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -179,6 +179,7 @@
#include <linux/blkdev.h>
#include <linux/types.h>
+#include <linux/dma-mapping.h>
#include <scsi/sg.h>
@@ -7284,10 +7285,10 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
* are guaranteed to be < 4G.
*/
if (IPS_ENABLE_DMA64 && IPS_HAS_ENH_SGLIST(ha) &&
- !pci_set_dma_mask(ha->pcidev, 0xffffffffffffffffULL)) {
+ !pci_set_dma_mask(ha->pcidev, DMA_64BIT_MASK)) {
(ha)->flags |= IPS_HA_ENH_SG;
} else {
- if (pci_set_dma_mask(ha->pcidev, 0xffffffffULL) != 0) {
+ if (pci_set_dma_mask(ha->pcidev, DMA_32BIT_MASK) != 0) {
printk(KERN_WARNING "Unable to set DMA Mask\n");
return ips_abort_init(ha, index);
}
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 7b82ff090d4..2068b66822b 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -3200,8 +3200,8 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
* Data-Out PDU's within R2T-sequence can be quite big;
* using mempool
*/
- ctask->datapool = mempool_create(ISCSI_DTASK_DEFAULT_MAX,
- mempool_alloc_slab, mempool_free_slab, taskcache);
+ ctask->datapool = mempool_create_slab_pool(ISCSI_DTASK_DEFAULT_MAX,
+ taskcache);
if (ctask->datapool == NULL) {
kfifo_free(ctask->r2tqueue);
iscsi_pool_free(&ctask->r2tpool, (void**)ctask->r2ts);
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index 352df47bcac..07017658ac5 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -38,18 +38,6 @@
#define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */
#define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */
-static void *
-lpfc_pool_kmalloc(gfp_t gfp_flags, void *data)
-{
- return kmalloc((unsigned long)data, gfp_flags);
-}
-
-static void
-lpfc_pool_kfree(void *obj, void *data)
-{
- kfree(obj);
-}
-
int
lpfc_mem_alloc(struct lpfc_hba * phba)
{
@@ -79,15 +67,13 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
pool->current_count++;
}
- phba->mbox_mem_pool = mempool_create(LPFC_MEM_POOL_SIZE,
- lpfc_pool_kmalloc, lpfc_pool_kfree,
- (void *)(unsigned long)sizeof(LPFC_MBOXQ_t));
+ phba->mbox_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE,
+ sizeof(LPFC_MBOXQ_t));
if (!phba->mbox_mem_pool)
goto fail_free_mbuf_pool;
- phba->nlp_mem_pool = mempool_create(LPFC_MEM_POOL_SIZE,
- lpfc_pool_kmalloc, lpfc_pool_kfree,
- (void *)(unsigned long)sizeof(struct lpfc_nodelist));
+ phba->nlp_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE,
+ sizeof(struct lpfc_nodelist));
if (!phba->nlp_mem_pool)
goto fail_free_mbox_pool;
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 7144674bc8e..80b68a2481b 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -45,6 +45,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/dma-mapping.h>
#include <scsi/scsicam.h>
#include "scsi.h"
@@ -2094,7 +2095,7 @@ make_local_pdev(adapter_t *adapter, struct pci_dev **pdev)
memcpy(*pdev, adapter->dev, sizeof(struct pci_dev));
- if( pci_set_dma_mask(*pdev, 0xffffffff) != 0 ) {
+ if( pci_set_dma_mask(*pdev, DMA_32BIT_MASK) != 0 ) {
kfree(*pdev);
return -1;
}
@@ -4859,10 +4860,10 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Set the Mode of addressing to 64 bit if we can */
if ((adapter->flag & BOARD_64BIT) && (sizeof(dma_addr_t) == 8)) {
- pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+ pci_set_dma_mask(pdev, DMA_64BIT_MASK);
adapter->has_64bit_addr = 1;
} else {
- pci_set_dma_mask(pdev, 0xffffffff);
+ pci_set_dma_mask(pdev, DMA_32BIT_MASK);
adapter->has_64bit_addr = 0;
}
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index d6d2125f904..f852421002e 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1748,7 +1748,7 @@ static int mesh_host_reset(struct scsi_cmnd *cmd)
static void set_mesh_power(struct mesh_state *ms, int state)
{
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return;
if (state) {
pmac_call_feature(PMAC_FTR_MESH_ENABLE, macio_get_of_node(ms->mdev), 0, 1);
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index a279ebb6144..30ee0ef4b45 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -38,6 +38,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ctype.h>
+#include <linux/dma-mapping.h>
#include <asm/dma.h>
#include <asm/system.h>
@@ -2776,7 +2777,7 @@ static int nsp32_detect(struct scsi_host_template *sht)
/*
* setup DMA
*/
- if (pci_set_dma_mask(PCIDEV, 0xffffffffUL) != 0) {
+ if (pci_set_dma_mask(PCIDEV, DMA_32BIT_MASK) != 0) {
nsp32_msg (KERN_ERR, "failed to set PCI DMA mask");
goto scsi_unregister;
}
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 66ea47a9c53..e3bd4bc339f 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -49,6 +49,7 @@ static const char * osst_version = "0.99.4";
#include <linux/blkdev.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
+#include <linux/jiffies.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
#include <asm/system.h>
@@ -856,7 +857,7 @@ static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt
) && result >= 0)
{
#if DEBUG
- if (debugging || jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC)
+ if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
printk (OSST_DEB_MSG
"%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
name, curr, curr+minlast, STp->first_frame_position,
@@ -867,7 +868,7 @@ static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt
return 0;
}
#if DEBUG
- if (jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC && notyetprinted)
+ if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
{
printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
name, curr, curr+minlast, STp->first_frame_position,
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index 05347eed9dd..fee843fab1c 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -18,6 +18,7 @@
#include <linux/parport.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
+#include <linux/jiffies.h>
#include <asm/io.h>
#include <scsi/scsi.h>
@@ -726,7 +727,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd)
retv--;
if (retv) {
- if ((jiffies - dev->jstart) > (1 * HZ)) {
+ if (time_after(jiffies, dev->jstart + (1 * HZ))) {
printk
("ppa: Parallel port cable is unplugged!!\n");
ppa_fail(dev, DID_BUS_BUSY);
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index e0230249fa0..5a48e55f941 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -350,6 +350,7 @@
#include <linux/pci_ids.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -4321,7 +4322,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
#ifdef QLA_64BIT_PTR
if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) {
- if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
+ if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "scsi(%li): Unable to set a "
"suitable DMA mask - aborting\n", ha->host_no);
error = -ENODEV;
@@ -4331,7 +4332,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
dprintk(2, "scsi(%li): 64 Bit PCI Addressing Enabled\n",
ha->host_no);
#else
- if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
+ if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "scsi(%li): Unable to set a "
"suitable DMA mask - aborting\n", ha->host_no);
error = -ENODEV;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 029bbf461bb..017729c59a4 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2154,8 +2154,7 @@ qla2x00_allocate_sp_pool(scsi_qla_host_t *ha)
int rval;
rval = QLA_SUCCESS;
- ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab,
- mempool_free_slab, srb_cachep);
+ ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
if (ha->srb_mempool == NULL) {
qla_printk(KERN_INFO, ha, "Unable to allocate SRB mempool.\n");
rval = QLA_FUNCTION_FAILED;
diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c
index 94ef3f08d37..52b224a5d6f 100644
--- a/drivers/scsi/qlogicfc.c
+++ b/drivers/scsi/qlogicfc.c
@@ -61,6 +61,8 @@
#include <linux/unistd.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/jiffies.h>
#include <asm/io.h>
#include <asm/irq.h>
#include "scsi.h"
@@ -737,8 +739,8 @@ static int isp2x00_detect(struct scsi_host_template * tmpt)
continue;
/* Try to configure DMA attributes. */
- if (pci_set_dma_mask(pdev, 0xffffffffffffffffULL) &&
- pci_set_dma_mask(pdev, 0xffffffffULL))
+ if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&
+ pci_set_dma_mask(pdev, DMA_32BIT_MASK))
continue;
host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata));
@@ -1325,7 +1327,7 @@ static int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
cmd->control_flags = cpu_to_le16(CFLAG_READ);
if (Cmnd->device->tagged_supported) {
- if ((jiffies - hostdata->tag_ages[Cmnd->device->id]) > (2 * ISP_TIMEOUT)) {
+ if (time_after(jiffies, hostdata->tag_ages[Cmnd->device->id] + (2 * ISP_TIMEOUT))) {
cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG);
hostdata->tag_ages[Cmnd->device->id] = jiffies;
} else
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index 1fd5fc6d0fe..c7e78dcf09d 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -24,6 +24,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/jiffies.h>
#include <asm/byteorder.h>
@@ -1017,7 +1018,7 @@ static inline void cmd_frob(struct Command_Entry *cmd, struct scsi_cmnd *Cmnd,
if (Cmnd->device->tagged_supported) {
if (qpti->cmd_count[Cmnd->device->id] == 0)
qpti->tag_ages[Cmnd->device->id] = jiffies;
- if ((jiffies - qpti->tag_ages[Cmnd->device->id]) > (5*HZ)) {
+ if (time_after(jiffies, qpti->tag_ages[Cmnd->device->id] + (5*HZ))) {
cmd->control_flags = CFLAG_ORDERED_TAG;
qpti->tag_ages[Cmnd->device->id] = jiffies;
} else
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ede158d08d9..8f010a314a3 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1787,9 +1787,8 @@ int __init scsi_init_queue(void)
sgp->name);
}
- sgp->pool = mempool_create(SG_MEMPOOL_SIZE,
- mempool_alloc_slab, mempool_free_slab,
- sgp->slab);
+ sgp->pool = mempool_create_slab_pool(SG_MEMPOOL_SIZE,
+ sgp->slab);
if (!sgp->pool) {
printk(KERN_ERR "SCSI: can't init sg mempool %s\n",
sgp->name);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 024ef86c524..c647d85d97d 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -190,7 +190,7 @@ static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf,
if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT,
SD_MAX_RETRIES, &data, NULL))
return -EINVAL;
- len = min(sizeof(buffer), data.length - data.header_length -
+ len = min_t(size_t, sizeof(buffer), data.length - data.header_length -
data.block_descriptor_length);
buffer_data = buffer + data.header_length +
data.block_descriptor_length;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 5996d3cd0ed..674b15c78f6 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1528,7 +1528,7 @@ static int serial8250_startup(struct uart_port *port)
/*
* Clear the FIFO buffers and disable them.
- * (they will be reeanbled in set_termios())
+ * (they will be reenabled in set_termios())
*/
serial8250_clear_fifos(up);
diff --git a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c
deleted file mode 100644
index 809f89ab965..00000000000
--- a/drivers/serial/8250_acpi.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2002-2003 Matthew Wilcox for Hewlett-Packard
- * Copyright (C) 2004 Hewlett-Packard Co
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/acpi.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/serial_core.h>
-
-#include <acpi/acpi_bus.h>
-
-#include <asm/io.h>
-
-#include "8250.h"
-
-struct serial_private {
- int line;
-};
-
-static acpi_status acpi_serial_mmio(struct uart_port *port,
- struct acpi_resource_address64 *addr)
-{
- port->mapbase = addr->minimum;
- port->iotype = UPIO_MEM;
- port->flags |= UPF_IOREMAP;
- return AE_OK;
-}
-
-static acpi_status acpi_serial_port(struct uart_port *port,
- struct acpi_resource_io *io)
-{
- if (io->address_length) {
- port->iobase = io->minimum;
- port->iotype = UPIO_PORT;
- } else
- printk(KERN_ERR "%s: zero-length IO port range?\n", __FUNCTION__);
- return AE_OK;
-}
-
-static acpi_status acpi_serial_ext_irq(struct uart_port *port,
- struct acpi_resource_extended_irq *ext_irq)
-{
- int rc;
-
- if (ext_irq->interrupt_count > 0) {
- rc = acpi_register_gsi(ext_irq->interrupts[0],
- ext_irq->triggering, ext_irq->polarity);
- if (rc < 0)
- return AE_ERROR;
- port->irq = rc;
- }
- return AE_OK;
-}
-
-static acpi_status acpi_serial_irq(struct uart_port *port,
- struct acpi_resource_irq *irq)
-{
- int rc;
-
- if (irq->interrupt_count > 0) {
- rc = acpi_register_gsi(irq->interrupts[0],
- irq->triggering, irq->polarity);
- if (rc < 0)
- return AE_ERROR;
- port->irq = rc;
- }
- return AE_OK;
-}
-
-static acpi_status acpi_serial_resource(struct acpi_resource *res, void *data)
-{
- struct uart_port *port = (struct uart_port *) data;
- struct acpi_resource_address64 addr;
- acpi_status status;
-
- status = acpi_resource_to_address64(res, &addr);
- if (ACPI_SUCCESS(status))
- return acpi_serial_mmio(port, &addr);
- else if (res->type == ACPI_RESOURCE_TYPE_IO)
- return acpi_serial_port(port, &res->data.io);
- else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ)
- return acpi_serial_ext_irq(port, &res->data.extended_irq);
- else if (res->type == ACPI_RESOURCE_TYPE_IRQ)
- return acpi_serial_irq(port, &res->data.irq);
- return AE_OK;
-}
-
-static int acpi_serial_add(struct acpi_device *device)
-{
- struct serial_private *priv;
- acpi_status status;
- struct uart_port port;
- int result;
-
- memset(&port, 0, sizeof(struct uart_port));
-
- port.uartclk = 1843200;
- port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
-
- priv = kmalloc(sizeof(struct serial_private), GFP_KERNEL);
- if (!priv) {
- result = -ENOMEM;
- goto fail;
- }
- memset(priv, 0, sizeof(*priv));
-
- status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
- acpi_serial_resource, &port);
- if (ACPI_FAILURE(status)) {
- result = -ENODEV;
- goto fail;
- }
-
- if (!port.mapbase && !port.iobase) {
- printk(KERN_ERR "%s: no iomem or port address in %s _CRS\n",
- __FUNCTION__, device->pnp.bus_id);
- result = -ENODEV;
- goto fail;
- }
-
- priv->line = serial8250_register_port(&port);
- if (priv->line < 0) {
- printk(KERN_WARNING "Couldn't register serial port %s: %d\n",
- device->pnp.bus_id, priv->line);
- result = -ENODEV;
- goto fail;
- }
-
- acpi_driver_data(device) = priv;
- return 0;
-
-fail:
- kfree(priv);
-
- return result;
-}
-
-static int acpi_serial_remove(struct acpi_device *device, int type)
-{
- struct serial_private *priv;
-
- if (!device || !acpi_driver_data(device))
- return -EINVAL;
-
- priv = acpi_driver_data(device);
- serial8250_unregister_port(priv->line);
- kfree(priv);
-
- return 0;
-}
-
-static struct acpi_driver acpi_serial_driver = {
- .name = "serial",
- .class = "",
- .ids = "PNP0501",
- .ops = {
- .add = acpi_serial_add,
- .remove = acpi_serial_remove,
- },
-};
-
-static int __init acpi_serial_init(void)
-{
- return acpi_bus_register_driver(&acpi_serial_driver);
-}
-
-static void __exit acpi_serial_exit(void)
-{
- acpi_bus_unregister_driver(&acpi_serial_driver);
-}
-
-module_init(acpi_serial_init);
-module_exit(acpi_serial_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic 8250/16x50 ACPI serial driver");
diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c
index 8d8d7a70d03..3d1bfd07208 100644
--- a/drivers/serial/8250_au1x00.c
+++ b/drivers/serial/8250_au1x00.c
@@ -51,7 +51,7 @@ static struct plat_serial8250_port au1x00_data[] = {
#elif defined(CONFIG_SOC_AU1100)
PORT(UART0_ADDR, AU1100_UART0_INT),
PORT(UART1_ADDR, AU1100_UART1_INT),
- PORT(UART2_ADDR, AU1100_UART2_INT),
+ /* The internal UART2 does not exist on the AU1100 processor. */
PORT(UART3_ADDR, AU1100_UART3_INT),
#elif defined(CONFIG_SOC_AU1550)
PORT(UART0_ADDR, AU1550_UART0_INT),
diff --git a/drivers/serial/8250_hp300.c b/drivers/serial/8250_hp300.c
index 4315afe9c08..53e81a44c1a 100644
--- a/drivers/serial/8250_hp300.c
+++ b/drivers/serial/8250_hp300.c
@@ -55,6 +55,8 @@ static struct dio_driver hpdca_driver = {
#endif
+static unsigned int num_ports;
+
extern int hp300_uart_scode;
/* Offset to UART registers from base of DCA */
@@ -199,6 +201,8 @@ static int __devinit hpdca_init_one(struct dio_dev *d,
out_8(d->resource.start + DIO_VIRADDRBASE + DCA_ID, 0xff);
udelay(100);
+ num_ports++;
+
return 0;
}
#endif
@@ -206,7 +210,6 @@ static int __devinit hpdca_init_one(struct dio_dev *d,
static int __init hp300_8250_init(void)
{
static int called = 0;
- int num_ports;
#ifdef CONFIG_HPAPCI
int line;
unsigned long base;
@@ -221,11 +224,8 @@ static int __init hp300_8250_init(void)
if (!MACH_IS_HP300)
return -ENODEV;
- num_ports = 0;
-
#ifdef CONFIG_HPDCA
- if (dio_module_init(&hpdca_driver) == 0)
- num_ports++;
+ dio_register_driver(&hpdca_driver);
#endif
#ifdef CONFIG_HPAPCI
if (hp300_model < HP_400) {
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index c66ef96c71b..fe0d8b8e91c 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -77,14 +77,6 @@ config SERIAL_8250_CS
If unsure, say N.
-config SERIAL_8250_ACPI
- bool "8250/16550 device discovery via ACPI namespace"
- default y if IA64
- depends on ACPI && SERIAL_8250
- ---help---
- If you wish to enable serial port discovery via the ACPI
- namespace, say Y here. If unsure, say N.
-
config SERIAL_8250_NR_UARTS
int "Maximum number of 8250/16550 serial ports"
depends on SERIAL_8250
@@ -628,22 +620,6 @@ config SERIAL_SH_SCI_CONSOLE
depends on SERIAL_SH_SCI=y
select SERIAL_CORE_CONSOLE
-config SERIAL_AU1X00
- bool "Enable Au1x00 UART Support"
- depends on MIPS && SOC_AU1X00
- select SERIAL_CORE
- help
- If you have an Alchemy AU1X00 processor (MIPS based) and you want
- to use serial ports, say Y. Otherwise, say N.
-
-config SERIAL_AU1X00_CONSOLE
- bool "Enable Au1x00 serial console"
- depends on SERIAL_AU1X00
- select SERIAL_CORE_CONSOLE
- help
- If you have an Alchemy AU1X00 processor (MIPS based) and you want
- to use a console on a serial port, say Y. Otherwise, say N.
-
config SERIAL_CORE
tristate
@@ -827,6 +803,7 @@ config SERIAL_ICOM
tristate "IBM Multiport Serial Adapter"
depends on PCI && (PPC_ISERIES || PPC_PSERIES)
select SERIAL_CORE
+ select FW_LOADER
help
This driver is for a family of multiport serial adapters
including 2 port RVX, 2 port internal modem, 4 port internal
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 50c221af9e6..d2b4c214876 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -5,7 +5,6 @@
#
serial-8250-y :=
-serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o
serial-8250-$(CONFIG_PNP) += 8250_pnp.o
serial-8250-$(CONFIG_GSC) += 8250_gsc.o
serial-8250-$(CONFIG_PCI) += 8250_pci.o
@@ -42,7 +41,6 @@ obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o
obj-$(CONFIG_V850E_UART) += v850e_uart.o
obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o
-obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o
obj-$(CONFIG_SERIAL_DZ) += dz.o
obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += sn_console.o
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index e04d5e82d9a..1631414000a 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -51,8 +51,6 @@
#include <linux/amba/serial.h>
#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
#define UART_NR 2
@@ -62,47 +60,19 @@
#define AMBA_ISR_PASS_LIMIT 256
-/*
- * Access macros for the AMBA UARTs
- */
-#define UART_GET_INT_STATUS(p) readb((p)->membase + UART010_IIR)
-#define UART_PUT_ICR(p, c) writel((c), (p)->membase + UART010_ICR)
-#define UART_GET_FR(p) readb((p)->membase + UART01x_FR)
-#define UART_GET_CHAR(p) readb((p)->membase + UART01x_DR)
-#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + UART01x_DR)
-#define UART_GET_RSR(p) readb((p)->membase + UART01x_RSR)
-#define UART_GET_CR(p) readb((p)->membase + UART010_CR)
-#define UART_PUT_CR(p,c) writel((c), (p)->membase + UART010_CR)
-#define UART_GET_LCRL(p) readb((p)->membase + UART010_LCRL)
-#define UART_PUT_LCRL(p,c) writel((c), (p)->membase + UART010_LCRL)
-#define UART_GET_LCRM(p) readb((p)->membase + UART010_LCRM)
-#define UART_PUT_LCRM(p,c) writel((c), (p)->membase + UART010_LCRM)
-#define UART_GET_LCRH(p) readb((p)->membase + UART010_LCRH)
-#define UART_PUT_LCRH(p,c) writel((c), (p)->membase + UART010_LCRH)
#define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0)
#define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0)
-#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART01x_FR_TMSK) == 0)
-#define UART_DUMMY_RSR_RX /*256*/0
+#define UART_DUMMY_RSR_RX 256
#define UART_PORT_SIZE 64
/*
- * On the Integrator platform, the port RTS and DTR are provided by
- * bits in the following SC_CTRLS register bits:
- * RTS DTR
- * UART0 7 6
- * UART1 5 4
- */
-#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
-#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
-
-/*
* We wrap our port structure around the generic uart_port.
*/
struct uart_amba_port {
struct uart_port port;
- unsigned int dtr_mask;
- unsigned int rts_mask;
+ struct amba_device *dev;
+ struct amba_pl010_data *data;
unsigned int old_status;
};
@@ -110,36 +80,36 @@ static void pl010_stop_tx(struct uart_port *port)
{
unsigned int cr;
- cr = UART_GET_CR(port);
+ cr = readb(port->membase + UART010_CR);
cr &= ~UART010_CR_TIE;
- UART_PUT_CR(port, cr);
+ writel(cr, port->membase + UART010_CR);
}
static void pl010_start_tx(struct uart_port *port)
{
unsigned int cr;
- cr = UART_GET_CR(port);
+ cr = readb(port->membase + UART010_CR);
cr |= UART010_CR_TIE;
- UART_PUT_CR(port, cr);
+ writel(cr, port->membase + UART010_CR);
}
static void pl010_stop_rx(struct uart_port *port)
{
unsigned int cr;
- cr = UART_GET_CR(port);
+ cr = readb(port->membase + UART010_CR);
cr &= ~(UART010_CR_RIE | UART010_CR_RTIE);
- UART_PUT_CR(port, cr);
+ writel(cr, port->membase + UART010_CR);
}
static void pl010_enable_ms(struct uart_port *port)
{
unsigned int cr;
- cr = UART_GET_CR(port);
+ cr = readb(port->membase + UART010_CR);
cr |= UART010_CR_MSIE;
- UART_PUT_CR(port, cr);
+ writel(cr, port->membase + UART010_CR);
}
static void
@@ -152,9 +122,9 @@ pl010_rx_chars(struct uart_port *port)
struct tty_struct *tty = port->info->tty;
unsigned int status, ch, flag, rsr, max_count = 256;
- status = UART_GET_FR(port);
+ status = readb(port->membase + UART01x_FR);
while (UART_RX_DATA(status) && max_count--) {
- ch = UART_GET_CHAR(port);
+ ch = readb(port->membase + UART01x_DR);
flag = TTY_NORMAL;
port->icount.rx++;
@@ -163,7 +133,7 @@ pl010_rx_chars(struct uart_port *port)
* Note that the error handling code is
* out of the main execution path
*/
- rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
+ rsr = readb(port->membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
if (unlikely(rsr & UART01x_RSR_ANY)) {
if (rsr & UART01x_RSR_BE) {
rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
@@ -193,7 +163,7 @@ pl010_rx_chars(struct uart_port *port)
uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag);
ignore_char:
- status = UART_GET_FR(port);
+ status = readb(port->membase + UART01x_FR);
}
tty_flip_buffer_push(tty);
return;
@@ -205,7 +175,7 @@ static void pl010_tx_chars(struct uart_port *port)
int count;
if (port->x_char) {
- UART_PUT_CHAR(port, port->x_char);
+ writel(port->x_char, port->membase + UART01x_DR);
port->icount.tx++;
port->x_char = 0;
return;
@@ -217,7 +187,7 @@ static void pl010_tx_chars(struct uart_port *port)
count = port->fifosize >> 1;
do {
- UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
+ writel(xmit->buf[xmit->tail], port->membase + UART01x_DR);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
if (uart_circ_empty(xmit))
@@ -236,9 +206,9 @@ static void pl010_modem_status(struct uart_port *port)
struct uart_amba_port *uap = (struct uart_amba_port *)port;
unsigned int status, delta;
- UART_PUT_ICR(&uap->port, 0);
+ writel(0, uap->port.membase + UART010_ICR);
- status = UART_GET_FR(&uap->port) & UART01x_FR_MODEM_ANY;
+ status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
delta = status ^ uap->old_status;
uap->old_status = status;
@@ -266,7 +236,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs)
spin_lock(&port->lock);
- status = UART_GET_INT_STATUS(port);
+ status = readb(port->membase + UART010_IIR);
if (status) {
do {
if (status & (UART010_IIR_RTIS | UART010_IIR_RIS))
@@ -283,7 +253,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs)
if (pass_counter-- == 0)
break;
- status = UART_GET_INT_STATUS(port);
+ status = readb(port->membase + UART010_IIR);
} while (status & (UART010_IIR_RTIS | UART010_IIR_RIS |
UART010_IIR_TIS));
handled = 1;
@@ -296,7 +266,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs)
static unsigned int pl010_tx_empty(struct uart_port *port)
{
- return UART_GET_FR(port) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT;
+ return readb(port->membase + UART01x_FR) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT;
}
static unsigned int pl010_get_mctrl(struct uart_port *port)
@@ -304,7 +274,7 @@ static unsigned int pl010_get_mctrl(struct uart_port *port)
unsigned int result = 0;
unsigned int status;
- status = UART_GET_FR(port);
+ status = readb(port->membase + UART01x_FR);
if (status & UART01x_FR_DCD)
result |= TIOCM_CAR;
if (status & UART01x_FR_DSR)
@@ -318,20 +288,9 @@ static unsigned int pl010_get_mctrl(struct uart_port *port)
static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
- unsigned int ctrls = 0, ctrlc = 0;
-
- if (mctrl & TIOCM_RTS)
- ctrlc |= uap->rts_mask;
- else
- ctrls |= uap->rts_mask;
-
- if (mctrl & TIOCM_DTR)
- ctrlc |= uap->dtr_mask;
- else
- ctrls |= uap->dtr_mask;
- __raw_writel(ctrls, SC_CTRLS);
- __raw_writel(ctrlc, SC_CTRLC);
+ if (uap->data)
+ uap->data->set_mctrl(uap->dev, uap->port.membase, mctrl);
}
static void pl010_break_ctl(struct uart_port *port, int break_state)
@@ -340,12 +299,12 @@ static void pl010_break_ctl(struct uart_port *port, int break_state)
unsigned int lcr_h;
spin_lock_irqsave(&port->lock, flags);
- lcr_h = UART_GET_LCRH(port);
+ lcr_h = readb(port->membase + UART010_LCRH);
if (break_state == -1)
lcr_h |= UART01x_LCRH_BRK;
else
lcr_h &= ~UART01x_LCRH_BRK;
- UART_PUT_LCRH(port, lcr_h);
+ writel(lcr_h, port->membase + UART010_LCRH);
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -364,13 +323,13 @@ static int pl010_startup(struct uart_port *port)
/*
* initialise the old status of the modem signals
*/
- uap->old_status = UART_GET_FR(port) & UART01x_FR_MODEM_ANY;
+ uap->old_status = readb(port->membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
/*
* Finally, enable interrupts
*/
- UART_PUT_CR(port, UART01x_CR_UARTEN | UART010_CR_RIE |
- UART010_CR_RTIE);
+ writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE,
+ port->membase + UART010_CR);
return 0;
}
@@ -385,11 +344,12 @@ static void pl010_shutdown(struct uart_port *port)
/*
* disable all interrupts, disable the port
*/
- UART_PUT_CR(port, 0);
+ writel(0, port->membase + UART010_CR);
/* disable break condition and fifos */
- UART_PUT_LCRH(port, UART_GET_LCRH(port) &
- ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN));
+ writel(readb(port->membase + UART010_LCRH) &
+ ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN),
+ port->membase + UART010_LCRH);
}
static void
@@ -466,25 +426,25 @@ pl010_set_termios(struct uart_port *port, struct termios *termios,
port->ignore_status_mask |= UART_DUMMY_RSR_RX;
/* first, disable everything */
- old_cr = UART_GET_CR(port) & ~UART010_CR_MSIE;
+ old_cr = readb(port->membase + UART010_CR) & ~UART010_CR_MSIE;
if (UART_ENABLE_MS(port, termios->c_cflag))
old_cr |= UART010_CR_MSIE;
- UART_PUT_CR(port, 0);
+ writel(0, port->membase + UART010_CR);
/* Set baud rate */
quot -= 1;
- UART_PUT_LCRM(port, ((quot & 0xf00) >> 8));
- UART_PUT_LCRL(port, (quot & 0xff));
+ writel((quot & 0xf00) >> 8, port->membase + UART010_LCRM);
+ writel(quot & 0xff, port->membase + UART010_LCRL);
/*
* ----------v----------v----------v----------v-----
* NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
* ----------^----------^----------^----------^-----
*/
- UART_PUT_LCRH(port, lcr_h);
- UART_PUT_CR(port, old_cr);
+ writel(lcr_h, port->membase + UART010_LCRH);
+ writel(old_cr, port->membase + UART010_CR);
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -556,59 +516,32 @@ static struct uart_ops amba_pl010_pops = {
.verify_port = pl010_verify_port,
};
-static struct uart_amba_port amba_ports[UART_NR] = {
- {
- .port = {
- .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
- .mapbase = INTEGRATOR_UART0_BASE,
- .iotype = UPIO_MEM,
- .irq = IRQ_UARTINT0,
- .uartclk = 14745600,
- .fifosize = 16,
- .ops = &amba_pl010_pops,
- .flags = UPF_BOOT_AUTOCONF,
- .line = 0,
- },
- .dtr_mask = 1 << 5,
- .rts_mask = 1 << 4,
- },
- {
- .port = {
- .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
- .mapbase = INTEGRATOR_UART1_BASE,
- .iotype = UPIO_MEM,
- .irq = IRQ_UARTINT1,
- .uartclk = 14745600,
- .fifosize = 16,
- .ops = &amba_pl010_pops,
- .flags = UPF_BOOT_AUTOCONF,
- .line = 1,
- },
- .dtr_mask = 1 << 7,
- .rts_mask = 1 << 6,
- }
-};
+static struct uart_amba_port *amba_ports[UART_NR];
#ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE
static void pl010_console_putchar(struct uart_port *port, int ch)
{
- while (!UART_TX_READY(UART_GET_FR(port)))
+ unsigned int status;
+
+ do {
+ status = readb(port->membase + UART01x_FR);
barrier();
- UART_PUT_CHAR(port, ch);
+ } while (!UART_TX_READY(status));
+ writel(ch, port->membase + UART01x_DR);
}
static void
pl010_console_write(struct console *co, const char *s, unsigned int count)
{
- struct uart_port *port = &amba_ports[co->index].port;
+ struct uart_port *port = &amba_ports[co->index]->port;
unsigned int status, old_cr;
/*
* First save the CR then disable the interrupts
*/
- old_cr = UART_GET_CR(port);
- UART_PUT_CR(port, UART01x_CR_UARTEN);
+ old_cr = readb(port->membase + UART010_CR);
+ writel(UART01x_CR_UARTEN, port->membase + UART010_CR);
uart_console_write(port, s, count, pl010_console_putchar);
@@ -617,18 +550,19 @@ pl010_console_write(struct console *co, const char *s, unsigned int count)
* and restore the TCR
*/
do {
- status = UART_GET_FR(port);
+ status = readb(port->membase + UART01x_FR);
+ barrier();
} while (status & UART01x_FR_BUSY);
- UART_PUT_CR(port, old_cr);
+ writel(old_cr, port->membase + UART010_CR);
}
static void __init
pl010_console_get_options(struct uart_port *port, int *baud,
int *parity, int *bits)
{
- if (UART_GET_CR(port) & UART01x_CR_UARTEN) {
+ if (readb(port->membase + UART010_CR) & UART01x_CR_UARTEN) {
unsigned int lcr_h, quot;
- lcr_h = UART_GET_LCRH(port);
+ lcr_h = readb(port->membase + UART010_LCRH);
*parity = 'n';
if (lcr_h & UART01x_LCRH_PEN) {
@@ -643,7 +577,7 @@ pl010_console_get_options(struct uart_port *port, int *baud,
else
*bits = 8;
- quot = UART_GET_LCRL(port) | UART_GET_LCRM(port) << 8;
+ quot = readb(port->membase + UART010_LCRL) | readb(port->membase + UART010_LCRM) << 8;
*baud = port->uartclk / (16 * (quot + 1));
}
}
@@ -663,7 +597,7 @@ static int __init pl010_console_setup(struct console *co, char *options)
*/
if (co->index >= UART_NR)
co->index = 0;
- port = &amba_ports[co->index].port;
+ port = &amba_ports[co->index]->port;
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -684,24 +618,6 @@ static struct console amba_console = {
.data = &amba_reg,
};
-static int __init amba_console_init(void)
-{
- /*
- * All port initializations are done statically
- */
- register_console(&amba_console);
- return 0;
-}
-console_initcall(amba_console_init);
-
-static int __init amba_late_console_init(void)
-{
- if (!(amba_console.flags & CON_ENABLED))
- register_console(&amba_console);
- return 0;
-}
-late_initcall(amba_late_console_init);
-
#define AMBA_CONSOLE &amba_console
#else
#define AMBA_CONSOLE NULL
@@ -719,30 +635,76 @@ static struct uart_driver amba_reg = {
static int pl010_probe(struct amba_device *dev, void *id)
{
- int i;
+ struct uart_amba_port *port;
+ void __iomem *base;
+ int i, ret;
- for (i = 0; i < UART_NR; i++) {
- if (amba_ports[i].port.mapbase != dev->res.start)
- continue;
+ for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
+ if (amba_ports[i] == NULL)
+ break;
- amba_ports[i].port.dev = &dev->dev;
- uart_add_one_port(&amba_reg, &amba_ports[i].port);
- amba_set_drvdata(dev, &amba_ports[i]);
- break;
+ if (i == ARRAY_SIZE(amba_ports)) {
+ ret = -EBUSY;
+ goto out;
}
- return 0;
+ port = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
+ if (!port) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ base = ioremap(dev->res.start, PAGE_SIZE);
+ if (!base) {
+ ret = -ENOMEM;
+ goto free;
+ }
+
+ port->port.dev = &dev->dev;
+ port->port.mapbase = dev->res.start;
+ port->port.membase = base;
+ port->port.iotype = UPIO_MEM;
+ port->port.irq = dev->irq[0];
+ port->port.uartclk = 14745600;
+ port->port.fifosize = 16;
+ port->port.ops = &amba_pl010_pops;
+ port->port.flags = UPF_BOOT_AUTOCONF;
+ port->port.line = i;
+ port->dev = dev;
+ port->data = dev->dev.platform_data;
+
+ amba_ports[i] = port;
+
+ amba_set_drvdata(dev, port);
+ ret = uart_add_one_port(&amba_reg, &port->port);
+ if (ret) {
+ amba_set_drvdata(dev, NULL);
+ amba_ports[i] = NULL;
+ iounmap(base);
+ free:
+ kfree(port);
+ }
+
+ out:
+ return ret;
}
static int pl010_remove(struct amba_device *dev)
{
- struct uart_amba_port *uap = amba_get_drvdata(dev);
-
- if (uap)
- uart_remove_one_port(&amba_reg, &uap->port);
+ struct uart_amba_port *port = amba_get_drvdata(dev);
+ int i;
amba_set_drvdata(dev, NULL);
+ uart_remove_one_port(&amba_reg, &port->port);
+
+ for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
+ if (amba_ports[i] == port)
+ amba_ports[i] = NULL;
+
+ iounmap(port->port.membase);
+ kfree(port);
+
return 0;
}
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
deleted file mode 100644
index 948880ac587..00000000000
--- a/drivers/serial/au1x00_uart.c
+++ /dev/null
@@ -1,1287 +0,0 @@
-/*
- * Driver for 8250/16550-type serial ports
- *
- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- * Copyright (C) 2001 Russell King.
- *
- * 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 note about mapbase / membase
- *
- * mapbase is the physical address of the IO port. Currently, we don't
- * support this very well, and it may well be dropped from this driver
- * in future. As such, mapbase should be NULL.
- *
- * membase is an 'ioremapped' cookie. This is compatible with the old
- * serial.c driver, and is currently the preferred form.
- */
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/delay.h>
-
-#include <asm/serial.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach-au1x00/au1000.h>
-
-#if defined(CONFIG_SERIAL_AU1X00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/serial_core.h>
-#include "8250.h"
-
-/*
- * Debugging.
- */
-#if 0
-#define DEBUG_AUTOCONF(fmt...) printk(fmt)
-#else
-#define DEBUG_AUTOCONF(fmt...) do { } while (0)
-#endif
-
-#if 0
-#define DEBUG_INTR(fmt...) printk(fmt)
-#else
-#define DEBUG_INTR(fmt...) do { } while (0)
-#endif
-
-#define PASS_LIMIT 256
-
-/*
- * We default to IRQ0 for the "no irq" hack. Some
- * machine types want others as well - they're free
- * to redefine this in their header file.
- */
-#define is_real_interrupt(irq) ((irq) != 0)
-
-static struct old_serial_port old_serial_port[] = {
- { .baud_base = 0,
- .iomem_base = (u8 *)UART0_ADDR,
- .irq = AU1000_UART0_INT,
- .flags = STD_COM_FLAGS,
- .iomem_reg_shift = 2,
- }, {
- .baud_base = 0,
- .iomem_base = (u8 *)UART1_ADDR,
- .irq = AU1000_UART1_INT,
- .flags = STD_COM_FLAGS,
- .iomem_reg_shift = 2
- }, {
- .baud_base = 0,
- .iomem_base = (u8 *)UART2_ADDR,
- .irq = AU1000_UART2_INT,
- .flags = STD_COM_FLAGS,
- .iomem_reg_shift = 2
- }, {
- .baud_base = 0,
- .iomem_base = (u8 *)UART3_ADDR,
- .irq = AU1000_UART3_INT,
- .flags = STD_COM_FLAGS,
- .iomem_reg_shift = 2
- }
-};
-
-#define UART_NR ARRAY_SIZE(old_serial_port)
-
-struct uart_8250_port {
- struct uart_port port;
- struct timer_list timer; /* "no irq" timer */
- struct list_head list; /* ports on this IRQ */
- unsigned short rev;
- unsigned char acr;
- unsigned char ier;
- unsigned char lcr;
- unsigned char mcr_mask; /* mask of user bits */
- unsigned char mcr_force; /* mask of forced bits */
- unsigned char lsr_break_flag;
-
- /*
- * We provide a per-port pm hook.
- */
- void (*pm)(struct uart_port *port,
- unsigned int state, unsigned int old);
-};
-
-struct irq_info {
- spinlock_t lock;
- struct list_head *head;
-};
-
-static struct irq_info irq_lists[NR_IRQS];
-
-/*
- * Here we define the default xmit fifo size used for each type of UART.
- */
-static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
- { "unknown", 1, 0 },
- { "8250", 1, 0 },
- { "16450", 1, 0 },
- { "16550", 1, 0 },
- /* PORT_16550A */
- { "AU1X00_UART",16, UART_CLEAR_FIFO | UART_USE_FIFO },
-};
-
-static unsigned int serial_in(struct uart_8250_port *up, int offset)
-{
- return au_readl((unsigned long)up->port.membase + offset);
-}
-
-static void serial_out(struct uart_8250_port *up, int offset, int value)
-{
- au_writel(value, (unsigned long)up->port.membase + offset);
-}
-
-#define serial_inp(up, offset) serial_in(up, offset)
-#define serial_outp(up, offset, value) serial_out(up, offset, value)
-
-/*
- * This routine is called by rs_init() to initialize a specific serial
- * port. It determines what type of UART chip this serial port is
- * using: 8250, 16450, 16550, 16550A. The important question is
- * whether or not this UART is a 16550A or not, since this will
- * determine whether or not we can use its FIFO features or not.
- */
-static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
-{
- unsigned char save_lcr, save_mcr;
- unsigned long flags;
-
- if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
- return;
-
- DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%08lx): ",
- up->port.line, up->port.iobase, up->port.membase);
-
- /*
- * We really do need global IRQs disabled here - we're going to
- * be frobbing the chips IRQ enable register to see if it exists.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-// save_flags(flags); cli();
-
- save_mcr = serial_in(up, UART_MCR);
- save_lcr = serial_in(up, UART_LCR);
-
- up->port.type = PORT_16550A;
- serial_outp(up, UART_LCR, save_lcr);
-
- up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
-
- if (up->port.type == PORT_UNKNOWN)
- goto out;
-
- /*
- * Reset the UART.
- */
- serial_outp(up, UART_MCR, save_mcr);
- serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR |
- UART_FCR_CLEAR_XMIT));
- serial_outp(up, UART_FCR, 0);
- (void)serial_in(up, UART_RX);
- serial_outp(up, UART_IER, 0);
-
- out:
- spin_unlock_irqrestore(&up->port.lock, flags);
-// restore_flags(flags);
- DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
-}
-
-static void serial8250_stop_tx(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
-
- if (up->ier & UART_IER_THRI) {
- up->ier &= ~UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
-static void serial8250_start_tx(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
-
- if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
-static void serial8250_stop_rx(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
-
- up->ier &= ~UART_IER_RLSI;
- up->port.read_status_mask &= ~UART_LSR_DR;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void serial8250_enable_ms(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
-
- up->ier |= UART_IER_MSI;
- serial_out(up, UART_IER, up->ier);
-}
-
-static void
-receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
-{
- struct tty_struct *tty = up->port.info->tty;
- unsigned char ch, flag;
- int max_count = 256;
-
- do {
- ch = serial_inp(up, UART_RX);
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
- UART_LSR_FE | UART_LSR_OE))) {
- /*
- * For statistics only
- */
- if (*status & UART_LSR_BI) {
- *status &= ~(UART_LSR_FE | UART_LSR_PE);
- up->port.icount.brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- goto ignore_char;
- } else if (*status & UART_LSR_PE)
- up->port.icount.parity++;
- else if (*status & UART_LSR_FE)
- up->port.icount.frame++;
- if (*status & UART_LSR_OE)
- up->port.icount.overrun++;
-
- /*
- * Mask off conditions which should be ingored.
- */
- *status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_AU1X00_CONSOLE
- if (up->port.line == up->port.cons->index) {
- /* Recover the break flag from console xmit */
- *status |= up->lsr_break_flag;
- up->lsr_break_flag = 0;
- }
-#endif
- if (*status & UART_LSR_BI) {
- DEBUG_INTR("handling break....");
- flag = TTY_BREAK;
- } else if (*status & UART_LSR_PE)
- flag = TTY_PARITY;
- else if (*status & UART_LSR_FE)
- flag = TTY_FRAME;
- }
- if (uart_handle_sysrq_char(&up->port, ch, regs))
- goto ignore_char;
- if ((*status & up->port.ignore_status_mask) == 0)
- tty_insert_flip_char(tty, ch, flag);
- if (*status & UART_LSR_OE)
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character.
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
- ignore_char:
- *status = serial_inp(up, UART_LSR);
- } while ((*status & UART_LSR_DR) && (max_count-- > 0));
- spin_unlock(&up->port.lock);
- tty_flip_buffer_push(tty);
- spin_lock(&up->port.lock);
-}
-
-static void transmit_chars(struct uart_8250_port *up)
-{
- struct circ_buf *xmit = &up->port.info->xmit;
- int count;
-
- if (up->port.x_char) {
- serial_outp(up, UART_TX, up->port.x_char);
- up->port.icount.tx++;
- up->port.x_char = 0;
- return;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
- serial8250_stop_tx(&up->port);
- return;
- }
-
- count = up->port.fifosize;
- do {
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- up->port.icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- DEBUG_INTR("THRE...");
-
- if (uart_circ_empty(xmit))
- serial8250_stop_tx(&up->port);
-}
-
-static void check_modem_status(struct uart_8250_port *up)
-{
- int status;
-
- status = serial_in(up, UART_MSR);
-
- if ((status & UART_MSR_ANY_DELTA) == 0)
- return;
-
- if (status & UART_MSR_TERI)
- up->port.icount.rng++;
- if (status & UART_MSR_DDSR)
- up->port.icount.dsr++;
- if (status & UART_MSR_DDCD)
- uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
- if (status & UART_MSR_DCTS)
- uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
- wake_up_interruptible(&up->port.info->delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static inline void
-serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
-{
- unsigned int status = serial_inp(up, UART_LSR);
-
- DEBUG_INTR("status = %x...", status);
-
- if (status & UART_LSR_DR)
- receive_chars(up, &status, regs);
- check_modem_status(up);
- if (status & UART_LSR_THRE)
- transmit_chars(up);
-}
-
-/*
- * This is the serial driver's interrupt routine.
- *
- * Arjan thinks the old way was overly complex, so it got simplified.
- * Alan disagrees, saying that need the complexity to handle the weird
- * nature of ISA shared interrupts. (This is a special exception.)
- *
- * In order to handle ISA shared interrupts properly, we need to check
- * that all ports have been serviced, and therefore the ISA interrupt
- * line has been de-asserted.
- *
- * This means we need to loop through all ports. checking that they
- * don't have an interrupt pending.
- */
-static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct irq_info *i = dev_id;
- struct list_head *l, *end = NULL;
- int pass_counter = 0;
-
- DEBUG_INTR("serial8250_interrupt(%d)...", irq);
-
- spin_lock(&i->lock);
-
- l = i->head;
- do {
- struct uart_8250_port *up;
- unsigned int iir;
-
- up = list_entry(l, struct uart_8250_port, list);
-
- iir = serial_in(up, UART_IIR);
- if (!(iir & UART_IIR_NO_INT)) {
- spin_lock(&up->port.lock);
- serial8250_handle_port(up, regs);
- spin_unlock(&up->port.lock);
-
- end = NULL;
- } else if (end == NULL)
- end = l;
-
- l = l->next;
-
- if (l == i->head && pass_counter++ > PASS_LIMIT) {
- /* If we hit this, we're dead. */
- printk(KERN_ERR "serial8250: too much work for "
- "irq%d\n", irq);
- break;
- }
- } while (l != end);
-
- spin_unlock(&i->lock);
-
- DEBUG_INTR("end.\n");
- /* FIXME! Was it really ours? */
- return IRQ_HANDLED;
-}
-
-/*
- * To support ISA shared interrupts, we need to have one interrupt
- * handler that ensures that the IRQ line has been deasserted
- * before returning. Failing to do this will result in the IRQ
- * line being stuck active, and, since ISA irqs are edge triggered,
- * no more IRQs will be seen.
- */
-static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
-{
- spin_lock_irq(&i->lock);
-
- if (!list_empty(i->head)) {
- if (i->head == &up->list)
- i->head = i->head->next;
- list_del(&up->list);
- } else {
- BUG_ON(i->head != &up->list);
- i->head = NULL;
- }
-
- spin_unlock_irq(&i->lock);
-}
-
-static int serial_link_irq_chain(struct uart_8250_port *up)
-{
- struct irq_info *i = irq_lists + up->port.irq;
- int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 0;
-
- spin_lock_irq(&i->lock);
-
- if (i->head) {
- list_add(&up->list, i->head);
- spin_unlock_irq(&i->lock);
-
- ret = 0;
- } else {
- INIT_LIST_HEAD(&up->list);
- i->head = &up->list;
- spin_unlock_irq(&i->lock);
-
- ret = request_irq(up->port.irq, serial8250_interrupt,
- irq_flags, "serial", i);
- if (ret < 0)
- serial_do_unlink(i, up);
- }
-
- return ret;
-}
-
-static void serial_unlink_irq_chain(struct uart_8250_port *up)
-{
- struct irq_info *i = irq_lists + up->port.irq;
-
- BUG_ON(i->head == NULL);
-
- if (list_empty(i->head))
- free_irq(up->port.irq, i);
-
- serial_do_unlink(i, up);
-}
-
-/*
- * This function is used to handle ports that do not have an
- * interrupt. This doesn't work very well for 16450's, but gives
- * barely passable results for a 16550A. (Although at the expense
- * of much CPU overhead).
- */
-static void serial8250_timeout(unsigned long data)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)data;
- unsigned int timeout;
- unsigned int iir;
-
- iir = serial_in(up, UART_IIR);
- if (!(iir & UART_IIR_NO_INT)) {
- spin_lock(&up->port.lock);
- serial8250_handle_port(up, NULL);
- spin_unlock(&up->port.lock);
- }
-
- timeout = up->port.timeout;
- timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
- mod_timer(&up->timer, jiffies + timeout);
-}
-
-static unsigned int serial8250_tx_empty(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned long flags;
- unsigned int ret;
-
- spin_lock_irqsave(&up->port.lock, flags);
- ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- return ret;
-}
-
-static unsigned int serial8250_get_mctrl(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned char status;
- unsigned int ret;
-
- status = serial_in(up, UART_MSR);
-
- ret = 0;
- if (status & UART_MSR_DCD)
- ret |= TIOCM_CAR;
- if (status & UART_MSR_RI)
- ret |= TIOCM_RNG;
- if (status & UART_MSR_DSR)
- ret |= TIOCM_DSR;
- if (status & UART_MSR_CTS)
- ret |= TIOCM_CTS;
- return ret;
-}
-
-static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned char mcr = 0;
-
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- mcr = (mcr & up->mcr_mask) | up->mcr_force;
-
- serial_out(up, UART_MCR, mcr);
-}
-
-static void serial8250_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (break_state == -1)
- up->lcr |= UART_LCR_SBC;
- else
- up->lcr &= ~UART_LCR_SBC;
- serial_out(up, UART_LCR, up->lcr);
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static int serial8250_startup(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned long flags;
- int retval;
-
- /*
- * Clear the FIFO buffers and disable them.
- * (they will be reeanbled in set_termios())
- */
- if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) {
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
- serial_outp(up, UART_FCR, 0);
- }
-
- /*
- * Clear the interrupt registers.
- */
- (void) serial_inp(up, UART_LSR);
- (void) serial_inp(up, UART_RX);
- (void) serial_inp(up, UART_IIR);
- (void) serial_inp(up, UART_MSR);
-
- /*
- * At this point, there's no way the LSR could still be 0xff;
- * if it is, then bail out, because there's likely no UART
- * here.
- */
- if (!(up->port.flags & UPF_BUGGY_UART) &&
- (serial_inp(up, UART_LSR) == 0xff)) {
- printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
- return -ENODEV;
- }
-
- retval = serial_link_irq_chain(up);
- if (retval)
- return retval;
-
- /*
- * Now, initialize the UART
- */
- serial_outp(up, UART_LCR, UART_LCR_WLEN8);
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (up->port.flags & UPF_FOURPORT) {
- if (!is_real_interrupt(up->port.irq))
- up->port.mctrl |= TIOCM_OUT1;
- } else
- /*
- * Most PC uarts need OUT2 raised to enable interrupts.
- */
- if (is_real_interrupt(up->port.irq))
- up->port.mctrl |= TIOCM_OUT2;
-
- serial8250_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Finally, enable interrupts. Note: Modem status interrupts
- * are set via set_termios(), which will be occurring imminently
- * anyway, so we don't enable them here.
- */
- up->ier = UART_IER_RLSI | UART_IER_RDI;
- serial_outp(up, UART_IER, up->ier);
-
- if (up->port.flags & UPF_FOURPORT) {
- unsigned int icp;
- /*
- * Enable interrupts on the AST Fourport board
- */
- icp = (up->port.iobase & 0xfe0) | 0x01f;
- outb_p(0x80, icp);
- (void) inb_p(icp);
- }
-
- /*
- * And clear the interrupt registers again for luck.
- */
- (void) serial_inp(up, UART_LSR);
- (void) serial_inp(up, UART_RX);
- (void) serial_inp(up, UART_IIR);
- (void) serial_inp(up, UART_MSR);
-
- return 0;
-}
-
-static void serial8250_shutdown(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned long flags;
-
- /*
- * Disable interrupts from this port
- */
- up->ier = 0;
- serial_outp(up, UART_IER, 0);
-
- spin_lock_irqsave(&up->port.lock, flags);
- if (up->port.flags & UPF_FOURPORT) {
- /* reset interrupts on the AST Fourport board */
- inb((up->port.iobase & 0xfe0) | 0x1f);
- up->port.mctrl |= TIOCM_OUT1;
- } else
- up->port.mctrl &= ~TIOCM_OUT2;
-
- serial8250_set_mctrl(&up->port, up->port.mctrl);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
- /*
- * Disable break condition and FIFOs
- */
- serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR |
- UART_FCR_CLEAR_XMIT);
- serial_outp(up, UART_FCR, 0);
-
- /*
- * Read data port to reset things, and then unlink from
- * the IRQ chain.
- */
- (void) serial_in(up, UART_RX);
-
- if (!is_real_interrupt(up->port.irq))
- del_timer_sync(&up->timer);
- else
- serial_unlink_irq_chain(up);
-}
-
-static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
-{
- unsigned int quot;
-
- /*
- * Handle magic divisors for baud rates above baud_base on
- * SMSC SuperIO chips.
- */
- if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
- baud == (port->uartclk/4))
- quot = 0x8001;
- else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
- baud == (port->uartclk/8))
- quot = 0x8002;
- else
- quot = uart_get_divisor(port, baud);
-
- return quot;
-}
-
-static void
-serial8250_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned char cval, fcr = 0;
- unsigned long flags;
- unsigned int baud, quot;
-
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- cval = UART_LCR_WLEN5;
- break;
- case CS6:
- cval = UART_LCR_WLEN6;
- break;
- case CS7:
- cval = UART_LCR_WLEN7;
- break;
- default:
- case CS8:
- cval = UART_LCR_WLEN8;
- break;
- }
-
- if (termios->c_cflag & CSTOPB)
- cval |= UART_LCR_STOP;
- if (termios->c_cflag & PARENB)
- cval |= UART_LCR_PARITY;
- if (!(termios->c_cflag & PARODD))
- cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
- if (termios->c_cflag & CMSPAR)
- cval |= UART_LCR_SPAR;
-#endif
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = serial8250_get_divisor(port, baud);
- quot = 0x35; /* FIXME */
-
- /*
- * Work around a bug in the Oxford Semiconductor 952 rev B
- * chip which causes it to seriously miscalculate baud rates
- * when DLL is 0.
- */
- if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 &&
- up->rev == 0x5201)
- quot ++;
-
- if (uart_config[up->port.type].flags & UART_USE_FIFO) {
- if (baud < 2400)
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_1;
- else
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_8;
- }
-
- /*
- * Ok, we're now changing the port state. Do it with
- * interrupts disabled.
- */
- spin_lock_irqsave(&up->port.lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
- if (termios->c_iflag & INPCK)
- up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (termios->c_iflag & (BRKINT | PARMRK))
- up->port.read_status_mask |= UART_LSR_BI;
-
- /*
- * Characteres to ignore
- */
- up->port.ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
- if (termios->c_iflag & IGNBRK) {
- up->port.ignore_status_mask |= UART_LSR_BI;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- up->port.ignore_status_mask |= UART_LSR_OE;
- }
-
- /*
- * ignore all characters if CREAD is not set
- */
- if ((termios->c_cflag & CREAD) == 0)
- up->port.ignore_status_mask |= UART_LSR_DR;
-
- /*
- * CTS flow control flag and modem status interrupts
- */
- up->ier &= ~UART_IER_MSI;
- if (UART_ENABLE_MS(&up->port, termios->c_cflag))
- up->ier |= UART_IER_MSI;
-
- serial_out(up, UART_IER, up->ier);
- serial_outp(up, 0x28, quot & 0xffff);
- up->lcr = cval; /* Save LCR */
- if (up->port.type != PORT_16750) {
- if (fcr & UART_FCR_ENABLE_FIFO) {
- /* emulated UARTs (Lucent Venus 167x) need two steps */
- serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- }
- serial_outp(up, UART_FCR, fcr); /* set fcr */
- }
- spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial8250_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- if (state) {
- /* sleep */
- if (up->pm)
- up->pm(port, state, oldstate);
- } else {
- /* wake */
- if (up->pm)
- up->pm(port, state, oldstate);
- }
-}
-
-/*
- * Resource handling. This is complicated by the fact that resources
- * depend on the port type. Maybe we should be claiming the standard
- * 8250 ports, and then trying to get other resources as necessary?
- */
-static int
-serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res)
-{
- unsigned int size = 8 << up->port.regshift;
- int ret = 0;
-
- switch (up->port.iotype) {
- case UPIO_MEM:
- if (up->port.mapbase) {
- *res = request_mem_region(up->port.mapbase, size, "serial");
- if (!*res)
- ret = -EBUSY;
- }
- break;
-
- case UPIO_HUB6:
- case UPIO_PORT:
- *res = request_region(up->port.iobase, size, "serial");
- if (!*res)
- ret = -EBUSY;
- break;
- }
- return ret;
-}
-
-
-static void serial8250_release_port(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned long start, offset = 0, size = 0;
-
- size <<= up->port.regshift;
-
- switch (up->port.iotype) {
- case UPIO_MEM:
- if (up->port.mapbase) {
- /*
- * Unmap the area.
- */
- iounmap(up->port.membase);
- up->port.membase = NULL;
-
- start = up->port.mapbase;
-
- if (size)
- release_mem_region(start + offset, size);
- release_mem_region(start, 8 << up->port.regshift);
- }
- break;
-
- case UPIO_HUB6:
- case UPIO_PORT:
- start = up->port.iobase;
-
- if (size)
- release_region(start + offset, size);
- release_region(start + offset, 8 << up->port.regshift);
- break;
-
- default:
- break;
- }
-}
-
-static int serial8250_request_port(struct uart_port *port)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- struct resource *res = NULL, *res_rsa = NULL;
- int ret = 0;
-
- ret = serial8250_request_std_resource(up, &res);
-
- /*
- * If we have a mapbase, then request that as well.
- */
- if (ret == 0 && up->port.flags & UPF_IOREMAP) {
- int size = res->end - res->start + 1;
-
- up->port.membase = ioremap(up->port.mapbase, size);
- if (!up->port.membase)
- ret = -ENOMEM;
- }
-
- if (ret < 0) {
- if (res_rsa)
- release_resource(res_rsa);
- if (res)
- release_resource(res);
- }
- return ret;
-}
-
-static void serial8250_config_port(struct uart_port *port, int flags)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
- struct resource *res_std = NULL, *res_rsa = NULL;
- int probeflags = PROBE_ANY;
-
- probeflags &= ~PROBE_RSA;
-
- if (flags & UART_CONFIG_TYPE)
- autoconfig(up, probeflags);
-
- /*
- * If the port wasn't an RSA port, release the resource.
- */
- if (up->port.type != PORT_RSA && res_rsa)
- release_resource(res_rsa);
-
- if (up->port.type == PORT_UNKNOWN && res_std)
- release_resource(res_std);
-}
-
-static int
-serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- if (ser->irq >= NR_IRQS || ser->irq < 0 ||
- ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
- ser->type > PORT_MAX_8250 || ser->type == PORT_CIRRUS ||
- ser->type == PORT_STARTECH)
- return -EINVAL;
- return 0;
-}
-
-static const char *
-serial8250_type(struct uart_port *port)
-{
- int type = port->type;
-
- if (type >= ARRAY_SIZE(uart_config))
- type = 0;
- return uart_config[type].name;
-}
-
-static struct uart_ops serial8250_pops = {
- .tx_empty = serial8250_tx_empty,
- .set_mctrl = serial8250_set_mctrl,
- .get_mctrl = serial8250_get_mctrl,
- .stop_tx = serial8250_stop_tx,
- .start_tx = serial8250_start_tx,
- .stop_rx = serial8250_stop_rx,
- .enable_ms = serial8250_enable_ms,
- .break_ctl = serial8250_break_ctl,
- .startup = serial8250_startup,
- .shutdown = serial8250_shutdown,
- .set_termios = serial8250_set_termios,
- .pm = serial8250_pm,
- .type = serial8250_type,
- .release_port = serial8250_release_port,
- .request_port = serial8250_request_port,
- .config_port = serial8250_config_port,
- .verify_port = serial8250_verify_port,
-};
-
-static struct uart_8250_port serial8250_ports[UART_NR];
-
-static void __init serial8250_isa_init_ports(void)
-{
- struct uart_8250_port *up;
- static int first = 1;
- int i;
-
- if (!first)
- return;
- first = 0;
-
- for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port);
- i++, up++) {
- up->port.iobase = old_serial_port[i].port;
- up->port.irq = old_serial_port[i].irq;
- up->port.uartclk = get_au1x00_uart_baud_base();
- up->port.flags = old_serial_port[i].flags;
- up->port.hub6 = old_serial_port[i].hub6;
- up->port.membase = old_serial_port[i].iomem_base;
- up->port.iotype = old_serial_port[i].io_type;
- up->port.regshift = old_serial_port[i].iomem_reg_shift;
- up->port.ops = &serial8250_pops;
- }
-}
-
-static void __init serial8250_register_ports(struct uart_driver *drv)
-{
- int i;
-
- serial8250_isa_init_ports();
-
- for (i = 0; i < UART_NR; i++) {
- struct uart_8250_port *up = &serial8250_ports[i];
-
- up->port.line = i;
- up->port.ops = &serial8250_pops;
- init_timer(&up->timer);
- up->timer.function = serial8250_timeout;
-
- /*
- * ALPHA_KLUDGE_MCR needs to be killed.
- */
- up->mcr_mask = ~ALPHA_KLUDGE_MCR;
- up->mcr_force = ALPHA_KLUDGE_MCR;
-
- uart_add_one_port(drv, &up->port);
- }
-}
-
-#ifdef CONFIG_SERIAL_AU1X00_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- * Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_8250_port *up)
-{
- unsigned int status, tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- do {
- status = serial_in(up, UART_LSR);
-
- if (status & UART_LSR_BI)
- up->lsr_break_flag = UART_LSR_BI;
-
- if (--tmout == 0)
- break;
- udelay(1);
- } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-
- /* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
- tmout = 1000000;
- while (--tmout &&
- ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
- udelay(1);
- }
-}
-
-static void au1x00_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_8250_port *up = (struct uart_8250_port *)port;
-
- wait_for_xmitr(up);
- serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- */
-static void
-serial8250_console_write(struct console *co, const char *s, unsigned int count)
-{
- struct uart_8250_port *up = &serial8250_ports[co->index];
- unsigned int ier;
-
- /*
- * First save the UER then disable the interrupts
- */
- ier = serial_in(up, UART_IER);
- serial_out(up, UART_IER, 0);
-
- uart_console_write(&up->port, s, count, au1x00_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up);
- serial_out(up, UART_IER, ier);
-}
-
-static int __init serial8250_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- /*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
- if (co->index >= UART_NR)
- co->index = 0;
- port = &serial8250_ports[co->index].port;
-
- /*
- * Temporary fix.
- */
- spin_lock_init(&port->lock);
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-extern struct uart_driver serial8250_reg;
-static struct console serial8250_console = {
- .name = "ttyS",
- .write = serial8250_console_write,
- .device = uart_console_device,
- .setup = serial8250_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
- .data = &serial8250_reg,
-};
-
-static int __init serial8250_console_init(void)
-{
- serial8250_isa_init_ports();
- register_console(&serial8250_console);
- return 0;
-}
-console_initcall(serial8250_console_init);
-
-#define SERIAL8250_CONSOLE &serial8250_console
-#else
-#define SERIAL8250_CONSOLE NULL
-#endif
-
-static struct uart_driver serial8250_reg = {
- .owner = THIS_MODULE,
- .driver_name = "serial",
- .devfs_name = "tts/",
- .dev_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
- .nr = UART_NR,
- .cons = SERIAL8250_CONSOLE,
-};
-
-int __init early_serial_setup(struct uart_port *port)
-{
- serial8250_isa_init_ports();
- serial8250_ports[port->line].port = *port;
- serial8250_ports[port->line].port.ops = &serial8250_pops;
- return 0;
-}
-
-/**
- * serial8250_suspend_port - suspend one serial port
- * @line: serial line number
- * @level: the level of port suspension, as per uart_suspend_port
- *
- * Suspend one serial port.
- */
-void serial8250_suspend_port(int line)
-{
- uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port);
-}
-
-/**
- * serial8250_resume_port - resume one serial port
- * @line: serial line number
- * @level: the level of port resumption, as per uart_resume_port
- *
- * Resume one serial port.
- */
-void serial8250_resume_port(int line)
-{
- uart_resume_port(&serial8250_reg, &serial8250_ports[line].port);
-}
-
-static int __init serial8250_init(void)
-{
- int ret, i;
-
- printk(KERN_INFO "Serial: Au1x00 driver\n");
-
- for (i = 0; i < NR_IRQS; i++)
- spin_lock_init(&irq_lists[i].lock);
-
- ret = uart_register_driver(&serial8250_reg);
- if (ret >= 0)
- serial8250_register_ports(&serial8250_reg);
-
- return ret;
-}
-
-static void __exit serial8250_exit(void)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++)
- uart_remove_one_port(&serial8250_reg, &serial8250_ports[i].port);
-
- uart_unregister_driver(&serial8250_reg);
-}
-
-module_init(serial8250_init);
-module_exit(serial8250_exit);
-
-EXPORT_SYMBOL(serial8250_suspend_port);
-EXPORT_SYMBOL(serial8250_resume_port);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Au1x00 serial driver\n");
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index a37579ce6d7..c620209d7b9 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (C) 2003-2006 Silicon Graphics, Inc. All Rights Reserved.
*/
@@ -323,9 +323,12 @@ static unsigned int Num_of_ioc4_cards;
#define IOC4_FIFO_CHARS 255
/* Device name we're using */
-#define DEVICE_NAME "ttyIOC"
-#define DEVICE_MAJOR 204
-#define DEVICE_MINOR 50
+#define DEVICE_NAME_RS232 "ttyIOC"
+#define DEVICE_NAME_RS422 "ttyAIOC"
+#define DEVICE_MAJOR 204
+#define DEVICE_MINOR_RS232 50
+#define DEVICE_MINOR_RS422 84
+
/* register offsets */
#define IOC4_SERIAL_OFFSET 0x300
@@ -341,10 +344,8 @@ static unsigned int Num_of_ioc4_cards;
#define MAX_BAUD_SUPPORTED 115200
/* protocol types supported */
-enum sio_proto {
- PROTO_RS232,
- PROTO_RS422
-};
+#define PROTO_RS232 3
+#define PROTO_RS422 7
/* Notification types */
#define N_DATA_READY 0x01
@@ -395,11 +396,17 @@ enum sio_proto {
/*
* This is the entry saved by the driver - one per card
*/
+
+#define UART_PORT_MIN 0
+#define UART_PORT_RS232 UART_PORT_MIN
+#define UART_PORT_RS422 1
+#define UART_PORT_COUNT 2 /* one for each mode */
+
struct ioc4_control {
int ic_irq;
struct {
- /* uart ports are allocated here */
- struct uart_port icp_uart_port;
+ /* uart ports are allocated here - 1 for rs232, 1 for rs422 */
+ struct uart_port icp_uart_port[UART_PORT_COUNT];
/* Handy reference material */
struct ioc4_port *icp_port;
} ic_port[IOC4_NUM_SERIAL_PORTS];
@@ -443,7 +450,9 @@ struct ioc4_soft {
/* Local port info for each IOC4 serial ports */
struct ioc4_port {
- struct uart_port *ip_port;
+ struct uart_port *ip_port; /* current active port ptr */
+ /* Ptrs for all ports */
+ struct uart_port *ip_all_ports[UART_PORT_COUNT];
/* Back ptrs for this port */
struct ioc4_control *ip_control;
struct pci_dev *ip_pdev;
@@ -502,6 +511,9 @@ struct ioc4_port {
#define DCD_ON 0x02
#define LOWAT_WRITTEN 0x04
#define READ_ABORTED 0x08
+#define PORT_ACTIVE 0x10
+#define PORT_INACTIVE 0 /* This is the value when "off" */
+
/* Since each port has different register offsets and bitmasks
* for everything, we'll store those that we need in tables so we
@@ -623,6 +635,23 @@ struct ring_buffer {
static void receive_chars(struct uart_port *);
static void handle_intr(void *arg, uint32_t sio_ir);
+/*
+ * port_is_active - determines if this port is currently active
+ * @port: ptr to soft struct for this port
+ * @uart_port: uart port to test for
+ */
+static inline int port_is_active(struct ioc4_port *port,
+ struct uart_port *uart_port)
+{
+ if (port) {
+ if ((port->ip_flags & PORT_ACTIVE)
+ && (port->ip_port == uart_port))
+ return 1;
+ }
+ return 0;
+}
+
+
/**
* write_ireg - write the interrupt regs
* @ioc4_soft: ptr to soft struct for this port
@@ -708,19 +737,33 @@ static int set_baud(struct ioc4_port *port, int baud)
/**
* get_ioc4_port - given a uart port, return the control structure
* @port: uart port
+ * @set: set this port as current
*/
-static struct ioc4_port *get_ioc4_port(struct uart_port *the_port)
+static struct ioc4_port *get_ioc4_port(struct uart_port *the_port, int set)
{
struct ioc4_driver_data *idd = dev_get_drvdata(the_port->dev);
struct ioc4_control *control = idd->idd_serial_data;
- int ii;
+ struct ioc4_port *port;
+ int port_num, port_type;
if (control) {
- for ( ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++ ) {
- if (!control->ic_port[ii].icp_port)
+ for ( port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS;
+ port_num++ ) {
+ port = control->ic_port[port_num].icp_port;
+ if (!port)
continue;
- if (the_port == control->ic_port[ii].icp_port->ip_port)
- return control->ic_port[ii].icp_port;
+ for (port_type = UART_PORT_MIN;
+ port_type < UART_PORT_COUNT;
+ port_type++) {
+ if (the_port == port->ip_all_ports
+ [port_type]) {
+ /* set local copy */
+ if (set) {
+ port->ip_port = the_port;
+ }
+ return port;
+ }
+ }
}
}
return NULL;
@@ -946,6 +989,7 @@ intr_connect(struct ioc4_soft *soft, int type,
* @arg: handler arg
* @regs: registers
*/
+
static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
{
struct ioc4_soft *soft;
@@ -953,7 +997,7 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
int xx, num_intrs = 0;
int intr_type;
int handled = 0;
- struct ioc4_intr_info *ii;
+ struct ioc4_intr_info *intr_info;
soft = arg;
for (intr_type = 0; intr_type < IOC4_NUM_INTR_TYPES; intr_type++) {
@@ -966,13 +1010,13 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
* which interrupt bits are set.
*/
for (xx = 0; xx < num_intrs; xx++) {
- ii = &soft->is_intr_type[intr_type].is_intr_info[xx];
- if ((this_mir = this_ir & ii->sd_bits)) {
+ intr_info = &soft->is_intr_type[intr_type].is_intr_info[xx];
+ if ((this_mir = this_ir & intr_info->sd_bits)) {
/* Disable owned interrupts, call handler */
handled++;
- write_ireg(soft, ii->sd_bits, IOC4_W_IEC,
+ write_ireg(soft, intr_info->sd_bits, IOC4_W_IEC,
intr_type);
- ii->sd_intr(ii->sd_info, this_mir);
+ intr_info->sd_intr(intr_info->sd_info, this_mir);
this_ir &= ~this_mir;
}
}
@@ -980,7 +1024,6 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
#ifdef DEBUG_INTERRUPTS
{
struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr;
- spinlock_t *lp = &soft->is_ir_lock;
unsigned long flag;
spin_lock_irqsave(&soft->is_ir_lock, flag);
@@ -1177,7 +1220,7 @@ static inline int local_open(struct ioc4_port *port)
{
int spiniter = 0;
- port->ip_flags = 0;
+ port->ip_flags = PORT_ACTIVE;
/* Pause the DMA interface if necessary */
if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
@@ -1187,6 +1230,7 @@ static inline int local_open(struct ioc4_port *port)
& IOC4_SSCR_PAUSE_STATE) == 0) {
spiniter++;
if (spiniter > MAXITER) {
+ port->ip_flags = PORT_INACTIVE;
return -1;
}
}
@@ -1506,14 +1550,13 @@ static int set_notification(struct ioc4_port *port, int mask, int set_on)
/**
* set_mcr - set the master control reg
* @the_port: port to use
- * @set: set ?
* @mask1: mcr mask
* @mask2: shadow mask
*/
-static inline int set_mcr(struct uart_port *the_port, int set,
+static inline int set_mcr(struct uart_port *the_port,
int mask1, int mask2)
{
- struct ioc4_port *port = get_ioc4_port(the_port);
+ struct ioc4_port *port = get_ioc4_port(the_port, 0);
uint32_t shadow;
int spiniter = 0;
char mcr;
@@ -1536,13 +1579,9 @@ static inline int set_mcr(struct uart_port *the_port, int set,
mcr = (shadow & 0xff000000) >> 24;
/* Set new value */
- if (set) {
- mcr |= mask1;
- shadow |= mask2;
- } else {
- mcr &= ~mask1;
- shadow &= ~mask2;
- }
+ mcr |= mask1;
+ shadow |= mask2;
+
writeb(mcr, &port->ip_uart_regs->i4u_mcr);
writel(shadow, &port->ip_serial_regs->shadow);
@@ -1558,7 +1597,7 @@ static inline int set_mcr(struct uart_port *the_port, int set,
* @port: port to use
* @proto: protocol to use
*/
-static int ioc4_set_proto(struct ioc4_port *port, enum sio_proto proto)
+static int ioc4_set_proto(struct ioc4_port *port, int proto)
{
struct hooks *hooks = port->ip_hooks;
@@ -1589,7 +1628,7 @@ static void transmit_chars(struct uart_port *the_port)
int result;
char *start;
struct tty_struct *tty;
- struct ioc4_port *port = get_ioc4_port(the_port);
+ struct ioc4_port *port = get_ioc4_port(the_port, 0);
struct uart_info *info;
if (!the_port)
@@ -1645,7 +1684,7 @@ static void
ioc4_change_speed(struct uart_port *the_port,
struct termios *new_termios, struct termios *old_termios)
{
- struct ioc4_port *port = get_ioc4_port(the_port);
+ struct ioc4_port *port = get_ioc4_port(the_port, 0);
int baud, bits;
unsigned cflag;
int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8;
@@ -1752,7 +1791,7 @@ static inline int ic4_startup_local(struct uart_port *the_port)
if (!the_port)
return -1;
- port = get_ioc4_port(the_port);
+ port = get_ioc4_port(the_port, 0);
if (!port)
return -1;
@@ -1760,6 +1799,9 @@ static inline int ic4_startup_local(struct uart_port *the_port)
local_open(port);
+ /* set the protocol - mapbase has the port type */
+ ioc4_set_proto(port, the_port->mapbase);
+
/* set the speed of the serial port */
ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0);
@@ -1768,17 +1810,17 @@ static inline int ic4_startup_local(struct uart_port *the_port)
/*
* ioc4_cb_output_lowat - called when the output low water mark is hit
- * @port: port to output
+ * @the_port: port to output
*/
-static void ioc4_cb_output_lowat(struct ioc4_port *port)
+static void ioc4_cb_output_lowat(struct uart_port *the_port)
{
unsigned long pflags;
/* ip_lock is set on the call here */
- if (port->ip_port) {
- spin_lock_irqsave(&port->ip_port->lock, pflags);
- transmit_chars(port->ip_port);
- spin_unlock_irqrestore(&port->ip_port->lock, pflags);
+ if (the_port) {
+ spin_lock_irqsave(&the_port->lock, pflags);
+ transmit_chars(the_port);
+ spin_unlock_irqrestore(&the_port->lock, pflags);
}
}
@@ -1923,7 +1965,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
&port->ip_mem->sio_ir.raw);
if (port->ip_notify & N_OUTPUT_LOWAT)
- ioc4_cb_output_lowat(port);
+ ioc4_cb_output_lowat(port->ip_port);
}
/* Handle tx_mt. Must come after tx_explicit. */
@@ -1936,7 +1978,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
* So send the notification now.
*/
if (port->ip_notify & N_OUTPUT_LOWAT) {
- ioc4_cb_output_lowat(port);
+ ioc4_cb_output_lowat(port->ip_port);
/* We need to reload the sio_ir since the lowat
* call may have caused another write to occur,
@@ -2023,7 +2065,7 @@ static inline int do_read(struct uart_port *the_port, unsigned char *buf,
int len)
{
int prod_ptr, cons_ptr, total;
- struct ioc4_port *port = get_ioc4_port(the_port);
+ struct ioc4_port *port = get_ioc4_port(the_port, 0);
struct ring *inring;
struct ring_entry *entry;
struct hooks *hooks = port->ip_hooks;
@@ -2335,17 +2377,27 @@ static void receive_chars(struct uart_port *the_port)
*/
static const char *ic4_type(struct uart_port *the_port)
{
- return "SGI IOC4 Serial";
+ if (the_port->mapbase == PROTO_RS232)
+ return "SGI IOC4 Serial [rs232]";
+ else
+ return "SGI IOC4 Serial [rs422]";
}
/**
- * ic4_tx_empty - Is the transmitter empty? We pretend we're always empty
- * @port: Port to operate on (we ignore since we always return 1)
+ * ic4_tx_empty - Is the transmitter empty?
+ * @port: Port to operate on
*
*/
static unsigned int ic4_tx_empty(struct uart_port *the_port)
{
- return 1;
+ struct ioc4_port *port = get_ioc4_port(the_port, 0);
+ unsigned int ret = 0;
+
+ if (port_is_active(port, the_port)) {
+ if (readl(&port->ip_serial_regs->shadow) & IOC4_SHADOW_TEMT)
+ ret = TIOCSER_TEMT;
+ }
+ return ret;
}
/**
@@ -2355,6 +2407,10 @@ static unsigned int ic4_tx_empty(struct uart_port *the_port)
*/
static void ic4_stop_tx(struct uart_port *the_port)
{
+ struct ioc4_port *port = get_ioc4_port(the_port, 0);
+
+ if (port_is_active(port, the_port))
+ set_notification(port, N_OUTPUT_LOWAT, 0);
}
/**
@@ -2377,11 +2433,12 @@ static void ic4_shutdown(struct uart_port *the_port)
struct ioc4_port *port;
struct uart_info *info;
- port = get_ioc4_port(the_port);
+ port = get_ioc4_port(the_port, 0);
if (!port)
return;
info = the_port->info;
+ port->ip_port = NULL;
wake_up_interruptible(&info->delta_msr_wait);
@@ -2390,6 +2447,7 @@ static void ic4_shutdown(struct uart_port *the_port)
spin_lock_irqsave(&the_port->lock, port_flags);
set_notification(port, N_ALL, 0);
+ port->ip_flags = PORT_INACTIVE;
spin_unlock_irqrestore(&the_port->lock, port_flags);
}
@@ -2402,6 +2460,11 @@ static void ic4_shutdown(struct uart_port *the_port)
static void ic4_set_mctrl(struct uart_port *the_port, unsigned int mctrl)
{
unsigned char mcr = 0;
+ struct ioc4_port *port;
+
+ port = get_ioc4_port(the_port, 0);
+ if (!port_is_active(port, the_port))
+ return;
if (mctrl & TIOCM_RTS)
mcr |= UART_MCR_RTS;
@@ -2414,7 +2477,7 @@ static void ic4_set_mctrl(struct uart_port *the_port, unsigned int mctrl)
if (mctrl & TIOCM_LOOP)
mcr |= UART_MCR_LOOP;
- set_mcr(the_port, 1, mcr, IOC4_SHADOW_DTR);
+ set_mcr(the_port, mcr, IOC4_SHADOW_DTR);
}
/**
@@ -2424,11 +2487,11 @@ static void ic4_set_mctrl(struct uart_port *the_port, unsigned int mctrl)
*/
static unsigned int ic4_get_mctrl(struct uart_port *the_port)
{
- struct ioc4_port *port = get_ioc4_port(the_port);
+ struct ioc4_port *port = get_ioc4_port(the_port, 0);
uint32_t shadow;
unsigned int ret = 0;
- if (!port)
+ if (!port_is_active(port, the_port))
return 0;
shadow = readl(&port->ip_serial_regs->shadow);
@@ -2448,9 +2511,9 @@ static unsigned int ic4_get_mctrl(struct uart_port *the_port)
*/
static void ic4_start_tx(struct uart_port *the_port)
{
- struct ioc4_port *port = get_ioc4_port(the_port);
+ struct ioc4_port *port = get_ioc4_port(the_port, 0);
- if (port) {
+ if (port_is_active(port, the_port)) {
set_notification(port, N_OUTPUT_LOWAT, 1);
enable_intrs(port, port->ip_hooks->intr_tx_mt);
}
@@ -2467,7 +2530,7 @@ static void ic4_break_ctl(struct uart_port *the_port, int break_state)
}
/**
- * ic4_startup - Start up the serial port - always return 0 (We're always on)
+ * ic4_startup - Start up the serial port
* @port: Port to operate on
*
*/
@@ -2479,17 +2542,16 @@ static int ic4_startup(struct uart_port *the_port)
struct uart_info *info;
unsigned long port_flags;
- if (!the_port) {
+ if (!the_port)
return -ENODEV;
- }
- port = get_ioc4_port(the_port);
- if (!port) {
+ port = get_ioc4_port(the_port, 1);
+ if (!port)
return -ENODEV;
- }
info = the_port->info;
control = port->ip_control;
if (!control) {
+ port->ip_port = NULL;
return -ENODEV;
}
@@ -2551,28 +2613,104 @@ static struct uart_ops ioc4_ops = {
* Boot-time initialization code
*/
-static struct uart_driver ioc4_uart = {
+static struct uart_driver ioc4_uart_rs232 = {
.owner = THIS_MODULE,
- .driver_name = "ioc4_serial",
- .dev_name = DEVICE_NAME,
+ .driver_name = "ioc4_serial_rs232",
+ .dev_name = DEVICE_NAME_RS232,
.major = DEVICE_MAJOR,
- .minor = DEVICE_MINOR,
+ .minor = DEVICE_MINOR_RS232,
.nr = IOC4_NUM_CARDS * IOC4_NUM_SERIAL_PORTS,
};
+static struct uart_driver ioc4_uart_rs422 = {
+ .owner = THIS_MODULE,
+ .driver_name = "ioc4_serial_rs422",
+ .dev_name = DEVICE_NAME_RS422,
+ .major = DEVICE_MAJOR,
+ .minor = DEVICE_MINOR_RS422,
+ .nr = IOC4_NUM_CARDS * IOC4_NUM_SERIAL_PORTS,
+};
+
+
/**
- * ioc4_serial_core_attach - register with serial core
+ * ioc4_serial_remove_one - detach function
+ *
+ * @idd: IOC4 master module data for this IOC4
+ */
+
+static int ioc4_serial_remove_one(struct ioc4_driver_data *idd)
+{
+ int port_num, port_type;
+ struct ioc4_control *control;
+ struct uart_port *the_port;
+ struct ioc4_port *port;
+ struct ioc4_soft *soft;
+
+ control = idd->idd_serial_data;
+
+ for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) {
+ for (port_type = UART_PORT_MIN;
+ port_type < UART_PORT_COUNT;
+ port_type++) {
+ the_port = &control->ic_port[port_num].icp_uart_port
+ [port_type];
+ if (the_port) {
+ switch (port_type) {
+ case UART_PORT_RS422:
+ uart_remove_one_port(&ioc4_uart_rs422,
+ the_port);
+ break;
+ default:
+ case UART_PORT_RS232:
+ uart_remove_one_port(&ioc4_uart_rs232,
+ the_port);
+ break;
+ }
+ }
+ }
+ port = control->ic_port[port_num].icp_port;
+ /* we allocate in pairs */
+ if (!(port_num & 1) && port) {
+ pci_free_consistent(port->ip_pdev,
+ TOTAL_RING_BUF_SIZE,
+ port->ip_cpu_ringbuf,
+ port->ip_dma_ringbuf);
+ kfree(port);
+ }
+ }
+ soft = control->ic_soft;
+ if (soft) {
+ free_irq(control->ic_irq, soft);
+ if (soft->is_ioc4_serial_addr) {
+ release_region((unsigned long)
+ soft->is_ioc4_serial_addr,
+ sizeof(struct ioc4_serial));
+ }
+ kfree(soft);
+ }
+ kfree(control);
+ idd->idd_serial_data = NULL;
+
+ return 0;
+}
+
+
+/**
+ * ioc4_serial_core_attach_rs232 - register with serial core
* This is done during pci probing
* @pdev: handle for this card
*/
static inline int
-ioc4_serial_core_attach(struct pci_dev *pdev)
+ioc4_serial_core_attach(struct pci_dev *pdev, int port_type)
{
struct ioc4_port *port;
struct uart_port *the_port;
struct ioc4_driver_data *idd = pci_get_drvdata(pdev);
struct ioc4_control *control = idd->idd_serial_data;
- int ii;
+ int port_num;
+ int port_type_idx;
+ struct uart_driver *u_driver;
+
DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n",
__FUNCTION__, pdev, (void *)control));
@@ -2580,28 +2718,36 @@ ioc4_serial_core_attach(struct pci_dev *pdev)
if (!control)
return -ENODEV;
+ port_type_idx = (port_type == PROTO_RS232) ? UART_PORT_RS232
+ : UART_PORT_RS422;
+
+ u_driver = (port_type == PROTO_RS232) ? &ioc4_uart_rs232
+ : &ioc4_uart_rs422;
+
/* once around for each port on this card */
- for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) {
- the_port = &control->ic_port[ii].icp_uart_port;
- port = control->ic_port[ii].icp_port;
- port->ip_port = the_port;
+ for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) {
+ the_port = &control->ic_port[port_num].icp_uart_port
+ [port_type_idx];
+ port = control->ic_port[port_num].icp_port;
+ port->ip_all_ports[port_type_idx] = the_port;
- DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p\n",
+ DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p : type %s\n",
__FUNCTION__, (void *)the_port,
- (void *)port));
+ (void *)port,
+ port_type == PROTO_RS232 ? "rs232" : "rs422"));
/* membase, iobase and mapbase just need to be non-0 */
the_port->membase = (unsigned char __iomem *)1;
- the_port->iobase = (pdev->bus->number << 16) | ii;
- the_port->line = (Num_of_ioc4_cards << 2) | ii;
- the_port->mapbase = 1;
+ the_port->iobase = (pdev->bus->number << 16) | port_num;
+ the_port->line = (Num_of_ioc4_cards << 2) | port_num;
+ the_port->mapbase = port_type;
the_port->type = PORT_16550A;
the_port->fifosize = IOC4_FIFO_CHARS;
the_port->ops = &ioc4_ops;
the_port->irq = control->ic_irq;
the_port->dev = &pdev->dev;
spin_lock_init(&the_port->lock);
- if (uart_add_one_port(&ioc4_uart, the_port) < 0) {
+ if (uart_add_one_port(u_driver, the_port) < 0) {
printk(KERN_WARNING
"%s: unable to add port %d bus %d\n",
__FUNCTION__, the_port->line, pdev->bus->number);
@@ -2610,8 +2756,6 @@ ioc4_serial_core_attach(struct pci_dev *pdev)
("IOC4 serial port %d irq = %d, bus %d\n",
the_port->line, the_port->irq, pdev->bus->number));
}
- /* all ports are rs232 for now */
- ioc4_set_proto(port, PROTO_RS232);
}
return 0;
}
@@ -2631,7 +2775,8 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
int ret = 0;
- DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev, idd->idd_pci_id));
+ DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev,
+ idd->idd_pci_id));
/* request serial registers */
tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET;
@@ -2653,11 +2798,11 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
goto out2;
}
DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n",
- __FUNCTION__, (void *)idd->idd_misc_regs, (void *)serial));
+ __FUNCTION__, (void *)idd->idd_misc_regs,
+ (void *)serial));
/* Get memory for the new card */
- control = kmalloc(sizeof(struct ioc4_control) * IOC4_NUM_SERIAL_PORTS,
- GFP_KERNEL);
+ control = kmalloc(sizeof(struct ioc4_control), GFP_KERNEL);
if (!control) {
printk(KERN_WARNING "ioc4_attach_one"
@@ -2702,7 +2847,7 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
/* Hook up interrupt handler */
if (!request_irq(idd->idd_pdev->irq, ioc4_intr, SA_SHIRQ,
- "sgi-ioc4serial", (void *)soft)) {
+ "sgi-ioc4serial", soft)) {
control->ic_irq = idd->idd_pdev->irq;
} else {
printk(KERN_WARNING
@@ -2713,16 +2858,21 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
if (ret)
goto out4;
- /* register port with the serial core */
+ /* register port with the serial core - 1 rs232, 1 rs422 */
- if ((ret = ioc4_serial_core_attach(idd->idd_pdev)))
+ if ((ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS232)))
goto out4;
+ if ((ret = ioc4_serial_core_attach(idd->idd_pdev, PROTO_RS422)))
+ goto out5;
+
Num_of_ioc4_cards++;
return ret;
/* error exits that give back resources */
+out5:
+ ioc4_serial_remove_one(idd);
out4:
kfree(soft);
out3:
@@ -2735,52 +2885,6 @@ out1:
}
-/**
- * ioc4_serial_remove_one - detach function
- *
- * @idd: IOC4 master module data for this IOC4
- */
-
-int ioc4_serial_remove_one(struct ioc4_driver_data *idd)
-{
- int ii;
- struct ioc4_control *control;
- struct uart_port *the_port;
- struct ioc4_port *port;
- struct ioc4_soft *soft;
-
- control = idd->idd_serial_data;
-
- for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) {
- the_port = &control->ic_port[ii].icp_uart_port;
- if (the_port) {
- uart_remove_one_port(&ioc4_uart, the_port);
- }
- port = control->ic_port[ii].icp_port;
- if (!(ii & 1) && port) {
- pci_free_consistent(port->ip_pdev,
- TOTAL_RING_BUF_SIZE,
- (void *)port->ip_cpu_ringbuf,
- port->ip_dma_ringbuf);
- kfree(port);
- }
- }
- soft = control->ic_soft;
- if (soft) {
- free_irq(control->ic_irq, (void *)soft);
- if (soft->is_ioc4_serial_addr) {
- release_region((unsigned long)
- soft->is_ioc4_serial_addr,
- sizeof(struct ioc4_serial));
- }
- kfree(soft);
- }
- kfree(control);
- idd->idd_serial_data = NULL;
-
- return 0;
-}
-
static struct ioc4_submodule ioc4_serial_submodule = {
.is_name = "IOC4_serial",
.is_owner = THIS_MODULE,
@@ -2796,9 +2900,15 @@ int ioc4_serial_init(void)
int ret;
/* register with serial core */
- if ((ret = uart_register_driver(&ioc4_uart)) < 0) {
+ if ((ret = uart_register_driver(&ioc4_uart_rs232)) < 0) {
+ printk(KERN_WARNING
+ "%s: Couldn't register rs232 IOC4 serial driver\n",
+ __FUNCTION__);
+ return ret;
+ }
+ if ((ret = uart_register_driver(&ioc4_uart_rs422)) < 0) {
printk(KERN_WARNING
- "%s: Couldn't register IOC4 serial driver\n",
+ "%s: Couldn't register rs422 IOC4 serial driver\n",
__FUNCTION__);
return ret;
}
@@ -2810,7 +2920,8 @@ int ioc4_serial_init(void)
static void __devexit ioc4_serial_exit(void)
{
ioc4_unregister_submodule(&ioc4_serial_submodule);
- uart_unregister_driver(&ioc4_uart);
+ uart_unregister_driver(&ioc4_uart_rs232);
+ uart_unregister_driver(&ioc4_uart_rs422);
}
module_init(ioc4_serial_init);
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 928e6cf12dc..6459edc7f5c 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -40,7 +40,7 @@
* and so on). So the PSC1 is mapped to /dev/ttyPSC0, PSC2 to /dev/ttyPSC1 and
* so on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly
* fpr the console code : without this 1:1 mapping, at early boot time, when we
- * are parsing the kernel args console=ttyPSC?, we wouldn't know wich PSC it
+ * are parsing the kernel args console=ttyPSC?, we wouldn't know which PSC it
* will be mapped to.
*/
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index 0ca83ac31d0..94681922ea0 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -1,6 +1,4 @@
/*
- * drivers/serial/mpsc.c
- *
* Generic driver for the MPSC (UART mode) on Marvell parts (e.g., GT64240,
* GT64260, MV64340, MV64360, GT96100, ... ).
*
@@ -52,9 +50,263 @@
* 4) AFAICT, hardware flow control isn't supported by the controller --MAG.
*/
+#include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/mv643xx.h>
#include <linux/platform_device.h>
-#include "mpsc.h"
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#define MPSC_NUM_CTLRS 2
+
+/*
+ * Descriptors and buffers must be cache line aligned.
+ * Buffers lengths must be multiple of cache line size.
+ * Number of Tx & Rx descriptors must be powers of 2.
+ */
+#define MPSC_RXR_ENTRIES 32
+#define MPSC_RXRE_SIZE dma_get_cache_alignment()
+#define MPSC_RXR_SIZE (MPSC_RXR_ENTRIES * MPSC_RXRE_SIZE)
+#define MPSC_RXBE_SIZE dma_get_cache_alignment()
+#define MPSC_RXB_SIZE (MPSC_RXR_ENTRIES * MPSC_RXBE_SIZE)
+
+#define MPSC_TXR_ENTRIES 32
+#define MPSC_TXRE_SIZE dma_get_cache_alignment()
+#define MPSC_TXR_SIZE (MPSC_TXR_ENTRIES * MPSC_TXRE_SIZE)
+#define MPSC_TXBE_SIZE dma_get_cache_alignment()
+#define MPSC_TXB_SIZE (MPSC_TXR_ENTRIES * MPSC_TXBE_SIZE)
+
+#define MPSC_DMA_ALLOC_SIZE (MPSC_RXR_SIZE + MPSC_RXB_SIZE + \
+ MPSC_TXR_SIZE + MPSC_TXB_SIZE + \
+ dma_get_cache_alignment() /* for alignment */)
+
+/* Rx and Tx Ring entry descriptors -- assume entry size is <= cacheline size */
+struct mpsc_rx_desc {
+ u16 bufsize;
+ u16 bytecnt;
+ u32 cmdstat;
+ u32 link;
+ u32 buf_ptr;
+} __attribute((packed));
+
+struct mpsc_tx_desc {
+ u16 bytecnt;
+ u16 shadow;
+ u32 cmdstat;
+ u32 link;
+ u32 buf_ptr;
+} __attribute((packed));
+
+/*
+ * Some regs that have the erratum that you can't read them are are shared
+ * between the two MPSC controllers. This struct contains those shared regs.
+ */
+struct mpsc_shared_regs {
+ phys_addr_t mpsc_routing_base_p;
+ phys_addr_t sdma_intr_base_p;
+
+ void __iomem *mpsc_routing_base;
+ void __iomem *sdma_intr_base;
+
+ u32 MPSC_MRR_m;
+ u32 MPSC_RCRR_m;
+ u32 MPSC_TCRR_m;
+ u32 SDMA_INTR_CAUSE_m;
+ u32 SDMA_INTR_MASK_m;
+};
+
+/* The main driver data structure */
+struct mpsc_port_info {
+ struct uart_port port; /* Overlay uart_port structure */
+
+ /* Internal driver state for this ctlr */
+ u8 ready;
+ u8 rcv_data;
+ tcflag_t c_iflag; /* save termios->c_iflag */
+ tcflag_t c_cflag; /* save termios->c_cflag */
+
+ /* Info passed in from platform */
+ u8 mirror_regs; /* Need to mirror regs? */
+ u8 cache_mgmt; /* Need manual cache mgmt? */
+ u8 brg_can_tune; /* BRG has baud tuning? */
+ u32 brg_clk_src;
+ u16 mpsc_max_idle;
+ int default_baud;
+ int default_bits;
+ int default_parity;
+ int default_flow;
+
+ /* Physical addresses of various blocks of registers (from platform) */
+ phys_addr_t mpsc_base_p;
+ phys_addr_t sdma_base_p;
+ phys_addr_t brg_base_p;
+
+ /* Virtual addresses of various blocks of registers (from platform) */
+ void __iomem *mpsc_base;
+ void __iomem *sdma_base;
+ void __iomem *brg_base;
+
+ /* Descriptor ring and buffer allocations */
+ void *dma_region;
+ dma_addr_t dma_region_p;
+
+ dma_addr_t rxr; /* Rx descriptor ring */
+ dma_addr_t rxr_p; /* Phys addr of rxr */
+ u8 *rxb; /* Rx Ring I/O buf */
+ u8 *rxb_p; /* Phys addr of rxb */
+ u32 rxr_posn; /* First desc w/ Rx data */
+
+ dma_addr_t txr; /* Tx descriptor ring */
+ dma_addr_t txr_p; /* Phys addr of txr */
+ u8 *txb; /* Tx Ring I/O buf */
+ u8 *txb_p; /* Phys addr of txb */
+ int txr_head; /* Where new data goes */
+ int txr_tail; /* Where sent data comes off */
+
+ /* Mirrored values of regs we can't read (if 'mirror_regs' set) */
+ u32 MPSC_MPCR_m;
+ u32 MPSC_CHR_1_m;
+ u32 MPSC_CHR_2_m;
+ u32 MPSC_CHR_10_m;
+ u32 BRG_BCR_m;
+ struct mpsc_shared_regs *shared_regs;
+};
+
+/* Hooks to platform-specific code */
+int mpsc_platform_register_driver(void);
+void mpsc_platform_unregister_driver(void);
+
+/* Hooks back in to mpsc common to be called by platform-specific code */
+struct mpsc_port_info *mpsc_device_probe(int index);
+struct mpsc_port_info *mpsc_device_remove(int index);
+
+/* Main MPSC Configuration Register Offsets */
+#define MPSC_MMCRL 0x0000
+#define MPSC_MMCRH 0x0004
+#define MPSC_MPCR 0x0008
+#define MPSC_CHR_1 0x000c
+#define MPSC_CHR_2 0x0010
+#define MPSC_CHR_3 0x0014
+#define MPSC_CHR_4 0x0018
+#define MPSC_CHR_5 0x001c
+#define MPSC_CHR_6 0x0020
+#define MPSC_CHR_7 0x0024
+#define MPSC_CHR_8 0x0028
+#define MPSC_CHR_9 0x002c
+#define MPSC_CHR_10 0x0030
+#define MPSC_CHR_11 0x0034
+
+#define MPSC_MPCR_FRZ (1 << 9)
+#define MPSC_MPCR_CL_5 0
+#define MPSC_MPCR_CL_6 1
+#define MPSC_MPCR_CL_7 2
+#define MPSC_MPCR_CL_8 3
+#define MPSC_MPCR_SBL_1 0
+#define MPSC_MPCR_SBL_2 1
+
+#define MPSC_CHR_2_TEV (1<<1)
+#define MPSC_CHR_2_TA (1<<7)
+#define MPSC_CHR_2_TTCS (1<<9)
+#define MPSC_CHR_2_REV (1<<17)
+#define MPSC_CHR_2_RA (1<<23)
+#define MPSC_CHR_2_CRD (1<<25)
+#define MPSC_CHR_2_EH (1<<31)
+#define MPSC_CHR_2_PAR_ODD 0
+#define MPSC_CHR_2_PAR_SPACE 1
+#define MPSC_CHR_2_PAR_EVEN 2
+#define MPSC_CHR_2_PAR_MARK 3
+
+/* MPSC Signal Routing */
+#define MPSC_MRR 0x0000
+#define MPSC_RCRR 0x0004
+#define MPSC_TCRR 0x0008
+
+/* Serial DMA Controller Interface Registers */
+#define SDMA_SDC 0x0000
+#define SDMA_SDCM 0x0008
+#define SDMA_RX_DESC 0x0800
+#define SDMA_RX_BUF_PTR 0x0808
+#define SDMA_SCRDP 0x0810
+#define SDMA_TX_DESC 0x0c00
+#define SDMA_SCTDP 0x0c10
+#define SDMA_SFTDP 0x0c14
+
+#define SDMA_DESC_CMDSTAT_PE (1<<0)
+#define SDMA_DESC_CMDSTAT_CDL (1<<1)
+#define SDMA_DESC_CMDSTAT_FR (1<<3)
+#define SDMA_DESC_CMDSTAT_OR (1<<6)
+#define SDMA_DESC_CMDSTAT_BR (1<<9)
+#define SDMA_DESC_CMDSTAT_MI (1<<10)
+#define SDMA_DESC_CMDSTAT_A (1<<11)
+#define SDMA_DESC_CMDSTAT_AM (1<<12)
+#define SDMA_DESC_CMDSTAT_CT (1<<13)
+#define SDMA_DESC_CMDSTAT_C (1<<14)
+#define SDMA_DESC_CMDSTAT_ES (1<<15)
+#define SDMA_DESC_CMDSTAT_L (1<<16)
+#define SDMA_DESC_CMDSTAT_F (1<<17)
+#define SDMA_DESC_CMDSTAT_P (1<<18)
+#define SDMA_DESC_CMDSTAT_EI (1<<23)
+#define SDMA_DESC_CMDSTAT_O (1<<31)
+
+#define SDMA_DESC_DFLT (SDMA_DESC_CMDSTAT_O | \
+ SDMA_DESC_CMDSTAT_EI)
+
+#define SDMA_SDC_RFT (1<<0)
+#define SDMA_SDC_SFM (1<<1)
+#define SDMA_SDC_BLMR (1<<6)
+#define SDMA_SDC_BLMT (1<<7)
+#define SDMA_SDC_POVR (1<<8)
+#define SDMA_SDC_RIFB (1<<9)
+
+#define SDMA_SDCM_ERD (1<<7)
+#define SDMA_SDCM_AR (1<<15)
+#define SDMA_SDCM_STD (1<<16)
+#define SDMA_SDCM_TXD (1<<23)
+#define SDMA_SDCM_AT (1<<31)
+
+#define SDMA_0_CAUSE_RXBUF (1<<0)
+#define SDMA_0_CAUSE_RXERR (1<<1)
+#define SDMA_0_CAUSE_TXBUF (1<<2)
+#define SDMA_0_CAUSE_TXEND (1<<3)
+#define SDMA_1_CAUSE_RXBUF (1<<8)
+#define SDMA_1_CAUSE_RXERR (1<<9)
+#define SDMA_1_CAUSE_TXBUF (1<<10)
+#define SDMA_1_CAUSE_TXEND (1<<11)
+
+#define SDMA_CAUSE_RX_MASK (SDMA_0_CAUSE_RXBUF | SDMA_0_CAUSE_RXERR | \
+ SDMA_1_CAUSE_RXBUF | SDMA_1_CAUSE_RXERR)
+#define SDMA_CAUSE_TX_MASK (SDMA_0_CAUSE_TXBUF | SDMA_0_CAUSE_TXEND | \
+ SDMA_1_CAUSE_TXBUF | SDMA_1_CAUSE_TXEND)
+
+/* SDMA Interrupt registers */
+#define SDMA_INTR_CAUSE 0x0000
+#define SDMA_INTR_MASK 0x0080
+
+/* Baud Rate Generator Interface Registers */
+#define BRG_BCR 0x0000
+#define BRG_BTR 0x0004
/*
* Define how this driver is known to the outside (we've been assigned a
@@ -1165,7 +1417,7 @@ mpsc_startup(struct uart_port *port)
flag = SA_SHIRQ;
if (request_irq(pi->port.irq, mpsc_sdma_intr, flag,
- "mpsc/sdma", pi))
+ "mpsc-sdma", pi))
printk(KERN_ERR "MPSC: Can't get SDMA IRQ %d\n",
pi->port.irq);
diff --git a/drivers/serial/mpsc.h b/drivers/serial/mpsc.h
deleted file mode 100644
index 678dbcf06c8..00000000000
--- a/drivers/serial/mpsc.h
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * drivers/serial/mpsc.h
- *
- * Author: Mark A. Greer <mgreer@mvista.com>
- *
- * 2004 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __MPSC_H__
-#define __MPSC_H__
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/mv643xx.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#define MPSC_NUM_CTLRS 2
-
-/*
- * Descriptors and buffers must be cache line aligned.
- * Buffers lengths must be multiple of cache line size.
- * Number of Tx & Rx descriptors must be powers of 2.
- */
-#define MPSC_RXR_ENTRIES 32
-#define MPSC_RXRE_SIZE dma_get_cache_alignment()
-#define MPSC_RXR_SIZE (MPSC_RXR_ENTRIES * MPSC_RXRE_SIZE)
-#define MPSC_RXBE_SIZE dma_get_cache_alignment()
-#define MPSC_RXB_SIZE (MPSC_RXR_ENTRIES * MPSC_RXBE_SIZE)
-
-#define MPSC_TXR_ENTRIES 32
-#define MPSC_TXRE_SIZE dma_get_cache_alignment()
-#define MPSC_TXR_SIZE (MPSC_TXR_ENTRIES * MPSC_TXRE_SIZE)
-#define MPSC_TXBE_SIZE dma_get_cache_alignment()
-#define MPSC_TXB_SIZE (MPSC_TXR_ENTRIES * MPSC_TXBE_SIZE)
-
-#define MPSC_DMA_ALLOC_SIZE (MPSC_RXR_SIZE + MPSC_RXB_SIZE + \
- MPSC_TXR_SIZE + MPSC_TXB_SIZE + \
- dma_get_cache_alignment() /* for alignment */)
-
-/* Rx and Tx Ring entry descriptors -- assume entry size is <= cacheline size */
-struct mpsc_rx_desc {
- u16 bufsize;
- u16 bytecnt;
- u32 cmdstat;
- u32 link;
- u32 buf_ptr;
-} __attribute((packed));
-
-struct mpsc_tx_desc {
- u16 bytecnt;
- u16 shadow;
- u32 cmdstat;
- u32 link;
- u32 buf_ptr;
-} __attribute((packed));
-
-/*
- * Some regs that have the erratum that you can't read them are are shared
- * between the two MPSC controllers. This struct contains those shared regs.
- */
-struct mpsc_shared_regs {
- phys_addr_t mpsc_routing_base_p;
- phys_addr_t sdma_intr_base_p;
-
- void __iomem *mpsc_routing_base;
- void __iomem *sdma_intr_base;
-
- u32 MPSC_MRR_m;
- u32 MPSC_RCRR_m;
- u32 MPSC_TCRR_m;
- u32 SDMA_INTR_CAUSE_m;
- u32 SDMA_INTR_MASK_m;
-};
-
-/* The main driver data structure */
-struct mpsc_port_info {
- struct uart_port port; /* Overlay uart_port structure */
-
- /* Internal driver state for this ctlr */
- u8 ready;
- u8 rcv_data;
- tcflag_t c_iflag; /* save termios->c_iflag */
- tcflag_t c_cflag; /* save termios->c_cflag */
-
- /* Info passed in from platform */
- u8 mirror_regs; /* Need to mirror regs? */
- u8 cache_mgmt; /* Need manual cache mgmt? */
- u8 brg_can_tune; /* BRG has baud tuning? */
- u32 brg_clk_src;
- u16 mpsc_max_idle;
- int default_baud;
- int default_bits;
- int default_parity;
- int default_flow;
-
- /* Physical addresses of various blocks of registers (from platform) */
- phys_addr_t mpsc_base_p;
- phys_addr_t sdma_base_p;
- phys_addr_t brg_base_p;
-
- /* Virtual addresses of various blocks of registers (from platform) */
- void __iomem *mpsc_base;
- void __iomem *sdma_base;
- void __iomem *brg_base;
-
- /* Descriptor ring and buffer allocations */
- void *dma_region;
- dma_addr_t dma_region_p;
-
- dma_addr_t rxr; /* Rx descriptor ring */
- dma_addr_t rxr_p; /* Phys addr of rxr */
- u8 *rxb; /* Rx Ring I/O buf */
- u8 *rxb_p; /* Phys addr of rxb */
- u32 rxr_posn; /* First desc w/ Rx data */
-
- dma_addr_t txr; /* Tx descriptor ring */
- dma_addr_t txr_p; /* Phys addr of txr */
- u8 *txb; /* Tx Ring I/O buf */
- u8 *txb_p; /* Phys addr of txb */
- int txr_head; /* Where new data goes */
- int txr_tail; /* Where sent data comes off */
-
- /* Mirrored values of regs we can't read (if 'mirror_regs' set) */
- u32 MPSC_MPCR_m;
- u32 MPSC_CHR_1_m;
- u32 MPSC_CHR_2_m;
- u32 MPSC_CHR_10_m;
- u32 BRG_BCR_m;
- struct mpsc_shared_regs *shared_regs;
-};
-
-/* Hooks to platform-specific code */
-int mpsc_platform_register_driver(void);
-void mpsc_platform_unregister_driver(void);
-
-/* Hooks back in to mpsc common to be called by platform-specific code */
-struct mpsc_port_info *mpsc_device_probe(int index);
-struct mpsc_port_info *mpsc_device_remove(int index);
-
-/*
- *****************************************************************************
- *
- * Multi-Protocol Serial Controller Interface Registers
- *
- *****************************************************************************
- */
-
-/* Main Configuratino Register Offsets */
-#define MPSC_MMCRL 0x0000
-#define MPSC_MMCRH 0x0004
-#define MPSC_MPCR 0x0008
-#define MPSC_CHR_1 0x000c
-#define MPSC_CHR_2 0x0010
-#define MPSC_CHR_3 0x0014
-#define MPSC_CHR_4 0x0018
-#define MPSC_CHR_5 0x001c
-#define MPSC_CHR_6 0x0020
-#define MPSC_CHR_7 0x0024
-#define MPSC_CHR_8 0x0028
-#define MPSC_CHR_9 0x002c
-#define MPSC_CHR_10 0x0030
-#define MPSC_CHR_11 0x0034
-
-#define MPSC_MPCR_FRZ (1 << 9)
-#define MPSC_MPCR_CL_5 0
-#define MPSC_MPCR_CL_6 1
-#define MPSC_MPCR_CL_7 2
-#define MPSC_MPCR_CL_8 3
-#define MPSC_MPCR_SBL_1 0
-#define MPSC_MPCR_SBL_2 1
-
-#define MPSC_CHR_2_TEV (1<<1)
-#define MPSC_CHR_2_TA (1<<7)
-#define MPSC_CHR_2_TTCS (1<<9)
-#define MPSC_CHR_2_REV (1<<17)
-#define MPSC_CHR_2_RA (1<<23)
-#define MPSC_CHR_2_CRD (1<<25)
-#define MPSC_CHR_2_EH (1<<31)
-#define MPSC_CHR_2_PAR_ODD 0
-#define MPSC_CHR_2_PAR_SPACE 1
-#define MPSC_CHR_2_PAR_EVEN 2
-#define MPSC_CHR_2_PAR_MARK 3
-
-/* MPSC Signal Routing */
-#define MPSC_MRR 0x0000
-#define MPSC_RCRR 0x0004
-#define MPSC_TCRR 0x0008
-
-/*
- *****************************************************************************
- *
- * Serial DMA Controller Interface Registers
- *
- *****************************************************************************
- */
-
-#define SDMA_SDC 0x0000
-#define SDMA_SDCM 0x0008
-#define SDMA_RX_DESC 0x0800
-#define SDMA_RX_BUF_PTR 0x0808
-#define SDMA_SCRDP 0x0810
-#define SDMA_TX_DESC 0x0c00
-#define SDMA_SCTDP 0x0c10
-#define SDMA_SFTDP 0x0c14
-
-#define SDMA_DESC_CMDSTAT_PE (1<<0)
-#define SDMA_DESC_CMDSTAT_CDL (1<<1)
-#define SDMA_DESC_CMDSTAT_FR (1<<3)
-#define SDMA_DESC_CMDSTAT_OR (1<<6)
-#define SDMA_DESC_CMDSTAT_BR (1<<9)
-#define SDMA_DESC_CMDSTAT_MI (1<<10)
-#define SDMA_DESC_CMDSTAT_A (1<<11)
-#define SDMA_DESC_CMDSTAT_AM (1<<12)
-#define SDMA_DESC_CMDSTAT_CT (1<<13)
-#define SDMA_DESC_CMDSTAT_C (1<<14)
-#define SDMA_DESC_CMDSTAT_ES (1<<15)
-#define SDMA_DESC_CMDSTAT_L (1<<16)
-#define SDMA_DESC_CMDSTAT_F (1<<17)
-#define SDMA_DESC_CMDSTAT_P (1<<18)
-#define SDMA_DESC_CMDSTAT_EI (1<<23)
-#define SDMA_DESC_CMDSTAT_O (1<<31)
-
-#define SDMA_DESC_DFLT (SDMA_DESC_CMDSTAT_O | \
- SDMA_DESC_CMDSTAT_EI)
-
-#define SDMA_SDC_RFT (1<<0)
-#define SDMA_SDC_SFM (1<<1)
-#define SDMA_SDC_BLMR (1<<6)
-#define SDMA_SDC_BLMT (1<<7)
-#define SDMA_SDC_POVR (1<<8)
-#define SDMA_SDC_RIFB (1<<9)
-
-#define SDMA_SDCM_ERD (1<<7)
-#define SDMA_SDCM_AR (1<<15)
-#define SDMA_SDCM_STD (1<<16)
-#define SDMA_SDCM_TXD (1<<23)
-#define SDMA_SDCM_AT (1<<31)
-
-#define SDMA_0_CAUSE_RXBUF (1<<0)
-#define SDMA_0_CAUSE_RXERR (1<<1)
-#define SDMA_0_CAUSE_TXBUF (1<<2)
-#define SDMA_0_CAUSE_TXEND (1<<3)
-#define SDMA_1_CAUSE_RXBUF (1<<8)
-#define SDMA_1_CAUSE_RXERR (1<<9)
-#define SDMA_1_CAUSE_TXBUF (1<<10)
-#define SDMA_1_CAUSE_TXEND (1<<11)
-
-#define SDMA_CAUSE_RX_MASK (SDMA_0_CAUSE_RXBUF | SDMA_0_CAUSE_RXERR | \
- SDMA_1_CAUSE_RXBUF | SDMA_1_CAUSE_RXERR)
-#define SDMA_CAUSE_TX_MASK (SDMA_0_CAUSE_TXBUF | SDMA_0_CAUSE_TXEND | \
- SDMA_1_CAUSE_TXBUF | SDMA_1_CAUSE_TXEND)
-
-/* SDMA Interrupt registers */
-#define SDMA_INTR_CAUSE 0x0000
-#define SDMA_INTR_MASK 0x0080
-
-/*
- *****************************************************************************
- *
- * Baud Rate Generator Interface Registers
- *
- *****************************************************************************
- */
-
-#define BRG_BCR 0x0000
-#define BRG_BTR 0x0004
-
-#endif /* __MPSC_H__ */
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index b848b7d9441..3bdee64d1a9 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -483,7 +483,7 @@ static int serial_txx9_startup(struct uart_port *port)
/*
* Clear the FIFO buffers and disable them.
- * (they will be reeanbled in set_termios())
+ * (they will be reenabled in set_termios())
*/
sio_set(up, TXX9_SIFCR,
TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 9fe2283d91e..1c4396c2962 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -641,7 +641,7 @@ static int sunsu_startup(struct uart_port *port)
/*
* Clear the FIFO buffers and disable them.
- * (they will be reeanbled in set_termios())
+ * (they will be reenabled in set_termios())
*/
if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) {
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c
index 3c987f49f6b..e166fffea86 100644
--- a/drivers/telephony/phonedev.c
+++ b/drivers/telephony/phonedev.c
@@ -29,6 +29,7 @@
#include <linux/kmod.h>
#include <linux/sem.h>
#include <linux/devfs_fs_kernel.h>
+#include <linux/mutex.h>
#define PHONE_NUM_DEVICES 256
@@ -37,7 +38,7 @@
*/
static struct phone_device *phone_device[PHONE_NUM_DEVICES];
-static DECLARE_MUTEX(phone_lock);
+static DEFINE_MUTEX(phone_lock);
/*
* Open a phone device.
@@ -48,19 +49,19 @@ static int phone_open(struct inode *inode, struct file *file)
unsigned int minor = iminor(inode);
int err = 0;
struct phone_device *p;
- struct file_operations *old_fops, *new_fops = NULL;
+ const struct file_operations *old_fops, *new_fops = NULL;
if (minor >= PHONE_NUM_DEVICES)
return -ENODEV;
- down(&phone_lock);
+ mutex_lock(&phone_lock);
p = phone_device[minor];
if (p)
new_fops = fops_get(p->f_op);
if (!new_fops) {
- up(&phone_lock);
+ mutex_unlock(&phone_lock);
request_module("char-major-%d-%d", PHONE_MAJOR, minor);
- down(&phone_lock);
+ mutex_lock(&phone_lock);
p = phone_device[minor];
if (p == NULL || (new_fops = fops_get(p->f_op)) == NULL)
{
@@ -78,7 +79,7 @@ static int phone_open(struct inode *inode, struct file *file)
}
fops_put(old_fops);
end:
- up(&phone_lock);
+ mutex_unlock(&phone_lock);
return err;
}
@@ -100,18 +101,18 @@ int phone_register_device(struct phone_device *p, int unit)
end = unit + 1; /* enter the loop at least one time */
}
- down(&phone_lock);
+ mutex_lock(&phone_lock);
for (i = base; i < end; i++) {
if (phone_device[i] == NULL) {
phone_device[i] = p;
p->minor = i;
devfs_mk_cdev(MKDEV(PHONE_MAJOR,i),
S_IFCHR|S_IRUSR|S_IWUSR, "phone/%d", i);
- up(&phone_lock);
+ mutex_unlock(&phone_lock);
return 0;
}
}
- up(&phone_lock);
+ mutex_unlock(&phone_lock);
return -ENFILE;
}
@@ -121,12 +122,12 @@ int phone_register_device(struct phone_device *p, int unit)
void phone_unregister_device(struct phone_device *pfd)
{
- down(&phone_lock);
+ mutex_lock(&phone_lock);
if (phone_device[pfd->minor] != pfd)
panic("phone: bad unregister");
devfs_remove("phone/%d", pfd->minor);
phone_device[pfd->minor] = NULL;
- up(&phone_lock);
+ mutex_unlock(&phone_lock);
}
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index b1222cd4aa4..7fdbc5dad5f 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -87,8 +87,6 @@ source "drivers/usb/input/Kconfig"
source "drivers/usb/image/Kconfig"
-source "drivers/usb/media/Kconfig"
-
source "drivers/usb/net/Kconfig"
source "drivers/usb/mon/Kconfig"
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index bb36a1c1dbb..9b7d9769fdc 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -35,20 +35,6 @@ obj-$(CONFIG_USB_WACOM) += input/
obj-$(CONFIG_USB_ACECAD) += input/
obj-$(CONFIG_USB_XPAD) += input/
-obj-$(CONFIG_USB_DABUSB) += media/
-obj-$(CONFIG_USB_DSBR) += media/
-obj-$(CONFIG_USB_ET61X251) += media/
-obj-$(CONFIG_USB_IBMCAM) += media/
-obj-$(CONFIG_USB_KONICAWC) += media/
-obj-$(CONFIG_USB_OV511) += media/
-obj-$(CONFIG_USB_PWC) += media/
-obj-$(CONFIG_USB_SE401) += media/
-obj-$(CONFIG_USB_SN9C102) += media/
-obj-$(CONFIG_USB_STV680) += media/
-obj-$(CONFIG_USB_VICAM) += media/
-obj-$(CONFIG_USB_W9968CF) += media/
-obj-$(CONFIG_USB_ZC0301) += media/
-
obj-$(CONFIG_USB_CATC) += net/
obj-$(CONFIG_USB_KAWETH) += net/
obj-$(CONFIG_USB_PEGASUS) += net/
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 37b13368c81..b263a54a13c 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -24,15 +24,15 @@
#include "usb.h"
#define MAX_USB_MINORS 256
-static struct file_operations *usb_minors[MAX_USB_MINORS];
+static const struct file_operations *usb_minors[MAX_USB_MINORS];
static DEFINE_SPINLOCK(minor_lock);
static int usb_open(struct inode * inode, struct file * file)
{
int minor = iminor(inode);
- struct file_operations *c;
+ const struct file_operations *c;
int err = -ENODEV;
- struct file_operations *old_fops, *new_fops = NULL;
+ const struct file_operations *old_fops, *new_fops = NULL;
spin_lock (&minor_lock);
c = usb_minors[minor];
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index e0afb5ad29e..0d2193b6923 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -296,7 +296,7 @@ done:
#ifdef CONFIG_PPC_PMAC
/* Disable ASIC clocks for USB */
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
struct device_node *of_node;
of_node = pci_device_to_OF_node (dev);
@@ -331,7 +331,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
#ifdef CONFIG_PPC_PMAC
/* Reenable ASIC clocks for USB */
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
struct device_node *of_node;
of_node = pci_device_to_OF_node (dev);
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c
index 4b55285de9a..fe0ed54fa0a 100644
--- a/drivers/usb/core/notify.c
+++ b/drivers/usb/core/notify.c
@@ -16,57 +16,7 @@
#include <linux/mutex.h>
#include "usb.h"
-
-static struct notifier_block *usb_notifier_list;
-static DEFINE_MUTEX(usb_notifier_lock);
-
-static void usb_notifier_chain_register(struct notifier_block **list,
- struct notifier_block *n)
-{
- mutex_lock(&usb_notifier_lock);
- while (*list) {
- if (n->priority > (*list)->priority)
- break;
- list = &((*list)->next);
- }
- n->next = *list;
- *list = n;
- mutex_unlock(&usb_notifier_lock);
-}
-
-static void usb_notifier_chain_unregister(struct notifier_block **nl,
- struct notifier_block *n)
-{
- mutex_lock(&usb_notifier_lock);
- while ((*nl)!=NULL) {
- if ((*nl)==n) {
- *nl = n->next;
- goto exit;
- }
- nl=&((*nl)->next);
- }
-exit:
- mutex_unlock(&usb_notifier_lock);
-}
-
-static int usb_notifier_call_chain(struct notifier_block **n,
- unsigned long val, void *v)
-{
- int ret=NOTIFY_DONE;
- struct notifier_block *nb = *n;
-
- mutex_lock(&usb_notifier_lock);
- while (nb) {
- ret = nb->notifier_call(nb,val,v);
- if (ret&NOTIFY_STOP_MASK) {
- goto exit;
- }
- nb = nb->next;
- }
-exit:
- mutex_unlock(&usb_notifier_lock);
- return ret;
-}
+static BLOCKING_NOTIFIER_HEAD(usb_notifier_list);
/**
* usb_register_notify - register a notifier callback whenever a usb change happens
@@ -76,7 +26,7 @@ exit:
*/
void usb_register_notify(struct notifier_block *nb)
{
- usb_notifier_chain_register(&usb_notifier_list, nb);
+ blocking_notifier_chain_register(&usb_notifier_list, nb);
}
EXPORT_SYMBOL_GPL(usb_register_notify);
@@ -89,27 +39,28 @@ EXPORT_SYMBOL_GPL(usb_register_notify);
*/
void usb_unregister_notify(struct notifier_block *nb)
{
- usb_notifier_chain_unregister(&usb_notifier_list, nb);
+ blocking_notifier_chain_unregister(&usb_notifier_list, nb);
}
EXPORT_SYMBOL_GPL(usb_unregister_notify);
void usb_notify_add_device(struct usb_device *udev)
{
- usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev);
+ blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev);
}
void usb_notify_remove_device(struct usb_device *udev)
{
- usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev);
+ blocking_notifier_call_chain(&usb_notifier_list,
+ USB_DEVICE_REMOVE, udev);
}
void usb_notify_add_bus(struct usb_bus *ubus)
{
- usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus);
+ blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus);
}
void usb_notify_remove_bus(struct usb_bus *ubus)
{
- usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus);
+ blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus);
}
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index b44cfda76b6..3f618ce6998 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1581,7 +1581,7 @@ restart:
static struct inode *
gadgetfs_create_file (struct super_block *sb, char const *name,
- void *data, struct file_operations *fops,
+ void *data, const struct file_operations *fops,
struct dentry **dentry_p);
static int activate_ep_files (struct dev_data *dev)
@@ -1955,7 +1955,7 @@ module_param (default_perm, uint, 0644);
static struct inode *
gadgetfs_make_inode (struct super_block *sb,
- void *data, struct file_operations *fops,
+ void *data, const struct file_operations *fops,
int mode)
{
struct inode *inode = new_inode (sb);
@@ -1979,7 +1979,7 @@ gadgetfs_make_inode (struct super_block *sb,
*/
static struct inode *
gadgetfs_create_file (struct super_block *sb, char const *name,
- void *data, struct file_operations *fops,
+ void *data, const struct file_operations *fops,
struct dentry **dentry_p)
{
struct dentry *dentry;
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 372527a8359..682bf221566 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -158,7 +158,7 @@ static int ohci_s3c2410_hub_control (
"s3c2410_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n",
hcd, typeReq, wValue, wIndex, buf, wLength);
- /* if we are only an humble host without any special capabilites
+ /* if we are only an humble host without any special capabilities
* process the request straight away and exit */
if (info == NULL) {
diff --git a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig
deleted file mode 100644
index 189d40f96be..00000000000
--- a/drivers/usb/media/Kconfig
+++ /dev/null
@@ -1,241 +0,0 @@
-#
-# USB Multimedia device configuration
-#
-comment "USB Multimedia devices"
- depends on USB
-
-config USB_DABUSB
- tristate "DABUSB driver"
- depends on USB
- ---help---
- A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
- brought to you by the DAB-Team
- <http://wwwbode.cs.tum.edu/Par/arch/dab/>. This driver can be taken
- as an example for URB-based bulk, control, and isochronous
- transactions. URB's are explained in
- <file:Documentation/usb/URB.txt>.
-
- To compile this driver as a module, choose M here: the
- module will be called dabusb.
-
-comment "Video4Linux support is needed for USB Multimedia device support"
- depends on USB && VIDEO_DEV=n
-
-config USB_VICAM
- tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
- depends on USB && VIDEO_DEV && EXPERIMENTAL
- ---help---
- Say Y here if you have 3com homeconnect camera (vicam).
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Multimedia Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called vicam.
-
-config USB_DSBR
- tristate "D-Link USB FM radio support (EXPERIMENTAL)"
- depends on USB && VIDEO_DEV && EXPERIMENTAL
- ---help---
- Say Y here if you want to connect this type of radio to your
- computer's USB port. Note that the audio is not digital, and
- you must connect the line out connector to a sound card or a
- set of speakers.
-
- This driver uses the Video For Linux API. You must enable
- (Y or M in config) Video For Linux (under Character Devices)
- to use this driver. Information on this API and pointers to
- "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called dsbr100.
-
-config USB_ET61X251
- tristate "USB ET61X[12]51 PC Camera Controller support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want support for cameras based on Etoms ET61X151
- or ET61X251 PC Camera Controllers.
-
- See <file:Documentation/usb/et61x251.txt> for more informations.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" to use this driver.
-
- To compile this driver as a module, choose M here: the
- module will be called et61x251.
-
-config USB_IBMCAM
- tristate "USB IBM (Xirlink) C-it Camera support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want to connect a IBM "C-It" camera, also known as
- "Xirlink PC Camera" to your computer's USB port. For more
- information, read <file:Documentation/usb/ibmcam.txt>.
-
- This driver uses the Video For Linux API. You must enable
- (Y or M in config) Video For Linux (under Character Devices)
- to use this driver. Information on this API and pointers to
- "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called ibmcam.
-
- This camera has several configuration options which
- can be specified when you load the module. Read
- <file:Documentation/usb/ibmcam.txt> to learn more.
-
-config USB_KONICAWC
- tristate "USB Konica Webcam support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want support for webcams based on a Konica
- chipset. This is known to work with the Intel YC76 webcam.
-
- This driver uses the Video For Linux API. You must enable
- (Y or M in config) Video For Linux (under Character Devices)
- to use this driver. Information on this API and pointers to
- "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called konicawc.
-
-config USB_OV511
- tristate "USB OV511 Camera support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want to connect this type of camera to your
- computer's USB port. See <file:Documentation/usb/ov511.txt> for more
- information and for a list of supported cameras.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Character Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called ov511.
-
-config USB_SE401
- tristate "USB SE401 Camera support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want to connect this type of camera to your
- computer's USB port. See <file:Documentation/usb/se401.txt> for more
- information and for a list of supported cameras.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Multimedia Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called se401.
-
-config USB_SN9C102
- tristate "USB SN9C10x PC Camera Controller support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want support for cameras based on SONiX SN9C101,
- SN9C102 or SN9C103 PC Camera Controllers.
-
- See <file:Documentation/usb/sn9c102.txt> for more informations.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" to use this driver.
-
- To compile this driver as a module, choose M here: the
- module will be called sn9c102.
-
-config USB_STV680
- tristate "USB STV680 (Pencam) Camera support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want to connect this type of camera to your
- computer's USB port. This includes the Pencam line of cameras.
- See <file:Documentation/usb/stv680.txt> for more information and for
- a list of supported cameras.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Multimedia Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called stv680.
-
-config USB_W9968CF
- tristate "USB W996[87]CF JPEG Dual Mode Camera support"
- depends on USB && VIDEO_DEV && I2C && VIDEO_OVCAMCHIP
- ---help---
- Say Y here if you want support for cameras based on OV681 or
- Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
-
- This driver has an optional plugin, which is distributed as a
- separate module only (released under GPL). It allows to use higher
- resolutions and framerates, but cannot be included in the official
- Linux kernel for performance purposes.
-
- See <file:Documentation/usb/w9968cf.txt> for more informations.
-
- This driver uses the Video For Linux and the I2C APIs. It needs the
- OmniVision Camera Chip support as well. You must say Y or M to
- "Video For Linux", "I2C Support" and "OmniVision Camera Chip
- support" to use this driver.
-
- To compile this driver as a module, choose M here: the
- module will be called w9968cf.
-
-config USB_ZC0301
- tristate "USB ZC0301 Image Processor and Control Chip support"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y here if you want support for cameras based on the ZC0301
- Image Processor and Control Chip.
-
- See <file:Documentation/usb/zc0301.txt> for more informations.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" to use this driver.
-
- To compile this driver as a module, choose M here: the
- module will be called zc0301.
-
-config USB_PWC
- tristate "USB Philips Cameras"
- depends on USB && VIDEO_DEV
- ---help---
- Say Y or M here if you want to use one of these Philips & OEM
- webcams:
- * Philips PCA645, PCA646
- * Philips PCVC675, PCVC680, PCVC690
- * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
- * Askey VC010
- * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
- and 'Orbit'/'Sphere'
- * Samsung MPC-C10, MPC-C30
- * Creative Webcam 5, Pro Ex
- * SOTEC Afina Eye
- * Visionite VCS-UC300, VCS-UM100
-
- The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
- and never will be, but the 665 and 720/20 are supported by other
- drivers.
-
- See <file:Documentation/usb/philips.txt> for more information and
- installation instructions.
-
- The built-in microphone is enabled by selecting USB Audio support.
-
- This driver uses the Video For Linux API. You must say Y or M to
- "Video For Linux" (under Character Devices) to use this driver.
- Information on this API and pointers to "v4l" programs may be found
- at <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called pwc.
diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile
deleted file mode 100644
index 50e89a33b85..00000000000
--- a/drivers/usb/media/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Makefile for USB Media drivers
-#
-
-sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \
- sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \
- sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \
- sn9c102_tas5130d1b.o
-et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o
-zc0301-objs := zc0301_core.o zc0301_pas202bcb.o
-
-obj-$(CONFIG_USB_DABUSB) += dabusb.o
-obj-$(CONFIG_USB_DSBR) += dsbr100.o
-obj-$(CONFIG_USB_ET61X251) += et61x251.o
-obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o
-obj-$(CONFIG_USB_KONICAWC) += konicawc.o usbvideo.o
-obj-$(CONFIG_USB_OV511) += ov511.o
-obj-$(CONFIG_USB_SE401) += se401.o
-obj-$(CONFIG_USB_SN9C102) += sn9c102.o
-obj-$(CONFIG_USB_STV680) += stv680.o
-obj-$(CONFIG_USB_VICAM) += vicam.o usbvideo.o
-obj-$(CONFIG_USB_W9968CF) += w9968cf.o
-obj-$(CONFIG_USB_ZC0301) += zc0301.o
-obj-$(CONFIG_USB_PWC) += pwc/
diff --git a/drivers/usb/media/pwc/pwc-kiara.c b/drivers/usb/media/pwc/pwc-kiara.c
deleted file mode 100644
index c498c68bace..00000000000
--- a/drivers/usb/media/pwc/pwc-kiara.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/* Linux driver for Philips webcam
- (C) 2004 Luc Saillard (luc@saillard.org)
-
- NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
- driver and thus may have bugs that are not present in the original version.
- Please send bug reports and support requests to <luc@saillard.org>.
- The decompression routines have been implemented by reverse-engineering the
- Nemosoft binary pwcx module. Caveat emptor.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-/* This tables contains entries for the 730/740/750 (Kiara) camera, with
- 4 different qualities (no compression, low, medium, high).
- It lists the bandwidth requirements for said mode by its alternate interface
- number. An alternate of 0 means that the mode is unavailable.
-
- There are 6 * 4 * 4 entries:
- 6 different resolutions subqcif, qsif, qcif, sif, cif, vga
- 6 framerates: 5, 10, 15, 20, 25, 30
- 4 compression modi: none, low, medium, high
-
- When an uncompressed mode is not available, the next available compressed mode
- will be chosen (unless the decompressor is absent). Sometimes there are only
- 1 or 2 compressed modes available; in that case entries are duplicated.
-*/
-
-
-#include "pwc-kiara.h"
-#include "pwc-uncompress.h"
-
-const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
-{
- /* SQCIF */
- {
- /* 5 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 10 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 15 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 20 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 25 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 30 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- },
- /* QSIF */
- {
- /* 5 fps */
- {
- {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
- {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
- {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
- {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
- },
- /* 10 fps */
- {
- {2, 291, 0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
- {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
- {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
- {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
- },
- /* 15 fps */
- {
- {3, 437, 0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
- {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
- {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
- {1, 192, 420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
- },
- /* 20 fps */
- {
- {4, 589, 0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
- {3, 448, 730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
- {2, 292, 476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
- {1, 192, 312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
- },
- /* 25 fps */
- {
- {5, 703, 0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
- {3, 447, 610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
- {2, 292, 398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
- {1, 193, 262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
- },
- /* 30 fps */
- {
- {8, 874, 0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
- {5, 704, 730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
- {3, 448, 492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
- {2, 292, 320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
- },
- },
- /* QCIF */
- {
- /* 5 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 10 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 15 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 20 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 25 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 30 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- },
- /* SIF */
- {
- /* 5 fps */
- {
- {4, 582, 0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
- {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
- {2, 291, 960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
- {1, 191, 630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
- },
- /* 10 fps */
- {
- {0, },
- {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
- {3, 447, 736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
- {2, 292, 480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
- },
- /* 15 fps */
- {
- {0, },
- {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
- {4, 592, 650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
- {3, 448, 492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
- },
- /* 20 fps */
- {
- {0, },
- {9, 958, 782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
- {5, 703, 574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
- {3, 446, 364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
- },
- /* 25 fps */
- {
- {0, },
- {9, 958, 654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
- {6, 776, 530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
- {4, 592, 404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
- },
- /* 30 fps */
- {
- {0, },
- {9, 957, 526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
- {6, 775, 426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
- {4, 590, 324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
- },
- },
- /* CIF */
- {
- /* 5 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 10 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 15 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 20 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 25 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 30 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- },
- /* VGA */
- {
- /* 5 fps */
- {
- {0, },
- {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
- {4, 592, 976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
- {3, 448, 738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
- },
- /* 10 fps */
- {
- {0, },
- {9, 956, 788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
- {6, 776, 640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
- {4, 592, 488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
- },
- /* 15 fps */
- {
- {0, },
- {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
- {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
- {8, 895, 492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
- },
- /* 20 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 25 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 30 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- },
-};
-
diff --git a/drivers/usb/media/pwc/pwc-timon.c b/drivers/usb/media/pwc/pwc-timon.c
deleted file mode 100644
index dee967173d6..00000000000
--- a/drivers/usb/media/pwc/pwc-timon.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/* Linux driver for Philips webcam
- (C) 2004 Luc Saillard (luc@saillard.org)
-
- NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
- driver and thus may have bugs that are not present in the original version.
- Please send bug reports and support requests to <luc@saillard.org>.
- The decompression routines have been implemented by reverse-engineering the
- Nemosoft binary pwcx module. Caveat emptor.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-
-/* This tables contains entries for the 675/680/690 (Timon) camera, with
- 4 different qualities (no compression, low, medium, high).
- It lists the bandwidth requirements for said mode by its alternate interface
- number. An alternate of 0 means that the mode is unavailable.
-
- There are 6 * 4 * 4 entries:
- 6 different resolutions subqcif, qsif, qcif, sif, cif, vga
- 6 framerates: 5, 10, 15, 20, 25, 30
- 4 compression modi: none, low, medium, high
-
- When an uncompressed mode is not available, the next available compressed mode
- will be chosen (unless the decompressor is absent). Sometimes there are only
- 1 or 2 compressed modes available; in that case entries are duplicated.
-*/
-
-#include "pwc-timon.h"
-
-const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] =
-{
- /* SQCIF */
- {
- /* 5 fps */
- {
- {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
- {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
- {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
- {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
- },
- /* 10 fps */
- {
- {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
- {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
- {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
- {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
- },
- /* 15 fps */
- {
- {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
- {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
- {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
- {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
- },
- /* 20 fps */
- {
- {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
- {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
- {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
- {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
- },
- /* 25 fps */
- {
- {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
- {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
- {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
- {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
- },
- /* 30 fps */
- {
- {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
- {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
- {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
- {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
- },
- },
- /* QSIF */
- {
- /* 5 fps */
- {
- {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
- {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
- {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
- {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
- },
- /* 10 fps */
- {
- {2, 291, 0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}},
- {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
- {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
- {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
- },
- /* 15 fps */
- {
- {3, 437, 0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}},
- {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
- {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
- {1, 191, 420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
- },
- /* 20 fps */
- {
- {4, 588, 0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}},
- {3, 447, 730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
- {2, 292, 476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
- {1, 192, 312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
- },
- /* 25 fps */
- {
- {5, 703, 0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}},
- {3, 447, 610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
- {2, 292, 398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
- {1, 192, 262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
- },
- /* 30 fps */
- {
- {8, 873, 0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}},
- {5, 704, 774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}},
- {3, 448, 492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}},
- {2, 291, 320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
- },
- },
- /* QCIF */
- {
- /* 5 fps */
- {
- {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
- {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
- {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
- {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
- },
- /* 10 fps */
- {
- {3, 385, 0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}},
- {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
- {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
- {1, 194, 532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}},
- },
- /* 15 fps */
- {
- {4, 577, 0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}},
- {3, 447, 818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}},
- {2, 292, 534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}},
- {1, 195, 356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}},
- },
- /* 20 fps */
- {
- {6, 776, 0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}},
- {4, 591, 804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}},
- {3, 447, 608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
- {2, 291, 396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
- },
- /* 25 fps */
- {
- {9, 928, 0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}},
- {5, 703, 800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}},
- {3, 447, 508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
- {2, 292, 332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
- },
- /* 30 fps */
- {
- {0, },
- {9, 956, 876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}},
- {4, 592, 542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}},
- {2, 291, 266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}},
- },
- },
- /* SIF */
- {
- /* 5 fps */
- {
- {4, 582, 0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}},
- {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}},
- {2, 291, 960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}},
- {1, 191, 630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}},
- },
- /* 10 fps */
- {
- {0, },
- {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}},
- {3, 447, 736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}},
- {2, 291, 480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}},
- },
- /* 15 fps */
- {
- {0, },
- {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}},
- {4, 591, 650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}},
- {3, 448, 492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}},
- },
- /* 20 fps */
- {
- {0, },
- {9, 958, 782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}},
- {5, 703, 574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}},
- {3, 446, 364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}},
- },
- /* 25 fps */
- {
- {0, },
- {9, 958, 654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}},
- {6, 776, 530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}},
- {4, 592, 404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}},
- },
- /* 30 fps */
- {
- {0, },
- {9, 957, 526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}},
- {6, 775, 426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}},
- {4, 590, 324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}},
- },
- },
- /* CIF */
- {
- /* 5 fps */
- {
- {6, 771, 0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}},
- {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}},
- {2, 291, 800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}},
- {1, 193, 528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}},
- },
- /* 10 fps */
- {
- {0, },
- {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}},
- {4, 591, 812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}},
- {2, 291, 400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}},
- },
- /* 15 fps */
- {
- {0, },
- {9, 956, 876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}},
- {5, 703, 644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}},
- {3, 448, 410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}},
- },
- /* 20 fps */
- {
- {0, },
- {9, 956, 650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}},
- {6, 776, 528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}},
- {4, 591, 402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}},
- },
- /* 25 fps */
- {
- {0, },
- {9, 956, 544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}},
- {7, 840, 478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}},
- {5, 703, 400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}},
- },
- /* 30 fps */
- {
- {0, },
- {9, 956, 438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}},
- {7, 838, 384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}},
- {6, 773, 354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}},
- },
- },
- /* VGA */
- {
- /* 5 fps */
- {
- {0, },
- {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}},
- {4, 592, 976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}},
- {3, 448, 738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}},
- },
- /* 10 fps */
- {
- {0, },
- {9, 956, 788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}},
- {6, 776, 640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}},
- {4, 592, 488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}},
- },
- /* 15 fps */
- {
- {0, },
- {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
- {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
- {8, 895, 492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}},
- },
- /* 20 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 25 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- /* 30 fps */
- {
- {0, },
- {0, },
- {0, },
- {0, },
- },
- },
-};
-
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c
index 9c5ab251370..f7ac9d6b985 100644
--- a/drivers/usb/net/zaurus.c
+++ b/drivers/usb/net/zaurus.c
@@ -217,7 +217,7 @@ static int blan_mdlm_bind(struct usbnet *dev, struct usb_interface *intf)
* with devices that use it and those that don't.
*/
if ((detail->bDetailData[1] & ~0x02) != 0x01) {
- /* bmDataCapabilites == 0 would be fine too,
+ /* bmDataCapabilities == 0 would be fine too,
* but framing is minidriver-coupled for now.
*/
bad_detail:
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index a8455c9e79d..495db5755df 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -102,7 +102,7 @@ static struct usb_driver option_driver = {
.no_dynamic_id = 1,
};
-/* The card has three separate interfaces, wich the serial driver
+/* The card has three separate interfaces, which the serial driver
* recognizes separately, thus num_port=1.
*/
static struct usb_serial_driver option_3port_device = {
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index fdebd60a325..22e9d696fdd 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -70,6 +70,22 @@ config FB_MACMODES
depends on FB
default n
+config FB_FIRMWARE_EDID
+ bool "Enable firmware EDID"
+ depends on FB
+ default y
+ ---help---
+ This enables access to the EDID transferred from the firmware.
+ On the i386, this is from the Video BIOS. Enable this if DDC/I2C
+ transfers do not work for your driver and if you are using
+ nvidiafb, i810fb or savagefb.
+
+ In general, choosing Y for this option is safe. If you
+ experience extremely long delays while booting before you get
+ something on your display, try setting this to N. Matrox cards in
+ combination with certain motherboards and monitors are known to
+ suffer from this problem.
+
config FB_MODE_HELPERS
bool "Enable Video Mode Handling Helpers"
depends on FB
@@ -1202,6 +1218,17 @@ config FB_AU1100
bool "Au1100 LCD Driver"
depends on (FB = y) && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y
+config FB_AU1200
+ bool "Au1200 LCD Driver"
+ depends on FB && MIPS && SOC_AU1200
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the framebuffer driver for the AMD Au1200 SOC. It can drive
+ various panels and CRTs by passing in kernel cmd line option
+ au1200fb:panel=<name>.
+
source "drivers/video/geode/Kconfig"
config FB_FFB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index aa434e725c0..cb90218515a 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -86,6 +86,7 @@ obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
obj-$(CONFIG_FB_PXA) += pxafb.o
obj-$(CONFIG_FB_W100) += w100fb.o
obj-$(CONFIG_FB_AU1100) += au1100fb.o
+obj-$(CONFIG_FB_AU1200) += au1200fb.o
obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o
obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o
obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 76448d6ae89..98baecccb3f 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -1308,7 +1308,7 @@ static int __init acornfb_probe(struct platform_device *dev)
/*
* Try to select a suitable default mode
*/
- for (i = 0; i < sizeof(modedb) / sizeof(*modedb); i++) {
+ for (i = 0; i < ARRAY_SIZE(modedb); i++) {
unsigned long hs;
hs = modedb[i].refresh *
@@ -1380,7 +1380,7 @@ static int __init acornfb_probe(struct platform_device *dev)
*/
free_unused_pages(PAGE_OFFSET + size, PAGE_OFFSET + MAX_SIZE);
#endif
-
+
fb_info.fix.smem_len = size;
current_par.palette_size = VIDC_PALETTE_SIZE;
@@ -1391,7 +1391,7 @@ static int __init acornfb_probe(struct platform_device *dev)
*/
do {
rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,
- sizeof(modedb) / sizeof(*modedb),
+ ARRAY_SIZE(modedb),
&acornfb_default_mode, DEFAULT_BPP);
/*
* If we found an exact match, all ok.
@@ -1408,7 +1408,7 @@ static int __init acornfb_probe(struct platform_device *dev)
break;
rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,
- sizeof(modedb) / sizeof(*modedb),
+ ARRAY_SIZE(modedb),
&acornfb_default_mode, DEFAULT_BPP);
if (rc)
break;
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index c924d81f797..29f9f0dfe3b 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -353,8 +353,6 @@ struct chips_init_reg {
unsigned char data;
};
-#define N_ELTS(x) (sizeof(x) / sizeof(x[0]))
-
static struct chips_init_reg chips_init_sr[] =
{
{0x00, 0x03}, /* Reset register */
@@ -460,22 +458,22 @@ static void __devinit chips_hw_init(struct fb_info *p)
{
int i;
- for (i = 0; i < N_ELTS(chips_init_xr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i)
write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
write_xr(0x81, 0x12);
write_xr(0x82, 0x08);
write_xr(0x20, 0x00);
- for (i = 0; i < N_ELTS(chips_init_sr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i)
write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
- for (i = 0; i < N_ELTS(chips_init_gr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i)
write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
- for (i = 0; i < N_ELTS(chips_init_ar); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i)
write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
/* Enable video output in attribute index register */
writeb(0x20, mmio_base + 0x780);
- for (i = 0; i < N_ELTS(chips_init_cr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i)
write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
- for (i = 0; i < N_ELTS(chips_init_fr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i)
write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
}
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 620c9a934e0..f7bbff4ddc6 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -67,6 +67,7 @@
#include <asm/io.h>
#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
#include <asm/pmac_feature.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
@@ -1725,9 +1726,9 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id *
strcpy(video_card, "Rage128 XX ");
video_card[8] = ent->device >> 8;
video_card[9] = ent->device & 0xFF;
-
+
/* range check to make sure */
- if (ent->driver_data < (sizeof(r128_family)/sizeof(char *)))
+ if (ent->driver_data < ARRAY_SIZE(r128_family))
strncat(video_card, r128_family[ent->driver_data], sizeof(video_card));
printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);
@@ -1748,7 +1749,7 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id *
var = default_var;
#ifdef CONFIG_PPC_PMAC
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
/* Indicate sleep capability */
if (par->chip_gen == rage_M3) {
pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1);
@@ -2011,7 +2012,7 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
return 0;
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && blank)
+ if (machine_is(powermac) && blank)
set_backlight_enable(0);
#endif /* CONFIG_PMAC_BACKLIGHT */
@@ -2029,7 +2030,7 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
aty128_set_lcd_enable(par, par->lcd_on && !blank);
}
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && !blank)
+ if (machine_is(powermac) && !blank)
set_backlight_enable(1);
#endif /* CONFIG_PMAC_BACKLIGHT */
return 0;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 485be386a8f..b39e72d5413 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -75,6 +75,7 @@
#include "ati_ids.h"
#ifdef __powerpc__
+#include <asm/machdep.h>
#include <asm/prom.h>
#include "../macmodes.h"
#endif
@@ -434,7 +435,7 @@ static int __devinit correct_chipset(struct atyfb_par *par)
const char *name;
int i;
- for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--)
+ for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
if (par->pci_id == aty_chips[i].pci_id)
break;
@@ -2168,10 +2169,10 @@ static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) {
refresh_tbl = ragexl_tbl;
- size = sizeof(ragexl_tbl)/sizeof(int);
+ size = ARRAY_SIZE(ragexl_tbl);
} else {
refresh_tbl = ragepro_tbl;
- size = sizeof(ragepro_tbl)/sizeof(int);
+ size = ARRAY_SIZE(ragepro_tbl);
}
for (i=0; i < size; i++) {
@@ -2298,6 +2299,10 @@ static int __init aty_init(struct fb_info *info, const char *name)
case CLK_ATI18818_1:
par->pll_ops = &aty_pll_ati18818_1;
break;
+ case CLK_IBMRGB514:
+ par->pll_ops = &aty_pll_ibm514;
+ break;
+#if 0 /* dead code */
case CLK_STG1703:
par->pll_ops = &aty_pll_stg1703;
break;
@@ -2307,9 +2312,7 @@ static int __init aty_init(struct fb_info *info, const char *name)
case CLK_ATT20C408:
par->pll_ops = &aty_pll_att20c408;
break;
- case CLK_IBMRGB514:
- par->pll_ops = &aty_pll_ibm514;
- break;
+#endif
default:
PRINTKI("aty_init: CLK type not implemented yet!");
par->pll_ops = &aty_pll_unsupported;
@@ -2516,7 +2519,7 @@ static int __init aty_init(struct fb_info *info, const char *name)
memset(&var, 0, sizeof(var));
#ifdef CONFIG_PPC
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
/*
* FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
* applies to all Mac video cards
@@ -2671,7 +2674,7 @@ static int atyfb_blank(int blank, struct fb_info *info)
return 0;
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && blank > FB_BLANK_NORMAL)
+ if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
set_backlight_enable(0);
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
if (par->lcd_table && blank > FB_BLANK_NORMAL &&
@@ -2703,7 +2706,7 @@ static int atyfb_blank(int blank, struct fb_info *info)
aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && blank <= FB_BLANK_NORMAL)
+ if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
set_backlight_enable(1);
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
@@ -3397,7 +3400,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
struct atyfb_par *par;
int i, rc = -ENOMEM;
- for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--)
+ for (i = ARRAY_SIZE(aty_chips); i >= 0; i--)
if (pdev->device == aty_chips[i].pci_id)
break;
diff --git a/drivers/video/aty/mach64_gx.c b/drivers/video/aty/mach64_gx.c
index 01fdff79483..2045639cb67 100644
--- a/drivers/video/aty/mach64_gx.c
+++ b/drivers/video/aty/mach64_gx.c
@@ -149,8 +149,7 @@ static int aty_var_to_pll_514(const struct fb_info *info, u32 vclk_per,
};
int i;
- for (i = 0; i < sizeof(RGB514_clocks) / sizeof(*RGB514_clocks);
- i++)
+ for (i = 0; i < ARRAY_SIZE(RGB514_clocks); i++)
if (vclk_per <= RGB514_clocks[i].limit) {
pll->ibm514.m = RGB514_clocks[i].m;
pll->ibm514.n = RGB514_clocks[i].n;
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index c9f0c5a07e6..9a6b5b39b88 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -1067,7 +1067,7 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
if (regno > 255)
- return 1;
+ return -EINVAL;
red >>= 8;
green >>= 8;
@@ -1086,9 +1086,9 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
pindex = regno * 8;
if (rinfo->depth == 16 && regno > 63)
- return 1;
+ return -EINVAL;
if (rinfo->depth == 15 && regno > 31)
- return 1;
+ return -EINVAL;
/* For 565, the green component is mixed one order
* below
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 5886a2f1323..c7091761cef 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -20,7 +20,7 @@
#include <linux/agp_backend.h>
#ifdef CONFIG_PPC_PMAC
-#include <asm/processor.h>
+#include <asm/machdep.h>
#include <asm/prom.h>
#include <asm/pmac_feature.h>
#endif
@@ -2745,7 +2745,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
rinfo->pm_mode |= radeon_pm_off;
}
#if defined(CONFIG_PPC_PMAC)
- if (_machine == _MACH_Pmac && rinfo->of_node) {
+ if (machine_is(powermac) && rinfo->of_node) {
if (rinfo->is_mobility && rinfo->pm_reg &&
rinfo->family <= CHIP_FAMILY_RV250)
rinfo->pm_mode |= radeon_pm_d2;
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
new file mode 100644
index 00000000000..b367de30b98
--- /dev/null
+++ b/drivers/video/au1200fb.c
@@ -0,0 +1,3844 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1200 LCD Driver.
+ *
+ * Copyright 2004-2005 AMD
+ * Author: AMD
+ *
+ * Based on:
+ * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
+ * Created 28 Dec 1997 by Geert Uytterhoeven
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ctype.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/mach-au1x00/au1000.h>
+#include "au1200fb.h"
+
+#ifdef CONFIG_PM
+#include <asm/mach-au1x00/au1xxx_pm.h>
+#endif
+
+#ifndef CONFIG_FB_AU1200_DEVS
+#define CONFIG_FB_AU1200_DEVS 4
+#endif
+
+#define DRIVER_NAME "au1200fb"
+#define DRIVER_DESC "LCD controller driver for AU1200 processors"
+
+#define DEBUG 1
+
+#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
+#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
+#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg)
+
+#if DEBUG
+#define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg)
+#else
+#define print_dbg(f, arg...) do {} while (0)
+#endif
+
+
+#define AU1200_LCD_FB_IOCTL 0x46FF
+
+#define AU1200_LCD_SET_SCREEN 1
+#define AU1200_LCD_GET_SCREEN 2
+#define AU1200_LCD_SET_WINDOW 3
+#define AU1200_LCD_GET_WINDOW 4
+#define AU1200_LCD_SET_PANEL 5
+#define AU1200_LCD_GET_PANEL 6
+
+#define SCREEN_SIZE (1<< 1)
+#define SCREEN_BACKCOLOR (1<< 2)
+#define SCREEN_BRIGHTNESS (1<< 3)
+#define SCREEN_COLORKEY (1<< 4)
+#define SCREEN_MASK (1<< 5)
+
+struct au1200_lcd_global_regs_t {
+ unsigned int flags;
+ unsigned int xsize;
+ unsigned int ysize;
+ unsigned int backcolor;
+ unsigned int brightness;
+ unsigned int colorkey;
+ unsigned int mask;
+ unsigned int panel_choice;
+ char panel_desc[80];
+
+};
+
+#define WIN_POSITION (1<< 0)
+#define WIN_ALPHA_COLOR (1<< 1)
+#define WIN_ALPHA_MODE (1<< 2)
+#define WIN_PRIORITY (1<< 3)
+#define WIN_CHANNEL (1<< 4)
+#define WIN_BUFFER_FORMAT (1<< 5)
+#define WIN_COLOR_ORDER (1<< 6)
+#define WIN_PIXEL_ORDER (1<< 7)
+#define WIN_SIZE (1<< 8)
+#define WIN_COLORKEY_MODE (1<< 9)
+#define WIN_DOUBLE_BUFFER_MODE (1<< 10)
+#define WIN_RAM_ARRAY_MODE (1<< 11)
+#define WIN_BUFFER_SCALE (1<< 12)
+#define WIN_ENABLE (1<< 13)
+
+struct au1200_lcd_window_regs_t {
+ unsigned int flags;
+ unsigned int xpos;
+ unsigned int ypos;
+ unsigned int alpha_color;
+ unsigned int alpha_mode;
+ unsigned int priority;
+ unsigned int channel;
+ unsigned int buffer_format;
+ unsigned int color_order;
+ unsigned int pixel_order;
+ unsigned int xsize;
+ unsigned int ysize;
+ unsigned int colorkey_mode;
+ unsigned int double_buffer_mode;
+ unsigned int ram_array_mode;
+ unsigned int xscale;
+ unsigned int yscale;
+ unsigned int enable;
+};
+
+
+struct au1200_lcd_iodata_t {
+ unsigned int subcmd;
+ struct au1200_lcd_global_regs_t global;
+ struct au1200_lcd_window_regs_t window;
+};
+
+#if defined(__BIG_ENDIAN)
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11
+#else
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00
+#endif
+#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565
+
+/* Private, per-framebuffer management information (independent of the panel itself) */
+struct au1200fb_device {
+ struct fb_info fb_info; /* FB driver info record */
+
+ int plane;
+ unsigned char* fb_mem; /* FrameBuffer memory map */
+ unsigned int fb_len;
+ dma_addr_t fb_phys;
+};
+
+static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS];
+/********************************************************************/
+
+/* LCD controller restrictions */
+#define AU1200_LCD_MAX_XRES 1280
+#define AU1200_LCD_MAX_YRES 1024
+#define AU1200_LCD_MAX_BPP 32
+#define AU1200_LCD_MAX_CLK 96000000 /* fixme: this needs to go away ? */
+#define AU1200_LCD_NBR_PALETTE_ENTRIES 256
+
+/* Default number of visible screen buffer to allocate */
+#define AU1200FB_NBR_VIDEO_BUFFERS 1
+
+/********************************************************************/
+
+static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR;
+static int window_index = 2; /* default is zero */
+static int panel_index = 2; /* default is zero */
+static struct window_settings *win;
+static struct panel_settings *panel;
+static int noblanking = 1;
+static int nohwcursor = 0;
+
+struct window_settings {
+ unsigned char name[64];
+ uint32 mode_backcolor;
+ uint32 mode_colorkey;
+ uint32 mode_colorkeymsk;
+ struct {
+ int xres;
+ int yres;
+ int xpos;
+ int ypos;
+ uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */
+ uint32 mode_winenable;
+ } w[4];
+};
+
+#if defined(__BIG_ENDIAN)
+#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00
+#else
+#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01
+#endif
+
+extern int board_au1200fb_panel_init (void);
+extern int board_au1200fb_panel_shutdown (void);
+
+#ifdef CONFIG_PM
+int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
+ au1xxx_request_t request, void *data);
+au1xxx_power_dev_t *LCD_pm_dev;
+#endif
+
+/*
+ * Default window configurations
+ */
+static struct window_settings windows[] = {
+ { /* Index 0 */
+ "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
+ /* mode_backcolor */ 0x006600ff,
+ /* mode_colorkey,msk*/ 0, 0,
+ {
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ LCD_WINENABLE_WEN0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 100, 100, 100, 100,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ LCD_WINENABLE_WEN1,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ 0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0,
+ },
+ },
+ },
+
+ { /* Index 1 */
+ "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
+ /* mode_backcolor */ 0x006600ff,
+ /* mode_colorkey,msk*/ 0, 0,
+ {
+ {
+ /* xres, yres, xpos, ypos */ 320, 240, 5, 5,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP |
+ LCD_WINCTRL1_PO_00,
+ /* mode_winenable*/ LCD_WINENABLE_WEN0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565
+ | LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ 0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 100, 100, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 200, 25, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0,
+ },
+ },
+ },
+ { /* Index 2 */
+ "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
+ /* mode_backcolor */ 0x006600ff,
+ /* mode_colorkey,msk*/ 0, 0,
+ {
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ LCD_WINENABLE_WEN0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ 0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP |
+ LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0,
+ },
+ },
+ },
+ /* Need VGA 640 @ 24bpp, @ 32bpp */
+ /* Need VGA 800 @ 24bpp, @ 32bpp */
+ /* Need VGA 1024 @ 24bpp, @ 32bpp */
+};
+
+/*
+ * Controller configurations for various panels.
+ */
+
+struct panel_settings
+{
+ const char name[25]; /* Full name <vendor>_<model> */
+
+ struct fb_monspecs monspecs; /* FB monitor specs */
+
+ /* panel timings */
+ uint32 mode_screen;
+ uint32 mode_horztiming;
+ uint32 mode_verttiming;
+ uint32 mode_clkcontrol;
+ uint32 mode_pwmdiv;
+ uint32 mode_pwmhi;
+ uint32 mode_outmask;
+ uint32 mode_fifoctrl;
+ uint32 mode_toyclksrc;
+ uint32 mode_backlight;
+ uint32 mode_auxpll;
+ int (*device_init)(void);
+ int (*device_shutdown)(void);
+#define Xres min_xres
+#define Yres min_yres
+ u32 min_xres; /* Minimum horizontal resolution */
+ u32 max_xres; /* Maximum horizontal resolution */
+ u32 min_yres; /* Minimum vertical resolution */
+ u32 max_yres; /* Maximum vertical resolution */
+};
+
+/********************************************************************/
+/* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */
+
+/* List of panels known to work with the AU1200 LCD controller.
+ * To add a new panel, enter the same specifications as the
+ * Generic_TFT one, and MAKE SURE that it doesn't conflicts
+ * with the controller restrictions. Restrictions are:
+ *
+ * STN color panels: max_bpp <= 12
+ * STN mono panels: max_bpp <= 4
+ * TFT panels: max_bpp <= 16
+ * max_xres <= 800
+ * max_yres <= 600
+ */
+static struct panel_settings known_lcd_panels[] =
+{
+ [0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */
+ .name = "QVGA_320x240",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = LCD_SCREEN_SX_N(320) |
+ LCD_SCREEN_SY_N(240),
+ .mode_horztiming = 0x00c4623b,
+ .mode_verttiming = 0x00502814,
+ .mode_clkcontrol = 0x00020002, /* /4=24Mhz */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 320, 320,
+ 240, 240,
+ },
+
+ [1] = { /* VGA 640x480 H:30.3kHz V:58Hz */
+ .name = "VGA_640x480",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x13f9df80,
+ .mode_horztiming = 0x003c5859,
+ .mode_verttiming = 0x00741201,
+ .mode_clkcontrol = 0x00020001, /* /4=24Mhz */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 640, 480,
+ 640, 480,
+ },
+
+ [2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */
+ .name = "SVGA_800x600",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x18fa5780,
+ .mode_horztiming = 0x00dc7e77,
+ .mode_verttiming = 0x00584805,
+ .mode_clkcontrol = 0x00020000, /* /2=48Mhz */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 800, 800,
+ 600, 600,
+ },
+
+ [3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */
+ .name = "XVGA_1024x768",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x1ffaff80,
+ .mode_horztiming = 0x007d0e57,
+ .mode_verttiming = 0x00740a01,
+ .mode_clkcontrol = 0x000A0000, /* /1 */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 6, /* 72MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 1024, 1024,
+ 768, 768,
+ },
+
+ [4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */
+ .name = "XVGA_1280x1024",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x27fbff80,
+ .mode_horztiming = 0x00cdb2c7,
+ .mode_verttiming = 0x00600002,
+ .mode_clkcontrol = 0x000A0000, /* /1 */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 10, /* 120MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 1280, 1280,
+ 1024, 1024,
+ },
+
+ [5] = { /* Samsung 1024x768 TFT */
+ .name = "Samsung_1024x768_TFT",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x1ffaff80,
+ .mode_horztiming = 0x018cc677,
+ .mode_verttiming = 0x00241217,
+ .mode_clkcontrol = 0x00000000, /* SCB 0x1 /4=24Mhz */
+ .mode_pwmdiv = 0x8000063f, /* SCB 0x0 */
+ .mode_pwmhi = 0x03400000, /* SCB 0x0 */
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = board_au1200fb_panel_init,
+ .device_shutdown = board_au1200fb_panel_shutdown,
+ 1024, 1024,
+ 768, 768,
+ },
+
+ [6] = { /* Toshiba 640x480 TFT */
+ .name = "Toshiba_640x480_TFT",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = LCD_SCREEN_SX_N(640) |
+ LCD_SCREEN_SY_N(480),
+ .mode_horztiming = LCD_HORZTIMING_HPW_N(96) |
+ LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51),
+ .mode_verttiming = LCD_VERTTIMING_VPW_N(2) |
+ LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32),
+ .mode_clkcontrol = 0x00000000, /* /4=24Mhz */
+ .mode_pwmdiv = 0x8000063f,
+ .mode_pwmhi = 0x03400000,
+ .mode_outmask = 0x00fcfcfc,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = board_au1200fb_panel_init,
+ .device_shutdown = board_au1200fb_panel_shutdown,
+ 640, 480,
+ 640, 480,
+ },
+
+ [7] = { /* Sharp 320x240 TFT */
+ .name = "Sharp_320x240_TFT",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 12500,
+ .hfmax = 20000,
+ .vfmin = 38,
+ .vfmax = 81,
+ .dclkmin = 4500000,
+ .dclkmax = 6800000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = LCD_SCREEN_SX_N(320) |
+ LCD_SCREEN_SY_N(240),
+ .mode_horztiming = LCD_HORZTIMING_HPW_N(60) |
+ LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2),
+ .mode_verttiming = LCD_VERTTIMING_VPW_N(2) |
+ LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5),
+ .mode_clkcontrol = LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/
+ .mode_pwmdiv = 0x8000063f,
+ .mode_pwmhi = 0x03400000,
+ .mode_outmask = 0x00fcfcfc,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = board_au1200fb_panel_init,
+ .device_shutdown = board_au1200fb_panel_shutdown,
+ 320, 320,
+ 240, 240,
+ },
+
+ [8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */
+ .name = "Toppoly_TD070WGCB2",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = LCD_SCREEN_SX_N(856) |
+ LCD_SCREEN_SY_N(480),
+ .mode_horztiming = LCD_HORZTIMING_HND2_N(43) |
+ LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114),
+ .mode_verttiming = LCD_VERTTIMING_VND2_N(20) |
+ LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4),
+ .mode_clkcontrol = 0x00020001, /* /4=24Mhz */
+ .mode_pwmdiv = 0x8000063f,
+ .mode_pwmhi = 0x03400000,
+ .mode_outmask = 0x00fcfcfc,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = board_au1200fb_panel_init,
+ .device_shutdown = board_au1200fb_panel_shutdown,
+ 856, 856,
+ 480, 480,
+ },
+};
+
+#define NUM_PANELS (ARRAY_SIZE(known_lcd_panels))
+
+/********************************************************************/
+
+#ifdef CONFIG_PM
+static int set_brightness(unsigned int brightness)
+{
+ unsigned int hi1, divider;
+
+ /* limit brightness pwm duty to >= 30/1600 */
+ if (brightness < 30) {
+ brightness = 30;
+ }
+ divider = (lcd->pwmdiv & 0x3FFFF) + 1;
+ hi1 = (lcd->pwmhi >> 16) + 1;
+ hi1 = (((brightness & 0xFF) + 1) * divider >> 8);
+ lcd->pwmhi &= 0xFFFF;
+ lcd->pwmhi |= (hi1 << 16);
+
+ return brightness;
+}
+#endif /* CONFIG_PM */
+
+static int winbpp (unsigned int winctrl1)
+{
+ int bits = 0;
+
+ /* how many bits are needed for each pixel format */
+ switch (winctrl1 & LCD_WINCTRL1_FRM) {
+ case LCD_WINCTRL1_FRM_1BPP:
+ bits = 1;
+ break;
+ case LCD_WINCTRL1_FRM_2BPP:
+ bits = 2;
+ break;
+ case LCD_WINCTRL1_FRM_4BPP:
+ bits = 4;
+ break;
+ case LCD_WINCTRL1_FRM_8BPP:
+ bits = 8;
+ break;
+ case LCD_WINCTRL1_FRM_12BPP:
+ case LCD_WINCTRL1_FRM_16BPP655:
+ case LCD_WINCTRL1_FRM_16BPP565:
+ case LCD_WINCTRL1_FRM_16BPP556:
+ case LCD_WINCTRL1_FRM_16BPPI1555:
+ case LCD_WINCTRL1_FRM_16BPPI5551:
+ case LCD_WINCTRL1_FRM_16BPPA1555:
+ case LCD_WINCTRL1_FRM_16BPPA5551:
+ bits = 16;
+ break;
+ case LCD_WINCTRL1_FRM_24BPP:
+ case LCD_WINCTRL1_FRM_32BPP:
+ bits = 32;
+ break;
+ }
+
+ return bits;
+}
+
+static int fbinfo2index (struct fb_info *fb_info)
+{
+ int i;
+
+ for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) {
+ if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info))
+ return i;
+ }
+ printk("au1200fb: ERROR: fbinfo2index failed!\n");
+ return -1;
+}
+
+static int au1200_setlocation (struct au1200fb_device *fbdev, int plane,
+ int xpos, int ypos)
+{
+ uint32 winctrl0, winctrl1, winenable, fb_offset = 0;
+ int xsz, ysz;
+
+ /* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */
+
+ winctrl0 = lcd->window[plane].winctrl0;
+ winctrl1 = lcd->window[plane].winctrl1;
+ winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN);
+ winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY);
+
+ /* Check for off-screen adjustments */
+ xsz = win->w[plane].xres;
+ ysz = win->w[plane].yres;
+ if ((xpos + win->w[plane].xres) > panel->Xres) {
+ /* Off-screen to the right */
+ xsz = panel->Xres - xpos; /* off by 1 ??? */
+ /*printk("off screen right\n");*/
+ }
+
+ if ((ypos + win->w[plane].yres) > panel->Yres) {
+ /* Off-screen to the bottom */
+ ysz = panel->Yres - ypos; /* off by 1 ??? */
+ /*printk("off screen bottom\n");*/
+ }
+
+ if (xpos < 0) {
+ /* Off-screen to the left */
+ xsz = win->w[plane].xres + xpos;
+ fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8);
+ xpos = 0;
+ /*printk("off screen left\n");*/
+ }
+
+ if (ypos < 0) {
+ /* Off-screen to the top */
+ ysz = win->w[plane].yres + ypos;
+ /* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */
+ ypos = 0;
+ /*printk("off screen top\n");*/
+ }
+
+ /* record settings */
+ win->w[plane].xpos = xpos;
+ win->w[plane].ypos = ypos;
+
+ xsz -= 1;
+ ysz -= 1;
+ winctrl0 |= (xpos << 21);
+ winctrl0 |= (ypos << 10);
+ winctrl1 |= (xsz << 11);
+ winctrl1 |= (ysz << 0);
+
+ /* Disable the window while making changes, then restore WINEN */
+ winenable = lcd->winenable & (1 << plane);
+ au_sync();
+ lcd->winenable &= ~(1 << plane);
+ lcd->window[plane].winctrl0 = winctrl0;
+ lcd->window[plane].winctrl1 = winctrl1;
+ lcd->window[plane].winbuf0 =
+ lcd->window[plane].winbuf1 = fbdev->fb_phys;
+ lcd->window[plane].winbufctrl = 0; /* select winbuf0 */
+ lcd->winenable |= winenable;
+ au_sync();
+
+ return 0;
+}
+
+static void au1200_setpanel (struct panel_settings *newpanel)
+{
+ /*
+ * Perform global setup/init of LCD controller
+ */
+ uint32 winenable;
+
+ /* Make sure all windows disabled */
+ winenable = lcd->winenable;
+ lcd->winenable = 0;
+ au_sync();
+ /*
+ * Ensure everything is disabled before reconfiguring
+ */
+ if (lcd->screen & LCD_SCREEN_SEN) {
+ /* Wait for vertical sync period */
+ lcd->intstatus = LCD_INT_SS;
+ while ((lcd->intstatus & LCD_INT_SS) == 0) {
+ au_sync();
+ }
+
+ lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/
+
+ do {
+ lcd->intstatus = lcd->intstatus; /*clear interrupts*/
+ au_sync();
+ /*wait for controller to shut down*/
+ } while ((lcd->intstatus & LCD_INT_SD) == 0);
+
+ /* Call shutdown of current panel (if up) */
+ /* this must occur last, because if an external clock is driving
+ the controller, the clock cannot be turned off before first
+ shutting down the controller.
+ */
+ if (panel->device_shutdown != NULL)
+ panel->device_shutdown();
+ }
+
+ /* Newpanel == NULL indicates a shutdown operation only */
+ if (newpanel == NULL)
+ return;
+
+ panel = newpanel;
+
+ printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres);
+
+ /*
+ * Setup clocking if internal LCD clock source (assumes sys_auxpll valid)
+ */
+ if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT))
+ {
+ uint32 sys_clksrc;
+ au_writel(panel->mode_auxpll, SYS_AUXPLL);
+ sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f;
+ sys_clksrc |= panel->mode_toyclksrc;
+ au_writel(sys_clksrc, SYS_CLKSRC);
+ }
+
+ /*
+ * Configure panel timings
+ */
+ lcd->screen = panel->mode_screen;
+ lcd->horztiming = panel->mode_horztiming;
+ lcd->verttiming = panel->mode_verttiming;
+ lcd->clkcontrol = panel->mode_clkcontrol;
+ lcd->pwmdiv = panel->mode_pwmdiv;
+ lcd->pwmhi = panel->mode_pwmhi;
+ lcd->outmask = panel->mode_outmask;
+ lcd->fifoctrl = panel->mode_fifoctrl;
+ au_sync();
+
+ /* fixme: Check window settings to make sure still valid
+ * for new geometry */
+#if 0
+ au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos);
+ au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos);
+ au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos);
+ au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos);
+#endif
+ lcd->winenable = winenable;
+
+ /*
+ * Re-enable screen now that it is configured
+ */
+ lcd->screen |= LCD_SCREEN_SEN;
+ au_sync();
+
+ /* Call init of panel */
+ if (panel->device_init != NULL) panel->device_init();
+
+ /* FIX!!!! not appropriate on panel change!!! Global setup/init */
+ lcd->intenable = 0;
+ lcd->intstatus = ~0;
+ lcd->backcolor = win->mode_backcolor;
+
+ /* Setup Color Key - FIX!!! */
+ lcd->colorkey = win->mode_colorkey;
+ lcd->colorkeymsk = win->mode_colorkeymsk;
+
+ /* Setup HWCursor - FIX!!! Need to support this eventually */
+ lcd->hwc.cursorctrl = 0;
+ lcd->hwc.cursorpos = 0;
+ lcd->hwc.cursorcolor0 = 0;
+ lcd->hwc.cursorcolor1 = 0;
+ lcd->hwc.cursorcolor2 = 0;
+ lcd->hwc.cursorcolor3 = 0;
+
+
+#if 0
+#define D(X) printk("%25s: %08X\n", #X, X)
+ D(lcd->screen);
+ D(lcd->horztiming);
+ D(lcd->verttiming);
+ D(lcd->clkcontrol);
+ D(lcd->pwmdiv);
+ D(lcd->pwmhi);
+ D(lcd->outmask);
+ D(lcd->fifoctrl);
+ D(lcd->window[0].winctrl0);
+ D(lcd->window[0].winctrl1);
+ D(lcd->window[0].winctrl2);
+ D(lcd->window[0].winbuf0);
+ D(lcd->window[0].winbuf1);
+ D(lcd->window[0].winbufctrl);
+ D(lcd->window[1].winctrl0);
+ D(lcd->window[1].winctrl1);
+ D(lcd->window[1].winctrl2);
+ D(lcd->window[1].winbuf0);
+ D(lcd->window[1].winbuf1);
+ D(lcd->window[1].winbufctrl);
+ D(lcd->window[2].winctrl0);
+ D(lcd->window[2].winctrl1);
+ D(lcd->window[2].winctrl2);
+ D(lcd->window[2].winbuf0);
+ D(lcd->window[2].winbuf1);
+ D(lcd->window[2].winbufctrl);
+ D(lcd->window[3].winctrl0);
+ D(lcd->window[3].winctrl1);
+ D(lcd->window[3].winctrl2);
+ D(lcd->window[3].winbuf0);
+ D(lcd->window[3].winbuf1);
+ D(lcd->window[3].winbufctrl);
+ D(lcd->winenable);
+ D(lcd->intenable);
+ D(lcd->intstatus);
+ D(lcd->backcolor);
+ D(lcd->winenable);
+ D(lcd->colorkey);
+ D(lcd->colorkeymsk);
+ D(lcd->hwc.cursorctrl);
+ D(lcd->hwc.cursorpos);
+ D(lcd->hwc.cursorcolor0);
+ D(lcd->hwc.cursorcolor1);
+ D(lcd->hwc.cursorcolor2);
+ D(lcd->hwc.cursorcolor3);
+#endif
+}
+
+static void au1200_setmode(struct au1200fb_device *fbdev)
+{
+ int plane = fbdev->plane;
+ /* Window/plane setup */
+ lcd->window[plane].winctrl1 = ( 0
+ | LCD_WINCTRL1_PRI_N(plane)
+ | win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */
+ ) ;
+
+ au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos);
+
+ lcd->window[plane].winctrl2 = ( 0
+ | LCD_WINCTRL2_CKMODE_00
+ | LCD_WINCTRL2_DBM
+ | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length)
+ | LCD_WINCTRL2_SCX_1
+ | LCD_WINCTRL2_SCY_1
+ ) ;
+ lcd->winenable |= win->w[plane].mode_winenable;
+ au_sync();
+}
+
+
+/* Inline helpers */
+
+/*#define panel_is_dual(panel) ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
+/*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
+
+#define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN)
+
+/* Bitfields format supported by the controller. */
+static struct fb_bitfield rgb_bitfields[][4] = {
+ /* Red, Green, Blue, Transp */
+ [LCD_WINCTRL1_FRM_16BPP655 >> 25] =
+ { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPP565 >> 25] =
+ { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPP556 >> 25] =
+ { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPPI1555 >> 25] =
+ { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPPI5551 >> 25] =
+ { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPPA1555 >> 25] =
+ { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPPA5551 >> 25] =
+ { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } },
+
+ [LCD_WINCTRL1_FRM_24BPP >> 25] =
+ { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_32BPP >> 25] =
+ { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } },
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Helpers */
+
+static void au1200fb_update_fbinfo(struct fb_info *fbi)
+{
+ /* FIX!!!! This also needs to take the window pixel format into account!!! */
+
+ /* Update var-dependent FB info */
+ if (panel_is_color(panel)) {
+ if (fbi->var.bits_per_pixel <= 8) {
+ /* palettized */
+ fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ fbi->fix.line_length = fbi->var.xres_virtual /
+ (8/fbi->var.bits_per_pixel);
+ } else {
+ /* non-palettized */
+ fbi->fix.visual = FB_VISUAL_TRUECOLOR;
+ fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8);
+ }
+ } else {
+ /* mono FIX!!! mono 8 and 4 bits */
+ fbi->fix.visual = FB_VISUAL_MONO10;
+ fbi->fix.line_length = fbi->var.xres_virtual / 8;
+ }
+
+ fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual;
+ print_dbg("line length: %d\n", fbi->fix.line_length);
+ print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* AU1200 framebuffer driver */
+
+/* fb_check_var
+ * Validate var settings with hardware restrictions and modify it if necessary
+ */
+static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *fbi)
+{
+ struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
+ u32 pixclock;
+ int screen_size, plane;
+
+ plane = fbdev->plane;
+
+ /* Make sure that the mode respect all LCD controller and
+ * panel restrictions. */
+ var->xres = win->w[plane].xres;
+ var->yres = win->w[plane].yres;
+
+ /* No need for virtual resolution support */
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres;
+
+ var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1);
+
+ screen_size = var->xres_virtual * var->yres_virtual;
+ if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8);
+ else screen_size /= (8/var->bits_per_pixel);
+
+ if (fbdev->fb_len < screen_size)
+ return -EINVAL; /* Virtual screen is to big, abort */
+
+ /* FIX!!!! what are the implicaitons of ignoring this for windows ??? */
+ /* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel
+ * clock can only be obtain by dividing this value by an even integer.
+ * Fallback to a slower pixel clock if necessary. */
+ pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin);
+ pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2));
+
+ if (AU1200_LCD_MAX_CLK % pixclock) {
+ int diff = AU1200_LCD_MAX_CLK % pixclock;
+ pixclock -= diff;
+ }
+
+ var->pixclock = KHZ2PICOS(pixclock/1000);
+#if 0
+ if (!panel_is_active(panel)) {
+ int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1;
+
+ if (!panel_is_color(panel)
+ && (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) {
+ /* STN 8bit mono panel support is up to 6MHz pixclock */
+ var->pixclock = KHZ2PICOS(6000);
+ } else if (!pcd) {
+ /* Other STN panel support is up to 12MHz */
+ var->pixclock = KHZ2PICOS(12000);
+ }
+ }
+#endif
+ /* Set bitfield accordingly */
+ switch (var->bits_per_pixel) {
+ case 16:
+ {
+ /* 16bpp True color.
+ * These must be set to MATCH WINCTRL[FORM] */
+ int idx;
+ idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
+ var->red = rgb_bitfields[idx][0];
+ var->green = rgb_bitfields[idx][1];
+ var->blue = rgb_bitfields[idx][2];
+ var->transp = rgb_bitfields[idx][3];
+ break;
+ }
+
+ case 32:
+ {
+ /* 32bpp True color.
+ * These must be set to MATCH WINCTRL[FORM] */
+ int idx;
+ idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
+ var->red = rgb_bitfields[idx][0];
+ var->green = rgb_bitfields[idx][1];
+ var->blue = rgb_bitfields[idx][2];
+ var->transp = rgb_bitfields[idx][3];
+ break;
+ }
+ default:
+ print_dbg("Unsupported depth %dbpp", var->bits_per_pixel);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* fb_set_par
+ * Set hardware with var settings. This will enable the controller with a
+ * specific mode, normally validated with the fb_check_var method
+ */
+static int au1200fb_fb_set_par(struct fb_info *fbi)
+{
+ struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
+
+ au1200fb_update_fbinfo(fbi);
+ au1200_setmode(fbdev);
+
+ return 0;
+}
+
+/* fb_setcolreg
+ * Set color in LCD palette.
+ */
+static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp, struct fb_info *fbi)
+{
+ volatile u32 *palette = lcd->palette;
+ u32 value;
+
+ if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1))
+ return -EINVAL;
+
+ if (fbi->var.grayscale) {
+ /* Convert color to grayscale */
+ red = green = blue =
+ (19595 * red + 38470 * green + 7471 * blue) >> 16;
+ }
+
+ if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) {
+ /* Place color in the pseudopalette */
+ if (regno > 16)
+ return -EINVAL;
+
+ palette = (u32*) fbi->pseudo_palette;
+
+ red >>= (16 - fbi->var.red.length);
+ green >>= (16 - fbi->var.green.length);
+ blue >>= (16 - fbi->var.blue.length);
+
+ value = (red << fbi->var.red.offset) |
+ (green << fbi->var.green.offset)|
+ (blue << fbi->var.blue.offset);
+ value &= 0xFFFF;
+
+ } else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) {
+ /* COLOR TFT PALLETTIZED (use RGB 565) */
+ value = (red & 0xF800)|((green >> 5) &
+ 0x07E0)|((blue >> 11) & 0x001F);
+ value &= 0xFFFF;
+
+ } else if (0 /*panel_is_color(fbdev->panel)*/) {
+ /* COLOR STN MODE */
+ value = 0x1234;
+ value &= 0xFFF;
+ } else {
+ /* MONOCHROME MODE */
+ value = (green >> 12) & 0x000F;
+ value &= 0xF;
+ }
+
+ palette[regno] = value;
+
+ return 0;
+}
+
+/* fb_blank
+ * Blank the screen. Depending on the mode, the screen will be
+ * activated with the backlight color, or desactivated
+ */
+static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi)
+{
+ /* Short-circuit screen blanking */
+ if (noblanking)
+ return 0;
+
+ switch (blank_mode) {
+
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ /* printk("turn on panel\n"); */
+ au1200_setpanel(panel);
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_POWERDOWN:
+ /* printk("turn off panel\n"); */
+ au1200_setpanel(NULL);
+ break;
+ default:
+ break;
+
+ }
+
+ /* FB_BLANK_NORMAL is a soft blank */
+ return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0;
+}
+
+/* fb_mmap
+ * Map video memory in user space. We don't use the generic fb_mmap
+ * method mainly to allow the use of the TLB streaming flag (CCA=6)
+ */
+static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+
+{
+ unsigned int len;
+ unsigned long start=0, off;
+ struct au1200fb_device *fbdev = (struct au1200fb_device *) info;
+
+#ifdef CONFIG_PM
+ au1xxx_pm_access(LCD_pm_dev);
+#endif
+
+ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
+ return -EINVAL;
+ }
+
+ start = fbdev->fb_phys & PAGE_MASK;
+ len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len);
+
+ off = vma->vm_pgoff << PAGE_SHIFT;
+
+ if ((vma->vm_end - vma->vm_start + off) > len) {
+ return -EINVAL;
+ }
+
+ off += start;
+ vma->vm_pgoff = off >> PAGE_SHIFT;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */
+
+ vma->vm_flags |= VM_IO;
+
+ return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+
+ return 0;
+}
+
+static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
+{
+
+ unsigned int hi1, divider;
+
+ /* SCREEN_SIZE: user cannot reset size, must switch panel choice */
+
+ if (pdata->flags & SCREEN_BACKCOLOR)
+ lcd->backcolor = pdata->backcolor;
+
+ if (pdata->flags & SCREEN_BRIGHTNESS) {
+
+ // limit brightness pwm duty to >= 30/1600
+ if (pdata->brightness < 30) {
+ pdata->brightness = 30;
+ }
+ divider = (lcd->pwmdiv & 0x3FFFF) + 1;
+ hi1 = (lcd->pwmhi >> 16) + 1;
+ hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8);
+ lcd->pwmhi &= 0xFFFF;
+ lcd->pwmhi |= (hi1 << 16);
+ }
+
+ if (pdata->flags & SCREEN_COLORKEY)
+ lcd->colorkey = pdata->colorkey;
+
+ if (pdata->flags & SCREEN_MASK)
+ lcd->colorkeymsk = pdata->mask;
+ au_sync();
+}
+
+static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
+{
+ unsigned int hi1, divider;
+
+ pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1;
+ pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1;
+
+ pdata->backcolor = lcd->backcolor;
+ pdata->colorkey = lcd->colorkey;
+ pdata->mask = lcd->colorkeymsk;
+
+ // brightness
+ hi1 = (lcd->pwmhi >> 16) + 1;
+ divider = (lcd->pwmdiv & 0x3FFFF) + 1;
+ pdata->brightness = ((hi1 << 8) / divider) - 1;
+ au_sync();
+}
+
+static void set_window(unsigned int plane,
+ struct au1200_lcd_window_regs_t *pdata)
+{
+ unsigned int val, bpp;
+
+ /* Window control register 0 */
+ if (pdata->flags & WIN_POSITION) {
+ val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX |
+ LCD_WINCTRL0_OY);
+ val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX);
+ val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY);
+ lcd->window[plane].winctrl0 = val;
+ }
+ if (pdata->flags & WIN_ALPHA_COLOR) {
+ val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A);
+ val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A);
+ lcd->window[plane].winctrl0 = val;
+ }
+ if (pdata->flags & WIN_ALPHA_MODE) {
+ val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN);
+ val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN);
+ lcd->window[plane].winctrl0 = val;
+ }
+
+ /* Window control register 1 */
+ if (pdata->flags & WIN_PRIORITY) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI);
+ val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_CHANNEL) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE);
+ val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_BUFFER_FORMAT) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM);
+ val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_COLOR_ORDER) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO);
+ val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_PIXEL_ORDER) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO);
+ val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_SIZE) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX |
+ LCD_WINCTRL1_SZY);
+ val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX);
+ val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY);
+ lcd->window[plane].winctrl1 = val;
+ /* program buffer line width */
+ bpp = winbpp(val) / 8;
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX);
+ val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX);
+ lcd->window[plane].winctrl2 = val;
+ }
+
+ /* Window control register 2 */
+ if (pdata->flags & WIN_COLORKEY_MODE) {
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE);
+ val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE);
+ lcd->window[plane].winctrl2 = val;
+ }
+ if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) {
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM);
+ val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM);
+ lcd->window[plane].winctrl2 = val;
+ }
+ if (pdata->flags & WIN_RAM_ARRAY_MODE) {
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM);
+ val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM);
+ lcd->window[plane].winctrl2 = val;
+ }
+
+ /* Buffer line width programmed with WIN_SIZE */
+
+ if (pdata->flags & WIN_BUFFER_SCALE) {
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX |
+ LCD_WINCTRL2_SCY);
+ val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX);
+ val |= ((pdata->ysize) & LCD_WINCTRL2_SCY);
+ lcd->window[plane].winctrl2 = val;
+ }
+
+ if (pdata->flags & WIN_ENABLE) {
+ val = lcd->winenable;
+ val &= ~(1<<plane);
+ val |= (pdata->enable & 1) << plane;
+ lcd->winenable = val;
+ }
+ au_sync();
+}
+
+static void get_window(unsigned int plane,
+ struct au1200_lcd_window_regs_t *pdata)
+{
+ /* Window control register 0 */
+ pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21;
+ pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10;
+ pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2;
+ pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1;
+
+ /* Window control register 1 */
+ pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30;
+ pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29;
+ pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25;
+ pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24;
+ pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22;
+ pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1;
+ pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1;
+
+ /* Window control register 2 */
+ pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24;
+ pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23;
+ pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21;
+
+ pdata->enable = (lcd->winenable >> plane) & 1;
+ au_sync();
+}
+
+static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+{
+ int plane;
+ int val;
+
+#ifdef CONFIG_PM
+ au1xxx_pm_access(LCD_pm_dev);
+#endif
+
+ plane = fbinfo2index(info);
+ print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane);
+
+ if (cmd == AU1200_LCD_FB_IOCTL) {
+ struct au1200_lcd_iodata_t iodata;
+
+ if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata)))
+ return -EFAULT;
+
+ print_dbg("FB IOCTL called\n");
+
+ switch (iodata.subcmd) {
+ case AU1200_LCD_SET_SCREEN:
+ print_dbg("AU1200_LCD_SET_SCREEN\n");
+ set_global(cmd, &iodata.global);
+ break;
+
+ case AU1200_LCD_GET_SCREEN:
+ print_dbg("AU1200_LCD_GET_SCREEN\n");
+ get_global(cmd, &iodata.global);
+ break;
+
+ case AU1200_LCD_SET_WINDOW:
+ print_dbg("AU1200_LCD_SET_WINDOW\n");
+ set_window(plane, &iodata.window);
+ break;
+
+ case AU1200_LCD_GET_WINDOW:
+ print_dbg("AU1200_LCD_GET_WINDOW\n");
+ get_window(plane, &iodata.window);
+ break;
+
+ case AU1200_LCD_SET_PANEL:
+ print_dbg("AU1200_LCD_SET_PANEL\n");
+ if ((iodata.global.panel_choice >= 0) &&
+ (iodata.global.panel_choice <
+ NUM_PANELS))
+ {
+ struct panel_settings *newpanel;
+ panel_index = iodata.global.panel_choice;
+ newpanel = &known_lcd_panels[panel_index];
+ au1200_setpanel(newpanel);
+ }
+ break;
+
+ case AU1200_LCD_GET_PANEL:
+ print_dbg("AU1200_LCD_GET_PANEL\n");
+ iodata.global.panel_choice = panel_index;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata));
+ if (val) {
+ print_dbg("error: could not copy %d bytes\n", val);
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+
+static struct fb_ops au1200fb_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = au1200fb_fb_check_var,
+ .fb_set_par = au1200fb_fb_set_par,
+ .fb_setcolreg = au1200fb_fb_setcolreg,
+ .fb_blank = au1200fb_fb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_sync = NULL,
+ .fb_ioctl = au1200fb_ioctl,
+ .fb_mmap = au1200fb_fb_mmap,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs)
+{
+ /* Nothing to do for now, just clear any pending interrupt */
+ lcd->intstatus = lcd->intstatus;
+ au_sync();
+
+ return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* AU1200 LCD device probe helpers */
+
+static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
+{
+ struct fb_info *fbi = &fbdev->fb_info;
+ int bpp;
+
+ memset(fbi, 0, sizeof(struct fb_info));
+ fbi->fbops = &au1200fb_fb_ops;
+
+ bpp = winbpp(win->w[fbdev->plane].mode_winctrl1);
+
+ /* Copy monitor specs from panel data */
+ /* fixme: we're setting up LCD controller windows, so these dont give a
+ damn as to what the monitor specs are (the panel itself does, but that
+ isnt done here...so maybe need a generic catchall monitor setting??? */
+ memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs));
+
+ /* We first try the user mode passed in argument. If that failed,
+ * or if no one has been specified, we default to the first mode of the
+ * panel list. Note that after this call, var data will be set */
+ if (!fb_find_mode(&fbi->var,
+ fbi,
+ NULL, /* drv_info.opt_mode, */
+ fbi->monspecs.modedb,
+ fbi->monspecs.modedb_len,
+ fbi->monspecs.modedb,
+ bpp)) {
+
+ print_err("Cannot find valid mode for panel %s", panel->name);
+ return -EFAULT;
+ }
+
+ fbi->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
+ if (!fbi->pseudo_palette) {
+ return -ENOMEM;
+ }
+ memset(fbi->pseudo_palette, 0, sizeof(u32) * 16);
+
+ if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
+ print_err("Fail to allocate colormap (%d entries)",
+ AU1200_LCD_NBR_PALETTE_ENTRIES);
+ kfree(fbi->pseudo_palette);
+ return -EFAULT;
+ }
+
+ strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id));
+ fbi->fix.smem_start = fbdev->fb_phys;
+ fbi->fix.smem_len = fbdev->fb_len;
+ fbi->fix.type = FB_TYPE_PACKED_PIXELS;
+ fbi->fix.xpanstep = 0;
+ fbi->fix.ypanstep = 0;
+ fbi->fix.mmio_start = 0;
+ fbi->fix.mmio_len = 0;
+ fbi->fix.accel = FB_ACCEL_NONE;
+
+ fbi->screen_base = (char __iomem *) fbdev->fb_mem;
+
+ au1200fb_update_fbinfo(fbi);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* AU1200 LCD controller device driver */
+
+static int au1200fb_drv_probe(struct device *dev)
+{
+ struct au1200fb_device *fbdev;
+ unsigned long page;
+ int bpp, plane, ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
+ bpp = winbpp(win->w[plane].mode_winctrl1);
+ if (win->w[plane].xres == 0)
+ win->w[plane].xres = panel->Xres;
+ if (win->w[plane].yres == 0)
+ win->w[plane].yres = panel->Yres;
+
+ fbdev = &_au1200fb_devices[plane];
+ memset(fbdev, 0, sizeof(struct au1200fb_device));
+ fbdev->plane = plane;
+
+ /* Allocate the framebuffer to the maximum screen size */
+ fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;
+
+ fbdev->fb_mem = dma_alloc_noncoherent(dev,
+ PAGE_ALIGN(fbdev->fb_len),
+ &fbdev->fb_phys, GFP_KERNEL);
+ if (!fbdev->fb_mem) {
+ print_err("fail to allocate frambuffer (size: %dK))",
+ fbdev->fb_len / 1024);
+ return -ENOMEM;
+ }
+
+ /*
+ * Set page reserved so that mmap will work. This is necessary
+ * since we'll be remapping normal memory.
+ */
+ for (page = (unsigned long)fbdev->fb_phys;
+ page < PAGE_ALIGN((unsigned long)fbdev->fb_phys +
+ fbdev->fb_len);
+ page += PAGE_SIZE) {
+ SetPageReserved(pfn_to_page(page >> PAGE_SHIFT)); /* LCD DMA is NOT coherent on Au1200 */
+ }
+ print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
+ print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
+
+ /* Init FB data */
+ if ((ret = au1200fb_init_fbinfo(fbdev)) < 0)
+ goto failed;
+
+ /* Register new framebuffer */
+ if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) {
+ print_err("cannot register new framebuffer");
+ goto failed;
+ }
+
+ au1200fb_fb_set_par(&fbdev->fb_info);
+
+#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
+ if (plane == 0)
+ if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) {
+ /* Start display and show logo on boot */
+ fb_set_cmap(&fbdev->fb_info.cmap,
+ &fbdev->fb_info);
+
+ fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR);
+ }
+#endif
+ }
+
+ /* Now hook interrupt too */
+ if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq,
+ SA_INTERRUPT | SA_SHIRQ, "lcd", (void *)dev)) < 0) {
+ print_err("fail to request interrupt line %d (err: %d)",
+ AU1200_LCD_INT, ret);
+ goto failed;
+ }
+
+ return 0;
+
+failed:
+ /* NOTE: This only does the current plane/window that failed; others are still active */
+ if (fbdev->fb_mem)
+ dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len),
+ fbdev->fb_mem, fbdev->fb_phys);
+ if (fbdev->fb_info.cmap.len != 0)
+ fb_dealloc_cmap(&fbdev->fb_info.cmap);
+ if (fbdev->fb_info.pseudo_palette)
+ kfree(fbdev->fb_info.pseudo_palette);
+ if (plane == 0)
+ free_irq(AU1200_LCD_INT, (void*)dev);
+ return ret;
+}
+
+static int au1200fb_drv_remove(struct device *dev)
+{
+ struct au1200fb_device *fbdev;
+ int plane;
+
+ if (!dev)
+ return -ENODEV;
+
+ /* Turn off the panel */
+ au1200_setpanel(NULL);
+
+ for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane)
+ {
+ fbdev = &_au1200fb_devices[plane];
+
+ /* Clean up all probe data */
+ unregister_framebuffer(&fbdev->fb_info);
+ if (fbdev->fb_mem)
+ dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len),
+ fbdev->fb_mem, fbdev->fb_phys);
+ if (fbdev->fb_info.cmap.len != 0)
+ fb_dealloc_cmap(&fbdev->fb_info.cmap);
+ if (fbdev->fb_info.pseudo_palette)
+ kfree(fbdev->fb_info.pseudo_palette);
+ }
+
+ free_irq(AU1200_LCD_INT, (void *)dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int au1200fb_drv_suspend(struct device *dev, u32 state, u32 level)
+{
+ /* TODO */
+ return 0;
+}
+
+static int au1200fb_drv_resume(struct device *dev, u32 level)
+{
+ /* TODO */
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct device_driver au1200fb_driver = {
+ .name = "au1200-lcd",
+ .bus = &platform_bus_type,
+ .probe = au1200fb_drv_probe,
+ .remove = au1200fb_drv_remove,
+#ifdef CONFIG_PM
+ .suspend = au1200fb_drv_suspend,
+ .resume = au1200fb_drv_resume,
+#endif
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Kernel driver */
+
+static void au1200fb_setup(void)
+{
+ char* options = NULL;
+ char* this_opt;
+ int num_panels = ARRAY_SIZE(known_lcd_panels);
+ int panel_idx = -1;
+
+ fb_get_options(DRIVER_NAME, &options);
+
+ if (options) {
+ while ((this_opt = strsep(&options,",")) != NULL) {
+ /* Panel option - can be panel name,
+ * "bs" for board-switch, or number/index */
+ if (!strncmp(this_opt, "panel:", 6)) {
+ int i;
+ long int li;
+ char *endptr;
+ this_opt += 6;
+ /* First check for index, which allows
+ * to short circuit this mess */
+ li = simple_strtol(this_opt, &endptr, 0);
+ if (*endptr == '\0') {
+ panel_idx = (int)li;
+ }
+ else if (strcmp(this_opt, "bs") == 0) {
+ extern int board_au1200fb_panel(void);
+ panel_idx = board_au1200fb_panel();
+ }
+
+ else
+ for (i = 0; i < num_panels; i++) {
+ if (!strcmp(this_opt, known_lcd_panels[i].name)) {
+ panel_idx = i;
+ break;
+ }
+ }
+
+ if ((panel_idx < 0) || (panel_idx >= num_panels)) {
+ print_warn("Panel %s not supported!", this_opt);
+ }
+ else
+ panel_index = panel_idx;
+ }
+
+ else if (strncmp(this_opt, "nohwcursor", 10) == 0) {
+ nohwcursor = 1;
+ }
+
+ /* Unsupported option */
+ else {
+ print_warn("Unsupported option \"%s\"", this_opt);
+ }
+ }
+ }
+}
+
+#ifdef CONFIG_PM
+static int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
+ au1xxx_request_t request, void *data) {
+ int retval = -1;
+ unsigned int d = 0;
+ unsigned int brightness = 0;
+
+ if (request == AU1XXX_PM_SLEEP) {
+ board_au1200fb_panel_shutdown();
+ }
+ else if (request == AU1XXX_PM_WAKEUP) {
+ if(dev->prev_state == SLEEP_STATE)
+ {
+ int plane;
+ au1200_setpanel(panel);
+ for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
+ struct au1200fb_device *fbdev;
+ fbdev = &_au1200fb_devices[plane];
+ au1200fb_fb_set_par(&fbdev->fb_info);
+ }
+ }
+
+ d = *((unsigned int*)data);
+ if(d <=10) brightness = 26;
+ else if(d<=20) brightness = 51;
+ else if(d<=30) brightness = 77;
+ else if(d<=40) brightness = 102;
+ else if(d<=50) brightness = 128;
+ else if(d<=60) brightness = 153;
+ else if(d<=70) brightness = 179;
+ else if(d<=80) brightness = 204;
+ else if(d<=90) brightness = 230;
+ else brightness = 255;
+ set_brightness(brightness);
+ } else if (request == AU1XXX_PM_GETSTATUS) {
+ return dev->cur_state;
+ } else if (request == AU1XXX_PM_ACCESS) {
+ if (dev->cur_state != SLEEP_STATE)
+ return retval;
+ else {
+ au1200_setpanel(panel);
+ }
+ } else if (request == AU1XXX_PM_IDLE) {
+ } else if (request == AU1XXX_PM_CLEANUP) {
+ }
+
+ return retval;
+}
+#endif
+
+static int __init au1200fb_init(void)
+{
+ print_info("" DRIVER_DESC "");
+
+ /* Setup driver with options */
+ au1200fb_setup();
+
+ /* Point to the panel selected */
+ panel = &known_lcd_panels[panel_index];
+ win = &windows[window_index];
+
+ printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
+ printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
+
+ /* Kickstart the panel, the framebuffers/windows come soon enough */
+ au1200_setpanel(panel);
+
+ #ifdef CONFIG_PM
+ LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL);
+ if ( LCD_pm_dev == NULL)
+ printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n");
+ else
+ printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n");
+ #endif
+
+ return driver_register(&au1200fb_driver);
+}
+
+static void __exit au1200fb_cleanup(void)
+{
+ driver_unregister(&au1200fb_driver);
+}
+
+module_init(au1200fb_init);
+module_exit(au1200fb_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1200 LCD Driver.
+ *
+ * Copyright 2004-2005 AMD
+ * Author: AMD
+ *
+ * Based on:
+ * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
+ * Created 28 Dec 1997 by Geert Uytterhoeven
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ctype.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/mach-au1x00/au1000.h>
+#include "au1200fb.h"
+
+#ifdef CONFIG_PM
+#include <asm/mach-au1x00/au1xxx_pm.h>
+#endif
+
+#ifndef CONFIG_FB_AU1200_DEVS
+#define CONFIG_FB_AU1200_DEVS 4
+#endif
+
+#define DRIVER_NAME "au1200fb"
+#define DRIVER_DESC "LCD controller driver for AU1200 processors"
+
+#define DEBUG 1
+
+#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
+#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
+#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg)
+
+#if DEBUG
+#define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg)
+#else
+#define print_dbg(f, arg...) do {} while (0)
+#endif
+
+
+#define AU1200_LCD_FB_IOCTL 0x46FF
+
+#define AU1200_LCD_SET_SCREEN 1
+#define AU1200_LCD_GET_SCREEN 2
+#define AU1200_LCD_SET_WINDOW 3
+#define AU1200_LCD_GET_WINDOW 4
+#define AU1200_LCD_SET_PANEL 5
+#define AU1200_LCD_GET_PANEL 6
+
+#define SCREEN_SIZE (1<< 1)
+#define SCREEN_BACKCOLOR (1<< 2)
+#define SCREEN_BRIGHTNESS (1<< 3)
+#define SCREEN_COLORKEY (1<< 4)
+#define SCREEN_MASK (1<< 5)
+
+struct au1200_lcd_global_regs_t {
+ unsigned int flags;
+ unsigned int xsize;
+ unsigned int ysize;
+ unsigned int backcolor;
+ unsigned int brightness;
+ unsigned int colorkey;
+ unsigned int mask;
+ unsigned int panel_choice;
+ char panel_desc[80];
+
+};
+
+#define WIN_POSITION (1<< 0)
+#define WIN_ALPHA_COLOR (1<< 1)
+#define WIN_ALPHA_MODE (1<< 2)
+#define WIN_PRIORITY (1<< 3)
+#define WIN_CHANNEL (1<< 4)
+#define WIN_BUFFER_FORMAT (1<< 5)
+#define WIN_COLOR_ORDER (1<< 6)
+#define WIN_PIXEL_ORDER (1<< 7)
+#define WIN_SIZE (1<< 8)
+#define WIN_COLORKEY_MODE (1<< 9)
+#define WIN_DOUBLE_BUFFER_MODE (1<< 10)
+#define WIN_RAM_ARRAY_MODE (1<< 11)
+#define WIN_BUFFER_SCALE (1<< 12)
+#define WIN_ENABLE (1<< 13)
+
+struct au1200_lcd_window_regs_t {
+ unsigned int flags;
+ unsigned int xpos;
+ unsigned int ypos;
+ unsigned int alpha_color;
+ unsigned int alpha_mode;
+ unsigned int priority;
+ unsigned int channel;
+ unsigned int buffer_format;
+ unsigned int color_order;
+ unsigned int pixel_order;
+ unsigned int xsize;
+ unsigned int ysize;
+ unsigned int colorkey_mode;
+ unsigned int double_buffer_mode;
+ unsigned int ram_array_mode;
+ unsigned int xscale;
+ unsigned int yscale;
+ unsigned int enable;
+};
+
+
+struct au1200_lcd_iodata_t {
+ unsigned int subcmd;
+ struct au1200_lcd_global_regs_t global;
+ struct au1200_lcd_window_regs_t window;
+};
+
+#if defined(__BIG_ENDIAN)
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11
+#else
+#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00
+#endif
+#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565
+
+/* Private, per-framebuffer management information (independent of the panel itself) */
+struct au1200fb_device {
+ struct fb_info fb_info; /* FB driver info record */
+
+ int plane;
+ unsigned char* fb_mem; /* FrameBuffer memory map */
+ unsigned int fb_len;
+ dma_addr_t fb_phys;
+};
+
+static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS];
+/********************************************************************/
+
+/* LCD controller restrictions */
+#define AU1200_LCD_MAX_XRES 1280
+#define AU1200_LCD_MAX_YRES 1024
+#define AU1200_LCD_MAX_BPP 32
+#define AU1200_LCD_MAX_CLK 96000000 /* fixme: this needs to go away ? */
+#define AU1200_LCD_NBR_PALETTE_ENTRIES 256
+
+/* Default number of visible screen buffer to allocate */
+#define AU1200FB_NBR_VIDEO_BUFFERS 1
+
+/********************************************************************/
+
+static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR;
+static int window_index = 2; /* default is zero */
+static int panel_index = 2; /* default is zero */
+static struct window_settings *win;
+static struct panel_settings *panel;
+static int noblanking = 1;
+static int nohwcursor = 0;
+
+struct window_settings {
+ unsigned char name[64];
+ uint32 mode_backcolor;
+ uint32 mode_colorkey;
+ uint32 mode_colorkeymsk;
+ struct {
+ int xres;
+ int yres;
+ int xpos;
+ int ypos;
+ uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */
+ uint32 mode_winenable;
+ } w[4];
+};
+
+#if defined(__BIG_ENDIAN)
+#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00
+#else
+#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01
+#endif
+
+extern int board_au1200fb_panel_init (void);
+extern int board_au1200fb_panel_shutdown (void);
+
+#ifdef CONFIG_PM
+int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
+ au1xxx_request_t request, void *data);
+au1xxx_power_dev_t *LCD_pm_dev;
+#endif
+
+/*
+ * Default window configurations
+ */
+static struct window_settings windows[] = {
+ { /* Index 0 */
+ "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
+ /* mode_backcolor */ 0x006600ff,
+ /* mode_colorkey,msk*/ 0, 0,
+ {
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ LCD_WINENABLE_WEN0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 100, 100, 100, 100,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ LCD_WINENABLE_WEN1,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ 0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0,
+ },
+ },
+ },
+
+ { /* Index 1 */
+ "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
+ /* mode_backcolor */ 0x006600ff,
+ /* mode_colorkey,msk*/ 0, 0,
+ {
+ {
+ /* xres, yres, xpos, ypos */ 320, 240, 5, 5,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP |
+ LCD_WINCTRL1_PO_00,
+ /* mode_winenable*/ LCD_WINENABLE_WEN0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565
+ | LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ 0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 100, 100, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 200, 25, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0,
+ },
+ },
+ },
+ { /* Index 2 */
+ "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
+ /* mode_backcolor */ 0x006600ff,
+ /* mode_colorkey,msk*/ 0, 0,
+ {
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ LCD_WINENABLE_WEN0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP,
+ /* mode_winenable*/ 0,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP |
+ LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
+ },
+ {
+ /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
+ /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
+ LCD_WINCTRL1_PO_16BPP |
+ LCD_WINCTRL1_PIPE,
+ /* mode_winenable*/ 0,
+ },
+ },
+ },
+ /* Need VGA 640 @ 24bpp, @ 32bpp */
+ /* Need VGA 800 @ 24bpp, @ 32bpp */
+ /* Need VGA 1024 @ 24bpp, @ 32bpp */
+};
+
+/*
+ * Controller configurations for various panels.
+ */
+
+struct panel_settings
+{
+ const char name[25]; /* Full name <vendor>_<model> */
+
+ struct fb_monspecs monspecs; /* FB monitor specs */
+
+ /* panel timings */
+ uint32 mode_screen;
+ uint32 mode_horztiming;
+ uint32 mode_verttiming;
+ uint32 mode_clkcontrol;
+ uint32 mode_pwmdiv;
+ uint32 mode_pwmhi;
+ uint32 mode_outmask;
+ uint32 mode_fifoctrl;
+ uint32 mode_toyclksrc;
+ uint32 mode_backlight;
+ uint32 mode_auxpll;
+ int (*device_init)(void);
+ int (*device_shutdown)(void);
+#define Xres min_xres
+#define Yres min_yres
+ u32 min_xres; /* Minimum horizontal resolution */
+ u32 max_xres; /* Maximum horizontal resolution */
+ u32 min_yres; /* Minimum vertical resolution */
+ u32 max_yres; /* Maximum vertical resolution */
+};
+
+/********************************************************************/
+/* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */
+
+/* List of panels known to work with the AU1200 LCD controller.
+ * To add a new panel, enter the same specifications as the
+ * Generic_TFT one, and MAKE SURE that it doesn't conflicts
+ * with the controller restrictions. Restrictions are:
+ *
+ * STN color panels: max_bpp <= 12
+ * STN mono panels: max_bpp <= 4
+ * TFT panels: max_bpp <= 16
+ * max_xres <= 800
+ * max_yres <= 600
+ */
+static struct panel_settings known_lcd_panels[] =
+{
+ [0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */
+ .name = "QVGA_320x240",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = LCD_SCREEN_SX_N(320) |
+ LCD_SCREEN_SY_N(240),
+ .mode_horztiming = 0x00c4623b,
+ .mode_verttiming = 0x00502814,
+ .mode_clkcontrol = 0x00020002, /* /4=24Mhz */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 320, 320,
+ 240, 240,
+ },
+
+ [1] = { /* VGA 640x480 H:30.3kHz V:58Hz */
+ .name = "VGA_640x480",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x13f9df80,
+ .mode_horztiming = 0x003c5859,
+ .mode_verttiming = 0x00741201,
+ .mode_clkcontrol = 0x00020001, /* /4=24Mhz */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 640, 480,
+ 640, 480,
+ },
+
+ [2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */
+ .name = "SVGA_800x600",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x18fa5780,
+ .mode_horztiming = 0x00dc7e77,
+ .mode_verttiming = 0x00584805,
+ .mode_clkcontrol = 0x00020000, /* /2=48Mhz */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 800, 800,
+ 600, 600,
+ },
+
+ [3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */
+ .name = "XVGA_1024x768",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x1ffaff80,
+ .mode_horztiming = 0x007d0e57,
+ .mode_verttiming = 0x00740a01,
+ .mode_clkcontrol = 0x000A0000, /* /1 */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 6, /* 72MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 1024, 1024,
+ 768, 768,
+ },
+
+ [4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */
+ .name = "XVGA_1280x1024",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x27fbff80,
+ .mode_horztiming = 0x00cdb2c7,
+ .mode_verttiming = 0x00600002,
+ .mode_clkcontrol = 0x000A0000, /* /1 */
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 10, /* 120MHz AUXPLL */
+ .device_init = NULL,
+ .device_shutdown = NULL,
+ 1280, 1280,
+ 1024, 1024,
+ },
+
+ [5] = { /* Samsung 1024x768 TFT */
+ .name = "Samsung_1024x768_TFT",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = 0x1ffaff80,
+ .mode_horztiming = 0x018cc677,
+ .mode_verttiming = 0x00241217,
+ .mode_clkcontrol = 0x00000000, /* SCB 0x1 /4=24Mhz */
+ .mode_pwmdiv = 0x8000063f, /* SCB 0x0 */
+ .mode_pwmhi = 0x03400000, /* SCB 0x0 */
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = board_au1200fb_panel_init,
+ .device_shutdown = board_au1200fb_panel_shutdown,
+ 1024, 1024,
+ 768, 768,
+ },
+
+ [6] = { /* Toshiba 640x480 TFT */
+ .name = "Toshiba_640x480_TFT",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = LCD_SCREEN_SX_N(640) |
+ LCD_SCREEN_SY_N(480),
+ .mode_horztiming = LCD_HORZTIMING_HPW_N(96) |
+ LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51),
+ .mode_verttiming = LCD_VERTTIMING_VPW_N(2) |
+ LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32),
+ .mode_clkcontrol = 0x00000000, /* /4=24Mhz */
+ .mode_pwmdiv = 0x8000063f,
+ .mode_pwmhi = 0x03400000,
+ .mode_outmask = 0x00fcfcfc,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = board_au1200fb_panel_init,
+ .device_shutdown = board_au1200fb_panel_shutdown,
+ 640, 480,
+ 640, 480,
+ },
+
+ [7] = { /* Sharp 320x240 TFT */
+ .name = "Sharp_320x240_TFT",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 12500,
+ .hfmax = 20000,
+ .vfmin = 38,
+ .vfmax = 81,
+ .dclkmin = 4500000,
+ .dclkmax = 6800000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = LCD_SCREEN_SX_N(320) |
+ LCD_SCREEN_SY_N(240),
+ .mode_horztiming = LCD_HORZTIMING_HPW_N(60) |
+ LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2),
+ .mode_verttiming = LCD_VERTTIMING_VPW_N(2) |
+ LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5),
+ .mode_clkcontrol = LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/
+ .mode_pwmdiv = 0x8000063f,
+ .mode_pwmhi = 0x03400000,
+ .mode_outmask = 0x00fcfcfc,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = board_au1200fb_panel_init,
+ .device_shutdown = board_au1200fb_panel_shutdown,
+ 320, 320,
+ 240, 240,
+ },
+
+ [8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */
+ .name = "Toppoly_TD070WGCB2",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = LCD_SCREEN_SX_N(856) |
+ LCD_SCREEN_SY_N(480),
+ .mode_horztiming = LCD_HORZTIMING_HND2_N(43) |
+ LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114),
+ .mode_verttiming = LCD_VERTTIMING_VND2_N(20) |
+ LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4),
+ .mode_clkcontrol = 0x00020001, /* /4=24Mhz */
+ .mode_pwmdiv = 0x8000063f,
+ .mode_pwmhi = 0x03400000,
+ .mode_outmask = 0x00fcfcfc,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = 8, /* 96MHz AUXPLL */
+ .device_init = board_au1200fb_panel_init,
+ .device_shutdown = board_au1200fb_panel_shutdown,
+ 856, 856,
+ 480, 480,
+ },
+};
+
+#define NUM_PANELS (ARRAY_SIZE(known_lcd_panels))
+
+/********************************************************************/
+
+#ifdef CONFIG_PM
+static int set_brightness(unsigned int brightness)
+{
+ unsigned int hi1, divider;
+
+ /* limit brightness pwm duty to >= 30/1600 */
+ if (brightness < 30) {
+ brightness = 30;
+ }
+ divider = (lcd->pwmdiv & 0x3FFFF) + 1;
+ hi1 = (lcd->pwmhi >> 16) + 1;
+ hi1 = (((brightness & 0xFF) + 1) * divider >> 8);
+ lcd->pwmhi &= 0xFFFF;
+ lcd->pwmhi |= (hi1 << 16);
+
+ return brightness;
+}
+#endif /* CONFIG_PM */
+
+static int winbpp (unsigned int winctrl1)
+{
+ int bits = 0;
+
+ /* how many bits are needed for each pixel format */
+ switch (winctrl1 & LCD_WINCTRL1_FRM) {
+ case LCD_WINCTRL1_FRM_1BPP:
+ bits = 1;
+ break;
+ case LCD_WINCTRL1_FRM_2BPP:
+ bits = 2;
+ break;
+ case LCD_WINCTRL1_FRM_4BPP:
+ bits = 4;
+ break;
+ case LCD_WINCTRL1_FRM_8BPP:
+ bits = 8;
+ break;
+ case LCD_WINCTRL1_FRM_12BPP:
+ case LCD_WINCTRL1_FRM_16BPP655:
+ case LCD_WINCTRL1_FRM_16BPP565:
+ case LCD_WINCTRL1_FRM_16BPP556:
+ case LCD_WINCTRL1_FRM_16BPPI1555:
+ case LCD_WINCTRL1_FRM_16BPPI5551:
+ case LCD_WINCTRL1_FRM_16BPPA1555:
+ case LCD_WINCTRL1_FRM_16BPPA5551:
+ bits = 16;
+ break;
+ case LCD_WINCTRL1_FRM_24BPP:
+ case LCD_WINCTRL1_FRM_32BPP:
+ bits = 32;
+ break;
+ }
+
+ return bits;
+}
+
+static int fbinfo2index (struct fb_info *fb_info)
+{
+ int i;
+
+ for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) {
+ if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info))
+ return i;
+ }
+ printk("au1200fb: ERROR: fbinfo2index failed!\n");
+ return -1;
+}
+
+static int au1200_setlocation (struct au1200fb_device *fbdev, int plane,
+ int xpos, int ypos)
+{
+ uint32 winctrl0, winctrl1, winenable, fb_offset = 0;
+ int xsz, ysz;
+
+ /* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */
+
+ winctrl0 = lcd->window[plane].winctrl0;
+ winctrl1 = lcd->window[plane].winctrl1;
+ winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN);
+ winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY);
+
+ /* Check for off-screen adjustments */
+ xsz = win->w[plane].xres;
+ ysz = win->w[plane].yres;
+ if ((xpos + win->w[plane].xres) > panel->Xres) {
+ /* Off-screen to the right */
+ xsz = panel->Xres - xpos; /* off by 1 ??? */
+ /*printk("off screen right\n");*/
+ }
+
+ if ((ypos + win->w[plane].yres) > panel->Yres) {
+ /* Off-screen to the bottom */
+ ysz = panel->Yres - ypos; /* off by 1 ??? */
+ /*printk("off screen bottom\n");*/
+ }
+
+ if (xpos < 0) {
+ /* Off-screen to the left */
+ xsz = win->w[plane].xres + xpos;
+ fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8);
+ xpos = 0;
+ /*printk("off screen left\n");*/
+ }
+
+ if (ypos < 0) {
+ /* Off-screen to the top */
+ ysz = win->w[plane].yres + ypos;
+ /* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */
+ ypos = 0;
+ /*printk("off screen top\n");*/
+ }
+
+ /* record settings */
+ win->w[plane].xpos = xpos;
+ win->w[plane].ypos = ypos;
+
+ xsz -= 1;
+ ysz -= 1;
+ winctrl0 |= (xpos << 21);
+ winctrl0 |= (ypos << 10);
+ winctrl1 |= (xsz << 11);
+ winctrl1 |= (ysz << 0);
+
+ /* Disable the window while making changes, then restore WINEN */
+ winenable = lcd->winenable & (1 << plane);
+ au_sync();
+ lcd->winenable &= ~(1 << plane);
+ lcd->window[plane].winctrl0 = winctrl0;
+ lcd->window[plane].winctrl1 = winctrl1;
+ lcd->window[plane].winbuf0 =
+ lcd->window[plane].winbuf1 = fbdev->fb_phys;
+ lcd->window[plane].winbufctrl = 0; /* select winbuf0 */
+ lcd->winenable |= winenable;
+ au_sync();
+
+ return 0;
+}
+
+static void au1200_setpanel (struct panel_settings *newpanel)
+{
+ /*
+ * Perform global setup/init of LCD controller
+ */
+ uint32 winenable;
+
+ /* Make sure all windows disabled */
+ winenable = lcd->winenable;
+ lcd->winenable = 0;
+ au_sync();
+ /*
+ * Ensure everything is disabled before reconfiguring
+ */
+ if (lcd->screen & LCD_SCREEN_SEN) {
+ /* Wait for vertical sync period */
+ lcd->intstatus = LCD_INT_SS;
+ while ((lcd->intstatus & LCD_INT_SS) == 0) {
+ au_sync();
+ }
+
+ lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/
+
+ do {
+ lcd->intstatus = lcd->intstatus; /*clear interrupts*/
+ au_sync();
+ /*wait for controller to shut down*/
+ } while ((lcd->intstatus & LCD_INT_SD) == 0);
+
+ /* Call shutdown of current panel (if up) */
+ /* this must occur last, because if an external clock is driving
+ the controller, the clock cannot be turned off before first
+ shutting down the controller.
+ */
+ if (panel->device_shutdown != NULL)
+ panel->device_shutdown();
+ }
+
+ /* Newpanel == NULL indicates a shutdown operation only */
+ if (newpanel == NULL)
+ return;
+
+ panel = newpanel;
+
+ printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres);
+
+ /*
+ * Setup clocking if internal LCD clock source (assumes sys_auxpll valid)
+ */
+ if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT))
+ {
+ uint32 sys_clksrc;
+ au_writel(panel->mode_auxpll, SYS_AUXPLL);
+ sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f;
+ sys_clksrc |= panel->mode_toyclksrc;
+ au_writel(sys_clksrc, SYS_CLKSRC);
+ }
+
+ /*
+ * Configure panel timings
+ */
+ lcd->screen = panel->mode_screen;
+ lcd->horztiming = panel->mode_horztiming;
+ lcd->verttiming = panel->mode_verttiming;
+ lcd->clkcontrol = panel->mode_clkcontrol;
+ lcd->pwmdiv = panel->mode_pwmdiv;
+ lcd->pwmhi = panel->mode_pwmhi;
+ lcd->outmask = panel->mode_outmask;
+ lcd->fifoctrl = panel->mode_fifoctrl;
+ au_sync();
+
+ /* fixme: Check window settings to make sure still valid
+ * for new geometry */
+#if 0
+ au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos);
+ au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos);
+ au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos);
+ au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos);
+#endif
+ lcd->winenable = winenable;
+
+ /*
+ * Re-enable screen now that it is configured
+ */
+ lcd->screen |= LCD_SCREEN_SEN;
+ au_sync();
+
+ /* Call init of panel */
+ if (panel->device_init != NULL) panel->device_init();
+
+ /* FIX!!!! not appropriate on panel change!!! Global setup/init */
+ lcd->intenable = 0;
+ lcd->intstatus = ~0;
+ lcd->backcolor = win->mode_backcolor;
+
+ /* Setup Color Key - FIX!!! */
+ lcd->colorkey = win->mode_colorkey;
+ lcd->colorkeymsk = win->mode_colorkeymsk;
+
+ /* Setup HWCursor - FIX!!! Need to support this eventually */
+ lcd->hwc.cursorctrl = 0;
+ lcd->hwc.cursorpos = 0;
+ lcd->hwc.cursorcolor0 = 0;
+ lcd->hwc.cursorcolor1 = 0;
+ lcd->hwc.cursorcolor2 = 0;
+ lcd->hwc.cursorcolor3 = 0;
+
+
+#if 0
+#define D(X) printk("%25s: %08X\n", #X, X)
+ D(lcd->screen);
+ D(lcd->horztiming);
+ D(lcd->verttiming);
+ D(lcd->clkcontrol);
+ D(lcd->pwmdiv);
+ D(lcd->pwmhi);
+ D(lcd->outmask);
+ D(lcd->fifoctrl);
+ D(lcd->window[0].winctrl0);
+ D(lcd->window[0].winctrl1);
+ D(lcd->window[0].winctrl2);
+ D(lcd->window[0].winbuf0);
+ D(lcd->window[0].winbuf1);
+ D(lcd->window[0].winbufctrl);
+ D(lcd->window[1].winctrl0);
+ D(lcd->window[1].winctrl1);
+ D(lcd->window[1].winctrl2);
+ D(lcd->window[1].winbuf0);
+ D(lcd->window[1].winbuf1);
+ D(lcd->window[1].winbufctrl);
+ D(lcd->window[2].winctrl0);
+ D(lcd->window[2].winctrl1);
+ D(lcd->window[2].winctrl2);
+ D(lcd->window[2].winbuf0);
+ D(lcd->window[2].winbuf1);
+ D(lcd->window[2].winbufctrl);
+ D(lcd->window[3].winctrl0);
+ D(lcd->window[3].winctrl1);
+ D(lcd->window[3].winctrl2);
+ D(lcd->window[3].winbuf0);
+ D(lcd->window[3].winbuf1);
+ D(lcd->window[3].winbufctrl);
+ D(lcd->winenable);
+ D(lcd->intenable);
+ D(lcd->intstatus);
+ D(lcd->backcolor);
+ D(lcd->winenable);
+ D(lcd->colorkey);
+ D(lcd->colorkeymsk);
+ D(lcd->hwc.cursorctrl);
+ D(lcd->hwc.cursorpos);
+ D(lcd->hwc.cursorcolor0);
+ D(lcd->hwc.cursorcolor1);
+ D(lcd->hwc.cursorcolor2);
+ D(lcd->hwc.cursorcolor3);
+#endif
+}
+
+static void au1200_setmode(struct au1200fb_device *fbdev)
+{
+ int plane = fbdev->plane;
+ /* Window/plane setup */
+ lcd->window[plane].winctrl1 = ( 0
+ | LCD_WINCTRL1_PRI_N(plane)
+ | win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */
+ ) ;
+
+ au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos);
+
+ lcd->window[plane].winctrl2 = ( 0
+ | LCD_WINCTRL2_CKMODE_00
+ | LCD_WINCTRL2_DBM
+ | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length)
+ | LCD_WINCTRL2_SCX_1
+ | LCD_WINCTRL2_SCY_1
+ ) ;
+ lcd->winenable |= win->w[plane].mode_winenable;
+ au_sync();
+}
+
+
+/* Inline helpers */
+
+/*#define panel_is_dual(panel) ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
+/*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
+
+#define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN)
+
+/* Bitfields format supported by the controller. */
+static struct fb_bitfield rgb_bitfields[][4] = {
+ /* Red, Green, Blue, Transp */
+ [LCD_WINCTRL1_FRM_16BPP655 >> 25] =
+ { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPP565 >> 25] =
+ { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPP556 >> 25] =
+ { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPPI1555 >> 25] =
+ { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPPI5551 >> 25] =
+ { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPPA1555 >> 25] =
+ { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } },
+
+ [LCD_WINCTRL1_FRM_16BPPA5551 >> 25] =
+ { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } },
+
+ [LCD_WINCTRL1_FRM_24BPP >> 25] =
+ { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } },
+
+ [LCD_WINCTRL1_FRM_32BPP >> 25] =
+ { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } },
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Helpers */
+
+static void au1200fb_update_fbinfo(struct fb_info *fbi)
+{
+ /* FIX!!!! This also needs to take the window pixel format into account!!! */
+
+ /* Update var-dependent FB info */
+ if (panel_is_color(panel)) {
+ if (fbi->var.bits_per_pixel <= 8) {
+ /* palettized */
+ fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ fbi->fix.line_length = fbi->var.xres_virtual /
+ (8/fbi->var.bits_per_pixel);
+ } else {
+ /* non-palettized */
+ fbi->fix.visual = FB_VISUAL_TRUECOLOR;
+ fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8);
+ }
+ } else {
+ /* mono FIX!!! mono 8 and 4 bits */
+ fbi->fix.visual = FB_VISUAL_MONO10;
+ fbi->fix.line_length = fbi->var.xres_virtual / 8;
+ }
+
+ fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual;
+ print_dbg("line length: %d\n", fbi->fix.line_length);
+ print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* AU1200 framebuffer driver */
+
+/* fb_check_var
+ * Validate var settings with hardware restrictions and modify it if necessary
+ */
+static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *fbi)
+{
+ struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
+ u32 pixclock;
+ int screen_size, plane;
+
+ plane = fbdev->plane;
+
+ /* Make sure that the mode respect all LCD controller and
+ * panel restrictions. */
+ var->xres = win->w[plane].xres;
+ var->yres = win->w[plane].yres;
+
+ /* No need for virtual resolution support */
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres;
+
+ var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1);
+
+ screen_size = var->xres_virtual * var->yres_virtual;
+ if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8);
+ else screen_size /= (8/var->bits_per_pixel);
+
+ if (fbdev->fb_len < screen_size)
+ return -EINVAL; /* Virtual screen is to big, abort */
+
+ /* FIX!!!! what are the implicaitons of ignoring this for windows ??? */
+ /* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel
+ * clock can only be obtain by dividing this value by an even integer.
+ * Fallback to a slower pixel clock if necessary. */
+ pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin);
+ pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2));
+
+ if (AU1200_LCD_MAX_CLK % pixclock) {
+ int diff = AU1200_LCD_MAX_CLK % pixclock;
+ pixclock -= diff;
+ }
+
+ var->pixclock = KHZ2PICOS(pixclock/1000);
+#if 0
+ if (!panel_is_active(panel)) {
+ int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1;
+
+ if (!panel_is_color(panel)
+ && (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) {
+ /* STN 8bit mono panel support is up to 6MHz pixclock */
+ var->pixclock = KHZ2PICOS(6000);
+ } else if (!pcd) {
+ /* Other STN panel support is up to 12MHz */
+ var->pixclock = KHZ2PICOS(12000);
+ }
+ }
+#endif
+ /* Set bitfield accordingly */
+ switch (var->bits_per_pixel) {
+ case 16:
+ {
+ /* 16bpp True color.
+ * These must be set to MATCH WINCTRL[FORM] */
+ int idx;
+ idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
+ var->red = rgb_bitfields[idx][0];
+ var->green = rgb_bitfields[idx][1];
+ var->blue = rgb_bitfields[idx][2];
+ var->transp = rgb_bitfields[idx][3];
+ break;
+ }
+
+ case 32:
+ {
+ /* 32bpp True color.
+ * These must be set to MATCH WINCTRL[FORM] */
+ int idx;
+ idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
+ var->red = rgb_bitfields[idx][0];
+ var->green = rgb_bitfields[idx][1];
+ var->blue = rgb_bitfields[idx][2];
+ var->transp = rgb_bitfields[idx][3];
+ break;
+ }
+ default:
+ print_dbg("Unsupported depth %dbpp", var->bits_per_pixel);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* fb_set_par
+ * Set hardware with var settings. This will enable the controller with a
+ * specific mode, normally validated with the fb_check_var method
+ */
+static int au1200fb_fb_set_par(struct fb_info *fbi)
+{
+ struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
+
+ au1200fb_update_fbinfo(fbi);
+ au1200_setmode(fbdev);
+
+ return 0;
+}
+
+/* fb_setcolreg
+ * Set color in LCD palette.
+ */
+static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp, struct fb_info *fbi)
+{
+ volatile u32 *palette = lcd->palette;
+ u32 value;
+
+ if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1))
+ return -EINVAL;
+
+ if (fbi->var.grayscale) {
+ /* Convert color to grayscale */
+ red = green = blue =
+ (19595 * red + 38470 * green + 7471 * blue) >> 16;
+ }
+
+ if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) {
+ /* Place color in the pseudopalette */
+ if (regno > 16)
+ return -EINVAL;
+
+ palette = (u32*) fbi->pseudo_palette;
+
+ red >>= (16 - fbi->var.red.length);
+ green >>= (16 - fbi->var.green.length);
+ blue >>= (16 - fbi->var.blue.length);
+
+ value = (red << fbi->var.red.offset) |
+ (green << fbi->var.green.offset)|
+ (blue << fbi->var.blue.offset);
+ value &= 0xFFFF;
+
+ } else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) {
+ /* COLOR TFT PALLETTIZED (use RGB 565) */
+ value = (red & 0xF800)|((green >> 5) &
+ 0x07E0)|((blue >> 11) & 0x001F);
+ value &= 0xFFFF;
+
+ } else if (0 /*panel_is_color(fbdev->panel)*/) {
+ /* COLOR STN MODE */
+ value = 0x1234;
+ value &= 0xFFF;
+ } else {
+ /* MONOCHROME MODE */
+ value = (green >> 12) & 0x000F;
+ value &= 0xF;
+ }
+
+ palette[regno] = value;
+
+ return 0;
+}
+
+/* fb_blank
+ * Blank the screen. Depending on the mode, the screen will be
+ * activated with the backlight color, or desactivated
+ */
+static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi)
+{
+ /* Short-circuit screen blanking */
+ if (noblanking)
+ return 0;
+
+ switch (blank_mode) {
+
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ /* printk("turn on panel\n"); */
+ au1200_setpanel(panel);
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_POWERDOWN:
+ /* printk("turn off panel\n"); */
+ au1200_setpanel(NULL);
+ break;
+ default:
+ break;
+
+ }
+
+ /* FB_BLANK_NORMAL is a soft blank */
+ return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0;
+}
+
+/* fb_mmap
+ * Map video memory in user space. We don't use the generic fb_mmap
+ * method mainly to allow the use of the TLB streaming flag (CCA=6)
+ */
+static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+
+{
+ unsigned int len;
+ unsigned long start=0, off;
+ struct au1200fb_device *fbdev = (struct au1200fb_device *) info;
+
+#ifdef CONFIG_PM
+ au1xxx_pm_access(LCD_pm_dev);
+#endif
+
+ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
+ return -EINVAL;
+ }
+
+ start = fbdev->fb_phys & PAGE_MASK;
+ len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len);
+
+ off = vma->vm_pgoff << PAGE_SHIFT;
+
+ if ((vma->vm_end - vma->vm_start + off) > len) {
+ return -EINVAL;
+ }
+
+ off += start;
+ vma->vm_pgoff = off >> PAGE_SHIFT;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */
+
+ vma->vm_flags |= VM_IO;
+
+ return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+
+ return 0;
+}
+
+static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
+{
+
+ unsigned int hi1, divider;
+
+ /* SCREEN_SIZE: user cannot reset size, must switch panel choice */
+
+ if (pdata->flags & SCREEN_BACKCOLOR)
+ lcd->backcolor = pdata->backcolor;
+
+ if (pdata->flags & SCREEN_BRIGHTNESS) {
+
+ // limit brightness pwm duty to >= 30/1600
+ if (pdata->brightness < 30) {
+ pdata->brightness = 30;
+ }
+ divider = (lcd->pwmdiv & 0x3FFFF) + 1;
+ hi1 = (lcd->pwmhi >> 16) + 1;
+ hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8);
+ lcd->pwmhi &= 0xFFFF;
+ lcd->pwmhi |= (hi1 << 16);
+ }
+
+ if (pdata->flags & SCREEN_COLORKEY)
+ lcd->colorkey = pdata->colorkey;
+
+ if (pdata->flags & SCREEN_MASK)
+ lcd->colorkeymsk = pdata->mask;
+ au_sync();
+}
+
+static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
+{
+ unsigned int hi1, divider;
+
+ pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1;
+ pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1;
+
+ pdata->backcolor = lcd->backcolor;
+ pdata->colorkey = lcd->colorkey;
+ pdata->mask = lcd->colorkeymsk;
+
+ // brightness
+ hi1 = (lcd->pwmhi >> 16) + 1;
+ divider = (lcd->pwmdiv & 0x3FFFF) + 1;
+ pdata->brightness = ((hi1 << 8) / divider) - 1;
+ au_sync();
+}
+
+static void set_window(unsigned int plane,
+ struct au1200_lcd_window_regs_t *pdata)
+{
+ unsigned int val, bpp;
+
+ /* Window control register 0 */
+ if (pdata->flags & WIN_POSITION) {
+ val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX |
+ LCD_WINCTRL0_OY);
+ val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX);
+ val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY);
+ lcd->window[plane].winctrl0 = val;
+ }
+ if (pdata->flags & WIN_ALPHA_COLOR) {
+ val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A);
+ val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A);
+ lcd->window[plane].winctrl0 = val;
+ }
+ if (pdata->flags & WIN_ALPHA_MODE) {
+ val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN);
+ val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN);
+ lcd->window[plane].winctrl0 = val;
+ }
+
+ /* Window control register 1 */
+ if (pdata->flags & WIN_PRIORITY) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI);
+ val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_CHANNEL) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE);
+ val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_BUFFER_FORMAT) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM);
+ val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_COLOR_ORDER) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO);
+ val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_PIXEL_ORDER) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO);
+ val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO);
+ lcd->window[plane].winctrl1 = val;
+ }
+ if (pdata->flags & WIN_SIZE) {
+ val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX |
+ LCD_WINCTRL1_SZY);
+ val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX);
+ val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY);
+ lcd->window[plane].winctrl1 = val;
+ /* program buffer line width */
+ bpp = winbpp(val) / 8;
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX);
+ val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX);
+ lcd->window[plane].winctrl2 = val;
+ }
+
+ /* Window control register 2 */
+ if (pdata->flags & WIN_COLORKEY_MODE) {
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE);
+ val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE);
+ lcd->window[plane].winctrl2 = val;
+ }
+ if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) {
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM);
+ val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM);
+ lcd->window[plane].winctrl2 = val;
+ }
+ if (pdata->flags & WIN_RAM_ARRAY_MODE) {
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM);
+ val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM);
+ lcd->window[plane].winctrl2 = val;
+ }
+
+ /* Buffer line width programmed with WIN_SIZE */
+
+ if (pdata->flags & WIN_BUFFER_SCALE) {
+ val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX |
+ LCD_WINCTRL2_SCY);
+ val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX);
+ val |= ((pdata->ysize) & LCD_WINCTRL2_SCY);
+ lcd->window[plane].winctrl2 = val;
+ }
+
+ if (pdata->flags & WIN_ENABLE) {
+ val = lcd->winenable;
+ val &= ~(1<<plane);
+ val |= (pdata->enable & 1) << plane;
+ lcd->winenable = val;
+ }
+ au_sync();
+}
+
+static void get_window(unsigned int plane,
+ struct au1200_lcd_window_regs_t *pdata)
+{
+ /* Window control register 0 */
+ pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21;
+ pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10;
+ pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2;
+ pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1;
+
+ /* Window control register 1 */
+ pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30;
+ pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29;
+ pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25;
+ pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24;
+ pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22;
+ pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1;
+ pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1;
+
+ /* Window control register 2 */
+ pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24;
+ pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23;
+ pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21;
+
+ pdata->enable = (lcd->winenable >> plane) & 1;
+ au_sync();
+}
+
+static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+{
+ int plane;
+ int val;
+
+#ifdef CONFIG_PM
+ au1xxx_pm_access(LCD_pm_dev);
+#endif
+
+ plane = fbinfo2index(info);
+ print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane);
+
+ if (cmd == AU1200_LCD_FB_IOCTL) {
+ struct au1200_lcd_iodata_t iodata;
+
+ if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata)))
+ return -EFAULT;
+
+ print_dbg("FB IOCTL called\n");
+
+ switch (iodata.subcmd) {
+ case AU1200_LCD_SET_SCREEN:
+ print_dbg("AU1200_LCD_SET_SCREEN\n");
+ set_global(cmd, &iodata.global);
+ break;
+
+ case AU1200_LCD_GET_SCREEN:
+ print_dbg("AU1200_LCD_GET_SCREEN\n");
+ get_global(cmd, &iodata.global);
+ break;
+
+ case AU1200_LCD_SET_WINDOW:
+ print_dbg("AU1200_LCD_SET_WINDOW\n");
+ set_window(plane, &iodata.window);
+ break;
+
+ case AU1200_LCD_GET_WINDOW:
+ print_dbg("AU1200_LCD_GET_WINDOW\n");
+ get_window(plane, &iodata.window);
+ break;
+
+ case AU1200_LCD_SET_PANEL:
+ print_dbg("AU1200_LCD_SET_PANEL\n");
+ if ((iodata.global.panel_choice >= 0) &&
+ (iodata.global.panel_choice <
+ NUM_PANELS))
+ {
+ struct panel_settings *newpanel;
+ panel_index = iodata.global.panel_choice;
+ newpanel = &known_lcd_panels[panel_index];
+ au1200_setpanel(newpanel);
+ }
+ break;
+
+ case AU1200_LCD_GET_PANEL:
+ print_dbg("AU1200_LCD_GET_PANEL\n");
+ iodata.global.panel_choice = panel_index;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata));
+ if (val) {
+ print_dbg("error: could not copy %d bytes\n", val);
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+
+static struct fb_ops au1200fb_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = au1200fb_fb_check_var,
+ .fb_set_par = au1200fb_fb_set_par,
+ .fb_setcolreg = au1200fb_fb_setcolreg,
+ .fb_blank = au1200fb_fb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_sync = NULL,
+ .fb_ioctl = au1200fb_ioctl,
+ .fb_mmap = au1200fb_fb_mmap,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs)
+{
+ /* Nothing to do for now, just clear any pending interrupt */
+ lcd->intstatus = lcd->intstatus;
+ au_sync();
+
+ return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* AU1200 LCD device probe helpers */
+
+static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
+{
+ struct fb_info *fbi = &fbdev->fb_info;
+ int bpp;
+
+ memset(fbi, 0, sizeof(struct fb_info));
+ fbi->fbops = &au1200fb_fb_ops;
+
+ bpp = winbpp(win->w[fbdev->plane].mode_winctrl1);
+
+ /* Copy monitor specs from panel data */
+ /* fixme: we're setting up LCD controller windows, so these dont give a
+ damn as to what the monitor specs are (the panel itself does, but that
+ isnt done here...so maybe need a generic catchall monitor setting??? */
+ memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs));
+
+ /* We first try the user mode passed in argument. If that failed,
+ * or if no one has been specified, we default to the first mode of the
+ * panel list. Note that after this call, var data will be set */
+ if (!fb_find_mode(&fbi->var,
+ fbi,
+ NULL, /* drv_info.opt_mode, */
+ fbi->monspecs.modedb,
+ fbi->monspecs.modedb_len,
+ fbi->monspecs.modedb,
+ bpp)) {
+
+ print_err("Cannot find valid mode for panel %s", panel->name);
+ return -EFAULT;
+ }
+
+ fbi->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
+ if (!fbi->pseudo_palette) {
+ return -ENOMEM;
+ }
+ memset(fbi->pseudo_palette, 0, sizeof(u32) * 16);
+
+ if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
+ print_err("Fail to allocate colormap (%d entries)",
+ AU1200_LCD_NBR_PALETTE_ENTRIES);
+ kfree(fbi->pseudo_palette);
+ return -EFAULT;
+ }
+
+ strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id));
+ fbi->fix.smem_start = fbdev->fb_phys;
+ fbi->fix.smem_len = fbdev->fb_len;
+ fbi->fix.type = FB_TYPE_PACKED_PIXELS;
+ fbi->fix.xpanstep = 0;
+ fbi->fix.ypanstep = 0;
+ fbi->fix.mmio_start = 0;
+ fbi->fix.mmio_len = 0;
+ fbi->fix.accel = FB_ACCEL_NONE;
+
+ fbi->screen_base = (char __iomem *) fbdev->fb_mem;
+
+ au1200fb_update_fbinfo(fbi);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* AU1200 LCD controller device driver */
+
+static int au1200fb_drv_probe(struct device *dev)
+{
+ struct au1200fb_device *fbdev;
+ unsigned long page;
+ int bpp, plane, ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
+ bpp = winbpp(win->w[plane].mode_winctrl1);
+ if (win->w[plane].xres == 0)
+ win->w[plane].xres = panel->Xres;
+ if (win->w[plane].yres == 0)
+ win->w[plane].yres = panel->Yres;
+
+ fbdev = &_au1200fb_devices[plane];
+ memset(fbdev, 0, sizeof(struct au1200fb_device));
+ fbdev->plane = plane;
+
+ /* Allocate the framebuffer to the maximum screen size */
+ fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;
+
+ fbdev->fb_mem = dma_alloc_noncoherent(dev,
+ PAGE_ALIGN(fbdev->fb_len),
+ &fbdev->fb_phys, GFP_KERNEL);
+ if (!fbdev->fb_mem) {
+ print_err("fail to allocate frambuffer (size: %dK))",
+ fbdev->fb_len / 1024);
+ return -ENOMEM;
+ }
+
+ /*
+ * Set page reserved so that mmap will work. This is necessary
+ * since we'll be remapping normal memory.
+ */
+ for (page = (unsigned long)fbdev->fb_phys;
+ page < PAGE_ALIGN((unsigned long)fbdev->fb_phys +
+ fbdev->fb_len);
+ page += PAGE_SIZE) {
+ SetPageReserved(pfn_to_page(page >> PAGE_SHIFT)); /* LCD DMA is NOT coherent on Au1200 */
+ }
+ print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
+ print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
+
+ /* Init FB data */
+ if ((ret = au1200fb_init_fbinfo(fbdev)) < 0)
+ goto failed;
+
+ /* Register new framebuffer */
+ if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) {
+ print_err("cannot register new framebuffer");
+ goto failed;
+ }
+
+ au1200fb_fb_set_par(&fbdev->fb_info);
+
+#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
+ if (plane == 0)
+ if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) {
+ /* Start display and show logo on boot */
+ fb_set_cmap(&fbdev->fb_info.cmap,
+ &fbdev->fb_info);
+
+ fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR);
+ }
+#endif
+ }
+
+ /* Now hook interrupt too */
+ if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq,
+ SA_INTERRUPT | SA_SHIRQ, "lcd", (void *)dev)) < 0) {
+ print_err("fail to request interrupt line %d (err: %d)",
+ AU1200_LCD_INT, ret);
+ goto failed;
+ }
+
+ return 0;
+
+failed:
+ /* NOTE: This only does the current plane/window that failed; others are still active */
+ if (fbdev->fb_mem)
+ dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len),
+ fbdev->fb_mem, fbdev->fb_phys);
+ if (fbdev->fb_info.cmap.len != 0)
+ fb_dealloc_cmap(&fbdev->fb_info.cmap);
+ if (fbdev->fb_info.pseudo_palette)
+ kfree(fbdev->fb_info.pseudo_palette);
+ if (plane == 0)
+ free_irq(AU1200_LCD_INT, (void*)dev);
+ return ret;
+}
+
+static int au1200fb_drv_remove(struct device *dev)
+{
+ struct au1200fb_device *fbdev;
+ int plane;
+
+ if (!dev)
+ return -ENODEV;
+
+ /* Turn off the panel */
+ au1200_setpanel(NULL);
+
+ for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane)
+ {
+ fbdev = &_au1200fb_devices[plane];
+
+ /* Clean up all probe data */
+ unregister_framebuffer(&fbdev->fb_info);
+ if (fbdev->fb_mem)
+ dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len),
+ fbdev->fb_mem, fbdev->fb_phys);
+ if (fbdev->fb_info.cmap.len != 0)
+ fb_dealloc_cmap(&fbdev->fb_info.cmap);
+ if (fbdev->fb_info.pseudo_palette)
+ kfree(fbdev->fb_info.pseudo_palette);
+ }
+
+ free_irq(AU1200_LCD_INT, (void *)dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int au1200fb_drv_suspend(struct device *dev, u32 state, u32 level)
+{
+ /* TODO */
+ return 0;
+}
+
+static int au1200fb_drv_resume(struct device *dev, u32 level)
+{
+ /* TODO */
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct device_driver au1200fb_driver = {
+ .name = "au1200-lcd",
+ .bus = &platform_bus_type,
+ .probe = au1200fb_drv_probe,
+ .remove = au1200fb_drv_remove,
+#ifdef CONFIG_PM
+ .suspend = au1200fb_drv_suspend,
+ .resume = au1200fb_drv_resume,
+#endif
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Kernel driver */
+
+static void au1200fb_setup(void)
+{
+ char* options = NULL;
+ char* this_opt;
+ int num_panels = ARRAY_SIZE(known_lcd_panels);
+ int panel_idx = -1;
+
+ fb_get_options(DRIVER_NAME, &options);
+
+ if (options) {
+ while ((this_opt = strsep(&options,",")) != NULL) {
+ /* Panel option - can be panel name,
+ * "bs" for board-switch, or number/index */
+ if (!strncmp(this_opt, "panel:", 6)) {
+ int i;
+ long int li;
+ char *endptr;
+ this_opt += 6;
+ /* First check for index, which allows
+ * to short circuit this mess */
+ li = simple_strtol(this_opt, &endptr, 0);
+ if (*endptr == '\0') {
+ panel_idx = (int)li;
+ }
+ else if (strcmp(this_opt, "bs") == 0) {
+ extern int board_au1200fb_panel(void);
+ panel_idx = board_au1200fb_panel();
+ }
+
+ else
+ for (i = 0; i < num_panels; i++) {
+ if (!strcmp(this_opt, known_lcd_panels[i].name)) {
+ panel_idx = i;
+ break;
+ }
+ }
+
+ if ((panel_idx < 0) || (panel_idx >= num_panels)) {
+ print_warn("Panel %s not supported!", this_opt);
+ }
+ else
+ panel_index = panel_idx;
+ }
+
+ else if (strncmp(this_opt, "nohwcursor", 10) == 0) {
+ nohwcursor = 1;
+ }
+
+ /* Unsupported option */
+ else {
+ print_warn("Unsupported option \"%s\"", this_opt);
+ }
+ }
+ }
+}
+
+#ifdef CONFIG_PM
+static int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
+ au1xxx_request_t request, void *data) {
+ int retval = -1;
+ unsigned int d = 0;
+ unsigned int brightness = 0;
+
+ if (request == AU1XXX_PM_SLEEP) {
+ board_au1200fb_panel_shutdown();
+ }
+ else if (request == AU1XXX_PM_WAKEUP) {
+ if(dev->prev_state == SLEEP_STATE)
+ {
+ int plane;
+ au1200_setpanel(panel);
+ for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
+ struct au1200fb_device *fbdev;
+ fbdev = &_au1200fb_devices[plane];
+ au1200fb_fb_set_par(&fbdev->fb_info);
+ }
+ }
+
+ d = *((unsigned int*)data);
+ if(d <=10) brightness = 26;
+ else if(d<=20) brightness = 51;
+ else if(d<=30) brightness = 77;
+ else if(d<=40) brightness = 102;
+ else if(d<=50) brightness = 128;
+ else if(d<=60) brightness = 153;
+ else if(d<=70) brightness = 179;
+ else if(d<=80) brightness = 204;
+ else if(d<=90) brightness = 230;
+ else brightness = 255;
+ set_brightness(brightness);
+ } else if (request == AU1XXX_PM_GETSTATUS) {
+ return dev->cur_state;
+ } else if (request == AU1XXX_PM_ACCESS) {
+ if (dev->cur_state != SLEEP_STATE)
+ return retval;
+ else {
+ au1200_setpanel(panel);
+ }
+ } else if (request == AU1XXX_PM_IDLE) {
+ } else if (request == AU1XXX_PM_CLEANUP) {
+ }
+
+ return retval;
+}
+#endif
+
+static int __init au1200fb_init(void)
+{
+ print_info("" DRIVER_DESC "");
+
+ /* Setup driver with options */
+ au1200fb_setup();
+
+ /* Point to the panel selected */
+ panel = &known_lcd_panels[panel_index];
+ win = &windows[window_index];
+
+ printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
+ printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
+
+ /* Kickstart the panel, the framebuffers/windows come soon enough */
+ au1200_setpanel(panel);
+
+ #ifdef CONFIG_PM
+ LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL);
+ if ( LCD_pm_dev == NULL)
+ printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n");
+ else
+ printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n");
+ #endif
+
+ return driver_register(&au1200fb_driver);
+}
+
+static void __exit au1200fb_cleanup(void)
+{
+ driver_unregister(&au1200fb_driver);
+}
+
+module_init(au1200fb_init);
+module_exit(au1200fb_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/au1200fb.h b/drivers/video/au1200fb.h
new file mode 100644
index 00000000000..e2672714d8d
--- /dev/null
+++ b/drivers/video/au1200fb.h
@@ -0,0 +1,572 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Hardware definitions for the Au1200 LCD controller
+ *
+ * Copyright 2004 AMD
+ * Author: AMD
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _AU1200LCD_H
+#define _AU1200LCD_H
+
+/********************************************************************/
+#define AU1200_LCD_ADDR 0xB5000000
+
+#define uint8 unsigned char
+#define uint32 unsigned int
+
+struct au1200_lcd {
+ volatile uint32 reserved0;
+ volatile uint32 screen;
+ volatile uint32 backcolor;
+ volatile uint32 horztiming;
+ volatile uint32 verttiming;
+ volatile uint32 clkcontrol;
+ volatile uint32 pwmdiv;
+ volatile uint32 pwmhi;
+ volatile uint32 reserved1;
+ volatile uint32 winenable;
+ volatile uint32 colorkey;
+ volatile uint32 colorkeymsk;
+ struct
+ {
+ volatile uint32 cursorctrl;
+ volatile uint32 cursorpos;
+ volatile uint32 cursorcolor0;
+ volatile uint32 cursorcolor1;
+ volatile uint32 cursorcolor2;
+ uint32 cursorcolor3;
+ } hwc;
+ volatile uint32 intstatus;
+ volatile uint32 intenable;
+ volatile uint32 outmask;
+ volatile uint32 fifoctrl;
+ uint32 reserved2[(0x0100-0x0058)/4];
+ struct
+ {
+ volatile uint32 winctrl0;
+ volatile uint32 winctrl1;
+ volatile uint32 winctrl2;
+ volatile uint32 winbuf0;
+ volatile uint32 winbuf1;
+ volatile uint32 winbufctrl;
+ uint32 winreserved0;
+ uint32 winreserved1;
+ } window[4];
+
+ uint32 reserved3[(0x0400-0x0180)/4];
+
+ volatile uint32 palette[(0x0800-0x0400)/4];
+
+ volatile uint8 cursorpattern[256];
+};
+
+/* lcd_screen */
+#define LCD_SCREEN_SEN (1<<31)
+#define LCD_SCREEN_SX (0x07FF<<19)
+#define LCD_SCREEN_SY (0x07FF<< 8)
+#define LCD_SCREEN_SWP (1<<7)
+#define LCD_SCREEN_SWD (1<<6)
+#define LCD_SCREEN_PT (7<<0)
+#define LCD_SCREEN_PT_TFT (0<<0)
+#define LCD_SCREEN_SX_N(WIDTH) ((WIDTH-1)<<19)
+#define LCD_SCREEN_SY_N(HEIGHT) ((HEIGHT-1)<<8)
+#define LCD_SCREEN_PT_CSTN (1<<0)
+#define LCD_SCREEN_PT_CDSTN (2<<0)
+#define LCD_SCREEN_PT_M8STN (3<<0)
+#define LCD_SCREEN_PT_M4STN (4<<0)
+
+/* lcd_backcolor */
+#define LCD_BACKCOLOR_SBGR (0xFF<<16)
+#define LCD_BACKCOLOR_SBGG (0xFF<<8)
+#define LCD_BACKCOLOR_SBGB (0xFF<<0)
+#define LCD_BACKCOLOR_SBGR_N(N) ((N)<<16)
+#define LCD_BACKCOLOR_SBGG_N(N) ((N)<<8)
+#define LCD_BACKCOLOR_SBGB_N(N) ((N)<<0)
+
+/* lcd_winenable */
+#define LCD_WINENABLE_WEN3 (1<<3)
+#define LCD_WINENABLE_WEN2 (1<<2)
+#define LCD_WINENABLE_WEN1 (1<<1)
+#define LCD_WINENABLE_WEN0 (1<<0)
+
+/* lcd_colorkey */
+#define LCD_COLORKEY_CKR (0xFF<<16)
+#define LCD_COLORKEY_CKG (0xFF<<8)
+#define LCD_COLORKEY_CKB (0xFF<<0)
+#define LCD_COLORKEY_CKR_N(N) ((N)<<16)
+#define LCD_COLORKEY_CKG_N(N) ((N)<<8)
+#define LCD_COLORKEY_CKB_N(N) ((N)<<0)
+
+/* lcd_colorkeymsk */
+#define LCD_COLORKEYMSK_CKMR (0xFF<<16)
+#define LCD_COLORKEYMSK_CKMG (0xFF<<8)
+#define LCD_COLORKEYMSK_CKMB (0xFF<<0)
+#define LCD_COLORKEYMSK_CKMR_N(N) ((N)<<16)
+#define LCD_COLORKEYMSK_CKMG_N(N) ((N)<<8)
+#define LCD_COLORKEYMSK_CKMB_N(N) ((N)<<0)
+
+/* lcd windows control 0 */
+#define LCD_WINCTRL0_OX (0x07FF<<21)
+#define LCD_WINCTRL0_OY (0x07FF<<10)
+#define LCD_WINCTRL0_A (0x00FF<<2)
+#define LCD_WINCTRL0_AEN (1<<1)
+#define LCD_WINCTRL0_OX_N(N) ((N)<<21)
+#define LCD_WINCTRL0_OY_N(N) ((N)<<10)
+#define LCD_WINCTRL0_A_N(N) ((N)<<2)
+
+/* lcd windows control 1 */
+#define LCD_WINCTRL1_PRI (3<<30)
+#define LCD_WINCTRL1_PIPE (1<<29)
+#define LCD_WINCTRL1_FRM (0xF<<25)
+#define LCD_WINCTRL1_CCO (1<<24)
+#define LCD_WINCTRL1_PO (3<<22)
+#define LCD_WINCTRL1_SZX (0x07FF<<11)
+#define LCD_WINCTRL1_SZY (0x07FF<<0)
+#define LCD_WINCTRL1_FRM_1BPP (0<<25)
+#define LCD_WINCTRL1_FRM_2BPP (1<<25)
+#define LCD_WINCTRL1_FRM_4BPP (2<<25)
+#define LCD_WINCTRL1_FRM_8BPP (3<<25)
+#define LCD_WINCTRL1_FRM_12BPP (4<<25)
+#define LCD_WINCTRL1_FRM_16BPP655 (5<<25)
+#define LCD_WINCTRL1_FRM_16BPP565 (6<<25)
+#define LCD_WINCTRL1_FRM_16BPP556 (7<<25)
+#define LCD_WINCTRL1_FRM_16BPPI1555 (8<<25)
+#define LCD_WINCTRL1_FRM_16BPPI5551 (9<<25)
+#define LCD_WINCTRL1_FRM_16BPPA1555 (10<<25)
+#define LCD_WINCTRL1_FRM_16BPPA5551 (11<<25)
+#define LCD_WINCTRL1_FRM_24BPP (12<<25)
+#define LCD_WINCTRL1_FRM_32BPP (13<<25)
+#define LCD_WINCTRL1_PRI_N(N) ((N)<<30)
+#define LCD_WINCTRL1_PO_00 (0<<22)
+#define LCD_WINCTRL1_PO_01 (1<<22)
+#define LCD_WINCTRL1_PO_10 (2<<22)
+#define LCD_WINCTRL1_PO_11 (3<<22)
+#define LCD_WINCTRL1_SZX_N(N) ((N-1)<<11)
+#define LCD_WINCTRL1_SZY_N(N) ((N-1)<<0)
+
+/* lcd windows control 2 */
+#define LCD_WINCTRL2_CKMODE (3<<24)
+#define LCD_WINCTRL2_DBM (1<<23)
+#define LCD_WINCTRL2_RAM (3<<21)
+#define LCD_WINCTRL2_BX (0x1FFF<<8)
+#define LCD_WINCTRL2_SCX (0xF<<4)
+#define LCD_WINCTRL2_SCY (0xF<<0)
+#define LCD_WINCTRL2_CKMODE_00 (0<<24)
+#define LCD_WINCTRL2_CKMODE_01 (1<<24)
+#define LCD_WINCTRL2_CKMODE_10 (2<<24)
+#define LCD_WINCTRL2_CKMODE_11 (3<<24)
+#define LCD_WINCTRL2_RAM_NONE (0<<21)
+#define LCD_WINCTRL2_RAM_PALETTE (1<<21)
+#define LCD_WINCTRL2_RAM_GAMMA (2<<21)
+#define LCD_WINCTRL2_RAM_BUFFER (3<<21)
+#define LCD_WINCTRL2_BX_N(N) ((N)<<8)
+#define LCD_WINCTRL2_SCX_1 (0<<4)
+#define LCD_WINCTRL2_SCX_2 (1<<4)
+#define LCD_WINCTRL2_SCX_4 (2<<4)
+#define LCD_WINCTRL2_SCY_1 (0<<0)
+#define LCD_WINCTRL2_SCY_2 (1<<0)
+#define LCD_WINCTRL2_SCY_4 (2<<0)
+
+/* lcd windows buffer control */
+#define LCD_WINBUFCTRL_DB (1<<1)
+#define LCD_WINBUFCTRL_DBN (1<<0)
+
+/* lcd_intstatus, lcd_intenable */
+#define LCD_INT_IFO (0xF<<14)
+#define LCD_INT_IFU (0xF<<10)
+#define LCD_INT_OFO (1<<9)
+#define LCD_INT_OFU (1<<8)
+#define LCD_INT_WAIT (1<<3)
+#define LCD_INT_SD (1<<2)
+#define LCD_INT_SA (1<<1)
+#define LCD_INT_SS (1<<0)
+
+/* lcd_horztiming */
+#define LCD_HORZTIMING_HND2 (0x1FF<<18)
+#define LCD_HORZTIMING_HND1 (0x1FF<<9)
+#define LCD_HORZTIMING_HPW (0x1FF<<0)
+#define LCD_HORZTIMING_HND2_N(N)(((N)-1)<<18)
+#define LCD_HORZTIMING_HND1_N(N)(((N)-1)<<9)
+#define LCD_HORZTIMING_HPW_N(N) (((N)-1)<<0)
+
+/* lcd_verttiming */
+#define LCD_VERTTIMING_VND2 (0x1FF<<18)
+#define LCD_VERTTIMING_VND1 (0x1FF<<9)
+#define LCD_VERTTIMING_VPW (0x1FF<<0)
+#define LCD_VERTTIMING_VND2_N(N)(((N)-1)<<18)
+#define LCD_VERTTIMING_VND1_N(N)(((N)-1)<<9)
+#define LCD_VERTTIMING_VPW_N(N) (((N)-1)<<0)
+
+/* lcd_clkcontrol */
+#define LCD_CLKCONTROL_EXT (1<<22)
+#define LCD_CLKCONTROL_DELAY (3<<20)
+#define LCD_CLKCONTROL_CDD (1<<19)
+#define LCD_CLKCONTROL_IB (1<<18)
+#define LCD_CLKCONTROL_IC (1<<17)
+#define LCD_CLKCONTROL_IH (1<<16)
+#define LCD_CLKCONTROL_IV (1<<15)
+#define LCD_CLKCONTROL_BF (0x1F<<10)
+#define LCD_CLKCONTROL_PCD (0x3FF<<0)
+#define LCD_CLKCONTROL_BF_N(N) (((N)-1)<<10)
+#define LCD_CLKCONTROL_PCD_N(N) ((N)<<0)
+
+/* lcd_pwmdiv */
+#define LCD_PWMDIV_EN (1<<31)
+#define LCD_PWMDIV_PWMDIV (0x1FFFF<<0)
+#define LCD_PWMDIV_PWMDIV_N(N) ((N)<<0)
+
+/* lcd_pwmhi */
+#define LCD_PWMHI_PWMHI1 (0xFFFF<<16)
+#define LCD_PWMHI_PWMHI0 (0xFFFF<<0)
+#define LCD_PWMHI_PWMHI1_N(N) ((N)<<16)
+#define LCD_PWMHI_PWMHI0_N(N) ((N)<<0)
+
+/* lcd_hwccon */
+#define LCD_HWCCON_EN (1<<0)
+
+/* lcd_cursorpos */
+#define LCD_CURSORPOS_HWCXOFF (0x1F<<27)
+#define LCD_CURSORPOS_HWCXPOS (0x07FF<<16)
+#define LCD_CURSORPOS_HWCYOFF (0x1F<<11)
+#define LCD_CURSORPOS_HWCYPOS (0x07FF<<0)
+#define LCD_CURSORPOS_HWCXOFF_N(N) ((N)<<27)
+#define LCD_CURSORPOS_HWCXPOS_N(N) ((N)<<16)
+#define LCD_CURSORPOS_HWCYOFF_N(N) ((N)<<11)
+#define LCD_CURSORPOS_HWCYPOS_N(N) ((N)<<0)
+
+/* lcd_cursorcolor */
+#define LCD_CURSORCOLOR_HWCA (0xFF<<24)
+#define LCD_CURSORCOLOR_HWCR (0xFF<<16)
+#define LCD_CURSORCOLOR_HWCG (0xFF<<8)
+#define LCD_CURSORCOLOR_HWCB (0xFF<<0)
+#define LCD_CURSORCOLOR_HWCA_N(N) ((N)<<24)
+#define LCD_CURSORCOLOR_HWCR_N(N) ((N)<<16)
+#define LCD_CURSORCOLOR_HWCG_N(N) ((N)<<8)
+#define LCD_CURSORCOLOR_HWCB_N(N) ((N)<<0)
+
+/* lcd_fifoctrl */
+#define LCD_FIFOCTRL_F3IF (1<<29)
+#define LCD_FIFOCTRL_F3REQ (0x1F<<24)
+#define LCD_FIFOCTRL_F2IF (1<<29)
+#define LCD_FIFOCTRL_F2REQ (0x1F<<16)
+#define LCD_FIFOCTRL_F1IF (1<<29)
+#define LCD_FIFOCTRL_F1REQ (0x1F<<8)
+#define LCD_FIFOCTRL_F0IF (1<<29)
+#define LCD_FIFOCTRL_F0REQ (0x1F<<0)
+#define LCD_FIFOCTRL_F3REQ_N(N) ((N-1)<<24)
+#define LCD_FIFOCTRL_F2REQ_N(N) ((N-1)<<16)
+#define LCD_FIFOCTRL_F1REQ_N(N) ((N-1)<<8)
+#define LCD_FIFOCTRL_F0REQ_N(N) ((N-1)<<0)
+
+/* lcd_outmask */
+#define LCD_OUTMASK_MASK (0x00FFFFFF)
+
+/********************************************************************/
+#endif /* _AU1200LCD_H */
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Hardware definitions for the Au1200 LCD controller
+ *
+ * Copyright 2004 AMD
+ * Author: AMD
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _AU1200LCD_H
+#define _AU1200LCD_H
+
+/********************************************************************/
+#define AU1200_LCD_ADDR 0xB5000000
+
+#define uint8 unsigned char
+#define uint32 unsigned int
+
+struct au1200_lcd {
+ volatile uint32 reserved0;
+ volatile uint32 screen;
+ volatile uint32 backcolor;
+ volatile uint32 horztiming;
+ volatile uint32 verttiming;
+ volatile uint32 clkcontrol;
+ volatile uint32 pwmdiv;
+ volatile uint32 pwmhi;
+ volatile uint32 reserved1;
+ volatile uint32 winenable;
+ volatile uint32 colorkey;
+ volatile uint32 colorkeymsk;
+ struct
+ {
+ volatile uint32 cursorctrl;
+ volatile uint32 cursorpos;
+ volatile uint32 cursorcolor0;
+ volatile uint32 cursorcolor1;
+ volatile uint32 cursorcolor2;
+ uint32 cursorcolor3;
+ } hwc;
+ volatile uint32 intstatus;
+ volatile uint32 intenable;
+ volatile uint32 outmask;
+ volatile uint32 fifoctrl;
+ uint32 reserved2[(0x0100-0x0058)/4];
+ struct
+ {
+ volatile uint32 winctrl0;
+ volatile uint32 winctrl1;
+ volatile uint32 winctrl2;
+ volatile uint32 winbuf0;
+ volatile uint32 winbuf1;
+ volatile uint32 winbufctrl;
+ uint32 winreserved0;
+ uint32 winreserved1;
+ } window[4];
+
+ uint32 reserved3[(0x0400-0x0180)/4];
+
+ volatile uint32 palette[(0x0800-0x0400)/4];
+
+ volatile uint8 cursorpattern[256];
+};
+
+/* lcd_screen */
+#define LCD_SCREEN_SEN (1<<31)
+#define LCD_SCREEN_SX (0x07FF<<19)
+#define LCD_SCREEN_SY (0x07FF<< 8)
+#define LCD_SCREEN_SWP (1<<7)
+#define LCD_SCREEN_SWD (1<<6)
+#define LCD_SCREEN_PT (7<<0)
+#define LCD_SCREEN_PT_TFT (0<<0)
+#define LCD_SCREEN_SX_N(WIDTH) ((WIDTH-1)<<19)
+#define LCD_SCREEN_SY_N(HEIGHT) ((HEIGHT-1)<<8)
+#define LCD_SCREEN_PT_CSTN (1<<0)
+#define LCD_SCREEN_PT_CDSTN (2<<0)
+#define LCD_SCREEN_PT_M8STN (3<<0)
+#define LCD_SCREEN_PT_M4STN (4<<0)
+
+/* lcd_backcolor */
+#define LCD_BACKCOLOR_SBGR (0xFF<<16)
+#define LCD_BACKCOLOR_SBGG (0xFF<<8)
+#define LCD_BACKCOLOR_SBGB (0xFF<<0)
+#define LCD_BACKCOLOR_SBGR_N(N) ((N)<<16)
+#define LCD_BACKCOLOR_SBGG_N(N) ((N)<<8)
+#define LCD_BACKCOLOR_SBGB_N(N) ((N)<<0)
+
+/* lcd_winenable */
+#define LCD_WINENABLE_WEN3 (1<<3)
+#define LCD_WINENABLE_WEN2 (1<<2)
+#define LCD_WINENABLE_WEN1 (1<<1)
+#define LCD_WINENABLE_WEN0 (1<<0)
+
+/* lcd_colorkey */
+#define LCD_COLORKEY_CKR (0xFF<<16)
+#define LCD_COLORKEY_CKG (0xFF<<8)
+#define LCD_COLORKEY_CKB (0xFF<<0)
+#define LCD_COLORKEY_CKR_N(N) ((N)<<16)
+#define LCD_COLORKEY_CKG_N(N) ((N)<<8)
+#define LCD_COLORKEY_CKB_N(N) ((N)<<0)
+
+/* lcd_colorkeymsk */
+#define LCD_COLORKEYMSK_CKMR (0xFF<<16)
+#define LCD_COLORKEYMSK_CKMG (0xFF<<8)
+#define LCD_COLORKEYMSK_CKMB (0xFF<<0)
+#define LCD_COLORKEYMSK_CKMR_N(N) ((N)<<16)
+#define LCD_COLORKEYMSK_CKMG_N(N) ((N)<<8)
+#define LCD_COLORKEYMSK_CKMB_N(N) ((N)<<0)
+
+/* lcd windows control 0 */
+#define LCD_WINCTRL0_OX (0x07FF<<21)
+#define LCD_WINCTRL0_OY (0x07FF<<10)
+#define LCD_WINCTRL0_A (0x00FF<<2)
+#define LCD_WINCTRL0_AEN (1<<1)
+#define LCD_WINCTRL0_OX_N(N) ((N)<<21)
+#define LCD_WINCTRL0_OY_N(N) ((N)<<10)
+#define LCD_WINCTRL0_A_N(N) ((N)<<2)
+
+/* lcd windows control 1 */
+#define LCD_WINCTRL1_PRI (3<<30)
+#define LCD_WINCTRL1_PIPE (1<<29)
+#define LCD_WINCTRL1_FRM (0xF<<25)
+#define LCD_WINCTRL1_CCO (1<<24)
+#define LCD_WINCTRL1_PO (3<<22)
+#define LCD_WINCTRL1_SZX (0x07FF<<11)
+#define LCD_WINCTRL1_SZY (0x07FF<<0)
+#define LCD_WINCTRL1_FRM_1BPP (0<<25)
+#define LCD_WINCTRL1_FRM_2BPP (1<<25)
+#define LCD_WINCTRL1_FRM_4BPP (2<<25)
+#define LCD_WINCTRL1_FRM_8BPP (3<<25)
+#define LCD_WINCTRL1_FRM_12BPP (4<<25)
+#define LCD_WINCTRL1_FRM_16BPP655 (5<<25)
+#define LCD_WINCTRL1_FRM_16BPP565 (6<<25)
+#define LCD_WINCTRL1_FRM_16BPP556 (7<<25)
+#define LCD_WINCTRL1_FRM_16BPPI1555 (8<<25)
+#define LCD_WINCTRL1_FRM_16BPPI5551 (9<<25)
+#define LCD_WINCTRL1_FRM_16BPPA1555 (10<<25)
+#define LCD_WINCTRL1_FRM_16BPPA5551 (11<<25)
+#define LCD_WINCTRL1_FRM_24BPP (12<<25)
+#define LCD_WINCTRL1_FRM_32BPP (13<<25)
+#define LCD_WINCTRL1_PRI_N(N) ((N)<<30)
+#define LCD_WINCTRL1_PO_00 (0<<22)
+#define LCD_WINCTRL1_PO_01 (1<<22)
+#define LCD_WINCTRL1_PO_10 (2<<22)
+#define LCD_WINCTRL1_PO_11 (3<<22)
+#define LCD_WINCTRL1_SZX_N(N) ((N-1)<<11)
+#define LCD_WINCTRL1_SZY_N(N) ((N-1)<<0)
+
+/* lcd windows control 2 */
+#define LCD_WINCTRL2_CKMODE (3<<24)
+#define LCD_WINCTRL2_DBM (1<<23)
+#define LCD_WINCTRL2_RAM (3<<21)
+#define LCD_WINCTRL2_BX (0x1FFF<<8)
+#define LCD_WINCTRL2_SCX (0xF<<4)
+#define LCD_WINCTRL2_SCY (0xF<<0)
+#define LCD_WINCTRL2_CKMODE_00 (0<<24)
+#define LCD_WINCTRL2_CKMODE_01 (1<<24)
+#define LCD_WINCTRL2_CKMODE_10 (2<<24)
+#define LCD_WINCTRL2_CKMODE_11 (3<<24)
+#define LCD_WINCTRL2_RAM_NONE (0<<21)
+#define LCD_WINCTRL2_RAM_PALETTE (1<<21)
+#define LCD_WINCTRL2_RAM_GAMMA (2<<21)
+#define LCD_WINCTRL2_RAM_BUFFER (3<<21)
+#define LCD_WINCTRL2_BX_N(N) ((N)<<8)
+#define LCD_WINCTRL2_SCX_1 (0<<4)
+#define LCD_WINCTRL2_SCX_2 (1<<4)
+#define LCD_WINCTRL2_SCX_4 (2<<4)
+#define LCD_WINCTRL2_SCY_1 (0<<0)
+#define LCD_WINCTRL2_SCY_2 (1<<0)
+#define LCD_WINCTRL2_SCY_4 (2<<0)
+
+/* lcd windows buffer control */
+#define LCD_WINBUFCTRL_DB (1<<1)
+#define LCD_WINBUFCTRL_DBN (1<<0)
+
+/* lcd_intstatus, lcd_intenable */
+#define LCD_INT_IFO (0xF<<14)
+#define LCD_INT_IFU (0xF<<10)
+#define LCD_INT_OFO (1<<9)
+#define LCD_INT_OFU (1<<8)
+#define LCD_INT_WAIT (1<<3)
+#define LCD_INT_SD (1<<2)
+#define LCD_INT_SA (1<<1)
+#define LCD_INT_SS (1<<0)
+
+/* lcd_horztiming */
+#define LCD_HORZTIMING_HND2 (0x1FF<<18)
+#define LCD_HORZTIMING_HND1 (0x1FF<<9)
+#define LCD_HORZTIMING_HPW (0x1FF<<0)
+#define LCD_HORZTIMING_HND2_N(N)(((N)-1)<<18)
+#define LCD_HORZTIMING_HND1_N(N)(((N)-1)<<9)
+#define LCD_HORZTIMING_HPW_N(N) (((N)-1)<<0)
+
+/* lcd_verttiming */
+#define LCD_VERTTIMING_VND2 (0x1FF<<18)
+#define LCD_VERTTIMING_VND1 (0x1FF<<9)
+#define LCD_VERTTIMING_VPW (0x1FF<<0)
+#define LCD_VERTTIMING_VND2_N(N)(((N)-1)<<18)
+#define LCD_VERTTIMING_VND1_N(N)(((N)-1)<<9)
+#define LCD_VERTTIMING_VPW_N(N) (((N)-1)<<0)
+
+/* lcd_clkcontrol */
+#define LCD_CLKCONTROL_EXT (1<<22)
+#define LCD_CLKCONTROL_DELAY (3<<20)
+#define LCD_CLKCONTROL_CDD (1<<19)
+#define LCD_CLKCONTROL_IB (1<<18)
+#define LCD_CLKCONTROL_IC (1<<17)
+#define LCD_CLKCONTROL_IH (1<<16)
+#define LCD_CLKCONTROL_IV (1<<15)
+#define LCD_CLKCONTROL_BF (0x1F<<10)
+#define LCD_CLKCONTROL_PCD (0x3FF<<0)
+#define LCD_CLKCONTROL_BF_N(N) (((N)-1)<<10)
+#define LCD_CLKCONTROL_PCD_N(N) ((N)<<0)
+
+/* lcd_pwmdiv */
+#define LCD_PWMDIV_EN (1<<31)
+#define LCD_PWMDIV_PWMDIV (0x1FFFF<<0)
+#define LCD_PWMDIV_PWMDIV_N(N) ((N)<<0)
+
+/* lcd_pwmhi */
+#define LCD_PWMHI_PWMHI1 (0xFFFF<<16)
+#define LCD_PWMHI_PWMHI0 (0xFFFF<<0)
+#define LCD_PWMHI_PWMHI1_N(N) ((N)<<16)
+#define LCD_PWMHI_PWMHI0_N(N) ((N)<<0)
+
+/* lcd_hwccon */
+#define LCD_HWCCON_EN (1<<0)
+
+/* lcd_cursorpos */
+#define LCD_CURSORPOS_HWCXOFF (0x1F<<27)
+#define LCD_CURSORPOS_HWCXPOS (0x07FF<<16)
+#define LCD_CURSORPOS_HWCYOFF (0x1F<<11)
+#define LCD_CURSORPOS_HWCYPOS (0x07FF<<0)
+#define LCD_CURSORPOS_HWCXOFF_N(N) ((N)<<27)
+#define LCD_CURSORPOS_HWCXPOS_N(N) ((N)<<16)
+#define LCD_CURSORPOS_HWCYOFF_N(N) ((N)<<11)
+#define LCD_CURSORPOS_HWCYPOS_N(N) ((N)<<0)
+
+/* lcd_cursorcolor */
+#define LCD_CURSORCOLOR_HWCA (0xFF<<24)
+#define LCD_CURSORCOLOR_HWCR (0xFF<<16)
+#define LCD_CURSORCOLOR_HWCG (0xFF<<8)
+#define LCD_CURSORCOLOR_HWCB (0xFF<<0)
+#define LCD_CURSORCOLOR_HWCA_N(N) ((N)<<24)
+#define LCD_CURSORCOLOR_HWCR_N(N) ((N)<<16)
+#define LCD_CURSORCOLOR_HWCG_N(N) ((N)<<8)
+#define LCD_CURSORCOLOR_HWCB_N(N) ((N)<<0)
+
+/* lcd_fifoctrl */
+#define LCD_FIFOCTRL_F3IF (1<<29)
+#define LCD_FIFOCTRL_F3REQ (0x1F<<24)
+#define LCD_FIFOCTRL_F2IF (1<<29)
+#define LCD_FIFOCTRL_F2REQ (0x1F<<16)
+#define LCD_FIFOCTRL_F1IF (1<<29)
+#define LCD_FIFOCTRL_F1REQ (0x1F<<8)
+#define LCD_FIFOCTRL_F0IF (1<<29)
+#define LCD_FIFOCTRL_F0REQ (0x1F<<0)
+#define LCD_FIFOCTRL_F3REQ_N(N) ((N-1)<<24)
+#define LCD_FIFOCTRL_F2REQ_N(N) ((N-1)<<16)
+#define LCD_FIFOCTRL_F1REQ_N(N) ((N-1)<<8)
+#define LCD_FIFOCTRL_F0REQ_N(N) ((N-1)<<0)
+
+/* lcd_outmask */
+#define LCD_OUTMASK_MASK (0x00FFFFFF)
+
+/********************************************************************/
+#endif /* _AU1200LCD_H */
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index ada6e75eb04..60831bb2368 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -20,14 +20,10 @@
#include <asm/hardware/locomo.h>
#include <asm/irq.h>
+#include <asm/mach/sharpsl_param.h>
+#include <asm/mach-types.h>
-#ifdef CONFIG_SA1100_COLLIE
-#include <asm/arch/collie.h>
-#else
-#include <asm/arch/poodle.h>
-#endif
-
-extern void (*sa1100fb_lcd_power)(int on);
+#include "../../../arch/arm/mach-sa1100/generic.h"
static struct locomo_dev *locomolcd_dev;
@@ -82,7 +78,7 @@ static void locomolcd_off(int comadj)
void locomolcd_power(int on)
{
- int comadj = 118;
+ int comadj = sharpsl_param.comadj;
unsigned long flags;
local_irq_save(flags);
@@ -93,11 +89,12 @@ void locomolcd_power(int on)
}
/* read comadj */
-#ifdef CONFIG_MACH_POODLE
- comadj = 118;
-#else
- comadj = 128;
-#endif
+ if (comadj == -1) {
+ if (machine_is_poodle())
+ comadj = 118;
+ if (machine_is_collie())
+ comadj = 128;
+ }
if (on)
locomolcd_on(comadj);
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index c029db4646f..6577fdfdfc1 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -327,8 +327,7 @@ static void bw2_init_one(struct sbus_dev *sdev)
} else
#else
{
- if (!sdev)
- BUG();
+ BUG_ON(!sdev);
all->par.physbase = sdev->reg_addrs[0].phys_addr;
resp = &sdev->resource[0];
sbusfb_fill_var(&all->info.var, (sdev ? sdev->prom_node : 0), 1);
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index bc061d4ec78..72ff6bf75e5 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -178,8 +178,6 @@ struct chips_init_reg {
unsigned char data;
};
-#define N_ELTS(x) (sizeof(x) / sizeof(x[0]))
-
static struct chips_init_reg chips_init_sr[] = {
{ 0x00, 0x03 },
{ 0x01, 0x01 },
@@ -287,18 +285,18 @@ static void __init chips_hw_init(void)
{
int i;
- for (i = 0; i < N_ELTS(chips_init_xr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i)
write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
outb(0x29, 0x3c2); /* set misc output reg */
- for (i = 0; i < N_ELTS(chips_init_sr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i)
write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
- for (i = 0; i < N_ELTS(chips_init_gr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i)
write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
- for (i = 0; i < N_ELTS(chips_init_ar); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i)
write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
- for (i = 0; i < N_ELTS(chips_init_cr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i)
write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
- for (i = 0; i < N_ELTS(chips_init_fr); ++i)
+ for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i)
write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
}
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index e0dbdfc0c8b..1103010af54 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -60,8 +60,8 @@
#include <asm/amigahw.h>
#endif
#ifdef CONFIG_PPC_PREP
-#include <asm/processor.h>
-#define isPReP (_machine == _MACH_prep)
+#include <asm/machdep.h>
+#define isPReP (machine_is(prep))
#else
#define isPReP 0
#endif
@@ -2622,7 +2622,7 @@ static int __init cirrusfb_init(void)
#endif
#ifdef CONFIG_ZORRO
- error |= zorro_module_init(&cirrusfb_zorro_driver);
+ error |= zorro_register_driver(&cirrusfb_zorro_driver);
#endif
#ifdef CONFIG_PCI
error |= pci_register_driver(&cirrusfb_pci_driver);
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 6ee449858a5..4444bef68fb 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -26,6 +26,30 @@ config VGA_CONSOLE
# fi
# fi
+config VGACON_SOFT_SCROLLBACK
+ bool "Enable Scrollback Buffer in System RAM"
+ depends on VGA_CONSOLE
+ default n
+ help
+ The scrollback buffer of the standard VGA console is located in
+ the VGA RAM. The size of this RAM is fixed and is quite small.
+ If you require a larger scrollback buffer, this can be placed in
+ System RAM which is dynamically allocated during intialization.
+ Placing the scrollback buffer in System RAM will slightly slow
+ down the console.
+
+ If you want this feature, say 'Y' here and enter the amount of
+ RAM to allocate for this buffer. If unsure, say 'N'.
+
+config VGACON_SOFT_SCROLLBACK_SIZE
+ int "Scrollback Buffer Size (in KB)"
+ depends on VGACON_SOFT_SCROLLBACK
+ default "64"
+ help
+ Enter the amount of System RAM to allocate for the scrollback
+ buffer. Each 64KB will give you approximately 16 80x25
+ screenfuls of scrollback buffer
+
config VIDEO_SELECT
bool "Video mode selection support"
depends on X86 && VGA_CONSOLE
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c
index 4fd07d9eca0..0cc1bfda76a 100644
--- a/drivers/video/console/fonts.c
+++ b/drivers/video/console/fonts.c
@@ -66,7 +66,7 @@ static const struct font_desc *fonts[] = {
#endif
};
-#define num_fonts (sizeof(fonts)/sizeof(*fonts))
+#define num_fonts ARRAY_SIZE(fonts)
#ifdef NO_FONTS
#error No fonts configured.
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index 762c7a59314..e99fe30e568 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -149,7 +149,7 @@ static inline void newport_clear_lines(int ystart, int yend, int ci)
newport_clear_screen(0, ystart, 1280 + 63, yend, ci);
}
-void newport_reset(void)
+static void newport_reset(void)
{
unsigned short treg;
int i;
@@ -193,7 +193,7 @@ void newport_reset(void)
* calculate the actual screen size by reading
* the video timing out of the VC2
*/
-void newport_get_screensize(void)
+static void newport_get_screensize(void)
{
int i, cols;
unsigned short ventry, treg;
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 5a86978537d..d5a04b68c4d 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -93,7 +93,6 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
static unsigned long vgacon_uni_pagedir[2];
-
/* Description of the hardware situation */
static unsigned long vga_vram_base; /* Base of video memory */
static unsigned long vga_vram_end; /* End of video memory */
@@ -161,6 +160,201 @@ static inline void write_vga(unsigned char reg, unsigned int val)
spin_unlock_irqrestore(&vga_lock, flags);
}
+static inline void vga_set_mem_top(struct vc_data *c)
+{
+ write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
+}
+
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK
+#include <linux/bootmem.h>
+/* software scrollback */
+static void *vgacon_scrollback;
+static int vgacon_scrollback_tail;
+static int vgacon_scrollback_size;
+static int vgacon_scrollback_rows;
+static int vgacon_scrollback_cnt;
+static int vgacon_scrollback_cur;
+static int vgacon_scrollback_save;
+static int vgacon_scrollback_restore;
+
+static void vgacon_scrollback_init(int pitch)
+{
+ int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
+
+ if (vgacon_scrollback) {
+ vgacon_scrollback_cnt = 0;
+ vgacon_scrollback_tail = 0;
+ vgacon_scrollback_cur = 0;
+ vgacon_scrollback_rows = rows - 1;
+ vgacon_scrollback_size = rows * pitch;
+ }
+}
+
+static void __init vgacon_scrollback_startup(void)
+{
+ vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE
+ * 1024);
+ vgacon_scrollback_init(vga_video_num_columns * 2);
+}
+
+static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
+{
+ void *p;
+
+ if (!vgacon_scrollback_size || c->vc_num != fg_console)
+ return;
+
+ p = (void *) (c->vc_origin + t * c->vc_size_row);
+
+ while (count--) {
+ scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+ p, c->vc_size_row);
+ vgacon_scrollback_cnt++;
+ p += c->vc_size_row;
+ vgacon_scrollback_tail += c->vc_size_row;
+
+ if (vgacon_scrollback_tail >= vgacon_scrollback_size)
+ vgacon_scrollback_tail = 0;
+
+ if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
+ vgacon_scrollback_cnt = vgacon_scrollback_rows;
+
+ vgacon_scrollback_cur = vgacon_scrollback_cnt;
+ }
+}
+
+static void vgacon_restore_screen(struct vc_data *c)
+{
+ vgacon_scrollback_save = 0;
+
+ if (!vga_is_gfx && !vgacon_scrollback_restore) {
+ scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
+ c->vc_screenbuf_size > vga_vram_size ?
+ vga_vram_size : c->vc_screenbuf_size);
+ vgacon_scrollback_restore = 1;
+ vgacon_scrollback_cur = vgacon_scrollback_cnt;
+ }
+}
+
+static int vgacon_scrolldelta(struct vc_data *c, int lines)
+{
+ int start, end, count, soff, diff;
+ void *d, *s;
+
+ if (!lines) {
+ c->vc_visible_origin = c->vc_origin;
+ vga_set_mem_top(c);
+ return 1;
+ }
+
+ if (!vgacon_scrollback)
+ return 1;
+
+ if (!vgacon_scrollback_save) {
+ vgacon_cursor(c, CM_ERASE);
+ vgacon_save_screen(c);
+ vgacon_scrollback_save = 1;
+ }
+
+ vgacon_scrollback_restore = 0;
+ start = vgacon_scrollback_cur + lines;
+ end = start + abs(lines);
+
+ if (start < 0)
+ start = 0;
+
+ if (start > vgacon_scrollback_cnt)
+ start = vgacon_scrollback_cnt;
+
+ if (end < 0)
+ end = 0;
+
+ if (end > vgacon_scrollback_cnt)
+ end = vgacon_scrollback_cnt;
+
+ vgacon_scrollback_cur = start;
+ count = end - start;
+ soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) *
+ c->vc_size_row);
+ soff -= count * c->vc_size_row;
+
+ if (soff < 0)
+ soff += vgacon_scrollback_size;
+
+ count = vgacon_scrollback_cnt - start;
+
+ if (count > c->vc_rows)
+ count = c->vc_rows;
+
+ diff = c->vc_rows - count;
+
+ d = (void *) c->vc_origin;
+ s = (void *) c->vc_screenbuf;
+
+ while (count--) {
+ scr_memcpyw(d, vgacon_scrollback + soff, c->vc_size_row);
+ d += c->vc_size_row;
+ soff += c->vc_size_row;
+
+ if (soff >= vgacon_scrollback_size)
+ soff = 0;
+ }
+
+ if (diff == c->vc_rows) {
+ vgacon_cursor(c, CM_MOVE);
+ } else {
+ while (diff--) {
+ scr_memcpyw(d, s, c->vc_size_row);
+ d += c->vc_size_row;
+ s += c->vc_size_row;
+ }
+ }
+
+ return 1;
+}
+#else
+#define vgacon_scrollback_startup(...) do { } while (0)
+#define vgacon_scrollback_init(...) do { } while (0)
+#define vgacon_scrollback_update(...) do { } while (0)
+
+static void vgacon_restore_screen(struct vc_data *c)
+{
+ if (c->vc_origin != c->vc_visible_origin)
+ vgacon_scrolldelta(c, 0);
+}
+
+static int vgacon_scrolldelta(struct vc_data *c, int lines)
+{
+ if (!lines) /* Turn scrollback off */
+ c->vc_visible_origin = c->vc_origin;
+ else {
+ int margin = c->vc_size_row * 4;
+ int ul, we, p, st;
+
+ if (vga_rolled_over >
+ (c->vc_scr_end - vga_vram_base) + margin) {
+ ul = c->vc_scr_end - vga_vram_base;
+ we = vga_rolled_over + c->vc_size_row;
+ } else {
+ ul = 0;
+ we = vga_vram_size;
+ }
+ p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
+ lines * c->vc_size_row;
+ st = (c->vc_origin - vga_vram_base - ul + we) % we;
+ if (st < 2 * margin)
+ margin = 0;
+ if (p < margin)
+ p = 0;
+ if (p > st - margin)
+ p = st;
+ c->vc_visible_origin = vga_vram_base + (p + ul) % we;
+ }
+ vga_set_mem_top(c);
+ return 1;
+}
+#endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
+
static const char __init *vgacon_startup(void)
{
const char *display_desc = NULL;
@@ -330,7 +524,7 @@ static const char __init *vgacon_startup(void)
vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH;
vgacon_yres = vga_scan_lines;
-
+ vgacon_scrollback_startup();
return display_desc;
}
@@ -357,11 +551,6 @@ static void vgacon_init(struct vc_data *c, int init)
con_set_default_unimap(c);
}
-static inline void vga_set_mem_top(struct vc_data *c)
-{
- write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
-}
-
static void vgacon_deinit(struct vc_data *c)
{
/* When closing the last console, reset video origin */
@@ -433,29 +622,37 @@ static void vgacon_set_cursor_size(int xpos, int from, int to)
cursor_size_lastto = to;
spin_lock_irqsave(&vga_lock, flags);
- outb_p(0x0a, vga_video_port_reg); /* Cursor start */
- curs = inb_p(vga_video_port_val);
- outb_p(0x0b, vga_video_port_reg); /* Cursor end */
- cure = inb_p(vga_video_port_val);
+ if (vga_video_type >= VIDEO_TYPE_VGAC) {
+ outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
+ curs = inb_p(vga_video_port_val);
+ outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
+ cure = inb_p(vga_video_port_val);
+ } else {
+ curs = 0;
+ cure = 0;
+ }
curs = (curs & 0xc0) | from;
cure = (cure & 0xe0) | to;
- outb_p(0x0a, vga_video_port_reg); /* Cursor start */
+ outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
outb_p(curs, vga_video_port_val);
- outb_p(0x0b, vga_video_port_reg); /* Cursor end */
+ outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
outb_p(cure, vga_video_port_val);
spin_unlock_irqrestore(&vga_lock, flags);
}
static void vgacon_cursor(struct vc_data *c, int mode)
{
- if (c->vc_origin != c->vc_visible_origin)
- vgacon_scrolldelta(c, 0);
+ vgacon_restore_screen(c);
+
switch (mode) {
case CM_ERASE:
write_vga(14, (c->vc_pos - vga_vram_base) / 2);
- vgacon_set_cursor_size(c->vc_x, 31, 30);
+ if (vga_video_type >= VIDEO_TYPE_VGAC)
+ vgacon_set_cursor_size(c->vc_x, 31, 30);
+ else
+ vgacon_set_cursor_size(c->vc_x, 31, 31);
break;
case CM_MOVE:
@@ -493,7 +690,10 @@ static void vgacon_cursor(struct vc_data *c, int mode)
10 ? 1 : 2));
break;
case CUR_NONE:
- vgacon_set_cursor_size(c->vc_x, 31, 30);
+ if (vga_video_type >= VIDEO_TYPE_VGAC)
+ vgacon_set_cursor_size(c->vc_x, 31, 30);
+ else
+ vgacon_set_cursor_size(c->vc_x, 31, 31);
break;
default:
vgacon_set_cursor_size(c->vc_x, 1,
@@ -595,6 +795,7 @@ static int vgacon_switch(struct vc_data *c)
vgacon_doresize(c, c->vc_cols, c->vc_rows);
}
+ vgacon_scrollback_init(c->vc_size_row);
return 0; /* Redrawing not needed */
}
@@ -1062,37 +1263,6 @@ static int vgacon_resize(struct vc_data *c, unsigned int width,
return 0;
}
-static int vgacon_scrolldelta(struct vc_data *c, int lines)
-{
- if (!lines) /* Turn scrollback off */
- c->vc_visible_origin = c->vc_origin;
- else {
- int margin = c->vc_size_row * 4;
- int ul, we, p, st;
-
- if (vga_rolled_over >
- (c->vc_scr_end - vga_vram_base) + margin) {
- ul = c->vc_scr_end - vga_vram_base;
- we = vga_rolled_over + c->vc_size_row;
- } else {
- ul = 0;
- we = vga_vram_size;
- }
- p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
- lines * c->vc_size_row;
- st = (c->vc_origin - vga_vram_base - ul + we) % we;
- if (st < 2 * margin)
- margin = 0;
- if (p < margin)
- p = 0;
- if (p > st - margin)
- p = st;
- c->vc_visible_origin = vga_vram_base + (p + ul) % we;
- }
- vga_set_mem_top(c);
- return 1;
-}
-
static int vgacon_set_origin(struct vc_data *c)
{
if (vga_is_gfx || /* We don't play origin tricks in graphic modes */
@@ -1135,15 +1305,14 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
if (t || b != c->vc_rows || vga_is_gfx)
return 0;
- if (c->vc_origin != c->vc_visible_origin)
- vgacon_scrolldelta(c, 0);
-
if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
return 0;
+ vgacon_restore_screen(c);
oldo = c->vc_origin;
delta = lines * c->vc_size_row;
if (dir == SM_UP) {
+ vgacon_scrollback_update(c, t, lines);
if (c->vc_scr_end + delta >= vga_vram_end) {
scr_memcpyw((u16 *) vga_vram_base,
(u16 *) (oldo + delta),
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index c32a2a50bfa..1f98392a43b 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -85,7 +85,7 @@ static struct fb_cmap default_16_colors = {
* Allocates memory for a colormap @cmap. @len is the
* number of entries in the palette.
*
- * Returns -1 errno on error, or zero on success.
+ * Returns negative errno on error, or zero on success.
*
*/
@@ -116,7 +116,7 @@ int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
fail:
fb_dealloc_cmap(cmap);
- return -1;
+ return -ENOMEM;
}
/**
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 07d882b1439..b1a8dca7643 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -55,7 +55,7 @@
#define FBPIXMAPSIZE (1024 * 8)
-static struct notifier_block *fb_notifier_list;
+static BLOCKING_NOTIFIER_HEAD(fb_notifier_list);
struct fb_info *registered_fb[FB_MAX];
int num_registered_fb;
@@ -784,7 +784,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
event.info = info;
event.data = &mode1;
- ret = notifier_call_chain(&fb_notifier_list,
+ ret = blocking_notifier_call_chain(&fb_notifier_list,
FB_EVENT_MODE_DELETE, &event);
}
@@ -830,8 +830,8 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
info->flags &= ~FBINFO_MISC_USEREVENT;
event.info = info;
- notifier_call_chain(&fb_notifier_list, evnt,
- &event);
+ blocking_notifier_call_chain(&fb_notifier_list,
+ evnt, &event);
}
}
}
@@ -854,7 +854,8 @@ fb_blank(struct fb_info *info, int blank)
event.info = info;
event.data = &blank;
- notifier_call_chain(&fb_notifier_list, FB_EVENT_BLANK, &event);
+ blocking_notifier_call_chain(&fb_notifier_list,
+ FB_EVENT_BLANK, &event);
}
return ret;
@@ -925,7 +926,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
con2fb.framebuffer = -1;
event.info = info;
event.data = &con2fb;
- notifier_call_chain(&fb_notifier_list,
+ blocking_notifier_call_chain(&fb_notifier_list,
FB_EVENT_GET_CONSOLE_MAP, &event);
return copy_to_user(argp, &con2fb,
sizeof(con2fb)) ? -EFAULT : 0;
@@ -944,7 +945,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return -EINVAL;
event.info = info;
event.data = &con2fb;
- return notifier_call_chain(&fb_notifier_list,
+ return blocking_notifier_call_chain(&fb_notifier_list,
FB_EVENT_SET_CONSOLE_MAP,
&event);
case FBIOBLANK:
@@ -1324,7 +1325,7 @@ register_framebuffer(struct fb_info *fb_info)
devfs_mk_cdev(MKDEV(FB_MAJOR, i),
S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i);
event.info = fb_info;
- notifier_call_chain(&fb_notifier_list,
+ blocking_notifier_call_chain(&fb_notifier_list,
FB_EVENT_FB_REGISTERED, &event);
return 0;
}
@@ -1366,7 +1367,7 @@ unregister_framebuffer(struct fb_info *fb_info)
*/
int fb_register_client(struct notifier_block *nb)
{
- return notifier_chain_register(&fb_notifier_list, nb);
+ return blocking_notifier_chain_register(&fb_notifier_list, nb);
}
/**
@@ -1375,7 +1376,7 @@ int fb_register_client(struct notifier_block *nb)
*/
int fb_unregister_client(struct notifier_block *nb)
{
- return notifier_chain_unregister(&fb_notifier_list, nb);
+ return blocking_notifier_chain_unregister(&fb_notifier_list, nb);
}
/**
@@ -1393,11 +1394,13 @@ void fb_set_suspend(struct fb_info *info, int state)
event.info = info;
if (state) {
- notifier_call_chain(&fb_notifier_list, FB_EVENT_SUSPEND, &event);
+ blocking_notifier_call_chain(&fb_notifier_list,
+ FB_EVENT_SUSPEND, &event);
info->state = FBINFO_STATE_SUSPENDED;
} else {
info->state = FBINFO_STATE_RUNNING;
- notifier_call_chain(&fb_notifier_list, FB_EVENT_RESUME, &event);
+ blocking_notifier_call_chain(&fb_notifier_list,
+ FB_EVENT_RESUME, &event);
}
}
@@ -1469,7 +1472,7 @@ int fb_new_modelist(struct fb_info *info)
if (!list_empty(&info->modelist)) {
event.info = info;
- err = notifier_call_chain(&fb_notifier_list,
+ err = blocking_notifier_call_chain(&fb_notifier_list,
FB_EVENT_NEW_MODELIST,
&event);
}
@@ -1495,7 +1498,7 @@ int fb_con_duit(struct fb_info *info, int event, void *data)
evnt.info = info;
evnt.data = data;
- return notifier_call_chain(&fb_notifier_list, event, &evnt);
+ return blocking_notifier_call_chain(&fb_notifier_list, event, &evnt);
}
EXPORT_SYMBOL(fb_con_duit);
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 7c74e7325d9..53beeb4a999 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -1281,7 +1281,7 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
-EINVAL : 0;
}
-#if defined(__i386__)
+#if defined(CONFIG_FB_FIRMWARE_EDID) && defined(__i386__)
#include <linux/pci.h>
/*
@@ -1311,11 +1311,11 @@ const unsigned char *fb_firmware_edid(struct device *device)
{
return NULL;
}
-#endif /* _i386_ */
+#endif
+EXPORT_SYMBOL(fb_firmware_edid);
EXPORT_SYMBOL(fb_parse_edid);
EXPORT_SYMBOL(fb_edid_to_monspecs);
-EXPORT_SYMBOL(fb_firmware_edid);
EXPORT_SYMBOL(fb_get_mode);
EXPORT_SYMBOL(fb_validate_mode);
EXPORT_SYMBOL(fb_destroy_modedb);
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 6d26057337e..b72b05250a9 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -348,7 +348,7 @@ static ssize_t store_cmap(struct class_device *class_device, const char *buf,
fb_copy_cmap(&umap, &fb_info->cmap);
fb_dealloc_cmap(&umap);
- return rc;
+ return rc ?: count;
}
for (i = 0; i < length; i++) {
u16 red, blue, green, tsp;
@@ -367,7 +367,7 @@ static ssize_t store_cmap(struct class_device *class_device, const char *buf,
if (transp)
fb_info->cmap.transp[i] = tsp;
}
- return 0;
+ return count;
}
static ssize_t show_cmap(struct class_device *class_device, char *buf)
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 9c9b21d469a..7633e41adda 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -466,8 +466,7 @@ static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
unsigned long flags;
u32 fg;
- if (rect->rop != ROP_COPY && rect->rop != ROP_XOR)
- BUG();
+ BUG_ON(rect->rop != ROP_COPY && rect->rop != ROP_XOR);
fg = ((u32 *)info->pseudo_palette)[rect->color];
diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig
index 42fb9a89a79..4e173ef20a7 100644
--- a/drivers/video/geode/Kconfig
+++ b/drivers/video/geode/Kconfig
@@ -8,9 +8,24 @@ config FB_GEODE
Say 'Y' here to allow you to select framebuffer drivers for
the AMD Geode family of processors.
+config FB_GEODE_GX
+ tristate "AMD Geode GX framebuffer support (EXPERIMENTAL)"
+ depends on FB && FB_GEODE && EXPERIMENTAL
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Framebuffer driver for the display controller integrated into the
+ AMD Geode GX processors.
+
+ To compile this driver as a module, choose M here: the module will be
+ called gxfb.
+
+ If unsure, say N.
+
config FB_GEODE_GX1
tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)"
- depends on FB_GEODE && EXPERIMENTAL
+ depends on FB && FB_GEODE && EXPERIMENTAL
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/geode/Makefile b/drivers/video/geode/Makefile
index 13ad501ea99..f896565bc31 100644
--- a/drivers/video/geode/Makefile
+++ b/drivers/video/geode/Makefile
@@ -1,5 +1,7 @@
# Makefile for the Geode family framebuffer drivers
obj-$(CONFIG_FB_GEODE_GX1) += gx1fb.o
+obj-$(CONFIG_FB_GEODE_GX) += gxfb.o
-gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o
+gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o
+gxfb-objs := gxfb_core.o display_gx.o video_gx.o
diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c
new file mode 100644
index 00000000000..825c3405f5c
--- /dev/null
+++ b/drivers/video/geode/display_gx.c
@@ -0,0 +1,156 @@
+/*
+ * Geode GX display controller.
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Portions from AMD's original 2.4 driver:
+ * Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by * the
+ * Free Software Foundation; either version 2 of the License, or * (at your
+ * option) any later version.
+ */
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/div64.h>
+#include <asm/delay.h>
+
+#include "geodefb.h"
+#include "display_gx.h"
+
+int gx_frame_buffer_size(void)
+{
+ /* Assuming 16 MiB. */
+ return 16*1024*1024;
+}
+
+int gx_line_delta(int xres, int bpp)
+{
+ /* Must be a multiple of 8 bytes. */
+ return (xres * (bpp >> 3) + 7) & ~0x7;
+}
+
+static void gx_set_mode(struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+ u32 gcfg, dcfg;
+ int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
+ int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
+
+ /* Unlock the display controller registers. */
+ readl(par->dc_regs + DC_UNLOCK);
+ writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
+
+ gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
+ dcfg = readl(par->dc_regs + DC_DISPLAY_CFG);
+
+ /* Disable the timing generator. */
+ dcfg &= ~(DC_DCFG_TGEN);
+ writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
+
+ /* Wait for pending memory requests before disabling the FIFO load. */
+ udelay(100);
+
+ /* Disable FIFO load and compression. */
+ gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
+ writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+ /* Setup DCLK and its divisor. */
+ par->vid_ops->set_dclk(info);
+
+ /*
+ * Setup new mode.
+ */
+
+ /* Clear all unused feature bits. */
+ gcfg &= DC_GCFG_YUVM | DC_GCFG_VDSE;
+ dcfg = 0;
+
+ /* Set FIFO priority (default 6/5) and enable. */
+ /* FIXME: increase fifo priority for 1280x1024 and higher modes? */
+ gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE;
+
+ /* Framebuffer start offset. */
+ writel(0, par->dc_regs + DC_FB_ST_OFFSET);
+
+ /* Line delta and line buffer length. */
+ writel(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH);
+ writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
+ par->dc_regs + DC_LINE_SIZE);
+
+ /* Enable graphics and video data and unmask address lines. */
+ dcfg |= DC_DCFG_GDEN | DC_DCFG_VDEN | DC_DCFG_A20M | DC_DCFG_A18M;
+
+ /* Set pixel format. */
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ dcfg |= DC_DCFG_DISP_MODE_8BPP;
+ break;
+ case 16:
+ dcfg |= DC_DCFG_DISP_MODE_16BPP;
+ dcfg |= DC_DCFG_16BPP_MODE_565;
+ break;
+ case 32:
+ dcfg |= DC_DCFG_DISP_MODE_24BPP;
+ dcfg |= DC_DCFG_PALB;
+ break;
+ }
+
+ /* Enable timing generator. */
+ dcfg |= DC_DCFG_TGEN;
+
+ /* Horizontal and vertical timings. */
+ hactive = info->var.xres;
+ hblankstart = hactive;
+ hsyncstart = hblankstart + info->var.right_margin;
+ hsyncend = hsyncstart + info->var.hsync_len;
+ hblankend = hsyncend + info->var.left_margin;
+ htotal = hblankend;
+
+ vactive = info->var.yres;
+ vblankstart = vactive;
+ vsyncstart = vblankstart + info->var.lower_margin;
+ vsyncend = vsyncstart + info->var.vsync_len;
+ vblankend = vsyncend + info->var.upper_margin;
+ vtotal = vblankend;
+
+ writel((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING);
+ writel((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING);
+ writel((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING);
+
+ writel((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING);
+ writel((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING);
+ writel((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING);
+
+ /* Write final register values. */
+ writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
+ writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+ par->vid_ops->configure_display(info);
+
+ /* Relock display controller registers */
+ writel(0, par->dc_regs + DC_UNLOCK);
+}
+
+static void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno,
+ unsigned red, unsigned green, unsigned blue)
+{
+ struct geodefb_par *par = info->par;
+ int val;
+
+ /* Hardware palette is in RGB 8-8-8 format. */
+ val = (red << 8) & 0xff0000;
+ val |= (green) & 0x00ff00;
+ val |= (blue >> 8) & 0x0000ff;
+
+ writel(regno, par->dc_regs + DC_PAL_ADDRESS);
+ writel(val, par->dc_regs + DC_PAL_DATA);
+}
+
+struct geode_dc_ops gx_dc_ops = {
+ .set_mode = gx_set_mode,
+ .set_palette_reg = gx_set_hw_palette_reg,
+};
diff --git a/drivers/video/geode/display_gx.h b/drivers/video/geode/display_gx.h
new file mode 100644
index 00000000000..86c62336130
--- /dev/null
+++ b/drivers/video/geode/display_gx.h
@@ -0,0 +1,96 @@
+/*
+ * Geode GX display controller
+ *
+ * Copyright (C) 2006 Arcom Control Systems Ltd.
+ *
+ * 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.
+ */
+#ifndef __DISPLAY_GX_H__
+#define __DISPLAY_GX_H__
+
+int gx_frame_buffer_size(void);
+int gx_line_delta(int xres, int bpp);
+
+extern struct geode_dc_ops gx_dc_ops;
+
+/* Display controller registers */
+
+#define DC_UNLOCK 0x00
+# define DC_UNLOCK_CODE 0x00004758
+
+#define DC_GENERAL_CFG 0x04
+# define DC_GCFG_DFLE 0x00000001
+# define DC_GCFG_CURE 0x00000002
+# define DC_GCFG_ICNE 0x00000004
+# define DC_GCFG_VIDE 0x00000008
+# define DC_GCFG_CMPE 0x00000020
+# define DC_GCFG_DECE 0x00000040
+# define DC_GCFG_VGAE 0x00000080
+# define DC_GCFG_DFHPSL_MASK 0x00000F00
+# define DC_GCFG_DFHPSL_POS 8
+# define DC_GCFG_DFHPEL_MASK 0x0000F000
+# define DC_GCFG_DFHPEL_POS 12
+# define DC_GCFG_STFM 0x00010000
+# define DC_GCFG_FDTY 0x00020000
+# define DC_GCFG_VGAFT 0x00040000
+# define DC_GCFG_VDSE 0x00080000
+# define DC_GCFG_YUVM 0x00100000
+# define DC_GCFG_VFSL 0x00800000
+# define DC_GCFG_SIGE 0x01000000
+# define DC_GCFG_SGRE 0x02000000
+# define DC_GCFG_SGFR 0x04000000
+# define DC_GCFG_CRC_MODE 0x08000000
+# define DC_GCFG_DIAG 0x10000000
+# define DC_GCFG_CFRW 0x20000000
+
+#define DC_DISPLAY_CFG 0x08
+# define DC_DCFG_TGEN 0x00000001
+# define DC_DCFG_GDEN 0x00000008
+# define DC_DCFG_VDEN 0x00000010
+# define DC_DCFG_TRUP 0x00000040
+# define DC_DCFG_DISP_MODE_MASK 0x00000300
+# define DC_DCFG_DISP_MODE_8BPP 0x00000000
+# define DC_DCFG_DISP_MODE_16BPP 0x00000100
+# define DC_DCFG_DISP_MODE_24BPP 0x00000200
+# define DC_DCFG_16BPP_MODE_MASK 0x00000c00
+# define DC_DCFG_16BPP_MODE_565 0x00000000
+# define DC_DCFG_16BPP_MODE_555 0x00000100
+# define DC_DCFG_16BPP_MODE_444 0x00000200
+# define DC_DCFG_DCEN 0x00080000
+# define DC_DCFG_PALB 0x02000000
+# define DC_DCFG_FRLK 0x04000000
+# define DC_DCFG_VISL 0x08000000
+# define DC_DCFG_FRSL 0x20000000
+# define DC_DCFG_A18M 0x40000000
+# define DC_DCFG_A20M 0x80000000
+
+#define DC_FB_ST_OFFSET 0x10
+
+#define DC_LINE_SIZE 0x30
+# define DC_LINE_SIZE_FB_LINE_SIZE_MASK 0x000007ff
+# define DC_LINE_SIZE_FB_LINE_SIZE_POS 0
+# define DC_LINE_SIZE_CB_LINE_SIZE_MASK 0x007f0000
+# define DC_LINE_SIZE_CB_LINE_SIZE_POS 16
+# define DC_LINE_SIZE_VID_LINE_SIZE_MASK 0xff000000
+# define DC_LINE_SIZE_VID_LINE_SIZE_POS 24
+
+#define DC_GFX_PITCH 0x34
+# define DC_GFX_PITCH_FB_PITCH_MASK 0x0000ffff
+# define DC_GFX_PITCH_FB_PITCH_POS 0
+# define DC_GFX_PITCH_CB_PITCH_MASK 0xffff0000
+# define DC_GFX_PITCH_CB_PITCH_POS 16
+
+#define DC_H_ACTIVE_TIMING 0x40
+#define DC_H_BLANK_TIMING 0x44
+#define DC_H_SYNC_TIMING 0x48
+#define DC_V_ACTIVE_TIMING 0x50
+#define DC_V_BLANK_TIMING 0x54
+#define DC_V_SYNC_TIMING 0x58
+
+#define DC_PAL_ADDRESS 0x70
+#define DC_PAL_DATA 0x74
+
+#endif /* !__DISPLAY_GX1_H__ */
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
new file mode 100644
index 00000000000..89c34b15f5d
--- /dev/null
+++ b/drivers/video/geode/gxfb_core.c
@@ -0,0 +1,423 @@
+/*
+ * Geode GX framebuffer driver.
+ *
+ * Copyright (C) 2006 Arcom Control Systems Ltd.
+ *
+ * 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 driver assumes that the BIOS has created a virtual PCI device header
+ * for the video device. The PCI header is assumed to contain the following
+ * BARs:
+ *
+ * BAR0 - framebuffer memory
+ * BAR1 - graphics processor registers
+ * BAR2 - display controller registers
+ * BAR3 - video processor and flat panel control registers.
+ *
+ * 16 MiB of framebuffer memory is assumed to be available.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include "geodefb.h"
+#include "display_gx.h"
+#include "video_gx.h"
+
+static char mode_option[32] = "640x480-16@60";
+
+/* Modes relevant to the GX (taken from modedb.c) */
+static const struct fb_videomode __initdata gx_modedb[] = {
+ /* 640x480-60 VESA */
+ { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 640x480-75 VESA */
+ { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 640x480-85 VESA */
+ { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 800x600-60 VESA */
+ { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 800x600-75 VESA */
+ { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 800x600-85 VESA */
+ { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1024x768-60 VESA */
+ { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
+ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1024x768-75 VESA */
+ { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1024x768-85 VESA */
+ { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x960-60 VESA */
+ { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x960-85 VESA */
+ { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x1024-60 VESA */
+ { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x1024-75 VESA */
+ { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1280x1024-85 VESA */
+ { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1600x1200-60 VESA */
+ { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1600x1200-75 VESA */
+ { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+ /* 1600x1200-85 VESA */
+ { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+};
+
+static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ if (var->xres > 1600 || var->yres > 1200)
+ return -EINVAL;
+ if ((var->xres > 1280 || var->yres > 1024) && var->bits_per_pixel > 16)
+ return -EINVAL;
+
+ if (var->bits_per_pixel == 32) {
+ var->red.offset = 16; var->red.length = 8;
+ var->green.offset = 8; var->green.length = 8;
+ var->blue.offset = 0; var->blue.length = 8;
+ } else if (var->bits_per_pixel == 16) {
+ var->red.offset = 11; var->red.length = 5;
+ var->green.offset = 5; var->green.length = 6;
+ var->blue.offset = 0; var->blue.length = 5;
+ } else if (var->bits_per_pixel == 8) {
+ var->red.offset = 0; var->red.length = 8;
+ var->green.offset = 0; var->green.length = 8;
+ var->blue.offset = 0; var->blue.length = 8;
+ } else
+ return -EINVAL;
+ var->transp.offset = 0; var->transp.length = 0;
+
+ /* Enough video memory? */
+ if (gx_line_delta(var->xres, var->bits_per_pixel) * var->yres > info->fix.smem_len)
+ return -EINVAL;
+
+ /* FIXME: Check timing parameters here? */
+
+ return 0;
+}
+
+static int gxfb_set_par(struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+
+ if (info->var.bits_per_pixel > 8) {
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ fb_dealloc_cmap(&info->cmap);
+ } else {
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ fb_alloc_cmap(&info->cmap, 1<<info->var.bits_per_pixel, 0);
+ }
+
+ info->fix.line_length = gx_line_delta(info->var.xres, info->var.bits_per_pixel);
+
+ par->dc_ops->set_mode(info);
+
+ return 0;
+}
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf->length;
+ return chan << bf->offset;
+}
+
+static int gxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+
+ if (info->var.grayscale) {
+ /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+ }
+
+ /* Truecolor has hardware independent palette */
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+ u32 *pal = info->pseudo_palette;
+ u32 v;
+
+ if (regno >= 16)
+ return -EINVAL;
+
+ v = chan_to_field(red, &info->var.red);
+ v |= chan_to_field(green, &info->var.green);
+ v |= chan_to_field(blue, &info->var.blue);
+
+ pal[regno] = v;
+ } else {
+ if (regno >= 256)
+ return -EINVAL;
+
+ par->dc_ops->set_palette_reg(info, regno, red, green, blue);
+ }
+
+ return 0;
+}
+
+static int gxfb_blank(int blank_mode, struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+
+ return par->vid_ops->blank_display(info, blank_mode);
+}
+
+static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
+{
+ struct geodefb_par *par = info->par;
+ int fb_len;
+ int ret;
+
+ ret = pci_enable_device(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = pci_request_region(dev, 3, "gxfb (video processor)");
+ if (ret < 0)
+ return ret;
+ par->vid_regs = ioremap(pci_resource_start(dev, 3),
+ pci_resource_len(dev, 3));
+ if (!par->vid_regs)
+ return -ENOMEM;
+
+ ret = pci_request_region(dev, 2, "gxfb (display controller)");
+ if (ret < 0)
+ return ret;
+ par->dc_regs = ioremap(pci_resource_start(dev, 2), pci_resource_len(dev, 2));
+ if (!par->dc_regs)
+ return -ENOMEM;
+
+ ret = pci_request_region(dev, 0, "gxfb (framebuffer)");
+ if (ret < 0)
+ return ret;
+ if ((fb_len = gx_frame_buffer_size()) < 0)
+ return -ENOMEM;
+ info->fix.smem_start = pci_resource_start(dev, 0);
+ info->fix.smem_len = fb_len;
+ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+ if (!info->screen_base)
+ return -ENOMEM;
+
+ dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
+ info->fix.smem_len / 1024, info->fix.smem_start);
+
+ return 0;
+}
+
+static struct fb_ops gxfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = gxfb_check_var,
+ .fb_set_par = gxfb_set_par,
+ .fb_setcolreg = gxfb_setcolreg,
+ .fb_blank = gxfb_blank,
+ /* No HW acceleration for now. */
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
+{
+ struct geodefb_par *par;
+ struct fb_info *info;
+
+ /* Alloc enough space for the pseudo palette. */
+ info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, dev);
+ if (!info)
+ return NULL;
+
+ par = info->par;
+
+ strcpy(info->fix.id, "Geode GX");
+
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.type_aux = 0;
+ info->fix.xpanstep = 0;
+ info->fix.ypanstep = 0;
+ info->fix.ywrapstep = 0;
+ info->fix.accel = FB_ACCEL_NONE;
+
+ info->var.nonstd = 0;
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->var.height = -1;
+ info->var.width = -1;
+ info->var.accel_flags = 0;
+ info->var.vmode = FB_VMODE_NONINTERLACED;
+
+ info->fbops = &gxfb_ops;
+ info->flags = FBINFO_DEFAULT;
+ info->node = -1;
+
+ info->pseudo_palette = (void *)par + sizeof(struct geodefb_par);
+
+ info->var.grayscale = 0;
+
+ return info;
+}
+
+static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct geodefb_par *par;
+ struct fb_info *info;
+ int ret;
+
+ info = gxfb_init_fbinfo(&pdev->dev);
+ if (!info)
+ return -ENOMEM;
+ par = info->par;
+
+ /* GX display controller and GX video device. */
+ par->dc_ops = &gx_dc_ops;
+ par->vid_ops = &gx_vid_ops;
+
+ if ((ret = gxfb_map_video_memory(info, pdev)) < 0) {
+ dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n");
+ goto err;
+ }
+
+ ret = fb_find_mode(&info->var, info, mode_option,
+ gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16);
+ if (ret == 0 || ret == 4) {
+ dev_err(&pdev->dev, "could not find valid video mode\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* Clear the frame buffer of garbage. */
+ memset_io(info->screen_base, 0, info->fix.smem_len);
+
+ gxfb_check_var(&info->var, info);
+ gxfb_set_par(info);
+
+ if (register_framebuffer(info) < 0) {
+ ret = -EINVAL;
+ goto err;
+ }
+ pci_set_drvdata(pdev, info);
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
+ return 0;
+
+ err:
+ if (info->screen_base) {
+ iounmap(info->screen_base);
+ pci_release_region(pdev, 0);
+ }
+ if (par->vid_regs) {
+ iounmap(par->vid_regs);
+ pci_release_region(pdev, 3);
+ }
+ if (par->dc_regs) {
+ iounmap(par->dc_regs);
+ pci_release_region(pdev, 2);
+ }
+
+ pci_disable_device(pdev);
+
+ if (info)
+ framebuffer_release(info);
+ return ret;
+}
+
+static void gxfb_remove(struct pci_dev *pdev)
+{
+ struct fb_info *info = pci_get_drvdata(pdev);
+ struct geodefb_par *par = info->par;
+
+ unregister_framebuffer(info);
+
+ iounmap((void __iomem *)info->screen_base);
+ pci_release_region(pdev, 0);
+
+ iounmap(par->vid_regs);
+ pci_release_region(pdev, 3);
+
+ iounmap(par->dc_regs);
+ pci_release_region(pdev, 2);
+
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+
+ framebuffer_release(info);
+}
+
+static struct pci_device_id gxfb_id_table[] = {
+ { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_VIDEO,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+ 0xff0000, 0 },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, gxfb_id_table);
+
+static struct pci_driver gxfb_driver = {
+ .name = "gxfb",
+ .id_table = gxfb_id_table,
+ .probe = gxfb_probe,
+ .remove = gxfb_remove,
+};
+
+static int __init gxfb_init(void)
+{
+#ifndef MODULE
+ if (fb_get_options("gxfb", NULL))
+ return -ENODEV;
+#endif
+ return pci_register_driver(&gxfb_driver);
+}
+
+static void __exit gxfb_cleanup(void)
+{
+ pci_unregister_driver(&gxfb_driver);
+}
+
+module_init(gxfb_init);
+module_exit(gxfb_cleanup);
+
+module_param_string(mode, mode_option, sizeof(mode_option), 0444);
+MODULE_PARM_DESC(mode, "video mode (<x>x<y>[-<bpp>][@<refr>])");
+
+MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c
new file mode 100644
index 00000000000..2b2a7880ea7
--- /dev/null
+++ b/drivers/video/geode/video_gx.c
@@ -0,0 +1,262 @@
+/*
+ * Geode GX video processor device.
+ *
+ * Copyright (C) 2006 Arcom Control Systems Ltd.
+ *
+ * Portions from AMD's original 2.4 driver:
+ * Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/msr.h>
+
+#include "geodefb.h"
+#include "video_gx.h"
+
+
+/*
+ * Tables of register settings for various DOTCLKs.
+ */
+struct gx_pll_entry {
+ long pixclock; /* ps */
+ u32 sys_rstpll_bits;
+ u32 dotpll_value;
+};
+
+#define POSTDIV3 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3)
+#define PREMULT2 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPREMULT2)
+#define PREDIV2 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3)
+
+static const struct gx_pll_entry gx_pll_table_48MHz[] = {
+ { 40123, POSTDIV3, 0x00000BF2 }, /* 24.9230 */
+ { 39721, 0, 0x00000037 }, /* 25.1750 */
+ { 35308, POSTDIV3|PREMULT2, 0x00000B1A }, /* 28.3220 */
+ { 31746, POSTDIV3, 0x000002D2 }, /* 31.5000 */
+ { 27777, POSTDIV3|PREMULT2, 0x00000FE2 }, /* 36.0000 */
+ { 26666, POSTDIV3, 0x0000057A }, /* 37.5000 */
+ { 25000, POSTDIV3, 0x0000030A }, /* 40.0000 */
+ { 22271, 0, 0x00000063 }, /* 44.9000 */
+ { 20202, 0, 0x0000054B }, /* 49.5000 */
+ { 20000, 0, 0x0000026E }, /* 50.0000 */
+ { 19860, PREMULT2, 0x00000037 }, /* 50.3500 */
+ { 18518, POSTDIV3|PREMULT2, 0x00000B0D }, /* 54.0000 */
+ { 17777, 0, 0x00000577 }, /* 56.2500 */
+ { 17733, 0, 0x000007F7 }, /* 56.3916 */
+ { 17653, 0, 0x0000057B }, /* 56.6444 */
+ { 16949, PREMULT2, 0x00000707 }, /* 59.0000 */
+ { 15873, POSTDIV3|PREMULT2, 0x00000B39 }, /* 63.0000 */
+ { 15384, POSTDIV3|PREMULT2, 0x00000B45 }, /* 65.0000 */
+ { 14814, POSTDIV3|PREMULT2, 0x00000FC1 }, /* 67.5000 */
+ { 14124, POSTDIV3, 0x00000561 }, /* 70.8000 */
+ { 13888, POSTDIV3, 0x000007E1 }, /* 72.0000 */
+ { 13426, PREMULT2, 0x00000F4A }, /* 74.4810 */
+ { 13333, 0, 0x00000052 }, /* 75.0000 */
+ { 12698, 0, 0x00000056 }, /* 78.7500 */
+ { 12500, POSTDIV3|PREMULT2, 0x00000709 }, /* 80.0000 */
+ { 11135, PREMULT2, 0x00000262 }, /* 89.8000 */
+ { 10582, 0, 0x000002D2 }, /* 94.5000 */
+ { 10101, PREMULT2, 0x00000B4A }, /* 99.0000 */
+ { 10000, PREMULT2, 0x00000036 }, /* 100.0000 */
+ { 9259, 0, 0x000007E2 }, /* 108.0000 */
+ { 8888, 0, 0x000007F6 }, /* 112.5000 */
+ { 7692, POSTDIV3|PREMULT2, 0x00000FB0 }, /* 130.0000 */
+ { 7407, POSTDIV3|PREMULT2, 0x00000B50 }, /* 135.0000 */
+ { 6349, 0, 0x00000055 }, /* 157.5000 */
+ { 6172, 0, 0x000009C1 }, /* 162.0000 */
+ { 5787, PREMULT2, 0x0000002D }, /* 172.798 */
+ { 5698, 0, 0x000002C1 }, /* 175.5000 */
+ { 5291, 0, 0x000002D1 }, /* 189.0000 */
+ { 4938, 0, 0x00000551 }, /* 202.5000 */
+ { 4357, 0, 0x0000057D }, /* 229.5000 */
+};
+
+static const struct gx_pll_entry gx_pll_table_14MHz[] = {
+ { 39721, 0, 0x00000037 }, /* 25.1750 */
+ { 35308, 0, 0x00000B7B }, /* 28.3220 */
+ { 31746, 0, 0x000004D3 }, /* 31.5000 */
+ { 27777, 0, 0x00000BE3 }, /* 36.0000 */
+ { 26666, 0, 0x0000074F }, /* 37.5000 */
+ { 25000, 0, 0x0000050B }, /* 40.0000 */
+ { 22271, 0, 0x00000063 }, /* 44.9000 */
+ { 20202, 0, 0x0000054B }, /* 49.5000 */
+ { 20000, 0, 0x0000026E }, /* 50.0000 */
+ { 19860, 0, 0x000007C3 }, /* 50.3500 */
+ { 18518, 0, 0x000007E3 }, /* 54.0000 */
+ { 17777, 0, 0x00000577 }, /* 56.2500 */
+ { 17733, 0, 0x000002FB }, /* 56.3916 */
+ { 17653, 0, 0x0000057B }, /* 56.6444 */
+ { 16949, 0, 0x0000058B }, /* 59.0000 */
+ { 15873, 0, 0x0000095E }, /* 63.0000 */
+ { 15384, 0, 0x0000096A }, /* 65.0000 */
+ { 14814, 0, 0x00000BC2 }, /* 67.5000 */
+ { 14124, 0, 0x0000098A }, /* 70.8000 */
+ { 13888, 0, 0x00000BE2 }, /* 72.0000 */
+ { 13333, 0, 0x00000052 }, /* 75.0000 */
+ { 12698, 0, 0x00000056 }, /* 78.7500 */
+ { 12500, 0, 0x0000050A }, /* 80.0000 */
+ { 11135, 0, 0x0000078E }, /* 89.8000 */
+ { 10582, 0, 0x000002D2 }, /* 94.5000 */
+ { 10101, 0, 0x000011F6 }, /* 99.0000 */
+ { 10000, 0, 0x0000054E }, /* 100.0000 */
+ { 9259, 0, 0x000007E2 }, /* 108.0000 */
+ { 8888, 0, 0x000002FA }, /* 112.5000 */
+ { 7692, 0, 0x00000BB1 }, /* 130.0000 */
+ { 7407, 0, 0x00000975 }, /* 135.0000 */
+ { 6349, 0, 0x00000055 }, /* 157.5000 */
+ { 6172, 0, 0x000009C1 }, /* 162.0000 */
+ { 5698, 0, 0x000002C1 }, /* 175.5000 */
+ { 5291, 0, 0x00000539 }, /* 189.0000 */
+ { 4938, 0, 0x00000551 }, /* 202.5000 */
+ { 4357, 0, 0x0000057D }, /* 229.5000 */
+};
+
+static void gx_set_dclk_frequency(struct fb_info *info)
+{
+ const struct gx_pll_entry *pll_table;
+ int pll_table_len;
+ int i, best_i;
+ long min, diff;
+ u64 dotpll, sys_rstpll;
+ int timeout = 1000;
+
+ /* Rev. 1 Geode GXs use a 14 MHz reference clock instead of 48 MHz. */
+ if (cpu_data->x86_mask == 1) {
+ pll_table = gx_pll_table_14MHz;
+ pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz);
+ } else {
+ pll_table = gx_pll_table_48MHz;
+ pll_table_len = ARRAY_SIZE(gx_pll_table_48MHz);
+ }
+
+ /* Search the table for the closest pixclock. */
+ best_i = 0;
+ min = abs(pll_table[0].pixclock - info->var.pixclock);
+ for (i = 1; i < pll_table_len; i++) {
+ diff = abs(pll_table[i].pixclock - info->var.pixclock);
+ if (diff < min) {
+ min = diff;
+ best_i = i;
+ }
+ }
+
+ rdmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll);
+ rdmsrl(MSR_GLCP_DOTPLL, dotpll);
+
+ /* Program new M, N and P. */
+ dotpll &= 0x00000000ffffffffull;
+ dotpll |= (u64)pll_table[best_i].dotpll_value << 32;
+ dotpll |= MSR_GLCP_DOTPLL_DOTRESET;
+ dotpll &= ~MSR_GLCP_DOTPLL_BYPASS;
+
+ wrmsrl(MSR_GLCP_DOTPLL, dotpll);
+
+ /* Program dividers. */
+ sys_rstpll &= ~( MSR_GLCP_SYS_RSTPLL_DOTPREDIV2
+ | MSR_GLCP_SYS_RSTPLL_DOTPREMULT2
+ | MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 );
+ sys_rstpll |= pll_table[best_i].sys_rstpll_bits;
+
+ wrmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll);
+
+ /* Clear reset bit to start PLL. */
+ dotpll &= ~(MSR_GLCP_DOTPLL_DOTRESET);
+ wrmsrl(MSR_GLCP_DOTPLL, dotpll);
+
+ /* Wait for LOCK bit. */
+ do {
+ rdmsrl(MSR_GLCP_DOTPLL, dotpll);
+ } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK));
+}
+
+static void gx_configure_display(struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+ u32 dcfg, fp_pm;
+
+ dcfg = readl(par->vid_regs + GX_DCFG);
+
+ /* Clear bits from existing mode. */
+ dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK
+ | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL
+ | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
+
+ /* Set default sync skew. */
+ dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT;
+
+ /* Enable hsync and vsync. */
+ dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN;
+
+ /* Sync polarities. */
+ if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+ dcfg |= GX_DCFG_CRT_HSYNC_POL;
+ if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+ dcfg |= GX_DCFG_CRT_VSYNC_POL;
+
+ writel(dcfg, par->vid_regs + GX_DCFG);
+
+ /* Power on flat panel. */
+ fp_pm = readl(par->vid_regs + GX_FP_PM);
+ fp_pm |= GX_FP_PM_P;
+ writel(fp_pm, par->vid_regs + GX_FP_PM);
+}
+
+static int gx_blank_display(struct fb_info *info, int blank_mode)
+{
+ struct geodefb_par *par = info->par;
+ u32 dcfg, fp_pm;
+ int blank, hsync, vsync;
+
+ /* CRT power saving modes. */
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ blank = 0; hsync = 1; vsync = 1;
+ break;
+ case FB_BLANK_NORMAL:
+ blank = 1; hsync = 1; vsync = 1;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ blank = 1; hsync = 1; vsync = 0;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ blank = 1; hsync = 0; vsync = 1;
+ break;
+ case FB_BLANK_POWERDOWN:
+ blank = 1; hsync = 0; vsync = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ dcfg = readl(par->vid_regs + GX_DCFG);
+ dcfg &= ~(GX_DCFG_DAC_BL_EN
+ | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN);
+ if (!blank)
+ dcfg |= GX_DCFG_DAC_BL_EN;
+ if (hsync)
+ dcfg |= GX_DCFG_HSYNC_EN;
+ if (vsync)
+ dcfg |= GX_DCFG_VSYNC_EN;
+ writel(dcfg, par->vid_regs + GX_DCFG);
+
+ /* Power on/off flat panel. */
+ fp_pm = readl(par->vid_regs + GX_FP_PM);
+ if (blank_mode == FB_BLANK_POWERDOWN)
+ fp_pm &= ~GX_FP_PM_P;
+ else
+ fp_pm |= GX_FP_PM_P;
+ writel(fp_pm, par->vid_regs + GX_FP_PM);
+
+ return 0;
+}
+
+struct geode_vid_ops gx_vid_ops = {
+ .set_dclk = gx_set_dclk_frequency,
+ .configure_display = gx_configure_display,
+ .blank_display = gx_blank_display,
+};
diff --git a/drivers/video/geode/video_gx.h b/drivers/video/geode/video_gx.h
new file mode 100644
index 00000000000..2d9211f3ed8
--- /dev/null
+++ b/drivers/video/geode/video_gx.h
@@ -0,0 +1,47 @@
+/*
+ * Geode GX video device
+ *
+ * Copyright (C) 2006 Arcom Control Systems Ltd.
+ *
+ * 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.
+ */
+#ifndef __VIDEO_GX_H__
+#define __VIDEO_GX_H__
+
+extern struct geode_vid_ops gx_vid_ops;
+
+/* Geode GX video processor registers */
+
+#define GX_DCFG 0x0008
+# define GX_DCFG_CRT_EN 0x00000001
+# define GX_DCFG_HSYNC_EN 0x00000002
+# define GX_DCFG_VSYNC_EN 0x00000004
+# define GX_DCFG_DAC_BL_EN 0x00000008
+# define GX_DCFG_CRT_HSYNC_POL 0x00000100
+# define GX_DCFG_CRT_VSYNC_POL 0x00000200
+# define GX_DCFG_CRT_SYNC_SKW_MASK 0x0001C000
+# define GX_DCFG_CRT_SYNC_SKW_DFLT 0x00010000
+# define GX_DCFG_VG_CK 0x00100000
+# define GX_DCFG_GV_GAM 0x00200000
+# define GX_DCFG_DAC_VREF 0x04000000
+
+/* Geode GX flat panel display control registers */
+#define GX_FP_PM 0x410
+# define GX_FP_PM_P 0x01000000
+
+/* Geode GX clock control MSRs */
+
+#define MSR_GLCP_SYS_RSTPLL 0x4c000014
+# define MSR_GLCP_SYS_RSTPLL_DOTPREDIV2 (0x0000000000000002ull)
+# define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 (0x0000000000000004ull)
+# define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 (0x0000000000000008ull)
+
+#define MSR_GLCP_DOTPLL 0x4c000015
+# define MSR_GLCP_DOTPLL_DOTRESET (0x0000000000000001ull)
+# define MSR_GLCP_DOTPLL_BYPASS (0x0000000000008000ull)
+# define MSR_GLCP_DOTPLL_LOCK (0x0000000002000000ull)
+
+#endif /* !__VIDEO_GX_H__ */
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
index bebdac59d23..abd920a663a 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/hpfb.c
@@ -386,7 +386,9 @@ int __init hpfb_init(void)
if (fb_get_options("hpfb", NULL))
return -ENODEV;
- dio_module_init(&hpfb_driver);
+ err = dio_register_driver(&hpfb_driver);
+ if (err)
+ return err;
fs = get_fs();
set_fs(KERNEL_DS);
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index e3c8b5f1ca7..3fe3ae1aff1 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -210,8 +210,7 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
}
}
- if (out_edid)
- *out_edid = edid;
+ *out_edid = edid;
return (edid) ? 0 : 1;
}
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 7db42542eb1..f73c642b50c 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -440,9 +440,9 @@ getclkMHz(struct imstt_par *par)
static void
setclkMHz(struct imstt_par *par, __u32 MHz)
{
- __u32 clk_m, clk_n, clk_p, x, stage, spilled;
+ __u32 clk_m, clk_n, x, stage, spilled;
- clk_m = clk_n = clk_p = 0;
+ clk_m = clk_n = 0;
stage = spilled = 0;
for (;;) {
switch (stage) {
@@ -453,7 +453,7 @@ setclkMHz(struct imstt_par *par, __u32 MHz)
clk_n++;
break;
}
- x = 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1));
+ x = 20 * (clk_m + 1) / (clk_n + 1);
if (x == MHz)
break;
if (x > MHz) {
@@ -466,7 +466,7 @@ setclkMHz(struct imstt_par *par, __u32 MHz)
par->init.pclk_m = clk_m;
par->init.pclk_n = clk_n;
- par->init.pclk_p = clk_p;
+ par->init.pclk_p = 0;
}
static struct imstt_regvals *
@@ -1372,18 +1372,24 @@ init_imstt(struct fb_info *info)
write_reg_le32(par->dc_regs, STGCTL, tmp & ~0x1);
write_reg_le32(par->dc_regs, SSR, 0);
- /* set default values for DAC registers */
+ /* set default values for DAC registers */
if (par->ramdac == IBM) {
- par->cmap_regs[PPMASK] = 0xff; eieio();
- par->cmap_regs[PIDXHI] = 0; eieio();
- for (i = 0; i < sizeof(ibm_initregs) / sizeof(*ibm_initregs); i++) {
- par->cmap_regs[PIDXLO] = ibm_initregs[i].addr; eieio();
- par->cmap_regs[PIDXDATA] = ibm_initregs[i].value; eieio();
+ par->cmap_regs[PPMASK] = 0xff;
+ eieio();
+ par->cmap_regs[PIDXHI] = 0;
+ eieio();
+ for (i = 0; i < ARRAY_SIZE(ibm_initregs); i++) {
+ par->cmap_regs[PIDXLO] = ibm_initregs[i].addr;
+ eieio();
+ par->cmap_regs[PIDXDATA] = ibm_initregs[i].value;
+ eieio();
}
} else {
- for (i = 0; i < sizeof(tvp_initregs) / sizeof(*tvp_initregs); i++) {
- par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr; eieio();
- par->cmap_regs[TVPIDATA] = tvp_initregs[i].value; eieio();
+ for (i = 0; i < ARRAY_SIZE(tvp_initregs); i++) {
+ par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr;
+ eieio();
+ par->cmap_regs[TVPIDATA] = tvp_initregs[i].value;
+ eieio();
}
}
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index 2fc71081f7e..c0385c6f7db 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -380,7 +380,7 @@ int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
if (mode_option && !strncmp(mode_option, "mac", 3)) {
mode_option += 3;
db = mac_modedb;
- dbsize = sizeof(mac_modedb)/sizeof(*mac_modedb);
+ dbsize = ARRAY_SIZE(mac_modedb);
}
return fb_find_mode(var, info, mode_option, db, dbsize,
&mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp);
diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c
index 0fbd9b5149f..a456e67a5b0 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.c
+++ b/drivers/video/matrox/matroxfb_DAC1064.c
@@ -12,7 +12,6 @@
*
*/
-/* make checkconfig does not walk through include tree :-( */
#include <linux/config.h>
#include "matroxfb_DAC1064.h"
diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/matrox/matroxfb_DAC1064.h
index a6a47012728..2e7238aa243 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.h
+++ b/drivers/video/matrox/matroxfb_DAC1064.h
@@ -1,7 +1,6 @@
#ifndef __MATROXFB_DAC1064_H__
#define __MATROXFB_DAC1064_H__
-/* make checkconfig does not walk through include tree */
#include <linux/config.h>
#include "matroxfb_base.h"
diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c
index 537ade5d8b2..23ebad0a12d 100644
--- a/drivers/video/matrox/matroxfb_Ti3026.c
+++ b/drivers/video/matrox/matroxfb_Ti3026.c
@@ -78,7 +78,6 @@
*
*/
-/* make checkconfig does not verify included files... */
#include <linux/config.h>
#include "matroxfb_Ti3026.h"
diff --git a/drivers/video/matrox/matroxfb_Ti3026.h b/drivers/video/matrox/matroxfb_Ti3026.h
index 541933d7e4e..536e5f69de9 100644
--- a/drivers/video/matrox/matroxfb_Ti3026.h
+++ b/drivers/video/matrox/matroxfb_Ti3026.h
@@ -1,7 +1,6 @@
#ifndef __MATROXFB_TI3026_H__
#define __MATROXFB_TI3026_H__
-/* make checkconfig does not walk through whole include tree */
#include <linux/config.h>
#include "matroxfb_base.h"
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 4055ff6f5a8..23c1827b2d0 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -99,7 +99,6 @@
*
*/
-/* make checkconfig does not check included files... */
#include <linux/config.h>
#include <linux/version.h>
@@ -116,6 +115,7 @@
#include <asm/uaccess.h>
#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
unsigned char nvram_read_byte(int);
static int default_vmode = VMODE_NVRAM;
static int default_cmode = CMODE_NVRAM;
@@ -1834,7 +1834,7 @@ static int initMatrox2(WPMINFO struct board* b){
/* FIXME: Where to move this?! */
#if defined(CONFIG_PPC_PMAC)
#ifndef MODULE
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
struct fb_var_screeninfo var;
if (default_vmode <= 0 || default_vmode > VMODE_MAX)
default_vmode = VMODE_640_480_60;
diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c
index c122d8743dd..4d610b405d4 100644
--- a/drivers/video/matrox/matroxfb_g450.c
+++ b/drivers/video/matrox/matroxfb_g450.c
@@ -59,7 +59,7 @@ static const struct mctl g450_controls[] =
}, offsetof(struct matrox_fb_info, altout.tvo_params.testout) },
};
-#define G450CTRLS (sizeof(g450_controls)/sizeof(g450_controls[0]))
+#define G450CTRLS ARRAY_SIZE(g450_controls)
/* Return: positive number: id found
-EINVAL: id not found, return failure
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 6019710dc29..5d29a26b8cd 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -89,12 +89,12 @@ static const struct mctl maven_controls[] =
}, offsetof(struct matrox_fb_info, altout.tvo_params.hue) },
{ { V4L2_CID_GAMMA, V4L2_CTRL_TYPE_INTEGER,
"gamma",
- 0, sizeof(maven_gamma)/sizeof(maven_gamma[0])-1, 1, 3,
+ 0, ARRAY_SIZE(maven_gamma) - 1, 1, 3,
0,
}, offsetof(struct matrox_fb_info, altout.tvo_params.gamma) },
{ { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN,
"test output",
- 0, 1, 1, 0,
+ 0, 1, 1, 0,
0,
}, offsetof(struct matrox_fb_info, altout.tvo_params.testout) },
{ { MATROXFB_CID_DEFLICKER, V4L2_CTRL_TYPE_INTEGER,
@@ -105,7 +105,7 @@ static const struct mctl maven_controls[] =
};
-#define MAVCTRLS (sizeof(maven_controls)/sizeof(maven_controls[0]))
+#define MAVCTRLS ARRAY_SIZE(maven_controls)
/* Return: positive number: id found
-EINVAL: id not found, return failure
@@ -129,7 +129,7 @@ static int get_ctrl_id(__u32 v4l2_id) {
struct maven_data {
struct matrox_fb_info* primary_head;
- struct i2c_client* client;
+ struct i2c_client client;
int version;
};
@@ -970,7 +970,7 @@ static inline int maven_compute_timming(struct maven_data* md,
static int maven_program_timming(struct maven_data* md,
const struct mavenregs* m) {
- struct i2c_client* c = md->client;
+ struct i2c_client* c = &md->client;
if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) {
LR(0x80);
@@ -1007,7 +1007,7 @@ static int maven_program_timming(struct maven_data* md,
}
static inline int maven_resync(struct maven_data* md) {
- struct i2c_client* c = md->client;
+ struct i2c_client* c = &md->client;
maven_set_reg(c, 0x95, 0x20); /* start whole thing */
return 0;
}
@@ -1065,48 +1065,48 @@ static int maven_set_control (struct maven_data* md,
maven_compute_bwlevel(md, &blacklevel, &whitelevel);
blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8);
whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8);
- maven_set_reg_pair(md->client, 0x0e, blacklevel);
- maven_set_reg_pair(md->client, 0x1e, whitelevel);
+ maven_set_reg_pair(&md->client, 0x0e, blacklevel);
+ maven_set_reg_pair(&md->client, 0x1e, whitelevel);
}
break;
case V4L2_CID_SATURATION:
{
- maven_set_reg(md->client, 0x20, p->value);
- maven_set_reg(md->client, 0x22, p->value);
+ maven_set_reg(&md->client, 0x20, p->value);
+ maven_set_reg(&md->client, 0x22, p->value);
}
break;
case V4L2_CID_HUE:
{
- maven_set_reg(md->client, 0x25, p->value);
+ maven_set_reg(&md->client, 0x25, p->value);
}
break;
case V4L2_CID_GAMMA:
{
const struct maven_gamma* g;
g = maven_compute_gamma(md);
- maven_set_reg(md->client, 0x83, g->reg83);
- maven_set_reg(md->client, 0x84, g->reg84);
- maven_set_reg(md->client, 0x85, g->reg85);
- maven_set_reg(md->client, 0x86, g->reg86);
- maven_set_reg(md->client, 0x87, g->reg87);
- maven_set_reg(md->client, 0x88, g->reg88);
- maven_set_reg(md->client, 0x89, g->reg89);
- maven_set_reg(md->client, 0x8a, g->reg8a);
- maven_set_reg(md->client, 0x8b, g->reg8b);
+ maven_set_reg(&md->client, 0x83, g->reg83);
+ maven_set_reg(&md->client, 0x84, g->reg84);
+ maven_set_reg(&md->client, 0x85, g->reg85);
+ maven_set_reg(&md->client, 0x86, g->reg86);
+ maven_set_reg(&md->client, 0x87, g->reg87);
+ maven_set_reg(&md->client, 0x88, g->reg88);
+ maven_set_reg(&md->client, 0x89, g->reg89);
+ maven_set_reg(&md->client, 0x8a, g->reg8a);
+ maven_set_reg(&md->client, 0x8b, g->reg8b);
}
break;
case MATROXFB_CID_TESTOUT:
{
unsigned char val
- = maven_get_reg (md->client,0x8d);
+ = maven_get_reg(&md->client,0x8d);
if (p->value) val |= 0x10;
else val &= ~0x10;
- maven_set_reg (md->client, 0x8d, val);
+ maven_set_reg(&md->client, 0x8d, val);
}
break;
case MATROXFB_CID_DEFLICKER:
{
- maven_set_reg(md->client, 0x93, maven_compute_deflicker(md));
+ maven_set_reg(&md->client, 0x93, maven_compute_deflicker(md));
}
break;
}
@@ -1185,7 +1185,6 @@ static int maven_init_client(struct i2c_client* clnt) {
MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo);
md->primary_head = MINFO;
- md->client = clnt;
down_write(&ACCESS_FBINFO(altout.lock));
ACCESS_FBINFO(outputs[1]).output = &maven_altout;
ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src;
@@ -1243,19 +1242,17 @@ static int maven_detect_client(struct i2c_adapter* adapter, int address, int kin
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_PROTOCOL_MANGLING))
goto ERROR0;
- if (!(new_client = (struct i2c_client*)kmalloc(sizeof(*new_client) + sizeof(*data),
- GFP_KERNEL))) {
+ if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR0;
}
- memset(new_client, 0, sizeof(*new_client) + sizeof(*data));
- data = (struct maven_data*)(new_client + 1);
+ new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &maven_driver;
new_client->flags = 0;
- strcpy(new_client->name, "maven client");
+ strlcpy(new_client->name, "maven", I2C_NAME_SIZE);
if ((err = i2c_attach_client(new_client)))
goto ERROR3;
err = maven_init_client(new_client);
@@ -1279,12 +1276,10 @@ static int maven_attach_adapter(struct i2c_adapter* adapter) {
static int maven_detach_client(struct i2c_client* client) {
int err;
- if ((err = i2c_detach_client(client))) {
- printk(KERN_ERR "maven: Cannot deregister client\n");
+ if ((err = i2c_detach_client(client)))
return err;
- }
maven_shutdown_client(client);
- kfree(client);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -1297,20 +1292,13 @@ static struct i2c_driver maven_driver={
.detach_client = maven_detach_client,
};
-/* ************************** */
-
-static int matroxfb_maven_init(void) {
- int err;
-
- err = i2c_add_driver(&maven_driver);
- if (err) {
- printk(KERN_ERR "maven: Maven driver failed to register (%d).\n", err);
- return err;
- }
- return 0;
+static int __init matroxfb_maven_init(void)
+{
+ return i2c_add_driver(&maven_driver);
}
-static void matroxfb_maven_exit(void) {
+static void __exit matroxfb_maven_exit(void)
+{
i2c_del_driver(&maven_driver);
}
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
index 455a46ce840..263d801ef78 100644
--- a/drivers/video/matrox/matroxfb_misc.c
+++ b/drivers/video/matrox/matroxfb_misc.c
@@ -84,7 +84,6 @@
*
*/
-/* make checkconfig does not check includes for this... */
#include <linux/config.h>
#include "matroxfb_misc.h"
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 1da2f84bdc2..26a1c618a20 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -183,6 +183,10 @@ static const struct fb_videomode modedb[] = {
NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
}, {
+ /* 1680x1050 @ 60 Hz, 65.191 kHz hsync */
+ NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ }, {
/* 1600x1200 @ 85 Hz, 105.77 kHz hsync */
NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
@@ -496,7 +500,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
/* Set up defaults */
if (!db) {
db = modedb;
- dbsize = sizeof(modedb)/sizeof(*modedb);
+ dbsize = ARRAY_SIZE(modedb);
}
if (!default_mode)
default_mode = &modedb[DEFAULT_MODEDB_INDEX];
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index b961d5601bd..24b12f71d5a 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -165,20 +165,20 @@ static int neoFindMode(int xres, int yres, int depth)
switch (depth) {
case 8:
- size = sizeof(bios8) / sizeof(biosMode);
+ size = ARRAY_SIZE(bios8);
mode = bios8;
break;
case 16:
- size = sizeof(bios16) / sizeof(biosMode);
+ size = ARRAY_SIZE(bios16);
mode = bios16;
break;
case 24:
- size = sizeof(bios24) / sizeof(biosMode);
+ size = ARRAY_SIZE(bios24);
mode = bios24;
break;
#ifdef NO_32BIT_SUPPORT_YET
case 32:
- size = sizeof(bios32) / sizeof(biosMode);
+ size = ARRAY_SIZE(bios32);
mode = bios32;
break;
#endif
diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c
index f377a29ec97..4aefb8f4163 100644
--- a/drivers/video/nvidia/nv_accel.c
+++ b/drivers/video/nvidia/nv_accel.c
@@ -300,6 +300,9 @@ int nvidiafb_sync(struct fb_info *info)
{
struct nvidia_par *par = info->par;
+ if (info->state != FBINFO_STATE_RUNNING)
+ return 0;
+
if (!par->lockup)
NVFlush(par);
@@ -313,6 +316,9 @@ void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
struct nvidia_par *par = info->par;
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
+
if (par->lockup)
return cfb_copyarea(info, region);
@@ -329,6 +335,9 @@ void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
struct nvidia_par *par = info->par;
u32 color;
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
+
if (par->lockup)
return cfb_fillrect(info, rect);
@@ -412,6 +421,9 @@ void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct nvidia_par *par = info->par;
+ if (info->state != FBINFO_STATE_RUNNING)
+ return;
+
if (image->depth == 1 && !par->lockup)
nvidiafb_mono_color_expand(info, image);
else
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index bd9eca05e14..1edb1c432b7 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -218,8 +218,7 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
}
}
- if (out_edid)
- *out_edid = edid;
+ *out_edid = edid;
return (edid) ? 0 : 1;
}
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h
index e4a5b1da71c..acdc2669340 100644
--- a/drivers/video/nvidia/nv_type.h
+++ b/drivers/video/nvidia/nv_type.h
@@ -129,6 +129,7 @@ struct nvidia_par {
int fpHeight;
int PanelTweak;
int paneltweak;
+ int pm_state;
u32 crtcSync_read;
u32 fpSyncs;
u32 dmaPut;
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index a7c4e5e8ead..093ab9977c7 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -21,6 +21,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/console.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
@@ -29,6 +30,7 @@
#include <asm/pci-bridge.h>
#endif
#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/machdep.h>
#include <asm/backlight.h>
#endif
@@ -296,6 +298,8 @@ static struct pci_device_id nvidiafb_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, 0x0252,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, 0x0313,
@@ -615,6 +619,30 @@ static int nvidia_panel_tweak(struct nvidia_par *par,
return tweak;
}
+static void nvidia_vga_protect(struct nvidia_par *par, int on)
+{
+ unsigned char tmp;
+
+ if (on) {
+ /*
+ * Turn off screen and disable sequencer.
+ */
+ tmp = NVReadSeq(par, 0x01);
+
+ NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */
+ NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */
+ } else {
+ /*
+ * Reenable sequencer, then turn on screen.
+ */
+
+ tmp = NVReadSeq(par, 0x01);
+
+ NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */
+ NVWriteSeq(par, 0x00, 0x03); /* End Reset */
+ }
+}
+
static void nvidia_save_vga(struct nvidia_par *par,
struct _riva_hw_state *state)
{
@@ -643,9 +671,9 @@ static void nvidia_save_vga(struct nvidia_par *par,
#undef DUMP_REG
-static void nvidia_write_regs(struct nvidia_par *par)
+static void nvidia_write_regs(struct nvidia_par *par,
+ struct _riva_hw_state *state)
{
- struct _riva_hw_state *state = &par->ModeReg;
int i;
NVTRACE_ENTER();
@@ -694,32 +722,6 @@ static void nvidia_write_regs(struct nvidia_par *par)
NVTRACE_LEAVE();
}
-static void nvidia_vga_protect(struct nvidia_par *par, int on)
-{
- unsigned char tmp;
-
- if (on) {
- /*
- * Turn off screen and disable sequencer.
- */
- tmp = NVReadSeq(par, 0x01);
-
- NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */
- NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */
- } else {
- /*
- * Reenable sequencer, then turn on screen.
- */
-
- tmp = NVReadSeq(par, 0x01);
-
- NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */
- NVWriteSeq(par, 0x00, 0x03); /* End Reset */
- }
-}
-
-
-
static int nvidia_calc_regs(struct fb_info *info)
{
struct nvidia_par *par = info->par;
@@ -1068,7 +1070,8 @@ static int nvidiafb_set_par(struct fb_info *info)
nvidia_vga_protect(par, 1);
- nvidia_write_regs(par);
+ nvidia_write_regs(par, &par->ModeReg);
+ NVSetStartAddress(par, 0);
#if defined (__BIG_ENDIAN)
/* turn on LFB swapping */
@@ -1353,7 +1356,7 @@ static int nvidiafb_blank(int blank, struct fb_info *info)
NVWriteCrtc(par, 0x1a, vesa);
#ifdef CONFIG_PMAC_BACKLIGHT
- if (par->FlatPanel && _machine == _MACH_Pmac) {
+ if (par->FlatPanel && machine_is(powermac)) {
set_backlight_enable(!blank);
}
#endif
@@ -1377,6 +1380,57 @@ static struct fb_ops nvidia_fb_ops = {
.fb_sync = nvidiafb_sync,
};
+#ifdef CONFIG_PM
+static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct nvidia_par *par = info->par;
+
+ acquire_console_sem();
+ par->pm_state = state.event;
+
+ if (state.event == PM_EVENT_FREEZE) {
+ dev->dev.power.power_state = state;
+ } else {
+ fb_set_suspend(info, 1);
+ nvidiafb_blank(FB_BLANK_POWERDOWN, info);
+ nvidia_write_regs(par, &par->SavedReg);
+ pci_save_state(dev);
+ pci_disable_device(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+ }
+
+ release_console_sem();
+ return 0;
+}
+
+static int nvidiafb_resume(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct nvidia_par *par = info->par;
+
+ acquire_console_sem();
+ pci_set_power_state(dev, PCI_D0);
+
+ if (par->pm_state != PM_EVENT_FREEZE) {
+ pci_restore_state(dev);
+ pci_enable_device(dev);
+ pci_set_master(dev);
+ }
+
+ par->pm_state = PM_EVENT_ON;
+ nvidiafb_set_par(info);
+ fb_set_suspend (info, 0);
+ nvidiafb_blank(FB_BLANK_UNBLANK, info);
+
+ release_console_sem();
+ return 0;
+}
+#else
+#define nvidiafb_suspend NULL
+#define nvidiafb_resume NULL
+#endif
+
static int __devinit nvidia_set_fbinfo(struct fb_info *info)
{
struct fb_monspecs *specs = &info->monspecs;
@@ -1688,7 +1742,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
info->fix.id,
par->FbMapSize / (1024 * 1024), info->fix.smem_start);
#ifdef CONFIG_PMAC_BACKLIGHT
- if (par->FlatPanel && _machine == _MACH_Pmac)
+ if (par->FlatPanel && machine_is(powermac))
register_backlight_controller(&nvidia_backlight_controller,
par, "mnca");
#endif
@@ -1720,8 +1774,6 @@ static void __exit nvidiafb_remove(struct pci_dev *pd)
struct nvidia_par *par = info->par;
NVTRACE_ENTER();
- if (!info)
- return;
unregister_framebuffer(info);
#ifdef CONFIG_MTRR
@@ -1798,8 +1850,10 @@ static int __devinit nvidiafb_setup(char *options)
static struct pci_driver nvidiafb_driver = {
.name = "nvidiafb",
.id_table = nvidiafb_pci_tbl,
- .probe = nvidiafb_probe,
- .remove = __exit_p(nvidiafb_remove),
+ .probe = nvidiafb_probe,
+ .suspend = nvidiafb_suspend,
+ .resume = nvidiafb_resume,
+ .remove = __exit_p(nvidiafb_remove),
};
/* ------------------------------------------------------------------------- *
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 0e78ddc8158..52c18a35fb4 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -3532,26 +3532,26 @@ int __init pm3fb_init(void)
MODULE_AUTHOR("Romain Dolbeau");
MODULE_DESCRIPTION("Permedia3 framebuffer device driver");
static char *mode[PM3_MAX_BOARD];
-MODULE_PARM(mode,PM3_MAX_BOARD_MODULE_ARRAY_STRING);
+module_param_array(mode, charp, NULL, 0);
MODULE_PARM_DESC(mode,"video mode");
-MODULE_PARM(disable,PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
+module_param_array(disable, short, NULL, 0);
MODULE_PARM_DESC(disable,"disable board");
static short off[PM3_MAX_BOARD];
-MODULE_PARM(off,PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
+module_param_array(off, short, NULL, 0);
MODULE_PARM_DESC(off,"disable board");
static char *pciid[PM3_MAX_BOARD];
-MODULE_PARM(pciid,PM3_MAX_BOARD_MODULE_ARRAY_STRING);
+module_param_array(pciid, charp, NULL, 0);
MODULE_PARM_DESC(pciid,"board PCI Id");
-MODULE_PARM(noaccel,PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
+module_param_array(noaccel, short, NULL, 0);
MODULE_PARM_DESC(noaccel,"disable accel");
static char *font[PM3_MAX_BOARD];
-MODULE_PARM(font,PM3_MAX_BOARD_MODULE_ARRAY_STRING);
+module_param_array(font, charp, NULL, 0);
MODULE_PARM_DESC(font,"choose font");
-MODULE_PARM(depth,PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
+module_param(depth, short, NULL, 0);
MODULE_PARM_DESC(depth,"boot-time depth");
-MODULE_PARM(printtimings, "h");
+module_param(printtimings, short, NULL, 0);
MODULE_PARM_DESC(printtimings, "print the memory timings of the card(s)");
-MODULE_PARM(forcesize, PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
+module_param(forcesize, short, NULL, 0);
MODULE_PARM_DESC(forcesize, "force specified memory size");
/*
MODULE_SUPPORTED_DEVICE("Permedia3 PCI boards")
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index eeeac924b50..73e2d7d1660 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -228,7 +228,7 @@ static void __init pmagbbfb_osc_setup(struct fb_info *info)
freq1 = (par->osc0 * count1 + count0 / 2) / count0;
par->osc1 = freq1;
- for (i = 0; i < sizeof(pmagbbfb_freqs) / sizeof(*pmagbbfb_freqs); i++)
+ for (i = 0; i < ARRAY_SIZE(pmagbbfb_freqs); i++)
if (freq1 >= pmagbbfb_freqs[i] -
(pmagbbfb_freqs[i] + 128) / 256 &&
freq1 <= pmagbbfb_freqs[i] +
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index db9fb9074db..afb6c2ead59 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -759,7 +759,7 @@ static void __iomem *radeon_find_rom(struct radeonfb_info *rinfo)
rom = rom_base;
for (i = 0; (i < 512) && (stage != 4); i++) {
- for(j = 0;j < sizeof(radeon_sig)/sizeof(char *);j++) {
+ for (j = 0; j < ARRAY_SIZE(radeon_sig); j++) {
if (radeon_sig[j][0] == *rom)
if (strncmp(radeon_sig[j], rom,
strlen(radeon_sig[j])) == 0) {
@@ -1596,7 +1596,7 @@ static int radeonfb_blank (int blank, struct fb_info *info)
return 0;
#ifdef CONFIG_PMAC_BACKLIGHT
- if (rinfo->dviDisp_type == MT_LCD && _machine == _MACH_Pmac) {
+ if (rinfo->dviDisp_type == MT_LCD && machine_is(powermac)) {
set_backlight_enable(!blank);
return 0;
}
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 6c19ab6afb0..3e9308f0f16 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -49,6 +49,7 @@
#include <asm/pci-bridge.h>
#endif
#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/machdep.h>
#include <asm/backlight.h>
#endif
@@ -1247,7 +1248,7 @@ static int rivafb_blank(int blank, struct fb_info *info)
CRTCout(par, 0x1a, vesa);
#ifdef CONFIG_PMAC_BACKLIGHT
- if ( par->FlatPanel && _machine == _MACH_Pmac) {
+ if ( par->FlatPanel && machine_is(powermac)) {
set_backlight_enable(!blank);
}
#endif
@@ -2037,9 +2038,9 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
info->fix.smem_len / (1024 * 1024),
info->fix.smem_start);
#ifdef CONFIG_PMAC_BACKLIGHT
- if (default_par->FlatPanel && _machine == _MACH_Pmac)
- register_backlight_controller(&riva_backlight_controller,
- default_par, "mnca");
+ if (default_par->FlatPanel && machine_is(powermac))
+ register_backlight_controller(&riva_backlight_controller,
+ default_par, "mnca");
#endif
NVTRACE_LEAVE();
return 0;
@@ -2072,8 +2073,6 @@ static void __exit rivafb_remove(struct pci_dev *pd)
struct riva_par *par = info->par;
NVTRACE_ENTER();
- if (!info)
- return;
#ifdef CONFIG_FB_RIVA_I2C
riva_delete_i2c_busses(par);
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 00719a91479..21debed863a 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -273,8 +273,7 @@ int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)
}
}
- if (out_edid)
- *out_edid = edid;
+ *out_edid = edid;
return (edid) ? 0 : 1;
}
diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
index 2d88f908170..c3e070a6eff 100644
--- a/drivers/video/sis/init301.c
+++ b/drivers/video/sis/init301.c
@@ -8564,11 +8564,9 @@ SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
static void
SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
{
- unsigned short temp,tempcl,tempch;
+ unsigned short temp;
SiS_LongDelay(SiS_Pr, 1);
- tempcl = 3;
- tempch = 0;
do {
temp = SiS_GetCH701x(SiS_Pr,0x66);
@@ -8582,13 +8580,6 @@ SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
SiS_SetCH701xForLCD(SiS_Pr);
- if(tempcl == 0) {
- if(tempch == 3) break;
- SiS_ChrontelResetDB(SiS_Pr);
- tempcl = 3;
- tempch++;
- }
- tempcl--;
temp = SiS_GetCH701x(SiS_Pr,0x76);
temp &= 0xfb; /* Reset PLL */
SiS_SetCH701x(SiS_Pr,0x76,temp);
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 99921df3547..c44de90ca12 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -32,7 +32,7 @@
-TODO: at one time or another test that the mode is acceptable by the monitor
-ASK: Can I choose different ordering for the color bitfields (rgba argb ...)
- wich one should i use ? is there any preferred one ? It seems ARGB is
+ which one should i use ? is there any preferred one ? It seems ARGB is
the one ...
-TODO: in set_var check the validity of timings (hsync vsync)...
-TODO: check and recheck the use of sst_wait_idle : we don't flush the fifo via
@@ -1194,10 +1194,11 @@ static struct dac_switch dacs[] __devinitdata = {
static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *par)
{
int i, ret = 0;
-
- for (i=0; i<sizeof(dacs)/sizeof(dacs[0]); i++) {
+
+ for (i = 0; i < ARRAY_SIZE(dacs); i++) {
ret = dacs[i].detect(info);
- if (ret) break;
+ if (ret)
+ break;
}
if (!ret)
return 0;
@@ -1604,8 +1605,8 @@ static int sstfb_dump_regs(struct fb_info *info)
{FBZMODE,"fbzmode"},
};
- const int pci_s = sizeof(pci_regs)/sizeof(pci_regs[0]);
- const int sst_s = sizeof(sst_regs)/sizeof(sst_regs[0]);
+ const int pci_s = ARRAY_SIZE(pci_regs);
+ const int sst_s = ARRAY_SIZE(sst_regs);
struct sstfb_par *par = info->par;
struct pci_dev *dev = par->dev;
u32 pci_res[pci_s];
diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c
index ed78747487e..5ea2345dab9 100644
--- a/drivers/video/virgefb.c
+++ b/drivers/video/virgefb.c
@@ -616,8 +616,7 @@ static struct {
#endif
};
-#define arraysize(x) (sizeof(x)/sizeof(*(x)))
-#define NUM_TOTAL_MODES arraysize(virgefb_predefined)
+#define NUM_TOTAL_MODES ARRAY_SIZE(virgefb_predefined)
/*
* Default to 800x600 for video=virge8:, virge16: or virge32:
diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c
index 591809cbbb9..2788b8ca9bb 100644
--- a/drivers/w1/masters/matrox_w1.c
+++ b/drivers/w1/masters/matrox_w1.c
@@ -98,7 +98,7 @@ static void matrox_w1_write_ddc_bit(void *, u8);
*
* Using tristate pins, since i can't find any open-drain pin in whole motherboard.
* Unfortunately we can't connect to Intel's 82801xx IO controller
- * since we don't know motherboard schema, wich has pretty unused(may be not) GPIO.
+ * since we don't know motherboard schema, which has pretty unused(may be not) GPIO.
*
* I've heard that PIIX also has open drain pin.
*
diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c
index fcbee748c59..067c07be928 100644
--- a/drivers/zorro/zorro-driver.c
+++ b/drivers/zorro/zorro-driver.c
@@ -65,22 +65,17 @@ static int zorro_device_probe(struct device *dev)
* @drv: the driver structure to register
*
* Adds the driver structure to the list of registered drivers
- * Returns the number of Zorro devices which were claimed by the driver
- * during registration. The driver remains registered even if the
- * return value is zero.
+ * Returns zero or a negative error value.
*/
int zorro_register_driver(struct zorro_driver *drv)
{
- int count = 0;
-
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &zorro_bus_type;
/* register with core */
- count = driver_register(&drv->driver);
- return count ? count : 1;
+ return driver_register(&drv->driver);
}
diff --git a/fs/9p/9p.h b/fs/9p/9p.h
index 95d72aec1c1..94e2f92ab2e 100644
--- a/fs/9p/9p.h
+++ b/fs/9p/9p.h
@@ -8,9 +8,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -235,6 +234,7 @@ struct Tcreate {
struct v9fs_str name;
u32 perm;
u8 mode;
+ struct v9fs_str extension;
};
struct Rcreate {
@@ -364,7 +364,7 @@ int v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
struct v9fs_fcall **rcall);
int v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
- u32 perm, u8 mode, struct v9fs_fcall **rcall);
+ u32 perm, u8 mode, char *extension, struct v9fs_fcall **rcall);
int v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid,
u64 offset, u32 count, struct v9fs_fcall **rcall);
@@ -372,3 +372,4 @@ int v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid,
int v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
u32 count, const char __user * data,
struct v9fs_fcall **rcall);
+int v9fs_printfcall(char *, int, struct v9fs_fcall *, int);
diff --git a/fs/9p/Makefile b/fs/9p/Makefile
index 2f4ce43f7b6..87897f84dfb 100644
--- a/fs/9p/Makefile
+++ b/fs/9p/Makefile
@@ -1,10 +1,9 @@
-obj-$(CONFIG_9P_FS) := 9p2000.o
+obj-$(CONFIG_9P_FS) := 9p.o
-9p2000-objs := \
+9p-objs := \
trans_fd.o \
- trans_sock.o \
mux.o \
- 9p.o \
+ fcall.o \
conv.o \
vfs_super.o \
vfs_inode.o \
@@ -14,5 +13,6 @@ obj-$(CONFIG_9P_FS) := 9p2000.o
vfs_dentry.o \
error.o \
v9fs.o \
- fid.o
+ fid.o \
+ fcprint.o
diff --git a/fs/9p/conv.c b/fs/9p/conv.c
index bba81714246..a767e05b60b 100644
--- a/fs/9p/conv.c
+++ b/fs/9p/conv.c
@@ -8,9 +8,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -666,7 +665,8 @@ struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode)
return fc;
}
-struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode)
+struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
+ char *extension, int extended)
{
int size;
struct v9fs_fcall *fc;
@@ -674,6 +674,9 @@ struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode)
struct cbuf *bufp = &buffer;
size = 4 + 2 + strlen(name) + 4 + 1; /* fid[4] name[s] perm[4] mode[1] */
+ if (extended && extension!=NULL)
+ size += 2 + strlen(extension); /* extension[s] */
+
fc = v9fs_create_common(bufp, size, TCREATE);
if (IS_ERR(fc))
goto error;
@@ -682,6 +685,8 @@ struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode)
v9fs_put_str(bufp, name, &fc->params.tcreate.name);
v9fs_put_int32(bufp, perm, &fc->params.tcreate.perm);
v9fs_put_int8(bufp, mode, &fc->params.tcreate.mode);
+ if (extended)
+ v9fs_put_str(bufp, extension, &fc->params.tcreate.extension);
if (buf_check_overflow(bufp)) {
kfree(fc);
diff --git a/fs/9p/conv.h b/fs/9p/conv.h
index f5896628dae..dd5b6b1b610 100644
--- a/fs/9p/conv.h
+++ b/fs/9p/conv.h
@@ -8,9 +8,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -39,7 +38,8 @@ struct v9fs_fcall *v9fs_create_tflush(u16 oldtag);
struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname,
char **wnames);
struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode);
-struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode);
+struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
+ char *extension, int extended);
struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count);
struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
const char __user *data);
diff --git a/fs/9p/debug.h b/fs/9p/debug.h
index fe551032788..4228c0bb3c3 100644
--- a/fs/9p/debug.h
+++ b/fs/9p/debug.h
@@ -5,9 +5,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -30,6 +29,7 @@
#define DEBUG_MUX (1<<5)
#define DEBUG_TRANS (1<<6)
#define DEBUG_SLABS (1<<7)
+#define DEBUG_FCALL (1<<8)
#define DEBUG_DUMP_PKT 0
diff --git a/fs/9p/error.c b/fs/9p/error.c
index e4b6f8f38b6..981fe8ecd78 100644
--- a/fs/9p/error.c
+++ b/fs/9p/error.c
@@ -11,9 +11,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/fs/9p/error.h b/fs/9p/error.h
index a9794e85fe5..5f3ca522b31 100644
--- a/fs/9p/error.h
+++ b/fs/9p/error.h
@@ -12,9 +12,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/fs/9p/9p.c b/fs/9p/fcall.c
index c148e6ba07e..71742ba150c 100644
--- a/fs/9p/9p.c
+++ b/fs/9p/fcall.c
@@ -1,5 +1,5 @@
/*
- * linux/fs/9p/9p.c
+ * linux/fs/9p/fcall.c
*
* This file contains functions to perform synchronous 9P calls
*
@@ -8,9 +8,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -152,10 +151,9 @@ v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid)
/**
* v9fs_v9fs_t_flush - flush a pending transaction
* @v9ses: 9P2000 session information
- * @tag: tid to release
+ * @tag: tag to release
*
*/
-
int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag)
{
int ret;
@@ -172,7 +170,7 @@ int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag)
return ret;
}
-#endif /* 0 */
+#endif
/**
* v9fs_t_stat - read a file's meta-data
@@ -334,8 +332,8 @@ v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
*/
int
-v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
- u32 perm, u8 mode, struct v9fs_fcall **rcp)
+v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, u32 perm,
+ u8 mode, char *extension, struct v9fs_fcall **rcp)
{
int ret;
struct v9fs_fcall *tc;
@@ -343,7 +341,9 @@ v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n",
fid, name, perm, mode);
- tc = v9fs_create_tcreate(fid, name, perm, mode);
+ tc = v9fs_create_tcreate(fid, name, perm, mode, extension,
+ v9ses->extended);
+
if (!IS_ERR(tc)) {
ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
kfree(tc);
diff --git a/fs/9p/fcprint.c b/fs/9p/fcprint.c
new file mode 100644
index 00000000000..583e827baeb
--- /dev/null
+++ b/fs/9p/fcprint.c
@@ -0,0 +1,346 @@
+/*
+ * linux/fs/9p/fcprint.c
+ *
+ * Print 9P call.
+ *
+ * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "mux.h"
+
+static int
+v9fs_printqid(char *buf, int buflen, struct v9fs_qid *q)
+{
+ int n;
+ char b[10];
+
+ n = 0;
+ if (q->type & V9FS_QTDIR)
+ b[n++] = 'd';
+ if (q->type & V9FS_QTAPPEND)
+ b[n++] = 'a';
+ if (q->type & V9FS_QTAUTH)
+ b[n++] = 'A';
+ if (q->type & V9FS_QTEXCL)
+ b[n++] = 'l';
+ if (q->type & V9FS_QTTMP)
+ b[n++] = 't';
+ if (q->type & V9FS_QTSYMLINK)
+ b[n++] = 'L';
+ b[n] = '\0';
+
+ return scnprintf(buf, buflen, "(%.16llx %x %s)", (long long int) q->path,
+ q->version, b);
+}
+
+static int
+v9fs_printperm(char *buf, int buflen, int perm)
+{
+ int n;
+ char b[15];
+
+ n = 0;
+ if (perm & V9FS_DMDIR)
+ b[n++] = 'd';
+ if (perm & V9FS_DMAPPEND)
+ b[n++] = 'a';
+ if (perm & V9FS_DMAUTH)
+ b[n++] = 'A';
+ if (perm & V9FS_DMEXCL)
+ b[n++] = 'l';
+ if (perm & V9FS_DMTMP)
+ b[n++] = 't';
+ if (perm & V9FS_DMDEVICE)
+ b[n++] = 'D';
+ if (perm & V9FS_DMSOCKET)
+ b[n++] = 'S';
+ if (perm & V9FS_DMNAMEDPIPE)
+ b[n++] = 'P';
+ if (perm & V9FS_DMSYMLINK)
+ b[n++] = 'L';
+ b[n] = '\0';
+
+ return scnprintf(buf, buflen, "%s%03o", b, perm&077);
+}
+
+static int
+v9fs_printstat(char *buf, int buflen, struct v9fs_stat *st, int extended)
+{
+ int n;
+
+ n = scnprintf(buf, buflen, "'%.*s' '%.*s'", st->name.len,
+ st->name.str, st->uid.len, st->uid.str);
+ if (extended)
+ n += scnprintf(buf+n, buflen-n, "(%d)", st->n_uid);
+
+ n += scnprintf(buf+n, buflen-n, " '%.*s'", st->gid.len, st->gid.str);
+ if (extended)
+ n += scnprintf(buf+n, buflen-n, "(%d)", st->n_gid);
+
+ n += scnprintf(buf+n, buflen-n, " '%.*s'", st->muid.len, st->muid.str);
+ if (extended)
+ n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid);
+
+ n += scnprintf(buf+n, buflen-n, " q ");
+ n += v9fs_printqid(buf+n, buflen-n, &st->qid);
+ n += scnprintf(buf+n, buflen-n, " m ");
+ n += v9fs_printperm(buf+n, buflen-n, st->mode);
+ n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld",
+ st->atime, st->mtime, (long long int) st->length);
+
+ if (extended)
+ n += scnprintf(buf+n, buflen-n, " ext '%.*s'",
+ st->extension.len, st->extension.str);
+
+ return n;
+}
+
+static int
+v9fs_dumpdata(char *buf, int buflen, u8 *data, int datalen)
+{
+ int i, n;
+
+ i = n = 0;
+ while (i < datalen) {
+ n += scnprintf(buf + n, buflen - n, "%02x", data[i]);
+ if (i%4 == 3)
+ n += scnprintf(buf + n, buflen - n, " ");
+ if (i%32 == 31)
+ n += scnprintf(buf + n, buflen - n, "\n");
+
+ i++;
+ }
+ n += scnprintf(buf + n, buflen - n, "\n");
+
+ return n;
+}
+
+static int
+v9fs_printdata(char *buf, int buflen, u8 *data, int datalen)
+{
+ return v9fs_dumpdata(buf, buflen, data, datalen<16?datalen:16);
+}
+
+int
+v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended)
+{
+ int i, ret, type, tag;
+
+ if (!fc)
+ return scnprintf(buf, buflen, "<NULL>");
+
+ type = fc->id;
+ tag = fc->tag;
+
+ ret = 0;
+ switch (type) {
+ case TVERSION:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Tversion tag %u msize %u version '%.*s'", tag,
+ fc->params.tversion.msize, fc->params.tversion.version.len,
+ fc->params.tversion.version.str);
+ break;
+
+ case RVERSION:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Rversion tag %u msize %u version '%.*s'", tag,
+ fc->params.rversion.msize, fc->params.rversion.version.len,
+ fc->params.rversion.version.str);
+ break;
+
+ case TAUTH:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag,
+ fc->params.tauth.afid, fc->params.tauth.uname.len,
+ fc->params.tauth.uname.str, fc->params.tauth.aname.len,
+ fc->params.tauth.aname.str);
+ break;
+
+ case RAUTH:
+ ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag);
+ v9fs_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid);
+ break;
+
+ case TATTACH:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'",
+ tag, fc->params.tattach.fid, fc->params.tattach.afid,
+ fc->params.tattach.uname.len, fc->params.tattach.uname.str,
+ fc->params.tattach.aname.len, fc->params.tattach.aname.str);
+ break;
+
+ case RATTACH:
+ ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ", tag);
+ v9fs_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid);
+ break;
+
+ case RERROR:
+ ret += scnprintf(buf+ret, buflen-ret, "Rerror tag %u ename '%.*s'",
+ tag, fc->params.rerror.error.len,
+ fc->params.rerror.error.str);
+ if (extended)
+ ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n",
+ fc->params.rerror.errno);
+ break;
+
+ case TFLUSH:
+ ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u",
+ tag, fc->params.tflush.oldtag);
+ break;
+
+ case RFLUSH:
+ ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag);
+ break;
+
+ case TWALK:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Twalk tag %u fid %d newfid %d nwname %d", tag,
+ fc->params.twalk.fid, fc->params.twalk.newfid,
+ fc->params.twalk.nwname);
+ for(i = 0; i < fc->params.twalk.nwname; i++)
+ ret += scnprintf(buf+ret, buflen-ret," '%.*s'",
+ fc->params.twalk.wnames[i].len,
+ fc->params.twalk.wnames[i].str);
+ break;
+
+ case RWALK:
+ ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d",
+ tag, fc->params.rwalk.nwqid);
+ for(i = 0; i < fc->params.rwalk.nwqid; i++)
+ ret += v9fs_printqid(buf+ret, buflen-ret,
+ &fc->params.rwalk.wqids[i]);
+ break;
+
+ case TOPEN:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Topen tag %u fid %d mode %d", tag,
+ fc->params.topen.fid, fc->params.topen.mode);
+ break;
+
+ case ROPEN:
+ ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag);
+ ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid);
+ ret += scnprintf(buf+ret, buflen-ret," iounit %d",
+ fc->params.ropen.iounit);
+ break;
+
+ case TCREATE:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Tcreate tag %u fid %d name '%.*s' perm ", tag,
+ fc->params.tcreate.fid, fc->params.tcreate.name.len,
+ fc->params.tcreate.name.str);
+
+ ret += v9fs_printperm(buf+ret, buflen-ret, fc->params.tcreate.perm);
+ ret += scnprintf(buf+ret, buflen-ret, " mode %d",
+ fc->params.tcreate.mode);
+ break;
+
+ case RCREATE:
+ ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag);
+ ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.rcreate.qid);
+ ret += scnprintf(buf+ret, buflen-ret, " iounit %d",
+ fc->params.rcreate.iounit);
+ break;
+
+ case TREAD:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Tread tag %u fid %d offset %lld count %u", tag,
+ fc->params.tread.fid,
+ (long long int) fc->params.tread.offset,
+ fc->params.tread.count);
+ break;
+
+ case RREAD:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Rread tag %u count %u data ", tag,
+ fc->params.rread.count);
+ ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.rread.data,
+ fc->params.rread.count);
+ break;
+
+ case TWRITE:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Twrite tag %u fid %d offset %lld count %u data ",
+ tag, fc->params.twrite.fid,
+ (long long int) fc->params.twrite.offset,
+ fc->params.twrite.count);
+ ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.twrite.data,
+ fc->params.twrite.count);
+ break;
+
+ case RWRITE:
+ ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u",
+ tag, fc->params.rwrite.count);
+ break;
+
+ case TCLUNK:
+ ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d",
+ tag, fc->params.tclunk.fid);
+ break;
+
+ case RCLUNK:
+ ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag);
+ break;
+
+ case TREMOVE:
+ ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d",
+ tag, fc->params.tremove.fid);
+ break;
+
+ case RREMOVE:
+ ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag);
+ break;
+
+ case TSTAT:
+ ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d",
+ tag, fc->params.tstat.fid);
+ break;
+
+ case RSTAT:
+ ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag);
+ ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat,
+ extended);
+ break;
+
+ case TWSTAT:
+ ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ",
+ tag, fc->params.twstat.fid);
+ ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.twstat.stat,
+ extended);
+ break;
+
+ case RWSTAT:
+ ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag);
+ break;
+
+ default:
+ ret += scnprintf(buf+ret, buflen-ret, "unknown type %d", type);
+ break;
+ }
+
+ return ret;
+}
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index c4d13bf904d..b7608af07ce 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -4,9 +4,8 @@
* Copyright (C) 2005, 2006 by Eric Van Hensbergen <ericvh@gmail.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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index 1fc2dd08d75..aa974d6875c 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -4,9 +4,8 @@
* Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
index e2ae60adda9..3e5b124a721 100644
--- a/fs/9p/mux.c
+++ b/fs/9p/mux.c
@@ -7,9 +7,8 @@
* Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.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 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -70,7 +69,7 @@ struct v9fs_mux_data {
int msize;
unsigned char *extended;
struct v9fs_transport *trans;
- struct v9fs_idpool tidpool;
+ struct v9fs_idpool tagpool;
int err;
wait_queue_head_t equeue;
struct list_head req_list;
@@ -280,8 +279,8 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
m->msize = msize;
m->extended = extended;
m->trans = trans;
- idr_init(&m->tidpool.pool);
- init_MUTEX(&m->tidpool.lock);
+ idr_init(&m->tagpool.pool);
+ init_MUTEX(&m->tagpool.lock);
m->err = 0;
init_waitqueue_head(&m->equeue);
INIT_LIST_HEAD(&m->req_list);
@@ -635,6 +634,14 @@ static void v9fs_read_work(void *a)
goto error;
}
+ if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) {
+ char buf[150];
+
+ v9fs_printfcall(buf, sizeof(buf), m->rcall,
+ *m->extended);
+ printk(KERN_NOTICE ">>> %p %s\n", m, buf);
+ }
+
rcall = m->rcall;
rbuf = m->rbuf;
if (m->rpos > n) {
@@ -740,6 +747,13 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
v9fs_set_tag(tc, n);
+ if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) {
+ char buf[150];
+
+ v9fs_printfcall(buf, sizeof(buf), tc, *m->extended);
+ printk(KERN_NOTICE "<<< %p %s\n", m, buf);
+ }
+
req->tag = n;
req->tcall = tc;
req->rcall = NULL;
@@ -965,7 +979,7 @@ static u16 v9fs_mux_get_tag(struct v9fs_mux_data *m)
{
int tag;
- tag = v9fs_get_idpool(&m->tidpool);
+ tag = v9fs_get_idpool(&m->tagpool);
if (tag < 0)
return V9FS_NOTAG;
else
@@ -974,6 +988,6 @@ static u16 v9fs_mux_get_tag(struct v9fs_mux_data *m)
static void v9fs_mux_put_tag(struct v9fs_mux_data *m, u16 tag)
{
- if (tag != V9FS_NOTAG && v9fs_check_idpool(tag, &m->tidpool))
- v9fs_put_idpool(tag, &m->tidpool);
+ if (tag != V9FS_NOTAG && v9fs_check_idpool(tag, &m->tagpool))
+ v9fs_put_idpool(tag, &m->tagpool);
}
diff --git a/fs/9p/mux.h b/fs/9p/mux.h
index 17144fdfa11..e90bfd32ea4 100644
--- a/fs/9p/mux.h
+++ b/fs/9p/mux.h
@@ -7,9 +7,8 @@
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/fs/9p/trans_fd.c b/fs/9p/trans_fd.c
index 5b2ce21b10f..94e0a7fd9fc 100644
--- a/fs/9p/trans_fd.c
+++ b/fs/9p/trans_fd.c
@@ -1,15 +1,16 @@
/*
* linux/fs/9p/trans_fd.c
*
- * File Descriptor Transport Layer
+ * Fd transport layer. Includes deprecated socket layer.
*
- * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
- * Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2006 by Russ Cox <rsc@swtch.com>
+ * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
+ * Copyright (C) 2004-2005 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -25,6 +26,7 @@
*/
#include <linux/config.h>
+#include <linux/in.h>
#include <linux/module.h>
#include <linux/net.h>
#include <linux/ipv6.h>
@@ -40,89 +42,119 @@
#include "v9fs.h"
#include "transport.h"
+#define V9FS_PORT 564
+
struct v9fs_trans_fd {
- struct file *in_file;
- struct file *out_file;
+ struct file *rd;
+ struct file *wr;
};
/**
- * v9fs_fd_recv - receive from a socket
+ * v9fs_fd_read- read from a fd
* @v9ses: session information
* @v: buffer to receive data into
* @len: size of receive buffer
*
*/
-
-static int v9fs_fd_recv(struct v9fs_transport *trans, void *v, int len)
+static int v9fs_fd_read(struct v9fs_transport *trans, void *v, int len)
{
- struct v9fs_trans_fd *ts = trans ? trans->priv : NULL;
+ int ret;
+ struct v9fs_trans_fd *ts;
- if (!trans || trans->status != Connected || !ts)
- return -EIO;
+ if (!trans || trans->status == Disconnected || !(ts = trans->priv))
+ return -EREMOTEIO;
- return kernel_read(ts->in_file, ts->in_file->f_pos, v, len);
+ if (!(ts->rd->f_flags & O_NONBLOCK))
+ dprintk(DEBUG_ERROR, "blocking read ...\n");
+
+ ret = kernel_read(ts->rd, ts->rd->f_pos, v, len);
+ if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
+ trans->status = Disconnected;
+ return ret;
}
/**
- * v9fs_fd_send - send to a socket
+ * v9fs_fd_write - write to a socket
* @v9ses: session information
* @v: buffer to send data from
* @len: size of send buffer
*
*/
-
-static int v9fs_fd_send(struct v9fs_transport *trans, void *v, int len)
+static int v9fs_fd_write(struct v9fs_transport *trans, void *v, int len)
{
- struct v9fs_trans_fd *ts = trans ? trans->priv : NULL;
- mm_segment_t oldfs = get_fs();
- int ret = 0;
+ int ret;
+ mm_segment_t oldfs;
+ struct v9fs_trans_fd *ts;
- if (!trans || trans->status != Connected || !ts)
- return -EIO;
+ if (!trans || trans->status == Disconnected || !(ts = trans->priv))
+ return -EREMOTEIO;
+
+ if (!(ts->wr->f_flags & O_NONBLOCK))
+ dprintk(DEBUG_ERROR, "blocking write ...\n");
oldfs = get_fs();
set_fs(get_ds());
/* The cast to a user pointer is valid due to the set_fs() */
- ret = vfs_write(ts->out_file, (void __user *)v, len, &ts->out_file->f_pos);
+ ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos);
set_fs(oldfs);
+ if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
+ trans->status = Disconnected;
return ret;
}
-/**
- * v9fs_fd_init - initialize file descriptor transport
- * @v9ses: session information
- * @addr: address of server to mount
- * @data: mount options
- *
- */
-
-static int
-v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
+static unsigned int
+v9fs_fd_poll(struct v9fs_transport *trans, struct poll_table_struct *pt)
{
- struct v9fs_trans_fd *ts = NULL;
- struct v9fs_transport *trans = v9ses->transport;
+ int ret, n;
+ struct v9fs_trans_fd *ts;
+ mm_segment_t oldfs;
- if((v9ses->wfdno == ~0) || (v9ses->rfdno == ~0)) {
- printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
- return -ENOPROTOOPT;
- }
+ if (!trans || trans->status != Connected || !(ts = trans->priv))
+ return -EREMOTEIO;
- ts = kmalloc(sizeof(struct v9fs_trans_fd), GFP_KERNEL);
+ if (!ts->rd->f_op || !ts->rd->f_op->poll)
+ return -EIO;
- if (!ts)
- return -ENOMEM;
+ if (!ts->wr->f_op || !ts->wr->f_op->poll)
+ return -EIO;
- ts->in_file = fget( v9ses->rfdno );
- ts->out_file = fget( v9ses->wfdno );
+ oldfs = get_fs();
+ set_fs(get_ds());
- if (!ts->in_file || !ts->out_file) {
- if (ts->in_file)
- fput(ts->in_file);
+ ret = ts->rd->f_op->poll(ts->rd, pt);
+ if (ret < 0)
+ goto end;
- if (ts->out_file)
- fput(ts->out_file);
+ if (ts->rd != ts->wr) {
+ n = ts->wr->f_op->poll(ts->wr, pt);
+ if (n < 0) {
+ ret = n;
+ goto end;
+ }
+ ret = (ret & ~POLLOUT) | (n & ~POLLIN);
+ }
+ end:
+ set_fs(oldfs);
+ return ret;
+}
+
+static int v9fs_fd_open(struct v9fs_session_info *v9ses, int rfd, int wfd)
+{
+ struct v9fs_transport *trans = v9ses->transport;
+ struct v9fs_trans_fd *ts = kmalloc(sizeof(struct v9fs_trans_fd),
+ GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ ts->rd = fget(rfd);
+ ts->wr = fget(wfd);
+ if (!ts->rd || !ts->wr) {
+ if (ts->rd)
+ fput(ts->rd);
+ if (ts->wr)
+ fput(ts->wr);
kfree(ts);
return -EIO;
}
@@ -133,84 +165,145 @@ v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
return 0;
}
-
-/**
- * v9fs_fd_close - shutdown file descriptor
- * @trans: private socket structure
- *
- */
-
-static void v9fs_fd_close(struct v9fs_transport *trans)
+static int v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr,
+ char *data)
{
- struct v9fs_trans_fd *ts;
-
- if (!trans)
- return;
-
- ts = xchg(&trans->priv, NULL);
+ if (v9ses->rfdno == ~0 || v9ses->wfdno == ~0) {
+ printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
+ return -ENOPROTOOPT;
+ }
- if (!ts)
- return;
+ return v9fs_fd_open(v9ses, v9ses->rfdno, v9ses->wfdno);
+}
- trans->status = Disconnected;
- if (ts->in_file)
- fput(ts->in_file);
+static int v9fs_socket_open(struct v9fs_session_info *v9ses,
+ struct socket *csocket)
+{
+ int fd, ret;
+
+ csocket->sk->sk_allocation = GFP_NOIO;
+ if ((fd = sock_map_fd(csocket)) < 0) {
+ eprintk(KERN_ERR, "v9fs_socket_open: failed to map fd\n");
+ ret = fd;
+ release_csocket:
+ sock_release(csocket);
+ return ret;
+ }
- if (ts->out_file)
- fput(ts->out_file);
+ if ((ret = v9fs_fd_open(v9ses, fd, fd)) < 0) {
+ sockfd_put(csocket);
+ eprintk(KERN_ERR, "v9fs_socket_open: failed to open fd\n");
+ goto release_csocket;
+ }
- kfree(ts);
+ ((struct v9fs_trans_fd *)v9ses->transport->priv)->rd->f_flags |=
+ O_NONBLOCK;
+ return 0;
}
-static unsigned int
-v9fs_fd_poll(struct v9fs_transport *trans, struct poll_table_struct *pt)
+static int v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr,
+ char *data)
{
- int ret, n;
- struct v9fs_trans_fd *ts;
- mm_segment_t oldfs;
+ int ret;
+ struct socket *csocket = NULL;
+ struct sockaddr_in sin_server;
+
+ sin_server.sin_family = AF_INET;
+ sin_server.sin_addr.s_addr = in_aton(addr);
+ sin_server.sin_port = htons(v9ses->port);
+ sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
+
+ if (!csocket) {
+ eprintk(KERN_ERR, "v9fs_trans_tcp: problem creating socket\n");
+ return -1;
+ }
- if (!trans)
- return -EIO;
+ ret = csocket->ops->connect(csocket,
+ (struct sockaddr *)&sin_server,
+ sizeof(struct sockaddr_in), 0);
+ if (ret < 0) {
+ eprintk(KERN_ERR,
+ "v9fs_trans_tcp: problem connecting socket to %s\n",
+ addr);
+ return ret;
+ }
- ts = trans->priv;
- if (trans->status != Connected || !ts)
- return -EIO;
+ return v9fs_socket_open(v9ses, csocket);
+}
- oldfs = get_fs();
- set_fs(get_ds());
+static int
+v9fs_unix_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
+{
+ int ret;
+ struct socket *csocket;
+ struct sockaddr_un sun_server;
+
+ if (strlen(addr) > UNIX_PATH_MAX) {
+ eprintk(KERN_ERR, "v9fs_trans_unix: address too long: %s\n",
+ addr);
+ return -ENAMETOOLONG;
+ }
- if (!ts->in_file->f_op || !ts->in_file->f_op->poll) {
- ret = -EIO;
- goto end;
+ sun_server.sun_family = PF_UNIX;
+ strcpy(sun_server.sun_path, addr);
+ sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
+ ret = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
+ sizeof(struct sockaddr_un) - 1, 0);
+ if (ret < 0) {
+ eprintk(KERN_ERR,
+ "v9fs_trans_unix: problem connecting socket: %s: %d\n",
+ addr, ret);
+ return ret;
}
- ret = ts->in_file->f_op->poll(ts->in_file, pt);
+ return v9fs_socket_open(v9ses, csocket);
+}
- if (ts->out_file != ts->in_file) {
- if (!ts->out_file->f_op || !ts->out_file->f_op->poll) {
- ret = -EIO;
- goto end;
- }
+/**
+ * v9fs_sock_close - shutdown socket
+ * @trans: private socket structure
+ *
+ */
+static void v9fs_fd_close(struct v9fs_transport *trans)
+{
+ struct v9fs_trans_fd *ts;
- n = ts->out_file->f_op->poll(ts->out_file, pt);
+ if (!trans)
+ return;
- ret &= ~POLLOUT;
- n &= ~POLLIN;
+ ts = xchg(&trans->priv, NULL);
- ret |= n;
- }
+ if (!ts)
+ return;
-end:
- set_fs(oldfs);
- return ret;
+ trans->status = Disconnected;
+ if (ts->rd)
+ fput(ts->rd);
+ if (ts->wr)
+ fput(ts->wr);
+ kfree(ts);
}
-
struct v9fs_transport v9fs_trans_fd = {
.init = v9fs_fd_init,
- .write = v9fs_fd_send,
- .read = v9fs_fd_recv,
+ .write = v9fs_fd_write,
+ .read = v9fs_fd_read,
.close = v9fs_fd_close,
.poll = v9fs_fd_poll,
};
+struct v9fs_transport v9fs_trans_tcp = {
+ .init = v9fs_tcp_init,
+ .write = v9fs_fd_write,
+ .read = v9fs_fd_read,
+ .close = v9fs_fd_close,
+ .poll = v9fs_fd_poll,
+};
+
+struct v9fs_transport v9fs_trans_unix = {
+ .init = v9fs_unix_init,
+ .write = v9fs_fd_write,
+ .read = v9fs_fd_read,
+ .close = v9fs_fd_close,
+ .poll = v9fs_fd_poll,
+};
diff --git a/fs/9p/trans_sock.c b/fs/9p/trans_sock.c
deleted file mode 100644
index 44e830697ac..00000000000
--- a/fs/9p/trans_sock.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * linux/fs/9p/trans_socket.c
- *
- * Socket Transport Layer
- *
- * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
- * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com>
- * Copyright (C) 1995, 1996 by Olaf Kirch <okir@monad.swb.de>
- *
- * 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:
- * Free Software Foundation
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02111-1301 USA
- *
- */
-
-#include <linux/config.h>
-#include <linux/in.h>
-#include <linux/module.h>
-#include <linux/net.h>
-#include <linux/ipv6.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/un.h>
-#include <asm/uaccess.h>
-#include <linux/inet.h>
-#include <linux/idr.h>
-#include <linux/file.h>
-
-#include "debug.h"
-#include "v9fs.h"
-#include "transport.h"
-
-#define V9FS_PORT 564
-
-struct v9fs_trans_sock {
- struct socket *s;
- struct file *filp;
-};
-
-/**
- * v9fs_sock_recv - receive from a socket
- * @v9ses: session information
- * @v: buffer to receive data into
- * @len: size of receive buffer
- *
- */
-
-static int v9fs_sock_recv(struct v9fs_transport *trans, void *v, int len)
-{
- int ret;
- struct v9fs_trans_sock *ts;
-
- if (!trans || trans->status == Disconnected) {
- dprintk(DEBUG_ERROR, "disconnected ...\n");
- return -EREMOTEIO;
- }
-
- ts = trans->priv;
-
- if (!(ts->filp->f_flags & O_NONBLOCK))
- dprintk(DEBUG_ERROR, "blocking read ...\n");
-
- ret = kernel_read(ts->filp, ts->filp->f_pos, v, len);
- if (ret <= 0) {
- if (ret != -ERESTARTSYS && ret != -EAGAIN)
- trans->status = Disconnected;
- }
-
- return ret;
-}
-
-/**
- * v9fs_sock_send - send to a socket
- * @v9ses: session information
- * @v: buffer to send data from
- * @len: size of send buffer
- *
- */
-
-static int v9fs_sock_send(struct v9fs_transport *trans, void *v, int len)
-{
- int ret;
- mm_segment_t oldfs;
- struct v9fs_trans_sock *ts;
-
- if (!trans || trans->status == Disconnected) {
- dprintk(DEBUG_ERROR, "disconnected ...\n");
- return -EREMOTEIO;
- }
-
- ts = trans->priv;
- if (!ts) {
- dprintk(DEBUG_ERROR, "no transport ...\n");
- return -EREMOTEIO;
- }
-
- if (!(ts->filp->f_flags & O_NONBLOCK))
- dprintk(DEBUG_ERROR, "blocking write ...\n");
-
- oldfs = get_fs();
- set_fs(get_ds());
- ret = vfs_write(ts->filp, (void __user *)v, len, &ts->filp->f_pos);
- set_fs(oldfs);
-
- if (ret < 0) {
- if (ret != -ERESTARTSYS)
- trans->status = Disconnected;
- }
-
- return ret;
-}
-
-static unsigned int v9fs_sock_poll(struct v9fs_transport *trans,
- struct poll_table_struct *pt) {
-
- int ret;
- struct v9fs_trans_sock *ts;
- mm_segment_t oldfs;
-
- if (!trans) {
- dprintk(DEBUG_ERROR, "no transport\n");
- return -EIO;
- }
-
- ts = trans->priv;
- if (trans->status != Connected || !ts) {
- dprintk(DEBUG_ERROR, "transport disconnected: %d\n", trans->status);
- return -EIO;
- }
-
- oldfs = get_fs();
- set_fs(get_ds());
-
- if (!ts->filp->f_op || !ts->filp->f_op->poll) {
- dprintk(DEBUG_ERROR, "no poll operation\n");
- ret = -EIO;
- goto end;
- }
-
- ret = ts->filp->f_op->poll(ts->filp, pt);
-
-end:
- set_fs(oldfs);
- return ret;
-}
-
-
-/**
- * v9fs_tcp_init - initialize TCP socket
- * @v9ses: session information
- * @addr: address of server to mount
- * @data: mount options
- *
- */
-
-static int
-v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
-{
- struct socket *csocket = NULL;
- struct sockaddr_in sin_server;
- int rc = 0;
- struct v9fs_trans_sock *ts = NULL;
- struct v9fs_transport *trans = v9ses->transport;
- int fd;
-
- trans->status = Disconnected;
-
- ts = kmalloc(sizeof(struct v9fs_trans_sock), GFP_KERNEL);
-
- if (!ts)
- return -ENOMEM;
-
- trans->priv = ts;
- ts->s = NULL;
- ts->filp = NULL;
-
- if (!addr)
- return -EINVAL;
-
- dprintk(DEBUG_TRANS, "Connecting to %s\n", addr);
-
- sin_server.sin_family = AF_INET;
- sin_server.sin_addr.s_addr = in_aton(addr);
- sin_server.sin_port = htons(v9ses->port);
- sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
- rc = csocket->ops->connect(csocket,
- (struct sockaddr *)&sin_server,
- sizeof(struct sockaddr_in), 0);
- if (rc < 0) {
- eprintk(KERN_ERR,
- "v9fs_trans_tcp: problem connecting socket to %s\n",
- addr);
- return rc;
- }
- csocket->sk->sk_allocation = GFP_NOIO;
-
- fd = sock_map_fd(csocket);
- if (fd < 0) {
- sock_release(csocket);
- kfree(ts);
- trans->priv = NULL;
- return fd;
- }
-
- ts->s = csocket;
- ts->filp = fget(fd);
- ts->filp->f_flags |= O_NONBLOCK;
- trans->status = Connected;
-
- return 0;
-}
-
-/**
- * v9fs_unix_init - initialize UNIX domain socket
- * @v9ses: session information
- * @dev_name: path to named pipe
- * @data: mount options
- *
- */
-
-static int
-v9fs_unix_init(struct v9fs_session_info *v9ses, const char *dev_name,
- char *data)
-{
- int rc, fd;
- struct socket *csocket;
- struct sockaddr_un sun_server;
- struct v9fs_transport *trans;
- struct v9fs_trans_sock *ts;
-
- rc = 0;
- csocket = NULL;
- trans = v9ses->transport;
-
- trans->status = Disconnected;
-
- if (strlen(dev_name) > UNIX_PATH_MAX) {
- eprintk(KERN_ERR, "v9fs_trans_unix: address too long: %s\n",
- dev_name);
- return -ENOMEM;
- }
-
- ts = kmalloc(sizeof(struct v9fs_trans_sock), GFP_KERNEL);
- if (!ts)
- return -ENOMEM;
-
- trans->priv = ts;
- ts->s = NULL;
- ts->filp = NULL;
-
- sun_server.sun_family = PF_UNIX;
- strcpy(sun_server.sun_path, dev_name);
- sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
- rc = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
- sizeof(struct sockaddr_un) - 1, 0); /* -1 *is* important */
- if (rc < 0) {
- eprintk(KERN_ERR,
- "v9fs_trans_unix: problem connecting socket: %s: %d\n",
- dev_name, rc);
- return rc;
- }
- csocket->sk->sk_allocation = GFP_NOIO;
-
- fd = sock_map_fd(csocket);
- if (fd < 0) {
- sock_release(csocket);
- kfree(ts);
- trans->priv = NULL;
- return fd;
- }
-
- ts->s = csocket;
- ts->filp = fget(fd);
- ts->filp->f_flags |= O_NONBLOCK;
- trans->status = Connected;
-
- return 0;
-}
-
-/**
- * v9fs_sock_close - shutdown socket
- * @trans: private socket structure
- *
- */
-
-static void v9fs_sock_close(struct v9fs_transport *trans)
-{
- struct v9fs_trans_sock *ts;
-
- if (!trans)
- return;
-
- ts = trans->priv;
-
- if ((ts) && (ts->filp)) {
- fput(ts->filp);
- ts->filp = NULL;
- ts->s = NULL;
- trans->status = Disconnected;
- }
-
- kfree(ts);
-
- trans->priv = NULL;
-}
-
-struct v9fs_transport v9fs_trans_tcp = {
- .init = v9fs_tcp_init,
- .write = v9fs_sock_send,
- .read = v9fs_sock_recv,
- .close = v9fs_sock_close,
- .poll = v9fs_sock_poll,
-};
-
-struct v9fs_transport v9fs_trans_unix = {
- .init = v9fs_unix_init,
- .write = v9fs_sock_send,
- .read = v9fs_sock_recv,
- .close = v9fs_sock_close,
- .poll = v9fs_sock_poll,
-};
diff --git a/fs/9p/transport.h b/fs/9p/transport.h
index 91fcdb94b36..b38a4b8a41c 100644
--- a/fs/9p/transport.h
+++ b/fs/9p/transport.h
@@ -7,9 +7,8 @@
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 61352491ba3..d37416eb579 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -7,9 +7,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -51,7 +50,7 @@ enum {
Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, Opt_debug,
Opt_rfdno, Opt_wfdno,
/* String options */
- Opt_name, Opt_remotename,
+ Opt_uname, Opt_remotename,
/* Options that take no arguments */
Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd,
/* Error token */
@@ -67,7 +66,7 @@ static match_table_t tokens = {
{Opt_rfdno, "rfdno=%u"},
{Opt_wfdno, "wfdno=%u"},
{Opt_debug, "debug=%x"},
- {Opt_name, "name=%s"},
+ {Opt_uname, "uname=%s"},
{Opt_remotename, "aname=%s"},
{Opt_unix, "proto=unix"},
{Opt_tcp, "proto=tcp"},
@@ -116,7 +115,7 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
if (!*p)
continue;
token = match_token(p, tokens, args);
- if (token < Opt_name) {
+ if (token < Opt_uname) {
if ((ret = match_int(&args[0], &option)) < 0) {
dprintk(DEBUG_ERROR,
"integer field, but no integer?\n");
@@ -158,7 +157,7 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
case Opt_fd:
v9ses->proto = PROTO_FD;
break;
- case Opt_name:
+ case Opt_uname:
match_strcpy(v9ses->name, &args[0]);
break;
case Opt_remotename:
@@ -289,7 +288,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
/* set global debug level */
v9fs_debug_level = v9ses->debug;
- /* id pools that are session-dependent: FIDs and TIDs */
+ /* id pools that are session-dependent: fids and tags */
idr_init(&v9ses->fidpool.pool);
init_MUTEX(&v9ses->fidpool.lock);
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index f337da7a0ee..c134d104cb2 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -5,9 +5,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -91,6 +90,3 @@ void v9fs_session_cancel(struct v9fs_session_info *v9ses);
#define V9FS_DEFUSER "nobody"
#define V9FS_DEFANAME ""
-/* inital pool sizes for fids and tags */
-#define V9FS_START_FIDS 8192
-#define V9FS_START_TIDS 256
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index a759278acaa..f867b8d3e97 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -5,9 +5,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -40,8 +39,8 @@
extern struct file_system_type v9fs_fs_type;
extern struct address_space_operations v9fs_addr_operations;
-extern struct file_operations v9fs_file_operations;
-extern struct file_operations v9fs_dir_operations;
+extern const struct file_operations v9fs_file_operations;
+extern const struct file_operations v9fs_dir_operations;
extern struct dentry_operations v9fs_dentry_operations;
struct inode *v9fs_get_inode(struct super_block *sb, int mode);
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 8100fb5171b..efda46fb64d 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -7,9 +7,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index 12c9cc926b7..062daa6000a 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -7,9 +7,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -51,7 +50,7 @@
*
*/
-int v9fs_dentry_delete(struct dentry *dentry)
+static int v9fs_dentry_delete(struct dentry *dentry)
{
dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
return 1;
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index cd5eeb032d6..e32d5971039 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -7,9 +7,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -205,7 +204,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
return 0;
}
-struct file_operations v9fs_dir_operations = {
+const struct file_operations v9fs_dir_operations = {
.read = generic_read_dir,
.readdir = v9fs_dir_readdir,
.open = v9fs_file_open,
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index de3a129698d..083dcfcd158 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -7,9 +7,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -69,29 +68,30 @@ int v9fs_file_open(struct inode *inode, struct file *file)
fid = v9fs_get_idpool(&v9ses->fidpool);
if (fid < 0) {
- eprintk(KERN_WARNING, "newfid fails!\n");
- return -ENOSPC;
- }
+ eprintk(KERN_WARNING, "newfid fails!\n");
+ return -ENOSPC;
+ }
err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, NULL);
if (err < 0) {
- dprintk(DEBUG_ERROR, "rewalk didn't work\n");
+ dprintk(DEBUG_ERROR, "rewalk didn't work\n");
goto put_fid;
}
- vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
- if (vfid == NULL) {
- dprintk(DEBUG_ERROR, "out of memory\n");
- goto clunk_fid;
- }
-
- /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
- /* translate open mode appropriately */
+ /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
+ /* translate open mode appropriately */
omode = v9fs_uflags2omode(file->f_flags);
err = v9fs_t_open(v9ses, fid, omode, &fcall);
if (err < 0) {
PRINT_FCALL_ERROR("open failed", fcall);
- goto destroy_vfid;
+ goto clunk_fid;
+ }
+
+ vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
+ if (vfid == NULL) {
+ dprintk(DEBUG_ERROR, "out of memory\n");
+ err = -ENOMEM;
+ goto clunk_fid;
}
file->private_data = vfid;
@@ -106,15 +106,12 @@ int v9fs_file_open(struct inode *inode, struct file *file)
return 0;
-destroy_vfid:
- v9fs_fid_destroy(vfid);
-
clunk_fid:
v9fs_t_clunk(v9ses, fid);
put_fid:
v9fs_put_idpool(fid, &v9ses->fidpool);
- kfree(fcall);
+ kfree(fcall);
return err;
}
@@ -269,7 +266,7 @@ v9fs_file_write(struct file *filp, const char __user * data,
return total;
}
-struct file_operations v9fs_file_operations = {
+const struct file_operations v9fs_file_operations = {
.llseek = generic_file_llseek,
.read = v9fs_file_read,
.write = v9fs_file_write,
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 651a9e14d9a..133db366d30 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -7,9 +7,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -255,8 +254,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
}
static int
-v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name,
- u32 perm, u8 mode, u32 *fidp, struct v9fs_qid *qid, u32 *iounit)
+v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm,
+ u8 mode, char *extension, u32 *fidp, struct v9fs_qid *qid, u32 *iounit)
{
u32 fid;
int err;
@@ -271,14 +270,14 @@ v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name,
err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall);
if (err < 0) {
PRINT_FCALL_ERROR("clone error", fcall);
- goto error;
+ goto put_fid;
}
kfree(fcall);
- err = v9fs_t_create(v9ses, fid, name, perm, mode, &fcall);
+ err = v9fs_t_create(v9ses, fid, name, perm, mode, extension, &fcall);
if (err < 0) {
PRINT_FCALL_ERROR("create fails", fcall);
- goto error;
+ goto clunk_fid;
}
if (iounit)
@@ -293,7 +292,11 @@ v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name,
kfree(fcall);
return 0;
-error:
+clunk_fid:
+ v9fs_t_clunk(v9ses, fid);
+ fid = V9FS_NOFID;
+
+put_fid:
if (fid >= 0)
v9fs_put_idpool(fid, &v9ses->fidpool);
@@ -348,7 +351,7 @@ error:
return ERR_PTR(err);
}
-struct inode *
+static struct inode *
v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid,
struct super_block *sb)
{
@@ -474,7 +477,7 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
flags = O_RDWR;
err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
- perm, v9fs_uflags2omode(flags), &fid, &qid, &iounit);
+ perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit);
if (err)
goto error;
@@ -550,7 +553,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
- perm, V9FS_OREAD, &fid, NULL, NULL);
+ perm, V9FS_OREAD, NULL, &fid, NULL, NULL);
if (err) {
dprintk(DEBUG_ERROR, "create error %d\n", err);
@@ -1008,11 +1011,13 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
/* copy extension buffer into buffer */
if (fcall->params.rstat.stat.extension.len < buflen)
- buflen = fcall->params.rstat.stat.extension.len;
+ buflen = fcall->params.rstat.stat.extension.len + 1;
- memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
+ memmove(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
buffer[buflen-1] = 0;
+ dprintk(DEBUG_ERROR, "%s -> %.*s (%s)\n", dentry->d_name.name, fcall->params.rstat.stat.extension.len,
+ fcall->params.rstat.stat.extension.str, buffer);
retval = buflen;
FreeFcall:
@@ -1072,7 +1077,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
if (!link)
link = ERR_PTR(-ENOMEM);
else {
- len = v9fs_readlink(dentry, link, strlen(link));
+ len = v9fs_readlink(dentry, link, PATH_MAX);
if (len < 0) {
__putname(link);
@@ -1109,10 +1114,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
struct v9fs_session_info *v9ses;
struct v9fs_fid *dfid, *vfid;
struct inode *inode;
- struct v9fs_fcall *fcall;
- struct v9fs_wstat wstat;
- fcall = NULL;
inode = NULL;
vfid = NULL;
v9ses = v9fs_inode2v9ses(dir);
@@ -1125,7 +1127,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
}
err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
- perm, V9FS_OREAD, &fid, NULL, NULL);
+ perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL);
if (err)
goto error;
@@ -1148,23 +1150,11 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
goto error;
}
- /* issue a Twstat */
- v9fs_blank_wstat(&wstat);
- wstat.muid = v9ses->name;
- wstat.extension = (char *) extension;
- err = v9fs_t_wstat(v9ses, vfid->fid, &wstat, &fcall);
- if (err < 0) {
- PRINT_FCALL_ERROR("wstat error", fcall);
- goto error;
- }
-
- kfree(fcall);
dentry->d_op = &v9fs_dentry_operations;
d_instantiate(dentry, inode);
return 0;
error:
- kfree(fcall);
if (vfid)
v9fs_fid_destroy(vfid);
@@ -1224,7 +1214,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
}
name = __getname();
- sprintf(name, "hardlink(%d)\n", oldfid->fid);
+ sprintf(name, "%d\n", oldfid->fid);
retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name);
__putname(name);
@@ -1253,6 +1243,8 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
return -EINVAL;
name = __getname();
+ if (!name)
+ return -ENOMEM;
/* build extension */
if (S_ISBLK(mode))
sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index d05318fa684..b0a0ae509c0 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -8,9 +8,8 @@
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
* 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.
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -262,7 +261,7 @@ static struct super_operations v9fs_super_ops = {
};
struct file_system_type v9fs_fs_type = {
- .name = "9P",
+ .name = "9p",
.get_sb = v9fs_get_sb,
.kill_sb = v9fs_kill_super,
.owner = THIS_MODULE,
diff --git a/fs/Kconfig b/fs/Kconfig
index c8d0a209120..e207be68d4c 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1555,6 +1555,7 @@ config RPCSEC_GSS_SPKM3
select CRYPTO
select CRYPTO_MD5
select CRYPTO_DES
+ select CRYPTO_CAST5
help
Provides for secure RPC calls by means of a gss-api
mechanism based on the SPKM3 public-key mechanism.
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h
index f6cd01352cc..29217ff36d4 100644
--- a/fs/adfs/adfs.h
+++ b/fs/adfs/adfs.h
@@ -85,7 +85,7 @@ void __adfs_error(struct super_block *sb, const char *function,
/* dir_*.c */
extern struct inode_operations adfs_dir_inode_operations;
-extern struct file_operations adfs_dir_operations;
+extern const struct file_operations adfs_dir_operations;
extern struct dentry_operations adfs_dentry_operations;
extern struct adfs_dir_ops adfs_f_dir_ops;
extern struct adfs_dir_ops adfs_fplus_dir_ops;
@@ -94,7 +94,7 @@ extern int adfs_dir_update(struct super_block *sb, struct object_info *obj);
/* file.c */
extern struct inode_operations adfs_file_inode_operations;
-extern struct file_operations adfs_file_operations;
+extern const struct file_operations adfs_file_operations;
static inline __u32 signed_asl(__u32 val, signed int shift)
{
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index 0b4c3a02807..7b075fc397d 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -196,7 +196,7 @@ out:
return ret;
}
-struct file_operations adfs_dir_operations = {
+const struct file_operations adfs_dir_operations = {
.read = generic_read_dir,
.readdir = adfs_readdir,
.fsync = file_fsync,
diff --git a/fs/adfs/file.c b/fs/adfs/file.c
index 6af10885f9d..1014b9f2117 100644
--- a/fs/adfs/file.c
+++ b/fs/adfs/file.c
@@ -25,7 +25,7 @@
#include "adfs.h"
-struct file_operations adfs_file_operations = {
+const struct file_operations adfs_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.mmap = generic_file_mmap,
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index 0c6799f2137..a43a876742b 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -192,9 +192,9 @@ extern void affs_dir_truncate(struct inode *);
extern struct inode_operations affs_file_inode_operations;
extern struct inode_operations affs_dir_inode_operations;
extern struct inode_operations affs_symlink_inode_operations;
-extern struct file_operations affs_file_operations;
-extern struct file_operations affs_file_operations_ofs;
-extern struct file_operations affs_dir_operations;
+extern const struct file_operations affs_file_operations;
+extern const struct file_operations affs_file_operations_ofs;
+extern const struct file_operations affs_dir_operations;
extern struct address_space_operations affs_symlink_aops;
extern struct address_space_operations affs_aops;
extern struct address_space_operations affs_aops_ofs;
diff --git a/fs/affs/dir.c b/fs/affs/dir.c
index 548efd0ee98..5d9649fa181 100644
--- a/fs/affs/dir.c
+++ b/fs/affs/dir.c
@@ -17,7 +17,7 @@
static int affs_readdir(struct file *, void *, filldir_t);
-struct file_operations affs_dir_operations = {
+const struct file_operations affs_dir_operations = {
.read = generic_read_dir,
.readdir = affs_readdir,
.fsync = file_fsync,
diff --git a/fs/affs/file.c b/fs/affs/file.c
index f72fb776ecd..7076262af39 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -25,7 +25,7 @@ static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext);
static int affs_file_open(struct inode *inode, struct file *filp);
static int affs_file_release(struct inode *inode, struct file *filp);
-struct file_operations affs_file_operations = {
+const struct file_operations affs_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 5c61c24dab2..a6dff6a4f20 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -32,7 +32,7 @@ static int afs_d_delete(struct dentry *dentry);
static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen,
loff_t fpos, ino_t ino, unsigned dtype);
-struct file_operations afs_dir_file_operations = {
+const struct file_operations afs_dir_file_operations = {
.open = afs_dir_open,
.readdir = afs_dir_readdir,
};
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 150b1922792..7bb716887e2 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -28,7 +28,7 @@ static int afs_file_release(struct inode *inode, struct file *file);
#endif
static int afs_file_readpage(struct file *file, struct page *page);
-static int afs_file_invalidatepage(struct page *page, unsigned long offset);
+static void afs_file_invalidatepage(struct page *page, unsigned long offset);
static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
struct inode_operations afs_file_inode_operations = {
@@ -212,7 +212,7 @@ int afs_cache_get_page_cookie(struct page *page,
/*
* invalidate part or all of a page
*/
-static int afs_file_invalidatepage(struct page *page, unsigned long offset)
+static void afs_file_invalidatepage(struct page *page, unsigned long offset)
{
int ret = 1;
@@ -238,11 +238,11 @@ static int afs_file_invalidatepage(struct page *page, unsigned long offset)
if (!PageWriteback(page))
ret = page->mapping->a_ops->releasepage(page,
0);
+ /* possibly should BUG_ON(!ret); - neilb */
}
}
_leave(" = %d", ret);
- return ret;
} /* end afs_file_invalidatepage() */
/*****************************************************************************/
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index ab8f87c6631..72febdf9a35 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -64,7 +64,7 @@ extern struct cachefs_index_def afs_cache_cell_index_def;
* dir.c
*/
extern struct inode_operations afs_dir_inode_operations;
-extern struct file_operations afs_dir_file_operations;
+extern const struct file_operations afs_dir_file_operations;
/*
* file.c
@@ -105,7 +105,7 @@ extern struct cachefs_netfs afs_cache_netfs;
* mntpt.c
*/
extern struct inode_operations afs_mntpt_inode_operations;
-extern struct file_operations afs_mntpt_file_operations;
+extern const struct file_operations afs_mntpt_file_operations;
extern struct afs_timer afs_mntpt_expiry_timer;
extern struct afs_timer_ops afs_mntpt_expiry_timer_ops;
extern unsigned long afs_mntpt_expiry_timeout;
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 31ee06590de..4e6eeb59b83 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -32,7 +32,7 @@ static struct dentry *afs_mntpt_lookup(struct inode *dir,
static int afs_mntpt_open(struct inode *inode, struct file *file);
static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd);
-struct file_operations afs_mntpt_file_operations = {
+const struct file_operations afs_mntpt_file_operations = {
.open = afs_mntpt_open,
};
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 9c81b8f7eef..101d21b6c03 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -37,7 +37,7 @@ static struct seq_operations afs_proc_cells_ops = {
.show = afs_proc_cells_show,
};
-static struct file_operations afs_proc_cells_fops = {
+static const struct file_operations afs_proc_cells_fops = {
.open = afs_proc_cells_open,
.read = seq_read,
.write = afs_proc_cells_write,
@@ -53,7 +53,7 @@ static ssize_t afs_proc_rootcell_write(struct file *file,
const char __user *buf,
size_t size, loff_t *_pos);
-static struct file_operations afs_proc_rootcell_fops = {
+static const struct file_operations afs_proc_rootcell_fops = {
.open = afs_proc_rootcell_open,
.read = afs_proc_rootcell_read,
.write = afs_proc_rootcell_write,
@@ -77,7 +77,7 @@ static struct seq_operations afs_proc_cell_volumes_ops = {
.show = afs_proc_cell_volumes_show,
};
-static struct file_operations afs_proc_cell_volumes_fops = {
+static const struct file_operations afs_proc_cell_volumes_fops = {
.open = afs_proc_cell_volumes_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -101,7 +101,7 @@ static struct seq_operations afs_proc_cell_vlservers_ops = {
.show = afs_proc_cell_vlservers_show,
};
-static struct file_operations afs_proc_cell_vlservers_fops = {
+static const struct file_operations afs_proc_cell_vlservers_fops = {
.open = afs_proc_cell_vlservers_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -124,7 +124,7 @@ static struct seq_operations afs_proc_cell_servers_ops = {
.show = afs_proc_cell_servers_show,
};
-static struct file_operations afs_proc_cell_servers_fops = {
+static const struct file_operations afs_proc_cell_servers_fops = {
.open = afs_proc_cell_servers_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/fs/aio.c b/fs/aio.c
index aec2b1916d1..e41e932ba48 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -122,10 +122,9 @@ static int aio_setup_ring(struct kioctx *ctx)
info->nr = 0;
info->ring_pages = info->internal_pages;
if (nr_pages > AIO_RING_PAGES) {
- info->ring_pages = kmalloc(sizeof(struct page *) * nr_pages, GFP_KERNEL);
+ info->ring_pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
if (!info->ring_pages)
return -ENOMEM;
- memset(info->ring_pages, 0, sizeof(struct page *) * nr_pages);
}
info->mmap_size = nr_pages * PAGE_SIZE;
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index 990c28da5ae..a62327f1bdf 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -146,7 +146,7 @@ struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info
extern struct inode_operations autofs_root_inode_operations;
extern struct inode_operations autofs_symlink_inode_operations;
-extern struct file_operations autofs_root_operations;
+extern const struct file_operations autofs_root_operations;
/* Initializing function */
diff --git a/fs/autofs/dirhash.c b/fs/autofs/dirhash.c
index 5ccfcf26310..3fded389d06 100644
--- a/fs/autofs/dirhash.c
+++ b/fs/autofs/dirhash.c
@@ -92,7 +92,7 @@ struct autofs_dir_ent *autofs_expire(struct super_block *sb,
;
dput(dentry);
- if ( may_umount(mnt) == 0 ) {
+ if ( may_umount(mnt) ) {
mntput(mnt);
DPRINTK(("autofs: signaling expire on %s\n", ent->name));
return ent; /* Expirable! */
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index 870e2cf3301..9cac08d6a87 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -26,7 +26,7 @@ static int autofs_root_rmdir(struct inode *,struct dentry *);
static int autofs_root_mkdir(struct inode *,struct dentry *,int);
static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
-struct file_operations autofs_root_operations = {
+const struct file_operations autofs_root_operations = {
.read = generic_read_dir,
.readdir = autofs_root_readdir,
.ioctl = autofs_root_ioctl,
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index f54c5b21f87..57c4903614e 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -3,6 +3,7 @@
* linux/fs/autofs/autofs_i.h
*
* Copyright 1997-1998 Transmeta Corporation - All Rights Reserved
+ * Copyright 2005-2006 Ian Kent <raven@themaw.net>
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
@@ -41,14 +42,6 @@
#define AUTOFS_SUPER_MAGIC 0x0187
-/*
- * If the daemon returns a negative response (AUTOFS_IOC_FAIL) then the
- * kernel will keep the negative response cached for up to the time given
- * here, although the time can be shorter if the kernel throws the dcache
- * entry away. This probably should be settable from user space.
- */
-#define AUTOFS_NEGATIVE_TIMEOUT (60*HZ) /* 1 minute */
-
/* Unified info structure. This is pointed to by both the dentry and
inode structures. Each file in the filesystem has an instance of this
structure. It holds a reference to the dentry, so dentries are never
@@ -63,6 +56,7 @@ struct autofs_info {
struct autofs_sb_info *sbi;
unsigned long last_used;
+ atomic_t count;
mode_t mode;
size_t size;
@@ -83,23 +77,37 @@ struct autofs_wait_queue {
int hash;
int len;
char *name;
+ u32 dev;
+ u64 ino;
+ uid_t uid;
+ gid_t gid;
+ pid_t pid;
+ pid_t tgid;
/* This is for status reporting upon return */
int status;
- atomic_t notified;
+ atomic_t notify;
atomic_t wait_ctr;
};
#define AUTOFS_SBI_MAGIC 0x6d4a556d
+#define AUTOFS_TYPE_INDIRECT 0x0001
+#define AUTOFS_TYPE_DIRECT 0x0002
+#define AUTOFS_TYPE_OFFSET 0x0004
+
struct autofs_sb_info {
u32 magic;
struct dentry *root;
+ int pipefd;
struct file *pipe;
pid_t oz_pgrp;
int catatonic;
int version;
int sub_version;
+ int min_proto;
+ int max_proto;
unsigned long exp_timeout;
+ unsigned int type;
int reghost_enabled;
int needs_reghost;
struct super_block *sb;
@@ -166,8 +174,10 @@ int autofs4_expire_multi(struct super_block *, struct vfsmount *,
extern struct inode_operations autofs4_symlink_inode_operations;
extern struct inode_operations autofs4_dir_inode_operations;
extern struct inode_operations autofs4_root_inode_operations;
-extern struct file_operations autofs4_dir_operations;
-extern struct file_operations autofs4_root_operations;
+extern struct inode_operations autofs4_indirect_root_inode_operations;
+extern struct inode_operations autofs4_direct_root_inode_operations;
+extern const struct file_operations autofs4_dir_operations;
+extern const struct file_operations autofs4_root_operations;
/* Initializing function */
@@ -176,13 +186,6 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *, struct autofs_sb_info
/* Queue management functions */
-enum autofs_notify
-{
- NFY_NONE,
- NFY_MOUNT,
- NFY_EXPIRE
-};
-
int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify);
int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int);
void autofs4_catatonic_mode(struct autofs_sb_info *);
@@ -200,12 +203,22 @@ static inline int autofs4_follow_mount(struct vfsmount **mnt, struct dentry **de
return res;
}
+static inline u32 autofs4_get_dev(struct autofs_sb_info *sbi)
+{
+ return new_encode_dev(sbi->sb->s_dev);
+}
+
+static inline u64 autofs4_get_ino(struct autofs_sb_info *sbi)
+{
+ return sbi->sb->s_root->d_inode->i_ino;
+}
+
static inline int simple_positive(struct dentry *dentry)
{
return dentry->d_inode && !d_unhashed(dentry);
}
-static inline int simple_empty_nolock(struct dentry *dentry)
+static inline int __simple_empty(struct dentry *dentry)
{
struct dentry *child;
int ret = 0;
@@ -217,3 +230,6 @@ static inline int simple_empty_nolock(struct dentry *dentry)
out:
return ret;
}
+
+void autofs4_dentry_release(struct dentry *);
+
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index dc39589df16..b8ce02607d6 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -4,7 +4,7 @@
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
* Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
- * Copyright 2001-2003 Ian Kent <raven@themaw.net>
+ * Copyright 2001-2006 Ian Kent <raven@themaw.net>
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
@@ -16,7 +16,7 @@
static unsigned long now;
-/* Check if a dentry can be expired return 1 if it can else return 0 */
+/* Check if a dentry can be expired */
static inline int autofs4_can_expire(struct dentry *dentry,
unsigned long timeout, int do_now)
{
@@ -41,14 +41,14 @@ static inline int autofs4_can_expire(struct dentry *dentry,
attempts if expire fails the first time */
ino->last_used = now;
}
-
return 1;
}
-/* Check a mount point for busyness return 1 if not busy, otherwise */
-static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry)
+/* Check a mount point for busyness */
+static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
{
- int status = 0;
+ struct dentry *top = dentry;
+ int status = 1;
DPRINTK("dentry %p %.*s",
dentry, (int)dentry->d_name.len, dentry->d_name.name);
@@ -63,9 +63,14 @@ static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry)
if (is_autofs4_dentry(dentry))
goto done;
- /* The big question */
- if (may_umount_tree(mnt) == 0)
- status = 1;
+ /* Update the expiry counter if fs is busy */
+ if (!may_umount_tree(mnt)) {
+ struct autofs_info *ino = autofs4_dentry_ino(top);
+ ino->last_used = jiffies;
+ goto done;
+ }
+
+ status = 0;
done:
DPRINTK("returning = %d", status);
mntput(mnt);
@@ -73,78 +78,124 @@ done:
return status;
}
+/*
+ * Calculate next entry in top down tree traversal.
+ * From next_mnt in namespace.c - elegant.
+ */
+static struct dentry *next_dentry(struct dentry *p, struct dentry *root)
+{
+ struct list_head *next = p->d_subdirs.next;
+
+ if (next == &p->d_subdirs) {
+ while (1) {
+ if (p == root)
+ return NULL;
+ next = p->d_u.d_child.next;
+ if (next != &p->d_parent->d_subdirs)
+ break;
+ p = p->d_parent;
+ }
+ }
+ return list_entry(next, struct dentry, d_u.d_child);
+}
+
+/*
+ * Check a direct mount point for busyness.
+ * Direct mounts have similar expiry semantics to tree mounts.
+ * The tree is not busy iff no mountpoints are busy and there are no
+ * autofs submounts.
+ */
+static int autofs4_direct_busy(struct vfsmount *mnt,
+ struct dentry *top,
+ unsigned long timeout,
+ int do_now)
+{
+ DPRINTK("top %p %.*s",
+ top, (int) top->d_name.len, top->d_name.name);
+
+ /* If it's busy update the expiry counters */
+ if (!may_umount_tree(mnt)) {
+ struct autofs_info *ino = autofs4_dentry_ino(top);
+ if (ino)
+ ino->last_used = jiffies;
+ return 1;
+ }
+
+ /* Timeout of a direct mount is determined by its top dentry */
+ if (!autofs4_can_expire(top, timeout, do_now))
+ return 1;
+
+ return 0;
+}
+
/* Check a directory tree of mount points for busyness
* The tree is not busy iff no mountpoints are busy
- * Return 1 if the tree is busy or 0 otherwise
*/
-static int autofs4_check_tree(struct vfsmount *mnt,
- struct dentry *top,
- unsigned long timeout,
- int do_now)
+static int autofs4_tree_busy(struct vfsmount *mnt,
+ struct dentry *top,
+ unsigned long timeout,
+ int do_now)
{
- struct dentry *this_parent = top;
- struct list_head *next;
+ struct autofs_info *top_ino = autofs4_dentry_ino(top);
+ struct dentry *p;
- DPRINTK("parent %p %.*s",
+ DPRINTK("top %p %.*s",
top, (int)top->d_name.len, top->d_name.name);
/* Negative dentry - give up */
if (!simple_positive(top))
- return 0;
-
- /* Timeout of a tree mount is determined by its top dentry */
- if (!autofs4_can_expire(top, timeout, do_now))
- return 0;
-
- /* Is someone visiting anywhere in the tree ? */
- if (may_umount_tree(mnt))
- return 0;
+ return 1;
spin_lock(&dcache_lock);
-repeat:
- next = this_parent->d_subdirs.next;
-resume:
- while (next != &this_parent->d_subdirs) {
- struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
-
+ for (p = top; p; p = next_dentry(p, top)) {
/* Negative dentry - give up */
- if (!simple_positive(dentry)) {
- next = next->next;
+ if (!simple_positive(p))
continue;
- }
DPRINTK("dentry %p %.*s",
- dentry, (int)dentry->d_name.len, dentry->d_name.name);
-
- if (!simple_empty_nolock(dentry)) {
- this_parent = dentry;
- goto repeat;
- }
+ p, (int) p->d_name.len, p->d_name.name);
- dentry = dget(dentry);
+ p = dget(p);
spin_unlock(&dcache_lock);
- if (d_mountpoint(dentry)) {
- /* First busy => tree busy */
- if (!autofs4_check_mount(mnt, dentry)) {
- dput(dentry);
- return 0;
+ /*
+ * Is someone visiting anywhere in the subtree ?
+ * If there's no mount we need to check the usage
+ * count for the autofs dentry.
+ * If the fs is busy update the expiry counter.
+ */
+ if (d_mountpoint(p)) {
+ if (autofs4_mount_busy(mnt, p)) {
+ top_ino->last_used = jiffies;
+ dput(p);
+ return 1;
+ }
+ } else {
+ struct autofs_info *ino = autofs4_dentry_ino(p);
+ unsigned int ino_count = atomic_read(&ino->count);
+
+ /* allow for dget above and top is already dgot */
+ if (p == top)
+ ino_count += 2;
+ else
+ ino_count++;
+
+ if (atomic_read(&p->d_count) > ino_count) {
+ top_ino->last_used = jiffies;
+ dput(p);
+ return 1;
}
}
-
- dput(dentry);
+ dput(p);
spin_lock(&dcache_lock);
- next = next->next;
- }
-
- if (this_parent != top) {
- next = this_parent->d_u.d_child.next;
- this_parent = this_parent->d_parent;
- goto resume;
}
spin_unlock(&dcache_lock);
- return 1;
+ /* Timeout of a tree mount is ultimately determined by its top dentry */
+ if (!autofs4_can_expire(top, timeout, do_now))
+ return 1;
+
+ return 0;
}
static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
@@ -152,58 +203,68 @@ static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
unsigned long timeout,
int do_now)
{
- struct dentry *this_parent = parent;
- struct list_head *next;
+ struct dentry *p;
DPRINTK("parent %p %.*s",
parent, (int)parent->d_name.len, parent->d_name.name);
spin_lock(&dcache_lock);
-repeat:
- next = this_parent->d_subdirs.next;
-resume:
- while (next != &this_parent->d_subdirs) {
- struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
-
+ for (p = parent; p; p = next_dentry(p, parent)) {
/* Negative dentry - give up */
- if (!simple_positive(dentry)) {
- next = next->next;
+ if (!simple_positive(p))
continue;
- }
DPRINTK("dentry %p %.*s",
- dentry, (int)dentry->d_name.len, dentry->d_name.name);
-
- if (!list_empty(&dentry->d_subdirs)) {
- this_parent = dentry;
- goto repeat;
- }
+ p, (int) p->d_name.len, p->d_name.name);
- dentry = dget(dentry);
+ p = dget(p);
spin_unlock(&dcache_lock);
- if (d_mountpoint(dentry)) {
- /* Can we expire this guy */
- if (!autofs4_can_expire(dentry, timeout, do_now))
- goto cont;
-
+ if (d_mountpoint(p)) {
/* Can we umount this guy */
- if (autofs4_check_mount(mnt, dentry))
- return dentry;
+ if (autofs4_mount_busy(mnt, p))
+ goto cont;
+ /* Can we expire this guy */
+ if (autofs4_can_expire(p, timeout, do_now))
+ return p;
}
cont:
- dput(dentry);
+ dput(p);
spin_lock(&dcache_lock);
- next = next->next;
}
+ spin_unlock(&dcache_lock);
+ return NULL;
+}
+
+/* Check if we can expire a direct mount (possibly a tree) */
+static struct dentry *autofs4_expire_direct(struct super_block *sb,
+ struct vfsmount *mnt,
+ struct autofs_sb_info *sbi,
+ int how)
+{
+ unsigned long timeout;
+ struct dentry *root = dget(sb->s_root);
+ int do_now = how & AUTOFS_EXP_IMMEDIATE;
+
+ if (!sbi->exp_timeout || !root)
+ return NULL;
+
+ now = jiffies;
+ timeout = sbi->exp_timeout;
+
+ /* Lock the tree as we must expire as a whole */
+ spin_lock(&sbi->fs_lock);
+ if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
+ struct autofs_info *ino = autofs4_dentry_ino(root);
- if (this_parent != parent) {
- next = this_parent->d_u.d_child.next;
- this_parent = this_parent->d_parent;
- goto resume;
+ /* Set this flag early to catch sys_chdir and the like */
+ ino->flags |= AUTOFS_INF_EXPIRING;
+ spin_unlock(&sbi->fs_lock);
+ return root;
}
- spin_unlock(&dcache_lock);
+ spin_unlock(&sbi->fs_lock);
+ dput(root);
return NULL;
}
@@ -214,10 +275,10 @@ cont:
* - it is unused by any user process
* - it has been unused for exp_timeout time
*/
-static struct dentry *autofs4_expire(struct super_block *sb,
- struct vfsmount *mnt,
- struct autofs_sb_info *sbi,
- int how)
+static struct dentry *autofs4_expire_indirect(struct super_block *sb,
+ struct vfsmount *mnt,
+ struct autofs_sb_info *sbi,
+ int how)
{
unsigned long timeout;
struct dentry *root = sb->s_root;
@@ -241,7 +302,7 @@ static struct dentry *autofs4_expire(struct super_block *sb,
struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
/* Negative dentry - give up */
- if ( !simple_positive(dentry) ) {
+ if (!simple_positive(dentry)) {
next = next->next;
continue;
}
@@ -249,31 +310,36 @@ static struct dentry *autofs4_expire(struct super_block *sb,
dentry = dget(dentry);
spin_unlock(&dcache_lock);
- /* Case 1: indirect mount or top level direct mount */
+ /*
+ * Case 1: (i) indirect mount or top level pseudo direct mount
+ * (autofs-4.1).
+ * (ii) indirect mount with offset mount, check the "/"
+ * offset (autofs-5.0+).
+ */
if (d_mountpoint(dentry)) {
DPRINTK("checking mountpoint %p %.*s",
dentry, (int)dentry->d_name.len, dentry->d_name.name);
- /* Can we expire this guy */
- if (!autofs4_can_expire(dentry, timeout, do_now))
+ /* Can we umount this guy */
+ if (autofs4_mount_busy(mnt, dentry))
goto next;
- /* Can we umount this guy */
- if (autofs4_check_mount(mnt, dentry)) {
+ /* Can we expire this guy */
+ if (autofs4_can_expire(dentry, timeout, do_now)) {
expired = dentry;
break;
}
goto next;
}
- if ( simple_empty(dentry) )
+ if (simple_empty(dentry))
goto next;
/* Case 2: tree mount, expire iff entire tree is not busy */
if (!exp_leaves) {
/* Lock the tree as we must expire as a whole */
spin_lock(&sbi->fs_lock);
- if (autofs4_check_tree(mnt, dentry, timeout, do_now)) {
+ if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
struct autofs_info *inf = autofs4_dentry_ino(dentry);
/* Set this flag early to catch sys_chdir and the like */
@@ -283,7 +349,10 @@ static struct dentry *autofs4_expire(struct super_block *sb,
break;
}
spin_unlock(&sbi->fs_lock);
- /* Case 3: direct mount, expire individual leaves */
+ /*
+ * Case 3: pseudo direct mount, expire individual leaves
+ * (autofs-4.1).
+ */
} else {
expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
if (expired) {
@@ -297,7 +366,7 @@ next:
next = next->next;
}
- if ( expired ) {
+ if (expired) {
DPRINTK("returning %p %.*s",
expired, (int)expired->d_name.len, expired->d_name.name);
spin_lock(&dcache_lock);
@@ -325,7 +394,7 @@ int autofs4_expire_run(struct super_block *sb,
pkt.hdr.proto_version = sbi->version;
pkt.hdr.type = autofs_ptype_expire;
- if ((dentry = autofs4_expire(sb, mnt, sbi, 0)) == NULL)
+ if ((dentry = autofs4_expire_indirect(sb, mnt, sbi, 0)) == NULL)
return -EAGAIN;
pkt.len = dentry->d_name.len;
@@ -351,17 +420,22 @@ int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
if (arg && get_user(do_now, arg))
return -EFAULT;
- if ((dentry = autofs4_expire(sb, mnt, sbi, do_now)) != NULL) {
- struct autofs_info *de_info = autofs4_dentry_ino(dentry);
+ if (sbi->type & AUTOFS_TYPE_DIRECT)
+ dentry = autofs4_expire_direct(sb, mnt, sbi, do_now);
+ else
+ dentry = autofs4_expire_indirect(sb, mnt, sbi, do_now);
+
+ if (dentry) {
+ struct autofs_info *ino = autofs4_dentry_ino(dentry);
/* This is synchronous because it makes the daemon a
little easier */
- de_info->flags |= AUTOFS_INF_EXPIRING;
+ ino->flags |= AUTOFS_INF_EXPIRING;
ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
- de_info->flags &= ~AUTOFS_INF_EXPIRING;
+ ino->flags &= ~AUTOFS_INF_EXPIRING;
dput(dentry);
}
-
+
return ret;
}
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 1ad98d48e55..fde78b110dd 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -3,6 +3,7 @@
* linux/fs/autofs/inode.c
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
+ * Copyright 2005-2006 Ian Kent <raven@themaw.net>
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
@@ -13,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/file.h>
+#include <linux/seq_file.h>
#include <linux/pagemap.h>
#include <linux/parser.h>
#include <linux/bitops.h>
@@ -46,6 +48,7 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
ino->size = 0;
ino->last_used = jiffies;
+ atomic_set(&ino->count, 0);
ino->sbi = sbi;
@@ -64,10 +67,19 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
void autofs4_free_ino(struct autofs_info *ino)
{
+ struct autofs_info *p_ino;
+
if (ino->dentry) {
ino->dentry->d_fsdata = NULL;
- if (ino->dentry->d_inode)
+ if (ino->dentry->d_inode) {
+ struct dentry *parent = ino->dentry->d_parent;
+ if (atomic_dec_and_test(&ino->count)) {
+ p_ino = autofs4_dentry_ino(parent);
+ if (p_ino && parent != ino->dentry)
+ atomic_dec(&p_ino->count);
+ }
dput(ino->dentry);
+ }
ino->dentry = NULL;
}
if (ino->free)
@@ -145,20 +157,44 @@ static void autofs4_put_super(struct super_block *sb)
autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */
/* Clean up and release dangling references */
- if (sbi)
- autofs4_force_release(sbi);
+ autofs4_force_release(sbi);
kfree(sbi);
DPRINTK("shutting down");
}
+static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+ struct autofs_sb_info *sbi = autofs4_sbi(mnt->mnt_sb);
+
+ if (!sbi)
+ return 0;
+
+ seq_printf(m, ",fd=%d", sbi->pipefd);
+ seq_printf(m, ",pgrp=%d", sbi->oz_pgrp);
+ seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ);
+ seq_printf(m, ",minproto=%d", sbi->min_proto);
+ seq_printf(m, ",maxproto=%d", sbi->max_proto);
+
+ if (sbi->type & AUTOFS_TYPE_OFFSET)
+ seq_printf(m, ",offset");
+ else if (sbi->type & AUTOFS_TYPE_DIRECT)
+ seq_printf(m, ",direct");
+ else
+ seq_printf(m, ",indirect");
+
+ return 0;
+}
+
static struct super_operations autofs4_sops = {
.put_super = autofs4_put_super,
.statfs = simple_statfs,
+ .show_options = autofs4_show_options,
};
-enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto};
+enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto,
+ Opt_indirect, Opt_direct, Opt_offset};
static match_table_t tokens = {
{Opt_fd, "fd=%u"},
@@ -167,11 +203,15 @@ static match_table_t tokens = {
{Opt_pgrp, "pgrp=%u"},
{Opt_minproto, "minproto=%u"},
{Opt_maxproto, "maxproto=%u"},
+ {Opt_indirect, "indirect"},
+ {Opt_direct, "direct"},
+ {Opt_offset, "offset"},
{Opt_err, NULL}
};
static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
- pid_t *pgrp, int *minproto, int *maxproto)
+ pid_t *pgrp, unsigned int *type,
+ int *minproto, int *maxproto)
{
char *p;
substring_t args[MAX_OPT_ARGS];
@@ -225,6 +265,15 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
return 1;
*maxproto = option;
break;
+ case Opt_indirect:
+ *type = AUTOFS_TYPE_INDIRECT;
+ break;
+ case Opt_direct:
+ *type = AUTOFS_TYPE_DIRECT;
+ break;
+ case Opt_offset:
+ *type = AUTOFS_TYPE_DIRECT | AUTOFS_TYPE_OFFSET;
+ break;
default:
return 1;
}
@@ -243,6 +292,10 @@ static struct autofs_info *autofs4_mkroot(struct autofs_sb_info *sbi)
return ino;
}
+static struct dentry_operations autofs4_sb_dentry_operations = {
+ .d_release = autofs4_dentry_release,
+};
+
int autofs4_fill_super(struct super_block *s, void *data, int silent)
{
struct inode * root_inode;
@@ -251,7 +304,6 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
int pipefd;
struct autofs_sb_info *sbi;
struct autofs_info *ino;
- int minproto, maxproto;
sbi = (struct autofs_sb_info *) kmalloc(sizeof(*sbi), GFP_KERNEL);
if ( !sbi )
@@ -263,12 +315,16 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
s->s_fs_info = sbi;
sbi->magic = AUTOFS_SBI_MAGIC;
sbi->root = NULL;
+ sbi->pipefd = -1;
sbi->catatonic = 0;
sbi->exp_timeout = 0;
sbi->oz_pgrp = process_group(current);
sbi->sb = s;
sbi->version = 0;
sbi->sub_version = 0;
+ sbi->type = 0;
+ sbi->min_proto = 0;
+ sbi->max_proto = 0;
mutex_init(&sbi->wq_mutex);
spin_lock_init(&sbi->fs_lock);
sbi->queues = NULL;
@@ -285,38 +341,46 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
if (!ino)
goto fail_free;
root_inode = autofs4_get_inode(s, ino);
- kfree(ino);
if (!root_inode)
- goto fail_free;
+ goto fail_ino;
- root_inode->i_op = &autofs4_root_inode_operations;
- root_inode->i_fop = &autofs4_root_operations;
root = d_alloc_root(root_inode);
- pipe = NULL;
-
if (!root)
goto fail_iput;
+ pipe = NULL;
+
+ root->d_op = &autofs4_sb_dentry_operations;
+ root->d_fsdata = ino;
/* Can this call block? */
if (parse_options(data, &pipefd,
&root_inode->i_uid, &root_inode->i_gid,
- &sbi->oz_pgrp,
- &minproto, &maxproto)) {
+ &sbi->oz_pgrp, &sbi->type,
+ &sbi->min_proto, &sbi->max_proto)) {
printk("autofs: called with bogus options\n");
goto fail_dput;
}
+ root_inode->i_fop = &autofs4_root_operations;
+ root_inode->i_op = sbi->type & AUTOFS_TYPE_DIRECT ?
+ &autofs4_direct_root_inode_operations :
+ &autofs4_indirect_root_inode_operations;
+
/* Couldn't this be tested earlier? */
- if (maxproto < AUTOFS_MIN_PROTO_VERSION ||
- minproto > AUTOFS_MAX_PROTO_VERSION) {
+ if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION ||
+ sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) {
printk("autofs: kernel does not match daemon version "
"daemon (%d, %d) kernel (%d, %d)\n",
- minproto, maxproto,
+ sbi->min_proto, sbi->max_proto,
AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION);
goto fail_dput;
}
- sbi->version = maxproto > AUTOFS_MAX_PROTO_VERSION ? AUTOFS_MAX_PROTO_VERSION : maxproto;
+ /* Establish highest kernel protocol version */
+ if (sbi->max_proto > AUTOFS_MAX_PROTO_VERSION)
+ sbi->version = AUTOFS_MAX_PROTO_VERSION;
+ else
+ sbi->version = sbi->max_proto;
sbi->sub_version = AUTOFS_PROTO_SUBVERSION;
DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp);
@@ -329,6 +393,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
if ( !pipe->f_op || !pipe->f_op->write )
goto fail_fput;
sbi->pipe = pipe;
+ sbi->pipefd = pipefd;
/*
* Take a reference to the root dentry so we get a chance to
@@ -356,6 +421,8 @@ fail_dput:
fail_iput:
printk("autofs: get root dentry failed\n");
iput(root_inode);
+fail_ino:
+ kfree(ino);
fail_free:
kfree(sbi);
fail_unlock:
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 62d8d4acb8b..84e030c8ddd 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -4,7 +4,7 @@
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
* Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
- * Copyright 2001-2003 Ian Kent <raven@themaw.net>
+ * Copyright 2001-2006 Ian Kent <raven@themaw.net>
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
@@ -30,9 +30,9 @@ static int autofs4_dir_close(struct inode *inode, struct file *file);
static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir);
static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir);
static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
-static int autofs4_dcache_readdir(struct file *, void *, filldir_t);
+static void *autofs4_follow_link(struct dentry *, struct nameidata *);
-struct file_operations autofs4_root_operations = {
+const struct file_operations autofs4_root_operations = {
.open = dcache_dir_open,
.release = dcache_dir_close,
.read = generic_read_dir,
@@ -40,14 +40,14 @@ struct file_operations autofs4_root_operations = {
.ioctl = autofs4_root_ioctl,
};
-struct file_operations autofs4_dir_operations = {
+const struct file_operations autofs4_dir_operations = {
.open = autofs4_dir_open,
.release = autofs4_dir_close,
.read = generic_read_dir,
.readdir = autofs4_dir_readdir,
};
-struct inode_operations autofs4_root_inode_operations = {
+struct inode_operations autofs4_indirect_root_inode_operations = {
.lookup = autofs4_lookup,
.unlink = autofs4_dir_unlink,
.symlink = autofs4_dir_symlink,
@@ -55,6 +55,14 @@ struct inode_operations autofs4_root_inode_operations = {
.rmdir = autofs4_dir_rmdir,
};
+struct inode_operations autofs4_direct_root_inode_operations = {
+ .lookup = autofs4_lookup,
+ .unlink = autofs4_dir_unlink,
+ .mkdir = autofs4_dir_mkdir,
+ .rmdir = autofs4_dir_rmdir,
+ .follow_link = autofs4_follow_link,
+};
+
struct inode_operations autofs4_dir_inode_operations = {
.lookup = autofs4_lookup,
.unlink = autofs4_dir_unlink,
@@ -82,87 +90,7 @@ static int autofs4_root_readdir(struct file *file, void *dirent,
DPRINTK("needs_reghost = %d", sbi->needs_reghost);
- return autofs4_dcache_readdir(file, dirent, filldir);
-}
-
-/* Update usage from here to top of tree, so that scan of
- top-level directories will give a useful result */
-static void autofs4_update_usage(struct vfsmount *mnt, struct dentry *dentry)
-{
- struct dentry *top = dentry->d_sb->s_root;
-
- spin_lock(&dcache_lock);
- for(; dentry != top; dentry = dentry->d_parent) {
- struct autofs_info *ino = autofs4_dentry_ino(dentry);
-
- if (ino) {
- touch_atime(mnt, dentry);
- ino->last_used = jiffies;
- }
- }
- spin_unlock(&dcache_lock);
-}
-
-/*
- * From 2.4 kernel readdir.c
- */
-static int autofs4_dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
-{
- int i;
- struct dentry *dentry = filp->f_dentry;
-
- i = filp->f_pos;
- switch (i) {
- case 0:
- if (filldir(dirent, ".", 1, i, dentry->d_inode->i_ino, DT_DIR) < 0)
- break;
- i++;
- filp->f_pos++;
- /* fallthrough */
- case 1:
- if (filldir(dirent, "..", 2, i, dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
- break;
- i++;
- filp->f_pos++;
- /* fallthrough */
- default: {
- struct list_head *list;
- int j = i-2;
-
- spin_lock(&dcache_lock);
- list = dentry->d_subdirs.next;
-
- for (;;) {
- if (list == &dentry->d_subdirs) {
- spin_unlock(&dcache_lock);
- return 0;
- }
- if (!j)
- break;
- j--;
- list = list->next;
- }
-
- while(1) {
- struct dentry *de = list_entry(list,
- struct dentry, d_u.d_child);
-
- if (!d_unhashed(de) && de->d_inode) {
- spin_unlock(&dcache_lock);
- if (filldir(dirent, de->d_name.name, de->d_name.len, filp->f_pos, de->d_inode->i_ino, DT_UNKNOWN) < 0)
- break;
- spin_lock(&dcache_lock);
- }
- filp->f_pos++;
- list = list->next;
- if (list != &dentry->d_subdirs)
- continue;
- spin_unlock(&dcache_lock);
- break;
- }
- }
- }
- return 0;
+ return dcache_readdir(file, dirent, filldir);
}
static int autofs4_dir_open(struct inode *inode, struct file *file)
@@ -170,8 +98,16 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
struct dentry *dentry = file->f_dentry;
struct vfsmount *mnt = file->f_vfsmnt;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct dentry *cursor;
int status;
+ status = dcache_dir_open(inode, file);
+ if (status)
+ goto out;
+
+ cursor = file->private_data;
+ cursor->d_fsdata = NULL;
+
DPRINTK("file=%p dentry=%p %.*s",
file, dentry, dentry->d_name.len, dentry->d_name.name);
@@ -180,12 +116,15 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
if (autofs4_ispending(dentry)) {
DPRINTK("dentry busy");
- return -EBUSY;
+ dcache_dir_close(inode, file);
+ status = -EBUSY;
+ goto out;
}
+ status = -ENOENT;
if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) {
struct nameidata nd;
- int empty;
+ int empty, ret;
/* In case there are stale directory dentrys from a failed mount */
spin_lock(&dcache_lock);
@@ -195,13 +134,13 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
if (!empty)
d_invalidate(dentry);
- nd.dentry = dentry;
- nd.mnt = mnt;
nd.flags = LOOKUP_DIRECTORY;
- status = (dentry->d_op->d_revalidate)(dentry, &nd);
+ ret = (dentry->d_op->d_revalidate)(dentry, &nd);
- if (!status)
- return -ENOENT;
+ if (!ret) {
+ dcache_dir_close(inode, file);
+ goto out;
+ }
}
if (d_mountpoint(dentry)) {
@@ -212,25 +151,29 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) {
dput(fp_dentry);
mntput(fp_mnt);
- return -ENOENT;
+ dcache_dir_close(inode, file);
+ goto out;
}
fp = dentry_open(fp_dentry, fp_mnt, file->f_flags);
status = PTR_ERR(fp);
if (IS_ERR(fp)) {
- file->private_data = NULL;
- return status;
+ dcache_dir_close(inode, file);
+ goto out;
}
- file->private_data = fp;
+ cursor->d_fsdata = fp;
}
-out:
return 0;
+out:
+ return status;
}
static int autofs4_dir_close(struct inode *inode, struct file *file)
{
struct dentry *dentry = file->f_dentry;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct dentry *cursor = file->private_data;
+ int status = 0;
DPRINTK("file=%p dentry=%p %.*s",
file, dentry, dentry->d_name.len, dentry->d_name.name);
@@ -240,26 +183,28 @@ static int autofs4_dir_close(struct inode *inode, struct file *file)
if (autofs4_ispending(dentry)) {
DPRINTK("dentry busy");
- return -EBUSY;
+ status = -EBUSY;
+ goto out;
}
if (d_mountpoint(dentry)) {
- struct file *fp = file->private_data;
-
- if (!fp)
- return -ENOENT;
-
+ struct file *fp = cursor->d_fsdata;
+ if (!fp) {
+ status = -ENOENT;
+ goto out;
+ }
filp_close(fp, current->files);
- file->private_data = NULL;
}
out:
- return 0;
+ dcache_dir_close(inode, file);
+ return status;
}
static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
{
struct dentry *dentry = file->f_dentry;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct dentry *cursor = file->private_data;
int status;
DPRINTK("file=%p dentry=%p %.*s",
@@ -274,7 +219,7 @@ static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldi
}
if (d_mountpoint(dentry)) {
- struct file *fp = file->private_data;
+ struct file *fp = cursor->d_fsdata;
if (!fp)
return -ENOENT;
@@ -289,27 +234,26 @@ static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldi
return status;
}
out:
- return autofs4_dcache_readdir(file, dirent, filldir);
+ return dcache_readdir(file, dirent, filldir);
}
-static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int flags)
+static int try_to_fill_dentry(struct dentry *dentry, int flags)
{
- struct super_block *sb = mnt->mnt_sb;
- struct autofs_sb_info *sbi = autofs4_sbi(sb);
- struct autofs_info *de_info = autofs4_dentry_ino(dentry);
+ struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct autofs_info *ino = autofs4_dentry_ino(dentry);
int status = 0;
/* Block on any pending expiry here; invalidate the dentry
when expiration is done to trigger mount request with a new
dentry */
- if (de_info && (de_info->flags & AUTOFS_INF_EXPIRING)) {
+ if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) {
DPRINTK("waiting for expire %p name=%.*s",
dentry, dentry->d_name.len, dentry->d_name.name);
status = autofs4_wait(sbi, dentry, NFY_NONE);
-
+
DPRINTK("expire done status=%d", status);
-
+
/*
* If the directory still exists the mount request must
* continue otherwise it can't be followed at the right
@@ -317,34 +261,36 @@ static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int f
*/
status = d_invalidate(dentry);
if (status != -EBUSY)
- return 0;
+ return -ENOENT;
}
DPRINTK("dentry=%p %.*s ino=%p",
dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
- /* Wait for a pending mount, triggering one if there isn't one already */
+ /*
+ * Wait for a pending mount, triggering one if there
+ * isn't one already
+ */
if (dentry->d_inode == NULL) {
DPRINTK("waiting for mount name=%.*s",
dentry->d_name.len, dentry->d_name.name);
status = autofs4_wait(sbi, dentry, NFY_MOUNT);
-
+
DPRINTK("mount done status=%d", status);
if (status && dentry->d_inode)
- return 0; /* Try to get the kernel to invalidate this dentry */
-
+ return status; /* Try to get the kernel to invalidate this dentry */
+
/* Turn this into a real negative dentry? */
if (status == -ENOENT) {
- dentry->d_time = jiffies + AUTOFS_NEGATIVE_TIMEOUT;
spin_lock(&dentry->d_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
- return 1;
+ return status;
} else if (status) {
/* Return a negative dentry, but leave it "pending" */
- return 1;
+ return status;
}
/* Trigger mount for path component or follow link */
} else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) ||
@@ -363,19 +309,87 @@ static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int f
spin_lock(&dentry->d_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
- return 0;
+ return status;
}
}
- /* We don't update the usages for the autofs daemon itself, this
- is necessary for recursive autofs mounts */
- if (!autofs4_oz_mode(sbi))
- autofs4_update_usage(mnt, dentry);
+ /* Initialize expiry counter after successful mount */
+ if (ino)
+ ino->last_used = jiffies;
spin_lock(&dentry->d_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
spin_unlock(&dentry->d_lock);
- return 1;
+ return status;
+}
+
+/* For autofs direct mounts the follow link triggers the mount */
+static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ int oz_mode = autofs4_oz_mode(sbi);
+ unsigned int lookup_type;
+ int status;
+
+ DPRINTK("dentry=%p %.*s oz_mode=%d nd->flags=%d",
+ dentry, dentry->d_name.len, dentry->d_name.name, oz_mode,
+ nd->flags);
+
+ /* If it's our master or we shouldn't trigger a mount we're done */
+ lookup_type = nd->flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY);
+ if (oz_mode || !lookup_type)
+ goto done;
+
+ /*
+ * If a request is pending wait for it.
+ * If it's a mount then it won't be expired till at least
+ * a liitle later and if it's an expire then we might need
+ * to mount it again.
+ */
+ if (autofs4_ispending(dentry)) {
+ DPRINTK("waiting for active request %p name=%.*s",
+ dentry, dentry->d_name.len, dentry->d_name.name);
+
+ status = autofs4_wait(sbi, dentry, NFY_NONE);
+
+ DPRINTK("request done status=%d", status);
+ }
+
+ /*
+ * If the dentry contains directories then it is an
+ * autofs multi-mount with no root mount offset. So
+ * don't try to mount it again.
+ */
+ spin_lock(&dcache_lock);
+ if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
+ spin_unlock(&dcache_lock);
+
+ status = try_to_fill_dentry(dentry, 0);
+ if (status)
+ goto out_error;
+
+ /*
+ * The mount succeeded but if there is no root mount
+ * it must be an autofs multi-mount with no root offset
+ * so we don't need to follow the mount.
+ */
+ if (d_mountpoint(dentry)) {
+ if (!autofs4_follow_mount(&nd->mnt, &nd->dentry)) {
+ status = -ENOENT;
+ goto out_error;
+ }
+ }
+
+ goto done;
+ }
+ spin_unlock(&dcache_lock);
+
+done:
+ return NULL;
+
+out_error:
+ path_release(nd);
+ return ERR_PTR(status);
}
/*
@@ -384,47 +398,43 @@ static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int f
* yet completely filled in, and revalidate has to delay such
* lookups..
*/
-static int autofs4_revalidate(struct dentry * dentry, struct nameidata *nd)
+static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
{
- struct inode * dir = dentry->d_parent->d_inode;
+ struct inode *dir = dentry->d_parent->d_inode;
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
int oz_mode = autofs4_oz_mode(sbi);
int flags = nd ? nd->flags : 0;
- int status = 1;
+ int status = 0;
/* Pending dentry */
if (autofs4_ispending(dentry)) {
if (!oz_mode)
- status = try_to_fill_dentry(nd->mnt, dentry, flags);
- return status;
+ status = try_to_fill_dentry(dentry, flags);
+ return !status;
}
/* Negative dentry.. invalidate if "old" */
if (dentry->d_inode == NULL)
- return (dentry->d_time - jiffies <= AUTOFS_NEGATIVE_TIMEOUT);
+ return 0;
/* Check for a non-mountpoint directory with no contents */
spin_lock(&dcache_lock);
if (S_ISDIR(dentry->d_inode->i_mode) &&
!d_mountpoint(dentry) &&
- list_empty(&dentry->d_subdirs)) {
+ __simple_empty(dentry)) {
DPRINTK("dentry=%p %.*s, emptydir",
dentry, dentry->d_name.len, dentry->d_name.name);
spin_unlock(&dcache_lock);
if (!oz_mode)
- status = try_to_fill_dentry(nd->mnt, dentry, flags);
- return status;
+ status = try_to_fill_dentry(dentry, flags);
+ return !status;
}
spin_unlock(&dcache_lock);
- /* Update the usage list */
- if (!oz_mode)
- autofs4_update_usage(nd->mnt, dentry);
-
return 1;
}
-static void autofs4_dentry_release(struct dentry *de)
+void autofs4_dentry_release(struct dentry *de)
{
struct autofs_info *inf;
@@ -462,12 +472,13 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
DPRINTK("name = %.*s",
dentry->d_name.len, dentry->d_name.name);
+ /* File name too long to exist */
if (dentry->d_name.len > NAME_MAX)
- return ERR_PTR(-ENAMETOOLONG);/* File name too long to exist */
+ return ERR_PTR(-ENAMETOOLONG);
sbi = autofs4_sbi(dir->i_sb);
-
oz_mode = autofs4_oz_mode(sbi);
+
DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
current->pid, process_group(current), sbi->catatonic, oz_mode);
@@ -519,7 +530,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
* doesn't do the right thing for all system calls, but it should
* be OK for the operations we permit from an autofs.
*/
- if ( dentry->d_inode && d_unhashed(dentry) )
+ if (dentry->d_inode && d_unhashed(dentry))
return ERR_PTR(-ENOENT);
return NULL;
@@ -531,6 +542,7 @@ static int autofs4_dir_symlink(struct inode *dir,
{
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
+ struct autofs_info *p_ino;
struct inode *inode;
char *cp;
@@ -564,6 +576,10 @@ static int autofs4_dir_symlink(struct inode *dir,
dentry->d_fsdata = ino;
ino->dentry = dget(dentry);
+ atomic_inc(&ino->count);
+ p_ino = autofs4_dentry_ino(dentry->d_parent);
+ if (p_ino && dentry->d_parent != dentry)
+ atomic_inc(&p_ino->count);
ino->inode = inode;
dir->i_mtime = CURRENT_TIME;
@@ -590,11 +606,17 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
{
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
+ struct autofs_info *p_ino;
/* This allows root to remove symlinks */
if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
return -EACCES;
+ if (atomic_dec_and_test(&ino->count)) {
+ p_ino = autofs4_dentry_ino(dentry->d_parent);
+ if (p_ino && dentry->d_parent != dentry)
+ atomic_dec(&p_ino->count);
+ }
dput(ino->dentry);
dentry->d_inode->i_size = 0;
@@ -611,6 +633,7 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
{
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
+ struct autofs_info *p_ino;
if (!autofs4_oz_mode(sbi))
return -EACCES;
@@ -625,8 +648,12 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
+ if (atomic_dec_and_test(&ino->count)) {
+ p_ino = autofs4_dentry_ino(dentry->d_parent);
+ if (p_ino && dentry->d_parent != dentry)
+ atomic_dec(&p_ino->count);
+ }
dput(ino->dentry);
-
dentry->d_inode->i_size = 0;
dentry->d_inode->i_nlink = 0;
@@ -640,6 +667,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry);
+ struct autofs_info *p_ino;
struct inode *inode;
if ( !autofs4_oz_mode(sbi) )
@@ -662,6 +690,10 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
dentry->d_fsdata = ino;
ino->dentry = dget(dentry);
+ atomic_inc(&ino->count);
+ p_ino = autofs4_dentry_ino(dentry->d_parent);
+ if (p_ino && dentry->d_parent != dentry)
+ atomic_inc(&p_ino->count);
ino->inode = inode;
dir->i_nlink++;
dir->i_mtime = CURRENT_TIME;
@@ -745,7 +777,7 @@ static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p)
{
int status = 0;
- if (may_umount(mnt) == 0)
+ if (may_umount(mnt))
status = 1;
DPRINTK("returning %d", status);
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index be78e9378c0..142ab6aa2aa 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -3,7 +3,7 @@
* linux/fs/autofs/waitq.c
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- * Copyright 2001-2003 Ian Kent <raven@themaw.net>
+ * Copyright 2001-2006 Ian Kent <raven@themaw.net>
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
@@ -33,7 +33,7 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
sbi->catatonic = 1;
wq = sbi->queues;
sbi->queues = NULL; /* Erase all wait queues */
- while ( wq ) {
+ while (wq) {
nwq = wq->next;
wq->status = -ENOENT; /* Magic is gone - report failure */
kfree(wq->name);
@@ -45,7 +45,6 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
fput(sbi->pipe); /* Close the pipe */
sbi->pipe = NULL;
}
-
shrink_dcache_sb(sbi->sb);
}
@@ -98,7 +97,10 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
pkt.hdr.proto_version = sbi->version;
pkt.hdr.type = type;
- if (type == autofs_ptype_missing) {
+ switch (type) {
+ /* Kernel protocol v4 missing and expire packets */
+ case autofs_ptype_missing:
+ {
struct autofs_packet_missing *mp = &pkt.missing;
pktsz = sizeof(*mp);
@@ -107,7 +109,10 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
mp->len = wq->len;
memcpy(mp->name, wq->name, wq->len);
mp->name[wq->len] = '\0';
- } else if (type == autofs_ptype_expire_multi) {
+ break;
+ }
+ case autofs_ptype_expire_multi:
+ {
struct autofs_packet_expire_multi *ep = &pkt.expire_multi;
pktsz = sizeof(*ep);
@@ -116,7 +121,34 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
ep->len = wq->len;
memcpy(ep->name, wq->name, wq->len);
ep->name[wq->len] = '\0';
- } else {
+ break;
+ }
+ /*
+ * Kernel protocol v5 packet for handling indirect and direct
+ * mount missing and expire requests
+ */
+ case autofs_ptype_missing_indirect:
+ case autofs_ptype_expire_indirect:
+ case autofs_ptype_missing_direct:
+ case autofs_ptype_expire_direct:
+ {
+ struct autofs_v5_packet *packet = &pkt.v5_packet;
+
+ pktsz = sizeof(*packet);
+
+ packet->wait_queue_token = wq->wait_queue_token;
+ packet->len = wq->len;
+ memcpy(packet->name, wq->name, wq->len);
+ packet->name[wq->len] = '\0';
+ packet->dev = wq->dev;
+ packet->ino = wq->ino;
+ packet->uid = wq->uid;
+ packet->gid = wq->gid;
+ packet->pid = wq->pid;
+ packet->tgid = wq->tgid;
+ break;
+ }
+ default:
printk("autofs4_notify_daemon: bad type %d!\n", type);
return;
}
@@ -162,21 +194,29 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
{
struct autofs_wait_queue *wq;
char *name;
- int len, status;
+ unsigned int len = 0;
+ unsigned int hash = 0;
+ int status;
/* In catatonic mode, we don't wait for nobody */
- if ( sbi->catatonic )
+ if (sbi->catatonic)
return -ENOENT;
name = kmalloc(NAME_MAX + 1, GFP_KERNEL);
if (!name)
return -ENOMEM;
- len = autofs4_getpath(sbi, dentry, &name);
- if (!len) {
- kfree(name);
- return -ENOENT;
+ /* If this is a direct mount request create a dummy name */
+ if (IS_ROOT(dentry) && (sbi->type & AUTOFS_TYPE_DIRECT))
+ len = sprintf(name, "%p", dentry);
+ else {
+ len = autofs4_getpath(sbi, dentry, &name);
+ if (!len) {
+ kfree(name);
+ return -ENOENT;
+ }
}
+ hash = full_name_hash(name, len);
if (mutex_lock_interruptible(&sbi->wq_mutex)) {
kfree(name);
@@ -190,7 +230,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
break;
}
- if ( !wq ) {
+ if (!wq) {
/* Can't wait for an expire if there's no mount */
if (notify == NFY_NONE && !d_mountpoint(dentry)) {
kfree(name);
@@ -200,7 +240,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
/* Create a new wait queue */
wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
- if ( !wq ) {
+ if (!wq) {
kfree(name);
mutex_unlock(&sbi->wq_mutex);
return -ENOMEM;
@@ -212,12 +252,18 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
wq->next = sbi->queues;
sbi->queues = wq;
init_waitqueue_head(&wq->queue);
- wq->hash = dentry->d_name.hash;
+ wq->hash = hash;
wq->name = name;
wq->len = len;
+ wq->dev = autofs4_get_dev(sbi);
+ wq->ino = autofs4_get_ino(sbi);
+ wq->uid = current->uid;
+ wq->gid = current->gid;
+ wq->pid = current->pid;
+ wq->tgid = current->tgid;
wq->status = -EINTR; /* Status return if interrupted */
atomic_set(&wq->wait_ctr, 2);
- atomic_set(&wq->notified, 1);
+ atomic_set(&wq->notify, 1);
mutex_unlock(&sbi->wq_mutex);
} else {
atomic_inc(&wq->wait_ctr);
@@ -227,9 +273,26 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
}
- if (notify != NFY_NONE && atomic_dec_and_test(&wq->notified)) {
- int type = (notify == NFY_MOUNT ?
- autofs_ptype_missing : autofs_ptype_expire_multi);
+ if (notify != NFY_NONE && atomic_read(&wq->notify)) {
+ int type;
+
+ atomic_dec(&wq->notify);
+
+ if (sbi->version < 5) {
+ if (notify == NFY_MOUNT)
+ type = autofs_ptype_missing;
+ else
+ type = autofs_ptype_expire_multi;
+ } else {
+ if (notify == NFY_MOUNT)
+ type = (sbi->type & AUTOFS_TYPE_DIRECT) ?
+ autofs_ptype_missing_direct :
+ autofs_ptype_missing_indirect;
+ else
+ type = (sbi->type & AUTOFS_TYPE_DIRECT) ?
+ autofs_ptype_expire_direct :
+ autofs_ptype_expire_indirect;
+ }
DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
@@ -240,14 +303,14 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
/* wq->name is NULL if and only if the lock is already released */
- if ( sbi->catatonic ) {
+ if (sbi->catatonic) {
/* We might have slept, so check again for catatonic mode */
wq->status = -ENOENT;
kfree(wq->name);
wq->name = NULL;
}
- if ( wq->name ) {
+ if (wq->name) {
/* Block all but "shutdown" signals while waiting */
sigset_t oldset;
unsigned long irqflags;
@@ -283,12 +346,12 @@ int autofs4_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_tok
struct autofs_wait_queue *wq, **wql;
mutex_lock(&sbi->wq_mutex);
- for ( wql = &sbi->queues ; (wq = *wql) != 0 ; wql = &wq->next ) {
- if ( wq->wait_queue_token == wait_queue_token )
+ for (wql = &sbi->queues ; (wq = *wql) != 0 ; wql = &wq->next) {
+ if (wq->wait_queue_token == wait_queue_token)
break;
}
- if ( !wq ) {
+ if (!wq) {
mutex_unlock(&sbi->wq_mutex);
return -EINVAL;
}
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index e172180a1d8..80599ae3396 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -22,7 +22,7 @@ static int return_EIO(void)
#define EIO_ERROR ((void *) (return_EIO))
-static struct file_operations bad_file_ops =
+static const struct file_operations bad_file_ops =
{
.llseek = EIO_ERROR,
.aio_read = EIO_ERROR,
diff --git a/fs/befs/datastream.c b/fs/befs/datastream.c
index 785f6b2d5d1..b7d6b920f65 100644
--- a/fs/befs/datastream.c
+++ b/fs/befs/datastream.c
@@ -118,7 +118,7 @@ befs_fblock2brun(struct super_block *sb, befs_data_stream * data,
* befs_read_lsmylink - read long symlink from datastream.
* @sb: Filesystem superblock
* @ds: Datastrem to read from
- * @buf: Buffer in wich to place long symlink data
+ * @buf: Buffer in which to place long symlink data
* @len: Length of the long symlink in bytes
*
* Returns the number of bytes read
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 044a5958782..68ebd10f345 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -64,7 +64,7 @@ static const struct super_operations befs_sops = {
/* slab cache for befs_inode_info objects */
static kmem_cache_t *befs_inode_cachep;
-static struct file_operations befs_dir_operations = {
+static const struct file_operations befs_dir_operations = {
.read = generic_read_dir,
.readdir = befs_readdir,
};
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h
index 1fbc53f14ab..9d791004b21 100644
--- a/fs/bfs/bfs.h
+++ b/fs/bfs/bfs.h
@@ -49,11 +49,11 @@ static inline struct bfs_inode_info *BFS_I(struct inode *inode)
/* file.c */
extern struct inode_operations bfs_file_inops;
-extern struct file_operations bfs_file_operations;
+extern const struct file_operations bfs_file_operations;
extern struct address_space_operations bfs_aops;
/* dir.c */
extern struct inode_operations bfs_dir_inops;
-extern struct file_operations bfs_dir_operations;
+extern const struct file_operations bfs_dir_operations;
#endif /* _FS_BFS_BFS_H */
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 5af928fa044..26fad962173 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -70,7 +70,7 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
return 0;
}
-struct file_operations bfs_dir_operations = {
+const struct file_operations bfs_dir_operations = {
.read = generic_read_dir,
.readdir = bfs_readdir,
.fsync = file_fsync,
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index 807723b65da..d83cd74a2e4 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -17,7 +17,7 @@
#define dprintf(x...)
#endif
-struct file_operations bfs_file_operations = {
+const struct file_operations bfs_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index c2eac2a50bd..537893a1601 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -500,17 +500,22 @@ out:
#define INTERPRETER_AOUT 1
#define INTERPRETER_ELF 2
+#ifndef STACK_RND_MASK
+#define STACK_RND_MASK 0x7ff /* with 4K pages 8MB of VA */
+#endif
static unsigned long randomize_stack_top(unsigned long stack_top)
{
unsigned int random_variable = 0;
- if (current->flags & PF_RANDOMIZE)
- random_variable = get_random_int() % (8*1024*1024);
+ if (current->flags & PF_RANDOMIZE) {
+ random_variable = get_random_int() & STACK_RND_MASK;
+ random_variable <<= PAGE_SHIFT;
+ }
#ifdef CONFIG_STACK_GROWSUP
- return PAGE_ALIGN(stack_top + random_variable);
+ return PAGE_ALIGN(stack_top) + random_variable;
#else
- return PAGE_ALIGN(stack_top - random_variable);
+ return PAGE_ALIGN(stack_top) - random_variable;
#endif
}
@@ -1334,7 +1339,7 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
i = p->state ? ffz(~p->state) + 1 : 0;
psinfo->pr_state = i;
- psinfo->pr_sname = (i < 0 || i > 5) ? '.' : "RSDTZW"[i];
+ psinfo->pr_sname = (i > 5) ? '.' : "RSDTZW"[i];
psinfo->pr_zomb = psinfo->pr_sname == 'Z';
psinfo->pr_nice = task_nice(p);
psinfo->pr_flag = p->flags;
@@ -1465,12 +1470,11 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
read_lock(&tasklist_lock);
do_each_thread(g,p)
if (current->mm == p->mm && current != p) {
- tmp = kmalloc(sizeof(*tmp), GFP_ATOMIC);
+ tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
if (!tmp) {
read_unlock(&tasklist_lock);
goto cleanup;
}
- memset(tmp, 0, sizeof(*tmp));
INIT_LIST_HEAD(&tmp->list);
tmp->thread = p;
list_add(&tmp->list, &thread_list);
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 5b3076e8ee9..a2e48c999c2 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -572,8 +572,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
csp -= sizeof(unsigned long);
__put_user(bprm->argc, (unsigned long *) csp);
- if (csp != sp)
- BUG();
+ BUG_ON(csp != sp);
/* fill in the argv[] array */
#ifdef CONFIG_MMU
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 108d56bbd0d..69f44dcdb0b 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -36,6 +36,7 @@
#include <linux/personality.h>
#include <linux/init.h>
#include <linux/flat.h>
+#include <linux/syscalls.h>
#include <asm/byteorder.h>
#include <asm/system.h>
@@ -426,6 +427,8 @@ static int load_flat_file(struct linux_binprm * bprm,
int i, rev, relocs = 0;
loff_t fpos;
unsigned long start_code, end_code;
+ int ret;
+ int exec_fileno;
hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
inode = bprm->file->f_dentry->d_inode;
@@ -450,7 +453,8 @@ static int load_flat_file(struct linux_binprm * bprm,
*/
if (strncmp(hdr->magic, "#!", 2))
printk("BINFMT_FLAT: bad header magic\n");
- return -ENOEXEC;
+ ret = -ENOEXEC;
+ goto err;
}
if (flags & FLAT_FLAG_KTRACE)
@@ -458,14 +462,16 @@ static int load_flat_file(struct linux_binprm * bprm,
if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) {
printk("BINFMT_FLAT: bad flat file version 0x%x (supported 0x%x and 0x%x)\n", rev, FLAT_VERSION, OLD_FLAT_VERSION);
- return -ENOEXEC;
+ ret = -ENOEXEC;
+ goto err;
}
/* Don't allow old format executables to use shared libraries */
if (rev == OLD_FLAT_VERSION && id != 0) {
printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n",
(int) FLAT_VERSION);
- return -ENOEXEC;
+ ret = -ENOEXEC;
+ goto err;
}
/*
@@ -478,7 +484,8 @@ static int load_flat_file(struct linux_binprm * bprm,
#ifndef CONFIG_BINFMT_ZFLAT
if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
printk("Support for ZFLAT executables is not enabled.\n");
- return -ENOEXEC;
+ ret = -ENOEXEC;
+ goto err;
}
#endif
@@ -490,14 +497,27 @@ static int load_flat_file(struct linux_binprm * bprm,
rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
if (rlim >= RLIM_INFINITY)
rlim = ~0;
- if (data_len + bss_len > rlim)
- return -ENOMEM;
+ if (data_len + bss_len > rlim) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* check file descriptor */
+ exec_fileno = get_unused_fd();
+ if (exec_fileno < 0) {
+ ret = -EMFILE;
+ goto err;
+ }
+ get_file(bprm->file);
+ fd_install(exec_fileno, bprm->file);
/* Flush all traces of the currently running executable */
if (id == 0) {
result = flush_old_exec(bprm);
- if (result)
- return result;
+ if (result) {
+ ret = result;
+ goto err_close;
+ }
/* OK, This is the point of no return */
set_personality(PER_LINUX);
@@ -527,7 +547,8 @@ static int load_flat_file(struct linux_binprm * bprm,
if (!textpos)
textpos = (unsigned long) -ENOMEM;
printk("Unable to mmap process text, errno %d\n", (int)-textpos);
- return(textpos);
+ ret = textpos;
+ goto err_close;
}
down_write(&current->mm->mmap_sem);
@@ -542,7 +563,8 @@ static int load_flat_file(struct linux_binprm * bprm,
printk("Unable to allocate RAM for process data, errno %d\n",
(int)-datapos);
do_munmap(current->mm, textpos, text_len);
- return realdatastart;
+ ret = realdatastart;
+ goto err_close;
}
datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
@@ -564,7 +586,8 @@ static int load_flat_file(struct linux_binprm * bprm,
printk("Unable to read data+bss, errno %d\n", (int)-result);
do_munmap(current->mm, textpos, text_len);
do_munmap(current->mm, realdatastart, data_len + extra);
- return result;
+ ret = result;
+ goto err_close;
}
reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
@@ -582,7 +605,8 @@ static int load_flat_file(struct linux_binprm * bprm,
textpos = (unsigned long) -ENOMEM;
printk("Unable to allocate RAM for process text/data, errno %d\n",
(int)-textpos);
- return(textpos);
+ ret = textpos;
+ goto err_close;
}
realdatastart = textpos + ntohl(hdr->data_start);
@@ -627,7 +651,8 @@ static int load_flat_file(struct linux_binprm * bprm,
printk("Unable to read code+data+bss, errno %d\n",(int)-result);
do_munmap(current->mm, textpos, text_len + data_len + extra +
MAX_SHARED_LIBS * sizeof(unsigned long));
- return result;
+ ret = result;
+ goto err_close;
}
}
@@ -690,8 +715,10 @@ static int load_flat_file(struct linux_binprm * bprm,
unsigned long addr;
if (*rp) {
addr = calc_reloc(*rp, libinfo, id, 0);
- if (addr == RELOC_FAILED)
- return -ENOEXEC;
+ if (addr == RELOC_FAILED) {
+ ret = -ENOEXEC;
+ goto err_close;
+ }
*rp = addr;
}
}
@@ -718,8 +745,10 @@ static int load_flat_file(struct linux_binprm * bprm,
relval = ntohl(reloc[i]);
addr = flat_get_relocate_addr(relval);
rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
- if (rp == (unsigned long *)RELOC_FAILED)
- return -ENOEXEC;
+ if (rp == (unsigned long *)RELOC_FAILED) {
+ ret = -ENOEXEC;
+ goto err_close;
+ }
/* Get the pointer's value. */
addr = flat_get_addr_from_rp(rp, relval, flags);
@@ -731,8 +760,10 @@ static int load_flat_file(struct linux_binprm * bprm,
if ((flags & FLAT_FLAG_GOTPIC) == 0)
addr = ntohl(addr);
addr = calc_reloc(addr, libinfo, id, 0);
- if (addr == RELOC_FAILED)
- return -ENOEXEC;
+ if (addr == RELOC_FAILED) {
+ ret = -ENOEXEC;
+ goto err_close;
+ }
/* Write back the relocated pointer. */
flat_put_addr_at_rp(rp, addr, relval);
@@ -752,6 +783,10 @@ static int load_flat_file(struct linux_binprm * bprm,
stack_len);
return 0;
+err_close:
+ sys_close(exec_fileno);
+err:
+ return ret;
}
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 6a7b730c206..d73d75591a3 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -600,7 +600,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
return count;
}
-static struct file_operations bm_entry_operations = {
+static const struct file_operations bm_entry_operations = {
.read = bm_entry_read,
.write = bm_entry_write,
};
@@ -668,7 +668,7 @@ out:
return count;
}
-static struct file_operations bm_register_operations = {
+static const struct file_operations bm_register_operations = {
.write = bm_register_write,
};
@@ -715,7 +715,7 @@ static ssize_t bm_status_write(struct file * file, const char __user * buffer,
return count;
}
-static struct file_operations bm_status_operations = {
+static const struct file_operations bm_status_operations = {
.read = bm_status_read,
.write = bm_status_write,
};
diff --git a/fs/bio.c b/fs/bio.c
index 0a8c59cb68f..eb8fbc53f2c 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -30,7 +30,7 @@
#define BIO_POOL_SIZE 256
-static kmem_cache_t *bio_slab;
+static kmem_cache_t *bio_slab __read_mostly;
#define BIOVEC_NR_POOLS 6
@@ -39,7 +39,7 @@ static kmem_cache_t *bio_slab;
* basically we just need to survive
*/
#define BIO_SPLIT_ENTRIES 8
-mempool_t *bio_split_pool;
+mempool_t *bio_split_pool __read_mostly;
struct biovec_slab {
int nr_vecs;
@@ -636,12 +636,10 @@ static struct bio *__bio_map_user_iov(request_queue_t *q,
return ERR_PTR(-ENOMEM);
ret = -ENOMEM;
- pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
+ pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
if (!pages)
goto out;
- memset(pages, 0, nr_pages * sizeof(struct page *));
-
for (i = 0; i < iov_count; i++) {
unsigned long uaddr = (unsigned long)iov[i].iov_base;
unsigned long len = iov[i].iov_len;
@@ -1127,16 +1125,6 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
return bp;
}
-static void *bio_pair_alloc(gfp_t gfp_flags, void *data)
-{
- return kmalloc(sizeof(struct bio_pair), gfp_flags);
-}
-
-static void bio_pair_free(void *bp, void *data)
-{
- kfree(bp);
-}
-
/*
* create memory pools for biovec's in a bio_set.
@@ -1153,8 +1141,7 @@ static int biovec_create_pools(struct bio_set *bs, int pool_entries, int scale)
if (i >= scale)
pool_entries >>= 1;
- *bvp = mempool_create(pool_entries, mempool_alloc_slab,
- mempool_free_slab, bp->slab);
+ *bvp = mempool_create_slab_pool(pool_entries, bp->slab);
if (!*bvp)
return -ENOMEM;
}
@@ -1186,15 +1173,12 @@ void bioset_free(struct bio_set *bs)
struct bio_set *bioset_create(int bio_pool_size, int bvec_pool_size, int scale)
{
- struct bio_set *bs = kmalloc(sizeof(*bs), GFP_KERNEL);
+ struct bio_set *bs = kzalloc(sizeof(*bs), GFP_KERNEL);
if (!bs)
return NULL;
- memset(bs, 0, sizeof(*bs));
- bs->bio_pool = mempool_create(bio_pool_size, mempool_alloc_slab,
- mempool_free_slab, bio_slab);
-
+ bs->bio_pool = mempool_create_slab_pool(bio_pool_size, bio_slab);
if (!bs->bio_pool)
goto bad;
@@ -1257,8 +1241,8 @@ static int __init init_bio(void)
if (!fs_bio_set)
panic("bio: can't allocate bios\n");
- bio_split_pool = mempool_create(BIO_SPLIT_ENTRIES,
- bio_pair_alloc, bio_pair_free, NULL);
+ bio_split_pool = mempool_create_kmalloc_pool(BIO_SPLIT_ENTRIES,
+ sizeof(struct bio_pair));
if (!bio_split_pool)
panic("bio: can't create split pool\n");
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 573fc8e0b67..af88c43043d 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -131,9 +131,10 @@ blkdev_get_block(struct inode *inode, sector_t iblock,
static int
blkdev_get_blocks(struct inode *inode, sector_t iblock,
- unsigned long max_blocks, struct buffer_head *bh, int create)
+ struct buffer_head *bh, int create)
{
sector_t end_block = max_block(I_BDEV(inode));
+ unsigned long max_blocks = bh->b_size >> inode->i_blkbits;
if ((iblock + max_blocks) > end_block) {
max_blocks = end_block - iblock;
@@ -234,7 +235,7 @@ static int block_fsync(struct file *filp, struct dentry *dentry, int datasync)
*/
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(bdev_lock);
-static kmem_cache_t * bdev_cachep;
+static kmem_cache_t * bdev_cachep __read_mostly;
static struct inode *bdev_alloc_inode(struct super_block *sb)
{
@@ -265,6 +266,9 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
mutex_init(&bdev->bd_mount_mutex);
INIT_LIST_HEAD(&bdev->bd_inodes);
INIT_LIST_HEAD(&bdev->bd_list);
+#ifdef CONFIG_SYSFS
+ INIT_LIST_HEAD(&bdev->bd_holder_list);
+#endif
inode_init_once(&ei->vfs_inode);
}
}
@@ -308,7 +312,7 @@ static struct file_system_type bd_type = {
.kill_sb = kill_anon_super,
};
-static struct vfsmount *bd_mnt;
+static struct vfsmount *bd_mnt __read_mostly;
struct super_block *blockdev_superblock;
void __init bdev_cache_init(void)
@@ -489,6 +493,300 @@ void bd_release(struct block_device *bdev)
EXPORT_SYMBOL(bd_release);
+#ifdef CONFIG_SYSFS
+/*
+ * Functions for bd_claim_by_kobject / bd_release_from_kobject
+ *
+ * If a kobject is passed to bd_claim_by_kobject()
+ * and the kobject has a parent directory,
+ * following symlinks are created:
+ * o from the kobject to the claimed bdev
+ * o from "holders" directory of the bdev to the parent of the kobject
+ * bd_release_from_kobject() removes these symlinks.
+ *
+ * Example:
+ * If /dev/dm-0 maps to /dev/sda, kobject corresponding to
+ * /sys/block/dm-0/slaves is passed to bd_claim_by_kobject(), then:
+ * /sys/block/dm-0/slaves/sda --> /sys/block/sda
+ * /sys/block/sda/holders/dm-0 --> /sys/block/dm-0
+ */
+
+static struct kobject *bdev_get_kobj(struct block_device *bdev)
+{
+ if (bdev->bd_contains != bdev)
+ return kobject_get(&bdev->bd_part->kobj);
+ else
+ return kobject_get(&bdev->bd_disk->kobj);
+}
+
+static struct kobject *bdev_get_holder(struct block_device *bdev)
+{
+ if (bdev->bd_contains != bdev)
+ return kobject_get(bdev->bd_part->holder_dir);
+ else
+ return kobject_get(bdev->bd_disk->holder_dir);
+}
+
+static void add_symlink(struct kobject *from, struct kobject *to)
+{
+ if (!from || !to)
+ return;
+ sysfs_create_link(from, to, kobject_name(to));
+}
+
+static void del_symlink(struct kobject *from, struct kobject *to)
+{
+ if (!from || !to)
+ return;
+ sysfs_remove_link(from, kobject_name(to));
+}
+
+/*
+ * 'struct bd_holder' contains pointers to kobjects symlinked by
+ * bd_claim_by_kobject.
+ * It's connected to bd_holder_list which is protected by bdev->bd_sem.
+ */
+struct bd_holder {
+ struct list_head list; /* chain of holders of the bdev */
+ int count; /* references from the holder */
+ struct kobject *sdir; /* holder object, e.g. "/block/dm-0/slaves" */
+ struct kobject *hdev; /* e.g. "/block/dm-0" */
+ struct kobject *hdir; /* e.g. "/block/sda/holders" */
+ struct kobject *sdev; /* e.g. "/block/sda" */
+};
+
+/*
+ * Get references of related kobjects at once.
+ * Returns 1 on success. 0 on failure.
+ *
+ * Should call bd_holder_release_dirs() after successful use.
+ */
+static int bd_holder_grab_dirs(struct block_device *bdev,
+ struct bd_holder *bo)
+{
+ if (!bdev || !bo)
+ return 0;
+
+ bo->sdir = kobject_get(bo->sdir);
+ if (!bo->sdir)
+ return 0;
+
+ bo->hdev = kobject_get(bo->sdir->parent);
+ if (!bo->hdev)
+ goto fail_put_sdir;
+
+ bo->sdev = bdev_get_kobj(bdev);
+ if (!bo->sdev)
+ goto fail_put_hdev;
+
+ bo->hdir = bdev_get_holder(bdev);
+ if (!bo->hdir)
+ goto fail_put_sdev;
+
+ return 1;
+
+fail_put_sdev:
+ kobject_put(bo->sdev);
+fail_put_hdev:
+ kobject_put(bo->hdev);
+fail_put_sdir:
+ kobject_put(bo->sdir);
+
+ return 0;
+}
+
+/* Put references of related kobjects at once. */
+static void bd_holder_release_dirs(struct bd_holder *bo)
+{
+ kobject_put(bo->hdir);
+ kobject_put(bo->sdev);
+ kobject_put(bo->hdev);
+ kobject_put(bo->sdir);
+}
+
+static struct bd_holder *alloc_bd_holder(struct kobject *kobj)
+{
+ struct bd_holder *bo;
+
+ bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+ if (!bo)
+ return NULL;
+
+ bo->count = 1;
+ bo->sdir = kobj;
+
+ return bo;
+}
+
+static void free_bd_holder(struct bd_holder *bo)
+{
+ kfree(bo);
+}
+
+/**
+ * add_bd_holder - create sysfs symlinks for bd_claim() relationship
+ *
+ * @bdev: block device to be bd_claimed
+ * @bo: preallocated and initialized by alloc_bd_holder()
+ *
+ * If there is no matching entry with @bo in @bdev->bd_holder_list,
+ * add @bo to the list, create symlinks.
+ *
+ * Returns 1 if @bo was added to the list.
+ * Returns 0 if @bo wasn't used by any reason and should be freed.
+ */
+static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
+{
+ struct bd_holder *tmp;
+
+ if (!bo)
+ return 0;
+
+ list_for_each_entry(tmp, &bdev->bd_holder_list, list) {
+ if (tmp->sdir == bo->sdir) {
+ tmp->count++;
+ return 0;
+ }
+ }
+
+ if (!bd_holder_grab_dirs(bdev, bo))
+ return 0;
+
+ add_symlink(bo->sdir, bo->sdev);
+ add_symlink(bo->hdir, bo->hdev);
+ list_add_tail(&bo->list, &bdev->bd_holder_list);
+ return 1;
+}
+
+/**
+ * del_bd_holder - delete sysfs symlinks for bd_claim() relationship
+ *
+ * @bdev: block device to be bd_claimed
+ * @kobj: holder's kobject
+ *
+ * If there is matching entry with @kobj in @bdev->bd_holder_list
+ * and no other bd_claim() from the same kobject,
+ * remove the struct bd_holder from the list, delete symlinks for it.
+ *
+ * Returns a pointer to the struct bd_holder when it's removed from the list
+ * and ready to be freed.
+ * Returns NULL if matching claim isn't found or there is other bd_claim()
+ * by the same kobject.
+ */
+static struct bd_holder *del_bd_holder(struct block_device *bdev,
+ struct kobject *kobj)
+{
+ struct bd_holder *bo;
+
+ list_for_each_entry(bo, &bdev->bd_holder_list, list) {
+ if (bo->sdir == kobj) {
+ bo->count--;
+ BUG_ON(bo->count < 0);
+ if (!bo->count) {
+ list_del(&bo->list);
+ del_symlink(bo->sdir, bo->sdev);
+ del_symlink(bo->hdir, bo->hdev);
+ bd_holder_release_dirs(bo);
+ return bo;
+ }
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * bd_claim_by_kobject - bd_claim() with additional kobject signature
+ *
+ * @bdev: block device to be claimed
+ * @holder: holder's signature
+ * @kobj: holder's kobject
+ *
+ * Do bd_claim() and if it succeeds, create sysfs symlinks between
+ * the bdev and the holder's kobject.
+ * Use bd_release_from_kobject() when relesing the claimed bdev.
+ *
+ * Returns 0 on success. (same as bd_claim())
+ * Returns errno on failure.
+ */
+static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
+ struct kobject *kobj)
+{
+ int res;
+ struct bd_holder *bo;
+
+ if (!kobj)
+ return -EINVAL;
+
+ bo = alloc_bd_holder(kobj);
+ if (!bo)
+ return -ENOMEM;
+
+ mutex_lock(&bdev->bd_mutex);
+ res = bd_claim(bdev, holder);
+ if (res || !add_bd_holder(bdev, bo))
+ free_bd_holder(bo);
+ mutex_unlock(&bdev->bd_mutex);
+
+ return res;
+}
+
+/**
+ * bd_release_from_kobject - bd_release() with additional kobject signature
+ *
+ * @bdev: block device to be released
+ * @kobj: holder's kobject
+ *
+ * Do bd_release() and remove sysfs symlinks created by bd_claim_by_kobject().
+ */
+static void bd_release_from_kobject(struct block_device *bdev,
+ struct kobject *kobj)
+{
+ struct bd_holder *bo;
+
+ if (!kobj)
+ return;
+
+ mutex_lock(&bdev->bd_mutex);
+ bd_release(bdev);
+ if ((bo = del_bd_holder(bdev, kobj)))
+ free_bd_holder(bo);
+ mutex_unlock(&bdev->bd_mutex);
+}
+
+/**
+ * bd_claim_by_disk - wrapper function for bd_claim_by_kobject()
+ *
+ * @bdev: block device to be claimed
+ * @holder: holder's signature
+ * @disk: holder's gendisk
+ *
+ * Call bd_claim_by_kobject() with getting @disk->slave_dir.
+ */
+int bd_claim_by_disk(struct block_device *bdev, void *holder,
+ struct gendisk *disk)
+{
+ return bd_claim_by_kobject(bdev, holder, kobject_get(disk->slave_dir));
+}
+EXPORT_SYMBOL_GPL(bd_claim_by_disk);
+
+/**
+ * bd_release_from_disk - wrapper function for bd_release_from_kobject()
+ *
+ * @bdev: block device to be claimed
+ * @disk: holder's gendisk
+ *
+ * Call bd_release_from_kobject() and put @disk->slave_dir.
+ */
+void bd_release_from_disk(struct block_device *bdev, struct gendisk *disk)
+{
+ bd_release_from_kobject(bdev, disk->slave_dir);
+ kobject_put(disk->slave_dir);
+}
+EXPORT_SYMBOL_GPL(bd_release_from_disk);
+#endif
+
/*
* Tries to open block device by device number. Use it ONLY if you
* really do not have anything better - i.e. when you are behind a
@@ -789,7 +1087,7 @@ struct address_space_operations def_blk_aops = {
.direct_IO = blkdev_direct_IO,
};
-struct file_operations def_blk_fops = {
+const struct file_operations def_blk_fops = {
.open = blkdev_open,
.release = blkdev_close,
.llseek = block_llseek,
diff --git a/fs/buffer.c b/fs/buffer.c
index 6d77ce9f54e..23f1f3a6807 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -160,12 +160,7 @@ int sync_blockdev(struct block_device *bdev)
}
EXPORT_SYMBOL(sync_blockdev);
-/*
- * Write out and wait upon all dirty data associated with this
- * superblock. Filesystem data as well as the underlying block
- * device. Takes the superblock lock.
- */
-int fsync_super(struct super_block *sb)
+static void __fsync_super(struct super_block *sb)
{
sync_inodes_sb(sb, 0);
DQUOT_SYNC(sb);
@@ -177,7 +172,16 @@ int fsync_super(struct super_block *sb)
sb->s_op->sync_fs(sb, 1);
sync_blockdev(sb->s_bdev);
sync_inodes_sb(sb, 1);
+}
+/*
+ * Write out and wait upon all dirty data associated with this
+ * superblock. Filesystem data as well as the underlying block
+ * device. Takes the superblock lock.
+ */
+int fsync_super(struct super_block *sb)
+{
+ __fsync_super(sb);
return sync_blockdev(sb->s_bdev);
}
@@ -216,19 +220,7 @@ struct super_block *freeze_bdev(struct block_device *bdev)
sb->s_frozen = SB_FREEZE_WRITE;
smp_wmb();
- sync_inodes_sb(sb, 0);
- DQUOT_SYNC(sb);
-
- lock_super(sb);
- if (sb->s_dirt && sb->s_op->write_super)
- sb->s_op->write_super(sb);
- unlock_super(sb);
-
- if (sb->s_op->sync_fs)
- sb->s_op->sync_fs(sb, 1);
-
- sync_blockdev(sb->s_bdev);
- sync_inodes_sb(sb, 1);
+ __fsync_super(sb);
sb->s_frozen = SB_FREEZE_TRANS;
smp_wmb();
@@ -434,8 +426,10 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
if (all_mapped) {
printk("__find_get_block_slow() failed. "
"block=%llu, b_blocknr=%llu\n",
- (unsigned long long)block, (unsigned long long)bh->b_blocknr);
- printk("b_state=0x%08lx, b_size=%u\n", bh->b_state, bh->b_size);
+ (unsigned long long)block,
+ (unsigned long long)bh->b_blocknr);
+ printk("b_state=0x%08lx, b_size=%zu\n",
+ bh->b_state, bh->b_size);
printk("device blocksize: %d\n", 1 << bd_inode->i_blkbits);
}
out_unlock:
@@ -499,7 +493,7 @@ static void free_more_memory(void)
wakeup_pdflush(1024);
yield();
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones;
if (*zones)
try_to_free_pages(zones, GFP_NOFS);
@@ -804,8 +798,7 @@ void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode)
if (!mapping->assoc_mapping) {
mapping->assoc_mapping = buffer_mapping;
} else {
- if (mapping->assoc_mapping != buffer_mapping)
- BUG();
+ BUG_ON(mapping->assoc_mapping != buffer_mapping);
}
if (list_empty(&bh->b_assoc_buffers)) {
spin_lock(&buffer_mapping->private_lock);
@@ -1122,8 +1115,7 @@ grow_dev_page(struct block_device *bdev, sector_t block,
if (!page)
return NULL;
- if (!PageLocked(page))
- BUG();
+ BUG_ON(!PageLocked(page));
if (page_has_buffers(page)) {
bh = page_buffers(page);
@@ -1530,8 +1522,7 @@ void set_bh_page(struct buffer_head *bh,
struct page *page, unsigned long offset)
{
bh->b_page = page;
- if (offset >= PAGE_SIZE)
- BUG();
+ BUG_ON(offset >= PAGE_SIZE);
if (PageHighMem(page))
/*
* This catches illegal uses and preserves the offset:
@@ -1601,11 +1592,10 @@ EXPORT_SYMBOL(try_to_release_page);
* point. Because the caller is about to free (and possibly reuse) those
* blocks on-disk.
*/
-int block_invalidatepage(struct page *page, unsigned long offset)
+void block_invalidatepage(struct page *page, unsigned long offset)
{
struct buffer_head *head, *bh, *next;
unsigned int curr_off = 0;
- int ret = 1;
BUG_ON(!PageLocked(page));
if (!page_has_buffers(page))
@@ -1632,19 +1622,18 @@ int block_invalidatepage(struct page *page, unsigned long offset)
* so real IO is not possible anymore.
*/
if (offset == 0)
- ret = try_to_release_page(page, 0);
+ try_to_release_page(page, 0);
out:
- return ret;
+ return;
}
EXPORT_SYMBOL(block_invalidatepage);
-int do_invalidatepage(struct page *page, unsigned long offset)
+void do_invalidatepage(struct page *page, unsigned long offset)
{
- int (*invalidatepage)(struct page *, unsigned long);
- invalidatepage = page->mapping->a_ops->invalidatepage;
- if (invalidatepage == NULL)
- invalidatepage = block_invalidatepage;
- return (*invalidatepage)(page, offset);
+ void (*invalidatepage)(struct page *, unsigned long);
+ invalidatepage = page->mapping->a_ops->invalidatepage ? :
+ block_invalidatepage;
+ (*invalidatepage)(page, offset);
}
/*
@@ -1746,6 +1735,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
sector_t block;
sector_t last_block;
struct buffer_head *bh, *head;
+ const unsigned blocksize = 1 << inode->i_blkbits;
int nr_underway = 0;
BUG_ON(!PageLocked(page));
@@ -1753,7 +1743,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
last_block = (i_size_read(inode) - 1) >> inode->i_blkbits;
if (!page_has_buffers(page)) {
- create_empty_buffers(page, 1 << inode->i_blkbits,
+ create_empty_buffers(page, blocksize,
(1 << BH_Dirty)|(1 << BH_Uptodate));
}
@@ -1788,6 +1778,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
clear_buffer_dirty(bh);
set_buffer_uptodate(bh);
} else if (!buffer_mapped(bh) && buffer_dirty(bh)) {
+ WARN_ON(bh->b_size != blocksize);
err = get_block(inode, block, bh, 1);
if (err)
goto recover;
@@ -1941,6 +1932,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
if (buffer_new(bh))
clear_buffer_new(bh);
if (!buffer_mapped(bh)) {
+ WARN_ON(bh->b_size != blocksize);
err = get_block(inode, block, bh, 1);
if (err)
break;
@@ -2096,6 +2088,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
fully_mapped = 0;
if (iblock < lblock) {
+ WARN_ON(bh->b_size != blocksize);
err = get_block(inode, iblock, bh, 0);
if (err)
SetPageError(page);
@@ -2417,6 +2410,7 @@ int nobh_prepare_write(struct page *page, unsigned from, unsigned to,
create = 1;
if (block_start >= to)
create = 0;
+ map_bh.b_size = blocksize;
ret = get_block(inode, block_in_file + block_in_page,
&map_bh, create);
if (ret)
@@ -2677,6 +2671,7 @@ int block_truncate_page(struct address_space *mapping,
err = 0;
if (!buffer_mapped(bh)) {
+ WARN_ON(bh->b_size != blocksize);
err = get_block(inode, iblock, bh, 0);
if (err)
goto unlock;
@@ -2763,6 +2758,7 @@ sector_t generic_block_bmap(struct address_space *mapping, sector_t block,
struct inode *inode = mapping->host;
tmp.b_state = 0;
tmp.b_blocknr = 0;
+ tmp.b_size = 1 << inode->i_blkbits;
get_block(inode, block, &tmp, 0);
return tmp.b_blocknr;
}
@@ -3015,7 +3011,7 @@ out:
}
EXPORT_SYMBOL(try_to_free_buffers);
-int block_sync_page(struct page *page)
+void block_sync_page(struct page *page)
{
struct address_space *mapping;
@@ -3023,7 +3019,6 @@ int block_sync_page(struct page *page)
mapping = page_mapping(page);
if (mapping)
blk_run_backing_dev(mapping->backing_dev_info, page);
- return 0;
}
/*
diff --git a/fs/char_dev.c b/fs/char_dev.c
index 5c36345c9bf..4e1b849f912 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -146,12 +146,10 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
int ret = 0;
int i;
- cd = kmalloc(sizeof(struct char_device_struct), GFP_KERNEL);
+ cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL);
if (cd == NULL)
return ERR_PTR(-ENOMEM);
- memset(cd, 0, sizeof(struct char_device_struct));
-
mutex_lock(&chrdevs_lock);
/* temporary */
@@ -252,7 +250,7 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
}
int register_chrdev(unsigned int major, const char *name,
- struct file_operations *fops)
+ const struct file_operations *fops)
{
struct char_device_struct *cd;
struct cdev *cdev;
@@ -408,7 +406,7 @@ static void cdev_purge(struct cdev *cdev)
* is contain the open that then fills in the correct operations
* depending on the special file...
*/
-struct file_operations def_chr_fops = {
+const struct file_operations def_chr_fops = {
.open = chrdev_open,
};
@@ -466,9 +464,8 @@ static struct kobj_type ktype_cdev_dynamic = {
struct cdev *cdev_alloc(void)
{
- struct cdev *p = kmalloc(sizeof(struct cdev), GFP_KERNEL);
+ struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);
if (p) {
- memset(p, 0, sizeof(struct cdev));
p->kobj.ktype = &ktype_cdev_dynamic;
INIT_LIST_HEAD(&p->list);
kobject_init(&p->kobj);
@@ -476,7 +473,7 @@ struct cdev *cdev_alloc(void)
return p;
}
-void cdev_init(struct cdev *cdev, struct file_operations *fops)
+void cdev_init(struct cdev *cdev, const struct file_operations *fops)
{
memset(cdev, 0, sizeof *cdev);
INIT_LIST_HEAD(&cdev->list);
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 221b3334b73..4bbc544857b 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -583,7 +583,7 @@ struct inode_operations cifs_symlink_inode_ops = {
#endif
};
-struct file_operations cifs_file_ops = {
+const struct file_operations cifs_file_ops = {
.read = do_sync_read,
.write = do_sync_write,
.readv = generic_file_readv,
@@ -607,7 +607,7 @@ struct file_operations cifs_file_ops = {
#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
-struct file_operations cifs_file_direct_ops = {
+const struct file_operations cifs_file_direct_ops = {
/* no mmap, no aio, no readv -
BB reevaluate whether they can be done with directio, no cache */
.read = cifs_user_read,
@@ -626,7 +626,7 @@ struct file_operations cifs_file_direct_ops = {
.dir_notify = cifs_dir_notify,
#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
-struct file_operations cifs_file_nobrl_ops = {
+const struct file_operations cifs_file_nobrl_ops = {
.read = do_sync_read,
.write = do_sync_write,
.readv = generic_file_readv,
@@ -649,7 +649,7 @@ struct file_operations cifs_file_nobrl_ops = {
#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
-struct file_operations cifs_file_direct_nobrl_ops = {
+const struct file_operations cifs_file_direct_nobrl_ops = {
/* no mmap, no aio, no readv -
BB reevaluate whether they can be done with directio, no cache */
.read = cifs_user_read,
@@ -668,7 +668,7 @@ struct file_operations cifs_file_direct_nobrl_ops = {
#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
-struct file_operations cifs_dir_ops = {
+const struct file_operations cifs_dir_ops = {
.readdir = cifs_readdir,
.release = cifs_closedir,
.read = generic_read_dir,
@@ -738,10 +738,8 @@ cifs_init_request_bufs(void)
cERROR(1,("cifs_min_rcv set to maximum (64)"));
}
- cifs_req_poolp = mempool_create(cifs_min_rcv,
- mempool_alloc_slab,
- mempool_free_slab,
- cifs_req_cachep);
+ cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
+ cifs_req_cachep);
if(cifs_req_poolp == NULL) {
kmem_cache_destroy(cifs_req_cachep);
@@ -771,10 +769,8 @@ cifs_init_request_bufs(void)
cFYI(1,("cifs_min_small set to maximum (256)"));
}
- cifs_sm_req_poolp = mempool_create(cifs_min_small,
- mempool_alloc_slab,
- mempool_free_slab,
- cifs_sm_req_cachep);
+ cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
+ cifs_sm_req_cachep);
if(cifs_sm_req_poolp == NULL) {
mempool_destroy(cifs_req_poolp);
@@ -808,10 +804,8 @@ cifs_init_mids(void)
if (cifs_mid_cachep == NULL)
return -ENOMEM;
- cifs_mid_poolp = mempool_create(3 /* a reasonable min simultan opers */,
- mempool_alloc_slab,
- mempool_free_slab,
- cifs_mid_cachep);
+ /* 3 is a reasonable minimum number of simultaneous operations */
+ cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep);
if(cifs_mid_poolp == NULL) {
kmem_cache_destroy(cifs_mid_cachep);
return -ENOMEM;
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 821a8eb2255..74f405ae4da 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -61,10 +61,10 @@ extern struct inode_operations cifs_file_inode_ops;
extern struct inode_operations cifs_symlink_inode_ops;
/* Functions related to files and directories */
-extern struct file_operations cifs_file_ops;
-extern struct file_operations cifs_file_direct_ops; /* if directio mount */
-extern struct file_operations cifs_file_nobrl_ops;
-extern struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */
+extern const struct file_operations cifs_file_ops;
+extern const struct file_operations cifs_file_direct_ops; /* if directio mount */
+extern const struct file_operations cifs_file_nobrl_ops;
+extern const struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */
extern int cifs_open(struct inode *inode, struct file *file);
extern int cifs_close(struct inode *inode, struct file *file);
extern int cifs_closedir(struct inode *inode, struct file *file);
@@ -76,7 +76,7 @@ extern int cifs_lock(struct file *, int, struct file_lock *);
extern int cifs_fsync(struct file *, struct dentry *, int);
extern int cifs_flush(struct file *);
extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
-extern struct file_operations cifs_dir_ops;
+extern const struct file_operations cifs_dir_ops;
extern int cifs_dir_open(struct inode *inode, struct file *file);
extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
extern int cifs_dir_notify(struct file *, unsigned long arg);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 165d6742638..fb49aef1f2e 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1339,7 +1339,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
return rc;
}
-/* static int cifs_sync_page(struct page *page)
+/* static void cifs_sync_page(struct page *page)
{
struct address_space *mapping;
struct inode *inode;
@@ -1353,16 +1353,18 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
return 0;
inode = mapping->host;
if (!inode)
- return 0; */
+ return; */
/* fill in rpages then
result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
/* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
+#if 0
if (rc < 0)
return rc;
return 0;
+#endif
} */
/*
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index ff93a9f81d1..598eec9778f 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -163,9 +163,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
if (num_of_bytes < end_of_file)
cFYI(1, ("allocation size less than end of file"));
- cFYI(1,
- ("Size %ld and blocks %ld",
- (unsigned long) inode->i_size, inode->i_blocks));
+ cFYI(1, ("Size %ld and blocks %llu",
+ (unsigned long) inode->i_size,
+ (unsigned long long)inode->i_blocks));
if (S_ISREG(inode->i_mode)) {
cFYI(1, ("File inode"));
inode->i_op = &cifs_file_inode_ops;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index edb3b6eb34b..488bd0d81dc 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -197,10 +197,10 @@ static void fill_in_inode(struct inode *tmp_inode,
if (allocation_size < end_of_file)
cFYI(1, ("May be sparse file, allocation less than file size"));
- cFYI(1,
- ("File Size %ld and blocks %ld and blocksize %ld",
- (unsigned long)tmp_inode->i_size, tmp_inode->i_blocks,
- tmp_inode->i_blksize));
+ cFYI(1, ("File Size %ld and blocks %llu and blocksize %ld",
+ (unsigned long)tmp_inode->i_size,
+ (unsigned long long)tmp_inode->i_blocks,
+ tmp_inode->i_blksize));
if (S_ISREG(tmp_inode->i_mode)) {
cFYI(1, ("File inode"));
tmp_inode->i_op = &cifs_file_inode_ops;
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index c607d923350..5d052713326 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -51,7 +51,7 @@ void coda_cache_clear_all(struct super_block *sb)
struct coda_sb_info *sbi;
sbi = coda_sbp(sb);
- if (!sbi) BUG();
+ BUG_ON(!sbi);
atomic_inc(&permission_epoch);
}
diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c
index 23aeef5aa81..4c9fecbfa91 100644
--- a/fs/coda/cnode.c
+++ b/fs/coda/cnode.c
@@ -120,8 +120,7 @@ void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid,
cii = ITOC(inode);
- if (!coda_fideq(&cii->c_fid, oldfid))
- BUG();
+ BUG_ON(!coda_fideq(&cii->c_fid, oldfid));
/* replace fid and rehash inode */
/* XXX we probably need to hold some lock here! */
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 54f76de8a68..71f2ea632e5 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -82,7 +82,7 @@ struct inode_operations coda_dir_inode_operations =
.setattr = coda_setattr,
};
-struct file_operations coda_dir_operations = {
+const struct file_operations coda_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = coda_readdir,
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 146a991d6eb..7c2642431fa 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -288,7 +288,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
return err;
}
-struct file_operations coda_file_operations = {
+const struct file_operations coda_file_operations = {
.llseek = generic_file_llseek,
.read = coda_file_read,
.write = coda_file_write,
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index 127714936c6..214822be87b 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -36,7 +36,7 @@ struct inode_operations coda_ioctl_inode_operations =
.setattr = coda_setattr,
};
-struct file_operations coda_ioctl_operations = {
+const struct file_operations coda_ioctl_operations = {
.owner = THIS_MODULE,
.ioctl = coda_pioctl,
};
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 98c74fe2e13..6c6771db36d 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -342,7 +342,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
}
-static struct file_operations coda_psdev_fops = {
+static const struct file_operations coda_psdev_fops = {
.owner = THIS_MODULE,
.read = coda_psdev_read,
.write = coda_psdev_write,
diff --git a/fs/compat.c b/fs/compat.c
index 2a88477330f..7f8e26ea427 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1476,10 +1476,9 @@ int compat_do_execve(char * filename,
int i;
retval = -ENOMEM;
- bprm = kmalloc(sizeof(*bprm), GFP_KERNEL);
+ bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
if (!bprm)
goto out_ret;
- memset(bprm, 0, sizeof(*bprm));
file = open_exec(filename);
retval = PTR_ERR(file);
@@ -1640,15 +1639,6 @@ void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
* This is a virtual copy of sys_select from fs/select.c and probably
* should be compared to it from time to time
*/
-static void *select_bits_alloc(int size)
-{
- return kmalloc(6 * size, GFP_KERNEL);
-}
-
-static void select_bits_free(void *bits, int size)
-{
- kfree(bits);
-}
/*
* We can actually return ERESTARTSYS instead of EINTR, but I'd
@@ -1687,7 +1677,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
*/
ret = -ENOMEM;
size = FDS_BYTES(n);
- bits = select_bits_alloc(size);
+ bits = kmalloc(6 * size, GFP_KERNEL);
if (!bits)
goto out_nofds;
fds.in = (unsigned long *) bits;
@@ -1721,7 +1711,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
compat_set_fd_set(n, exp, fds.res_ex);
out:
- select_bits_free(bits, size);
+ kfree(bits);
out_nofds:
return ret;
}
@@ -2170,9 +2160,12 @@ asmlinkage long compat_sys_nfsservctl(int cmd, struct compat_nfsctl_arg __user *
default:
err = -EINVAL;
- goto done;
+ break;
}
+ if (err)
+ goto done;
+
oldfs = get_fs();
set_fs(KERNEL_DS);
/* The __user pointer casts are valid because of the set_fs() */
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index f70e46951b3..3f4ff7a242b 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -72,9 +72,9 @@ extern void configfs_release_fs(void);
extern struct rw_semaphore configfs_rename_sem;
extern struct super_block * configfs_sb;
-extern struct file_operations configfs_dir_operations;
-extern struct file_operations configfs_file_operations;
-extern struct file_operations bin_fops;
+extern const struct file_operations configfs_dir_operations;
+extern const struct file_operations configfs_file_operations;
+extern const struct file_operations bin_fops;
extern struct inode_operations configfs_dir_inode_operations;
extern struct inode_operations configfs_symlink_inode_operations;
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index ca60e3abef4..8ed9b06a982 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -1027,7 +1027,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin)
return offset;
}
-struct file_operations configfs_dir_operations = {
+const struct file_operations configfs_dir_operations = {
.open = configfs_dir_open,
.release = configfs_dir_close,
.llseek = configfs_dir_lseek,
diff --git a/fs/configfs/file.c b/fs/configfs/file.c
index 3921920d871..f499803743e 100644
--- a/fs/configfs/file.c
+++ b/fs/configfs/file.c
@@ -322,7 +322,7 @@ static int configfs_release(struct inode * inode, struct file * filp)
return 0;
}
-struct file_operations configfs_file_operations = {
+const struct file_operations configfs_file_operations = {
.read = configfs_read_file,
.write = configfs_write_file,
.llseek = generic_file_llseek,
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 8ad52f5bf25..9efcc3a164e 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -22,16 +22,17 @@
#include <linux/cramfs_fs_sb.h>
#include <linux/buffer_head.h>
#include <linux/vfs.h>
+#include <linux/mutex.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
static struct super_operations cramfs_ops;
static struct inode_operations cramfs_dir_inode_operations;
-static struct file_operations cramfs_directory_operations;
+static const struct file_operations cramfs_directory_operations;
static struct address_space_operations cramfs_aops;
-static DECLARE_MUTEX(read_mutex);
+static DEFINE_MUTEX(read_mutex);
/* These two macros may change in future, to provide better st_ino
@@ -250,20 +251,20 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
memset(sbi, 0, sizeof(struct cramfs_sb_info));
/* Invalidate the read buffers on mount: think disk change.. */
- down(&read_mutex);
+ mutex_lock(&read_mutex);
for (i = 0; i < READ_BUFFERS; i++)
buffer_blocknr[i] = -1;
/* Read the first block and get the superblock from it */
memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
- up(&read_mutex);
+ mutex_unlock(&read_mutex);
/* Do sanity checks on the superblock */
if (super.magic != CRAMFS_MAGIC) {
/* check at 512 byte offset */
- down(&read_mutex);
+ mutex_lock(&read_mutex);
memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super));
- up(&read_mutex);
+ mutex_unlock(&read_mutex);
if (super.magic != CRAMFS_MAGIC) {
if (!silent)
printk(KERN_ERR "cramfs: wrong magic\n");
@@ -366,7 +367,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
mode_t mode;
int namelen, error;
- down(&read_mutex);
+ mutex_lock(&read_mutex);
de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+256);
name = (char *)(de+1);
@@ -379,7 +380,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
memcpy(buf, name, namelen);
ino = CRAMINO(de);
mode = de->mode;
- up(&read_mutex);
+ mutex_unlock(&read_mutex);
nextoffset = offset + sizeof(*de) + namelen;
for (;;) {
if (!namelen) {
@@ -410,7 +411,7 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s
unsigned int offset = 0;
int sorted;
- down(&read_mutex);
+ mutex_lock(&read_mutex);
sorted = CRAMFS_SB(dir->i_sb)->flags & CRAMFS_FLAG_SORTED_DIRS;
while (offset < dir->i_size) {
struct cramfs_inode *de;
@@ -433,7 +434,7 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s
for (;;) {
if (!namelen) {
- up(&read_mutex);
+ mutex_unlock(&read_mutex);
return ERR_PTR(-EIO);
}
if (name[namelen-1])
@@ -447,7 +448,7 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s
continue;
if (!retval) {
struct cramfs_inode entry = *de;
- up(&read_mutex);
+ mutex_unlock(&read_mutex);
d_add(dentry, get_cramfs_inode(dir->i_sb, &entry));
return NULL;
}
@@ -455,7 +456,7 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s
if (sorted)
break;
}
- up(&read_mutex);
+ mutex_unlock(&read_mutex);
d_add(dentry, NULL);
return NULL;
}
@@ -474,21 +475,21 @@ static int cramfs_readpage(struct file *file, struct page * page)
u32 start_offset, compr_len;
start_offset = OFFSET(inode) + maxblock*4;
- down(&read_mutex);
+ mutex_lock(&read_mutex);
if (page->index)
start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 4);
compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - start_offset);
- up(&read_mutex);
+ mutex_unlock(&read_mutex);
pgdata = kmap(page);
if (compr_len == 0)
; /* hole */
else {
- down(&read_mutex);
+ mutex_lock(&read_mutex);
bytes_filled = cramfs_uncompress_block(pgdata,
PAGE_CACHE_SIZE,
cramfs_read(sb, start_offset, compr_len),
compr_len);
- up(&read_mutex);
+ mutex_unlock(&read_mutex);
}
} else
pgdata = kmap(page);
@@ -511,7 +512,7 @@ static struct address_space_operations cramfs_aops = {
/*
* A directory can only readdir
*/
-static struct file_operations cramfs_directory_operations = {
+static const struct file_operations cramfs_directory_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = cramfs_readdir,
diff --git a/fs/dcache.c b/fs/dcache.c
index 653f64ce98e..19458d39950 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -34,9 +34,8 @@
#include <linux/swap.h>
#include <linux/bootmem.h>
-/* #define DCACHE_DEBUG 1 */
-int sysctl_vfs_cache_pressure = 100;
+int sysctl_vfs_cache_pressure __read_mostly = 100;
EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure);
__cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock);
@@ -44,7 +43,7 @@ static seqlock_t rename_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED;
EXPORT_SYMBOL(dcache_lock);
-static kmem_cache_t *dentry_cache;
+static kmem_cache_t *dentry_cache __read_mostly;
#define DNAME_INLINE_LEN (sizeof(struct dentry)-offsetof(struct dentry,d_iname))
@@ -59,9 +58,9 @@ static kmem_cache_t *dentry_cache;
#define D_HASHBITS d_hash_shift
#define D_HASHMASK d_hash_mask
-static unsigned int d_hash_mask;
-static unsigned int d_hash_shift;
-static struct hlist_head *dentry_hashtable;
+static unsigned int d_hash_mask __read_mostly;
+static unsigned int d_hash_shift __read_mostly;
+static struct hlist_head *dentry_hashtable __read_mostly;
static LIST_HEAD(dentry_unused);
/* Statistics gathering. */
@@ -325,10 +324,13 @@ static struct dentry * __d_find_alias(struct inode *inode, int want_discon)
struct dentry * d_find_alias(struct inode *inode)
{
- struct dentry *de;
- spin_lock(&dcache_lock);
- de = __d_find_alias(inode, 0);
- spin_unlock(&dcache_lock);
+ struct dentry *de = NULL;
+
+ if (!list_empty(&inode->i_dentry)) {
+ spin_lock(&dcache_lock);
+ de = __d_find_alias(inode, 0);
+ spin_unlock(&dcache_lock);
+ }
return de;
}
@@ -486,6 +488,7 @@ repeat:
continue;
}
prune_one_dentry(dentry);
+ cond_resched_lock(&dcache_lock);
goto repeat;
}
spin_unlock(&dcache_lock);
@@ -599,10 +602,6 @@ resume:
*/
if (!list_empty(&dentry->d_subdirs)) {
this_parent = dentry;
-#ifdef DCACHE_DEBUG
-printk(KERN_DEBUG "select_parent: descending to %s/%s, found=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, found);
-#endif
goto repeat;
}
}
@@ -612,10 +611,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name, found);
if (this_parent != parent) {
next = this_parent->d_u.d_child.next;
this_parent = this_parent->d_parent;
-#ifdef DCACHE_DEBUG
-printk(KERN_DEBUG "select_parent: ascending to %s/%s, found=%d\n",
-this_parent->d_parent->d_name.name, this_parent->d_name.name, found);
-#endif
goto resume;
}
out:
@@ -794,11 +789,12 @@ struct dentry *d_alloc_name(struct dentry *parent, const char *name)
void d_instantiate(struct dentry *entry, struct inode * inode)
{
- if (!list_empty(&entry->d_alias)) BUG();
+ BUG_ON(!list_empty(&entry->d_alias));
spin_lock(&dcache_lock);
if (inode)
list_add(&entry->d_alias, &inode->i_dentry);
entry->d_inode = inode;
+ fsnotify_d_instantiate(entry, inode);
spin_unlock(&dcache_lock);
security_d_instantiate(entry, inode);
}
@@ -850,6 +846,7 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
list_add(&entry->d_alias, &inode->i_dentry);
do_negative:
entry->d_inode = inode;
+ fsnotify_d_instantiate(entry, inode);
spin_unlock(&dcache_lock);
security_d_instantiate(entry, inode);
return NULL;
@@ -980,6 +977,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
new = __d_find_alias(inode, 1);
if (new) {
BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED));
+ fsnotify_d_instantiate(new, inode);
spin_unlock(&dcache_lock);
security_d_instantiate(new, inode);
d_rehash(dentry);
@@ -989,6 +987,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
/* d_instantiate takes dcache_lock, so we do it by hand */
list_add(&dentry->d_alias, &inode->i_dentry);
dentry->d_inode = inode;
+ fsnotify_d_instantiate(dentry, inode);
spin_unlock(&dcache_lock);
security_d_instantiate(dentry, inode);
d_rehash(dentry);
@@ -1173,6 +1172,9 @@ void d_delete(struct dentry * dentry)
spin_lock(&dentry->d_lock);
isdir = S_ISDIR(dentry->d_inode->i_mode);
if (atomic_read(&dentry->d_count) == 1) {
+ /* remove this and other inotify debug checks after 2.6.18 */
+ dentry->d_flags &= ~DCACHE_INOTIFY_PARENT_WATCHED;
+
dentry_iput(dentry);
fsnotify_nameremove(dentry, isdir);
return;
@@ -1339,6 +1341,7 @@ already_unhashed:
list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
spin_unlock(&target->d_lock);
+ fsnotify_d_move(dentry);
spin_unlock(&dentry->d_lock);
write_sequnlock(&rename_lock);
spin_unlock(&dcache_lock);
@@ -1707,10 +1710,10 @@ static void __init dcache_init(unsigned long mempages)
}
/* SLAB cache for __getname() consumers */
-kmem_cache_t *names_cachep;
+kmem_cache_t *names_cachep __read_mostly;
/* SLAB cache for file structures */
-kmem_cache_t *filp_cachep;
+kmem_cache_t *filp_cachep __read_mostly;
EXPORT_SYMBOL(d_genocide);
diff --git a/fs/dcookies.c b/fs/dcookies.c
index f8274a8f83b..8749339bf4f 100644
--- a/fs/dcookies.c
+++ b/fs/dcookies.c
@@ -23,6 +23,7 @@
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/dcookies.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
/* The dcookies are allocated from a kmem_cache and
@@ -36,10 +37,10 @@ struct dcookie_struct {
};
static LIST_HEAD(dcookie_users);
-static DECLARE_MUTEX(dcookie_sem);
-static kmem_cache_t * dcookie_cache;
-static struct list_head * dcookie_hashtable;
-static size_t hash_size;
+static DEFINE_MUTEX(dcookie_mutex);
+static kmem_cache_t *dcookie_cache __read_mostly;
+static struct list_head *dcookie_hashtable __read_mostly;
+static size_t hash_size __read_mostly;
static inline int is_live(void)
{
@@ -114,7 +115,7 @@ int get_dcookie(struct dentry * dentry, struct vfsmount * vfsmnt,
int err = 0;
struct dcookie_struct * dcs;
- down(&dcookie_sem);
+ mutex_lock(&dcookie_mutex);
if (!is_live()) {
err = -EINVAL;
@@ -134,7 +135,7 @@ int get_dcookie(struct dentry * dentry, struct vfsmount * vfsmnt,
*cookie = dcookie_value(dcs);
out:
- up(&dcookie_sem);
+ mutex_unlock(&dcookie_mutex);
return err;
}
@@ -157,7 +158,7 @@ asmlinkage long sys_lookup_dcookie(u64 cookie64, char __user * buf, size_t len)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- down(&dcookie_sem);
+ mutex_lock(&dcookie_mutex);
if (!is_live()) {
err = -EINVAL;
@@ -192,7 +193,7 @@ asmlinkage long sys_lookup_dcookie(u64 cookie64, char __user * buf, size_t len)
out_free:
kfree(kbuf);
out:
- up(&dcookie_sem);
+ mutex_unlock(&dcookie_mutex);
return err;
}
@@ -290,7 +291,7 @@ struct dcookie_user * dcookie_register(void)
{
struct dcookie_user * user;
- down(&dcookie_sem);
+ mutex_lock(&dcookie_mutex);
user = kmalloc(sizeof(struct dcookie_user), GFP_KERNEL);
if (!user)
@@ -302,7 +303,7 @@ struct dcookie_user * dcookie_register(void)
list_add(&user->next, &dcookie_users);
out:
- up(&dcookie_sem);
+ mutex_unlock(&dcookie_mutex);
return user;
out_free:
kfree(user);
@@ -313,7 +314,7 @@ out_free:
void dcookie_unregister(struct dcookie_user * user)
{
- down(&dcookie_sem);
+ mutex_lock(&dcookie_mutex);
list_del(&user->next);
kfree(user);
@@ -321,7 +322,7 @@ void dcookie_unregister(struct dcookie_user * user)
if (!is_live())
dcookie_exit();
- up(&dcookie_sem);
+ mutex_unlock(&dcookie_mutex);
}
EXPORT_SYMBOL_GPL(dcookie_register);
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 40c4fc973fa..66a505422e5 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -39,7 +39,7 @@ static int default_open(struct inode *inode, struct file *file)
return 0;
}
-struct file_operations debugfs_file_operations = {
+const struct file_operations debugfs_file_operations = {
.read = default_read_file,
.write = default_write_file,
.open = default_open,
@@ -213,7 +213,7 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
return count;
}
-static struct file_operations fops_bool = {
+static const struct file_operations fops_bool = {
.read = read_file_bool,
.write = write_file_bool,
.open = default_open,
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index d4f1a2cddd4..85d166cdcae 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -191,7 +191,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
*/
struct dentry *debugfs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data,
- struct file_operations *fops)
+ const struct file_operations *fops)
{
struct dentry *dentry = NULL;
int error;
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index b621521e09d..52f5059c4f3 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -856,14 +856,14 @@ static int devfsd_close(struct inode *inode, struct file *file);
#ifdef CONFIG_DEVFS_DEBUG
static ssize_t stat_read(struct file *file, char __user *buf, size_t len,
loff_t * ppos);
-static struct file_operations stat_fops = {
+static const struct file_operations stat_fops = {
.open = nonseekable_open,
.read = stat_read,
};
#endif
/* Devfs daemon file operations */
-static struct file_operations devfsd_fops = {
+static const struct file_operations devfsd_fops = {
.open = nonseekable_open,
.read = devfsd_read,
.ioctl = devfsd_ioctl,
@@ -1842,8 +1842,8 @@ static int try_modload(struct devfs_entry *parent, struct fs_info *fs_info,
static struct inode_operations devfs_iops;
static struct inode_operations devfs_dir_iops;
-static struct file_operations devfs_fops;
-static struct file_operations devfs_dir_fops;
+static const struct file_operations devfs_fops;
+static const struct file_operations devfs_dir_fops;
static struct inode_operations devfs_symlink_iops;
static int devfs_notify_change(struct dentry *dentry, struct iattr *iattr)
@@ -2061,11 +2061,11 @@ static int devfs_open(struct inode *inode, struct file *file)
return err;
} /* End Function devfs_open */
-static struct file_operations devfs_fops = {
+static const struct file_operations devfs_fops = {
.open = devfs_open,
};
-static struct file_operations devfs_dir_fops = {
+static const struct file_operations devfs_dir_fops = {
.read = generic_read_dir,
.readdir = devfs_readdir,
};
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 27f3e787fac..910a8ed74b5 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -86,12 +86,12 @@ struct dio {
unsigned first_block_in_page; /* doesn't change, Used only once */
int boundary; /* prev block is at a boundary */
int reap_counter; /* rate limit reaping */
- get_blocks_t *get_blocks; /* block mapping function */
+ get_block_t *get_block; /* block mapping function */
dio_iodone_t *end_io; /* IO completion function */
sector_t final_block_in_bio; /* current final block in bio + 1 */
sector_t next_block_for_io; /* next block to be put under IO,
in dio_blocks units */
- struct buffer_head map_bh; /* last get_blocks() result */
+ struct buffer_head map_bh; /* last get_block() result */
/*
* Deferred addition of a page to the dio. These variables are
@@ -129,6 +129,7 @@ struct dio {
/* AIO related stuff */
struct kiocb *iocb; /* kiocb */
int is_async; /* is IO async ? */
+ int io_error; /* IO error in completion path */
ssize_t result; /* IO result */
};
@@ -210,9 +211,9 @@ static struct page *dio_get_page(struct dio *dio)
/*
* Called when all DIO BIO I/O has been completed - let the filesystem
- * know, if it registered an interest earlier via get_blocks. Pass the
+ * know, if it registered an interest earlier via get_block. Pass the
* private field of the map buffer_head so that filesystems can use it
- * to hold additional state between get_blocks calls and dio_complete.
+ * to hold additional state between get_block calls and dio_complete.
*/
static void dio_complete(struct dio *dio, loff_t offset, ssize_t bytes)
{
@@ -250,6 +251,10 @@ static void finished_one_bio(struct dio *dio)
((offset + transferred) > dio->i_size))
transferred = dio->i_size - offset;
+ /* check for error in completion path */
+ if (dio->io_error)
+ transferred = dio->io_error;
+
dio_complete(dio, offset, transferred);
/* Complete AIO later if falling back to buffered i/o */
@@ -406,7 +411,7 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio)
int page_no;
if (!uptodate)
- dio->result = -EIO;
+ dio->io_error = -EIO;
if (dio->is_async && dio->rw == READ) {
bio_check_pages_dirty(bio); /* transfers ownership */
@@ -488,7 +493,7 @@ static int dio_bio_reap(struct dio *dio)
* The fs is allowed to map lots of blocks at once. If it wants to do that,
* it uses the passed inode-relative block number as the file offset, as usual.
*
- * get_blocks() is passed the number of i_blkbits-sized blocks which direct_io
+ * get_block() is passed the number of i_blkbits-sized blocks which direct_io
* has remaining to do. The fs should not map more than this number of blocks.
*
* If the fs has mapped a lot of blocks, it should populate bh->b_size to
@@ -501,7 +506,7 @@ static int dio_bio_reap(struct dio *dio)
* In the case of filesystem holes: the fs may return an arbitrarily-large
* hole by returning an appropriate value in b_size and by clearing
* buffer_mapped(). However the direct-io code will only process holes one
- * block at a time - it will repeatedly call get_blocks() as it walks the hole.
+ * block at a time - it will repeatedly call get_block() as it walks the hole.
*/
static int get_more_blocks(struct dio *dio)
{
@@ -519,8 +524,6 @@ static int get_more_blocks(struct dio *dio)
*/
ret = dio->page_errors;
if (ret == 0) {
- map_bh->b_state = 0;
- map_bh->b_size = 0;
BUG_ON(dio->block_in_file >= dio->final_block_in_request);
fs_startblk = dio->block_in_file >> dio->blkfactor;
dio_count = dio->final_block_in_request - dio->block_in_file;
@@ -529,6 +532,9 @@ static int get_more_blocks(struct dio *dio)
if (dio_count & blkmask)
fs_count++;
+ map_bh->b_state = 0;
+ map_bh->b_size = fs_count << dio->inode->i_blkbits;
+
create = dio->rw == WRITE;
if (dio->lock_type == DIO_LOCKING) {
if (dio->block_in_file < (i_size_read(dio->inode) >>
@@ -537,13 +543,14 @@ static int get_more_blocks(struct dio *dio)
} else if (dio->lock_type == DIO_NO_LOCKING) {
create = 0;
}
+
/*
* For writes inside i_size we forbid block creations: only
* overwrites are permitted. We fall back to buffered writes
* at a higher level for inside-i_size block-instantiating
* writes.
*/
- ret = (*dio->get_blocks)(dio->inode, fs_startblk, fs_count,
+ ret = (*dio->get_block)(dio->inode, fs_startblk,
map_bh, create);
}
return ret;
@@ -778,11 +785,11 @@ static void dio_zero_block(struct dio *dio, int end)
* happily perform page-sized but 512-byte aligned IOs. It is important that
* blockdev IO be able to have fine alignment and large sizes.
*
- * So what we do is to permit the ->get_blocks function to populate bh.b_size
+ * So what we do is to permit the ->get_block function to populate bh.b_size
* with the size of IO which is permitted at this offset and this i_blkbits.
*
* For best results, the blockdev should be set up with 512-byte i_blkbits and
- * it should set b_size to PAGE_SIZE or more inside get_blocks(). This gives
+ * it should set b_size to PAGE_SIZE or more inside get_block(). This gives
* fine alignment but still allows this function to work in PAGE_SIZE units.
*/
static int do_direct_IO(struct dio *dio)
@@ -942,7 +949,7 @@ out:
static ssize_t
direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
const struct iovec *iov, loff_t offset, unsigned long nr_segs,
- unsigned blkbits, get_blocks_t get_blocks, dio_iodone_t end_io,
+ unsigned blkbits, get_block_t get_block, dio_iodone_t end_io,
struct dio *dio)
{
unsigned long user_addr;
@@ -964,13 +971,14 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
dio->boundary = 0;
dio->reap_counter = 0;
- dio->get_blocks = get_blocks;
+ dio->get_block = get_block;
dio->end_io = end_io;
dio->map_bh.b_private = NULL;
dio->final_block_in_bio = -1;
dio->next_block_for_io = -1;
dio->page_errors = 0;
+ dio->io_error = 0;
dio->result = 0;
dio->iocb = iocb;
dio->i_size = i_size_read(inode);
@@ -1171,7 +1179,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
ssize_t
__blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
struct block_device *bdev, const struct iovec *iov, loff_t offset,
- unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io,
+ unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
int dio_lock_type)
{
int seg;
@@ -1267,7 +1275,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
(end > i_size_read(inode)));
retval = direct_io_worker(rw, iocb, inode, iov, offset,
- nr_segs, blkbits, get_blocks, end_io, dio);
+ nr_segs, blkbits, get_block, end_io, dio);
if (rw == READ && dio_lock_type == DIO_LOCKING)
release_i_mutex = 0;
diff --git a/fs/dnotify.c b/fs/dnotify.c
index f3b540dd5d1..f932591df5a 100644
--- a/fs/dnotify.c
+++ b/fs/dnotify.c
@@ -21,9 +21,9 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
-int dir_notify_enable = 1;
+int dir_notify_enable __read_mostly = 1;
-static kmem_cache_t *dn_cache;
+static kmem_cache_t *dn_cache __read_mostly;
static void redo_inode_mask(struct inode *inode)
{
diff --git a/fs/efs/dir.c b/fs/efs/dir.c
index 777c614ff36..17f5b2d3c16 100644
--- a/fs/efs/dir.c
+++ b/fs/efs/dir.c
@@ -10,7 +10,7 @@
static int efs_readdir(struct file *, void *, filldir_t);
-struct file_operations efs_dir_operations = {
+const struct file_operations efs_dir_operations = {
.read = generic_read_dir,
.readdir = efs_readdir,
};
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 1c2b16fda13..242fe1a66ce 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -281,16 +281,16 @@ static struct mutex epmutex;
static struct poll_safewake psw;
/* Slab cache used to allocate "struct epitem" */
-static kmem_cache_t *epi_cache;
+static kmem_cache_t *epi_cache __read_mostly;
/* Slab cache used to allocate "struct eppoll_entry" */
-static kmem_cache_t *pwq_cache;
+static kmem_cache_t *pwq_cache __read_mostly;
/* Virtual fs used to allocate inodes for eventpoll files */
-static struct vfsmount *eventpoll_mnt;
+static struct vfsmount *eventpoll_mnt __read_mostly;
/* File callbacks that implement the eventpoll file behaviour */
-static struct file_operations eventpoll_fops = {
+static const struct file_operations eventpoll_fops = {
.release = ep_eventpoll_close,
.poll = ep_eventpoll_poll
};
@@ -599,7 +599,7 @@ sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
switch (op) {
case EPOLL_CTL_ADD:
if (!epi) {
- epds.events |= POLLERR | POLLHUP;
+ epds.events |= POLLERR | POLLHUP | POLLRDHUP;
error = ep_insert(ep, &epds, tfile, fd);
} else
@@ -613,7 +613,7 @@ sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
break;
case EPOLL_CTL_MOD:
if (epi) {
- epds.events |= POLLERR | POLLHUP;
+ epds.events |= POLLERR | POLLHUP | POLLRDHUP;
error = ep_modify(ep, epi, &epds);
} else
error = -ENOENT;
diff --git a/fs/exec.c b/fs/exec.c
index 0b515ac5313..950ebd43cdc 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -127,7 +127,7 @@ asmlinkage long sys_uselib(const char __user * library)
struct nameidata nd;
int error;
- error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ);
+ error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC);
if (error)
goto out;
@@ -477,7 +477,7 @@ struct file *open_exec(const char *name)
int err;
struct file *file;
- err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ);
+ err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC);
file = ERR_PTR(err);
if (!err) {
@@ -616,6 +616,15 @@ static int de_thread(struct task_struct *tsk)
kmem_cache_free(sighand_cachep, newsighand);
return -EAGAIN;
}
+
+ /*
+ * child_reaper ignores SIGKILL, change it now.
+ * Reparenting needs write_lock on tasklist_lock,
+ * so it is safe to do it under read_lock.
+ */
+ if (unlikely(current->group_leader == child_reaper))
+ child_reaper = current;
+
zap_other_threads(current);
read_unlock(&tasklist_lock);
@@ -632,7 +641,7 @@ static int de_thread(struct task_struct *tsk)
* synchronize with any firing (by calling del_timer_sync)
* before we can safely let the old group leader die.
*/
- sig->real_timer.data = current;
+ sig->tsk = current;
spin_unlock_irq(lock);
if (hrtimer_cancel(&sig->real_timer))
hrtimer_restart(&sig->real_timer);
@@ -699,22 +708,30 @@ static int de_thread(struct task_struct *tsk)
remove_parent(current);
remove_parent(leader);
- switch_exec_pids(leader, current);
+
+ /* Become a process group leader with the old leader's pid.
+ * Note: The old leader also uses thispid until release_task
+ * is called. Odd but simple and correct.
+ */
+ detach_pid(current, PIDTYPE_PID);
+ current->pid = leader->pid;
+ attach_pid(current, PIDTYPE_PID, current->pid);
+ attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
+ attach_pid(current, PIDTYPE_SID, current->signal->session);
+ list_add_tail(&current->tasks, &init_task.tasks);
current->parent = current->real_parent = leader->real_parent;
leader->parent = leader->real_parent = child_reaper;
current->group_leader = current;
leader->group_leader = leader;
- add_parent(current, current->parent);
- add_parent(leader, leader->parent);
+ add_parent(current);
+ add_parent(leader);
if (ptrace) {
current->ptrace = ptrace;
__ptrace_link(current, parent);
}
- list_del(&current->tasks);
- list_add_tail(&current->tasks, &init_task.tasks);
current->exit_signal = SIGCHLD;
BUG_ON(leader->exit_state != EXIT_ZOMBIE);
@@ -751,7 +768,6 @@ no_thread_group:
/*
* Move our state over to newsighand and switch it in.
*/
- spin_lock_init(&newsighand->siglock);
atomic_set(&newsighand->count, 1);
memcpy(newsighand->action, oldsighand->action,
sizeof(newsighand->action));
@@ -768,7 +784,7 @@ no_thread_group:
write_unlock_irq(&tasklist_lock);
if (atomic_dec_and_test(&oldsighand->count))
- sighand_free(oldsighand);
+ kmem_cache_free(sighand_cachep, oldsighand);
}
BUG_ON(!thread_group_leader(current));
@@ -1143,10 +1159,9 @@ int do_execve(char * filename,
int i;
retval = -ENOMEM;
- bprm = kmalloc(sizeof(*bprm), GFP_KERNEL);
+ bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
if (!bprm)
goto out_ret;
- memset(bprm, 0, sizeof(*bprm));
file = open_exec(filename);
retval = PTR_ERR(file);
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index b3dbd716cd3..d672aa9f406 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -416,8 +416,7 @@ void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
lock_page(page);
err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
- if (err)
- BUG();
+ BUG_ON(err);
de->inode = cpu_to_le32(inode->i_ino);
ext2_set_de_type (de, inode);
err = ext2_commit_chunk(page, from, to);
@@ -554,8 +553,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page )
from = (char*)pde - (char*)page_address(page);
lock_page(page);
err = mapping->a_ops->prepare_write(NULL, page, from, to);
- if (err)
- BUG();
+ BUG_ON(err);
if (pde)
pde->rec_len = cpu_to_le16(to-from);
dir->inode = 0;
@@ -660,7 +658,7 @@ not_empty:
return 0;
}
-struct file_operations ext2_dir_operations = {
+const struct file_operations ext2_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = ext2_readdir,
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 11035ac7986..9f74a62be55 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -154,12 +154,12 @@ extern void ext2_write_super (struct super_block *);
*/
/* dir.c */
-extern struct file_operations ext2_dir_operations;
+extern const struct file_operations ext2_dir_operations;
/* file.c */
extern struct inode_operations ext2_file_inode_operations;
-extern struct file_operations ext2_file_operations;
-extern struct file_operations ext2_xip_file_operations;
+extern const struct file_operations ext2_file_operations;
+extern const struct file_operations ext2_xip_file_operations;
/* inode.c */
extern struct address_space_operations ext2_aops;
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index a484412fc78..509cceca04d 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -39,7 +39,7 @@ static int ext2_release_file (struct inode * inode, struct file * filp)
* We have mostly NULL's here: the current defaults are ok for
* the ext2 filesystem.
*/
-struct file_operations ext2_file_operations = {
+const struct file_operations ext2_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
@@ -56,7 +56,7 @@ struct file_operations ext2_file_operations = {
};
#ifdef CONFIG_EXT2_FS_XIP
-struct file_operations ext2_xip_file_operations = {
+const struct file_operations ext2_xip_file_operations = {
.llseek = generic_file_llseek,
.read = xip_file_read,
.write = xip_file_write,
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index a717837f272..04af9c45dce 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -667,18 +667,6 @@ static sector_t ext2_bmap(struct address_space *mapping, sector_t block)
return generic_block_bmap(mapping,block,ext2_get_block);
}
-static int
-ext2_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks,
- struct buffer_head *bh_result, int create)
-{
- int ret;
-
- ret = ext2_get_block(inode, iblock, bh_result, create);
- if (ret == 0)
- bh_result->b_size = (1 << inode->i_blkbits);
- return ret;
-}
-
static ssize_t
ext2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
loff_t offset, unsigned long nr_segs)
@@ -687,7 +675,7 @@ ext2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
struct inode *inode = file->f_mapping->host;
return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
- offset, nr_segs, ext2_get_blocks, NULL);
+ offset, nr_segs, ext2_get_block, NULL);
}
static int
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 268b73f5847..7e30bae174e 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -211,8 +211,6 @@ static int ext2_show_options(struct seq_file *seq, struct vfsmount *vfs)
if (sbi->s_mount_opt & EXT2_MOUNT_GRPID)
seq_puts(seq, ",grpid");
- else
- seq_puts(seq, ",nogrpid");
#if defined(CONFIG_QUOTA)
if (sbi->s_mount_opt & EXT2_MOUNT_USRQUOTA)
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 46623f77666..77927d6938f 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -653,9 +653,11 @@ claim_block(spinlock_t *lock, int block, struct buffer_head *bh)
*/
static int
ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group,
- struct buffer_head *bitmap_bh, int goal, struct ext3_reserve_window *my_rsv)
+ struct buffer_head *bitmap_bh, int goal,
+ unsigned long *count, struct ext3_reserve_window *my_rsv)
{
int group_first_block, start, end;
+ unsigned long num = 0;
/* we do allocation within the reservation window if we have a window */
if (my_rsv) {
@@ -713,8 +715,18 @@ repeat:
goto fail_access;
goto repeat;
}
- return goal;
+ num++;
+ goal++;
+ while (num < *count && goal < end
+ && ext3_test_allocatable(goal, bitmap_bh)
+ && claim_block(sb_bgl_lock(EXT3_SB(sb), group), goal, bitmap_bh)) {
+ num++;
+ goal++;
+ }
+ *count = num;
+ return goal - num;
fail_access:
+ *count = num;
return -1;
}
@@ -999,6 +1011,31 @@ retry:
goto retry;
}
+static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv,
+ struct super_block *sb, int size)
+{
+ struct ext3_reserve_window_node *next_rsv;
+ struct rb_node *next;
+ spinlock_t *rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock;
+
+ if (!spin_trylock(rsv_lock))
+ return;
+
+ next = rb_next(&my_rsv->rsv_node);
+
+ if (!next)
+ my_rsv->rsv_end += size;
+ else {
+ next_rsv = list_entry(next, struct ext3_reserve_window_node, rsv_node);
+
+ if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size)
+ my_rsv->rsv_end += size;
+ else
+ my_rsv->rsv_end = next_rsv->rsv_start - 1;
+ }
+ spin_unlock(rsv_lock);
+}
+
/*
* This is the main function used to allocate a new block and its reservation
* window.
@@ -1024,11 +1061,12 @@ static int
ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
unsigned int group, struct buffer_head *bitmap_bh,
int goal, struct ext3_reserve_window_node * my_rsv,
- int *errp)
+ unsigned long *count, int *errp)
{
unsigned long group_first_block;
int ret = 0;
int fatal;
+ unsigned long num = *count;
*errp = 0;
@@ -1051,7 +1089,8 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
* or last attempt to allocate a block with reservation turned on failed
*/
if (my_rsv == NULL ) {
- ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, NULL);
+ ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh,
+ goal, count, NULL);
goto out;
}
/*
@@ -1081,6 +1120,8 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
while (1) {
if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) ||
!goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) {
+ if (my_rsv->rsv_goal_size < *count)
+ my_rsv->rsv_goal_size = *count;
ret = alloc_new_reservation(my_rsv, goal, sb,
group, bitmap_bh);
if (ret < 0)
@@ -1088,16 +1129,21 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
if (!goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb))
goal = -1;
- }
+ } else if (goal > 0 && (my_rsv->rsv_end-goal+1) < *count)
+ try_to_extend_reservation(my_rsv, sb,
+ *count-my_rsv->rsv_end + goal - 1);
+
if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb))
|| (my_rsv->rsv_end < group_first_block))
BUG();
ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal,
- &my_rsv->rsv_window);
+ &num, &my_rsv->rsv_window);
if (ret >= 0) {
- my_rsv->rsv_alloc_hit++;
+ my_rsv->rsv_alloc_hit += num;
+ *count = num;
break; /* succeed */
}
+ num = *count;
}
out:
if (ret >= 0) {
@@ -1154,8 +1200,8 @@ int ext3_should_retry_alloc(struct super_block *sb, int *retries)
* bitmap, and then for any free bit if that fails.
* This function also updates quota and i_blocks field.
*/
-int ext3_new_block(handle_t *handle, struct inode *inode,
- unsigned long goal, int *errp)
+int ext3_new_blocks(handle_t *handle, struct inode *inode,
+ unsigned long goal, unsigned long *count, int *errp)
{
struct buffer_head *bitmap_bh = NULL;
struct buffer_head *gdp_bh;
@@ -1178,6 +1224,7 @@ int ext3_new_block(handle_t *handle, struct inode *inode,
static int goal_hits, goal_attempts;
#endif
unsigned long ngroups;
+ unsigned long num = *count;
*errp = -ENOSPC;
sb = inode->i_sb;
@@ -1189,7 +1236,7 @@ int ext3_new_block(handle_t *handle, struct inode *inode,
/*
* Check quota for allocation of this block.
*/
- if (DQUOT_ALLOC_BLOCK(inode, 1)) {
+ if (DQUOT_ALLOC_BLOCK(inode, num)) {
*errp = -EDQUOT;
return 0;
}
@@ -1244,7 +1291,7 @@ retry:
if (!bitmap_bh)
goto io_error;
ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no,
- bitmap_bh, ret_block, my_rsv, &fatal);
+ bitmap_bh, ret_block, my_rsv, &num, &fatal);
if (fatal)
goto out;
if (ret_block >= 0)
@@ -1281,7 +1328,7 @@ retry:
if (!bitmap_bh)
goto io_error;
ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no,
- bitmap_bh, -1, my_rsv, &fatal);
+ bitmap_bh, -1, my_rsv, &num, &fatal);
if (fatal)
goto out;
if (ret_block >= 0)
@@ -1316,13 +1363,15 @@ allocated:
target_block = ret_block + group_no * EXT3_BLOCKS_PER_GROUP(sb)
+ le32_to_cpu(es->s_first_data_block);
- if (target_block == le32_to_cpu(gdp->bg_block_bitmap) ||
- target_block == le32_to_cpu(gdp->bg_inode_bitmap) ||
+ if (in_range(le32_to_cpu(gdp->bg_block_bitmap), target_block, num) ||
+ in_range(le32_to_cpu(gdp->bg_inode_bitmap), target_block, num) ||
in_range(target_block, le32_to_cpu(gdp->bg_inode_table),
+ EXT3_SB(sb)->s_itb_per_group) ||
+ in_range(target_block + num - 1, le32_to_cpu(gdp->bg_inode_table),
EXT3_SB(sb)->s_itb_per_group))
ext3_error(sb, "ext3_new_block",
"Allocating block in system zone - "
- "block = %u", target_block);
+ "blocks from %u, length %lu", target_block, num);
performed_allocation = 1;
@@ -1341,10 +1390,14 @@ allocated:
jbd_lock_bh_state(bitmap_bh);
spin_lock(sb_bgl_lock(sbi, group_no));
if (buffer_jbd(bitmap_bh) && bh2jh(bitmap_bh)->b_committed_data) {
- if (ext3_test_bit(ret_block,
- bh2jh(bitmap_bh)->b_committed_data)) {
- printk("%s: block was unexpectedly set in "
- "b_committed_data\n", __FUNCTION__);
+ int i;
+
+ for (i = 0; i < num; i++) {
+ if (ext3_test_bit(ret_block,
+ bh2jh(bitmap_bh)->b_committed_data)) {
+ printk("%s: block was unexpectedly set in "
+ "b_committed_data\n", __FUNCTION__);
+ }
}
}
ext3_debug("found bit %d\n", ret_block);
@@ -1355,7 +1408,7 @@ allocated:
/* ret_block was blockgroup-relative. Now it becomes fs-relative */
ret_block = target_block;
- if (ret_block >= le32_to_cpu(es->s_blocks_count)) {
+ if (ret_block + num - 1 >= le32_to_cpu(es->s_blocks_count)) {
ext3_error(sb, "ext3_new_block",
"block(%d) >= blocks count(%d) - "
"block_group = %d, es == %p ", ret_block,
@@ -1373,9 +1426,9 @@ allocated:
spin_lock(sb_bgl_lock(sbi, group_no));
gdp->bg_free_blocks_count =
- cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - 1);
+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - num);
spin_unlock(sb_bgl_lock(sbi, group_no));
- percpu_counter_mod(&sbi->s_freeblocks_counter, -1);
+ percpu_counter_mod(&sbi->s_freeblocks_counter, -num);
BUFFER_TRACE(gdp_bh, "journal_dirty_metadata for group descriptor");
err = ext3_journal_dirty_metadata(handle, gdp_bh);
@@ -1388,6 +1441,8 @@ allocated:
*errp = 0;
brelse(bitmap_bh);
+ DQUOT_FREE_BLOCK(inode, *count-num);
+ *count = num;
return ret_block;
io_error:
@@ -1401,11 +1456,19 @@ out:
* Undo the block allocation
*/
if (!performed_allocation)
- DQUOT_FREE_BLOCK(inode, 1);
+ DQUOT_FREE_BLOCK(inode, *count);
brelse(bitmap_bh);
return 0;
}
+int ext3_new_block(handle_t *handle, struct inode *inode,
+ unsigned long goal, int *errp)
+{
+ unsigned long count = 1;
+
+ return ext3_new_blocks(handle, inode, goal, &count, errp);
+}
+
unsigned long ext3_count_free_blocks(struct super_block *sb)
{
unsigned long desc_count;
diff --git a/fs/ext3/bitmap.c b/fs/ext3/bitmap.c
index cb16b4c5d5d..ce4f82b9e52 100644
--- a/fs/ext3/bitmap.c
+++ b/fs/ext3/bitmap.c
@@ -7,11 +7,11 @@
* Universite Pierre et Marie Curie (Paris VI)
*/
-#ifdef EXT3FS_DEBUG
-
#include <linux/buffer_head.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
-#include "ext3_fs.h"
+#ifdef EXT3FS_DEBUG
static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index 773459164bb..f37528ed222 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -39,7 +39,7 @@ static int ext3_dx_readdir(struct file * filp,
static int ext3_release_dir (struct inode * inode,
struct file * filp);
-struct file_operations ext3_dir_operations = {
+const struct file_operations ext3_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = ext3_readdir, /* we take BKL. needed?*/
@@ -131,8 +131,9 @@ static int ext3_readdir(struct file * filp,
struct buffer_head *bh = NULL;
map_bh.b_state = 0;
- err = ext3_get_block_handle(NULL, inode, blk, &map_bh, 0, 0);
- if (!err) {
+ err = ext3_get_blocks_handle(NULL, inode, blk, 1,
+ &map_bh, 0, 0);
+ if (err > 0) {
page_cache_readahead(sb->s_bdev->bd_inode->i_mapping,
&filp->f_ra,
filp,
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 59098ea5671..783a796220b 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -105,7 +105,7 @@ force_commit:
return ret;
}
-struct file_operations ext3_file_operations = {
+const struct file_operations ext3_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 2c361377e0a..48ae0339af1 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -44,16 +44,16 @@ static int ext3_writepage_trans_blocks(struct inode *inode);
/*
* Test whether an inode is a fast symlink.
*/
-static inline int ext3_inode_is_fast_symlink(struct inode *inode)
+static int ext3_inode_is_fast_symlink(struct inode *inode)
{
int ea_blocks = EXT3_I(inode)->i_file_acl ?
(inode->i_sb->s_blocksize >> 9) : 0;
- return (S_ISLNK(inode->i_mode) &&
- inode->i_blocks - ea_blocks == 0);
+ return (S_ISLNK(inode->i_mode) && inode->i_blocks - ea_blocks == 0);
}
-/* The ext3 forget function must perform a revoke if we are freeing data
+/*
+ * The ext3 forget function must perform a revoke if we are freeing data
* which has been journaled. Metadata (eg. indirect blocks) must be
* revoked in all cases.
*
@@ -61,10 +61,8 @@ static inline int ext3_inode_is_fast_symlink(struct inode *inode)
* but there may still be a record of it in the journal, and that record
* still needs to be revoked.
*/
-
-int ext3_forget(handle_t *handle, int is_metadata,
- struct inode *inode, struct buffer_head *bh,
- int blocknr)
+int ext3_forget(handle_t *handle, int is_metadata, struct inode *inode,
+ struct buffer_head *bh, int blocknr)
{
int err;
@@ -104,10 +102,9 @@ int ext3_forget(handle_t *handle, int is_metadata,
}
/*
- * Work out how many blocks we need to progress with the next chunk of a
+ * Work out how many blocks we need to proceed with the next chunk of a
* truncate transaction.
*/
-
static unsigned long blocks_for_truncate(struct inode *inode)
{
unsigned long needed;
@@ -141,7 +138,6 @@ static unsigned long blocks_for_truncate(struct inode *inode)
* extend fails, we need to propagate the failure up and restart the
* transaction in the top-level truncate loop. --sct
*/
-
static handle_t *start_transaction(struct inode *inode)
{
handle_t *result;
@@ -194,9 +190,11 @@ void ext3_delete_inode (struct inode * inode)
handle = start_transaction(inode);
if (IS_ERR(handle)) {
- /* If we're going to skip the normal cleanup, we still
- * need to make sure that the in-core orphan linked list
- * is properly cleaned up. */
+ /*
+ * If we're going to skip the normal cleanup, we still need to
+ * make sure that the in-core orphan linked list is properly
+ * cleaned up.
+ */
ext3_orphan_del(NULL, inode);
goto no_delete;
}
@@ -235,16 +233,6 @@ no_delete:
clear_inode(inode); /* We must guarantee clearing of inode... */
}
-static int ext3_alloc_block (handle_t *handle,
- struct inode * inode, unsigned long goal, int *err)
-{
- unsigned long result;
-
- result = ext3_new_block(handle, inode, goal, err);
- return result;
-}
-
-
typedef struct {
__le32 *p;
__le32 key;
@@ -257,7 +245,7 @@ static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v)
p->bh = bh;
}
-static inline int verify_chain(Indirect *from, Indirect *to)
+static int verify_chain(Indirect *from, Indirect *to)
{
while (from <= to && from->key == *from->p)
from++;
@@ -327,10 +315,10 @@ static int ext3_block_to_path(struct inode *inode,
offsets[n++] = i_block & (ptrs - 1);
final = ptrs;
} else {
- ext3_warning (inode->i_sb, "ext3_block_to_path", "block > big");
+ ext3_warning(inode->i_sb, "ext3_block_to_path", "block > big");
}
if (boundary)
- *boundary = (i_block & (ptrs - 1)) == (final - 1);
+ *boundary = final - 1 - (i_block & (ptrs - 1));
return n;
}
@@ -419,7 +407,6 @@ no_block:
*
* Caller must make sure that @ind is valid and will stay that way.
*/
-
static unsigned long ext3_find_near(struct inode *inode, Indirect *ind)
{
struct ext3_inode_info *ei = EXT3_I(inode);
@@ -429,17 +416,18 @@ static unsigned long ext3_find_near(struct inode *inode, Indirect *ind)
unsigned long colour;
/* Try to find previous block */
- for (p = ind->p - 1; p >= start; p--)
+ for (p = ind->p - 1; p >= start; p--) {
if (*p)
return le32_to_cpu(*p);
+ }
/* No such thing, so let's try location of indirect block */
if (ind->bh)
return ind->bh->b_blocknr;
/*
- * It is going to be refered from inode itself? OK, just put it into
- * the same cylinder group then.
+ * It is going to be referred to from the inode itself? OK, just put it
+ * into the same cylinder group then.
*/
bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
@@ -463,7 +451,9 @@ static unsigned long ext3_find_near(struct inode *inode, Indirect *ind)
static unsigned long ext3_find_goal(struct inode *inode, long block,
Indirect chain[4], Indirect *partial)
{
- struct ext3_block_alloc_info *block_i = EXT3_I(inode)->i_block_alloc_info;
+ struct ext3_block_alloc_info *block_i;
+
+ block_i = EXT3_I(inode)->i_block_alloc_info;
/*
* try the heuristic for sequential allocation,
@@ -478,13 +468,113 @@ static unsigned long ext3_find_goal(struct inode *inode, long block,
}
/**
+ * ext3_blks_to_allocate: Look up the block map and count the number
+ * of direct blocks need to be allocated for the given branch.
+ *
+ * @branch: chain of indirect blocks
+ * @k: number of blocks need for indirect blocks
+ * @blks: number of data blocks to be mapped.
+ * @blocks_to_boundary: the offset in the indirect block
+ *
+ * return the total number of blocks to be allocate, including the
+ * direct and indirect blocks.
+ */
+static int ext3_blks_to_allocate(Indirect *branch, int k, unsigned long blks,
+ int blocks_to_boundary)
+{
+ unsigned long count = 0;
+
+ /*
+ * Simple case, [t,d]Indirect block(s) has not allocated yet
+ * then it's clear blocks on that path have not allocated
+ */
+ if (k > 0) {
+ /* right now we don't handle cross boundary allocation */
+ if (blks < blocks_to_boundary + 1)
+ count += blks;
+ else
+ count += blocks_to_boundary + 1;
+ return count;
+ }
+
+ count++;
+ while (count < blks && count <= blocks_to_boundary &&
+ le32_to_cpu(*(branch[0].p + count)) == 0) {
+ count++;
+ }
+ return count;
+}
+
+/**
+ * ext3_alloc_blocks: multiple allocate blocks needed for a branch
+ * @indirect_blks: the number of blocks need to allocate for indirect
+ * blocks
+ *
+ * @new_blocks: on return it will store the new block numbers for
+ * the indirect blocks(if needed) and the first direct block,
+ * @blks: on return it will store the total number of allocated
+ * direct blocks
+ */
+static int ext3_alloc_blocks(handle_t *handle, struct inode *inode,
+ unsigned long goal, int indirect_blks, int blks,
+ unsigned long long new_blocks[4], int *err)
+{
+ int target, i;
+ unsigned long count = 0;
+ int index = 0;
+ unsigned long current_block = 0;
+ int ret = 0;
+
+ /*
+ * Here we try to allocate the requested multiple blocks at once,
+ * on a best-effort basis.
+ * To build a branch, we should allocate blocks for
+ * the indirect blocks(if not allocated yet), and at least
+ * the first direct block of this branch. That's the
+ * minimum number of blocks need to allocate(required)
+ */
+ target = blks + indirect_blks;
+
+ while (1) {
+ count = target;
+ /* allocating blocks for indirect blocks and direct blocks */
+ current_block = ext3_new_blocks(handle,inode,goal,&count,err);
+ if (*err)
+ goto failed_out;
+
+ target -= count;
+ /* allocate blocks for indirect blocks */
+ while (index < indirect_blks && count) {
+ new_blocks[index++] = current_block++;
+ count--;
+ }
+
+ if (count > 0)
+ break;
+ }
+
+ /* save the new block number for the first direct block */
+ new_blocks[index] = current_block;
+
+ /* total number of blocks allocated for direct blocks */
+ ret = count;
+ *err = 0;
+ return ret;
+failed_out:
+ for (i = 0; i <index; i++)
+ ext3_free_blocks(handle, inode, new_blocks[i], 1);
+ return ret;
+}
+
+/**
* ext3_alloc_branch - allocate and set up a chain of blocks.
* @inode: owner
- * @num: depth of the chain (number of blocks to allocate)
+ * @indirect_blks: number of allocated indirect blocks
+ * @blks: number of allocated direct blocks
* @offsets: offsets (in the blocks) to store the pointers to next.
* @branch: place to store the chain in.
*
- * This function allocates @num blocks, zeroes out all but the last one,
+ * This function allocates blocks, zeroes out all but the last one,
* links them into chain and (if we are synchronous) writes them to disk.
* In other words, it prepares a branch that can be spliced onto the
* inode. It stores the information about that chain in the branch[], in
@@ -501,97 +591,106 @@ static unsigned long ext3_find_goal(struct inode *inode, long block,
* ext3_alloc_block() (normally -ENOSPC). Otherwise we set the chain
* as described above and return 0.
*/
-
static int ext3_alloc_branch(handle_t *handle, struct inode *inode,
- int num,
- unsigned long goal,
- int *offsets,
- Indirect *branch)
+ int indirect_blks, int *blks, unsigned long goal,
+ int *offsets, Indirect *branch)
{
int blocksize = inode->i_sb->s_blocksize;
- int n = 0, keys = 0;
+ int i, n = 0;
int err = 0;
- int i;
- int parent = ext3_alloc_block(handle, inode, goal, &err);
-
- branch[0].key = cpu_to_le32(parent);
- if (parent) {
- for (n = 1; n < num; n++) {
- struct buffer_head *bh;
- /* Allocate the next block */
- int nr = ext3_alloc_block(handle, inode, parent, &err);
- if (!nr)
- break;
- branch[n].key = cpu_to_le32(nr);
+ struct buffer_head *bh;
+ int num;
+ unsigned long long new_blocks[4];
+ unsigned long long current_block;
- /*
- * Get buffer_head for parent block, zero it out
- * and set the pointer to new one, then send
- * parent to disk.
- */
- bh = sb_getblk(inode->i_sb, parent);
- if (!bh)
- break;
- keys = n+1;
- branch[n].bh = bh;
- lock_buffer(bh);
- BUFFER_TRACE(bh, "call get_create_access");
- err = ext3_journal_get_create_access(handle, bh);
- if (err) {
- unlock_buffer(bh);
- brelse(bh);
- break;
- }
+ num = ext3_alloc_blocks(handle, inode, goal, indirect_blks,
+ *blks, new_blocks, &err);
+ if (err)
+ return err;
- memset(bh->b_data, 0, blocksize);
- branch[n].p = (__le32*) bh->b_data + offsets[n];
- *branch[n].p = branch[n].key;
- BUFFER_TRACE(bh, "marking uptodate");
- set_buffer_uptodate(bh);
+ branch[0].key = cpu_to_le32(new_blocks[0]);
+ /*
+ * metadata blocks and data blocks are allocated.
+ */
+ for (n = 1; n <= indirect_blks; n++) {
+ /*
+ * Get buffer_head for parent block, zero it out
+ * and set the pointer to new one, then send
+ * parent to disk.
+ */
+ bh = sb_getblk(inode->i_sb, new_blocks[n-1]);
+ branch[n].bh = bh;
+ lock_buffer(bh);
+ BUFFER_TRACE(bh, "call get_create_access");
+ err = ext3_journal_get_create_access(handle, bh);
+ if (err) {
unlock_buffer(bh);
+ brelse(bh);
+ goto failed;
+ }
- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
- err = ext3_journal_dirty_metadata(handle, bh);
- if (err)
- break;
-
- parent = nr;
+ memset(bh->b_data, 0, blocksize);
+ branch[n].p = (__le32 *) bh->b_data + offsets[n];
+ branch[n].key = cpu_to_le32(new_blocks[n]);
+ *branch[n].p = branch[n].key;
+ if ( n == indirect_blks) {
+ current_block = new_blocks[n];
+ /*
+ * End of chain, update the last new metablock of
+ * the chain to point to the new allocated
+ * data blocks numbers
+ */
+ for (i=1; i < num; i++)
+ *(branch[n].p + i) = cpu_to_le32(++current_block);
}
- }
- if (n == num)
- return 0;
+ BUFFER_TRACE(bh, "marking uptodate");
+ set_buffer_uptodate(bh);
+ unlock_buffer(bh);
+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
+ err = ext3_journal_dirty_metadata(handle, bh);
+ if (err)
+ goto failed;
+ }
+ *blks = num;
+ return err;
+failed:
/* Allocation failed, free what we already allocated */
- for (i = 1; i < keys; i++) {
+ for (i = 1; i <= n ; i++) {
BUFFER_TRACE(branch[i].bh, "call journal_forget");
ext3_journal_forget(handle, branch[i].bh);
}
- for (i = 0; i < keys; i++)
- ext3_free_blocks(handle, inode, le32_to_cpu(branch[i].key), 1);
+ for (i = 0; i <indirect_blks; i++)
+ ext3_free_blocks(handle, inode, new_blocks[i], 1);
+
+ ext3_free_blocks(handle, inode, new_blocks[i], num);
+
return err;
}
/**
- * ext3_splice_branch - splice the allocated branch onto inode.
- * @inode: owner
- * @block: (logical) number of block we are adding
- * @chain: chain of indirect blocks (with a missing link - see
- * ext3_alloc_branch)
- * @where: location of missing link
- * @num: number of blocks we are adding
- *
- * This function fills the missing link and does all housekeeping needed in
- * inode (->i_blocks, etc.). In case of success we end up with the full
- * chain to new block and return 0.
+ * ext3_splice_branch - splice the allocated branch onto inode.
+ * @inode: owner
+ * @block: (logical) number of block we are adding
+ * @chain: chain of indirect blocks (with a missing link - see
+ * ext3_alloc_branch)
+ * @where: location of missing link
+ * @num: number of indirect blocks we are adding
+ * @blks: number of direct blocks we are adding
+ *
+ * This function fills the missing link and does all housekeeping needed in
+ * inode (->i_blocks, etc.). In case of success we end up with the full
+ * chain to new block and return 0.
*/
-
-static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block,
- Indirect chain[4], Indirect *where, int num)
+static int ext3_splice_branch(handle_t *handle, struct inode *inode,
+ long block, Indirect *where, int num, int blks)
{
int i;
int err = 0;
- struct ext3_block_alloc_info *block_i = EXT3_I(inode)->i_block_alloc_info;
+ struct ext3_block_alloc_info *block_i;
+ unsigned long current_block;
+ block_i = EXT3_I(inode)->i_block_alloc_info;
/*
* If we're splicing into a [td]indirect block (as opposed to the
* inode) then we need to get write access to the [td]indirect block
@@ -608,13 +707,24 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block,
*where->p = where->key;
/*
+ * Update the host buffer_head or inode to point to more just allocated
+ * direct blocks blocks
+ */
+ if (num == 0 && blks > 1) {
+ current_block = le32_to_cpu(where->key + 1);
+ for (i = 1; i < blks; i++)
+ *(where->p + i ) = cpu_to_le32(current_block++);
+ }
+
+ /*
* update the most recently allocated logical & physical block
* in i_block_alloc_info, to assist find the proper goal block for next
* allocation
*/
if (block_i) {
- block_i->last_alloc_logical_block = block;
- block_i->last_alloc_physical_block = le32_to_cpu(where[num-1].key);
+ block_i->last_alloc_logical_block = block + blks - 1;
+ block_i->last_alloc_physical_block =
+ le32_to_cpu(where[num].key + blks - 1);
}
/* We are done with atomic stuff, now do the rest of housekeeping */
@@ -625,7 +735,7 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block,
/* had we spliced it onto indirect block? */
if (where->bh) {
/*
- * akpm: If we spliced it onto an indirect block, we haven't
+ * If we spliced it onto an indirect block, we haven't
* altered the inode. Note however that if it is being spliced
* onto an indirect block at the very end of the file (the
* file is growing) then we *will* alter the inode to reflect
@@ -647,10 +757,13 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block,
return err;
err_out:
- for (i = 1; i < num; i++) {
+ for (i = 1; i <= num; i++) {
BUFFER_TRACE(where[i].bh, "call journal_forget");
ext3_journal_forget(handle, where[i].bh);
+ ext3_free_blocks(handle,inode,le32_to_cpu(where[i-1].key),1);
}
+ ext3_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks);
+
return err;
}
@@ -666,26 +779,33 @@ err_out:
* allocations is needed - we simply release blocks and do not touch anything
* reachable from inode.
*
- * akpm: `handle' can be NULL if create == 0.
+ * `handle' can be NULL if create == 0.
*
* The BKL may not be held on entry here. Be sure to take it early.
+ * return > 0, # of blocks mapped or allocated.
+ * return = 0, if plain lookup failed.
+ * return < 0, error case.
*/
-
-int
-ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
- struct buffer_head *bh_result, int create, int extend_disksize)
+int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
+ sector_t iblock, unsigned long maxblocks,
+ struct buffer_head *bh_result,
+ int create, int extend_disksize)
{
int err = -EIO;
int offsets[4];
Indirect chain[4];
Indirect *partial;
unsigned long goal;
- int left;
- int boundary = 0;
- const int depth = ext3_block_to_path(inode, iblock, offsets, &boundary);
+ int indirect_blks;
+ int blocks_to_boundary = 0;
+ int depth;
struct ext3_inode_info *ei = EXT3_I(inode);
+ int count = 0;
+ unsigned long first_block = 0;
+
J_ASSERT(handle != NULL || create == 0);
+ depth = ext3_block_to_path(inode,iblock,offsets,&blocks_to_boundary);
if (depth == 0)
goto out;
@@ -694,8 +814,31 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
/* Simplest case - block found, no allocation needed */
if (!partial) {
+ first_block = chain[depth - 1].key;
clear_buffer_new(bh_result);
- goto got_it;
+ count++;
+ /*map more blocks*/
+ while (count < maxblocks && count <= blocks_to_boundary) {
+ if (!verify_chain(chain, partial)) {
+ /*
+ * Indirect block might be removed by
+ * truncate while we were reading it.
+ * Handling of that case: forget what we've
+ * got now. Flag the err as EAGAIN, so it
+ * will reread.
+ */
+ err = -EAGAIN;
+ count = 0;
+ break;
+ }
+ if (le32_to_cpu(*(chain[depth-1].p+count) ==
+ (first_block + count)))
+ count++;
+ else
+ break;
+ }
+ if (err != -EAGAIN)
+ goto got_it;
}
/* Next simple case - plain lookup or failed read of indirect block */
@@ -723,6 +866,7 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
}
partial = ext3_get_branch(inode, depth, offsets, chain, &err);
if (!partial) {
+ count++;
mutex_unlock(&ei->truncate_mutex);
if (err)
goto cleanup;
@@ -740,12 +884,19 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
goal = ext3_find_goal(inode, iblock, chain, partial);
- left = (chain + depth) - partial;
+ /* the number of blocks need to allocate for [d,t]indirect blocks */
+ indirect_blks = (chain + depth) - partial - 1;
/*
+ * Next look up the indirect map to count the totoal number of
+ * direct blocks to allocate for this branch.
+ */
+ count = ext3_blks_to_allocate(partial, indirect_blks,
+ maxblocks, blocks_to_boundary);
+ /*
* Block out ext3_truncate while we alter the tree
*/
- err = ext3_alloc_branch(handle, inode, left, goal,
+ err = ext3_alloc_branch(handle, inode, indirect_blks, &count, goal,
offsets + (partial - chain), partial);
/*
@@ -756,8 +907,8 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
* may need to return -EAGAIN upwards in the worst case. --sct
*/
if (!err)
- err = ext3_splice_branch(handle, inode, iblock, chain,
- partial, left);
+ err = ext3_splice_branch(handle, inode, iblock,
+ partial, indirect_blks, count);
/*
* i_disksize growing is protected by truncate_mutex. Don't forget to
* protect it if you're about to implement concurrent
@@ -772,8 +923,9 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
set_buffer_new(bh_result);
got_it:
map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
- if (boundary)
+ if (blocks_to_boundary == 0)
set_buffer_boundary(bh_result);
+ err = count;
/* Clean up and exit */
partial = chain + depth - 1; /* the whole chain */
cleanup:
@@ -787,34 +939,21 @@ out:
return err;
}
-static int ext3_get_block(struct inode *inode, sector_t iblock,
- struct buffer_head *bh_result, int create)
-{
- handle_t *handle = NULL;
- int ret;
-
- if (create) {
- handle = ext3_journal_current_handle();
- J_ASSERT(handle != 0);
- }
- ret = ext3_get_block_handle(handle, inode, iblock,
- bh_result, create, 1);
- return ret;
-}
-
#define DIO_CREDITS (EXT3_RESERVE_TRANS_BLOCKS + 32)
-static int
-ext3_direct_io_get_blocks(struct inode *inode, sector_t iblock,
- unsigned long max_blocks, struct buffer_head *bh_result,
- int create)
+static int ext3_get_block(struct inode *inode, sector_t iblock,
+ struct buffer_head *bh_result, int create)
{
handle_t *handle = journal_current_handle();
int ret = 0;
+ unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
- if (!handle)
+ if (!create)
goto get_block; /* A read */
+ if (max_blocks == 1)
+ goto get_block; /* A single block get */
+
if (handle->h_transaction->t_state == T_LOCKED) {
/*
* Huge direct-io writes can hold off commits for long
@@ -841,18 +980,22 @@ ext3_direct_io_get_blocks(struct inode *inode, sector_t iblock,
}
get_block:
- if (ret == 0)
- ret = ext3_get_block_handle(handle, inode, iblock,
- bh_result, create, 0);
- bh_result->b_size = (1 << inode->i_blkbits);
+ if (ret == 0) {
+ ret = ext3_get_blocks_handle(handle, inode, iblock,
+ max_blocks, bh_result, create, 0);
+ if (ret > 0) {
+ bh_result->b_size = (ret << inode->i_blkbits);
+ ret = 0;
+ }
+ }
return ret;
}
/*
* `handle' can be NULL if create is zero
*/
-struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode,
- long block, int create, int * errp)
+struct buffer_head *ext3_getblk(handle_t *handle, struct inode *inode,
+ long block, int create, int *errp)
{
struct buffer_head dummy;
int fatal = 0, err;
@@ -862,8 +1005,16 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode,
dummy.b_state = 0;
dummy.b_blocknr = -1000;
buffer_trace_init(&dummy.b_history);
- *errp = ext3_get_block_handle(handle, inode, block, &dummy, create, 1);
- if (!*errp && buffer_mapped(&dummy)) {
+ err = ext3_get_blocks_handle(handle, inode, block, 1,
+ &dummy, create, 1);
+ if (err == 1) {
+ err = 0;
+ } else if (err >= 0) {
+ WARN_ON(1);
+ err = -EIO;
+ }
+ *errp = err;
+ if (!err && buffer_mapped(&dummy)) {
struct buffer_head *bh;
bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
if (!bh) {
@@ -874,17 +1025,18 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode,
J_ASSERT(create != 0);
J_ASSERT(handle != 0);
- /* Now that we do not always journal data, we
- should keep in mind whether this should
- always journal the new buffer as metadata.
- For now, regular file writes use
- ext3_get_block instead, so it's not a
- problem. */
+ /*
+ * Now that we do not always journal data, we should
+ * keep in mind whether this should always journal the
+ * new buffer as metadata. For now, regular file
+ * writes use ext3_get_block instead, so it's not a
+ * problem.
+ */
lock_buffer(bh);
BUFFER_TRACE(bh, "call get_create_access");
fatal = ext3_journal_get_create_access(handle, bh);
if (!fatal && !buffer_uptodate(bh)) {
- memset(bh->b_data, 0, inode->i_sb->s_blocksize);
+ memset(bh->b_data,0,inode->i_sb->s_blocksize);
set_buffer_uptodate(bh);
}
unlock_buffer(bh);
@@ -906,7 +1058,7 @@ err:
return NULL;
}
-struct buffer_head *ext3_bread(handle_t *handle, struct inode * inode,
+struct buffer_head *ext3_bread(handle_t *handle, struct inode *inode,
int block, int create, int *err)
{
struct buffer_head * bh;
@@ -982,9 +1134,8 @@ static int walk_page_buffers( handle_t *handle,
* is elevated. We'll still have enough credits for the tiny quotafile
* write.
*/
-
-static int do_journal_get_write_access(handle_t *handle,
- struct buffer_head *bh)
+static int do_journal_get_write_access(handle_t *handle,
+ struct buffer_head *bh)
{
if (!buffer_mapped(bh) || buffer_freed(bh))
return 0;
@@ -1025,8 +1176,7 @@ out:
return ret;
}
-int
-ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
+int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
{
int err = journal_dirty_data(handle, bh);
if (err)
@@ -1051,7 +1201,6 @@ static int commit_write_fn(handle_t *handle, struct buffer_head *bh)
* ext3 never places buffers on inode->i_mapping->private_list. metadata
* buffers are managed internally.
*/
-
static int ext3_ordered_commit_write(struct file *file, struct page *page,
unsigned from, unsigned to)
{
@@ -1261,7 +1410,7 @@ static int journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh)
* we don't need to open a transaction here.
*/
static int ext3_ordered_writepage(struct page *page,
- struct writeback_control *wbc)
+ struct writeback_control *wbc)
{
struct inode *inode = page->mapping->host;
struct buffer_head *page_bufs;
@@ -1430,7 +1579,7 @@ ext3_readpages(struct file *file, struct address_space *mapping,
return mpage_readpages(mapping, pages, nr_pages, ext3_get_block);
}
-static int ext3_invalidatepage(struct page *page, unsigned long offset)
+static void ext3_invalidatepage(struct page *page, unsigned long offset)
{
journal_t *journal = EXT3_JOURNAL(page->mapping->host);
@@ -1440,7 +1589,7 @@ static int ext3_invalidatepage(struct page *page, unsigned long offset)
if (offset == 0)
ClearPageChecked(page);
- return journal_invalidatepage(journal, page, offset);
+ journal_invalidatepage(journal, page, offset);
}
static int ext3_releasepage(struct page *page, gfp_t wait)
@@ -1492,11 +1641,10 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
offset, nr_segs,
- ext3_direct_io_get_blocks, NULL);
+ ext3_get_block, NULL);
/*
- * Reacquire the handle: ext3_direct_io_get_block() can restart the
- * transaction
+ * Reacquire the handle: ext3_get_block() can restart the transaction
*/
handle = journal_current_handle();
@@ -1752,11 +1900,8 @@ static inline int all_zeroes(__le32 *p, __le32 *q)
* c) free the subtrees growing from the inode past the @chain[0].
* (no partially truncated stuff there). */
-static Indirect *ext3_find_shared(struct inode *inode,
- int depth,
- int offsets[4],
- Indirect chain[4],
- __le32 *top)
+static Indirect *ext3_find_shared(struct inode *inode, int depth,
+ int offsets[4], Indirect chain[4], __le32 *top)
{
Indirect *partial, *p;
int k, err;
@@ -1795,8 +1940,7 @@ static Indirect *ext3_find_shared(struct inode *inode,
}
/* Writer: end */
- while(partial > p)
- {
+ while(partial > p) {
brelse(partial->bh);
partial--;
}
@@ -1812,10 +1956,9 @@ no_top:
* We release `count' blocks on disk, but (last - first) may be greater
* than `count' because there can be holes in there.
*/
-static void
-ext3_clear_blocks(handle_t *handle, struct inode *inode, struct buffer_head *bh,
- unsigned long block_to_free, unsigned long count,
- __le32 *first, __le32 *last)
+static void ext3_clear_blocks(handle_t *handle, struct inode *inode,
+ struct buffer_head *bh, unsigned long block_to_free,
+ unsigned long count, __le32 *first, __le32 *last)
{
__le32 *p;
if (try_to_extend_transaction(handle, inode)) {
@@ -2076,8 +2219,7 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
* that's fine - as long as they are linked from the inode, the post-crash
* ext3_truncate() run will find them and release them.
*/
-
-void ext3_truncate(struct inode * inode)
+void ext3_truncate(struct inode *inode)
{
handle_t *handle;
struct ext3_inode_info *ei = EXT3_I(inode);
@@ -2201,29 +2343,26 @@ void ext3_truncate(struct inode * inode)
do_indirects:
/* Kill the remaining (whole) subtrees */
switch (offsets[0]) {
- default:
- nr = i_data[EXT3_IND_BLOCK];
- if (nr) {
- ext3_free_branches(handle, inode, NULL,
- &nr, &nr+1, 1);
- i_data[EXT3_IND_BLOCK] = 0;
- }
- case EXT3_IND_BLOCK:
- nr = i_data[EXT3_DIND_BLOCK];
- if (nr) {
- ext3_free_branches(handle, inode, NULL,
- &nr, &nr+1, 2);
- i_data[EXT3_DIND_BLOCK] = 0;
- }
- case EXT3_DIND_BLOCK:
- nr = i_data[EXT3_TIND_BLOCK];
- if (nr) {
- ext3_free_branches(handle, inode, NULL,
- &nr, &nr+1, 3);
- i_data[EXT3_TIND_BLOCK] = 0;
- }
- case EXT3_TIND_BLOCK:
- ;
+ default:
+ nr = i_data[EXT3_IND_BLOCK];
+ if (nr) {
+ ext3_free_branches(handle, inode, NULL, &nr, &nr+1, 1);
+ i_data[EXT3_IND_BLOCK] = 0;
+ }
+ case EXT3_IND_BLOCK:
+ nr = i_data[EXT3_DIND_BLOCK];
+ if (nr) {
+ ext3_free_branches(handle, inode, NULL, &nr, &nr+1, 2);
+ i_data[EXT3_DIND_BLOCK] = 0;
+ }
+ case EXT3_DIND_BLOCK:
+ nr = i_data[EXT3_TIND_BLOCK];
+ if (nr) {
+ ext3_free_branches(handle, inode, NULL, &nr, &nr+1, 3);
+ i_data[EXT3_TIND_BLOCK] = 0;
+ }
+ case EXT3_TIND_BLOCK:
+ ;
}
ext3_discard_reservation(inode);
@@ -2232,8 +2371,10 @@ do_indirects:
inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
ext3_mark_inode_dirty(handle, inode);
- /* In a multi-transaction truncate, we only make the final
- * transaction synchronous */
+ /*
+ * In a multi-transaction truncate, we only make the final transaction
+ * synchronous
+ */
if (IS_SYNC(inode))
handle->h_sync = 1;
out_stop:
@@ -2259,20 +2400,16 @@ static unsigned long ext3_get_inode_block(struct super_block *sb,
struct ext3_group_desc * gdp;
- if ((ino != EXT3_ROOT_INO &&
- ino != EXT3_JOURNAL_INO &&
- ino != EXT3_RESIZE_INO &&
- ino < EXT3_FIRST_INO(sb)) ||
- ino > le32_to_cpu(
- EXT3_SB(sb)->s_es->s_inodes_count)) {
- ext3_error (sb, "ext3_get_inode_block",
+ if ((ino != EXT3_ROOT_INO && ino != EXT3_JOURNAL_INO &&
+ ino != EXT3_RESIZE_INO && ino < EXT3_FIRST_INO(sb)) ||
+ ino > le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count)) {
+ ext3_error(sb, "ext3_get_inode_block",
"bad inode number: %lu", ino);
return 0;
}
block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb);
if (block_group >= EXT3_SB(sb)->s_groups_count) {
- ext3_error (sb, "ext3_get_inode_block",
- "group >= groups count");
+ ext3_error(sb,"ext3_get_inode_block","group >= groups count");
return 0;
}
smp_rmb();
@@ -2285,7 +2422,7 @@ static unsigned long ext3_get_inode_block(struct super_block *sb,
return 0;
}
- gdp = (struct ext3_group_desc *) bh->b_data;
+ gdp = (struct ext3_group_desc *)bh->b_data;
/*
* Figure out the offset within the block group inode table
*/
@@ -2834,7 +2971,7 @@ err_out:
/*
- * akpm: how many blocks doth make a writepage()?
+ * How many blocks doth make a writepage()?
*
* With N blocks per page, it may be:
* N data blocks
@@ -2924,8 +3061,8 @@ ext3_reserve_inode_write(handle_t *handle, struct inode *inode,
}
/*
- * akpm: What we do here is to mark the in-core inode as clean
- * with respect to inode dirtiness (it may still be data-dirty).
+ * What we do here is to mark the in-core inode as clean with respect to inode
+ * dirtiness (it may still be data-dirty).
* This means that the in-core inode may be reaped by prune_icache
* without having to perform any I/O. This is a very good thing,
* because *any* task may call prune_icache - even ones which
@@ -2957,7 +3094,7 @@ int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode)
}
/*
- * akpm: ext3_dirty_inode() is called from __mark_inode_dirty()
+ * ext3_dirty_inode() is called from __mark_inode_dirty()
*
* We're really interested in the case where a file is being extended.
* i_size has been changed by generic_commit_write() and we thus need
@@ -2993,7 +3130,7 @@ out:
return;
}
-#ifdef AKPM
+#if 0
/*
* Bind an inode's backing buffer_head into this transaction, to prevent
* it from being flushed to disk early. Unlike
@@ -3001,8 +3138,7 @@ out:
* returns no iloc structure, so the caller needs to repeat the iloc
* lookup to mark the inode dirty later.
*/
-static inline int
-ext3_pin_inode(handle_t *handle, struct inode *inode)
+static int ext3_pin_inode(handle_t *handle, struct inode *inode)
{
struct ext3_iloc iloc;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 86e443182de..f8a5266ea1f 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1678,12 +1678,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
}
if (test_opt(sb, NOBH)) {
- if (sb->s_blocksize_bits != PAGE_CACHE_SHIFT) {
- printk(KERN_WARNING "EXT3-fs: Ignoring nobh option "
- "since filesystem blocksize doesn't match "
- "pagesize\n");
- clear_opt(sbi->s_mount_opt, NOBH);
- }
if (!(test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)) {
printk(KERN_WARNING "EXT3-fs: Ignoring nobh option - "
"its supported only with writeback mode\n");
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 4095bc149eb..698b85bb1dd 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -741,7 +741,7 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp,
return ret;
}
-struct file_operations fat_dir_operations = {
+const struct file_operations fat_dir_operations = {
.read = generic_read_dir,
.readdir = fat_readdir,
.ioctl = fat_dir_ioctl,
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 88aa1ae13f9..1ee25232e6a 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -112,7 +112,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
}
}
-struct file_operations fat_file_operations = {
+const struct file_operations fat_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 297300fe81c..c1ce284f8a9 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -101,11 +101,11 @@ static int __fat_get_blocks(struct inode *inode, sector_t iblock,
}
static int fat_get_blocks(struct inode *inode, sector_t iblock,
- unsigned long max_blocks,
struct buffer_head *bh_result, int create)
{
struct super_block *sb = inode->i_sb;
int err;
+ unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
err = __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create);
if (err)
@@ -1435,9 +1435,6 @@ out_fail:
EXPORT_SYMBOL_GPL(fat_fill_super);
-int __init fat_cache_init(void);
-void fat_cache_destroy(void);
-
static int __init init_fat_fs(void)
{
int err;
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 03c789560fb..2a2479196f9 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -412,7 +412,7 @@ out:
/* Table to convert sigio signal codes into poll band bitmaps */
-static long band_table[NSIGPOLL] = {
+static const long band_table[NSIGPOLL] = {
POLLIN | POLLRDNORM, /* POLL_IN */
POLLOUT | POLLWRNORM | POLLWRBAND, /* POLL_OUT */
POLLIN | POLLRDNORM | POLLMSG, /* POLL_MSG */
@@ -531,7 +531,7 @@ int send_sigurg(struct fown_struct *fown)
}
static DEFINE_RWLOCK(fasync_lock);
-static kmem_cache_t *fasync_cache;
+static kmem_cache_t *fasync_cache __read_mostly;
/*
* fasync_helper() is used by some character device drivers (mainly mice)
diff --git a/fs/fifo.c b/fs/fifo.c
index d13fcd3ec80..889f722ee36 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -145,6 +145,6 @@ err_nocleanup:
* is contain the open that then fills in the correct operations
* depending on the access mode of the file...
*/
-struct file_operations def_fifo_fops = {
+const struct file_operations def_fifo_fops = {
.open = fifo_open, /* will set read or write pipe_fops */
};
diff --git a/fs/file.c b/fs/file.c
index bbc74331473..55f4e702256 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -373,6 +373,6 @@ static void __devinit fdtable_defer_list_init(int cpu)
void __init files_defer_init(void)
{
int i;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
fdtable_defer_list_init(i);
}
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 927acf70c59..1cf1fe8466a 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -63,7 +63,7 @@ extern void vxfs_clear_inode(struct inode *);
/* vxfs_lookup.c */
extern struct inode_operations vxfs_dir_inode_ops;
-extern struct file_operations vxfs_dir_operations;
+extern const struct file_operations vxfs_dir_operations;
/* vxfs_olt.c */
extern int vxfs_read_olt(struct super_block *, u_long);
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 554eb455722..29cce456c7c 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -56,7 +56,7 @@ struct inode_operations vxfs_dir_inode_ops = {
.lookup = vxfs_lookup,
};
-struct file_operations vxfs_dir_operations = {
+const struct file_operations vxfs_dir_operations = {
.readdir = vxfs_readdir,
};
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 785c7213a54..f3fbe2d030f 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -381,8 +381,8 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
list_move(&inode->i_list, &sb->s_dirty);
}
spin_unlock(&inode_lock);
- cond_resched();
iput(inode);
+ cond_resched();
spin_lock(&inode_lock);
if (wbc->nr_to_write <= 0)
break;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 0c9a2ee54c9..23d1f52eb1b 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -922,7 +922,7 @@ static int fuse_dev_release(struct inode *inode, struct file *file)
return 0;
}
-struct file_operations fuse_dev_operations = {
+const struct file_operations fuse_dev_operations = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = fuse_dev_read,
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index c72a8a97935..256355b8025 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1170,7 +1170,7 @@ static struct inode_operations fuse_dir_inode_operations = {
.removexattr = fuse_removexattr,
};
-static struct file_operations fuse_dir_operations = {
+static const struct file_operations fuse_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = fuse_readdir,
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 6f05379b0a0..975f2697e86 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -12,7 +12,7 @@
#include <linux/slab.h>
#include <linux/kernel.h>
-static struct file_operations fuse_direct_io_file_operations;
+static const struct file_operations fuse_direct_io_file_operations;
static int fuse_send_open(struct inode *inode, struct file *file, int isdir,
struct fuse_open_out *outargp)
@@ -611,7 +611,7 @@ static int fuse_set_page_dirty(struct page *page)
return 0;
}
-static struct file_operations fuse_file_operations = {
+static const struct file_operations fuse_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
@@ -623,7 +623,7 @@ static struct file_operations fuse_file_operations = {
.sendfile = generic_file_sendfile,
};
-static struct file_operations fuse_direct_io_file_operations = {
+static const struct file_operations fuse_direct_io_file_operations = {
.llseek = generic_file_llseek,
.read = fuse_direct_read,
.write = fuse_direct_write,
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 4a83adfec96..a16a04fcf41 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -346,7 +346,7 @@ static inline u64 get_node_id(struct inode *inode)
}
/** Device operations */
-extern struct file_operations fuse_dev_operations;
+extern const struct file_operations fuse_dev_operations;
/**
* This is the single global spinlock which protects FUSE's structures
diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index a7a7d77f3fd..1e44dcfe49c 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -306,8 +306,7 @@ void hfs_bnode_unhash(struct hfs_bnode *node)
for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
*p && *p != node; p = &(*p)->next_hash)
;
- if (!*p)
- BUG();
+ BUG_ON(!*p);
*p = node->next_hash;
node->tree->node_hash_cnt--;
}
@@ -415,8 +414,7 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
spin_lock(&tree->hash_lock);
node = hfs_bnode_findhash(tree, num);
spin_unlock(&tree->hash_lock);
- if (node)
- BUG();
+ BUG_ON(node);
node = __hfs_bnode_create(tree, num);
if (!node)
return ERR_PTR(-ENOMEM);
@@ -459,8 +457,7 @@ void hfs_bnode_put(struct hfs_bnode *node)
dprint(DBG_BNODE_REFS, "put_node(%d:%d): %d\n",
node->tree->cnid, node->this, atomic_read(&node->refcnt));
- if (!atomic_read(&node->refcnt))
- BUG();
+ BUG_ON(!atomic_read(&node->refcnt));
if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
return;
for (i = 0; i < tree->pages_per_bnode; i++) {
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index 7bb11edd148..d20131ce4b9 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -36,8 +36,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
tree->inode = iget_locked(sb, id);
if (!tree->inode)
goto free_tree;
- if (!(tree->inode->i_state & I_NEW))
- BUG();
+ BUG_ON(!(tree->inode->i_state & I_NEW));
{
struct hfs_mdb *mdb = HFS_SB(sb)->mdb;
HFS_I(tree->inode)->flags = 0;
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index 534e5a7480e..7cd8cc03aea 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -313,7 +313,7 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
return res;
}
-struct file_operations hfs_dir_operations = {
+const struct file_operations hfs_dir_operations = {
.read = generic_read_dir,
.readdir = hfs_readdir,
.llseek = generic_file_llseek,
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 18ce47ab1b7..3ed8663a8db 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -169,7 +169,7 @@ extern int hfs_cat_move(u32, struct inode *, struct qstr *,
extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, struct qstr *);
/* dir.c */
-extern struct file_operations hfs_dir_operations;
+extern const struct file_operations hfs_dir_operations;
extern struct inode_operations hfs_dir_inode_operations;
/* extent.c */
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 39fd85b9b91..2d4ced22201 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -17,7 +17,7 @@
#include "hfs_fs.h"
#include "btree.h"
-static struct file_operations hfs_file_operations;
+static const struct file_operations hfs_file_operations;
static struct inode_operations hfs_file_inode_operations;
/*================ Variable-like macros ================*/
@@ -98,17 +98,6 @@ static int hfs_releasepage(struct page *page, gfp_t mask)
return res ? try_to_free_buffers(page) : 0;
}
-static int hfs_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks,
- struct buffer_head *bh_result, int create)
-{
- int ret;
-
- ret = hfs_get_block(inode, iblock, bh_result, create);
- if (!ret)
- bh_result->b_size = (1 << inode->i_blkbits);
- return ret;
-}
-
static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
const struct iovec *iov, loff_t offset, unsigned long nr_segs)
{
@@ -116,7 +105,7 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
- offset, nr_segs, hfs_get_blocks, NULL);
+ offset, nr_segs, hfs_get_block, NULL);
}
static int hfs_writepages(struct address_space *mapping,
@@ -612,7 +601,7 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
}
-static struct file_operations hfs_file_operations = {
+static const struct file_operations hfs_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 01a6fe3a395..1f9ece0de32 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -483,7 +483,7 @@ struct inode_operations hfsplus_dir_inode_operations = {
.rename = hfsplus_rename,
};
-struct file_operations hfsplus_dir_operations = {
+const struct file_operations hfsplus_dir_operations = {
.read = generic_read_dir,
.readdir = hfsplus_readdir,
.ioctl = hfsplus_ioctl,
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 12ed2b7d046..acf66dba3e0 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -93,17 +93,6 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
return res ? try_to_free_buffers(page) : 0;
}
-static int hfsplus_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks,
- struct buffer_head *bh_result, int create)
-{
- int ret;
-
- ret = hfsplus_get_block(inode, iblock, bh_result, create);
- if (!ret)
- bh_result->b_size = (1 << inode->i_blkbits);
- return ret;
-}
-
static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb,
const struct iovec *iov, loff_t offset, unsigned long nr_segs)
{
@@ -111,7 +100,7 @@ static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb,
struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
- offset, nr_segs, hfsplus_get_blocks, NULL);
+ offset, nr_segs, hfsplus_get_block, NULL);
}
static int hfsplus_writepages(struct address_space *mapping,
@@ -291,7 +280,7 @@ static struct inode_operations hfsplus_file_inode_operations = {
.listxattr = hfsplus_listxattr,
};
-static struct file_operations hfsplus_file_operations = {
+static const struct file_operations hfsplus_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index b3ad0bd0312..bf0f8e16e43 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -384,7 +384,7 @@ int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync);
}
-static struct file_operations hostfs_file_fops = {
+static const struct file_operations hostfs_file_fops = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.sendfile = generic_file_sendfile,
@@ -399,7 +399,7 @@ static struct file_operations hostfs_file_fops = {
.fsync = hostfs_fsync,
};
-static struct file_operations hostfs_dir_fops = {
+static const struct file_operations hostfs_dir_fops = {
.llseek = generic_file_llseek,
.readdir = hostfs_readdir,
.read = generic_read_dir,
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
index b97809deba6..23b7cee7212 100644
--- a/fs/hostfs/hostfs_user.c
+++ b/fs/hostfs/hostfs_user.c
@@ -360,7 +360,6 @@ int do_statfs(char *root, long *bsize_out, long long *blocks_out,
spare_out[2] = buf.f_spare[2];
spare_out[3] = buf.f_spare[3];
spare_out[4] = buf.f_spare[4];
- spare_out[5] = buf.f_spare[5];
return(0);
}
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c
index 5591f9623aa..ecc9180645a 100644
--- a/fs/hpfs/dir.c
+++ b/fs/hpfs/dir.c
@@ -310,7 +310,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
return ERR_PTR(-ENOENT);
}
-struct file_operations hpfs_dir_ops =
+const struct file_operations hpfs_dir_ops =
{
.llseek = hpfs_dir_lseek,
.read = generic_read_dir,
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 7c995ac4081..d3b9fffe45a 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -119,7 +119,7 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf,
return retval;
}
-struct file_operations hpfs_file_ops =
+const struct file_operations hpfs_file_ops =
{
.llseek = generic_file_llseek,
.read = generic_file_read,
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 4c6473ab3b3..29b7a3e5517 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -240,7 +240,7 @@ void hpfs_set_dentry_operations(struct dentry *);
/* dir.c */
struct dentry *hpfs_lookup(struct inode *, struct dentry *, struct nameidata *);
-extern struct file_operations hpfs_dir_ops;
+extern const struct file_operations hpfs_dir_ops;
/* dnode.c */
@@ -266,7 +266,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int);
/* file.c */
int hpfs_file_fsync(struct file *, struct dentry *, int);
-extern struct file_operations hpfs_file_ops;
+extern const struct file_operations hpfs_file_ops;
extern struct inode_operations hpfs_file_iops;
extern struct address_space_operations hpfs_aops;
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
index a44dc589739..2ba20cdb5ba 100644
--- a/fs/hppfs/hppfs_kern.c
+++ b/fs/hppfs/hppfs_kern.c
@@ -558,7 +558,7 @@ static loff_t hppfs_llseek(struct file *file, loff_t off, int where)
return(default_llseek(file, off, where));
}
-static struct file_operations hppfs_file_fops = {
+static const struct file_operations hppfs_file_fops = {
.owner = NULL,
.llseek = hppfs_llseek,
.read = hppfs_read,
@@ -609,7 +609,7 @@ static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync)
return(0);
}
-static struct file_operations hppfs_dir_fops = {
+static const struct file_operations hppfs_dir_fops = {
.owner = NULL,
.readdir = hppfs_readdir,
.open = hppfs_dir_open,
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 25fa8bba8cb..3a5b4e92345 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -35,7 +35,7 @@
static struct super_operations hugetlbfs_ops;
static struct address_space_operations hugetlbfs_aops;
-struct file_operations hugetlbfs_file_operations;
+const struct file_operations hugetlbfs_file_operations;
static struct inode_operations hugetlbfs_dir_inode_operations;
static struct inode_operations hugetlbfs_inode_operations;
@@ -566,7 +566,7 @@ static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
inode_init_once(&ei->vfs_inode);
}
-struct file_operations hugetlbfs_file_operations = {
+const struct file_operations hugetlbfs_file_operations = {
.mmap = hugetlbfs_file_mmap,
.fsync = simple_sync_file,
.get_unmapped_area = hugetlb_get_unmapped_area,
diff --git a/fs/inode.c b/fs/inode.c
index a51c671c54c..32b7c337502 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -56,8 +56,8 @@
#define I_HASHBITS i_hash_shift
#define I_HASHMASK i_hash_mask
-static unsigned int i_hash_mask;
-static unsigned int i_hash_shift;
+static unsigned int i_hash_mask __read_mostly;
+static unsigned int i_hash_shift __read_mostly;
/*
* Each inode can be on two separate lists. One is
@@ -73,7 +73,7 @@ static unsigned int i_hash_shift;
LIST_HEAD(inode_in_use);
LIST_HEAD(inode_unused);
-static struct hlist_head *inode_hashtable;
+static struct hlist_head *inode_hashtable __read_mostly;
/*
* A simple spinlock to protect the list manipulations.
@@ -91,20 +91,20 @@ DEFINE_SPINLOCK(inode_lock);
* from its final dispose_list, the struct super_block they refer to
* (for inode->i_sb->s_op) may already have been freed and reused.
*/
-DEFINE_MUTEX(iprune_mutex);
+static DEFINE_MUTEX(iprune_mutex);
/*
* Statistics gathering..
*/
struct inodes_stat_t inodes_stat;
-static kmem_cache_t * inode_cachep;
+static kmem_cache_t * inode_cachep __read_mostly;
static struct inode *alloc_inode(struct super_block *sb)
{
static struct address_space_operations empty_aops;
static struct inode_operations empty_iops;
- static struct file_operations empty_fops;
+ static const struct file_operations empty_fops;
struct inode *inode;
if (sb->s_op->alloc_inode)
diff --git a/fs/inotify.c b/fs/inotify.c
index 0ee39ef591c..367c487c014 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -38,17 +38,16 @@
#include <asm/ioctls.h>
static atomic_t inotify_cookie;
-static atomic_t inotify_watches;
-static kmem_cache_t *watch_cachep;
-static kmem_cache_t *event_cachep;
+static kmem_cache_t *watch_cachep __read_mostly;
+static kmem_cache_t *event_cachep __read_mostly;
-static struct vfsmount *inotify_mnt;
+static struct vfsmount *inotify_mnt __read_mostly;
/* these are configurable via /proc/sys/fs/inotify/ */
-int inotify_max_user_instances;
-int inotify_max_user_watches;
-int inotify_max_queued_events;
+int inotify_max_user_instances __read_mostly;
+int inotify_max_user_watches __read_mostly;
+int inotify_max_queued_events __read_mostly;
/*
* Lock ordering:
@@ -381,6 +380,48 @@ static int find_inode(const char __user *dirname, struct nameidata *nd,
}
/*
+ * inotify_inode_watched - returns nonzero if there are watches on this inode
+ * and zero otherwise. We call this lockless, we do not care if we race.
+ */
+static inline int inotify_inode_watched(struct inode *inode)
+{
+ return !list_empty(&inode->inotify_watches);
+}
+
+/*
+ * Get child dentry flag into synch with parent inode.
+ * Flag should always be clear for negative dentrys.
+ */
+static void set_dentry_child_flags(struct inode *inode, int watched)
+{
+ struct dentry *alias;
+
+ spin_lock(&dcache_lock);
+ list_for_each_entry(alias, &inode->i_dentry, d_alias) {
+ struct dentry *child;
+
+ list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) {
+ if (!child->d_inode) {
+ WARN_ON(child->d_flags & DCACHE_INOTIFY_PARENT_WATCHED);
+ continue;
+ }
+ spin_lock(&child->d_lock);
+ if (watched) {
+ WARN_ON(child->d_flags &
+ DCACHE_INOTIFY_PARENT_WATCHED);
+ child->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED;
+ } else {
+ WARN_ON(!(child->d_flags &
+ DCACHE_INOTIFY_PARENT_WATCHED));
+ child->d_flags&=~DCACHE_INOTIFY_PARENT_WATCHED;
+ }
+ spin_unlock(&child->d_lock);
+ }
+ }
+ spin_unlock(&dcache_lock);
+}
+
+/*
* create_watch - creates a watch on the given device.
*
* Callers must hold dev->mutex. Calls inotify_dev_get_wd() so may sleep.
@@ -426,7 +467,6 @@ static struct inotify_watch *create_watch(struct inotify_device *dev,
get_inotify_watch(watch);
atomic_inc(&dev->user->inotify_watches);
- atomic_inc(&inotify_watches);
return watch;
}
@@ -458,8 +498,10 @@ static void remove_watch_no_event(struct inotify_watch *watch,
list_del(&watch->i_list);
list_del(&watch->d_list);
+ if (!inotify_inode_watched(watch->inode))
+ set_dentry_child_flags(watch->inode, 0);
+
atomic_dec(&dev->user->inotify_watches);
- atomic_dec(&inotify_watches);
idr_remove(&dev->idr, watch->wd);
put_inotify_watch(watch);
}
@@ -481,16 +523,39 @@ static void remove_watch(struct inotify_watch *watch,struct inotify_device *dev)
remove_watch_no_event(watch, dev);
}
+/* Kernel API */
+
/*
- * inotify_inode_watched - returns nonzero if there are watches on this inode
- * and zero otherwise. We call this lockless, we do not care if we race.
+ * inotify_d_instantiate - instantiate dcache entry for inode
*/
-static inline int inotify_inode_watched(struct inode *inode)
+void inotify_d_instantiate(struct dentry *entry, struct inode *inode)
{
- return !list_empty(&inode->inotify_watches);
+ struct dentry *parent;
+
+ if (!inode)
+ return;
+
+ WARN_ON(entry->d_flags & DCACHE_INOTIFY_PARENT_WATCHED);
+ spin_lock(&entry->d_lock);
+ parent = entry->d_parent;
+ if (inotify_inode_watched(parent->d_inode))
+ entry->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED;
+ spin_unlock(&entry->d_lock);
}
-/* Kernel API */
+/*
+ * inotify_d_move - dcache entry has been moved
+ */
+void inotify_d_move(struct dentry *entry)
+{
+ struct dentry *parent;
+
+ parent = entry->d_parent;
+ if (inotify_inode_watched(parent->d_inode))
+ entry->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED;
+ else
+ entry->d_flags &= ~DCACHE_INOTIFY_PARENT_WATCHED;
+}
/**
* inotify_inode_queue_event - queue an event to all watches on this inode
@@ -538,7 +603,7 @@ void inotify_dentry_parent_queue_event(struct dentry *dentry, u32 mask,
struct dentry *parent;
struct inode *inode;
- if (!atomic_read (&inotify_watches))
+ if (!(dentry->d_flags & DCACHE_INOTIFY_PARENT_WATCHED))
return;
spin_lock(&dentry->d_lock);
@@ -855,7 +920,7 @@ static long inotify_ioctl(struct file *file, unsigned int cmd,
return ret;
}
-static struct file_operations inotify_fops = {
+static const struct file_operations inotify_fops = {
.poll = inotify_poll,
.read = inotify_read,
.release = inotify_release,
@@ -993,6 +1058,9 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
goto out;
}
+ if (!inotify_inode_watched(inode))
+ set_dentry_child_flags(inode, 1);
+
/* Add the watch to the device's and the inode's list */
list_add(&watch->d_list, &dev->watches);
list_add(&watch->i_list, &inode->inotify_watches);
@@ -1065,7 +1133,6 @@ static int __init inotify_setup(void)
inotify_max_user_watches = 8192;
atomic_set(&inotify_cookie, 0);
- atomic_set(&inotify_watches, 0);
watch_cachep = kmem_cache_create("inotify_watch_cache",
sizeof(struct inotify_watch),
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 7901ac9f97a..5440ea292c6 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -16,7 +16,7 @@
static int isofs_readdir(struct file *, void *, filldir_t);
-struct file_operations isofs_dir_operations =
+const struct file_operations isofs_dir_operations =
{
.read = generic_read_dir,
.readdir = isofs_readdir,
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index 439a19b1bf3..b87ba066f5e 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -175,6 +175,6 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de,
}
extern struct inode_operations isofs_dir_inode_operations;
-extern struct file_operations isofs_dir_operations;
+extern const struct file_operations isofs_dir_operations;
extern struct address_space_operations isofs_symlink_aops;
extern struct export_operations isofs_export_ops;
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 95a628d8cac..7f96b5cb678 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -33,9 +33,11 @@
#include <linux/mm.h>
#include <linux/suspend.h>
#include <linux/pagemap.h>
+#include <linux/kthread.h>
+#include <linux/proc_fs.h>
+
#include <asm/uaccess.h>
#include <asm/page.h>
-#include <linux/proc_fs.h>
EXPORT_SYMBOL(journal_start);
EXPORT_SYMBOL(journal_restart);
@@ -111,18 +113,15 @@ static void commit_timeout(unsigned long __data)
static int kjournald(void *arg)
{
- journal_t *journal = (journal_t *) arg;
+ journal_t *journal = arg;
transaction_t *transaction;
- struct timer_list timer;
- daemonize("kjournald");
-
- /* Set up an interval timer which can be used to trigger a
- commit wakeup after the commit interval expires */
- init_timer(&timer);
- timer.data = (unsigned long) current;
- timer.function = commit_timeout;
- journal->j_commit_timer = &timer;
+ /*
+ * Set up an interval timer which can be used to trigger a commit wakeup
+ * after the commit interval expires
+ */
+ setup_timer(&journal->j_commit_timer, commit_timeout,
+ (unsigned long)current);
/* Record that the journal thread is running */
journal->j_task = current;
@@ -146,7 +145,7 @@ loop:
if (journal->j_commit_sequence != journal->j_commit_request) {
jbd_debug(1, "OK, requests differ\n");
spin_unlock(&journal->j_state_lock);
- del_timer_sync(journal->j_commit_timer);
+ del_timer_sync(&journal->j_commit_timer);
journal_commit_transaction(journal);
spin_lock(&journal->j_state_lock);
goto loop;
@@ -203,7 +202,7 @@ loop:
end_loop:
spin_unlock(&journal->j_state_lock);
- del_timer_sync(journal->j_commit_timer);
+ del_timer_sync(&journal->j_commit_timer);
journal->j_task = NULL;
wake_up(&journal->j_wait_done_commit);
jbd_debug(1, "Journal thread exiting.\n");
@@ -212,7 +211,7 @@ end_loop:
static void journal_start_thread(journal_t *journal)
{
- kernel_thread(kjournald, journal, CLONE_VM|CLONE_FS|CLONE_FILES);
+ kthread_run(kjournald, journal, "kjournald");
wait_event(journal->j_wait_done_commit, journal->j_task != 0);
}
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 5fc40888f4c..c609f5034fc 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -53,8 +53,8 @@ get_transaction(journal_t *journal, transaction_t *transaction)
spin_lock_init(&transaction->t_handle_lock);
/* Set up the commit timer for the new transaction. */
- journal->j_commit_timer->expires = transaction->t_expires;
- add_timer(journal->j_commit_timer);
+ journal->j_commit_timer.expires = transaction->t_expires;
+ add_timer(&journal->j_commit_timer);
J_ASSERT(journal->j_running_transaction == NULL);
journal->j_running_transaction = transaction;
@@ -1873,16 +1873,15 @@ zap_buffer_unlocked:
}
/**
- * int journal_invalidatepage()
+ * void journal_invalidatepage()
* @journal: journal to use for flush...
* @page: page to flush
* @offset: length of page to invalidate.
*
* Reap page buffers containing data after offset in page.
*
- * Return non-zero if the page's buffers were successfully reaped.
*/
-int journal_invalidatepage(journal_t *journal,
+void journal_invalidatepage(journal_t *journal,
struct page *page,
unsigned long offset)
{
@@ -1893,7 +1892,7 @@ int journal_invalidatepage(journal_t *journal,
if (!PageLocked(page))
BUG();
if (!page_has_buffers(page))
- return 1;
+ return;
/* We will potentially be playing with lists other than just the
* data lists (especially for journaled data mode), so be
@@ -1916,11 +1915,9 @@ int journal_invalidatepage(journal_t *journal,
} while (bh != head);
if (!offset) {
- if (!may_free || !try_to_free_buffers(page))
- return 0;
- J_ASSERT(!page_has_buffers(page));
+ if (may_free && try_to_free_buffers(page))
+ J_ASSERT(!page_has_buffers(page));
}
- return 1;
}
/*
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index 5a4519e834d..020cc097c53 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -55,9 +55,9 @@
static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
static struct super_operations jffs_ops;
-static struct file_operations jffs_file_operations;
+static const struct file_operations jffs_file_operations;
static struct inode_operations jffs_file_inode_operations;
-static struct file_operations jffs_dir_operations;
+static const struct file_operations jffs_dir_operations;
static struct inode_operations jffs_dir_inode_operations;
static struct address_space_operations jffs_address_operations;
@@ -1629,7 +1629,7 @@ static int jffs_fsync(struct file *f, struct dentry *d, int datasync)
}
-static struct file_operations jffs_file_operations =
+static const struct file_operations jffs_file_operations =
{
.open = generic_file_open,
.llseek = generic_file_llseek,
@@ -1649,7 +1649,7 @@ static struct inode_operations jffs_file_inode_operations =
};
-static struct file_operations jffs_dir_operations =
+static const struct file_operations jffs_dir_operations =
{
.readdir = jffs_readdir,
};
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c
index 4db8be8e90c..5c63e0cdcf4 100644
--- a/fs/jffs2/compr_zlib.c
+++ b/fs/jffs2/compr_zlib.c
@@ -33,13 +33,14 @@
*/
#define STREAM_END_SPACE 12
-static DECLARE_MUTEX(deflate_sem);
-static DECLARE_MUTEX(inflate_sem);
+static DEFINE_MUTEX(deflate_mutex);
+static DEFINE_MUTEX(inflate_mutex);
static z_stream inf_strm, def_strm;
#ifdef __KERNEL__ /* Linux-only */
#include <linux/vmalloc.h>
#include <linux/init.h>
+#include <linux/mutex.h>
static int __init alloc_workspaces(void)
{
@@ -79,11 +80,11 @@ static int jffs2_zlib_compress(unsigned char *data_in,
if (*dstlen <= STREAM_END_SPACE)
return -1;
- down(&deflate_sem);
+ mutex_lock(&deflate_mutex);
if (Z_OK != zlib_deflateInit(&def_strm, 3)) {
printk(KERN_WARNING "deflateInit failed\n");
- up(&deflate_sem);
+ mutex_unlock(&deflate_mutex);
return -1;
}
@@ -104,7 +105,7 @@ static int jffs2_zlib_compress(unsigned char *data_in,
if (ret != Z_OK) {
D1(printk(KERN_DEBUG "deflate in loop returned %d\n", ret));
zlib_deflateEnd(&def_strm);
- up(&deflate_sem);
+ mutex_unlock(&deflate_mutex);
return -1;
}
}
@@ -133,7 +134,7 @@ static int jffs2_zlib_compress(unsigned char *data_in,
*sourcelen = def_strm.total_in;
ret = 0;
out:
- up(&deflate_sem);
+ mutex_unlock(&deflate_mutex);
return ret;
}
@@ -145,7 +146,7 @@ static int jffs2_zlib_decompress(unsigned char *data_in,
int ret;
int wbits = MAX_WBITS;
- down(&inflate_sem);
+ mutex_lock(&inflate_mutex);
inf_strm.next_in = data_in;
inf_strm.avail_in = srclen;
@@ -173,7 +174,7 @@ static int jffs2_zlib_decompress(unsigned char *data_in,
if (Z_OK != zlib_inflateInit2(&inf_strm, wbits)) {
printk(KERN_WARNING "inflateInit failed\n");
- up(&inflate_sem);
+ mutex_unlock(&inflate_mutex);
return 1;
}
@@ -183,7 +184,7 @@ static int jffs2_zlib_decompress(unsigned char *data_in,
printk(KERN_NOTICE "inflate returned %d\n", ret);
}
zlib_inflateEnd(&inf_strm);
- up(&inflate_sem);
+ mutex_unlock(&inflate_mutex);
return 0;
}
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index a7bf9cb2567..8bc7a5018e4 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -37,7 +37,7 @@ static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t);
static int jffs2_rename (struct inode *, struct dentry *,
struct inode *, struct dentry *);
-struct file_operations jffs2_dir_operations =
+const struct file_operations jffs2_dir_operations =
{
.read = generic_read_dir,
.readdir = jffs2_readdir,
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 935f273dc57..9f4171213e5 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -38,7 +38,7 @@ int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync)
return 0;
}
-struct file_operations jffs2_file_operations =
+const struct file_operations jffs2_file_operations =
{
.llseek = generic_file_llseek,
.open = generic_file_open,
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 59e7a393200..d307cf54862 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -159,11 +159,11 @@ void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c);
void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c);
/* dir.c */
-extern struct file_operations jffs2_dir_operations;
+extern const struct file_operations jffs2_dir_operations;
extern struct inode_operations jffs2_dir_inode_operations;
/* file.c */
-extern struct file_operations jffs2_file_operations;
+extern const struct file_operations jffs2_file_operations;
extern struct inode_operations jffs2_file_inode_operations;
extern struct address_space_operations jffs2_file_address_operations;
int jffs2_fsync(struct file *, struct dentry *, int);
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index e1ac6e497e2..1c9745be5ad 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -100,7 +100,7 @@ struct inode_operations jfs_file_inode_operations = {
#endif
};
-struct file_operations jfs_file_operations = {
+const struct file_operations jfs_file_operations = {
.open = jfs_open,
.llseek = generic_file_llseek,
.write = generic_file_write,
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 51a5fed90cc..04eb78f1252 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -258,7 +258,8 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
static int jfs_get_block(struct inode *ip, sector_t lblock,
struct buffer_head *bh_result, int create)
{
- return jfs_get_blocks(ip, lblock, 1, bh_result, create);
+ return jfs_get_blocks(ip, lblock, bh_result->b_size >> ip->i_blkbits,
+ bh_result, create);
}
static int jfs_writepage(struct page *page, struct writeback_control *wbc)
@@ -301,7 +302,7 @@ static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb,
struct inode *inode = file->f_mapping->host;
return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
- offset, nr_segs, jfs_get_blocks, NULL);
+ offset, nr_segs, jfs_get_block, NULL);
}
struct address_space_operations jfs_aops = {
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index 095d471b9f9..c3007267446 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -35,9 +35,9 @@ extern void jfs_set_inode_flags(struct inode *);
extern struct address_space_operations jfs_aops;
extern struct inode_operations jfs_dir_inode_operations;
-extern struct file_operations jfs_dir_operations;
+extern const struct file_operations jfs_dir_operations;
extern struct inode_operations jfs_file_inode_operations;
-extern struct file_operations jfs_file_operations;
+extern const struct file_operations jfs_file_operations;
extern struct inode_operations jfs_symlink_inode_operations;
extern struct dentry_operations jfs_ci_dentry_operations;
#endif /* _H_JFS_INODE */
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index 0b348b13b55..3315f0b1fbc 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -69,6 +69,7 @@
#include <linux/bio.h>
#include <linux/suspend.h>
#include <linux/delay.h>
+#include <linux/mutex.h>
#include "jfs_incore.h"
#include "jfs_filsys.h"
#include "jfs_metapage.h"
@@ -165,7 +166,7 @@ do { \
*/
static LIST_HEAD(jfs_external_logs);
static struct jfs_log *dummy_log = NULL;
-static DECLARE_MUTEX(jfs_log_sem);
+static DEFINE_MUTEX(jfs_log_mutex);
/*
* forward references
@@ -1085,20 +1086,20 @@ int lmLogOpen(struct super_block *sb)
if (sbi->mntflag & JFS_INLINELOG)
return open_inline_log(sb);
- down(&jfs_log_sem);
+ mutex_lock(&jfs_log_mutex);
list_for_each_entry(log, &jfs_external_logs, journal_list) {
if (log->bdev->bd_dev == sbi->logdev) {
if (memcmp(log->uuid, sbi->loguuid,
sizeof(log->uuid))) {
jfs_warn("wrong uuid on JFS journal\n");
- up(&jfs_log_sem);
+ mutex_unlock(&jfs_log_mutex);
return -EINVAL;
}
/*
* add file system to log active file system list
*/
if ((rc = lmLogFileSystem(log, sbi, 1))) {
- up(&jfs_log_sem);
+ mutex_unlock(&jfs_log_mutex);
return rc;
}
goto journal_found;
@@ -1106,7 +1107,7 @@ int lmLogOpen(struct super_block *sb)
}
if (!(log = kzalloc(sizeof(struct jfs_log), GFP_KERNEL))) {
- up(&jfs_log_sem);
+ mutex_unlock(&jfs_log_mutex);
return -ENOMEM;
}
INIT_LIST_HEAD(&log->sb_list);
@@ -1151,7 +1152,7 @@ journal_found:
sbi->log = log;
LOG_UNLOCK(log);
- up(&jfs_log_sem);
+ mutex_unlock(&jfs_log_mutex);
return 0;
/*
@@ -1168,7 +1169,7 @@ journal_found:
blkdev_put(bdev);
free: /* free log descriptor */
- up(&jfs_log_sem);
+ mutex_unlock(&jfs_log_mutex);
kfree(log);
jfs_warn("lmLogOpen: exit(%d)", rc);
@@ -1212,11 +1213,11 @@ static int open_dummy_log(struct super_block *sb)
{
int rc;
- down(&jfs_log_sem);
+ mutex_lock(&jfs_log_mutex);
if (!dummy_log) {
dummy_log = kzalloc(sizeof(struct jfs_log), GFP_KERNEL);
if (!dummy_log) {
- up(&jfs_log_sem);
+ mutex_unlock(&jfs_log_mutex);
return -ENOMEM;
}
INIT_LIST_HEAD(&dummy_log->sb_list);
@@ -1229,7 +1230,7 @@ static int open_dummy_log(struct super_block *sb)
if (rc) {
kfree(dummy_log);
dummy_log = NULL;
- up(&jfs_log_sem);
+ mutex_unlock(&jfs_log_mutex);
return rc;
}
}
@@ -1238,7 +1239,7 @@ static int open_dummy_log(struct super_block *sb)
list_add(&JFS_SBI(sb)->log_list, &dummy_log->sb_list);
JFS_SBI(sb)->log = dummy_log;
LOG_UNLOCK(dummy_log);
- up(&jfs_log_sem);
+ mutex_unlock(&jfs_log_mutex);
return 0;
}
@@ -1466,7 +1467,7 @@ int lmLogClose(struct super_block *sb)
jfs_info("lmLogClose: log:0x%p", log);
- down(&jfs_log_sem);
+ mutex_lock(&jfs_log_mutex);
LOG_LOCK(log);
list_del(&sbi->log_list);
LOG_UNLOCK(log);
@@ -1516,7 +1517,7 @@ int lmLogClose(struct super_block *sb)
kfree(log);
out:
- up(&jfs_log_sem);
+ mutex_unlock(&jfs_log_mutex);
jfs_info("lmLogClose: exit(%d)", rc);
return rc;
}
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 5fbaeaadccd..f28696f235c 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -220,8 +220,8 @@ int __init metapage_init(void)
if (metapage_cache == NULL)
return -ENOMEM;
- metapage_mempool = mempool_create(METAPOOL_MIN_PAGES, mempool_alloc_slab,
- mempool_free_slab, metapage_cache);
+ metapage_mempool = mempool_create_slab_pool(METAPOOL_MIN_PAGES,
+ metapage_cache);
if (metapage_mempool == NULL) {
kmem_cache_destroy(metapage_cache);
@@ -578,14 +578,13 @@ static int metapage_releasepage(struct page *page, gfp_t gfp_mask)
return 0;
}
-static int metapage_invalidatepage(struct page *page, unsigned long offset)
+static void metapage_invalidatepage(struct page *page, unsigned long offset)
{
BUG_ON(offset);
- if (PageWriteback(page))
- return 0;
+ BUG_ON(PageWriteback(page));
- return metapage_releasepage(page, 0);
+ metapage_releasepage(page, 0);
}
struct address_space_operations jfs_metapage_aops = {
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 309cee575f7..09ea03f6227 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1519,7 +1519,7 @@ struct inode_operations jfs_dir_inode_operations = {
#endif
};
-struct file_operations jfs_dir_operations = {
+const struct file_operations jfs_dir_operations = {
.read = generic_read_dir,
.readdir = jfs_readdir,
.fsync = jfs_fsync,
diff --git a/fs/libfs.c b/fs/libfs.c
index 4fdeaceb892..7145ba7a48d 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -179,7 +179,7 @@ ssize_t generic_read_dir(struct file *filp, char __user *buf, size_t siz, loff_t
return -EISDIR;
}
-struct file_operations simple_dir_operations = {
+const struct file_operations simple_dir_operations = {
.open = dcache_dir_open,
.release = dcache_dir_close,
.llseek = dcache_dir_lseek,
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index da6354baa0b..bce74446870 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -44,32 +44,25 @@ static LIST_HEAD(nlm_blocked);
/*
* Queue up a lock for blocking so that the GRANTED request can see it
*/
-int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl)
+struct nlm_wait *nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl)
{
struct nlm_wait *block;
- BUG_ON(req->a_block != NULL);
block = kmalloc(sizeof(*block), GFP_KERNEL);
- if (block == NULL)
- return -ENOMEM;
- block->b_host = host;
- block->b_lock = fl;
- init_waitqueue_head(&block->b_wait);
- block->b_status = NLM_LCK_BLOCKED;
-
- list_add(&block->b_list, &nlm_blocked);
- req->a_block = block;
-
- return 0;
+ if (block != NULL) {
+ block->b_host = host;
+ block->b_lock = fl;
+ init_waitqueue_head(&block->b_wait);
+ block->b_status = NLM_LCK_BLOCKED;
+ list_add(&block->b_list, &nlm_blocked);
+ }
+ return block;
}
-void nlmclnt_finish_block(struct nlm_rqst *req)
+void nlmclnt_finish_block(struct nlm_wait *block)
{
- struct nlm_wait *block = req->a_block;
-
if (block == NULL)
return;
- req->a_block = NULL;
list_del(&block->b_list);
kfree(block);
}
@@ -77,15 +70,14 @@ void nlmclnt_finish_block(struct nlm_rqst *req)
/*
* Block on a lock
*/
-long nlmclnt_block(struct nlm_rqst *req, long timeout)
+int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout)
{
- struct nlm_wait *block = req->a_block;
long ret;
/* A borken server might ask us to block even if we didn't
* request it. Just say no!
*/
- if (!req->a_args.block)
+ if (block == NULL)
return -EAGAIN;
/* Go to sleep waiting for GRANT callback. Some servers seem
@@ -99,13 +91,10 @@ long nlmclnt_block(struct nlm_rqst *req, long timeout)
ret = wait_event_interruptible_timeout(block->b_wait,
block->b_status != NLM_LCK_BLOCKED,
timeout);
-
- if (block->b_status != NLM_LCK_BLOCKED) {
- req->a_res.status = block->b_status;
- block->b_status = NLM_LCK_BLOCKED;
- }
-
- return ret;
+ if (ret < 0)
+ return -ERESTARTSYS;
+ req->a_res.status = block->b_status;
+ return 0;
}
/*
@@ -125,7 +114,15 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock)
list_for_each_entry(block, &nlm_blocked, b_list) {
struct file_lock *fl_blocked = block->b_lock;
- if (!nlm_compare_locks(fl_blocked, fl))
+ if (fl_blocked->fl_start != fl->fl_start)
+ continue;
+ if (fl_blocked->fl_end != fl->fl_end)
+ continue;
+ /*
+ * Careful! The NLM server will return the 32-bit "pid" that
+ * we put on the wire: in this case the lockowner "pid".
+ */
+ if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid)
continue;
if (!nlm_cmp_addr(&block->b_host->h_addr, addr))
continue;
@@ -147,34 +144,6 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock)
*/
/*
- * Mark the locks for reclaiming.
- * FIXME: In 2.5 we don't want to iterate through any global file_lock_list.
- * Maintain NLM lock reclaiming lists in the nlm_host instead.
- */
-static
-void nlmclnt_mark_reclaim(struct nlm_host *host)
-{
- struct file_lock *fl;
- struct inode *inode;
- struct list_head *tmp;
-
- list_for_each(tmp, &file_lock_list) {
- fl = list_entry(tmp, struct file_lock, fl_link);
-
- inode = fl->fl_file->f_dentry->d_inode;
- if (inode->i_sb->s_magic != NFS_SUPER_MAGIC)
- continue;
- if (fl->fl_u.nfs_fl.owner == NULL)
- continue;
- if (fl->fl_u.nfs_fl.owner->host != host)
- continue;
- if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED))
- continue;
- fl->fl_u.nfs_fl.flags |= NFS_LCK_RECLAIM;
- }
-}
-
-/*
* Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number,
* that we mark locks for reclaiming, and that we bump the pseudo NSM state.
*/
@@ -186,7 +155,12 @@ void nlmclnt_prepare_reclaim(struct nlm_host *host, u32 newstate)
host->h_state++;
host->h_nextrebind = 0;
nlm_rebind_host(host);
- nlmclnt_mark_reclaim(host);
+
+ /*
+ * Mark the locks for reclaiming.
+ */
+ list_splice_init(&host->h_granted, &host->h_reclaim);
+
dprintk("NLM: reclaiming locks for host %s", host->h_name);
}
@@ -215,9 +189,7 @@ reclaimer(void *ptr)
{
struct nlm_host *host = (struct nlm_host *) ptr;
struct nlm_wait *block;
- struct list_head *tmp;
- struct file_lock *fl;
- struct inode *inode;
+ struct file_lock *fl, *next;
daemonize("%s-reclaim", host->h_name);
allow_signal(SIGKILL);
@@ -229,23 +201,13 @@ reclaimer(void *ptr)
/* First, reclaim all locks that have been marked. */
restart:
- list_for_each(tmp, &file_lock_list) {
- fl = list_entry(tmp, struct file_lock, fl_link);
+ list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) {
+ list_del_init(&fl->fl_u.nfs_fl.list);
- inode = fl->fl_file->f_dentry->d_inode;
- if (inode->i_sb->s_magic != NFS_SUPER_MAGIC)
- continue;
- if (fl->fl_u.nfs_fl.owner == NULL)
- continue;
- if (fl->fl_u.nfs_fl.owner->host != host)
- continue;
- if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_RECLAIM))
- continue;
-
- fl->fl_u.nfs_fl.flags &= ~NFS_LCK_RECLAIM;
- nlmclnt_reclaim(host, fl);
if (signalled())
- break;
+ continue;
+ if (nlmclnt_reclaim(host, fl) == 0)
+ list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted);
goto restart;
}
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 970b6a6aa33..f96e38155b5 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -132,59 +132,18 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry->d_inode), sizeof(struct nfs_fh));
lock->caller = system_utsname.nodename;
lock->oh.data = req->a_owner;
- lock->oh.len = sprintf(req->a_owner, "%d@%s",
- current->pid, system_utsname.nodename);
- locks_copy_lock(&lock->fl, fl);
+ lock->oh.len = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s",
+ (unsigned int)fl->fl_u.nfs_fl.owner->pid,
+ system_utsname.nodename);
+ lock->svid = fl->fl_u.nfs_fl.owner->pid;
+ lock->fl.fl_start = fl->fl_start;
+ lock->fl.fl_end = fl->fl_end;
+ lock->fl.fl_type = fl->fl_type;
}
static void nlmclnt_release_lockargs(struct nlm_rqst *req)
{
- struct file_lock *fl = &req->a_args.lock.fl;
-
- if (fl->fl_ops && fl->fl_ops->fl_release_private)
- fl->fl_ops->fl_release_private(fl);
-}
-
-/*
- * Initialize arguments for GRANTED call. The nlm_rqst structure
- * has been cleared already.
- */
-int
-nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock)
-{
- locks_copy_lock(&call->a_args.lock.fl, &lock->fl);
- memcpy(&call->a_args.lock.fh, &lock->fh, sizeof(call->a_args.lock.fh));
- call->a_args.lock.caller = system_utsname.nodename;
- call->a_args.lock.oh.len = lock->oh.len;
-
- /* set default data area */
- call->a_args.lock.oh.data = call->a_owner;
-
- if (lock->oh.len > NLMCLNT_OHSIZE) {
- void *data = kmalloc(lock->oh.len, GFP_KERNEL);
- if (!data) {
- nlmclnt_freegrantargs(call);
- return 0;
- }
- call->a_args.lock.oh.data = (u8 *) data;
- }
-
- memcpy(call->a_args.lock.oh.data, lock->oh.data, lock->oh.len);
- return 1;
-}
-
-void
-nlmclnt_freegrantargs(struct nlm_rqst *call)
-{
- struct file_lock *fl = &call->a_args.lock.fl;
- /*
- * Check whether we allocated memory for the owner.
- */
- if (call->a_args.lock.oh.data != (u8 *) call->a_owner) {
- kfree(call->a_args.lock.oh.data);
- }
- if (fl->fl_ops && fl->fl_ops->fl_release_private)
- fl->fl_ops->fl_release_private(fl);
+ BUG_ON(req->a_args.lock.fl.fl_ops != NULL);
}
/*
@@ -193,9 +152,8 @@ nlmclnt_freegrantargs(struct nlm_rqst *call)
int
nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
{
- struct nfs_server *nfssrv = NFS_SERVER(inode);
struct nlm_host *host;
- struct nlm_rqst reqst, *call = &reqst;
+ struct nlm_rqst *call;
sigset_t oldset;
unsigned long flags;
int status, proto, vers;
@@ -209,23 +167,17 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
/* Retrieve transport protocol from NFS client */
proto = NFS_CLIENT(inode)->cl_xprt->prot;
- if (!(host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers)))
+ host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers);
+ if (host == NULL)
return -ENOLCK;
- /* Create RPC client handle if not there, and copy soft
- * and intr flags from NFS client. */
- if (host->h_rpcclnt == NULL) {
- struct rpc_clnt *clnt;
+ call = nlm_alloc_call(host);
+ if (call == NULL)
+ return -ENOMEM;
- /* Bind an rpc client to this host handle (does not
- * perform a portmapper lookup) */
- if (!(clnt = nlm_bind_host(host))) {
- status = -ENOLCK;
- goto done;
- }
- clnt->cl_softrtry = nfssrv->client->cl_softrtry;
- clnt->cl_intr = nfssrv->client->cl_intr;
- }
+ nlmclnt_locks_init_private(fl, host);
+ /* Set up the argument struct */
+ nlmclnt_setlockargs(call, fl);
/* Keep the old signal mask */
spin_lock_irqsave(&current->sighand->siglock, flags);
@@ -238,26 +190,10 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
&& (current->flags & PF_EXITING)) {
sigfillset(&current->blocked); /* Mask all signals */
recalc_sigpending();
- spin_unlock_irqrestore(&current->sighand->siglock, flags);
- call = nlmclnt_alloc_call();
- if (!call) {
- status = -ENOMEM;
- goto out_restore;
- }
call->a_flags = RPC_TASK_ASYNC;
- } else {
- spin_unlock_irqrestore(&current->sighand->siglock, flags);
- memset(call, 0, sizeof(*call));
- locks_init_lock(&call->a_args.lock.fl);
- locks_init_lock(&call->a_res.lock.fl);
}
- call->a_host = host;
-
- nlmclnt_locks_init_private(fl, host);
-
- /* Set up the argument struct */
- nlmclnt_setlockargs(call, fl);
+ spin_unlock_irqrestore(&current->sighand->siglock, flags);
if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
if (fl->fl_type != F_UNLCK) {
@@ -270,41 +206,58 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
else
status = -EINVAL;
- out_restore:
+ fl->fl_ops->fl_release_private(fl);
+ fl->fl_ops = NULL;
+
spin_lock_irqsave(&current->sighand->siglock, flags);
current->blocked = oldset;
recalc_sigpending();
spin_unlock_irqrestore(&current->sighand->siglock, flags);
-done:
dprintk("lockd: clnt proc returns %d\n", status);
- nlm_release_host(host);
return status;
}
EXPORT_SYMBOL(nlmclnt_proc);
/*
* Allocate an NLM RPC call struct
+ *
+ * Note: the caller must hold a reference to host. In case of failure,
+ * this reference will be released.
*/
-struct nlm_rqst *
-nlmclnt_alloc_call(void)
+struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
{
struct nlm_rqst *call;
- while (!signalled()) {
- call = (struct nlm_rqst *) kmalloc(sizeof(struct nlm_rqst), GFP_KERNEL);
- if (call) {
- memset(call, 0, sizeof(*call));
+ for(;;) {
+ call = kzalloc(sizeof(*call), GFP_KERNEL);
+ if (call != NULL) {
locks_init_lock(&call->a_args.lock.fl);
locks_init_lock(&call->a_res.lock.fl);
+ call->a_host = host;
return call;
}
- printk("nlmclnt_alloc_call: failed, waiting for memory\n");
+ if (signalled())
+ break;
+ printk("nlm_alloc_call: failed, waiting for memory\n");
schedule_timeout_interruptible(5*HZ);
}
+ nlm_release_host(host);
return NULL;
}
+void nlm_release_call(struct nlm_rqst *call)
+{
+ nlm_release_host(call->a_host);
+ nlmclnt_release_lockargs(call);
+ kfree(call);
+}
+
+static void nlmclnt_rpc_release(void *data)
+{
+ return nlm_release_call(data);
+}
+
static int nlm_wait_on_grace(wait_queue_head_t *queue)
{
DEFINE_WAIT(wait);
@@ -401,57 +354,45 @@ in_grace_period:
/*
* Generic NLM call, async version.
*/
-int nlmsvc_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
+static int __nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops)
{
struct nlm_host *host = req->a_host;
struct rpc_clnt *clnt;
- struct rpc_message msg = {
- .rpc_argp = &req->a_args,
- .rpc_resp = &req->a_res,
- };
- int status;
+ int status = -ENOLCK;
dprintk("lockd: call procedure %d on %s (async)\n",
(int)proc, host->h_name);
/* If we have no RPC client yet, create one. */
- if ((clnt = nlm_bind_host(host)) == NULL)
- return -ENOLCK;
- msg.rpc_proc = &clnt->cl_procinfo[proc];
+ clnt = nlm_bind_host(host);
+ if (clnt == NULL)
+ goto out_err;
+ msg->rpc_proc = &clnt->cl_procinfo[proc];
/* bootstrap and kick off the async RPC call */
- status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req);
-
+ status = rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req);
+ if (status == 0)
+ return 0;
+out_err:
+ nlm_release_call(req);
return status;
}
-static int nlmclnt_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
+int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
{
- struct nlm_host *host = req->a_host;
- struct rpc_clnt *clnt;
- struct nlm_args *argp = &req->a_args;
- struct nlm_res *resp = &req->a_res;
struct rpc_message msg = {
- .rpc_argp = argp,
- .rpc_resp = resp,
+ .rpc_argp = &req->a_args,
+ .rpc_resp = &req->a_res,
};
- int status;
-
- dprintk("lockd: call procedure %d on %s (async)\n",
- (int)proc, host->h_name);
-
- /* If we have no RPC client yet, create one. */
- if ((clnt = nlm_bind_host(host)) == NULL)
- return -ENOLCK;
- msg.rpc_proc = &clnt->cl_procinfo[proc];
+ return __nlm_async_call(req, proc, &msg, tk_ops);
+}
- /* Increment host refcount */
- nlm_get_host(host);
- /* bootstrap and kick off the async RPC call */
- status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req);
- if (status < 0)
- nlm_release_host(host);
- return status;
+int nlm_async_reply(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
+{
+ struct rpc_message msg = {
+ .rpc_argp = &req->a_res,
+ };
+ return __nlm_async_call(req, proc, &msg, tk_ops);
}
/*
@@ -463,36 +404,41 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
int status;
status = nlmclnt_call(req, NLMPROC_TEST);
- nlmclnt_release_lockargs(req);
if (status < 0)
- return status;
+ goto out;
- status = req->a_res.status;
- if (status == NLM_LCK_GRANTED) {
- fl->fl_type = F_UNLCK;
- } if (status == NLM_LCK_DENIED) {
- /*
- * Report the conflicting lock back to the application.
- */
- locks_copy_lock(fl, &req->a_res.lock.fl);
- fl->fl_pid = 0;
- } else {
- return nlm_stat_to_errno(req->a_res.status);
+ switch (req->a_res.status) {
+ case NLM_LCK_GRANTED:
+ fl->fl_type = F_UNLCK;
+ break;
+ case NLM_LCK_DENIED:
+ /*
+ * Report the conflicting lock back to the application.
+ */
+ fl->fl_start = req->a_res.lock.fl.fl_start;
+ fl->fl_end = req->a_res.lock.fl.fl_start;
+ fl->fl_type = req->a_res.lock.fl.fl_type;
+ fl->fl_pid = 0;
+ break;
+ default:
+ status = nlm_stat_to_errno(req->a_res.status);
}
-
- return 0;
+out:
+ nlm_release_call(req);
+ return status;
}
static void nlmclnt_locks_copy_lock(struct file_lock *new, struct file_lock *fl)
{
- memcpy(&new->fl_u.nfs_fl, &fl->fl_u.nfs_fl, sizeof(new->fl_u.nfs_fl));
- nlm_get_lockowner(new->fl_u.nfs_fl.owner);
+ new->fl_u.nfs_fl.state = fl->fl_u.nfs_fl.state;
+ new->fl_u.nfs_fl.owner = nlm_get_lockowner(fl->fl_u.nfs_fl.owner);
+ list_add_tail(&new->fl_u.nfs_fl.list, &fl->fl_u.nfs_fl.owner->host->h_granted);
}
static void nlmclnt_locks_release_private(struct file_lock *fl)
{
+ list_del(&fl->fl_u.nfs_fl.list);
nlm_put_lockowner(fl->fl_u.nfs_fl.owner);
- fl->fl_ops = NULL;
}
static struct file_lock_operations nlmclnt_lock_ops = {
@@ -504,8 +450,8 @@ static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *ho
{
BUG_ON(fl->fl_ops != NULL);
fl->fl_u.nfs_fl.state = 0;
- fl->fl_u.nfs_fl.flags = 0;
fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner);
+ INIT_LIST_HEAD(&fl->fl_u.nfs_fl.list);
fl->fl_ops = &nlmclnt_lock_ops;
}
@@ -552,57 +498,52 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
{
struct nlm_host *host = req->a_host;
struct nlm_res *resp = &req->a_res;
- long timeout;
- int status;
+ struct nlm_wait *block = NULL;
+ int status = -ENOLCK;
if (!host->h_monitored && nsm_monitor(host) < 0) {
printk(KERN_NOTICE "lockd: failed to monitor %s\n",
host->h_name);
- status = -ENOLCK;
goto out;
}
- if (req->a_args.block) {
- status = nlmclnt_prepare_block(req, host, fl);
- if (status < 0)
- goto out;
- }
+ block = nlmclnt_prepare_block(host, fl);
for(;;) {
status = nlmclnt_call(req, NLMPROC_LOCK);
if (status < 0)
goto out_unblock;
- if (resp->status != NLM_LCK_BLOCKED)
+ if (!req->a_args.block)
break;
- /* Wait on an NLM blocking lock */
- timeout = nlmclnt_block(req, NLMCLNT_POLL_TIMEOUT);
/* Did a reclaimer thread notify us of a server reboot? */
if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD)
continue;
if (resp->status != NLM_LCK_BLOCKED)
break;
- if (timeout >= 0)
- continue;
- /* We were interrupted. Send a CANCEL request to the server
+ /* Wait on an NLM blocking lock */
+ status = nlmclnt_block(block, req, NLMCLNT_POLL_TIMEOUT);
+ /* if we were interrupted. Send a CANCEL request to the server
* and exit
*/
- status = (int)timeout;
- goto out_unblock;
+ if (status < 0)
+ goto out_unblock;
+ if (resp->status != NLM_LCK_BLOCKED)
+ break;
}
if (resp->status == NLM_LCK_GRANTED) {
fl->fl_u.nfs_fl.state = host->h_state;
- fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
fl->fl_flags |= FL_SLEEP;
+ /* Ensure the resulting lock will get added to granted list */
do_vfs_lock(fl);
}
status = nlm_stat_to_errno(resp->status);
out_unblock:
- nlmclnt_finish_block(req);
+ nlmclnt_finish_block(block);
/* Cancel the blocked request if it is still pending */
if (resp->status == NLM_LCK_BLOCKED)
nlmclnt_cancel(host, req->a_args.block, fl);
out:
- nlmclnt_release_lockargs(req);
+ nlm_release_call(req);
return status;
}
@@ -658,10 +599,6 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
struct nlm_res *resp = &req->a_res;
int status;
- /* Clean the GRANTED flag now so the lock doesn't get
- * reclaimed while we're stuck in the unlock call. */
- fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED;
-
/*
* Note: the server is supposed to either grant us the unlock
* request, or to deny it with NLM_LCK_DENIED_GRACE_PERIOD. In either
@@ -669,32 +606,24 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
*/
do_vfs_lock(fl);
- if (req->a_flags & RPC_TASK_ASYNC) {
- status = nlmclnt_async_call(req, NLMPROC_UNLOCK,
- &nlmclnt_unlock_ops);
- /* Hrmf... Do the unlock early since locks_remove_posix()
- * really expects us to free the lock synchronously */
- if (status < 0) {
- nlmclnt_release_lockargs(req);
- kfree(req);
- }
- return status;
- }
+ if (req->a_flags & RPC_TASK_ASYNC)
+ return nlm_async_call(req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops);
status = nlmclnt_call(req, NLMPROC_UNLOCK);
- nlmclnt_release_lockargs(req);
if (status < 0)
- return status;
+ goto out;
+ status = 0;
if (resp->status == NLM_LCK_GRANTED)
- return 0;
+ goto out;
if (resp->status != NLM_LCK_DENIED_NOLOCKS)
printk("lockd: unexpected unlock status: %d\n", resp->status);
-
/* What to do now? I'm out of my depth... */
-
- return -ENOLCK;
+ status = -ENOLCK;
+out:
+ nlm_release_call(req);
+ return status;
}
static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
@@ -716,9 +645,6 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
if (status != NLM_LCK_GRANTED)
printk(KERN_WARNING "lockd: unexpected unlock status: %d\n", status);
die:
- nlm_release_host(req->a_host);
- nlmclnt_release_lockargs(req);
- kfree(req);
return;
retry_rebind:
nlm_rebind_host(req->a_host);
@@ -728,6 +654,7 @@ die:
static const struct rpc_call_ops nlmclnt_unlock_ops = {
.rpc_call_done = nlmclnt_unlock_callback,
+ .rpc_release = nlmclnt_rpc_release,
};
/*
@@ -749,20 +676,15 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl
recalc_sigpending();
spin_unlock_irqrestore(&current->sighand->siglock, flags);
- req = nlmclnt_alloc_call();
+ req = nlm_alloc_call(nlm_get_host(host));
if (!req)
return -ENOMEM;
- req->a_host = host;
req->a_flags = RPC_TASK_ASYNC;
nlmclnt_setlockargs(req, fl);
req->a_args.block = block;
- status = nlmclnt_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops);
- if (status < 0) {
- nlmclnt_release_lockargs(req);
- kfree(req);
- }
+ status = nlm_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops);
spin_lock_irqsave(&current->sighand->siglock, flags);
current->blocked = oldset;
@@ -791,6 +713,7 @@ static void nlmclnt_cancel_callback(struct rpc_task *task, void *data)
switch (req->a_res.status) {
case NLM_LCK_GRANTED:
case NLM_LCK_DENIED_GRACE_PERIOD:
+ case NLM_LCK_DENIED:
/* Everything's good */
break;
case NLM_LCK_DENIED_NOLOCKS:
@@ -802,9 +725,6 @@ static void nlmclnt_cancel_callback(struct rpc_task *task, void *data)
}
die:
- nlm_release_host(req->a_host);
- nlmclnt_release_lockargs(req);
- kfree(req);
return;
retry_cancel:
@@ -818,6 +738,7 @@ retry_cancel:
static const struct rpc_call_ops nlmclnt_cancel_ops = {
.rpc_call_done = nlmclnt_cancel_callback,
+ .rpc_release = nlmclnt_rpc_release,
};
/*
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 82f7a0b1d8a..729ac427d35 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -16,6 +16,7 @@
#include <linux/sunrpc/svc.h>
#include <linux/lockd/lockd.h>
#include <linux/lockd/sm_inter.h>
+#include <linux/mutex.h>
#define NLMDBG_FACILITY NLMDBG_HOSTCACHE
@@ -30,7 +31,7 @@
static struct nlm_host * nlm_hosts[NLM_HOST_NRHASH];
static unsigned long next_gc;
static int nrhosts;
-static DECLARE_MUTEX(nlm_host_sema);
+static DEFINE_MUTEX(nlm_host_mutex);
static void nlm_gc_hosts(void);
@@ -71,7 +72,7 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
hash = NLM_ADDRHASH(sin->sin_addr.s_addr);
/* Lock hash table */
- down(&nlm_host_sema);
+ mutex_lock(&nlm_host_mutex);
if (time_after_eq(jiffies, next_gc))
nlm_gc_hosts();
@@ -91,7 +92,7 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
nlm_hosts[hash] = host;
}
nlm_get_host(host);
- up(&nlm_host_sema);
+ mutex_unlock(&nlm_host_mutex);
return host;
}
}
@@ -123,12 +124,14 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
nlm_hosts[hash] = host;
INIT_LIST_HEAD(&host->h_lockowners);
spin_lock_init(&host->h_lock);
+ INIT_LIST_HEAD(&host->h_granted);
+ INIT_LIST_HEAD(&host->h_reclaim);
if (++nrhosts > NLM_HOST_MAX)
next_gc = 0;
nohost:
- up(&nlm_host_sema);
+ mutex_unlock(&nlm_host_mutex);
return host;
}
@@ -139,19 +142,19 @@ nlm_find_client(void)
* and return it
*/
int hash;
- down(&nlm_host_sema);
+ mutex_lock(&nlm_host_mutex);
for (hash = 0 ; hash < NLM_HOST_NRHASH; hash++) {
struct nlm_host *host, **hp;
for (hp = &nlm_hosts[hash]; (host = *hp) != 0; hp = &host->h_next) {
if (host->h_server &&
host->h_killed == 0) {
nlm_get_host(host);
- up(&nlm_host_sema);
+ mutex_unlock(&nlm_host_mutex);
return host;
}
}
}
- up(&nlm_host_sema);
+ mutex_unlock(&nlm_host_mutex);
return NULL;
}
@@ -191,11 +194,12 @@ nlm_bind_host(struct nlm_host *host)
xprt->resvport = 1; /* NLM requires a reserved port */
/* Existing NLM servers accept AUTH_UNIX only */
- clnt = rpc_create_client(xprt, host->h_name, &nlm_program,
+ clnt = rpc_new_client(xprt, host->h_name, &nlm_program,
host->h_version, RPC_AUTH_UNIX);
if (IS_ERR(clnt))
goto forgetit;
clnt->cl_autobind = 1; /* turn on pmap queries */
+ clnt->cl_softrtry = 1; /* All queries are soft */
host->h_rpcclnt = clnt;
}
@@ -242,8 +246,12 @@ void nlm_release_host(struct nlm_host *host)
{
if (host != NULL) {
dprintk("lockd: release host %s\n", host->h_name);
- atomic_dec(&host->h_count);
BUG_ON(atomic_read(&host->h_count) < 0);
+ if (atomic_dec_and_test(&host->h_count)) {
+ BUG_ON(!list_empty(&host->h_lockowners));
+ BUG_ON(!list_empty(&host->h_granted));
+ BUG_ON(!list_empty(&host->h_reclaim));
+ }
}
}
@@ -258,7 +266,7 @@ nlm_shutdown_hosts(void)
int i;
dprintk("lockd: shutting down host module\n");
- down(&nlm_host_sema);
+ mutex_lock(&nlm_host_mutex);
/* First, make all hosts eligible for gc */
dprintk("lockd: nuking all hosts...\n");
@@ -269,7 +277,7 @@ nlm_shutdown_hosts(void)
/* Then, perform a garbage collection pass */
nlm_gc_hosts();
- up(&nlm_host_sema);
+ mutex_unlock(&nlm_host_mutex);
/* complain if any hosts are left */
if (nrhosts) {
@@ -331,7 +339,6 @@ nlm_gc_hosts(void)
rpc_destroy_client(host->h_rpcclnt);
}
}
- BUG_ON(!list_empty(&host->h_lockowners));
kfree(host);
nrhosts--;
}
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index a89cb8aa2c8..3fc683f46b3 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -35,6 +35,10 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res)
struct rpc_clnt *clnt;
int status;
struct nsm_args args;
+ struct rpc_message msg = {
+ .rpc_argp = &args,
+ .rpc_resp = res,
+ };
clnt = nsm_create();
if (IS_ERR(clnt)) {
@@ -49,7 +53,8 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res)
args.proc = NLMPROC_NSM_NOTIFY;
memset(res, 0, sizeof(*res));
- status = rpc_call(clnt, proc, &args, res, 0);
+ msg.rpc_proc = &clnt->cl_procinfo[proc];
+ status = rpc_call_sync(clnt, &msg, 0);
if (status < 0)
printk(KERN_DEBUG "nsm_mon_unmon: rpc failed, status=%d\n",
status);
@@ -214,12 +219,16 @@ static struct rpc_procinfo nsm_procedures[] = {
.p_encode = (kxdrproc_t) xdr_encode_mon,
.p_decode = (kxdrproc_t) xdr_decode_stat_res,
.p_bufsiz = MAX(SM_mon_sz, SM_monres_sz) << 2,
+ .p_statidx = SM_MON,
+ .p_name = "MONITOR",
},
[SM_UNMON] = {
.p_proc = SM_UNMON,
.p_encode = (kxdrproc_t) xdr_encode_unmon,
.p_decode = (kxdrproc_t) xdr_decode_stat,
.p_bufsiz = MAX(SM_mon_id_sz, SM_unmonres_sz) << 2,
+ .p_statidx = SM_UNMON,
+ .p_name = "UNMONITOR",
},
};
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 5e85bde6c12..fd56c8872f3 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/sunrpc/types.h>
#include <linux/sunrpc/stats.h>
@@ -43,13 +44,13 @@ static struct svc_program nlmsvc_program;
struct nlmsvc_binding * nlmsvc_ops;
EXPORT_SYMBOL(nlmsvc_ops);
-static DECLARE_MUTEX(nlmsvc_sema);
+static DEFINE_MUTEX(nlmsvc_mutex);
static unsigned int nlmsvc_users;
static pid_t nlmsvc_pid;
int nlmsvc_grace_period;
unsigned long nlmsvc_timeout;
-static DECLARE_MUTEX_LOCKED(lockd_start);
+static DECLARE_COMPLETION(lockd_start_done);
static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);
/*
@@ -112,7 +113,7 @@ lockd(struct svc_rqst *rqstp)
* Let our maker know we're running.
*/
nlmsvc_pid = current->pid;
- up(&lockd_start);
+ complete(&lockd_start_done);
daemonize("lockd");
@@ -215,7 +216,7 @@ lockd_up(void)
struct svc_serv * serv;
int error = 0;
- down(&nlmsvc_sema);
+ mutex_lock(&nlmsvc_mutex);
/*
* Unconditionally increment the user count ... this is
* the number of clients who _want_ a lockd process.
@@ -263,7 +264,7 @@ lockd_up(void)
"lockd_up: create thread failed, error=%d\n", error);
goto destroy_and_out;
}
- down(&lockd_start);
+ wait_for_completion(&lockd_start_done);
/*
* Note: svc_serv structures have an initial use count of 1,
@@ -272,7 +273,7 @@ lockd_up(void)
destroy_and_out:
svc_destroy(serv);
out:
- up(&nlmsvc_sema);
+ mutex_unlock(&nlmsvc_mutex);
return error;
}
EXPORT_SYMBOL(lockd_up);
@@ -285,7 +286,7 @@ lockd_down(void)
{
static int warned;
- down(&nlmsvc_sema);
+ mutex_lock(&nlmsvc_mutex);
if (nlmsvc_users) {
if (--nlmsvc_users)
goto out;
@@ -315,7 +316,7 @@ lockd_down(void)
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
out:
- up(&nlmsvc_sema);
+ mutex_unlock(&nlmsvc_mutex);
}
EXPORT_SYMBOL(lockd_down);
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index b10f913aa06..a2dd9ccb9b3 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -21,10 +21,6 @@
#define NLMDBG_FACILITY NLMDBG_CLIENT
-static u32 nlm4svc_callback(struct svc_rqst *, u32, struct nlm_res *);
-
-static const struct rpc_call_ops nlm4svc_callback_ops;
-
/*
* Obtain client and file from arguments
*/
@@ -234,83 +230,89 @@ nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
}
/*
+ * This is the generic lockd callback for async RPC calls
+ */
+static void nlm4svc_callback_exit(struct rpc_task *task, void *data)
+{
+ dprintk("lockd: %4d callback returned %d\n", task->tk_pid,
+ -task->tk_status);
+}
+
+static void nlm4svc_callback_release(void *data)
+{
+ nlm_release_call(data);
+}
+
+static const struct rpc_call_ops nlm4svc_callback_ops = {
+ .rpc_call_done = nlm4svc_callback_exit,
+ .rpc_release = nlm4svc_callback_release,
+};
+
+/*
* `Async' versions of the above service routines. They aren't really,
* because we send the callback before the reply proper. I hope this
* doesn't break any clients.
*/
-static int
-nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
- void *resp)
+static int nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
+ int (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *))
{
- struct nlm_res res;
- u32 stat;
+ struct nlm_host *host;
+ struct nlm_rqst *call;
+ int stat;
- dprintk("lockd: TEST_MSG called\n");
- memset(&res, 0, sizeof(res));
+ host = nlmsvc_lookup_host(rqstp);
+ if (host == NULL)
+ return rpc_system_err;
+
+ call = nlm_alloc_call(host);
+ if (call == NULL)
+ return rpc_system_err;
- if ((stat = nlm4svc_proc_test(rqstp, argp, &res)) == 0)
- stat = nlm4svc_callback(rqstp, NLMPROC_TEST_RES, &res);
- return stat;
+ stat = func(rqstp, argp, &call->a_res);
+ if (stat != 0) {
+ nlm_release_call(call);
+ return stat;
+ }
+
+ call->a_flags = RPC_TASK_ASYNC;
+ if (nlm_async_reply(call, proc, &nlm4svc_callback_ops) < 0)
+ return rpc_system_err;
+ return rpc_success;
}
-static int
-nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static int nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
void *resp)
{
- struct nlm_res res;
- u32 stat;
+ dprintk("lockd: TEST_MSG called\n");
+ return nlm4svc_callback(rqstp, NLMPROC_TEST_RES, argp, nlm4svc_proc_test);
+}
+static int nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+ void *resp)
+{
dprintk("lockd: LOCK_MSG called\n");
- memset(&res, 0, sizeof(res));
-
- if ((stat = nlm4svc_proc_lock(rqstp, argp, &res)) == 0)
- stat = nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, &res);
- return stat;
+ return nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlm4svc_proc_lock);
}
-static int
-nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static int nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
void *resp)
{
- struct nlm_res res;
- u32 stat;
-
dprintk("lockd: CANCEL_MSG called\n");
- memset(&res, 0, sizeof(res));
-
- if ((stat = nlm4svc_proc_cancel(rqstp, argp, &res)) == 0)
- stat = nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, &res);
- return stat;
+ return nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlm4svc_proc_cancel);
}
-static int
-nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static int nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
void *resp)
{
- struct nlm_res res;
- u32 stat;
-
dprintk("lockd: UNLOCK_MSG called\n");
- memset(&res, 0, sizeof(res));
-
- if ((stat = nlm4svc_proc_unlock(rqstp, argp, &res)) == 0)
- stat = nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, &res);
- return stat;
+ return nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlm4svc_proc_unlock);
}
-static int
-nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static int nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
void *resp)
{
- struct nlm_res res;
- u32 stat;
-
dprintk("lockd: GRANTED_MSG called\n");
- memset(&res, 0, sizeof(res));
-
- if ((stat = nlm4svc_proc_granted(rqstp, argp, &res)) == 0)
- stat = nlm4svc_callback(rqstp, NLMPROC_GRANTED_RES, &res);
- return stat;
+ return nlm4svc_callback(rqstp, NLMPROC_GRANTED_RES, argp, nlm4svc_proc_granted);
}
/*
@@ -472,55 +474,6 @@ nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp,
/*
- * This is the generic lockd callback for async RPC calls
- */
-static u32
-nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp)
-{
- struct nlm_host *host;
- struct nlm_rqst *call;
-
- if (!(call = nlmclnt_alloc_call()))
- return rpc_system_err;
-
- host = nlmclnt_lookup_host(&rqstp->rq_addr,
- rqstp->rq_prot, rqstp->rq_vers);
- if (!host) {
- kfree(call);
- return rpc_system_err;
- }
-
- call->a_flags = RPC_TASK_ASYNC;
- call->a_host = host;
- memcpy(&call->a_args, resp, sizeof(*resp));
-
- if (nlmsvc_async_call(call, proc, &nlm4svc_callback_ops) < 0)
- goto error;
-
- return rpc_success;
- error:
- kfree(call);
- nlm_release_host(host);
- return rpc_system_err;
-}
-
-static void nlm4svc_callback_exit(struct rpc_task *task, void *data)
-{
- struct nlm_rqst *call = data;
-
- if (task->tk_status < 0) {
- dprintk("lockd: %4d callback failed (errno = %d)\n",
- task->tk_pid, -task->tk_status);
- }
- nlm_release_host(call->a_host);
- kfree(call);
-}
-
-static const struct rpc_call_ops nlm4svc_callback_ops = {
- .rpc_call_done = nlm4svc_callback_exit,
-};
-
-/*
* NLM Server procedures.
*/
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 9cfced65d4a..d2b66bad7d5 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -39,9 +39,12 @@
#define nlm_deadlock nlm_lck_denied
#endif
+static void nlmsvc_release_block(struct nlm_block *block);
static void nlmsvc_insert_block(struct nlm_block *block, unsigned long);
static int nlmsvc_remove_block(struct nlm_block *block);
+static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock);
+static void nlmsvc_freegrantargs(struct nlm_rqst *call);
static const struct rpc_call_ops nlmsvc_grant_ops;
/*
@@ -58,6 +61,7 @@ nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
struct nlm_block **bp, *b;
dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when);
+ kref_get(&block->b_count);
if (block->b_queued)
nlmsvc_remove_block(block);
bp = &nlm_blocked;
@@ -90,6 +94,7 @@ nlmsvc_remove_block(struct nlm_block *block)
if (b == block) {
*bp = block->b_next;
block->b_queued = 0;
+ nlmsvc_release_block(block);
return 1;
}
}
@@ -98,11 +103,10 @@ nlmsvc_remove_block(struct nlm_block *block)
}
/*
- * Find a block for a given lock and optionally remove it from
- * the list.
+ * Find a block for a given lock
*/
static struct nlm_block *
-nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock, int remove)
+nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock)
{
struct nlm_block **head, *block;
struct file_lock *fl;
@@ -112,17 +116,14 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock, int remove)
(long long)lock->fl.fl_start,
(long long)lock->fl.fl_end, lock->fl.fl_type);
for (head = &nlm_blocked; (block = *head) != 0; head = &block->b_next) {
- fl = &block->b_call.a_args.lock.fl;
+ fl = &block->b_call->a_args.lock.fl;
dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n",
block->b_file, fl->fl_pid,
(long long)fl->fl_start,
(long long)fl->fl_end, fl->fl_type,
- nlmdbg_cookie2a(&block->b_call.a_args.cookie));
+ nlmdbg_cookie2a(&block->b_call->a_args.cookie));
if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) {
- if (remove) {
- *head = block->b_next;
- block->b_queued = 0;
- }
+ kref_get(&block->b_count);
return block;
}
}
@@ -150,11 +151,13 @@ nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin)
for (block = nlm_blocked; block; block = block->b_next) {
dprintk("cookie: head of blocked queue %p, block %p\n",
nlm_blocked, block);
- if (nlm_cookie_match(&block->b_call.a_args.cookie,cookie)
+ if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie)
&& nlm_cmp_addr(sin, &block->b_host->h_addr))
break;
}
+ if (block != NULL)
+ kref_get(&block->b_count);
return block;
}
@@ -174,27 +177,30 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
{
struct nlm_block *block;
struct nlm_host *host;
- struct nlm_rqst *call;
+ struct nlm_rqst *call = NULL;
/* Create host handle for callback */
- host = nlmclnt_lookup_host(&rqstp->rq_addr,
- rqstp->rq_prot, rqstp->rq_vers);
+ host = nlmsvc_lookup_host(rqstp);
if (host == NULL)
return NULL;
+ call = nlm_alloc_call(host);
+ if (call == NULL)
+ return NULL;
+
/* Allocate memory for block, and initialize arguments */
- if (!(block = (struct nlm_block *) kmalloc(sizeof(*block), GFP_KERNEL)))
+ block = kzalloc(sizeof(*block), GFP_KERNEL);
+ if (block == NULL)
goto failed;
- memset(block, 0, sizeof(*block));
- locks_init_lock(&block->b_call.a_args.lock.fl);
- locks_init_lock(&block->b_call.a_res.lock.fl);
+ kref_init(&block->b_count);
- if (!nlmclnt_setgrantargs(&block->b_call, lock))
+ if (!nlmsvc_setgrantargs(call, lock))
goto failed_free;
/* Set notifier function for VFS, and init args */
- block->b_call.a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations;
- block->b_call.a_args.cookie = *cookie; /* see above */
+ call->a_args.lock.fl.fl_flags |= FL_SLEEP;
+ call->a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations;
+ call->a_args.cookie = *cookie; /* see above */
dprintk("lockd: created block %p...\n", block);
@@ -202,22 +208,23 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
block->b_daemon = rqstp->rq_server;
block->b_host = host;
block->b_file = file;
+ file->f_count++;
/* Add to file's list of blocks */
block->b_fnext = file->f_blocks;
file->f_blocks = block;
/* Set up RPC arguments for callback */
- call = &block->b_call;
- call->a_host = host;
+ block->b_call = call;
call->a_flags = RPC_TASK_ASYNC;
+ call->a_block = block;
return block;
failed_free:
kfree(block);
failed:
- nlm_release_host(host);
+ nlm_release_call(call);
return NULL;
}
@@ -227,29 +234,26 @@ failed:
* It is the caller's responsibility to check whether the file
* can be closed hereafter.
*/
-static int
-nlmsvc_delete_block(struct nlm_block *block, int unlock)
+static int nlmsvc_unlink_block(struct nlm_block *block)
{
- struct file_lock *fl = &block->b_call.a_args.lock.fl;
- struct nlm_file *file = block->b_file;
- struct nlm_block **bp;
- int status = 0;
-
- dprintk("lockd: deleting block %p...\n", block);
+ int status;
+ dprintk("lockd: unlinking block %p...\n", block);
/* Remove block from list */
+ status = posix_unblock_lock(block->b_file->f_file, &block->b_call->a_args.lock.fl);
nlmsvc_remove_block(block);
- if (unlock)
- status = posix_unblock_lock(file->f_file, fl);
+ return status;
+}
- /* If the block is in the middle of a GRANT callback,
- * don't kill it yet. */
- if (block->b_incall) {
- nlmsvc_insert_block(block, NLM_NEVER);
- block->b_done = 1;
- return status;
- }
+static void nlmsvc_free_block(struct kref *kref)
+{
+ struct nlm_block *block = container_of(kref, struct nlm_block, b_count);
+ struct nlm_file *file = block->b_file;
+ struct nlm_block **bp;
+ dprintk("lockd: freeing block %p...\n", block);
+
+ down(&file->f_sema);
/* Remove block from file's list of blocks */
for (bp = &file->f_blocks; *bp; bp = &(*bp)->b_fnext) {
if (*bp == block) {
@@ -257,36 +261,93 @@ nlmsvc_delete_block(struct nlm_block *block, int unlock)
break;
}
}
+ up(&file->f_sema);
- if (block->b_host)
- nlm_release_host(block->b_host);
- nlmclnt_freegrantargs(&block->b_call);
+ nlmsvc_freegrantargs(block->b_call);
+ nlm_release_call(block->b_call);
+ nlm_release_file(block->b_file);
kfree(block);
- return status;
+}
+
+static void nlmsvc_release_block(struct nlm_block *block)
+{
+ if (block != NULL)
+ kref_put(&block->b_count, nlmsvc_free_block);
+}
+
+static void nlmsvc_act_mark(struct nlm_host *host, struct nlm_file *file)
+{
+ struct nlm_block *block;
+
+ down(&file->f_sema);
+ for (block = file->f_blocks; block != NULL; block = block->b_fnext)
+ block->b_host->h_inuse = 1;
+ up(&file->f_sema);
+}
+
+static void nlmsvc_act_unlock(struct nlm_host *host, struct nlm_file *file)
+{
+ struct nlm_block *block;
+
+restart:
+ down(&file->f_sema);
+ for (block = file->f_blocks; block != NULL; block = block->b_fnext) {
+ if (host != NULL && host != block->b_host)
+ continue;
+ if (!block->b_queued)
+ continue;
+ kref_get(&block->b_count);
+ up(&file->f_sema);
+ nlmsvc_unlink_block(block);
+ nlmsvc_release_block(block);
+ goto restart;
+ }
+ up(&file->f_sema);
}
/*
* Loop over all blocks and perform the action specified.
* (NLM_ACT_CHECK handled by nlmsvc_inspect_file).
*/
-int
+void
nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action)
{
- struct nlm_block *block, *next;
- /* XXX: Will everything get cleaned up if we don't unlock here? */
+ if (action == NLM_ACT_MARK)
+ nlmsvc_act_mark(host, file);
+ else
+ nlmsvc_act_unlock(host, file);
+}
- down(&file->f_sema);
- for (block = file->f_blocks; block; block = next) {
- next = block->b_fnext;
- if (action == NLM_ACT_MARK)
- block->b_host->h_inuse = 1;
- else if (action == NLM_ACT_UNLOCK) {
- if (host == NULL || host == block->b_host)
- nlmsvc_delete_block(block, 1);
- }
+/*
+ * Initialize arguments for GRANTED call. The nlm_rqst structure
+ * has been cleared already.
+ */
+static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock)
+{
+ locks_copy_lock(&call->a_args.lock.fl, &lock->fl);
+ memcpy(&call->a_args.lock.fh, &lock->fh, sizeof(call->a_args.lock.fh));
+ call->a_args.lock.caller = system_utsname.nodename;
+ call->a_args.lock.oh.len = lock->oh.len;
+
+ /* set default data area */
+ call->a_args.lock.oh.data = call->a_owner;
+ call->a_args.lock.svid = lock->fl.fl_pid;
+
+ if (lock->oh.len > NLMCLNT_OHSIZE) {
+ void *data = kmalloc(lock->oh.len, GFP_KERNEL);
+ if (!data)
+ return 0;
+ call->a_args.lock.oh.data = (u8 *) data;
}
- up(&file->f_sema);
- return 0;
+
+ memcpy(call->a_args.lock.oh.data, lock->oh.data, lock->oh.len);
+ return 1;
+}
+
+static void nlmsvc_freegrantargs(struct nlm_rqst *call)
+{
+ if (call->a_args.lock.oh.data != call->a_owner)
+ kfree(call->a_args.lock.oh.data);
}
/*
@@ -297,9 +358,9 @@ u32
nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
struct nlm_lock *lock, int wait, struct nlm_cookie *cookie)
{
- struct file_lock *conflock;
- struct nlm_block *block;
+ struct nlm_block *block, *newblock = NULL;
int error;
+ u32 ret;
dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
file->f_file->f_dentry->d_inode->i_sb->s_id,
@@ -310,69 +371,65 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
wait);
- /* Get existing block (in case client is busy-waiting) */
- block = nlmsvc_lookup_block(file, lock, 0);
-
- lock->fl.fl_flags |= FL_LOCKD;
-
+ lock->fl.fl_flags &= ~FL_SLEEP;
again:
/* Lock file against concurrent access */
down(&file->f_sema);
+ /* Get existing block (in case client is busy-waiting) */
+ block = nlmsvc_lookup_block(file, lock);
+ if (block == NULL) {
+ if (newblock != NULL)
+ lock = &newblock->b_call->a_args.lock;
+ } else
+ lock = &block->b_call->a_args.lock;
- if (!(conflock = posix_test_lock(file->f_file, &lock->fl))) {
- error = posix_lock_file(file->f_file, &lock->fl);
+ error = posix_lock_file(file->f_file, &lock->fl);
+ lock->fl.fl_flags &= ~FL_SLEEP;
- if (block)
- nlmsvc_delete_block(block, 0);
- up(&file->f_sema);
+ dprintk("lockd: posix_lock_file returned %d\n", error);
- dprintk("lockd: posix_lock_file returned %d\n", -error);
- switch(-error) {
+ switch(error) {
case 0:
- return nlm_granted;
- case EDEADLK:
- return nlm_deadlock;
- case EAGAIN:
- return nlm_lck_denied;
+ ret = nlm_granted;
+ goto out;
+ case -EAGAIN:
+ break;
+ case -EDEADLK:
+ ret = nlm_deadlock;
+ goto out;
default: /* includes ENOLCK */
- return nlm_lck_denied_nolocks;
- }
+ ret = nlm_lck_denied_nolocks;
+ goto out;
}
- if (!wait) {
- up(&file->f_sema);
- return nlm_lck_denied;
- }
+ ret = nlm_lck_denied;
+ if (!wait)
+ goto out;
- if (posix_locks_deadlock(&lock->fl, conflock)) {
- up(&file->f_sema);
- return nlm_deadlock;
- }
+ ret = nlm_lck_blocked;
+ if (block != NULL)
+ goto out;
/* If we don't have a block, create and initialize it. Then
* retry because we may have slept in kmalloc. */
/* We have to release f_sema as nlmsvc_create_block may try to
* to claim it while doing host garbage collection */
- if (block == NULL) {
+ if (newblock == NULL) {
up(&file->f_sema);
dprintk("lockd: blocking on this lock (allocating).\n");
- if (!(block = nlmsvc_create_block(rqstp, file, lock, cookie)))
+ if (!(newblock = nlmsvc_create_block(rqstp, file, lock, cookie)))
return nlm_lck_denied_nolocks;
goto again;
}
/* Append to list of blocked */
- nlmsvc_insert_block(block, NLM_NEVER);
-
- if (list_empty(&block->b_call.a_args.lock.fl.fl_block)) {
- /* Now add block to block list of the conflicting lock
- if we haven't done so. */
- dprintk("lockd: blocking on this lock.\n");
- posix_block_lock(conflock, &block->b_call.a_args.lock.fl);
- }
-
+ nlmsvc_insert_block(newblock, NLM_NEVER);
+out:
up(&file->f_sema);
- return nlm_lck_blocked;
+ nlmsvc_release_block(newblock);
+ nlmsvc_release_block(block);
+ dprintk("lockd: nlmsvc_lock returned %u\n", ret);
+ return ret;
}
/*
@@ -382,8 +439,6 @@ u32
nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
struct nlm_lock *conflock)
{
- struct file_lock *fl;
-
dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
file->f_file->f_dentry->d_inode->i_sb->s_id,
file->f_file->f_dentry->d_inode->i_ino,
@@ -391,13 +446,14 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
(long long)lock->fl.fl_start,
(long long)lock->fl.fl_end);
- if ((fl = posix_test_lock(file->f_file, &lock->fl)) != NULL) {
+ if (posix_test_lock(file->f_file, &lock->fl, &conflock->fl)) {
dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",
- fl->fl_type, (long long)fl->fl_start,
- (long long)fl->fl_end);
+ conflock->fl.fl_type,
+ (long long)conflock->fl.fl_start,
+ (long long)conflock->fl.fl_end);
conflock->caller = "somehost"; /* FIXME */
conflock->oh.len = 0; /* don't return OH info */
- conflock->fl = *fl;
+ conflock->svid = conflock->fl.fl_pid;
return nlm_lck_denied;
}
@@ -453,9 +509,12 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
(long long)lock->fl.fl_end);
down(&file->f_sema);
- if ((block = nlmsvc_lookup_block(file, lock, 1)) != NULL)
- status = nlmsvc_delete_block(block, 1);
+ block = nlmsvc_lookup_block(file, lock);
up(&file->f_sema);
+ if (block != NULL) {
+ status = nlmsvc_unlink_block(block);
+ nlmsvc_release_block(block);
+ }
return status ? nlm_lck_denied : nlm_granted;
}
@@ -473,7 +532,7 @@ nlmsvc_notify_blocked(struct file_lock *fl)
dprintk("lockd: VFS unblock notification for block %p\n", fl);
for (bp = &nlm_blocked; (block = *bp) != 0; bp = &block->b_next) {
- if (nlm_compare_locks(&block->b_call.a_args.lock.fl, fl)) {
+ if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) {
nlmsvc_insert_block(block, 0);
svc_wake_up(block->b_daemon);
return;
@@ -508,17 +567,13 @@ static void
nlmsvc_grant_blocked(struct nlm_block *block)
{
struct nlm_file *file = block->b_file;
- struct nlm_lock *lock = &block->b_call.a_args.lock;
- struct file_lock *conflock;
+ struct nlm_lock *lock = &block->b_call->a_args.lock;
int error;
dprintk("lockd: grant blocked lock %p\n", block);
- /* First thing is lock the file */
- down(&file->f_sema);
-
/* Unlink block request from list */
- nlmsvc_remove_block(block);
+ nlmsvc_unlink_block(block);
/* If b_granted is true this means we've been here before.
* Just retry the grant callback, possibly refreshing the RPC
@@ -529,24 +584,21 @@ nlmsvc_grant_blocked(struct nlm_block *block)
}
/* Try the lock operation again */
- if ((conflock = posix_test_lock(file->f_file, &lock->fl)) != NULL) {
- /* Bummer, we blocked again */
+ lock->fl.fl_flags |= FL_SLEEP;
+ error = posix_lock_file(file->f_file, &lock->fl);
+ lock->fl.fl_flags &= ~FL_SLEEP;
+
+ switch (error) {
+ case 0:
+ break;
+ case -EAGAIN:
dprintk("lockd: lock still blocked\n");
nlmsvc_insert_block(block, NLM_NEVER);
- posix_block_lock(conflock, &lock->fl);
- up(&file->f_sema);
return;
- }
-
- /* Alright, no conflicting lock. Now lock it for real. If the
- * following yields an error, this is most probably due to low
- * memory. Retry the lock in a few seconds.
- */
- if ((error = posix_lock_file(file->f_file, &lock->fl)) < 0) {
+ default:
printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
-error, __FUNCTION__);
nlmsvc_insert_block(block, 10 * HZ);
- up(&file->f_sema);
return;
}
@@ -554,17 +606,15 @@ callback:
/* Lock was granted by VFS. */
dprintk("lockd: GRANTing blocked lock.\n");
block->b_granted = 1;
- block->b_incall = 1;
/* Schedule next grant callback in 30 seconds */
nlmsvc_insert_block(block, 30 * HZ);
/* Call the client */
- nlm_get_host(block->b_call.a_host);
- if (nlmsvc_async_call(&block->b_call, NLMPROC_GRANTED_MSG,
+ kref_get(&block->b_count);
+ if (nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG,
&nlmsvc_grant_ops) < 0)
- nlm_release_host(block->b_call.a_host);
- up(&file->f_sema);
+ nlmsvc_release_block(block);
}
/*
@@ -578,20 +628,10 @@ callback:
static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
{
struct nlm_rqst *call = data;
- struct nlm_block *block;
+ struct nlm_block *block = call->a_block;
unsigned long timeout;
- struct sockaddr_in *peer_addr = RPC_PEERADDR(task->tk_client);
dprintk("lockd: GRANT_MSG RPC callback\n");
- dprintk("callback: looking for cookie %s, host (%u.%u.%u.%u)\n",
- nlmdbg_cookie2a(&call->a_args.cookie),
- NIPQUAD(peer_addr->sin_addr.s_addr));
- if (!(block = nlmsvc_find_block(&call->a_args.cookie, peer_addr))) {
- dprintk("lockd: no block for cookie %s, host (%u.%u.%u.%u)\n",
- nlmdbg_cookie2a(&call->a_args.cookie),
- NIPQUAD(peer_addr->sin_addr.s_addr));
- return;
- }
/* Technically, we should down the file semaphore here. Since we
* move the block towards the head of the queue only, no harm
@@ -608,13 +648,18 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
}
nlmsvc_insert_block(block, timeout);
svc_wake_up(block->b_daemon);
- block->b_incall = 0;
+}
- nlm_release_host(call->a_host);
+void nlmsvc_grant_release(void *data)
+{
+ struct nlm_rqst *call = data;
+
+ nlmsvc_release_block(call->a_block);
}
static const struct rpc_call_ops nlmsvc_grant_ops = {
.rpc_call_done = nlmsvc_grant_callback,
+ .rpc_release = nlmsvc_grant_release,
};
/*
@@ -634,25 +679,17 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status
return;
file = block->b_file;
- file->f_count++;
- down(&file->f_sema);
- block = nlmsvc_find_block(cookie, &rqstp->rq_addr);
if (block) {
if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
/* Try again in a couple of seconds */
nlmsvc_insert_block(block, 10 * HZ);
- up(&file->f_sema);
} else {
/* Lock is now held by client, or has been rejected.
* In both cases, the block should be removed. */
- up(&file->f_sema);
- if (status == NLM_LCK_GRANTED)
- nlmsvc_delete_block(block, 0);
- else
- nlmsvc_delete_block(block, 1);
+ nlmsvc_unlink_block(block);
}
}
- nlm_release_file(file);
+ nlmsvc_release_block(block);
}
/*
@@ -675,10 +712,12 @@ nlmsvc_retry_blocked(void)
break;
dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n",
block, block->b_when, block->b_done);
+ kref_get(&block->b_count);
if (block->b_done)
- nlmsvc_delete_block(block, 0);
+ nlmsvc_unlink_block(block);
else
nlmsvc_grant_blocked(block);
+ nlmsvc_release_block(block);
}
if ((block = nlm_blocked) && block->b_when != NLM_NEVER)
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 35681d9cf1f..d210cf304e9 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -22,10 +22,6 @@
#define NLMDBG_FACILITY NLMDBG_CLIENT
-static u32 nlmsvc_callback(struct svc_rqst *, u32, struct nlm_res *);
-
-static const struct rpc_call_ops nlmsvc_callback_ops;
-
#ifdef CONFIG_LOCKD_V4
static u32
cast_to_nlm(u32 status, u32 vers)
@@ -262,83 +258,91 @@ nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
}
/*
+ * This is the generic lockd callback for async RPC calls
+ */
+static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
+{
+ dprintk("lockd: %4d callback returned %d\n", task->tk_pid,
+ -task->tk_status);
+}
+
+static void nlmsvc_callback_release(void *data)
+{
+ nlm_release_call(data);
+}
+
+static const struct rpc_call_ops nlmsvc_callback_ops = {
+ .rpc_call_done = nlmsvc_callback_exit,
+ .rpc_release = nlmsvc_callback_release,
+};
+
+/*
* `Async' versions of the above service routines. They aren't really,
* because we send the callback before the reply proper. I hope this
* doesn't break any clients.
*/
-static int
-nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
- void *resp)
+static int nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
+ int (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *))
{
- struct nlm_res res;
- u32 stat;
+ struct nlm_host *host;
+ struct nlm_rqst *call;
+ int stat;
- dprintk("lockd: TEST_MSG called\n");
- memset(&res, 0, sizeof(res));
+ host = nlmsvc_lookup_host(rqstp);
+ if (host == NULL)
+ return rpc_system_err;
- if ((stat = nlmsvc_proc_test(rqstp, argp, &res)) == 0)
- stat = nlmsvc_callback(rqstp, NLMPROC_TEST_RES, &res);
- return stat;
+ call = nlm_alloc_call(host);
+ if (call == NULL)
+ return rpc_system_err;
+
+ stat = func(rqstp, argp, &call->a_res);
+ if (stat != 0) {
+ nlm_release_call(call);
+ return stat;
+ }
+
+ call->a_flags = RPC_TASK_ASYNC;
+ if (nlm_async_reply(call, proc, &nlmsvc_callback_ops) < 0)
+ return rpc_system_err;
+ return rpc_success;
}
-static int
-nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static int nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
void *resp)
{
- struct nlm_res res;
- u32 stat;
+ dprintk("lockd: TEST_MSG called\n");
+ return nlmsvc_callback(rqstp, NLMPROC_TEST_RES, argp, nlmsvc_proc_test);
+}
+static int nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+ void *resp)
+{
dprintk("lockd: LOCK_MSG called\n");
- memset(&res, 0, sizeof(res));
-
- if ((stat = nlmsvc_proc_lock(rqstp, argp, &res)) == 0)
- stat = nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, &res);
- return stat;
+ return nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlmsvc_proc_lock);
}
-static int
-nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
+static int nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
void *resp)
{
- struct nlm_res res;
- u32 stat;
-
dprintk("lockd: CANCEL_MSG called\n");
- memset(&res, 0, sizeof(res));
-
- if ((stat = nlmsvc_proc_cancel(rqstp, argp, &res)) == 0)
- stat = nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, &res);
- return stat;
+ return nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlmsvc_proc_cancel);
}
static int
nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
void *resp)
{
- struct nlm_res res;
- u32 stat;
-
dprintk("lockd: UNLOCK_MSG called\n");
- memset(&res, 0, sizeof(res));
-
- if ((stat = nlmsvc_proc_unlock(rqstp, argp, &res)) == 0)
- stat = nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, &res);
- return stat;
+ return nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlmsvc_proc_unlock);
}
static int
nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
void *resp)
{
- struct nlm_res res;
- u32 stat;
-
dprintk("lockd: GRANTED_MSG called\n");
- memset(&res, 0, sizeof(res));
-
- if ((stat = nlmsvc_proc_granted(rqstp, argp, &res)) == 0)
- stat = nlmsvc_callback(rqstp, NLMPROC_GRANTED_RES, &res);
- return stat;
+ return nlmsvc_callback(rqstp, NLMPROC_GRANTED_RES, argp, nlmsvc_proc_granted);
}
/*
@@ -497,55 +501,6 @@ nlmsvc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp,
}
/*
- * This is the generic lockd callback for async RPC calls
- */
-static u32
-nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp)
-{
- struct nlm_host *host;
- struct nlm_rqst *call;
-
- if (!(call = nlmclnt_alloc_call()))
- return rpc_system_err;
-
- host = nlmclnt_lookup_host(&rqstp->rq_addr,
- rqstp->rq_prot, rqstp->rq_vers);
- if (!host) {
- kfree(call);
- return rpc_system_err;
- }
-
- call->a_flags = RPC_TASK_ASYNC;
- call->a_host = host;
- memcpy(&call->a_args, resp, sizeof(*resp));
-
- if (nlmsvc_async_call(call, proc, &nlmsvc_callback_ops) < 0)
- goto error;
-
- return rpc_success;
- error:
- nlm_release_host(host);
- kfree(call);
- return rpc_system_err;
-}
-
-static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
-{
- struct nlm_rqst *call = data;
-
- if (task->tk_status < 0) {
- dprintk("lockd: %4d callback failed (errno = %d)\n",
- task->tk_pid, -task->tk_status);
- }
- nlm_release_host(call->a_host);
- kfree(call);
-}
-
-static const struct rpc_call_ops nlmsvc_callback_ops = {
- .rpc_call_done = nlmsvc_callback_exit,
-};
-
-/*
* NLM Server procedures.
*/
diff --git a/fs/lockd/svcshare.c b/fs/lockd/svcshare.c
index 4943fb7836c..27288c83da9 100644
--- a/fs/lockd/svcshare.c
+++ b/fs/lockd/svcshare.c
@@ -88,7 +88,7 @@ nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file,
* Traverse all shares for a given file (and host).
* NLM_ACT_CHECK is handled by nlmsvc_inspect_file.
*/
-int
+void
nlmsvc_traverse_shares(struct nlm_host *host, struct nlm_file *file, int action)
{
struct nlm_share *share, **shpp;
@@ -106,6 +106,4 @@ nlmsvc_traverse_shares(struct nlm_host *host, struct nlm_file *file, int action)
}
shpp = &share->s_next;
}
-
- return 0;
}
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 62f4a385177..a570e5c8a93 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -11,6 +11,7 @@
#include <linux/string.h>
#include <linux/time.h>
#include <linux/in.h>
+#include <linux/mutex.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/clnt.h>
#include <linux/nfsd/nfsfh.h>
@@ -28,7 +29,7 @@
#define FILE_HASH_BITS 5
#define FILE_NRHASH (1<<FILE_HASH_BITS)
static struct nlm_file * nlm_files[FILE_NRHASH];
-static DECLARE_MUTEX(nlm_file_sema);
+static DEFINE_MUTEX(nlm_file_mutex);
#ifdef NFSD_DEBUG
static inline void nlm_debug_print_fh(char *msg, struct nfs_fh *f)
@@ -91,7 +92,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
hash = file_hash(f);
/* Lock file table */
- down(&nlm_file_sema);
+ mutex_lock(&nlm_file_mutex);
for (file = nlm_files[hash]; file; file = file->f_next)
if (!nfs_compare_fh(&file->f_handle, f))
@@ -130,7 +131,7 @@ found:
nfserr = 0;
out_unlock:
- up(&nlm_file_sema);
+ mutex_unlock(&nlm_file_mutex);
return nfserr;
out_free:
@@ -182,7 +183,7 @@ nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file, int action)
again:
file->f_locks = 0;
for (fl = inode->i_flock; fl; fl = fl->fl_next) {
- if (!(fl->fl_flags & FL_LOCKD))
+ if (fl->fl_lmops != &nlmsvc_lock_operations)
continue;
/* update current lock count */
@@ -224,9 +225,8 @@ nlm_inspect_file(struct nlm_host *host, struct nlm_file *file, int action)
if (file->f_count || file->f_blocks || file->f_shares)
return 1;
} else {
- if (nlmsvc_traverse_blocks(host, file, action)
- || nlmsvc_traverse_shares(host, file, action))
- return 1;
+ nlmsvc_traverse_blocks(host, file, action);
+ nlmsvc_traverse_shares(host, file, action);
}
return nlm_traverse_locks(host, file, action);
}
@@ -240,14 +240,14 @@ nlm_traverse_files(struct nlm_host *host, int action)
struct nlm_file *file, **fp;
int i;
- down(&nlm_file_sema);
+ mutex_lock(&nlm_file_mutex);
for (i = 0; i < FILE_NRHASH; i++) {
fp = nlm_files + i;
while ((file = *fp) != NULL) {
/* Traverse locks, blocks and shares of this file
* and update file->f_locks count */
if (nlm_inspect_file(host, file, action)) {
- up(&nlm_file_sema);
+ mutex_unlock(&nlm_file_mutex);
return 1;
}
@@ -262,7 +262,7 @@ nlm_traverse_files(struct nlm_host *host, int action)
}
}
}
- up(&nlm_file_sema);
+ mutex_unlock(&nlm_file_mutex);
return 0;
}
@@ -282,7 +282,7 @@ nlm_release_file(struct nlm_file *file)
file, file->f_count);
/* Lock file table */
- down(&nlm_file_sema);
+ mutex_lock(&nlm_file_mutex);
/* If there are no more locks etc, delete the file */
if(--file->f_count == 0) {
@@ -290,7 +290,7 @@ nlm_release_file(struct nlm_file *file)
nlm_delete_file(file);
}
- up(&nlm_file_sema);
+ mutex_unlock(&nlm_file_mutex);
}
/*
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 1d700a4dd0b..f22a3764461 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -131,10 +131,11 @@ nlm_decode_lock(u32 *p, struct nlm_lock *lock)
|| !(p = nlm_decode_fh(p, &lock->fh))
|| !(p = nlm_decode_oh(p, &lock->oh)))
return NULL;
+ lock->svid = ntohl(*p++);
locks_init_lock(fl);
fl->fl_owner = current->files;
- fl->fl_pid = ntohl(*p++);
+ fl->fl_pid = (pid_t)lock->svid;
fl->fl_flags = FL_POSIX;
fl->fl_type = F_RDLCK; /* as good as anything else */
start = ntohl(*p++);
@@ -174,7 +175,7 @@ nlm_encode_lock(u32 *p, struct nlm_lock *lock)
else
len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
- *p++ = htonl(fl->fl_pid);
+ *p++ = htonl(lock->svid);
*p++ = htonl(start);
*p++ = htonl(len);
@@ -197,7 +198,7 @@ nlm_encode_testres(u32 *p, struct nlm_res *resp)
struct file_lock *fl = &resp->lock.fl;
*p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one;
- *p++ = htonl(fl->fl_pid);
+ *p++ = htonl(resp->lock.svid);
/* Encode owner handle. */
if (!(p = xdr_encode_netobj(p, &resp->lock.oh)))
@@ -298,7 +299,8 @@ nlmsvc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
memset(lock, 0, sizeof(*lock));
locks_init_lock(&lock->fl);
- lock->fl.fl_pid = ~(u32) 0;
+ lock->svid = ~(u32) 0;
+ lock->fl.fl_pid = (pid_t)lock->svid;
if (!(p = nlm_decode_cookie(p, &argp->cookie))
|| !(p = xdr_decode_string_inplace(p, &lock->caller,
@@ -415,7 +417,8 @@ nlmclt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
memset(&resp->lock, 0, sizeof(resp->lock));
locks_init_lock(fl);
excl = ntohl(*p++);
- fl->fl_pid = ntohl(*p++);
+ resp->lock.svid = ntohl(*p++);
+ fl->fl_pid = (pid_t)resp->lock.svid;
if (!(p = nlm_decode_oh(p, &resp->lock.oh)))
return -EIO;
@@ -543,7 +546,9 @@ nlmclt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
.p_proc = NLMPROC_##proc, \
.p_encode = (kxdrproc_t) nlmclt_encode_##argtype, \
.p_decode = (kxdrproc_t) nlmclt_decode_##restype, \
- .p_bufsiz = MAX(NLM_##argtype##_sz, NLM_##restype##_sz) << 2 \
+ .p_bufsiz = MAX(NLM_##argtype##_sz, NLM_##restype##_sz) << 2, \
+ .p_statidx = NLMPROC_##proc, \
+ .p_name = #proc, \
}
static struct rpc_procinfo nlm_procedures[] = {
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index fdcf105a530..36eb175ec33 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -130,10 +130,11 @@ nlm4_decode_lock(u32 *p, struct nlm_lock *lock)
|| !(p = nlm4_decode_fh(p, &lock->fh))
|| !(p = nlm4_decode_oh(p, &lock->oh)))
return NULL;
+ lock->svid = ntohl(*p++);
locks_init_lock(fl);
fl->fl_owner = current->files;
- fl->fl_pid = ntohl(*p++);
+ fl->fl_pid = (pid_t)lock->svid;
fl->fl_flags = FL_POSIX;
fl->fl_type = F_RDLCK; /* as good as anything else */
p = xdr_decode_hyper(p, &start);
@@ -167,7 +168,7 @@ nlm4_encode_lock(u32 *p, struct nlm_lock *lock)
|| (fl->fl_end > NLM4_OFFSET_MAX && fl->fl_end != OFFSET_MAX))
return NULL;
- *p++ = htonl(fl->fl_pid);
+ *p++ = htonl(lock->svid);
start = loff_t_to_s64(fl->fl_start);
if (fl->fl_end == OFFSET_MAX)
@@ -198,7 +199,7 @@ nlm4_encode_testres(u32 *p, struct nlm_res *resp)
struct file_lock *fl = &resp->lock.fl;
*p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one;
- *p++ = htonl(fl->fl_pid);
+ *p++ = htonl(resp->lock.svid);
/* Encode owner handle. */
if (!(p = xdr_encode_netobj(p, &resp->lock.oh)))
@@ -212,8 +213,8 @@ nlm4_encode_testres(u32 *p, struct nlm_res *resp)
p = xdr_encode_hyper(p, start);
p = xdr_encode_hyper(p, len);
- dprintk("xdr: encode_testres (status %d pid %d type %d start %Ld end %Ld)\n",
- resp->status, fl->fl_pid, fl->fl_type,
+ dprintk("xdr: encode_testres (status %u pid %d type %d start %Ld end %Ld)\n",
+ resp->status, (int)resp->lock.svid, fl->fl_type,
(long long)fl->fl_start, (long long)fl->fl_end);
}
@@ -303,7 +304,8 @@ nlm4svc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
memset(lock, 0, sizeof(*lock));
locks_init_lock(&lock->fl);
- lock->fl.fl_pid = ~(u32) 0;
+ lock->svid = ~(u32) 0;
+ lock->fl.fl_pid = (pid_t)lock->svid;
if (!(p = nlm4_decode_cookie(p, &argp->cookie))
|| !(p = xdr_decode_string_inplace(p, &lock->caller,
@@ -420,7 +422,8 @@ nlm4clt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
memset(&resp->lock, 0, sizeof(resp->lock));
locks_init_lock(fl);
excl = ntohl(*p++);
- fl->fl_pid = ntohl(*p++);
+ resp->lock.svid = ntohl(*p++);
+ fl->fl_pid = (pid_t)resp->lock.svid;
if (!(p = nlm4_decode_oh(p, &resp->lock.oh)))
return -EIO;
@@ -548,7 +551,9 @@ nlm4clt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
.p_proc = NLMPROC_##proc, \
.p_encode = (kxdrproc_t) nlm4clt_encode_##argtype, \
.p_decode = (kxdrproc_t) nlm4clt_decode_##restype, \
- .p_bufsiz = MAX(NLM4_##argtype##_sz, NLM4_##restype##_sz) << 2 \
+ .p_bufsiz = MAX(NLM4_##argtype##_sz, NLM4_##restype##_sz) << 2, \
+ .p_statidx = NLMPROC_##proc, \
+ .p_name = #proc, \
}
static struct rpc_procinfo nlm4_procedures[] = {
diff --git a/fs/locks.c b/fs/locks.c
index 909eab8fb1d..4d9e71d43e7 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -139,13 +139,10 @@ int lease_break_time = 45;
#define for_each_lock(inode, lockp) \
for (lockp = &inode->i_flock; *lockp != NULL; lockp = &(*lockp)->fl_next)
-LIST_HEAD(file_lock_list);
-
-EXPORT_SYMBOL(file_lock_list);
-
+static LIST_HEAD(file_lock_list);
static LIST_HEAD(blocked_list);
-static kmem_cache_t *filelock_cache;
+static kmem_cache_t *filelock_cache __read_mostly;
/* Allocate an empty lock structure. */
static struct file_lock *locks_alloc_lock(void)
@@ -153,6 +150,21 @@ static struct file_lock *locks_alloc_lock(void)
return kmem_cache_alloc(filelock_cache, SLAB_KERNEL);
}
+static void locks_release_private(struct file_lock *fl)
+{
+ if (fl->fl_ops) {
+ if (fl->fl_ops->fl_release_private)
+ fl->fl_ops->fl_release_private(fl);
+ fl->fl_ops = NULL;
+ }
+ if (fl->fl_lmops) {
+ if (fl->fl_lmops->fl_release_private)
+ fl->fl_lmops->fl_release_private(fl);
+ fl->fl_lmops = NULL;
+ }
+
+}
+
/* Free a lock which is not in use. */
static void locks_free_lock(struct file_lock *fl)
{
@@ -169,18 +181,7 @@ static void locks_free_lock(struct file_lock *fl)
if (!list_empty(&fl->fl_link))
panic("Attempting to free lock on active lock list");
- if (fl->fl_ops) {
- if (fl->fl_ops->fl_release_private)
- fl->fl_ops->fl_release_private(fl);
- fl->fl_ops = NULL;
- }
-
- if (fl->fl_lmops) {
- if (fl->fl_lmops->fl_release_private)
- fl->fl_lmops->fl_release_private(fl);
- fl->fl_lmops = NULL;
- }
-
+ locks_release_private(fl);
kmem_cache_free(filelock_cache, fl);
}
@@ -218,24 +219,46 @@ static void init_once(void *foo, kmem_cache_t *cache, unsigned long flags)
locks_init_lock(lock);
}
+static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
+{
+ if (fl->fl_ops) {
+ if (fl->fl_ops->fl_copy_lock)
+ fl->fl_ops->fl_copy_lock(new, fl);
+ new->fl_ops = fl->fl_ops;
+ }
+ if (fl->fl_lmops) {
+ if (fl->fl_lmops->fl_copy_lock)
+ fl->fl_lmops->fl_copy_lock(new, fl);
+ new->fl_lmops = fl->fl_lmops;
+ }
+}
+
/*
* Initialize a new lock from an existing file_lock structure.
*/
-void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
+static void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
{
new->fl_owner = fl->fl_owner;
new->fl_pid = fl->fl_pid;
- new->fl_file = fl->fl_file;
+ new->fl_file = NULL;
new->fl_flags = fl->fl_flags;
new->fl_type = fl->fl_type;
new->fl_start = fl->fl_start;
new->fl_end = fl->fl_end;
+ new->fl_ops = NULL;
+ new->fl_lmops = NULL;
+}
+
+void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
+{
+ locks_release_private(new);
+
+ __locks_copy_lock(new, fl);
+ new->fl_file = fl->fl_file;
new->fl_ops = fl->fl_ops;
new->fl_lmops = fl->fl_lmops;
- if (fl->fl_ops && fl->fl_ops->fl_copy_lock)
- fl->fl_ops->fl_copy_lock(new, fl);
- if (fl->fl_lmops && fl->fl_lmops->fl_copy_lock)
- fl->fl_lmops->fl_copy_lock(new, fl);
+
+ locks_copy_private(new, fl);
}
EXPORT_SYMBOL(locks_copy_lock);
@@ -510,12 +533,7 @@ static void locks_delete_block(struct file_lock *waiter)
static void locks_insert_block(struct file_lock *blocker,
struct file_lock *waiter)
{
- if (!list_empty(&waiter->fl_block)) {
- printk(KERN_ERR "locks_insert_block: removing duplicated lock "
- "(pid=%d %Ld-%Ld type=%d)\n", waiter->fl_pid,
- waiter->fl_start, waiter->fl_end, waiter->fl_type);
- __locks_delete_block(waiter);
- }
+ BUG_ON(!list_empty(&waiter->fl_block));
list_add_tail(&waiter->fl_block, &blocker->fl_block);
waiter->fl_next = blocker;
if (IS_POSIX(blocker))
@@ -654,8 +672,9 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w
return result;
}
-struct file_lock *
-posix_test_lock(struct file *filp, struct file_lock *fl)
+int
+posix_test_lock(struct file *filp, struct file_lock *fl,
+ struct file_lock *conflock)
{
struct file_lock *cfl;
@@ -666,9 +685,13 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
if (posix_locks_conflict(cfl, fl))
break;
}
+ if (cfl) {
+ __locks_copy_lock(conflock, cfl);
+ unlock_kernel();
+ return 1;
+ }
unlock_kernel();
-
- return (cfl);
+ return 0;
}
EXPORT_SYMBOL(posix_test_lock);
@@ -769,9 +792,7 @@ out:
return error;
}
-EXPORT_SYMBOL(posix_lock_file);
-
-static int __posix_lock_file(struct inode *inode, struct file_lock *request)
+static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock)
{
struct file_lock *fl;
struct file_lock *new_fl, *new_fl2;
@@ -795,6 +816,8 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request)
continue;
if (!posix_locks_conflict(request, fl))
continue;
+ if (conflock)
+ locks_copy_lock(conflock, fl);
error = -EAGAIN;
if (!(request->fl_flags & FL_SLEEP))
goto out;
@@ -904,7 +927,8 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request)
fl->fl_start = request->fl_start;
fl->fl_end = request->fl_end;
fl->fl_type = request->fl_type;
- fl->fl_u = request->fl_u;
+ locks_release_private(fl);
+ locks_copy_private(fl, request);
request = fl;
added = 1;
}
@@ -963,8 +987,24 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request)
*/
int posix_lock_file(struct file *filp, struct file_lock *fl)
{
- return __posix_lock_file(filp->f_dentry->d_inode, fl);
+ return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, NULL);
}
+EXPORT_SYMBOL(posix_lock_file);
+
+/**
+ * posix_lock_file_conf - Apply a POSIX-style lock to a file
+ * @filp: The file to apply the lock to
+ * @fl: The lock to be applied
+ * @conflock: Place to return a copy of the conflicting lock, if found.
+ *
+ * Except for the conflock parameter, acts just like posix_lock_file.
+ */
+int posix_lock_file_conf(struct file *filp, struct file_lock *fl,
+ struct file_lock *conflock)
+{
+ return __posix_lock_file_conf(filp->f_dentry->d_inode, fl, conflock);
+}
+EXPORT_SYMBOL(posix_lock_file_conf);
/**
* posix_lock_file_wait - Apply a POSIX-style lock to a file
@@ -980,7 +1020,7 @@ int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
int error;
might_sleep ();
for (;;) {
- error = __posix_lock_file(filp->f_dentry->d_inode, fl);
+ error = posix_lock_file(filp, fl);
if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
break;
error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
@@ -1052,7 +1092,7 @@ int locks_mandatory_area(int read_write, struct inode *inode,
fl.fl_end = offset + count - 1;
for (;;) {
- error = __posix_lock_file(inode, &fl);
+ error = __posix_lock_file_conf(inode, &fl, NULL);
if (error != -EAGAIN)
break;
if (!(fl.fl_flags & FL_SLEEP))
@@ -1544,7 +1584,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
*/
int fcntl_getlk(struct file *filp, struct flock __user *l)
{
- struct file_lock *fl, file_lock;
+ struct file_lock *fl, cfl, file_lock;
struct flock flock;
int error;
@@ -1568,7 +1608,7 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
else
fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
} else {
- fl = posix_test_lock(filp, &file_lock);
+ fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
}
flock.l_type = F_UNLCK;
@@ -1665,7 +1705,7 @@ again:
error = filp->f_op->lock(filp, cmd, file_lock);
else {
for (;;) {
- error = __posix_lock_file(inode, file_lock);
+ error = posix_lock_file(filp, file_lock);
if ((error != -EAGAIN) || (cmd == F_SETLK))
break;
error = wait_event_interruptible(file_lock->fl_wait,
@@ -1698,7 +1738,7 @@ out:
*/
int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
{
- struct file_lock *fl, file_lock;
+ struct file_lock *fl, cfl, file_lock;
struct flock64 flock;
int error;
@@ -1722,7 +1762,7 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
else
fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
} else {
- fl = posix_test_lock(filp, &file_lock);
+ fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
}
flock.l_type = F_UNLCK;
@@ -1808,7 +1848,7 @@ again:
error = filp->f_op->lock(filp, cmd, file_lock);
else {
for (;;) {
- error = __posix_lock_file(inode, file_lock);
+ error = posix_lock_file(filp, file_lock);
if ((error != -EAGAIN) || (cmd == F_SETLK64))
break;
error = wait_event_interruptible(file_lock->fl_wait,
@@ -1936,21 +1976,6 @@ void locks_remove_flock(struct file *filp)
}
/**
- * posix_block_lock - blocks waiting for a file lock
- * @blocker: the lock which is blocking
- * @waiter: the lock which conflicts and has to wait
- *
- * lockd needs to block waiting for locks.
- */
-void
-posix_block_lock(struct file_lock *blocker, struct file_lock *waiter)
-{
- locks_insert_block(blocker, waiter);
-}
-
-EXPORT_SYMBOL(posix_block_lock);
-
-/**
* posix_unblock_lock - stop waiting for a file lock
* @filp: how the file was opened
* @waiter: the lock which was waiting
diff --git a/fs/mbcache.c b/fs/mbcache.c
index 73e754fea2d..e4fde1ab22c 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -311,7 +311,7 @@ fail:
/*
* mb_cache_shrink()
*
- * Removes all cache entires of a device from the cache. All cache entries
+ * Removes all cache entries of a device from the cache. All cache entries
* currently in use cannot be freed, and thus remain in the cache. All others
* are freed.
*
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index dc6a4e4abcd..4a6abc49418 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -56,7 +56,7 @@ void minix_free_block(struct inode * inode, int block)
unsigned int bit,zone;
if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
- printk("trying to free block not in datazone\n");
+ printk("Trying to free block not in datazone\n");
return;
}
zone = block - sbi->s_firstdatazone + 1;
@@ -124,7 +124,7 @@ minix_V1_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
ino / MINIX_INODES_PER_BLOCK;
*bh = sb_bread(sb, block);
if (!*bh) {
- printk("unable to read i-node block\n");
+ printk("Unable to read inode block\n");
return NULL;
}
p = (void *)(*bh)->b_data;
@@ -149,7 +149,7 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
ino / MINIX2_INODES_PER_BLOCK;
*bh = sb_bread(sb, block);
if (!*bh) {
- printk("unable to read i-node block\n");
+ printk("Unable to read inode block\n");
return NULL;
}
p = (void *)(*bh)->b_data;
@@ -204,7 +204,7 @@ void minix_free_inode(struct inode * inode)
bh = sbi->s_imap[ino >> 13];
lock_kernel();
if (!minix_test_and_clear_bit(ino & 8191, bh->b_data))
- printk("minix_free_inode: bit %lu already cleared.\n", ino);
+ printk("minix_free_inode: bit %lu already cleared\n", ino);
unlock_kernel();
mark_buffer_dirty(bh);
out:
@@ -238,7 +238,7 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
return NULL;
}
if (minix_test_and_set_bit(j,bh->b_data)) { /* shouldn't happen */
- printk("new_inode: bit already set");
+ printk("new_inode: bit already set\n");
unlock_kernel();
iput(inode);
return NULL;
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index 732502aabc0..69224d1fe04 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -14,7 +14,7 @@ typedef struct minix_dir_entry minix_dirent;
static int minix_readdir(struct file *, void *, filldir_t);
-struct file_operations minix_dir_operations = {
+const struct file_operations minix_dir_operations = {
.read = generic_read_dir,
.readdir = minix_readdir,
.fsync = minix_sync_file,
diff --git a/fs/minix/file.c b/fs/minix/file.c
index f1d77acb3f0..420b32882a1 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -15,7 +15,7 @@
*/
int minix_sync_file(struct file *, struct dentry *, int);
-struct file_operations minix_file_operations = {
+const struct file_operations minix_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index d9ffc43fee5..2dcccf1d1b7 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -127,11 +127,11 @@ static int minix_remount (struct super_block * sb, int * flags, char * data)
mark_buffer_dirty(sbi->s_sbh);
if (!(sbi->s_mount_state & MINIX_VALID_FS))
- printk ("MINIX-fs warning: remounting unchecked fs, "
- "running fsck is recommended.\n");
+ printk("MINIX-fs warning: remounting unchecked fs, "
+ "running fsck is recommended\n");
else if ((sbi->s_mount_state & MINIX_ERROR_FS))
- printk ("MINIX-fs warning: remounting fs with errors, "
- "running fsck is recommended.\n");
+ printk("MINIX-fs warning: remounting fs with errors, "
+ "running fsck is recommended\n");
}
return 0;
}
@@ -245,11 +245,11 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
mark_buffer_dirty(bh);
}
if (!(sbi->s_mount_state & MINIX_VALID_FS))
- printk ("MINIX-fs: mounting unchecked file system, "
- "running fsck is recommended.\n");
+ printk("MINIX-fs: mounting unchecked file system, "
+ "running fsck is recommended\n");
else if (sbi->s_mount_state & MINIX_ERROR_FS)
- printk ("MINIX-fs: mounting file system with errors, "
- "running fsck is recommended.\n");
+ printk("MINIX-fs: mounting file system with errors, "
+ "running fsck is recommended\n");
return 0;
out_iput:
@@ -273,19 +273,19 @@ out_no_bitmap:
out_no_map:
if (!silent)
- printk ("MINIX-fs: can't allocate map\n");
+ printk("MINIX-fs: can't allocate map\n");
goto out_release;
out_no_fs:
if (!silent)
- printk("VFS: Can't find a Minix or Minix V2 filesystem on device "
- "%s.\n", s->s_id);
+ printk("VFS: Can't find a Minix or Minix V2 filesystem "
+ "on device %s\n", s->s_id);
out_release:
brelse(bh);
goto out;
out_bad_hblock:
- printk("MINIX-fs: blocksize too small for device.\n");
+ printk("MINIX-fs: blocksize too small for device\n");
goto out;
out_bad_sb:
@@ -524,7 +524,7 @@ int minix_sync_inode(struct inode * inode)
sync_dirty_buffer(bh);
if (buffer_req(bh) && !buffer_uptodate(bh))
{
- printk ("IO error syncing minix inode [%s:%08lx]\n",
+ printk("IO error syncing minix inode [%s:%08lx]\n",
inode->i_sb->s_id, inode->i_ino);
err = -1;
}
diff --git a/fs/minix/itree_v1.c b/fs/minix/itree_v1.c
index ba06aef4aca..656b1347a25 100644
--- a/fs/minix/itree_v1.c
+++ b/fs/minix/itree_v1.c
@@ -25,9 +25,9 @@ static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
int n = 0;
if (block < 0) {
- printk("minix_bmap: block<0");
+ printk("minix_bmap: block<0\n");
} else if (block >= (minix_sb(inode->i_sb)->s_max_size/BLOCK_SIZE)) {
- printk("minix_bmap: block>big");
+ printk("minix_bmap: block>big\n");
} else if (block < 7) {
offsets[n++] = block;
} else if ((block -= 7) < 512) {
diff --git a/fs/minix/itree_v2.c b/fs/minix/itree_v2.c
index 3adc7675560..9adcdc754e0 100644
--- a/fs/minix/itree_v2.c
+++ b/fs/minix/itree_v2.c
@@ -25,9 +25,9 @@ static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
int n = 0;
if (block < 0) {
- printk("minix_bmap: block<0");
+ printk("minix_bmap: block<0\n");
} else if (block >= (minix_sb(inode->i_sb)->s_max_size/BLOCK_SIZE)) {
- printk("minix_bmap: block>big");
+ printk("minix_bmap: block>big\n");
} else if (block < 7) {
offsets[n++] = block;
} else if ((block -= 7) < 256) {
diff --git a/fs/minix/minix.h b/fs/minix/minix.h
index e42a8bb8900..c55b77cdcc8 100644
--- a/fs/minix/minix.h
+++ b/fs/minix/minix.h
@@ -81,8 +81,8 @@ extern int minix_sync_file(struct file *, struct dentry *, int);
extern struct inode_operations minix_file_inode_operations;
extern struct inode_operations minix_dir_inode_operations;
-extern struct file_operations minix_file_operations;
-extern struct file_operations minix_dir_operations;
+extern const struct file_operations minix_file_operations;
+extern const struct file_operations minix_dir_operations;
extern struct dentry_operations minix_dentry_operations;
static inline struct minix_sb_info *minix_sb(struct super_block *sb)
diff --git a/fs/mpage.c b/fs/mpage.c
index e431cb3878d..9bf2eb30e6f 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -163,9 +163,19 @@ map_buffer_to_page(struct page *page, struct buffer_head *bh, int page_block)
} while (page_bh != head);
}
+/*
+ * This is the worker routine which does all the work of mapping the disk
+ * blocks and constructs largest possible bios, submits them for IO if the
+ * blocks are not contiguous on the disk.
+ *
+ * We pass a buffer_head back and forth and use its buffer_mapped() flag to
+ * represent the validity of its disk mapping and to decide when to do the next
+ * get_block() call.
+ */
static struct bio *
do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
- sector_t *last_block_in_bio, get_block_t get_block)
+ sector_t *last_block_in_bio, struct buffer_head *map_bh,
+ unsigned long *first_logical_block, get_block_t get_block)
{
struct inode *inode = page->mapping->host;
const unsigned blkbits = inode->i_blkbits;
@@ -173,33 +183,72 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
const unsigned blocksize = 1 << blkbits;
sector_t block_in_file;
sector_t last_block;
+ sector_t last_block_in_file;
sector_t blocks[MAX_BUF_PER_PAGE];
unsigned page_block;
unsigned first_hole = blocks_per_page;
struct block_device *bdev = NULL;
- struct buffer_head bh;
int length;
int fully_mapped = 1;
+ unsigned nblocks;
+ unsigned relative_block;
if (page_has_buffers(page))
goto confused;
block_in_file = (sector_t)page->index << (PAGE_CACHE_SHIFT - blkbits);
- last_block = (i_size_read(inode) + blocksize - 1) >> blkbits;
+ last_block = block_in_file + nr_pages * blocks_per_page;
+ last_block_in_file = (i_size_read(inode) + blocksize - 1) >> blkbits;
+ if (last_block > last_block_in_file)
+ last_block = last_block_in_file;
+ page_block = 0;
+
+ /*
+ * Map blocks using the result from the previous get_blocks call first.
+ */
+ nblocks = map_bh->b_size >> blkbits;
+ if (buffer_mapped(map_bh) && block_in_file > *first_logical_block &&
+ block_in_file < (*first_logical_block + nblocks)) {
+ unsigned map_offset = block_in_file - *first_logical_block;
+ unsigned last = nblocks - map_offset;
+
+ for (relative_block = 0; ; relative_block++) {
+ if (relative_block == last) {
+ clear_buffer_mapped(map_bh);
+ break;
+ }
+ if (page_block == blocks_per_page)
+ break;
+ blocks[page_block] = map_bh->b_blocknr + map_offset +
+ relative_block;
+ page_block++;
+ block_in_file++;
+ }
+ bdev = map_bh->b_bdev;
+ }
+
+ /*
+ * Then do more get_blocks calls until we are done with this page.
+ */
+ map_bh->b_page = page;
+ while (page_block < blocks_per_page) {
+ map_bh->b_state = 0;
+ map_bh->b_size = 0;
- bh.b_page = page;
- for (page_block = 0; page_block < blocks_per_page;
- page_block++, block_in_file++) {
- bh.b_state = 0;
if (block_in_file < last_block) {
- if (get_block(inode, block_in_file, &bh, 0))
+ map_bh->b_size = (last_block-block_in_file) << blkbits;
+ if (get_block(inode, block_in_file, map_bh, 0))
goto confused;
+ *first_logical_block = block_in_file;
}
- if (!buffer_mapped(&bh)) {
+ if (!buffer_mapped(map_bh)) {
fully_mapped = 0;
if (first_hole == blocks_per_page)
first_hole = page_block;
+ page_block++;
+ block_in_file++;
+ clear_buffer_mapped(map_bh);
continue;
}
@@ -209,8 +258,8 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
* we just collected from get_block into the page's buffers
* so readpage doesn't have to repeat the get_block call
*/
- if (buffer_uptodate(&bh)) {
- map_buffer_to_page(page, &bh, page_block);
+ if (buffer_uptodate(map_bh)) {
+ map_buffer_to_page(page, map_bh, page_block);
goto confused;
}
@@ -218,10 +267,20 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
goto confused; /* hole -> non-hole */
/* Contiguous blocks? */
- if (page_block && blocks[page_block-1] != bh.b_blocknr-1)
+ if (page_block && blocks[page_block-1] != map_bh->b_blocknr-1)
goto confused;
- blocks[page_block] = bh.b_blocknr;
- bdev = bh.b_bdev;
+ nblocks = map_bh->b_size >> blkbits;
+ for (relative_block = 0; ; relative_block++) {
+ if (relative_block == nblocks) {
+ clear_buffer_mapped(map_bh);
+ break;
+ } else if (page_block == blocks_per_page)
+ break;
+ blocks[page_block] = map_bh->b_blocknr+relative_block;
+ page_block++;
+ block_in_file++;
+ }
+ bdev = map_bh->b_bdev;
}
if (first_hole != blocks_per_page) {
@@ -260,7 +319,7 @@ alloc_new:
goto alloc_new;
}
- if (buffer_boundary(&bh) || (first_hole != blocks_per_page))
+ if (buffer_boundary(map_bh) || (first_hole != blocks_per_page))
bio = mpage_bio_submit(READ, bio);
else
*last_block_in_bio = blocks[blocks_per_page - 1];
@@ -331,7 +390,10 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
unsigned page_idx;
sector_t last_block_in_bio = 0;
struct pagevec lru_pvec;
+ struct buffer_head map_bh;
+ unsigned long first_logical_block = 0;
+ clear_buffer_mapped(&map_bh);
pagevec_init(&lru_pvec, 0);
for (page_idx = 0; page_idx < nr_pages; page_idx++) {
struct page *page = list_entry(pages->prev, struct page, lru);
@@ -342,7 +404,9 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
page->index, GFP_KERNEL)) {
bio = do_mpage_readpage(bio, page,
nr_pages - page_idx,
- &last_block_in_bio, get_block);
+ &last_block_in_bio, &map_bh,
+ &first_logical_block,
+ get_block);
if (!pagevec_add(&lru_pvec, page))
__pagevec_lru_add(&lru_pvec);
} else {
@@ -364,9 +428,12 @@ int mpage_readpage(struct page *page, get_block_t get_block)
{
struct bio *bio = NULL;
sector_t last_block_in_bio = 0;
+ struct buffer_head map_bh;
+ unsigned long first_logical_block = 0;
- bio = do_mpage_readpage(bio, page, 1,
- &last_block_in_bio, get_block);
+ clear_buffer_mapped(&map_bh);
+ bio = do_mpage_readpage(bio, page, 1, &last_block_in_bio,
+ &map_bh, &first_logical_block, get_block);
if (bio)
mpage_bio_submit(READ, bio);
return 0;
@@ -472,6 +539,7 @@ __mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
for (page_block = 0; page_block < blocks_per_page; ) {
map_bh.b_state = 0;
+ map_bh.b_size = 1 << blkbits;
if (get_block(inode, block_in_file, &map_bh, 1))
goto confused;
if (buffer_new(&map_bh))
diff --git a/fs/namei.c b/fs/namei.c
index c72b940797f..22f6e8d16aa 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -546,6 +546,22 @@ struct path {
struct dentry *dentry;
};
+static inline void dput_path(struct path *path, struct nameidata *nd)
+{
+ dput(path->dentry);
+ if (path->mnt != nd->mnt)
+ mntput(path->mnt);
+}
+
+static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
+{
+ dput(nd->dentry);
+ if (nd->mnt != path->mnt)
+ mntput(nd->mnt);
+ nd->mnt = path->mnt;
+ nd->dentry = path->dentry;
+}
+
static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd)
{
int error;
@@ -555,8 +571,11 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
touch_atime(path->mnt, dentry);
nd_set_link(nd, NULL);
- if (path->mnt == nd->mnt)
- mntget(path->mnt);
+ if (path->mnt != nd->mnt) {
+ path_to_nameidata(path, nd);
+ dget(dentry);
+ }
+ mntget(path->mnt);
cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
error = PTR_ERR(cookie);
if (!IS_ERR(cookie)) {
@@ -573,22 +592,6 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
return error;
}
-static inline void dput_path(struct path *path, struct nameidata *nd)
-{
- dput(path->dentry);
- if (path->mnt != nd->mnt)
- mntput(path->mnt);
-}
-
-static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
-{
- dput(nd->dentry);
- if (nd->mnt != path->mnt)
- mntput(nd->mnt);
- nd->mnt = path->mnt;
- nd->dentry = path->dentry;
-}
-
/*
* This limits recursive symlink follows to 8, while
* limiting consecutive symlinks to 40.
@@ -1353,6 +1356,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
return -ENOENT;
BUG_ON(victim->d_parent->d_inode != dir);
+ audit_inode_child(victim->d_name.name, victim->d_inode, dir->i_ino);
error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
if (error)
@@ -1472,7 +1476,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
DQUOT_INIT(dir);
error = dir->i_op->create(dir, dentry, mode, nd);
if (!error)
- fsnotify_create(dir, dentry->d_name.name);
+ fsnotify_create(dir, dentry);
return error;
}
@@ -1628,6 +1632,12 @@ do_last:
goto exit;
}
+ if (IS_ERR(nd->intent.open.file)) {
+ mutex_unlock(&dir->d_inode->i_mutex);
+ error = PTR_ERR(nd->intent.open.file);
+ goto exit_dput;
+ }
+
/* Negative dentry, just create the file */
if (!path.dentry->d_inode) {
if (!IS_POSIXACL(dir->d_inode))
@@ -1793,7 +1803,7 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
DQUOT_INIT(dir);
error = dir->i_op->mknod(dir, dentry, mode, dev);
if (!error)
- fsnotify_create(dir, dentry->d_name.name);
+ fsnotify_create(dir, dentry);
return error;
}
@@ -1870,7 +1880,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
DQUOT_INIT(dir);
error = dir->i_op->mkdir(dir, dentry, mode);
if (!error)
- fsnotify_mkdir(dir, dentry->d_name.name);
+ fsnotify_mkdir(dir, dentry);
return error;
}
@@ -2133,7 +2143,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, i
DQUOT_INIT(dir);
error = dir->i_op->symlink(dir, dentry, oldname);
if (!error)
- fsnotify_create(dir, dentry->d_name.name);
+ fsnotify_create(dir, dentry);
return error;
}
@@ -2210,7 +2220,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
error = dir->i_op->link(old_dentry, dir, new_dentry);
mutex_unlock(&old_dentry->d_inode->i_mutex);
if (!error)
- fsnotify_create(dir, new_dentry->d_name.name);
+ fsnotify_create(dir, new_dentry);
return error;
}
@@ -2621,16 +2631,27 @@ int __page_symlink(struct inode *inode, const char *symname, int len,
int err = -ENOMEM;
char *kaddr;
+retry:
page = find_or_create_page(mapping, 0, gfp_mask);
if (!page)
goto fail;
err = mapping->a_ops->prepare_write(NULL, page, 0, len-1);
+ if (err == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ goto retry;
+ }
if (err)
goto fail_map;
kaddr = kmap_atomic(page, KM_USER0);
memcpy(kaddr, symname, len-1);
kunmap_atomic(kaddr, KM_USER0);
- mapping->a_ops->commit_write(NULL, page, 0, len-1);
+ err = mapping->a_ops->commit_write(NULL, page, 0, len-1);
+ if (err == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ goto retry;
+ }
+ if (err)
+ goto fail_map;
/*
* Notice that we are _not_ going to block here - end of page is
* unmapped, so this will only try to map the rest of page, see
@@ -2640,7 +2661,8 @@ int __page_symlink(struct inode *inode, const char *symname, int len,
*/
if (!PageUptodate(page)) {
err = mapping->a_ops->readpage(NULL, page);
- wait_on_page_locked(page);
+ if (err != AOP_TRUNCATED_PAGE)
+ wait_on_page_locked(page);
} else {
unlock_page(page);
}
diff --git a/fs/namespace.c b/fs/namespace.c
index 39c81a8d631..bf478addb85 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -43,9 +43,9 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
static int event;
-static struct list_head *mount_hashtable;
+static struct list_head *mount_hashtable __read_mostly;
static int hash_mask __read_mostly, hash_bits __read_mostly;
-static kmem_cache_t *mnt_cache;
+static kmem_cache_t *mnt_cache __read_mostly;
static struct rw_semaphore namespace_sem;
/* /sys/fs */
@@ -399,6 +399,44 @@ struct seq_operations mounts_op = {
.show = show_vfsmnt
};
+static int show_vfsstat(struct seq_file *m, void *v)
+{
+ struct vfsmount *mnt = v;
+ int err = 0;
+
+ /* device */
+ if (mnt->mnt_devname) {
+ seq_puts(m, "device ");
+ mangle(m, mnt->mnt_devname);
+ } else
+ seq_puts(m, "no device");
+
+ /* mount point */
+ seq_puts(m, " mounted on ");
+ seq_path(m, mnt, mnt->mnt_root, " \t\n\\");
+ seq_putc(m, ' ');
+
+ /* file system type */
+ seq_puts(m, "with fstype ");
+ mangle(m, mnt->mnt_sb->s_type->name);
+
+ /* optional statistics */
+ if (mnt->mnt_sb->s_op->show_stats) {
+ seq_putc(m, ' ');
+ err = mnt->mnt_sb->s_op->show_stats(m, mnt);
+ }
+
+ seq_putc(m, '\n');
+ return err;
+}
+
+struct seq_operations mountstats_op = {
+ .start = m_start,
+ .next = m_next,
+ .stop = m_stop,
+ .show = show_vfsstat,
+};
+
/**
* may_umount_tree - check if a mount tree is busy
* @mnt: root of mount tree
@@ -421,9 +459,9 @@ int may_umount_tree(struct vfsmount *mnt)
spin_unlock(&vfsmount_lock);
if (actual_refs > minimum_refs)
- return -EBUSY;
+ return 0;
- return 0;
+ return 1;
}
EXPORT_SYMBOL(may_umount_tree);
@@ -443,10 +481,10 @@ EXPORT_SYMBOL(may_umount_tree);
*/
int may_umount(struct vfsmount *mnt)
{
- int ret = 0;
+ int ret = 1;
spin_lock(&vfsmount_lock);
if (propagate_mount_busy(mnt, 2))
- ret = -EBUSY;
+ ret = 0;
spin_unlock(&vfsmount_lock);
return ret;
}
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index cfd76f431dc..f0860c602d8 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -49,7 +49,7 @@ extern int ncp_symlink(struct inode *, struct dentry *, const char *);
#define ncp_symlink NULL
#endif
-struct file_operations ncp_dir_operations =
+const struct file_operations ncp_dir_operations =
{
.read = generic_read_dir,
.readdir = ncp_readdir,
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index ebdad8f6398..e6b7c67cf05 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -283,7 +283,7 @@ static int ncp_release(struct inode *inode, struct file *file) {
return 0;
}
-struct file_operations ncp_file_operations =
+const struct file_operations ncp_file_operations =
{
.llseek = remote_llseek,
.read = ncp_file_read,
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index fcd97406a77..90c95adc8c1 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -14,6 +14,7 @@
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/nfs_fs.h>
+#include <linux/mutex.h>
#include <net/inet_sock.h>
@@ -31,7 +32,7 @@ struct nfs_callback_data {
};
static struct nfs_callback_data nfs_callback_info;
-static DECLARE_MUTEX(nfs_callback_sema);
+static DEFINE_MUTEX(nfs_callback_mutex);
static struct svc_program nfs4_callback_program;
unsigned int nfs_callback_set_tcpport;
@@ -55,7 +56,12 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
complete(&nfs_callback_info.started);
- while (nfs_callback_info.users != 0 || !signalled()) {
+ for(;;) {
+ if (signalled()) {
+ if (nfs_callback_info.users == 0)
+ break;
+ flush_signals(current);
+ }
/*
* Listen for a request on the socket
*/
@@ -73,6 +79,7 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
svc_process(serv, rqstp);
}
+ svc_exit_thread(rqstp);
nfs_callback_info.pid = 0;
complete(&nfs_callback_info.stopped);
unlock_kernel();
@@ -89,7 +96,7 @@ int nfs_callback_up(void)
int ret = 0;
lock_kernel();
- down(&nfs_callback_sema);
+ mutex_lock(&nfs_callback_mutex);
if (nfs_callback_info.users++ || nfs_callback_info.pid != 0)
goto out;
init_completion(&nfs_callback_info.started);
@@ -115,7 +122,7 @@ int nfs_callback_up(void)
nfs_callback_info.serv = serv;
wait_for_completion(&nfs_callback_info.started);
out:
- up(&nfs_callback_sema);
+ mutex_unlock(&nfs_callback_mutex);
unlock_kernel();
return ret;
out_destroy:
@@ -133,13 +140,15 @@ int nfs_callback_down(void)
int ret = 0;
lock_kernel();
- down(&nfs_callback_sema);
- if (--nfs_callback_info.users || nfs_callback_info.pid == 0)
- goto out;
- kill_proc(nfs_callback_info.pid, SIGKILL, 1);
- wait_for_completion(&nfs_callback_info.stopped);
-out:
- up(&nfs_callback_sema);
+ mutex_lock(&nfs_callback_mutex);
+ nfs_callback_info.users--;
+ do {
+ if (nfs_callback_info.users != 0 || nfs_callback_info.pid == 0)
+ break;
+ if (kill_proc(nfs_callback_info.pid, SIGKILL, 1) < 0)
+ break;
+ } while (wait_for_completion_timeout(&nfs_callback_info.stopped, 5*HZ) == 0);
+ mutex_unlock(&nfs_callback_mutex);
unlock_kernel();
return ret;
}
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 7c33b9a81a9..05c38cf40b6 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -330,7 +330,7 @@ static unsigned encode_op_hdr(struct xdr_stream *xdr, uint32_t op, uint32_t res)
static unsigned encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr, const struct cb_getattrres *res)
{
- uint32_t *savep;
+ uint32_t *savep = NULL;
unsigned status = res->status;
if (unlikely(status != 0))
@@ -358,23 +358,26 @@ static unsigned process_op(struct svc_rqst *rqstp,
struct xdr_stream *xdr_in, void *argp,
struct xdr_stream *xdr_out, void *resp)
{
- struct callback_op *op;
- unsigned int op_nr;
+ struct callback_op *op = &callback_ops[0];
+ unsigned int op_nr = OP_CB_ILLEGAL;
unsigned int status = 0;
long maxlen;
unsigned res;
dprintk("%s: start\n", __FUNCTION__);
status = decode_op_hdr(xdr_in, &op_nr);
- if (unlikely(status != 0)) {
- op_nr = OP_CB_ILLEGAL;
- op = &callback_ops[0];
- } else if (unlikely(op_nr != OP_CB_GETATTR && op_nr != OP_CB_RECALL)) {
- op_nr = OP_CB_ILLEGAL;
- op = &callback_ops[0];
- status = htonl(NFS4ERR_OP_ILLEGAL);
- } else
- op = &callback_ops[op_nr];
+ if (likely(status == 0)) {
+ switch (op_nr) {
+ case OP_CB_GETATTR:
+ case OP_CB_RECALL:
+ op = &callback_ops[op_nr];
+ break;
+ default:
+ op_nr = OP_CB_ILLEGAL;
+ op = &callback_ops[0];
+ status = htonl(NFS4ERR_OP_ILLEGAL);
+ }
+ }
maxlen = xdr_out->end - xdr_out->p;
if (maxlen > 0 && maxlen < PAGE_SIZE) {
@@ -416,6 +419,7 @@ static int nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *resp
decode_compound_hdr_arg(&xdr_in, &hdr_arg);
hdr_res.taglen = hdr_arg.taglen;
hdr_res.tag = hdr_arg.tag;
+ hdr_res.nops = NULL;
encode_compound_hdr_res(&xdr_out, &hdr_res);
for (;;) {
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index c6f07c1c71e..d3be923d4e4 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -421,3 +421,22 @@ void nfs_delegation_reap_unclaimed(struct nfs4_client *clp)
nfs_free_delegation(delegation);
}
}
+
+int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
+{
+ struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
+ struct nfs_inode *nfsi = NFS_I(inode);
+ struct nfs_delegation *delegation;
+ int res = 0;
+
+ if (nfsi->delegation_state == 0)
+ return 0;
+ spin_lock(&clp->cl_lock);
+ delegation = nfsi->delegation;
+ if (delegation != NULL) {
+ memcpy(dst->data, delegation->stateid.data, sizeof(dst->data));
+ res = 1;
+ }
+ spin_unlock(&clp->cl_lock);
+ return res;
+}
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 7a0b2bfce77..3858694652f 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -41,6 +41,7 @@ void nfs_delegation_reap_unclaimed(struct nfs4_client *clp);
int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
+int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
static inline int nfs_have_delegation(struct inode *inode, int flags)
{
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index a1554bead69..a23f3489416 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -34,6 +34,7 @@
#include "nfs4_fs.h"
#include "delegation.h"
+#include "iostat.h"
#define NFS_PARANOIA 1
/* #define NFS_DEBUG_VERBOSE 1 */
@@ -53,7 +54,7 @@ static int nfs_rename(struct inode *, struct dentry *,
static int nfs_fsync_dir(struct file *, struct dentry *, int);
static loff_t nfs_llseek_dir(struct file *, loff_t, int);
-struct file_operations nfs_dir_operations = {
+const struct file_operations nfs_dir_operations = {
.llseek = nfs_llseek_dir,
.read = generic_read_dir,
.readdir = nfs_readdir,
@@ -129,6 +130,9 @@ nfs_opendir(struct inode *inode, struct file *filp)
{
int res = 0;
+ dfprintk(VFS, "NFS: opendir(%s/%ld)\n",
+ inode->i_sb->s_id, inode->i_ino);
+
lock_kernel();
/* Call generic open code in order to cache credentials */
if (!res)
@@ -172,7 +176,9 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
unsigned long timestamp;
int error;
- dfprintk(VFS, "NFS: nfs_readdir_filler() reading cookie %Lu into page %lu.\n", (long long)desc->entry->cookie, page->index);
+ dfprintk(DIRCACHE, "NFS: %s: reading cookie %Lu into page %lu\n",
+ __FUNCTION__, (long long)desc->entry->cookie,
+ page->index);
again:
timestamp = jiffies;
@@ -244,7 +250,8 @@ int find_dirent(nfs_readdir_descriptor_t *desc)
status;
while((status = dir_decode(desc)) == 0) {
- dfprintk(VFS, "NFS: found cookie %Lu\n", (unsigned long long)entry->cookie);
+ dfprintk(DIRCACHE, "NFS: %s: examining cookie %Lu\n",
+ __FUNCTION__, (unsigned long long)entry->cookie);
if (entry->prev_cookie == *desc->dir_cookie)
break;
if (loop_count++ > 200) {
@@ -252,7 +259,6 @@ int find_dirent(nfs_readdir_descriptor_t *desc)
schedule();
}
}
- dfprintk(VFS, "NFS: find_dirent() returns %d\n", status);
return status;
}
@@ -276,7 +282,8 @@ int find_dirent_index(nfs_readdir_descriptor_t *desc)
if (status)
break;
- dfprintk(VFS, "NFS: found cookie %Lu at index %Ld\n", (unsigned long long)entry->cookie, desc->current_index);
+ dfprintk(DIRCACHE, "NFS: found cookie %Lu at index %Ld\n",
+ (unsigned long long)entry->cookie, desc->current_index);
if (desc->file->f_pos == desc->current_index) {
*desc->dir_cookie = entry->cookie;
@@ -288,7 +295,6 @@ int find_dirent_index(nfs_readdir_descriptor_t *desc)
schedule();
}
}
- dfprintk(VFS, "NFS: find_dirent_index() returns %d\n", status);
return status;
}
@@ -303,7 +309,9 @@ int find_dirent_page(nfs_readdir_descriptor_t *desc)
struct page *page;
int status;
- dfprintk(VFS, "NFS: find_dirent_page() searching directory page %ld\n", desc->page_index);
+ dfprintk(DIRCACHE, "NFS: %s: searching page %ld for target %Lu\n",
+ __FUNCTION__, desc->page_index,
+ (long long) *desc->dir_cookie);
page = read_cache_page(inode->i_mapping, desc->page_index,
(filler_t *)nfs_readdir_filler, desc);
@@ -324,7 +332,7 @@ int find_dirent_page(nfs_readdir_descriptor_t *desc)
if (status < 0)
dir_page_release(desc);
out:
- dfprintk(VFS, "NFS: find_dirent_page() returns %d\n", status);
+ dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __FUNCTION__, status);
return status;
read_error:
page_cache_release(page);
@@ -346,13 +354,15 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
/* Always search-by-index from the beginning of the cache */
if (*desc->dir_cookie == 0) {
- dfprintk(VFS, "NFS: readdir_search_pagecache() searching for offset %Ld\n", (long long)desc->file->f_pos);
+ dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for offset %Ld\n",
+ (long long)desc->file->f_pos);
desc->page_index = 0;
desc->entry->cookie = desc->entry->prev_cookie = 0;
desc->entry->eof = 0;
desc->current_index = 0;
} else
- dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (unsigned long long)*desc->dir_cookie);
+ dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for cookie %Lu\n",
+ (unsigned long long)*desc->dir_cookie);
for (;;) {
res = find_dirent_page(desc);
@@ -365,7 +375,8 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
schedule();
}
}
- dfprintk(VFS, "NFS: readdir_search_pagecache() returned %d\n", res);
+
+ dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __FUNCTION__, res);
return res;
}
@@ -390,7 +401,8 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
int loop_count = 0,
res;
- dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)entry->cookie);
+ dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n",
+ (unsigned long long)entry->cookie);
for(;;) {
unsigned d_type = DT_UNKNOWN;
@@ -427,7 +439,8 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
dir_page_release(desc);
if (dentry != NULL)
dput(dentry);
- dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (unsigned long long)*desc->dir_cookie, res);
+ dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
+ (unsigned long long)*desc->dir_cookie, res);
return res;
}
@@ -453,7 +466,8 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
struct page *page = NULL;
int status;
- dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (unsigned long long)*desc->dir_cookie);
+ dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n",
+ (unsigned long long)*desc->dir_cookie);
page = alloc_page(GFP_HIGHUSER);
if (!page) {
@@ -485,7 +499,8 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
desc->entry->cookie = desc->entry->prev_cookie = 0;
desc->entry->eof = 0;
out:
- dfprintk(VFS, "NFS: uncached_readdir() returns %d\n", status);
+ dfprintk(DIRCACHE, "NFS: %s: returns %d\n",
+ __FUNCTION__, status);
return status;
out_release:
dir_page_release(desc);
@@ -507,6 +522,11 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
struct nfs_fattr fattr;
long res;
+ dfprintk(VFS, "NFS: readdir(%s/%s) starting at cookie %Lu\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+ (long long)filp->f_pos);
+ nfs_inc_stats(inode, NFSIOS_VFSGETDENTS);
+
lock_kernel();
res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
@@ -566,9 +586,12 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
}
unlock_kernel();
- if (res < 0)
- return res;
- return 0;
+ if (res > 0)
+ res = 0;
+ dfprintk(VFS, "NFS: readdir(%s/%s) returns %ld\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+ res);
+ return res;
}
loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
@@ -599,6 +622,10 @@ out:
*/
int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync)
{
+ dfprintk(VFS, "NFS: fsync_dir(%s/%s) datasync %d\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+ datasync);
+
return 0;
}
@@ -713,6 +740,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
parent = dget_parent(dentry);
lock_kernel();
dir = parent->d_inode;
+ nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE);
inode = dentry->d_inode;
if (!inode) {
@@ -722,8 +750,9 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
}
if (is_bad_inode(inode)) {
- dfprintk(VFS, "nfs_lookup_validate: %s/%s has dud inode\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ dfprintk(LOOKUPCACHE, "%s: %s/%s has dud inode\n",
+ __FUNCTION__, dentry->d_parent->d_name.name,
+ dentry->d_name.name);
goto out_bad;
}
@@ -755,6 +784,9 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
out_valid:
unlock_kernel();
dput(parent);
+ dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is valid\n",
+ __FUNCTION__, dentry->d_parent->d_name.name,
+ dentry->d_name.name);
return 1;
out_zap_parent:
nfs_zap_caches(dir);
@@ -771,6 +803,9 @@ out_zap_parent:
d_drop(dentry);
unlock_kernel();
dput(parent);
+ dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n",
+ __FUNCTION__, dentry->d_parent->d_name.name,
+ dentry->d_name.name);
return 0;
}
@@ -844,6 +879,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
dfprintk(VFS, "NFS: lookup(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
+ nfs_inc_stats(dir, NFSIOS_VFSLOOKUP);
res = ERR_PTR(-ENAMETOOLONG);
if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
@@ -865,9 +901,9 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
res = ERR_PTR(error);
goto out_unlock;
}
- res = ERR_PTR(-EACCES);
inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
- if (!inode)
+ res = (struct dentry *)inode;
+ if (IS_ERR(res))
goto out_unlock;
no_entry:
res = d_add_unique(dentry, inode);
@@ -912,6 +948,9 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
struct dentry *res = NULL;
int error;
+ dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
+ dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
+
/* Check that we are indeed trying to open this file */
if (!is_atomic_open(dir, nd))
goto no_open;
@@ -1057,7 +1096,7 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
return NULL;
dentry->d_op = NFS_PROTO(dir)->dentry_ops;
inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr);
- if (!inode) {
+ if (IS_ERR(inode)) {
dput(dentry);
return NULL;
}
@@ -1095,9 +1134,9 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
if (error < 0)
goto out_err;
}
- error = -ENOMEM;
inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
- if (inode == NULL)
+ error = PTR_ERR(inode);
+ if (IS_ERR(inode))
goto out_err;
d_instantiate(dentry, inode);
return 0;
@@ -1119,8 +1158,8 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
int error;
int open_flags = 0;
- dfprintk(VFS, "NFS: create(%s/%ld, %s\n", dir->i_sb->s_id,
- dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
+ dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
attr.ia_mode = mode;
attr.ia_valid = ATTR_MODE;
@@ -1153,8 +1192,8 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
struct iattr attr;
int status;
- dfprintk(VFS, "NFS: mknod(%s/%ld, %s\n", dir->i_sb->s_id,
- dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: mknod(%s/%ld), %s\n",
+ dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
if (!new_valid_dev(rdev))
return -EINVAL;
@@ -1186,8 +1225,8 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
struct iattr attr;
int error;
- dfprintk(VFS, "NFS: mkdir(%s/%ld, %s\n", dir->i_sb->s_id,
- dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: mkdir(%s/%ld), %s\n",
+ dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
attr.ia_valid = ATTR_MODE;
attr.ia_mode = mode | S_IFDIR;
@@ -1212,8 +1251,8 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
{
int error;
- dfprintk(VFS, "NFS: rmdir(%s/%ld, %s\n", dir->i_sb->s_id,
- dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n",
+ dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
lock_kernel();
nfs_begin_data_update(dir);
@@ -1241,6 +1280,7 @@ static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
atomic_read(&dentry->d_count));
+ nfs_inc_stats(dir, NFSIOS_SILLYRENAME);
#ifdef NFS_PARANOIA
if (!dentry->d_inode)
@@ -1268,8 +1308,8 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
sillycounter++;
sprintf(suffix, "%*.*x", countersize, countersize, sillycounter);
- dfprintk(VFS, "trying to rename %s to %s\n",
- dentry->d_name.name, silly);
+ dfprintk(VFS, "NFS: trying to rename %s to %s\n",
+ dentry->d_name.name, silly);
sdentry = lookup_one_len(silly, dentry->d_parent, slen);
/*
@@ -1640,6 +1680,8 @@ int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
struct rpc_cred *cred;
int res = 0;
+ nfs_inc_stats(inode, NFSIOS_VFSACCESS);
+
if (mask == 0)
goto out;
/* Is this sys_access() ? */
@@ -1679,13 +1721,15 @@ force_lookup:
res = PTR_ERR(cred);
unlock_kernel();
out:
+ dfprintk(VFS, "NFS: permission(%s/%ld), mask=0x%x, res=%d\n",
+ inode->i_sb->s_id, inode->i_ino, mask, res);
return res;
out_notsup:
res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
if (res == 0)
res = generic_permission(inode, mask, NULL);
unlock_kernel();
- return res;
+ goto out;
}
/*
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 4ae2f3b33fe..0f583cb16dd 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -7,11 +7,11 @@
*
* There are important applications whose performance or correctness
* depends on uncached access to file data. Database clusters
- * (multiple copies of the same instance running on separate hosts)
+ * (multiple copies of the same instance running on separate hosts)
* implement their own cache coherency protocol that subsumes file
- * system cache protocols. Applications that process datasets
- * considerably larger than the client's memory do not always benefit
- * from a local cache. A streaming video server, for instance, has no
+ * system cache protocols. Applications that process datasets
+ * considerably larger than the client's memory do not always benefit
+ * from a local cache. A streaming video server, for instance, has no
* need to cache the contents of a file.
*
* When an application requests uncached I/O, all read and write requests
@@ -34,6 +34,7 @@
* 08 Jun 2003 Port to 2.5 APIs --cel
* 31 Mar 2004 Handle direct I/O without VFS support --cel
* 15 Sep 2004 Parallel async reads --cel
+ * 04 May 2005 support O_DIRECT with aio --cel
*
*/
@@ -54,10 +55,10 @@
#include <asm/uaccess.h>
#include <asm/atomic.h>
+#include "iostat.h"
+
#define NFSDBG_FACILITY NFSDBG_VFS
-#define MAX_DIRECTIO_SIZE (4096UL << PAGE_SHIFT)
-static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty);
static kmem_cache_t *nfs_direct_cachep;
/*
@@ -65,38 +66,78 @@ static kmem_cache_t *nfs_direct_cachep;
*/
struct nfs_direct_req {
struct kref kref; /* release manager */
- struct list_head list; /* nfs_read_data structs */
- wait_queue_head_t wait; /* wait for i/o completion */
+
+ /* I/O parameters */
+ struct list_head list, /* nfs_read/write_data structs */
+ rewrite_list; /* saved nfs_write_data structs */
+ struct nfs_open_context *ctx; /* file open context info */
+ struct kiocb * iocb; /* controlling i/o request */
+ struct inode * inode; /* target file of i/o */
+ unsigned long user_addr; /* location of user's buffer */
+ size_t user_count; /* total bytes to move */
+ loff_t pos; /* starting offset in file */
struct page ** pages; /* pages in our buffer */
unsigned int npages; /* count of pages */
- atomic_t complete, /* i/os we're waiting for */
- count, /* bytes actually processed */
+
+ /* completion state */
+ spinlock_t lock; /* protect completion state */
+ int outstanding; /* i/os we're waiting for */
+ ssize_t count, /* bytes actually processed */
error; /* any reported error */
+ struct completion completion; /* wait for i/o completion */
+
+ /* commit state */
+ struct nfs_write_data * commit_data; /* special write_data for commits */
+ int flags;
+#define NFS_ODIRECT_DO_COMMIT (1) /* an unstable reply was received */
+#define NFS_ODIRECT_RESCHED_WRITES (2) /* write verification failed */
+ struct nfs_writeverf verf; /* unstable write verifier */
};
+static void nfs_direct_write_schedule(struct nfs_direct_req *dreq, int sync);
+static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode);
/**
- * nfs_get_user_pages - find and set up pages underlying user's buffer
- * rw: direction (read or write)
- * user_addr: starting address of this segment of user's buffer
- * count: size of this segment
- * @pages: returned array of page struct pointers underlying user's buffer
+ * nfs_direct_IO - NFS address space operation for direct I/O
+ * @rw: direction (read or write)
+ * @iocb: target I/O control block
+ * @iov: array of vectors that define I/O buffer
+ * @pos: offset in file to begin the operation
+ * @nr_segs: size of iovec array
+ *
+ * The presence of this routine in the address space ops vector means
+ * the NFS client supports direct I/O. However, we shunt off direct
+ * read and write requests before the VFS gets them, so this method
+ * should never be called.
*/
-static inline int
-nfs_get_user_pages(int rw, unsigned long user_addr, size_t size,
- struct page ***pages)
+ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs)
+{
+ struct dentry *dentry = iocb->ki_filp->f_dentry;
+
+ dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n",
+ dentry->d_name.name, (long long) pos, nr_segs);
+
+ return -EINVAL;
+}
+
+static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty)
+{
+ int i;
+ for (i = 0; i < npages; i++) {
+ struct page *page = pages[i];
+ if (do_dirty && !PageCompound(page))
+ set_page_dirty_lock(page);
+ page_cache_release(page);
+ }
+ kfree(pages);
+}
+
+static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t size, struct page ***pages)
{
int result = -ENOMEM;
unsigned long page_count;
size_t array_size;
- /* set an arbitrary limit to prevent type overflow */
- /* XXX: this can probably be as large as INT_MAX */
- if (size > MAX_DIRECTIO_SIZE) {
- *pages = NULL;
- return -EFBIG;
- }
-
page_count = (user_addr + size + PAGE_SIZE - 1) >> PAGE_SHIFT;
page_count -= user_addr >> PAGE_SHIFT;
@@ -108,75 +149,117 @@ nfs_get_user_pages(int rw, unsigned long user_addr, size_t size,
page_count, (rw == READ), 0,
*pages, NULL);
up_read(&current->mm->mmap_sem);
- /*
- * If we got fewer pages than expected from get_user_pages(),
- * the user buffer runs off the end of a mapping; return EFAULT.
- */
- if (result >= 0 && result < page_count) {
- nfs_free_user_pages(*pages, result, 0);
+ if (result != page_count) {
+ /*
+ * If we got fewer pages than expected from
+ * get_user_pages(), the user buffer runs off the
+ * end of a mapping; return EFAULT.
+ */
+ if (result >= 0) {
+ nfs_free_user_pages(*pages, result, 0);
+ result = -EFAULT;
+ } else
+ kfree(*pages);
*pages = NULL;
- result = -EFAULT;
}
}
return result;
}
-/**
- * nfs_free_user_pages - tear down page struct array
- * @pages: array of page struct pointers underlying target buffer
- * @npages: number of pages in the array
- * @do_dirty: dirty the pages as we release them
- */
-static void
-nfs_free_user_pages(struct page **pages, int npages, int do_dirty)
+static inline struct nfs_direct_req *nfs_direct_req_alloc(void)
{
- int i;
- for (i = 0; i < npages; i++) {
- struct page *page = pages[i];
- if (do_dirty && !PageCompound(page))
- set_page_dirty_lock(page);
- page_cache_release(page);
- }
- kfree(pages);
+ struct nfs_direct_req *dreq;
+
+ dreq = kmem_cache_alloc(nfs_direct_cachep, SLAB_KERNEL);
+ if (!dreq)
+ return NULL;
+
+ kref_init(&dreq->kref);
+ init_completion(&dreq->completion);
+ INIT_LIST_HEAD(&dreq->list);
+ INIT_LIST_HEAD(&dreq->rewrite_list);
+ dreq->iocb = NULL;
+ dreq->ctx = NULL;
+ spin_lock_init(&dreq->lock);
+ dreq->outstanding = 0;
+ dreq->count = 0;
+ dreq->error = 0;
+ dreq->flags = 0;
+
+ return dreq;
}
-/**
- * nfs_direct_req_release - release nfs_direct_req structure for direct read
- * @kref: kref object embedded in an nfs_direct_req structure
- *
- */
static void nfs_direct_req_release(struct kref *kref)
{
struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref);
+
+ if (dreq->ctx != NULL)
+ put_nfs_open_context(dreq->ctx);
kmem_cache_free(nfs_direct_cachep, dreq);
}
-/**
- * nfs_direct_read_alloc - allocate nfs_read_data structures for direct read
- * @count: count of bytes for the read request
- * @rsize: local rsize setting
+/*
+ * Collects and returns the final error value/byte-count.
+ */
+static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq)
+{
+ ssize_t result = -EIOCBQUEUED;
+
+ /* Async requests don't wait here */
+ if (dreq->iocb)
+ goto out;
+
+ result = wait_for_completion_interruptible(&dreq->completion);
+
+ if (!result)
+ result = dreq->error;
+ if (!result)
+ result = dreq->count;
+
+out:
+ kref_put(&dreq->kref, nfs_direct_req_release);
+ return (ssize_t) result;
+}
+
+/*
+ * We must hold a reference to all the pages in this direct read request
+ * until the RPCs complete. This could be long *after* we are woken up in
+ * nfs_direct_wait (for instance, if someone hits ^C on a slow server).
*
+ * In addition, synchronous I/O uses a stack-allocated iocb. Thus we
+ * can't trust the iocb is still valid here if this is a synchronous
+ * request. If the waiter is woken prematurely, the iocb is long gone.
+ */
+static void nfs_direct_complete(struct nfs_direct_req *dreq)
+{
+ nfs_free_user_pages(dreq->pages, dreq->npages, 1);
+
+ if (dreq->iocb) {
+ long res = (long) dreq->error;
+ if (!res)
+ res = (long) dreq->count;
+ aio_complete(dreq->iocb, res, 0);
+ }
+ complete_all(&dreq->completion);
+
+ kref_put(&dreq->kref, nfs_direct_req_release);
+}
+
+/*
* Note we also set the number of requests we have in the dreq when we are
* done. This prevents races with I/O completion so we will always wait
* until all requests have been dispatched and completed.
*/
-static struct nfs_direct_req *nfs_direct_read_alloc(size_t nbytes, unsigned int rsize)
+static struct nfs_direct_req *nfs_direct_read_alloc(size_t nbytes, size_t rsize)
{
struct list_head *list;
struct nfs_direct_req *dreq;
- unsigned int reads = 0;
unsigned int rpages = (rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
- dreq = kmem_cache_alloc(nfs_direct_cachep, SLAB_KERNEL);
+ dreq = nfs_direct_req_alloc();
if (!dreq)
return NULL;
- kref_init(&dreq->kref);
- init_waitqueue_head(&dreq->wait);
- INIT_LIST_HEAD(&dreq->list);
- atomic_set(&dreq->count, 0);
- atomic_set(&dreq->error, 0);
-
list = &dreq->list;
for(;;) {
struct nfs_read_data *data = nfs_readdata_alloc(rpages);
@@ -196,72 +279,70 @@ static struct nfs_direct_req *nfs_direct_read_alloc(size_t nbytes, unsigned int
list_add(&data->pages, list);
data->req = (struct nfs_page *) dreq;
- reads++;
+ dreq->outstanding++;
if (nbytes <= rsize)
break;
nbytes -= rsize;
}
kref_get(&dreq->kref);
- atomic_set(&dreq->complete, reads);
return dreq;
}
-/**
- * nfs_direct_read_result - handle a read reply for a direct read request
- * @data: address of NFS READ operation control block
- * @status: status of this NFS READ operation
- *
- * We must hold a reference to all the pages in this direct read request
- * until the RPCs complete. This could be long *after* we are woken up in
- * nfs_direct_read_wait (for instance, if someone hits ^C on a slow server).
- */
-static void nfs_direct_read_result(struct nfs_read_data *data, int status)
+static void nfs_direct_read_result(struct rpc_task *task, void *calldata)
{
+ struct nfs_read_data *data = calldata;
struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
- if (likely(status >= 0))
- atomic_add(data->res.count, &dreq->count);
+ if (nfs_readpage_result(task, data) != 0)
+ return;
+
+ spin_lock(&dreq->lock);
+
+ if (likely(task->tk_status >= 0))
+ dreq->count += data->res.count;
else
- atomic_set(&dreq->error, status);
+ dreq->error = task->tk_status;
- if (unlikely(atomic_dec_and_test(&dreq->complete))) {
- nfs_free_user_pages(dreq->pages, dreq->npages, 1);
- wake_up(&dreq->wait);
- kref_put(&dreq->kref, nfs_direct_req_release);
+ if (--dreq->outstanding) {
+ spin_unlock(&dreq->lock);
+ return;
}
+
+ spin_unlock(&dreq->lock);
+ nfs_direct_complete(dreq);
}
-/**
- * nfs_direct_read_schedule - dispatch NFS READ operations for a direct read
- * @dreq: address of nfs_direct_req struct for this request
- * @inode: target inode
- * @ctx: target file open context
- * @user_addr: starting address of this segment of user's buffer
- * @count: size of this segment
- * @file_offset: offset in file to begin the operation
- *
+static const struct rpc_call_ops nfs_read_direct_ops = {
+ .rpc_call_done = nfs_direct_read_result,
+ .rpc_release = nfs_readdata_release,
+};
+
+/*
* For each nfs_read_data struct that was allocated on the list, dispatch
* an NFS READ operation
*/
-static void nfs_direct_read_schedule(struct nfs_direct_req *dreq,
- struct inode *inode, struct nfs_open_context *ctx,
- unsigned long user_addr, size_t count, loff_t file_offset)
+static void nfs_direct_read_schedule(struct nfs_direct_req *dreq)
{
+ struct nfs_open_context *ctx = dreq->ctx;
+ struct inode *inode = ctx->dentry->d_inode;
struct list_head *list = &dreq->list;
struct page **pages = dreq->pages;
+ size_t count = dreq->user_count;
+ loff_t pos = dreq->pos;
+ size_t rsize = NFS_SERVER(inode)->rsize;
unsigned int curpage, pgbase;
- unsigned int rsize = NFS_SERVER(inode)->rsize;
curpage = 0;
- pgbase = user_addr & ~PAGE_MASK;
+ pgbase = dreq->user_addr & ~PAGE_MASK;
do {
struct nfs_read_data *data;
- unsigned int bytes;
+ size_t bytes;
bytes = rsize;
if (count < rsize)
bytes = count;
+ BUG_ON(list_empty(list));
data = list_entry(list->next, struct nfs_read_data, pages);
list_del_init(&data->pages);
@@ -269,7 +350,7 @@ static void nfs_direct_read_schedule(struct nfs_direct_req *dreq,
data->cred = ctx->cred;
data->args.fh = NFS_FH(inode);
data->args.context = ctx;
- data->args.offset = file_offset;
+ data->args.offset = pos;
data->args.pgbase = pgbase;
data->args.pages = &pages[curpage];
data->args.count = bytes;
@@ -277,77 +358,38 @@ static void nfs_direct_read_schedule(struct nfs_direct_req *dreq,
data->res.eof = 0;
data->res.count = bytes;
+ rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC,
+ &nfs_read_direct_ops, data);
NFS_PROTO(inode)->read_setup(data);
data->task.tk_cookie = (unsigned long) inode;
- data->complete = nfs_direct_read_result;
lock_kernel();
rpc_execute(&data->task);
unlock_kernel();
- dfprintk(VFS, "NFS: %4d initiated direct read call (req %s/%Ld, %u bytes @ offset %Lu)\n",
+ dfprintk(VFS, "NFS: %5u initiated direct read call (req %s/%Ld, %zu bytes @ offset %Lu)\n",
data->task.tk_pid,
inode->i_sb->s_id,
(long long)NFS_FILEID(inode),
bytes,
(unsigned long long)data->args.offset);
- file_offset += bytes;
+ pos += bytes;
pgbase += bytes;
curpage += pgbase >> PAGE_SHIFT;
pgbase &= ~PAGE_MASK;
count -= bytes;
} while (count != 0);
+ BUG_ON(!list_empty(list));
}
-/**
- * nfs_direct_read_wait - wait for I/O completion for direct reads
- * @dreq: request on which we are to wait
- * @intr: whether or not this wait can be interrupted
- *
- * Collects and returns the final error value/byte-count.
- */
-static ssize_t nfs_direct_read_wait(struct nfs_direct_req *dreq, int intr)
-{
- int result = 0;
-
- if (intr) {
- result = wait_event_interruptible(dreq->wait,
- (atomic_read(&dreq->complete) == 0));
- } else {
- wait_event(dreq->wait, (atomic_read(&dreq->complete) == 0));
- }
-
- if (!result)
- result = atomic_read(&dreq->error);
- if (!result)
- result = atomic_read(&dreq->count);
-
- kref_put(&dreq->kref, nfs_direct_req_release);
- return (ssize_t) result;
-}
-
-/**
- * nfs_direct_read_seg - Read in one iov segment. Generate separate
- * read RPCs for each "rsize" bytes.
- * @inode: target inode
- * @ctx: target file open context
- * @user_addr: starting address of this segment of user's buffer
- * @count: size of this segment
- * @file_offset: offset in file to begin the operation
- * @pages: array of addresses of page structs defining user's buffer
- * @nr_pages: number of pages in the array
- *
- */
-static ssize_t nfs_direct_read_seg(struct inode *inode,
- struct nfs_open_context *ctx, unsigned long user_addr,
- size_t count, loff_t file_offset, struct page **pages,
- unsigned int nr_pages)
+static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos, struct page **pages, unsigned int nr_pages)
{
ssize_t result;
sigset_t oldset;
+ struct inode *inode = iocb->ki_filp->f_mapping->host;
struct rpc_clnt *clnt = NFS_CLIENT(inode);
struct nfs_direct_req *dreq;
@@ -355,284 +397,350 @@ static ssize_t nfs_direct_read_seg(struct inode *inode,
if (!dreq)
return -ENOMEM;
+ dreq->user_addr = user_addr;
+ dreq->user_count = count;
+ dreq->pos = pos;
dreq->pages = pages;
dreq->npages = nr_pages;
+ dreq->inode = inode;
+ dreq->ctx = get_nfs_open_context((struct nfs_open_context *)iocb->ki_filp->private_data);
+ if (!is_sync_kiocb(iocb))
+ dreq->iocb = iocb;
+ nfs_add_stats(inode, NFSIOS_DIRECTREADBYTES, count);
rpc_clnt_sigmask(clnt, &oldset);
- nfs_direct_read_schedule(dreq, inode, ctx, user_addr, count,
- file_offset);
- result = nfs_direct_read_wait(dreq, clnt->cl_intr);
+ nfs_direct_read_schedule(dreq);
+ result = nfs_direct_wait(dreq);
rpc_clnt_sigunmask(clnt, &oldset);
return result;
}
-/**
- * nfs_direct_read - For each iov segment, map the user's buffer
- * then generate read RPCs.
- * @inode: target inode
- * @ctx: target file open context
- * @iov: array of vectors that define I/O buffer
- * file_offset: offset in file to begin the operation
- * nr_segs: size of iovec array
- *
- * We've already pushed out any non-direct writes so that this read
- * will see them when we read from the server.
- */
-static ssize_t
-nfs_direct_read(struct inode *inode, struct nfs_open_context *ctx,
- const struct iovec *iov, loff_t file_offset,
- unsigned long nr_segs)
+static void nfs_direct_free_writedata(struct nfs_direct_req *dreq)
{
- ssize_t tot_bytes = 0;
- unsigned long seg = 0;
-
- while ((seg < nr_segs) && (tot_bytes >= 0)) {
- ssize_t result;
- int page_count;
- struct page **pages;
- const struct iovec *vec = &iov[seg++];
- unsigned long user_addr = (unsigned long) vec->iov_base;
- size_t size = vec->iov_len;
-
- page_count = nfs_get_user_pages(READ, user_addr, size, &pages);
- if (page_count < 0) {
- nfs_free_user_pages(pages, 0, 0);
- if (tot_bytes > 0)
- break;
- return page_count;
- }
+ list_splice_init(&dreq->rewrite_list, &dreq->list);
+ while (!list_empty(&dreq->list)) {
+ struct nfs_write_data *data = list_entry(dreq->list.next, struct nfs_write_data, pages);
+ list_del(&data->pages);
+ nfs_writedata_release(data);
+ }
+}
- result = nfs_direct_read_seg(inode, ctx, user_addr, size,
- file_offset, pages, page_count);
+#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
+{
+ struct list_head *pos;
- if (result <= 0) {
- if (tot_bytes > 0)
- break;
- return result;
- }
- tot_bytes += result;
- file_offset += result;
- if (result < size)
- break;
+ list_splice_init(&dreq->rewrite_list, &dreq->list);
+ list_for_each(pos, &dreq->list)
+ dreq->outstanding++;
+ dreq->count = 0;
+
+ nfs_direct_write_schedule(dreq, FLUSH_STABLE);
+}
+
+static void nfs_direct_commit_result(struct rpc_task *task, void *calldata)
+{
+ struct nfs_write_data *data = calldata;
+ struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
+
+ /* Call the NFS version-specific code */
+ if (NFS_PROTO(data->inode)->commit_done(task, data) != 0)
+ return;
+ if (unlikely(task->tk_status < 0)) {
+ dreq->error = task->tk_status;
+ dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
+ }
+ if (memcmp(&dreq->verf, &data->verf, sizeof(data->verf))) {
+ dprintk("NFS: %5u commit verify failed\n", task->tk_pid);
+ dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
}
- return tot_bytes;
+ dprintk("NFS: %5u commit returned %d\n", task->tk_pid, task->tk_status);
+ nfs_direct_write_complete(dreq, data->inode);
}
-/**
- * nfs_direct_write_seg - Write out one iov segment. Generate separate
- * write RPCs for each "wsize" bytes, then commit.
- * @inode: target inode
- * @ctx: target file open context
- * user_addr: starting address of this segment of user's buffer
- * count: size of this segment
- * file_offset: offset in file to begin the operation
- * @pages: array of addresses of page structs defining user's buffer
- * nr_pages: size of pages array
- */
-static ssize_t nfs_direct_write_seg(struct inode *inode,
- struct nfs_open_context *ctx, unsigned long user_addr,
- size_t count, loff_t file_offset, struct page **pages,
- int nr_pages)
+static const struct rpc_call_ops nfs_commit_direct_ops = {
+ .rpc_call_done = nfs_direct_commit_result,
+ .rpc_release = nfs_commit_release,
+};
+
+static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
{
- const unsigned int wsize = NFS_SERVER(inode)->wsize;
- size_t request;
- int curpage, need_commit;
- ssize_t result, tot_bytes;
- struct nfs_writeverf first_verf;
- struct nfs_write_data *wdata;
-
- wdata = nfs_writedata_alloc(NFS_SERVER(inode)->wpages);
- if (!wdata)
- return -ENOMEM;
+ struct nfs_write_data *data = dreq->commit_data;
+ struct rpc_task *task = &data->task;
- wdata->inode = inode;
- wdata->cred = ctx->cred;
- wdata->args.fh = NFS_FH(inode);
- wdata->args.context = ctx;
- wdata->args.stable = NFS_UNSTABLE;
- if (IS_SYNC(inode) || NFS_PROTO(inode)->version == 2 || count <= wsize)
- wdata->args.stable = NFS_FILE_SYNC;
- wdata->res.fattr = &wdata->fattr;
- wdata->res.verf = &wdata->verf;
+ data->inode = dreq->inode;
+ data->cred = dreq->ctx->cred;
- nfs_begin_data_update(inode);
-retry:
- need_commit = 0;
- tot_bytes = 0;
- curpage = 0;
- request = count;
- wdata->args.pgbase = user_addr & ~PAGE_MASK;
- wdata->args.offset = file_offset;
- do {
- wdata->args.count = request;
- if (wdata->args.count > wsize)
- wdata->args.count = wsize;
- wdata->args.pages = &pages[curpage];
+ data->args.fh = NFS_FH(data->inode);
+ data->args.offset = dreq->pos;
+ data->args.count = dreq->user_count;
+ data->res.count = 0;
+ data->res.fattr = &data->fattr;
+ data->res.verf = &data->verf;
- dprintk("NFS: direct write: c=%u o=%Ld ua=%lu, pb=%u, cp=%u\n",
- wdata->args.count, (long long) wdata->args.offset,
- user_addr + tot_bytes, wdata->args.pgbase, curpage);
+ rpc_init_task(&data->task, NFS_CLIENT(dreq->inode), RPC_TASK_ASYNC,
+ &nfs_commit_direct_ops, data);
+ NFS_PROTO(data->inode)->commit_setup(data, 0);
- lock_kernel();
- result = NFS_PROTO(inode)->write(wdata);
- unlock_kernel();
+ data->task.tk_priority = RPC_PRIORITY_NORMAL;
+ data->task.tk_cookie = (unsigned long)data->inode;
+ /* Note: task.tk_ops->rpc_release will free dreq->commit_data */
+ dreq->commit_data = NULL;
- if (result <= 0) {
- if (tot_bytes > 0)
- break;
- goto out;
- }
+ dprintk("NFS: %5u initiated commit call\n", task->tk_pid);
- if (tot_bytes == 0)
- memcpy(&first_verf.verifier, &wdata->verf.verifier,
- sizeof(first_verf.verifier));
- if (wdata->verf.committed != NFS_FILE_SYNC) {
- need_commit = 1;
- if (memcmp(&first_verf.verifier, &wdata->verf.verifier,
- sizeof(first_verf.verifier)))
- goto sync_retry;
- }
+ lock_kernel();
+ rpc_execute(&data->task);
+ unlock_kernel();
+}
- tot_bytes += result;
+static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode)
+{
+ int flags = dreq->flags;
- /* in case of a short write: stop now, let the app recover */
- if (result < wdata->args.count)
+ dreq->flags = 0;
+ switch (flags) {
+ case NFS_ODIRECT_DO_COMMIT:
+ nfs_direct_commit_schedule(dreq);
break;
+ case NFS_ODIRECT_RESCHED_WRITES:
+ nfs_direct_write_reschedule(dreq);
+ break;
+ default:
+ nfs_end_data_update(inode);
+ if (dreq->commit_data != NULL)
+ nfs_commit_free(dreq->commit_data);
+ nfs_direct_free_writedata(dreq);
+ nfs_direct_complete(dreq);
+ }
+}
- wdata->args.offset += result;
- wdata->args.pgbase += result;
- curpage += wdata->args.pgbase >> PAGE_SHIFT;
- wdata->args.pgbase &= ~PAGE_MASK;
- request -= result;
- } while (request != 0);
+static void nfs_alloc_commit_data(struct nfs_direct_req *dreq)
+{
+ dreq->commit_data = nfs_commit_alloc(0);
+ if (dreq->commit_data != NULL)
+ dreq->commit_data->req = (struct nfs_page *) dreq;
+}
+#else
+static inline void nfs_alloc_commit_data(struct nfs_direct_req *dreq)
+{
+ dreq->commit_data = NULL;
+}
- /*
- * Commit data written so far, even in the event of an error
- */
- if (need_commit) {
- wdata->args.count = tot_bytes;
- wdata->args.offset = file_offset;
+static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode)
+{
+ nfs_end_data_update(inode);
+ nfs_direct_free_writedata(dreq);
+ nfs_direct_complete(dreq);
+}
+#endif
- lock_kernel();
- result = NFS_PROTO(inode)->commit(wdata);
- unlock_kernel();
+static struct nfs_direct_req *nfs_direct_write_alloc(size_t nbytes, size_t wsize)
+{
+ struct list_head *list;
+ struct nfs_direct_req *dreq;
+ unsigned int wpages = (wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
+ dreq = nfs_direct_req_alloc();
+ if (!dreq)
+ return NULL;
+
+ list = &dreq->list;
+ for(;;) {
+ struct nfs_write_data *data = nfs_writedata_alloc(wpages);
- if (result < 0 || memcmp(&first_verf.verifier,
- &wdata->verf.verifier,
- sizeof(first_verf.verifier)) != 0)
- goto sync_retry;
+ if (unlikely(!data)) {
+ while (!list_empty(list)) {
+ data = list_entry(list->next,
+ struct nfs_write_data, pages);
+ list_del(&data->pages);
+ nfs_writedata_free(data);
+ }
+ kref_put(&dreq->kref, nfs_direct_req_release);
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&data->pages);
+ list_add(&data->pages, list);
+
+ data->req = (struct nfs_page *) dreq;
+ dreq->outstanding++;
+ if (nbytes <= wsize)
+ break;
+ nbytes -= wsize;
}
- result = tot_bytes;
-out:
- nfs_end_data_update(inode);
- nfs_writedata_free(wdata);
- return result;
+ nfs_alloc_commit_data(dreq);
-sync_retry:
- wdata->args.stable = NFS_FILE_SYNC;
- goto retry;
+ kref_get(&dreq->kref);
+ return dreq;
}
-/**
- * nfs_direct_write - For each iov segment, map the user's buffer
- * then generate write and commit RPCs.
- * @inode: target inode
- * @ctx: target file open context
- * @iov: array of vectors that define I/O buffer
- * file_offset: offset in file to begin the operation
- * nr_segs: size of iovec array
- *
- * Upon return, generic_file_direct_IO invalidates any cached pages
- * that non-direct readers might access, so they will pick up these
- * writes immediately.
- */
-static ssize_t nfs_direct_write(struct inode *inode,
- struct nfs_open_context *ctx, const struct iovec *iov,
- loff_t file_offset, unsigned long nr_segs)
+static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
{
- ssize_t tot_bytes = 0;
- unsigned long seg = 0;
-
- while ((seg < nr_segs) && (tot_bytes >= 0)) {
- ssize_t result;
- int page_count;
- struct page **pages;
- const struct iovec *vec = &iov[seg++];
- unsigned long user_addr = (unsigned long) vec->iov_base;
- size_t size = vec->iov_len;
-
- page_count = nfs_get_user_pages(WRITE, user_addr, size, &pages);
- if (page_count < 0) {
- nfs_free_user_pages(pages, 0, 0);
- if (tot_bytes > 0)
- break;
- return page_count;
- }
+ struct nfs_write_data *data = calldata;
+ struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
+ int status = task->tk_status;
+
+ if (nfs_writeback_done(task, data) != 0)
+ return;
+
+ spin_lock(&dreq->lock);
- result = nfs_direct_write_seg(inode, ctx, user_addr, size,
- file_offset, pages, page_count);
- nfs_free_user_pages(pages, page_count, 0);
+ if (likely(status >= 0))
+ dreq->count += data->res.count;
+ else
+ dreq->error = task->tk_status;
- if (result <= 0) {
- if (tot_bytes > 0)
+ if (data->res.verf->committed != NFS_FILE_SYNC) {
+ switch (dreq->flags) {
+ case 0:
+ memcpy(&dreq->verf, &data->verf, sizeof(dreq->verf));
+ dreq->flags = NFS_ODIRECT_DO_COMMIT;
break;
- return result;
+ case NFS_ODIRECT_DO_COMMIT:
+ if (memcmp(&dreq->verf, &data->verf, sizeof(dreq->verf))) {
+ dprintk("NFS: %5u write verify failed\n", task->tk_pid);
+ dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
+ }
}
- tot_bytes += result;
- file_offset += result;
- if (result < size)
- break;
}
- return tot_bytes;
+ /* In case we have to resend */
+ data->args.stable = NFS_FILE_SYNC;
+
+ spin_unlock(&dreq->lock);
}
-/**
- * nfs_direct_IO - NFS address space operation for direct I/O
- * rw: direction (read or write)
- * @iocb: target I/O control block
- * @iov: array of vectors that define I/O buffer
- * file_offset: offset in file to begin the operation
- * nr_segs: size of iovec array
- *
+/*
+ * NB: Return the value of the first error return code. Subsequent
+ * errors after the first one are ignored.
*/
-ssize_t
-nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
- loff_t file_offset, unsigned long nr_segs)
+static void nfs_direct_write_release(void *calldata)
{
- ssize_t result = -EINVAL;
- struct file *file = iocb->ki_filp;
- struct nfs_open_context *ctx;
- struct dentry *dentry = file->f_dentry;
- struct inode *inode = dentry->d_inode;
+ struct nfs_write_data *data = calldata;
+ struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
- /*
- * No support for async yet
- */
- if (!is_sync_kiocb(iocb))
- return result;
-
- ctx = (struct nfs_open_context *)file->private_data;
- switch (rw) {
- case READ:
- dprintk("NFS: direct_IO(read) (%s) off/no(%Lu/%lu)\n",
- dentry->d_name.name, file_offset, nr_segs);
-
- result = nfs_direct_read(inode, ctx, iov,
- file_offset, nr_segs);
- break;
- case WRITE:
- dprintk("NFS: direct_IO(write) (%s) off/no(%Lu/%lu)\n",
- dentry->d_name.name, file_offset, nr_segs);
-
- result = nfs_direct_write(inode, ctx, iov,
- file_offset, nr_segs);
- break;
- default:
- break;
+ spin_lock(&dreq->lock);
+ if (--dreq->outstanding) {
+ spin_unlock(&dreq->lock);
+ return;
}
+ spin_unlock(&dreq->lock);
+
+ nfs_direct_write_complete(dreq, data->inode);
+}
+
+static const struct rpc_call_ops nfs_write_direct_ops = {
+ .rpc_call_done = nfs_direct_write_result,
+ .rpc_release = nfs_direct_write_release,
+};
+
+/*
+ * For each nfs_write_data struct that was allocated on the list, dispatch
+ * an NFS WRITE operation
+ */
+static void nfs_direct_write_schedule(struct nfs_direct_req *dreq, int sync)
+{
+ struct nfs_open_context *ctx = dreq->ctx;
+ struct inode *inode = ctx->dentry->d_inode;
+ struct list_head *list = &dreq->list;
+ struct page **pages = dreq->pages;
+ size_t count = dreq->user_count;
+ loff_t pos = dreq->pos;
+ size_t wsize = NFS_SERVER(inode)->wsize;
+ unsigned int curpage, pgbase;
+
+ curpage = 0;
+ pgbase = dreq->user_addr & ~PAGE_MASK;
+ do {
+ struct nfs_write_data *data;
+ size_t bytes;
+
+ bytes = wsize;
+ if (count < wsize)
+ bytes = count;
+
+ BUG_ON(list_empty(list));
+ data = list_entry(list->next, struct nfs_write_data, pages);
+ list_move_tail(&data->pages, &dreq->rewrite_list);
+
+ data->inode = inode;
+ data->cred = ctx->cred;
+ data->args.fh = NFS_FH(inode);
+ data->args.context = ctx;
+ data->args.offset = pos;
+ data->args.pgbase = pgbase;
+ data->args.pages = &pages[curpage];
+ data->args.count = bytes;
+ data->res.fattr = &data->fattr;
+ data->res.count = bytes;
+ data->res.verf = &data->verf;
+
+ rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC,
+ &nfs_write_direct_ops, data);
+ NFS_PROTO(inode)->write_setup(data, sync);
+
+ data->task.tk_priority = RPC_PRIORITY_NORMAL;
+ data->task.tk_cookie = (unsigned long) inode;
+
+ lock_kernel();
+ rpc_execute(&data->task);
+ unlock_kernel();
+
+ dfprintk(VFS, "NFS: %5u initiated direct write call (req %s/%Ld, %zu bytes @ offset %Lu)\n",
+ data->task.tk_pid,
+ inode->i_sb->s_id,
+ (long long)NFS_FILEID(inode),
+ bytes,
+ (unsigned long long)data->args.offset);
+
+ pos += bytes;
+ pgbase += bytes;
+ curpage += pgbase >> PAGE_SHIFT;
+ pgbase &= ~PAGE_MASK;
+
+ count -= bytes;
+ } while (count != 0);
+ BUG_ON(!list_empty(list));
+}
+
+static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos, struct page **pages, int nr_pages)
+{
+ ssize_t result;
+ sigset_t oldset;
+ struct inode *inode = iocb->ki_filp->f_mapping->host;
+ struct rpc_clnt *clnt = NFS_CLIENT(inode);
+ struct nfs_direct_req *dreq;
+ size_t wsize = NFS_SERVER(inode)->wsize;
+ int sync = 0;
+
+ dreq = nfs_direct_write_alloc(count, wsize);
+ if (!dreq)
+ return -ENOMEM;
+ if (dreq->commit_data == NULL || count < wsize)
+ sync = FLUSH_STABLE;
+
+ dreq->user_addr = user_addr;
+ dreq->user_count = count;
+ dreq->pos = pos;
+ dreq->pages = pages;
+ dreq->npages = nr_pages;
+ dreq->inode = inode;
+ dreq->ctx = get_nfs_open_context((struct nfs_open_context *)iocb->ki_filp->private_data);
+ if (!is_sync_kiocb(iocb))
+ dreq->iocb = iocb;
+
+ nfs_add_stats(inode, NFSIOS_DIRECTWRITTENBYTES, count);
+
+ nfs_begin_data_update(inode);
+
+ rpc_clnt_sigmask(clnt, &oldset);
+ nfs_direct_write_schedule(dreq, sync);
+ result = nfs_direct_wait(dreq);
+ rpc_clnt_sigunmask(clnt, &oldset);
+
return result;
}
@@ -640,49 +748,40 @@ nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
* nfs_file_direct_read - file direct read operation for NFS files
* @iocb: target I/O control block
* @buf: user's buffer into which to read data
- * count: number of bytes to read
- * pos: byte offset in file where reading starts
+ * @count: number of bytes to read
+ * @pos: byte offset in file where reading starts
*
* We use this function for direct reads instead of calling
* generic_file_aio_read() in order to avoid gfar's check to see if
* the request starts before the end of the file. For that check
* to work, we must generate a GETATTR before each direct read, and
* even then there is a window between the GETATTR and the subsequent
- * READ where the file size could change. So our preference is simply
+ * READ where the file size could change. Our preference is simply
* to do all reads the application wants, and the server will take
* care of managing the end of file boundary.
- *
+ *
* This function also eliminates unnecessarily updating the file's
* atime locally, as the NFS server sets the file's atime, and this
* client must read the updated atime from the server back into its
* cache.
*/
-ssize_t
-nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
+ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
{
ssize_t retval = -EINVAL;
- loff_t *ppos = &iocb->ki_pos;
+ int page_count;
+ struct page **pages;
struct file *file = iocb->ki_filp;
- struct nfs_open_context *ctx =
- (struct nfs_open_context *) file->private_data;
struct address_space *mapping = file->f_mapping;
- struct inode *inode = mapping->host;
- struct iovec iov = {
- .iov_base = buf,
- .iov_len = count,
- };
dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
file->f_dentry->d_parent->d_name.name,
file->f_dentry->d_name.name,
(unsigned long) count, (long long) pos);
- if (!is_sync_kiocb(iocb))
- goto out;
if (count < 0)
goto out;
retval = -EFAULT;
- if (!access_ok(VERIFY_WRITE, iov.iov_base, iov.iov_len))
+ if (!access_ok(VERIFY_WRITE, buf, count))
goto out;
retval = 0;
if (!count)
@@ -692,9 +791,16 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t
if (retval)
goto out;
- retval = nfs_direct_read(inode, ctx, &iov, pos, 1);
+ retval = nfs_get_user_pages(READ, (unsigned long) buf,
+ count, &pages);
+ if (retval < 0)
+ goto out;
+ page_count = retval;
+
+ retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos,
+ pages, page_count);
if (retval > 0)
- *ppos = pos + retval;
+ iocb->ki_pos = pos + retval;
out:
return retval;
@@ -704,8 +810,8 @@ out:
* nfs_file_direct_write - file direct write operation for NFS files
* @iocb: target I/O control block
* @buf: user's buffer from which to write data
- * count: number of bytes to write
- * pos: byte offset in file where writing starts
+ * @count: number of bytes to write
+ * @pos: byte offset in file where writing starts
*
* We use this function for direct writes instead of calling
* generic_file_aio_write() in order to avoid taking the inode
@@ -725,28 +831,19 @@ out:
* Note that O_APPEND is not supported for NFS direct writes, as there
* is no atomic O_APPEND write facility in the NFS protocol.
*/
-ssize_t
-nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
+ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
{
ssize_t retval;
+ int page_count;
+ struct page **pages;
struct file *file = iocb->ki_filp;
- struct nfs_open_context *ctx =
- (struct nfs_open_context *) file->private_data;
struct address_space *mapping = file->f_mapping;
- struct inode *inode = mapping->host;
- struct iovec iov = {
- .iov_base = (char __user *)buf,
- };
dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
file->f_dentry->d_parent->d_name.name,
file->f_dentry->d_name.name,
(unsigned long) count, (long long) pos);
- retval = -EINVAL;
- if (!is_sync_kiocb(iocb))
- goto out;
-
retval = generic_write_checks(file, &pos, &count, 0);
if (retval)
goto out;
@@ -757,19 +854,35 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
retval = 0;
if (!count)
goto out;
- iov.iov_len = count,
retval = -EFAULT;
- if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len))
+ if (!access_ok(VERIFY_READ, buf, count))
goto out;
retval = nfs_sync_mapping(mapping);
if (retval)
goto out;
- retval = nfs_direct_write(inode, ctx, &iov, pos, 1);
+ retval = nfs_get_user_pages(WRITE, (unsigned long) buf,
+ count, &pages);
+ if (retval < 0)
+ goto out;
+ page_count = retval;
+
+ retval = nfs_direct_write(iocb, (unsigned long) buf, count,
+ pos, pages, page_count);
+
+ /*
+ * XXX: nfs_end_data_update() already ensures this file's
+ * cached data is subsequently invalidated. Do we really
+ * need to call invalidate_inode_pages2() again here?
+ *
+ * For aio writes, this invalidation will almost certainly
+ * occur before the writes complete. Kind of racey.
+ */
if (mapping->nrpages)
invalidate_inode_pages2(mapping);
+
if (retval > 0)
iocb->ki_pos = pos + retval;
@@ -777,6 +890,10 @@ out:
return retval;
}
+/**
+ * nfs_init_directcache - create a slab cache for nfs_direct_req structures
+ *
+ */
int nfs_init_directcache(void)
{
nfs_direct_cachep = kmem_cache_create("nfs_direct_cache",
@@ -790,6 +907,10 @@ int nfs_init_directcache(void)
return 0;
}
+/**
+ * nfs_init_directcache - destroy the slab cache for nfs_direct_req structures
+ *
+ */
void nfs_destroy_directcache(void)
{
if (kmem_cache_destroy(nfs_direct_cachep))
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 7a79fbe9f53..f1df2c8d925 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -32,6 +32,7 @@
#include <asm/system.h>
#include "delegation.h"
+#include "iostat.h"
#define NFSDBG_FACILITY NFSDBG_FILE
@@ -48,7 +49,7 @@ static int nfs_check_flags(int flags);
static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
-struct file_operations nfs_file_operations = {
+const struct file_operations nfs_file_operations = {
.llseek = nfs_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
@@ -102,18 +103,15 @@ static int nfs_check_flags(int flags)
static int
nfs_file_open(struct inode *inode, struct file *filp)
{
- struct nfs_server *server = NFS_SERVER(inode);
- int (*open)(struct inode *, struct file *);
int res;
res = nfs_check_flags(filp->f_flags);
if (res)
return res;
+ nfs_inc_stats(inode, NFSIOS_VFSOPEN);
lock_kernel();
- /* Do NFSv4 open() call */
- if ((open = server->rpc_ops->file_open) != NULL)
- res = open(inode, filp);
+ res = NFS_SERVER(inode)->rpc_ops->file_open(inode, filp);
unlock_kernel();
return res;
}
@@ -124,6 +122,7 @@ nfs_file_release(struct inode *inode, struct file *filp)
/* Ensure that dirty pages are flushed out with the right creds */
if (filp->f_mode & FMODE_WRITE)
filemap_fdatawrite(filp->f_mapping);
+ nfs_inc_stats(inode, NFSIOS_VFSRELEASE);
return NFS_PROTO(inode)->file_release(inode, filp);
}
@@ -199,6 +198,7 @@ nfs_file_flush(struct file *file)
if ((file->f_mode & FMODE_WRITE) == 0)
return 0;
+ nfs_inc_stats(inode, NFSIOS_VFSFLUSH);
lock_kernel();
/* Ensure that data+attribute caches are up to date after close() */
status = nfs_wb_all(inode);
@@ -229,6 +229,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
(unsigned long) count, (unsigned long) pos);
result = nfs_revalidate_file(inode, iocb->ki_filp);
+ nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count);
if (!result)
result = generic_file_aio_read(iocb, buf, count, pos);
return result;
@@ -282,6 +283,7 @@ nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
dfprintk(VFS, "nfs: fsync(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
+ nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
lock_kernel();
status = nfs_wb_all(inode);
if (!status) {
@@ -316,6 +318,16 @@ static int nfs_commit_write(struct file *file, struct page *page, unsigned offse
return status;
}
+static void nfs_invalidate_page(struct page *page, unsigned long offset)
+{
+ /* FIXME: we really should cancel any unstarted writes on this page */
+}
+
+static int nfs_release_page(struct page *page, gfp_t gfp)
+{
+ return !nfs_wb_page(page->mapping->host, page);
+}
+
struct address_space_operations nfs_file_aops = {
.readpage = nfs_readpage,
.readpages = nfs_readpages,
@@ -324,6 +336,8 @@ struct address_space_operations nfs_file_aops = {
.writepages = nfs_writepages,
.prepare_write = nfs_prepare_write,
.commit_write = nfs_commit_write,
+ .invalidatepage = nfs_invalidate_page,
+ .releasepage = nfs_release_page,
#ifdef CONFIG_NFS_DIRECTIO
.direct_IO = nfs_direct_IO,
#endif
@@ -365,6 +379,7 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t
if (!count)
goto out;
+ nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
result = generic_file_aio_write(iocb, buf, count, pos);
out:
return result;
@@ -376,15 +391,17 @@ out_swapfile:
static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
{
- struct file_lock *cfl;
+ struct file_lock cfl;
struct inode *inode = filp->f_mapping->host;
int status = 0;
lock_kernel();
/* Try local locking first */
- cfl = posix_test_lock(filp, fl);
- if (cfl != NULL) {
- locks_copy_lock(fl, cfl);
+ if (posix_test_lock(filp, fl, &cfl)) {
+ fl->fl_start = cfl.fl_start;
+ fl->fl_end = cfl.fl_end;
+ fl->fl_type = cfl.fl_type;
+ fl->fl_pid = cfl.fl_pid;
goto out;
}
@@ -425,10 +442,8 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl)
static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
{
struct inode *inode = filp->f_mapping->host;
- sigset_t oldset;
int status;
- rpc_clnt_sigmask(NFS_CLIENT(inode), &oldset);
/*
* Flush all pending writes before doing anything
* with locks..
@@ -446,17 +461,14 @@ static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
else
status = do_vfs_lock(filp, fl);
unlock_kernel();
- rpc_clnt_sigunmask(NFS_CLIENT(inode), &oldset);
return status;
}
static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
{
struct inode *inode = filp->f_mapping->host;
- sigset_t oldset;
int status;
- rpc_clnt_sigmask(NFS_CLIENT(inode), &oldset);
/*
* Flush all pending writes before doing anything
* with locks..
@@ -489,7 +501,6 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
nfs_sync_mapping(filp->f_mapping);
nfs_zap_caches(inode);
out:
- rpc_clnt_sigunmask(NFS_CLIENT(inode), &oldset);
return status;
}
@@ -504,9 +515,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
inode->i_sb->s_id, inode->i_ino,
fl->fl_type, fl->fl_flags,
(long long)fl->fl_start, (long long)fl->fl_end);
-
- if (!inode)
- return -EINVAL;
+ nfs_inc_stats(inode, NFSIOS_VFSLOCK);
/* No mandatory locks over NFS */
if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
@@ -531,9 +540,6 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
inode->i_sb->s_id, inode->i_ino,
fl->fl_type, fl->fl_flags);
- if (!inode)
- return -EINVAL;
-
/*
* No BSD flocks over NFS allowed.
* Note: we could try to fake a POSIX lock request here by
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 821edd30333..3fab5b0cfc5 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -35,6 +35,7 @@
*/
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
@@ -74,8 +75,8 @@ struct idmap {
struct dentry *idmap_dentry;
wait_queue_head_t idmap_wq;
struct idmap_msg idmap_im;
- struct semaphore idmap_lock; /* Serializes upcalls */
- struct semaphore idmap_im_lock; /* Protects the hashtable */
+ struct mutex idmap_lock; /* Serializes upcalls */
+ struct mutex idmap_im_lock; /* Protects the hashtable */
struct idmap_hashtable idmap_user_hash;
struct idmap_hashtable idmap_group_hash;
};
@@ -101,11 +102,9 @@ nfs_idmap_new(struct nfs4_client *clp)
if (clp->cl_idmap != NULL)
return;
- if ((idmap = kmalloc(sizeof(*idmap), GFP_KERNEL)) == NULL)
+ if ((idmap = kzalloc(sizeof(*idmap), GFP_KERNEL)) == NULL)
return;
- memset(idmap, 0, sizeof(*idmap));
-
snprintf(idmap->idmap_path, sizeof(idmap->idmap_path),
"%s/idmap", clp->cl_rpcclient->cl_pathname);
@@ -116,8 +115,8 @@ nfs_idmap_new(struct nfs4_client *clp)
return;
}
- init_MUTEX(&idmap->idmap_lock);
- init_MUTEX(&idmap->idmap_im_lock);
+ mutex_init(&idmap->idmap_lock);
+ mutex_init(&idmap->idmap_im_lock);
init_waitqueue_head(&idmap->idmap_wq);
idmap->idmap_user_hash.h_type = IDMAP_TYPE_USER;
idmap->idmap_group_hash.h_type = IDMAP_TYPE_GROUP;
@@ -132,6 +131,8 @@ nfs_idmap_delete(struct nfs4_client *clp)
if (!idmap)
return;
+ dput(idmap->idmap_dentry);
+ idmap->idmap_dentry = NULL;
rpc_unlink(idmap->idmap_path);
clp->cl_idmap = NULL;
kfree(idmap);
@@ -232,8 +233,8 @@ nfs_idmap_id(struct idmap *idmap, struct idmap_hashtable *h,
if (namelen >= IDMAP_NAMESZ)
return -EINVAL;
- down(&idmap->idmap_lock);
- down(&idmap->idmap_im_lock);
+ mutex_lock(&idmap->idmap_lock);
+ mutex_lock(&idmap->idmap_im_lock);
he = idmap_lookup_name(h, name, namelen);
if (he != NULL) {
@@ -259,11 +260,11 @@ nfs_idmap_id(struct idmap *idmap, struct idmap_hashtable *h,
}
set_current_state(TASK_UNINTERRUPTIBLE);
- up(&idmap->idmap_im_lock);
+ mutex_unlock(&idmap->idmap_im_lock);
schedule();
current->state = TASK_RUNNING;
remove_wait_queue(&idmap->idmap_wq, &wq);
- down(&idmap->idmap_im_lock);
+ mutex_lock(&idmap->idmap_im_lock);
if (im->im_status & IDMAP_STATUS_SUCCESS) {
*id = im->im_id;
@@ -272,8 +273,8 @@ nfs_idmap_id(struct idmap *idmap, struct idmap_hashtable *h,
out:
memset(im, 0, sizeof(*im));
- up(&idmap->idmap_im_lock);
- up(&idmap->idmap_lock);
+ mutex_unlock(&idmap->idmap_im_lock);
+ mutex_unlock(&idmap->idmap_lock);
return (ret);
}
@@ -293,8 +294,8 @@ nfs_idmap_name(struct idmap *idmap, struct idmap_hashtable *h,
im = &idmap->idmap_im;
- down(&idmap->idmap_lock);
- down(&idmap->idmap_im_lock);
+ mutex_lock(&idmap->idmap_lock);
+ mutex_lock(&idmap->idmap_im_lock);
he = idmap_lookup_id(h, id);
if (he != 0) {
@@ -320,11 +321,11 @@ nfs_idmap_name(struct idmap *idmap, struct idmap_hashtable *h,
}
set_current_state(TASK_UNINTERRUPTIBLE);
- up(&idmap->idmap_im_lock);
+ mutex_unlock(&idmap->idmap_im_lock);
schedule();
current->state = TASK_RUNNING;
remove_wait_queue(&idmap->idmap_wq, &wq);
- down(&idmap->idmap_im_lock);
+ mutex_lock(&idmap->idmap_im_lock);
if (im->im_status & IDMAP_STATUS_SUCCESS) {
if ((len = strnlen(im->im_name, IDMAP_NAMESZ)) == 0)
@@ -335,8 +336,8 @@ nfs_idmap_name(struct idmap *idmap, struct idmap_hashtable *h,
out:
memset(im, 0, sizeof(*im));
- up(&idmap->idmap_im_lock);
- up(&idmap->idmap_lock);
+ mutex_unlock(&idmap->idmap_im_lock);
+ mutex_unlock(&idmap->idmap_lock);
return ret;
}
@@ -380,7 +381,7 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
if (copy_from_user(&im_in, src, mlen) != 0)
return (-EFAULT);
- down(&idmap->idmap_im_lock);
+ mutex_lock(&idmap->idmap_im_lock);
ret = mlen;
im->im_status = im_in.im_status;
@@ -440,7 +441,7 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
idmap_update_entry(he, im_in.im_name, namelen_in, im_in.im_id);
ret = mlen;
out:
- up(&idmap->idmap_im_lock);
+ mutex_unlock(&idmap->idmap_im_lock);
return ret;
}
@@ -452,10 +453,10 @@ idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg)
if (msg->errno >= 0)
return;
- down(&idmap->idmap_im_lock);
+ mutex_lock(&idmap->idmap_im_lock);
im->im_status = IDMAP_STATUS_LOOKUPFAIL;
wake_up(&idmap->idmap_wq);
- up(&idmap->idmap_im_lock);
+ mutex_unlock(&idmap->idmap_im_lock);
}
/*
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 3413996f9a8..2f7656b911b 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -26,6 +26,7 @@
#include <linux/unistd.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/stats.h>
+#include <linux/sunrpc/metrics.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_mount.h>
#include <linux/nfs4_mount.h>
@@ -42,6 +43,7 @@
#include "nfs4_fs.h"
#include "callback.h"
#include "delegation.h"
+#include "iostat.h"
#define NFSDBG_FACILITY NFSDBG_VFS
#define NFS_PARANOIA 1
@@ -65,6 +67,7 @@ static void nfs_clear_inode(struct inode *);
static void nfs_umount_begin(struct super_block *);
static int nfs_statfs(struct super_block *, struct kstatfs *);
static int nfs_show_options(struct seq_file *, struct vfsmount *);
+static int nfs_show_stats(struct seq_file *, struct vfsmount *);
static void nfs_zap_acl_cache(struct inode *);
static struct rpc_program nfs_program;
@@ -78,6 +81,7 @@ static struct super_operations nfs_sops = {
.clear_inode = nfs_clear_inode,
.umount_begin = nfs_umount_begin,
.show_options = nfs_show_options,
+ .show_stats = nfs_show_stats,
};
/*
@@ -133,7 +137,7 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
static int
nfs_write_inode(struct inode *inode, int sync)
{
- int flags = sync ? FLUSH_WAIT : 0;
+ int flags = sync ? FLUSH_SYNC : 0;
int ret;
ret = nfs_commit_inode(inode, flags);
@@ -237,7 +241,6 @@ static struct inode *
nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo)
{
struct nfs_server *server = NFS_SB(sb);
- struct inode *rooti;
int error;
error = server->rpc_ops->getroot(server, rootfh, fsinfo);
@@ -246,10 +249,7 @@ nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *f
return ERR_PTR(error);
}
- rooti = nfs_fhget(sb, rootfh, fsinfo->fattr);
- if (!rooti)
- return ERR_PTR(-ENOMEM);
- return rooti;
+ return nfs_fhget(sb, rootfh, fsinfo->fattr);
}
/*
@@ -277,6 +277,10 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
sb->s_magic = NFS_SUPER_MAGIC;
+ server->io_stats = nfs_alloc_iostats();
+ if (server->io_stats == NULL)
+ return -ENOMEM;
+
root_inode = nfs_get_root(sb, &server->fh, &fsinfo);
/* Did getting the root inode fail? */
if (IS_ERR(root_inode)) {
@@ -290,6 +294,9 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
}
sb->s_root->d_op = server->rpc_ops->dentry_ops;
+ /* mount time stamp, in seconds */
+ server->mount_time = jiffies;
+
/* Get some general file system info */
if (server->namelen == 0 &&
server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)
@@ -396,6 +403,9 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans);
+ server->retrans_timeo = timeparms.to_initval;
+ server->retrans_count = timeparms.to_retries;
+
/* create transport and client */
xprt = xprt_create_proto(proto, &server->addr, &timeparms);
if (IS_ERR(xprt)) {
@@ -579,7 +589,7 @@ nfs_statfs(struct super_block *sb, struct kstatfs *buf)
}
-static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
+static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults)
{
static struct proc_nfs_info {
int flag;
@@ -588,28 +598,26 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
} nfs_info[] = {
{ NFS_MOUNT_SOFT, ",soft", ",hard" },
{ NFS_MOUNT_INTR, ",intr", "" },
- { NFS_MOUNT_POSIX, ",posix", "" },
{ NFS_MOUNT_NOCTO, ",nocto", "" },
{ NFS_MOUNT_NOAC, ",noac", "" },
- { NFS_MOUNT_NONLM, ",nolock", ",lock" },
+ { NFS_MOUNT_NONLM, ",nolock", "" },
{ NFS_MOUNT_NOACL, ",noacl", "" },
{ 0, NULL, NULL }
};
struct proc_nfs_info *nfs_infop;
- struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
char buf[12];
char *proto;
- seq_printf(m, ",v%d", nfss->rpc_ops->version);
+ seq_printf(m, ",vers=%d", nfss->rpc_ops->version);
seq_printf(m, ",rsize=%d", nfss->rsize);
seq_printf(m, ",wsize=%d", nfss->wsize);
- if (nfss->acregmin != 3*HZ)
+ if (nfss->acregmin != 3*HZ || showdefaults)
seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
- if (nfss->acregmax != 60*HZ)
+ if (nfss->acregmax != 60*HZ || showdefaults)
seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
- if (nfss->acdirmin != 30*HZ)
+ if (nfss->acdirmin != 30*HZ || showdefaults)
seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
- if (nfss->acdirmax != 60*HZ)
+ if (nfss->acdirmax != 60*HZ || showdefaults)
seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
if (nfss->flags & nfs_infop->flag)
@@ -629,8 +637,96 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
proto = buf;
}
seq_printf(m, ",proto=%s", proto);
+ seq_printf(m, ",timeo=%lu", 10U * nfss->retrans_timeo / HZ);
+ seq_printf(m, ",retrans=%u", nfss->retrans_count);
+}
+
+static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+ struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
+
+ nfs_show_mount_options(m, nfss, 0);
+
seq_puts(m, ",addr=");
seq_escape(m, nfss->hostname, " \t\n\\");
+
+ return 0;
+}
+
+static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
+{
+ int i, cpu;
+ struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
+ struct rpc_auth *auth = nfss->client->cl_auth;
+ struct nfs_iostats totals = { };
+
+ seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS);
+
+ /*
+ * Display all mount option settings
+ */
+ seq_printf(m, "\n\topts:\t");
+ seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw");
+ seq_puts(m, mnt->mnt_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : "");
+ seq_puts(m, mnt->mnt_sb->s_flags & MS_NOATIME ? ",noatime" : "");
+ seq_puts(m, mnt->mnt_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : "");
+ nfs_show_mount_options(m, nfss, 1);
+
+ seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ);
+
+ seq_printf(m, "\n\tcaps:\t");
+ seq_printf(m, "caps=0x%x", nfss->caps);
+ seq_printf(m, ",wtmult=%d", nfss->wtmult);
+ seq_printf(m, ",dtsize=%d", nfss->dtsize);
+ seq_printf(m, ",bsize=%d", nfss->bsize);
+ seq_printf(m, ",namelen=%d", nfss->namelen);
+
+#ifdef CONFIG_NFS_V4
+ if (nfss->rpc_ops->version == 4) {
+ seq_printf(m, "\n\tnfsv4:\t");
+ seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
+ seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]);
+ seq_printf(m, ",acl=0x%x", nfss->acl_bitmask);
+ }
+#endif
+
+ /*
+ * Display security flavor in effect for this mount
+ */
+ seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor);
+ if (auth->au_flavor)
+ seq_printf(m, ",pseudoflavor=%d", auth->au_flavor);
+
+ /*
+ * Display superblock I/O counters
+ */
+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ struct nfs_iostats *stats;
+
+ if (!cpu_possible(cpu))
+ continue;
+
+ preempt_disable();
+ stats = per_cpu_ptr(nfss->io_stats, cpu);
+
+ for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
+ totals.events[i] += stats->events[i];
+ for (i = 0; i < __NFSIOS_BYTESMAX; i++)
+ totals.bytes[i] += stats->bytes[i];
+
+ preempt_enable();
+ }
+
+ seq_printf(m, "\n\tevents:\t");
+ for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
+ seq_printf(m, "%lu ", totals.events[i]);
+ seq_printf(m, "\n\tbytes:\t");
+ for (i = 0; i < __NFSIOS_BYTESMAX; i++)
+ seq_printf(m, "%Lu ", totals.bytes[i]);
+ seq_printf(m, "\n");
+
+ rpc_print_iostats(m, nfss->client);
+
return 0;
}
@@ -660,6 +756,8 @@ static void nfs_zap_caches_locked(struct inode *inode)
struct nfs_inode *nfsi = NFS_I(inode);
int mode = inode->i_mode;
+ nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
+
NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
NFS_ATTRTIMEO_UPDATE(inode) = jiffies;
@@ -751,7 +849,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
.fh = fh,
.fattr = fattr
};
- struct inode *inode = NULL;
+ struct inode *inode = ERR_PTR(-ENOENT);
unsigned long hash;
if ((fattr->valid & NFS_ATTR_FATTR) == 0)
@@ -764,8 +862,11 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
hash = nfs_fattr_to_ino_t(fattr);
- if (!(inode = iget5_locked(sb, hash, nfs_find_actor, nfs_init_locked, &desc)))
+ inode = iget5_locked(sb, hash, nfs_find_actor, nfs_init_locked, &desc);
+ if (inode == NULL) {
+ inode = ERR_PTR(-ENOMEM);
goto out_no_inode;
+ }
if (inode->i_state & I_NEW) {
struct nfs_inode *nfsi = NFS_I(inode);
@@ -834,7 +935,7 @@ out:
return inode;
out_no_inode:
- printk("nfs_fhget: iget failed\n");
+ dprintk("nfs_fhget: iget failed with error %ld\n", PTR_ERR(inode));
goto out;
}
@@ -847,6 +948,8 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
struct nfs_fattr fattr;
int error;
+ nfs_inc_stats(inode, NFSIOS_VFSSETATTR);
+
if (attr->ia_valid & ATTR_SIZE) {
if (!S_ISREG(inode->i_mode) || attr->ia_size == i_size_read(inode))
attr->ia_valid &= ~ATTR_SIZE;
@@ -859,11 +962,9 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
lock_kernel();
nfs_begin_data_update(inode);
- /* Write all dirty data if we're changing file permissions or size */
- if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE)) != 0) {
- filemap_write_and_wait(inode->i_mapping);
- nfs_wb_all(inode);
- }
+ /* Write all dirty data */
+ filemap_write_and_wait(inode->i_mapping);
+ nfs_wb_all(inode);
/*
* Return any delegations if we're going to change ACLs
*/
@@ -902,6 +1003,7 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
spin_unlock(&inode->i_lock);
}
if ((attr->ia_valid & ATTR_SIZE) != 0) {
+ nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
inode->i_size = attr->ia_size;
vmtruncate(inode, attr->ia_size);
}
@@ -949,7 +1051,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
int err;
/* Flush out writes to the server in order to update c/mtime */
- nfs_sync_inode(inode, 0, 0, FLUSH_WAIT|FLUSH_NOCOMMIT);
+ nfs_sync_inode_wait(inode, 0, 0, FLUSH_NOCOMMIT);
/*
* We may force a getattr if the user cares about atime.
@@ -973,7 +1075,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
return err;
}
-struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred)
+static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred)
{
struct nfs_open_context *ctx;
@@ -981,6 +1083,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rp
if (ctx != NULL) {
atomic_set(&ctx->count, 1);
ctx->dentry = dget(dentry);
+ ctx->vfsmnt = mntget(mnt);
ctx->cred = get_rpccred(cred);
ctx->state = NULL;
ctx->lockowner = current->files;
@@ -1011,6 +1114,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
if (ctx->cred != NULL)
put_rpccred(ctx->cred);
dput(ctx->dentry);
+ mntput(ctx->vfsmnt);
kfree(ctx);
}
}
@@ -1019,7 +1123,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
* Ensure that mmap has a recent RPC credential for use when writing out
* shared pages
*/
-void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
+static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
{
struct inode *inode = filp->f_dentry->d_inode;
struct nfs_inode *nfsi = NFS_I(inode);
@@ -1051,7 +1155,7 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_c
return ctx;
}
-void nfs_file_clear_open_context(struct file *filp)
+static void nfs_file_clear_open_context(struct file *filp)
{
struct inode *inode = filp->f_dentry->d_inode;
struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data;
@@ -1076,7 +1180,7 @@ int nfs_open(struct inode *inode, struct file *filp)
cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
if (IS_ERR(cred))
return PTR_ERR(cred);
- ctx = alloc_nfs_open_context(filp->f_dentry, cred);
+ ctx = alloc_nfs_open_context(filp->f_vfsmnt, filp->f_dentry, cred);
put_rpccred(cred);
if (ctx == NULL)
return -ENOMEM;
@@ -1185,6 +1289,7 @@ int nfs_attribute_timeout(struct inode *inode)
*/
int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
{
+ nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE);
if (!(NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
&& !nfs_attribute_timeout(inode))
return NFS_STALE(inode) ? -ESTALE : 0;
@@ -1201,6 +1306,7 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
struct nfs_inode *nfsi = NFS_I(inode);
if (nfsi->cache_validity & NFS_INO_INVALID_DATA) {
+ nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);
if (S_ISREG(inode->i_mode))
nfs_sync_mapping(mapping);
invalidate_inode_pages2(mapping);
@@ -1299,39 +1405,37 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
if ((fattr->valid & NFS_ATTR_FATTR) == 0)
return 0;
+ /* Has the inode gone and changed behind our back? */
+ if (nfsi->fileid != fattr->fileid
+ || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) {
+ return -EIO;
+ }
+
/* Are we in the process of updating data on the server? */
data_unstable = nfs_caches_unstable(inode);
/* Do atomic weak cache consistency updates */
nfs_wcc_update_inode(inode, fattr);
- if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
- nfsi->change_attr != fattr->change_attr) {
+ if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0) {
+ if (nfsi->change_attr == fattr->change_attr)
+ goto out;
nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
if (!data_unstable)
nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
}
- /* Has the inode gone and changed behind our back? */
- if (nfsi->fileid != fattr->fileid
- || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) {
- return -EIO;
- }
-
- cur_size = i_size_read(inode);
- new_isize = nfs_size_to_loff_t(fattr->size);
-
/* Verify a few of the more important attributes */
if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
if (!data_unstable)
nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
}
- if (cur_size != new_isize) {
- nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
- if (nfsi->npages == 0)
- nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
- }
+
+ cur_size = i_size_read(inode);
+ new_isize = nfs_size_to_loff_t(fattr->size);
+ if (cur_size != new_isize && nfsi->npages == 0)
+ nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;
/* Have any file permissions changed? */
if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
@@ -1343,6 +1447,7 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
if (inode->i_nlink != fattr->nlink)
nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
+out:
if (!timespec_equal(&inode->i_atime, &fattr->atime))
nfsi->cache_validity |= NFS_INO_INVALID_ATIME;
@@ -1481,15 +1586,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
nfsi->cache_change_attribute = jiffies;
}
- if ((fattr->valid & NFS_ATTR_FATTR_V4)
- && nfsi->change_attr != fattr->change_attr) {
- dprintk("NFS: change_attr change on server for file %s/%ld\n",
- inode->i_sb->s_id, inode->i_ino);
- nfsi->change_attr = fattr->change_attr;
- invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
- nfsi->cache_change_attribute = jiffies;
- }
-
/* If ctime has changed we should definitely clear access+acl caches */
if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) {
invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
@@ -1519,8 +1615,20 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
inode->i_blksize = fattr->du.nfs2.blocksize;
}
+ if ((fattr->valid & NFS_ATTR_FATTR_V4)) {
+ if (nfsi->change_attr != fattr->change_attr) {
+ dprintk("NFS: change_attr change on server for file %s/%ld\n",
+ inode->i_sb->s_id, inode->i_ino);
+ nfsi->change_attr = fattr->change_attr;
+ invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+ nfsi->cache_change_attribute = jiffies;
+ } else
+ invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA);
+ }
+
/* Update attrtimeo value if we're out of the unstable period */
if (invalid & NFS_INO_INVALID_ATTR) {
+ nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
nfsi->attrtimeo_timestamp = jiffies;
} else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) {
@@ -1637,10 +1745,9 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
#endif /* CONFIG_NFS_V3 */
s = ERR_PTR(-ENOMEM);
- server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);
+ server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
if (!server)
goto out_err;
- memset(server, 0, sizeof(struct nfs_server));
/* Zero out the NFS state stuff */
init_nfsv4_state(server);
server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
@@ -1712,6 +1819,7 @@ static void nfs_kill_super(struct super_block *s)
rpciod_down(); /* release rpciod */
+ nfs_free_iostats(server->io_stats);
kfree(server->hostname);
kfree(server);
}
@@ -1738,6 +1846,7 @@ static struct super_operations nfs4_sops = {
.clear_inode = nfs4_clear_inode,
.umount_begin = nfs_umount_begin,
.show_options = nfs_show_options,
+ .show_stats = nfs_show_stats,
};
/*
@@ -1800,6 +1909,9 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans);
+ server->retrans_timeo = timeparms.to_initval;
+ server->retrans_count = timeparms.to_retries;
+
clp = nfs4_get_client(&server->addr.sin_addr);
if (!clp) {
dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
@@ -1941,10 +2053,9 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
return ERR_PTR(-EINVAL);
}
- server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);
+ server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
if (!server)
return ERR_PTR(-ENOMEM);
- memset(server, 0, sizeof(struct nfs_server));
/* Zero out the NFS state stuff */
init_nfsv4_state(server);
server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
@@ -2024,10 +2135,12 @@ static void nfs4_kill_super(struct super_block *sb)
if (server->client != NULL && !IS_ERR(server->client))
rpc_shutdown_client(server->client);
- rpciod_down(); /* release rpciod */
destroy_nfsv4_state(server);
+ rpciod_down();
+
+ nfs_free_iostats(server->io_stats);
kfree(server->hostname);
kfree(server);
}
diff --git a/fs/nfs/iostat.h b/fs/nfs/iostat.h
new file mode 100644
index 00000000000..6350ecbde58
--- /dev/null
+++ b/fs/nfs/iostat.h
@@ -0,0 +1,164 @@
+/*
+ * linux/fs/nfs/iostat.h
+ *
+ * Declarations for NFS client per-mount statistics
+ *
+ * Copyright (C) 2005, 2006 Chuck Lever <cel@netapp.com>
+ *
+ * NFS client per-mount statistics provide information about the health of
+ * the NFS client and the health of each NFS mount point. Generally these
+ * are not for detailed problem diagnosis, but simply to indicate that there
+ * is a problem.
+ *
+ * These counters are not meant to be human-readable, but are meant to be
+ * integrated into system monitoring tools such as "sar" and "iostat". As
+ * such, the counters are sampled by the tools over time, and are never
+ * zeroed after a file system is mounted. Moving averages can be computed
+ * by the tools by taking the difference between two instantaneous samples
+ * and dividing that by the time between the samples.
+ */
+
+#ifndef _NFS_IOSTAT
+#define _NFS_IOSTAT
+
+#define NFS_IOSTAT_VERS "1.0"
+
+/*
+ * NFS byte counters
+ *
+ * 1. SERVER - the number of payload bytes read from or written to the
+ * server by the NFS client via an NFS READ or WRITE request.
+ *
+ * 2. NORMAL - the number of bytes read or written by applications via
+ * the read(2) and write(2) system call interfaces.
+ *
+ * 3. DIRECT - the number of bytes read or written from files opened
+ * with the O_DIRECT flag.
+ *
+ * These counters give a view of the data throughput into and out of the NFS
+ * client. Comparing the number of bytes requested by an application with the
+ * number of bytes the client requests from the server can provide an
+ * indication of client efficiency (per-op, cache hits, etc).
+ *
+ * These counters can also help characterize which access methods are in
+ * use. DIRECT by itself shows whether there is any O_DIRECT traffic.
+ * NORMAL + DIRECT shows how much data is going through the system call
+ * interface. A large amount of SERVER traffic without much NORMAL or
+ * DIRECT traffic shows that applications are using mapped files.
+ *
+ * NFS page counters
+ *
+ * These count the number of pages read or written via nfs_readpage(),
+ * nfs_readpages(), or their write equivalents.
+ */
+enum nfs_stat_bytecounters {
+ NFSIOS_NORMALREADBYTES = 0,
+ NFSIOS_NORMALWRITTENBYTES,
+ NFSIOS_DIRECTREADBYTES,
+ NFSIOS_DIRECTWRITTENBYTES,
+ NFSIOS_SERVERREADBYTES,
+ NFSIOS_SERVERWRITTENBYTES,
+ NFSIOS_READPAGES,
+ NFSIOS_WRITEPAGES,
+ __NFSIOS_BYTESMAX,
+};
+
+/*
+ * NFS event counters
+ *
+ * These counters provide a low-overhead way of monitoring client activity
+ * without enabling NFS trace debugging. The counters show the rate at
+ * which VFS requests are made, and how often the client invalidates its
+ * data and attribute caches. This allows system administrators to monitor
+ * such things as how close-to-open is working, and answer questions such
+ * as "why are there so many GETATTR requests on the wire?"
+ *
+ * They also count anamolous events such as short reads and writes, silly
+ * renames due to close-after-delete, and operations that change the size
+ * of a file (such operations can often be the source of data corruption
+ * if applications aren't using file locking properly).
+ */
+enum nfs_stat_eventcounters {
+ NFSIOS_INODEREVALIDATE = 0,
+ NFSIOS_DENTRYREVALIDATE,
+ NFSIOS_DATAINVALIDATE,
+ NFSIOS_ATTRINVALIDATE,
+ NFSIOS_VFSOPEN,
+ NFSIOS_VFSLOOKUP,
+ NFSIOS_VFSACCESS,
+ NFSIOS_VFSUPDATEPAGE,
+ NFSIOS_VFSREADPAGE,
+ NFSIOS_VFSREADPAGES,
+ NFSIOS_VFSWRITEPAGE,
+ NFSIOS_VFSWRITEPAGES,
+ NFSIOS_VFSGETDENTS,
+ NFSIOS_VFSSETATTR,
+ NFSIOS_VFSFLUSH,
+ NFSIOS_VFSFSYNC,
+ NFSIOS_VFSLOCK,
+ NFSIOS_VFSRELEASE,
+ NFSIOS_CONGESTIONWAIT,
+ NFSIOS_SETATTRTRUNC,
+ NFSIOS_EXTENDWRITE,
+ NFSIOS_SILLYRENAME,
+ NFSIOS_SHORTREAD,
+ NFSIOS_SHORTWRITE,
+ NFSIOS_DELAY,
+ __NFSIOS_COUNTSMAX,
+};
+
+#ifdef __KERNEL__
+
+#include <linux/percpu.h>
+#include <linux/cache.h>
+
+struct nfs_iostats {
+ unsigned long long bytes[__NFSIOS_BYTESMAX];
+ unsigned long events[__NFSIOS_COUNTSMAX];
+} ____cacheline_aligned;
+
+static inline void nfs_inc_server_stats(struct nfs_server *server, enum nfs_stat_eventcounters stat)
+{
+ struct nfs_iostats *iostats;
+ int cpu;
+
+ cpu = get_cpu();
+ iostats = per_cpu_ptr(server->io_stats, cpu);
+ iostats->events[stat] ++;
+ put_cpu_no_resched();
+}
+
+static inline void nfs_inc_stats(struct inode *inode, enum nfs_stat_eventcounters stat)
+{
+ nfs_inc_server_stats(NFS_SERVER(inode), stat);
+}
+
+static inline void nfs_add_server_stats(struct nfs_server *server, enum nfs_stat_bytecounters stat, unsigned long addend)
+{
+ struct nfs_iostats *iostats;
+ int cpu;
+
+ cpu = get_cpu();
+ iostats = per_cpu_ptr(server->io_stats, cpu);
+ iostats->bytes[stat] += addend;
+ put_cpu_no_resched();
+}
+
+static inline void nfs_add_stats(struct inode *inode, enum nfs_stat_bytecounters stat, unsigned long addend)
+{
+ nfs_add_server_stats(NFS_SERVER(inode), stat, addend);
+}
+
+static inline struct nfs_iostats *nfs_alloc_iostats(void)
+{
+ return alloc_percpu(struct nfs_iostats);
+}
+
+static inline void nfs_free_iostats(struct nfs_iostats *stats)
+{
+ if (stats != NULL)
+ free_percpu(stats);
+}
+
+#endif
+#endif
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 0b9a78353d6..445abb4d421 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -49,9 +49,12 @@ nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
struct mnt_fhstatus result = {
.fh = fh
};
+ struct rpc_message msg = {
+ .rpc_argp = path,
+ .rpc_resp = &result,
+ };
char hostname[32];
int status;
- int call;
dprintk("NFS: nfs_mount(%08x:%s)\n",
(unsigned)ntohl(addr->sin_addr.s_addr), path);
@@ -61,8 +64,12 @@ nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
if (IS_ERR(mnt_clnt))
return PTR_ERR(mnt_clnt);
- call = (version == NFS_MNT3_VERSION) ? MOUNTPROC3_MNT : MNTPROC_MNT;
- status = rpc_call(mnt_clnt, call, path, &result, 0);
+ if (version == NFS_MNT3_VERSION)
+ msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT];
+ else
+ msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT];
+
+ status = rpc_call_sync(mnt_clnt, &msg, 0);
return status < 0? status : (result.status? -EACCES : 0);
}
@@ -137,6 +144,8 @@ static struct rpc_procinfo mnt_procedures[] = {
.p_encode = (kxdrproc_t) xdr_encode_dirpath,
.p_decode = (kxdrproc_t) xdr_decode_fhstatus,
.p_bufsiz = MNT_dirpath_sz << 2,
+ .p_statidx = MNTPROC_MNT,
+ .p_name = "MOUNT",
},
};
@@ -146,6 +155,8 @@ static struct rpc_procinfo mnt3_procedures[] = {
.p_encode = (kxdrproc_t) xdr_encode_dirpath,
.p_decode = (kxdrproc_t) xdr_decode_fhstatus3,
.p_bufsiz = MNT_dirpath_sz << 2,
+ .p_statidx = MOUNTPROC3_MNT,
+ .p_name = "MOUNT",
},
};
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 6548a65de94..f0015fa876e 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -682,7 +682,9 @@ nfs_stat_to_errno(int stat)
.p_encode = (kxdrproc_t) nfs_xdr_##argtype, \
.p_decode = (kxdrproc_t) nfs_xdr_##restype, \
.p_bufsiz = MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2, \
- .p_timer = timer \
+ .p_timer = timer, \
+ .p_statidx = NFSPROC_##proc, \
+ .p_name = #proc, \
}
struct rpc_procinfo nfs_procedures[] = {
PROC(GETATTR, fhandle, attrstat, 1),
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index 6a5bbc0ae94..33287879bd2 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -190,6 +190,10 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
struct nfs3_getaclres res = {
.fattr = &fattr,
};
+ struct rpc_message msg = {
+ .rpc_argp = &args,
+ .rpc_resp = &res,
+ };
struct posix_acl *acl;
int status, count;
@@ -218,8 +222,8 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
return NULL;
dprintk("NFS call getacl\n");
- status = rpc_call(server->client_acl, ACLPROC3_GETACL,
- &args, &res, 0);
+ msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_GETACL];
+ status = rpc_call_sync(server->client_acl, &msg, 0);
dprintk("NFS reply getacl: %d\n", status);
/* pages may have been allocated at the xdr layer. */
@@ -286,6 +290,10 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
.acl_access = acl,
.pages = pages,
};
+ struct rpc_message msg = {
+ .rpc_argp = &args,
+ .rpc_resp = &fattr,
+ };
int status, count;
status = -EOPNOTSUPP;
@@ -306,8 +314,8 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
dprintk("NFS call setacl\n");
nfs_begin_data_update(inode);
- status = rpc_call(server->client_acl, ACLPROC3_SETACL,
- &args, &fattr, 0);
+ msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL];
+ status = rpc_call_sync(server->client_acl, &msg, 0);
spin_lock(&inode->i_lock);
NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS;
spin_unlock(&inode->i_lock);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index ed67567f055..cf186f0d2b3 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -19,6 +19,8 @@
#include <linux/smp_lock.h>
#include <linux/nfs_mount.h>
+#include "iostat.h"
+
#define NFSDBG_FACILITY NFSDBG_PROC
extern struct rpc_procinfo nfs3_procedures[];
@@ -41,27 +43,14 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
return res;
}
-static inline int
-nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
-{
- struct rpc_message msg = {
- .rpc_proc = &clnt->cl_procinfo[proc],
- .rpc_argp = argp,
- .rpc_resp = resp,
- };
- return nfs3_rpc_wrapper(clnt, &msg, flags);
-}
-
-#define rpc_call(clnt, proc, argp, resp, flags) \
- nfs3_rpc_call_wrapper(clnt, proc, argp, resp, flags)
-#define rpc_call_sync(clnt, msg, flags) \
- nfs3_rpc_wrapper(clnt, msg, flags)
+#define rpc_call_sync(clnt, msg, flags) nfs3_rpc_wrapper(clnt, msg, flags)
static int
-nfs3_async_handle_jukebox(struct rpc_task *task)
+nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode)
{
if (task->tk_status != -EJUKEBOX)
return 0;
+ nfs_inc_stats(inode, NFSIOS_DELAY);
task->tk_status = 0;
rpc_restart_call(task);
rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
@@ -72,14 +61,21 @@ static int
do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle,
struct nfs_fsinfo *info)
{
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_FSINFO],
+ .rpc_argp = fhandle,
+ .rpc_resp = info,
+ };
int status;
dprintk("%s: call fsinfo\n", __FUNCTION__);
nfs_fattr_init(info->fattr);
- status = rpc_call(client, NFS3PROC_FSINFO, fhandle, info, 0);
+ status = rpc_call_sync(client, &msg, 0);
dprintk("%s: reply fsinfo: %d\n", __FUNCTION__, status);
if (!(info->fattr->valid & NFS_ATTR_FATTR)) {
- status = rpc_call(client, NFS3PROC_GETATTR, fhandle, info->fattr, 0);
+ msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
+ msg.rpc_resp = info->fattr;
+ status = rpc_call_sync(client, &msg, 0);
dprintk("%s: reply getattr: %d\n", __FUNCTION__, status);
}
return status;
@@ -107,12 +103,16 @@ static int
nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR],
+ .rpc_argp = fhandle,
+ .rpc_resp = fattr,
+ };
int status;
dprintk("NFS call getattr\n");
nfs_fattr_init(fattr);
- status = rpc_call(server->client, NFS3PROC_GETATTR,
- fhandle, fattr, 0);
+ status = rpc_call_sync(server->client, &msg, 0);
dprintk("NFS reply getattr: %d\n", status);
return status;
}
@@ -126,11 +126,16 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
.fh = NFS_FH(inode),
.sattr = sattr,
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_SETATTR],
+ .rpc_argp = &arg,
+ .rpc_resp = fattr,
+ };
int status;
dprintk("NFS call setattr\n");
nfs_fattr_init(fattr);
- status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0);
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
if (status == 0)
nfs_setattr_update_inode(inode, sattr);
dprintk("NFS reply setattr: %d\n", status);
@@ -152,15 +157,23 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name,
.fh = fhandle,
.fattr = fattr
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_LOOKUP],
+ .rpc_argp = &arg,
+ .rpc_resp = &res,
+ };
int status;
dprintk("NFS call lookup %s\n", name->name);
nfs_fattr_init(&dir_attr);
nfs_fattr_init(fattr);
- status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0);
- if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR))
- status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR,
- fhandle, fattr, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) {
+ msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
+ msg.rpc_argp = fhandle;
+ msg.rpc_resp = fattr;
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ }
dprintk("NFS reply lookup: %d\n", status);
if (status >= 0)
status = nfs_refresh_inode(dir, &dir_attr);
@@ -180,7 +193,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
.rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS],
.rpc_argp = &arg,
.rpc_resp = &res,
- .rpc_cred = entry->cred
+ .rpc_cred = entry->cred,
};
int mode = entry->mask;
int status;
@@ -226,12 +239,16 @@ static int nfs3_proc_readlink(struct inode *inode, struct page *page,
.pglen = pglen,
.pages = &page
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_READLINK],
+ .rpc_argp = &args,
+ .rpc_resp = &fattr,
+ };
int status;
dprintk("NFS call readlink\n");
nfs_fattr_init(&fattr);
- status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK,
- &args, &fattr, 0);
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
nfs_refresh_inode(inode, &fattr);
dprintk("NFS reply readlink: %d\n", status);
return status;
@@ -327,6 +344,11 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
.fh = &fhandle,
.fattr = &fattr
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_CREATE],
+ .rpc_argp = &arg,
+ .rpc_resp = &res,
+ };
mode_t mode = sattr->ia_mode;
int status;
@@ -343,8 +365,8 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
again:
nfs_fattr_init(&dir_attr);
nfs_fattr_init(&fattr);
- status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0);
- nfs_post_op_update_inode(dir, &dir_attr);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ nfs_refresh_inode(dir, &dir_attr);
/* If the server doesn't support the exclusive creation semantics,
* try again with simple 'guarded' mode. */
@@ -447,7 +469,7 @@ nfs3_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
struct rpc_message *msg = &task->tk_msg;
struct nfs_fattr *dir_attr;
- if (nfs3_async_handle_jukebox(task))
+ if (nfs3_async_handle_jukebox(task, dir->d_inode))
return 1;
if (msg->rpc_argp) {
dir_attr = (struct nfs_fattr*)msg->rpc_resp;
@@ -474,12 +496,17 @@ nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
.fromattr = &old_dir_attr,
.toattr = &new_dir_attr
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_RENAME],
+ .rpc_argp = &arg,
+ .rpc_resp = &res,
+ };
int status;
dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name);
nfs_fattr_init(&old_dir_attr);
nfs_fattr_init(&new_dir_attr);
- status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0);
+ status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
nfs_post_op_update_inode(old_dir, &old_dir_attr);
nfs_post_op_update_inode(new_dir, &new_dir_attr);
dprintk("NFS reply rename: %d\n", status);
@@ -500,12 +527,17 @@ nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
.dir_attr = &dir_attr,
.fattr = &fattr
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_LINK],
+ .rpc_argp = &arg,
+ .rpc_resp = &res,
+ };
int status;
dprintk("NFS call link %s\n", name->name);
nfs_fattr_init(&dir_attr);
nfs_fattr_init(&fattr);
- status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0);
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
nfs_post_op_update_inode(dir, &dir_attr);
nfs_post_op_update_inode(inode, &fattr);
dprintk("NFS reply link: %d\n", status);
@@ -531,6 +563,11 @@ nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
.fh = fhandle,
.fattr = fattr
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK],
+ .rpc_argp = &arg,
+ .rpc_resp = &res,
+ };
int status;
if (path->len > NFS3_MAXPATHLEN)
@@ -538,7 +575,7 @@ nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
dprintk("NFS call symlink %s -> %s\n", name->name, path->name);
nfs_fattr_init(&dir_attr);
nfs_fattr_init(fattr);
- status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
nfs_post_op_update_inode(dir, &dir_attr);
dprintk("NFS reply symlink: %d\n", status);
return status;
@@ -560,6 +597,11 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
.fh = &fhandle,
.fattr = &fattr
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR],
+ .rpc_argp = &arg,
+ .rpc_resp = &res,
+ };
int mode = sattr->ia_mode;
int status;
@@ -569,7 +611,7 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
nfs_fattr_init(&dir_attr);
nfs_fattr_init(&fattr);
- status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
nfs_post_op_update_inode(dir, &dir_attr);
if (status != 0)
goto out;
@@ -591,11 +633,16 @@ nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
.name = name->name,
.len = name->len
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_RMDIR],
+ .rpc_argp = &arg,
+ .rpc_resp = &dir_attr,
+ };
int status;
dprintk("NFS call rmdir %s\n", name->name);
nfs_fattr_init(&dir_attr);
- status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
nfs_post_op_update_inode(dir, &dir_attr);
dprintk("NFS reply rmdir: %d\n", status);
return status;
@@ -672,6 +719,11 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
.fh = &fh,
.fattr = &fattr
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD],
+ .rpc_argp = &arg,
+ .rpc_resp = &res,
+ };
mode_t mode = sattr->ia_mode;
int status;
@@ -690,7 +742,7 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
nfs_fattr_init(&dir_attr);
nfs_fattr_init(&fattr);
- status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
nfs_post_op_update_inode(dir, &dir_attr);
if (status != 0)
goto out;
@@ -707,11 +759,16 @@ static int
nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsstat *stat)
{
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_FSSTAT],
+ .rpc_argp = fhandle,
+ .rpc_resp = stat,
+ };
int status;
dprintk("NFS call fsstat\n");
nfs_fattr_init(stat->fattr);
- status = rpc_call(server->client, NFS3PROC_FSSTAT, fhandle, stat, 0);
+ status = rpc_call_sync(server->client, &msg, 0);
dprintk("NFS reply statfs: %d\n", status);
return status;
}
@@ -720,11 +777,16 @@ static int
nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsinfo *info)
{
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_FSINFO],
+ .rpc_argp = fhandle,
+ .rpc_resp = info,
+ };
int status;
dprintk("NFS call fsinfo\n");
nfs_fattr_init(info->fattr);
- status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0);
+ status = rpc_call_sync(server->client_sys, &msg, 0);
dprintk("NFS reply fsinfo: %d\n", status);
return status;
}
@@ -733,40 +795,34 @@ static int
nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_pathconf *info)
{
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_PATHCONF],
+ .rpc_argp = fhandle,
+ .rpc_resp = info,
+ };
int status;
dprintk("NFS call pathconf\n");
nfs_fattr_init(info->fattr);
- status = rpc_call(server->client, NFS3PROC_PATHCONF, fhandle, info, 0);
+ status = rpc_call_sync(server->client, &msg, 0);
dprintk("NFS reply pathconf: %d\n", status);
return status;
}
extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
-static void nfs3_read_done(struct rpc_task *task, void *calldata)
+static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data)
{
- struct nfs_read_data *data = calldata;
-
- if (nfs3_async_handle_jukebox(task))
- return;
+ if (nfs3_async_handle_jukebox(task, data->inode))
+ return -EAGAIN;
/* Call back common NFS readpage processing */
if (task->tk_status >= 0)
nfs_refresh_inode(data->inode, &data->fattr);
- nfs_readpage_result(task, calldata);
+ return 0;
}
-static const struct rpc_call_ops nfs3_read_ops = {
- .rpc_call_done = nfs3_read_done,
- .rpc_release = nfs_readdata_release,
-};
-
-static void
-nfs3_proc_read_setup(struct nfs_read_data *data)
+static void nfs3_proc_read_setup(struct nfs_read_data *data)
{
- struct rpc_task *task = &data->task;
- struct inode *inode = data->inode;
- int flags;
struct rpc_message msg = {
.rpc_proc = &nfs3_procedures[NFS3PROC_READ],
.rpc_argp = &data->args,
@@ -774,37 +830,20 @@ nfs3_proc_read_setup(struct nfs_read_data *data)
.rpc_cred = data->cred,
};
- /* N.B. Do we need to test? Never called for swapfile inode */
- flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
-
- /* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_read_ops, data);
- rpc_call_setup(task, &msg, 0);
+ rpc_call_setup(&data->task, &msg, 0);
}
-static void nfs3_write_done(struct rpc_task *task, void *calldata)
+static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data)
{
- struct nfs_write_data *data = calldata;
-
- if (nfs3_async_handle_jukebox(task))
- return;
+ if (nfs3_async_handle_jukebox(task, data->inode))
+ return -EAGAIN;
if (task->tk_status >= 0)
nfs_post_op_update_inode(data->inode, data->res.fattr);
- nfs_writeback_done(task, calldata);
+ return 0;
}
-static const struct rpc_call_ops nfs3_write_ops = {
- .rpc_call_done = nfs3_write_done,
- .rpc_release = nfs_writedata_release,
-};
-
-static void
-nfs3_proc_write_setup(struct nfs_write_data *data, int how)
+static void nfs3_proc_write_setup(struct nfs_write_data *data, int how)
{
- struct rpc_task *task = &data->task;
- struct inode *inode = data->inode;
- int stable;
- int flags;
struct rpc_message msg = {
.rpc_proc = &nfs3_procedures[NFS3PROC_WRITE],
.rpc_argp = &data->args,
@@ -812,45 +851,28 @@ nfs3_proc_write_setup(struct nfs_write_data *data, int how)
.rpc_cred = data->cred,
};
+ data->args.stable = NFS_UNSTABLE;
if (how & FLUSH_STABLE) {
- if (!NFS_I(inode)->ncommit)
- stable = NFS_FILE_SYNC;
- else
- stable = NFS_DATA_SYNC;
- } else
- stable = NFS_UNSTABLE;
- data->args.stable = stable;
-
- /* Set the initial flags for the task. */
- flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
+ data->args.stable = NFS_FILE_SYNC;
+ if (NFS_I(data->inode)->ncommit)
+ data->args.stable = NFS_DATA_SYNC;
+ }
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_write_ops, data);
- rpc_call_setup(task, &msg, 0);
+ rpc_call_setup(&data->task, &msg, 0);
}
-static void nfs3_commit_done(struct rpc_task *task, void *calldata)
+static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data)
{
- struct nfs_write_data *data = calldata;
-
- if (nfs3_async_handle_jukebox(task))
- return;
+ if (nfs3_async_handle_jukebox(task, data->inode))
+ return -EAGAIN;
if (task->tk_status >= 0)
nfs_post_op_update_inode(data->inode, data->res.fattr);
- nfs_commit_done(task, calldata);
+ return 0;
}
-static const struct rpc_call_ops nfs3_commit_ops = {
- .rpc_call_done = nfs3_commit_done,
- .rpc_release = nfs_commit_release,
-};
-
-static void
-nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
+static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
{
- struct rpc_task *task = &data->task;
- struct inode *inode = data->inode;
- int flags;
struct rpc_message msg = {
.rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT],
.rpc_argp = &data->args,
@@ -858,12 +880,7 @@ nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
.rpc_cred = data->cred,
};
- /* Set the initial flags for the task. */
- flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
-
- /* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_commit_ops, data);
- rpc_call_setup(task, &msg, 0);
+ rpc_call_setup(&data->task, &msg, 0);
}
static int
@@ -902,8 +919,11 @@ struct nfs_rpc_ops nfs_v3_clientops = {
.pathconf = nfs3_proc_pathconf,
.decode_dirent = nfs3_decode_dirent,
.read_setup = nfs3_proc_read_setup,
+ .read_done = nfs3_read_done,
.write_setup = nfs3_proc_write_setup,
+ .write_done = nfs3_write_done,
.commit_setup = nfs3_proc_commit_setup,
+ .commit_done = nfs3_commit_done,
.file_open = nfs_open,
.file_release = nfs_release,
.lock = nfs3_proc_lock,
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 5224a191efb..ec233619687 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -1109,7 +1109,9 @@ nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
.p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
.p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
.p_bufsiz = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2, \
- .p_timer = timer \
+ .p_timer = timer, \
+ .p_statidx = NFS3PROC_##proc, \
+ .p_name = #proc, \
}
struct rpc_procinfo nfs3_procedures[] = {
@@ -1150,6 +1152,7 @@ static struct rpc_procinfo nfs3_acl_procedures[] = {
.p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
.p_bufsiz = MAX(ACL3_getaclargs_sz, ACL3_getaclres_sz) << 2,
.p_timer = 1,
+ .p_name = "GETACL",
},
[ACLPROC3_SETACL] = {
.p_proc = ACLPROC3_SETACL,
@@ -1157,6 +1160,7 @@ static struct rpc_procinfo nfs3_acl_procedures[] = {
.p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
.p_bufsiz = MAX(ACL3_setaclargs_sz, ACL3_setaclres_sz) << 2,
.p_timer = 0,
+ .p_name = "SETACL",
},
};
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f8c0066e02e..47ece1dd3c6 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -51,6 +51,7 @@
#include "nfs4_fs.h"
#include "delegation.h"
+#include "iostat.h"
#define NFSDBG_FACILITY NFSDBG_PROC
@@ -335,7 +336,7 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
if (!(data->f_attr.valid & NFS_ATTR_FATTR))
goto out;
inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr);
- if (inode == NULL)
+ if (IS_ERR(inode))
goto out;
state = nfs4_get_open_state(inode, data->owner);
if (state == NULL)
@@ -604,11 +605,14 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
int status;
atomic_inc(&data->count);
+ /*
+ * If rpc_run_task() ends up calling ->rpc_release(), we
+ * want to ensure that it takes the 'error' code path.
+ */
+ data->rpc_status = -ENOMEM;
task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data);
- if (IS_ERR(task)) {
- nfs4_opendata_free(data);
+ if (IS_ERR(task))
return PTR_ERR(task);
- }
status = nfs4_wait_for_completion_rpc_task(task);
if (status != 0) {
data->cancelled = 1;
@@ -707,11 +711,14 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
int status;
atomic_inc(&data->count);
+ /*
+ * If rpc_run_task() ends up calling ->rpc_release(), we
+ * want to ensure that it takes the 'error' code path.
+ */
+ data->rpc_status = -ENOMEM;
task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data);
- if (IS_ERR(task)) {
- nfs4_opendata_free(data);
+ if (IS_ERR(task))
return PTR_ERR(task);
- }
status = nfs4_wait_for_completion_rpc_task(task);
if (status != 0) {
data->cancelled = 1;
@@ -908,7 +915,7 @@ out_put_state_owner:
static struct nfs4_state *nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred)
{
struct nfs4_exception exception = { };
- struct nfs4_state *res;
+ struct nfs4_state *res = ERR_PTR(-EIO);
int err;
do {
@@ -1017,12 +1024,12 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry,
return res;
}
-static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
- struct nfs_fh *fhandle, struct iattr *sattr,
- struct nfs4_state *state)
+static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
+ struct iattr *sattr, struct nfs4_state *state)
{
+ struct nfs_server *server = NFS_SERVER(inode);
struct nfs_setattrargs arg = {
- .fh = fhandle,
+ .fh = NFS_FH(inode),
.iap = sattr,
.server = server,
.bitmask = server->attr_bitmask,
@@ -1041,7 +1048,9 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
nfs_fattr_init(fattr);
- if (state != NULL) {
+ if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) {
+ /* Use that stateid */
+ } else if (state != NULL) {
msg.rpc_cred = state->owner->so_cred;
nfs4_copy_stateid(&arg.stateid, state, current->files);
} else
@@ -1053,16 +1062,15 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
return status;
}
-static int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
- struct nfs_fh *fhandle, struct iattr *sattr,
- struct nfs4_state *state)
+static int nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
+ struct iattr *sattr, struct nfs4_state *state)
{
+ struct nfs_server *server = NFS_SERVER(inode);
struct nfs4_exception exception = { };
int err;
do {
err = nfs4_handle_exception(server,
- _nfs4_do_setattr(server, fattr, fhandle, sattr,
- state),
+ _nfs4_do_setattr(inode, fattr, sattr, state),
&exception);
} while (exception.retry);
return err;
@@ -1503,8 +1511,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
if (ctx != NULL)
state = ctx->state;
- status = nfs4_do_setattr(NFS_SERVER(inode), fattr,
- NFS_FH(inode), sattr, state);
+ status = nfs4_do_setattr(inode, fattr, sattr, state);
if (status == 0)
nfs_setattr_update_inode(inode, sattr);
if (ctx != NULL)
@@ -1823,8 +1830,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
d_instantiate(dentry, igrab(state->inode));
if (flags & O_EXCL) {
struct nfs_fattr fattr;
- status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
- NFS_FH(state->inode), sattr, state);
+ status = nfs4_do_setattr(state->inode, &fattr, sattr, state);
if (status == 0)
nfs_setattr_update_inode(state->inode, sattr);
}
@@ -2344,75 +2350,50 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
return err;
}
-static void nfs4_read_done(struct rpc_task *task, void *calldata)
+static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
{
- struct nfs_read_data *data = calldata;
- struct inode *inode = data->inode;
+ struct nfs_server *server = NFS_SERVER(data->inode);
- if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
+ if (nfs4_async_handle_error(task, server) == -EAGAIN) {
rpc_restart_call(task);
- return;
+ return -EAGAIN;
}
if (task->tk_status > 0)
- renew_lease(NFS_SERVER(inode), data->timestamp);
- /* Call back common NFS readpage processing */
- nfs_readpage_result(task, calldata);
+ renew_lease(server, data->timestamp);
+ return 0;
}
-static const struct rpc_call_ops nfs4_read_ops = {
- .rpc_call_done = nfs4_read_done,
- .rpc_release = nfs_readdata_release,
-};
-
-static void
-nfs4_proc_read_setup(struct nfs_read_data *data)
+static void nfs4_proc_read_setup(struct nfs_read_data *data)
{
- struct rpc_task *task = &data->task;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ],
.rpc_argp = &data->args,
.rpc_resp = &data->res,
.rpc_cred = data->cred,
};
- struct inode *inode = data->inode;
- int flags;
data->timestamp = jiffies;
- /* N.B. Do we need to test? Never called for swapfile inode */
- flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
-
- /* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_read_ops, data);
- rpc_call_setup(task, &msg, 0);
+ rpc_call_setup(&data->task, &msg, 0);
}
-static void nfs4_write_done(struct rpc_task *task, void *calldata)
+static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
{
- struct nfs_write_data *data = calldata;
struct inode *inode = data->inode;
if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
rpc_restart_call(task);
- return;
+ return -EAGAIN;
}
if (task->tk_status >= 0) {
renew_lease(NFS_SERVER(inode), data->timestamp);
nfs_post_op_update_inode(inode, data->res.fattr);
}
- /* Call back common NFS writeback processing */
- nfs_writeback_done(task, calldata);
+ return 0;
}
-static const struct rpc_call_ops nfs4_write_ops = {
- .rpc_call_done = nfs4_write_done,
- .rpc_release = nfs_writedata_release,
-};
-
-static void
-nfs4_proc_write_setup(struct nfs_write_data *data, int how)
+static void nfs4_proc_write_setup(struct nfs_write_data *data, int how)
{
- struct rpc_task *task = &data->task;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE],
.rpc_argp = &data->args,
@@ -2422,7 +2403,6 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how)
struct inode *inode = data->inode;
struct nfs_server *server = NFS_SERVER(inode);
int stable;
- int flags;
if (how & FLUSH_STABLE) {
if (!NFS_I(inode)->ncommit)
@@ -2437,57 +2417,37 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how)
data->timestamp = jiffies;
- /* Set the initial flags for the task. */
- flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
-
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_write_ops, data);
- rpc_call_setup(task, &msg, 0);
+ rpc_call_setup(&data->task, &msg, 0);
}
-static void nfs4_commit_done(struct rpc_task *task, void *calldata)
+static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
{
- struct nfs_write_data *data = calldata;
struct inode *inode = data->inode;
if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
rpc_restart_call(task);
- return;
+ return -EAGAIN;
}
if (task->tk_status >= 0)
nfs_post_op_update_inode(inode, data->res.fattr);
- /* Call back common NFS writeback processing */
- nfs_commit_done(task, calldata);
+ return 0;
}
-static const struct rpc_call_ops nfs4_commit_ops = {
- .rpc_call_done = nfs4_commit_done,
- .rpc_release = nfs_commit_release,
-};
-
-static void
-nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
+static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
{
- struct rpc_task *task = &data->task;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT],
.rpc_argp = &data->args,
.rpc_resp = &data->res,
.rpc_cred = data->cred,
};
- struct inode *inode = data->inode;
- struct nfs_server *server = NFS_SERVER(inode);
- int flags;
+ struct nfs_server *server = NFS_SERVER(data->inode);
data->args.bitmask = server->attr_bitmask;
data->res.server = server;
- /* Set the initial flags for the task. */
- flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
-
- /* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_commit_ops, data);
- rpc_call_setup(task, &msg, 0);
+ rpc_call_setup(&data->task, &msg, 0);
}
/*
@@ -2755,8 +2715,10 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
rpc_wake_up_task(task);
task->tk_status = 0;
return -EAGAIN;
- case -NFS4ERR_GRACE:
case -NFS4ERR_DELAY:
+ nfs_inc_server_stats((struct nfs_server *) server,
+ NFSIOS_DELAY);
+ case -NFS4ERR_GRACE:
rpc_delay(task, NFS4_POLL_RETRY_MAX);
task->tk_status = 0;
return -EAGAIN;
@@ -2893,8 +2855,7 @@ int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short p
return status;
}
-int
-nfs4_proc_setclientid_confirm(struct nfs4_client *clp, struct rpc_cred *cred)
+static int _nfs4_proc_setclientid_confirm(struct nfs4_client *clp, struct rpc_cred *cred)
{
struct nfs_fsinfo fsinfo;
struct rpc_message msg = {
@@ -2918,6 +2879,24 @@ nfs4_proc_setclientid_confirm(struct nfs4_client *clp, struct rpc_cred *cred)
return status;
}
+int nfs4_proc_setclientid_confirm(struct nfs4_client *clp, struct rpc_cred *cred)
+{
+ long timeout;
+ int err;
+ do {
+ err = _nfs4_proc_setclientid_confirm(clp, cred);
+ switch (err) {
+ case 0:
+ return err;
+ case -NFS4ERR_RESOURCE:
+ /* The IBM lawyers misread another document! */
+ case -NFS4ERR_DELAY:
+ err = nfs4_delay(clp->cl_rpcclient, &timeout);
+ }
+ } while (err == 0);
+ return err;
+}
+
struct nfs4_delegreturndata {
struct nfs4_delegreturnargs args;
struct nfs4_delegreturnres res;
@@ -2958,7 +2937,7 @@ static void nfs4_delegreturn_release(void *calldata)
kfree(calldata);
}
-const static struct rpc_call_ops nfs4_delegreturn_ops = {
+static const struct rpc_call_ops nfs4_delegreturn_ops = {
.rpc_call_prepare = nfs4_delegreturn_prepare,
.rpc_call_done = nfs4_delegreturn_done,
.rpc_release = nfs4_delegreturn_release,
@@ -2986,10 +2965,8 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
data->rpc_status = 0;
task = rpc_run_task(NFS_CLIENT(inode), RPC_TASK_ASYNC, &nfs4_delegreturn_ops, data);
- if (IS_ERR(task)) {
- nfs4_delegreturn_release(data);
+ if (IS_ERR(task))
return PTR_ERR(task);
- }
status = nfs4_wait_for_completion_rpc_task(task);
if (status == 0) {
status = data->rpc_status;
@@ -3209,7 +3186,6 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
struct nfs_seqid *seqid)
{
struct nfs4_unlockdata *data;
- struct rpc_task *task;
data = nfs4_alloc_unlockdata(fl, ctx, lsp, seqid);
if (data == NULL) {
@@ -3219,10 +3195,7 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
/* Unlock _before_ we do the RPC call */
do_vfs_lock(fl->fl_file, fl);
- task = rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data);
- if (IS_ERR(task))
- nfs4_locku_release_calldata(data);
- return task;
+ return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data);
}
static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
@@ -3403,10 +3376,8 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
data->arg.reclaim = 1;
task = rpc_run_task(NFS_CLIENT(state->inode), RPC_TASK_ASYNC,
&nfs4_lock_ops, data);
- if (IS_ERR(task)) {
- nfs4_lock_release(data);
+ if (IS_ERR(task))
return PTR_ERR(task);
- }
ret = nfs4_wait_for_completion_rpc_task(task);
if (ret == 0) {
ret = data->rpc_status;
@@ -3588,6 +3559,8 @@ ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
{
size_t len = strlen(XATTR_NAME_NFSV4_ACL) + 1;
+ if (!nfs4_server_supports_acls(NFS_SERVER(dentry->d_inode)))
+ return 0;
if (buf && buflen < len)
return -ERANGE;
if (buf)
@@ -3644,8 +3617,11 @@ struct nfs_rpc_ops nfs_v4_clientops = {
.pathconf = nfs4_proc_pathconf,
.decode_dirent = nfs4_decode_dirent,
.read_setup = nfs4_proc_read_setup,
+ .read_done = nfs4_read_done,
.write_setup = nfs4_proc_write_setup,
+ .write_done = nfs4_write_done,
.commit_setup = nfs4_proc_commit_setup,
+ .commit_done = nfs4_commit_done,
.file_open = nfs_open,
.file_release = nfs_release,
.lock = nfs4_proc_lock,
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index afad0255e7d..96e5b82c153 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -977,6 +977,7 @@ out:
out_error:
printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n",
NIPQUAD(clp->cl_addr.s_addr), -status);
+ set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
goto out;
}
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 0a1bd36a483..7c5d70efe72 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -4344,6 +4344,8 @@ nfs_stat_to_errno(int stat)
.p_encode = (kxdrproc_t) nfs4_xdr_##argtype, \
.p_decode = (kxdrproc_t) nfs4_xdr_##restype, \
.p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2, \
+ .p_statidx = NFSPROC4_CLNT_##proc, \
+ .p_name = #proc, \
}
struct rpc_procinfo nfs4_procedures[] = {
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index d53857b148e..106aca388eb 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -85,6 +85,9 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
atomic_set(&req->wb_complete, 0);
req->wb_index = page->index;
page_cache_get(page);
+ BUG_ON(PagePrivate(page));
+ BUG_ON(!PageLocked(page));
+ BUG_ON(page->mapping->host != inode);
req->wb_offset = offset;
req->wb_pgbase = offset;
req->wb_bytes = count;
@@ -132,9 +135,11 @@ void nfs_clear_page_writeback(struct nfs_page *req)
{
struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
- spin_lock(&nfsi->req_lock);
- radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
- spin_unlock(&nfsi->req_lock);
+ if (req->wb_page != NULL) {
+ spin_lock(&nfsi->req_lock);
+ radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
+ spin_unlock(&nfsi->req_lock);
+ }
nfs_unlock_request(req);
}
@@ -147,8 +152,9 @@ void nfs_clear_page_writeback(struct nfs_page *req)
*/
void nfs_clear_request(struct nfs_page *req)
{
- if (req->wb_page) {
- page_cache_release(req->wb_page);
+ struct page *page = req->wb_page;
+ if (page != NULL) {
+ page_cache_release(page);
req->wb_page = NULL;
}
}
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index f5150d71c03..9dd85cac2df 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -58,16 +58,23 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
{
struct nfs_fattr *fattr = info->fattr;
struct nfs2_fsstat fsinfo;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_GETATTR],
+ .rpc_argp = fhandle,
+ .rpc_resp = fattr,
+ };
int status;
dprintk("%s: call getattr\n", __FUNCTION__);
nfs_fattr_init(fattr);
- status = rpc_call(server->client_sys, NFSPROC_GETATTR, fhandle, fattr, 0);
+ status = rpc_call_sync(server->client_sys, &msg, 0);
dprintk("%s: reply getattr: %d\n", __FUNCTION__, status);
if (status)
return status;
dprintk("%s: call statfs\n", __FUNCTION__);
- status = rpc_call(server->client_sys, NFSPROC_STATFS, fhandle, &fsinfo, 0);
+ msg.rpc_proc = &nfs_procedures[NFSPROC_STATFS];
+ msg.rpc_resp = &fsinfo;
+ status = rpc_call_sync(server->client_sys, &msg, 0);
dprintk("%s: reply statfs: %d\n", __FUNCTION__, status);
if (status)
return status;
@@ -90,12 +97,16 @@ static int
nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_GETATTR],
+ .rpc_argp = fhandle,
+ .rpc_resp = fattr,
+ };
int status;
dprintk("NFS call getattr\n");
nfs_fattr_init(fattr);
- status = rpc_call(server->client, NFSPROC_GETATTR,
- fhandle, fattr, 0);
+ status = rpc_call_sync(server->client, &msg, 0);
dprintk("NFS reply getattr: %d\n", status);
return status;
}
@@ -109,6 +120,11 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
.fh = NFS_FH(inode),
.sattr = sattr
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_SETATTR],
+ .rpc_argp = &arg,
+ .rpc_resp = fattr,
+ };
int status;
/* Mask out the non-modebit related stuff from attr->ia_mode */
@@ -116,7 +132,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
dprintk("NFS call setattr\n");
nfs_fattr_init(fattr);
- status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0);
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
if (status == 0)
nfs_setattr_update_inode(inode, sattr);
dprintk("NFS reply setattr: %d\n", status);
@@ -136,11 +152,16 @@ nfs_proc_lookup(struct inode *dir, struct qstr *name,
.fh = fhandle,
.fattr = fattr
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_LOOKUP],
+ .rpc_argp = &arg,
+ .rpc_resp = &res,
+ };
int status;
dprintk("NFS call lookup %s\n", name->name);
nfs_fattr_init(fattr);
- status = rpc_call(NFS_CLIENT(dir), NFSPROC_LOOKUP, &arg, &res, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
dprintk("NFS reply lookup: %d\n", status);
return status;
}
@@ -154,10 +175,14 @@ static int nfs_proc_readlink(struct inode *inode, struct page *page,
.pglen = pglen,
.pages = &page
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_READLINK],
+ .rpc_argp = &args,
+ };
int status;
dprintk("NFS call readlink\n");
- status = rpc_call(NFS_CLIENT(inode), NFSPROC_READLINK, &args, NULL, 0);
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
dprintk("NFS reply readlink: %d\n", status);
return status;
}
@@ -233,11 +258,16 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
.fh = &fhandle,
.fattr = &fattr
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_CREATE],
+ .rpc_argp = &arg,
+ .rpc_resp = &res,
+ };
int status;
nfs_fattr_init(&fattr);
dprintk("NFS call create %s\n", dentry->d_name.name);
- status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
if (status == 0)
status = nfs_instantiate(dentry, &fhandle, &fattr);
dprintk("NFS reply create: %d\n", status);
@@ -263,6 +293,11 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
.fh = &fhandle,
.fattr = &fattr
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_CREATE],
+ .rpc_argp = &arg,
+ .rpc_resp = &res,
+ };
int status, mode;
dprintk("NFS call mknod %s\n", dentry->d_name.name);
@@ -277,13 +312,13 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
}
nfs_fattr_init(&fattr);
- status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
nfs_mark_for_revalidate(dir);
if (status == -EINVAL && S_ISFIFO(mode)) {
sattr->ia_mode = mode;
nfs_fattr_init(&fattr);
- status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
}
if (status == 0)
status = nfs_instantiate(dentry, &fhandle, &fattr);
@@ -302,8 +337,6 @@ nfs_proc_remove(struct inode *dir, struct qstr *name)
struct rpc_message msg = {
.rpc_proc = &nfs_procedures[NFSPROC_REMOVE],
.rpc_argp = &arg,
- .rpc_resp = NULL,
- .rpc_cred = NULL
};
int status;
@@ -355,10 +388,14 @@ nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
.toname = new_name->name,
.tolen = new_name->len
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_RENAME],
+ .rpc_argp = &arg,
+ };
int status;
dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name);
- status = rpc_call(NFS_CLIENT(old_dir), NFSPROC_RENAME, &arg, NULL, 0);
+ status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
nfs_mark_for_revalidate(old_dir);
nfs_mark_for_revalidate(new_dir);
dprintk("NFS reply rename: %d\n", status);
@@ -374,10 +411,14 @@ nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
.toname = name->name,
.tolen = name->len
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_LINK],
+ .rpc_argp = &arg,
+ };
int status;
dprintk("NFS call link %s\n", name->name);
- status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0);
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
nfs_mark_for_revalidate(inode);
nfs_mark_for_revalidate(dir);
dprintk("NFS reply link: %d\n", status);
@@ -397,6 +438,10 @@ nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
.tolen = path->len,
.sattr = sattr
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_SYMLINK],
+ .rpc_argp = &arg,
+ };
int status;
if (path->len > NFS2_MAXPATHLEN)
@@ -404,7 +449,7 @@ nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
dprintk("NFS call symlink %s -> %s\n", name->name, path->name);
nfs_fattr_init(fattr);
fhandle->size = 0;
- status = rpc_call(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
nfs_mark_for_revalidate(dir);
dprintk("NFS reply symlink: %d\n", status);
return status;
@@ -425,11 +470,16 @@ nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
.fh = &fhandle,
.fattr = &fattr
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_MKDIR],
+ .rpc_argp = &arg,
+ .rpc_resp = &res,
+ };
int status;
dprintk("NFS call mkdir %s\n", dentry->d_name.name);
nfs_fattr_init(&fattr);
- status = rpc_call(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
nfs_mark_for_revalidate(dir);
if (status == 0)
status = nfs_instantiate(dentry, &fhandle, &fattr);
@@ -445,10 +495,14 @@ nfs_proc_rmdir(struct inode *dir, struct qstr *name)
.name = name->name,
.len = name->len
};
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_RMDIR],
+ .rpc_argp = &arg,
+ };
int status;
dprintk("NFS call rmdir %s\n", name->name);
- status = rpc_call(NFS_CLIENT(dir), NFSPROC_RMDIR, &arg, NULL, 0);
+ status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
nfs_mark_for_revalidate(dir);
dprintk("NFS reply rmdir: %d\n", status);
return status;
@@ -470,13 +524,12 @@ nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
.fh = NFS_FH(dir),
.cookie = cookie,
.count = count,
- .pages = &page
+ .pages = &page,
};
struct rpc_message msg = {
.rpc_proc = &nfs_procedures[NFSPROC_READDIR],
.rpc_argp = &arg,
- .rpc_resp = NULL,
- .rpc_cred = cred
+ .rpc_cred = cred,
};
int status;
@@ -495,11 +548,16 @@ nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsstat *stat)
{
struct nfs2_fsstat fsinfo;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_STATFS],
+ .rpc_argp = fhandle,
+ .rpc_resp = &fsinfo,
+ };
int status;
dprintk("NFS call statfs\n");
nfs_fattr_init(stat->fattr);
- status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0);
+ status = rpc_call_sync(server->client, &msg, 0);
dprintk("NFS reply statfs: %d\n", status);
if (status)
goto out;
@@ -518,11 +576,16 @@ nfs_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsinfo *info)
{
struct nfs2_fsstat fsinfo;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_STATFS],
+ .rpc_argp = fhandle,
+ .rpc_resp = &fsinfo,
+ };
int status;
dprintk("NFS call fsinfo\n");
nfs_fattr_init(info->fattr);
- status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0);
+ status = rpc_call_sync(server->client, &msg, 0);
dprintk("NFS reply fsinfo: %d\n", status);
if (status)
goto out;
@@ -550,10 +613,8 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int);
-static void nfs_read_done(struct rpc_task *task, void *calldata)
+static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
{
- struct nfs_read_data *data = calldata;
-
if (task->tk_status >= 0) {
nfs_refresh_inode(data->inode, data->res.fattr);
/* Emulate the eof flag, which isn't normally needed in NFSv2
@@ -562,20 +623,11 @@ static void nfs_read_done(struct rpc_task *task, void *calldata)
if (data->args.offset + data->args.count >= data->res.fattr->size)
data->res.eof = 1;
}
- nfs_readpage_result(task, calldata);
+ return 0;
}
-static const struct rpc_call_ops nfs_read_ops = {
- .rpc_call_done = nfs_read_done,
- .rpc_release = nfs_readdata_release,
-};
-
-static void
-nfs_proc_read_setup(struct nfs_read_data *data)
+static void nfs_proc_read_setup(struct nfs_read_data *data)
{
- struct rpc_task *task = &data->task;
- struct inode *inode = data->inode;
- int flags;
struct rpc_message msg = {
.rpc_proc = &nfs_procedures[NFSPROC_READ],
.rpc_argp = &data->args,
@@ -583,34 +635,18 @@ nfs_proc_read_setup(struct nfs_read_data *data)
.rpc_cred = data->cred,
};
- /* N.B. Do we need to test? Never called for swapfile inode */
- flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
-
- /* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs_read_ops, data);
- rpc_call_setup(task, &msg, 0);
+ rpc_call_setup(&data->task, &msg, 0);
}
-static void nfs_write_done(struct rpc_task *task, void *calldata)
+static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data)
{
- struct nfs_write_data *data = calldata;
-
if (task->tk_status >= 0)
nfs_post_op_update_inode(data->inode, data->res.fattr);
- nfs_writeback_done(task, calldata);
+ return 0;
}
-static const struct rpc_call_ops nfs_write_ops = {
- .rpc_call_done = nfs_write_done,
- .rpc_release = nfs_writedata_release,
-};
-
-static void
-nfs_proc_write_setup(struct nfs_write_data *data, int how)
+static void nfs_proc_write_setup(struct nfs_write_data *data, int how)
{
- struct rpc_task *task = &data->task;
- struct inode *inode = data->inode;
- int flags;
struct rpc_message msg = {
.rpc_proc = &nfs_procedures[NFSPROC_WRITE],
.rpc_argp = &data->args,
@@ -621,12 +657,8 @@ nfs_proc_write_setup(struct nfs_write_data *data, int how)
/* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */
data->args.stable = NFS_FILE_SYNC;
- /* Set the initial flags for the task. */
- flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
-
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs_write_ops, data);
- rpc_call_setup(task, &msg, 0);
+ rpc_call_setup(&data->task, &msg, 0);
}
static void
@@ -672,7 +704,9 @@ struct nfs_rpc_ops nfs_v2_clientops = {
.pathconf = nfs_proc_pathconf,
.decode_dirent = nfs_decode_dirent,
.read_setup = nfs_proc_read_setup,
+ .read_done = nfs_read_done,
.write_setup = nfs_proc_write_setup,
+ .write_done = nfs_write_done,
.commit_setup = nfs_proc_commit_setup,
.file_open = nfs_open,
.file_release = nfs_release,
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 05eb43fadf8..624ca7146b6 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -31,17 +31,49 @@
#include <asm/system.h>
+#include "iostat.h"
+
#define NFSDBG_FACILITY NFSDBG_PAGECACHE
static int nfs_pagein_one(struct list_head *, struct inode *);
-static void nfs_readpage_result_partial(struct nfs_read_data *, int);
-static void nfs_readpage_result_full(struct nfs_read_data *, int);
+static const struct rpc_call_ops nfs_read_partial_ops;
+static const struct rpc_call_ops nfs_read_full_ops;
static kmem_cache_t *nfs_rdata_cachep;
-mempool_t *nfs_rdata_mempool;
+static mempool_t *nfs_rdata_mempool;
#define MIN_POOL_READ (32)
+struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
+{
+ struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, SLAB_NOFS);
+
+ if (p) {
+ memset(p, 0, sizeof(*p));
+ INIT_LIST_HEAD(&p->pages);
+ if (pagecount < NFS_PAGEVEC_SIZE)
+ p->pagevec = &p->page_array[0];
+ else {
+ size_t size = ++pagecount * sizeof(struct page *);
+ p->pagevec = kmalloc(size, GFP_NOFS);
+ if (p->pagevec) {
+ memset(p->pagevec, 0, size);
+ } else {
+ mempool_free(p, nfs_rdata_mempool);
+ p = NULL;
+ }
+ }
+ }
+ return p;
+}
+
+void nfs_readdata_free(struct nfs_read_data *p)
+{
+ if (p && (p->pagevec != &p->page_array[0]))
+ kfree(p->pagevec);
+ mempool_free(p, nfs_rdata_mempool);
+}
+
void nfs_readdata_release(void *data)
{
nfs_readdata_free(data);
@@ -133,6 +165,8 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
}
count -= result;
rdata->args.pgbase += result;
+ nfs_add_stats(inode, NFSIOS_SERVERREADBYTES, result);
+
/* Note: result == 0 should only happen if we're caching
* a write that extends the file and punches a hole.
*/
@@ -196,9 +230,11 @@ static void nfs_readpage_release(struct nfs_page *req)
* Set up the NFS read request struct
*/
static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
+ const struct rpc_call_ops *call_ops,
unsigned int count, unsigned int offset)
{
struct inode *inode;
+ int flags;
data->req = req;
data->inode = inode = req->wb_context->dentry->d_inode;
@@ -216,6 +252,9 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
data->res.eof = 0;
nfs_fattr_init(&data->fattr);
+ /* Set up the initial task struct. */
+ flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
+ rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data);
NFS_PROTO(inode)->read_setup(data);
data->task.tk_cookie = (unsigned long)inode;
@@ -303,14 +342,15 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
list_del_init(&data->pages);
data->pagevec[0] = page;
- data->complete = nfs_readpage_result_partial;
if (nbytes > rsize) {
- nfs_read_rpcsetup(req, data, rsize, offset);
+ nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
+ rsize, offset);
offset += rsize;
nbytes -= rsize;
} else {
- nfs_read_rpcsetup(req, data, nbytes, offset);
+ nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
+ nbytes, offset);
nbytes = 0;
}
nfs_execute_read(data);
@@ -356,8 +396,7 @@ static int nfs_pagein_one(struct list_head *head, struct inode *inode)
}
req = nfs_list_entry(data->pages.next);
- data->complete = nfs_readpage_result_full;
- nfs_read_rpcsetup(req, data, count, 0);
+ nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0);
nfs_execute_read(data);
return 0;
@@ -391,12 +430,15 @@ nfs_pagein_list(struct list_head *head, int rpages)
/*
* Handle a read reply that fills part of a page.
*/
-static void nfs_readpage_result_partial(struct nfs_read_data *data, int status)
+static void nfs_readpage_result_partial(struct rpc_task *task, void *calldata)
{
+ struct nfs_read_data *data = calldata;
struct nfs_page *req = data->req;
struct page *page = req->wb_page;
- if (status >= 0) {
+ if (nfs_readpage_result(task, data) != 0)
+ return;
+ if (task->tk_status >= 0) {
unsigned int request = data->args.count;
unsigned int result = data->res.count;
@@ -415,20 +457,28 @@ static void nfs_readpage_result_partial(struct nfs_read_data *data, int status)
}
}
+static const struct rpc_call_ops nfs_read_partial_ops = {
+ .rpc_call_done = nfs_readpage_result_partial,
+ .rpc_release = nfs_readdata_release,
+};
+
/*
* This is the callback from RPC telling us whether a reply was
* received or some error occurred (timeout or socket shutdown).
*/
-static void nfs_readpage_result_full(struct nfs_read_data *data, int status)
+static void nfs_readpage_result_full(struct rpc_task *task, void *calldata)
{
+ struct nfs_read_data *data = calldata;
unsigned int count = data->res.count;
+ if (nfs_readpage_result(task, data) != 0)
+ return;
while (!list_empty(&data->pages)) {
struct nfs_page *req = nfs_list_entry(data->pages.next);
struct page *page = req->wb_page;
nfs_list_remove_request(req);
- if (status >= 0) {
+ if (task->tk_status >= 0) {
if (count < PAGE_CACHE_SIZE) {
if (count < req->wb_bytes)
memclear_highpage_flush(page,
@@ -444,22 +494,33 @@ static void nfs_readpage_result_full(struct nfs_read_data *data, int status)
}
}
+static const struct rpc_call_ops nfs_read_full_ops = {
+ .rpc_call_done = nfs_readpage_result_full,
+ .rpc_release = nfs_readdata_release,
+};
+
/*
* This is the callback from RPC telling us whether a reply was
* received or some error occurred (timeout or socket shutdown).
*/
-void nfs_readpage_result(struct rpc_task *task, void *calldata)
+int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data)
{
- struct nfs_read_data *data = calldata;
struct nfs_readargs *argp = &data->args;
struct nfs_readres *resp = &data->res;
- int status = task->tk_status;
+ int status;
dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
- task->tk_pid, status);
+ task->tk_pid, task->tk_status);
+
+ status = NFS_PROTO(data->inode)->read_done(task, data);
+ if (status != 0)
+ return status;
+
+ nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, resp->count);
/* Is this a short read? */
if (task->tk_status >= 0 && resp->count < argp->count && !resp->eof) {
+ nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);
/* Has the server at least made some progress? */
if (resp->count != 0) {
/* Yes, so retry the read at the end of the data */
@@ -467,14 +528,14 @@ void nfs_readpage_result(struct rpc_task *task, void *calldata)
argp->pgbase += resp->count;
argp->count -= resp->count;
rpc_restart_call(task);
- return;
+ return -EAGAIN;
}
task->tk_status = -EIO;
}
spin_lock(&data->inode->i_lock);
NFS_I(data->inode)->cache_validity |= NFS_INO_INVALID_ATIME;
spin_unlock(&data->inode->i_lock);
- data->complete(data, status);
+ return 0;
}
/*
@@ -491,6 +552,9 @@ int nfs_readpage(struct file *file, struct page *page)
dprintk("NFS: nfs_readpage (%p %ld@%lu)\n",
page, PAGE_CACHE_SIZE, page->index);
+ nfs_inc_stats(inode, NFSIOS_VFSREADPAGE);
+ nfs_add_stats(inode, NFSIOS_READPAGES, 1);
+
/*
* Try to flush any pending writes to the file..
*
@@ -570,6 +634,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
inode->i_sb->s_id,
(long long)NFS_FILEID(inode),
nr_pages);
+ nfs_inc_stats(inode, NFSIOS_VFSREADPAGES);
if (filp == NULL) {
desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ);
@@ -582,6 +647,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
if (!list_empty(&head)) {
int err = nfs_pagein_list(&head, server->rpages);
if (!ret)
+ nfs_add_stats(inode, NFSIOS_READPAGES, err);
ret = err;
}
put_nfs_open_context(desc.ctx);
@@ -597,10 +663,8 @@ int nfs_init_readpagecache(void)
if (nfs_rdata_cachep == NULL)
return -ENOMEM;
- nfs_rdata_mempool = mempool_create(MIN_POOL_READ,
- mempool_alloc_slab,
- mempool_free_slab,
- nfs_rdata_cachep);
+ nfs_rdata_mempool = mempool_create_slab_pool(MIN_POOL_READ,
+ nfs_rdata_cachep);
if (nfs_rdata_mempool == NULL)
return -ENOMEM;
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index a65c7b53d55..0e28189c215 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -163,10 +163,9 @@ nfs_async_unlink(struct dentry *dentry)
struct rpc_clnt *clnt = NFS_CLIENT(dir->d_inode);
int status = -ENOMEM;
- data = kmalloc(sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
goto out;
- memset(data, 0, sizeof(*data));
data->cred = rpcauth_lookupcred(clnt->cl_auth, 0);
if (IS_ERR(data->cred)) {
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 9449b683550..4cfada2cc09 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -63,6 +63,7 @@
#include <linux/smp_lock.h>
#include "delegation.h"
+#include "iostat.h"
#define NFSDBG_FACILITY NFSDBG_PAGECACHE
@@ -76,20 +77,21 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context*,
struct inode *,
struct page *,
unsigned int, unsigned int);
-static void nfs_writeback_done_partial(struct nfs_write_data *, int);
-static void nfs_writeback_done_full(struct nfs_write_data *, int);
static int nfs_wait_on_write_congestion(struct address_space *, int);
static int nfs_wait_on_requests(struct inode *, unsigned long, unsigned int);
static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
unsigned int npages, int how);
+static const struct rpc_call_ops nfs_write_partial_ops;
+static const struct rpc_call_ops nfs_write_full_ops;
+static const struct rpc_call_ops nfs_commit_ops;
static kmem_cache_t *nfs_wdata_cachep;
-mempool_t *nfs_wdata_mempool;
+static mempool_t *nfs_wdata_mempool;
static mempool_t *nfs_commit_mempool;
static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion);
-static inline struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount)
+struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount)
{
struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS);
@@ -100,11 +102,39 @@ static inline struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount)
p->pagevec = &p->page_array[0];
else {
size_t size = ++pagecount * sizeof(struct page *);
+ p->pagevec = kzalloc(size, GFP_NOFS);
+ if (!p->pagevec) {
+ mempool_free(p, nfs_commit_mempool);
+ p = NULL;
+ }
+ }
+ }
+ return p;
+}
+
+void nfs_commit_free(struct nfs_write_data *p)
+{
+ if (p && (p->pagevec != &p->page_array[0]))
+ kfree(p->pagevec);
+ mempool_free(p, nfs_commit_mempool);
+}
+
+struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
+{
+ struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, SLAB_NOFS);
+
+ if (p) {
+ memset(p, 0, sizeof(*p));
+ INIT_LIST_HEAD(&p->pages);
+ if (pagecount < NFS_PAGEVEC_SIZE)
+ p->pagevec = &p->page_array[0];
+ else {
+ size_t size = ++pagecount * sizeof(struct page *);
p->pagevec = kmalloc(size, GFP_NOFS);
if (p->pagevec) {
memset(p->pagevec, 0, size);
} else {
- mempool_free(p, nfs_commit_mempool);
+ mempool_free(p, nfs_wdata_mempool);
p = NULL;
}
}
@@ -112,11 +142,11 @@ static inline struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount)
return p;
}
-static inline void nfs_commit_free(struct nfs_write_data *p)
+void nfs_writedata_free(struct nfs_write_data *p)
{
if (p && (p->pagevec != &p->page_array[0]))
kfree(p->pagevec);
- mempool_free(p, nfs_commit_mempool);
+ mempool_free(p, nfs_wdata_mempool);
}
void nfs_writedata_release(void *wdata)
@@ -136,6 +166,7 @@ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int c
end = ((loff_t)page->index << PAGE_CACHE_SHIFT) + ((loff_t)offset+count);
if (i_size >= end)
return;
+ nfs_inc_stats(inode, NFSIOS_EXTENDWRITE);
i_size_write(inode, end);
}
@@ -225,6 +256,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode,
wdata->args.pgbase += result;
written += result;
count -= result;
+ nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, result);
} while (count);
/* Update file length */
nfs_grow_file(page, offset, written);
@@ -281,6 +313,9 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
int priority = wb_priority(wbc);
int err;
+ nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE);
+ nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1);
+
/*
* Note: We need to ensure that we have a reference to the inode
* if we are to do asynchronous writes. If not, waiting
@@ -345,6 +380,8 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
struct inode *inode = mapping->host;
int err;
+ nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES);
+
err = generic_writepages(mapping, wbc);
if (err)
return err;
@@ -356,6 +393,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
err = nfs_flush_inode(inode, 0, 0, wb_priority(wbc));
if (err < 0)
goto out;
+ nfs_add_stats(inode, NFSIOS_WRITEPAGES, err);
wbc->nr_to_write -= err;
if (!wbc->nonblocking && wbc->sync_mode == WB_SYNC_ALL) {
err = nfs_wait_on_requests(inode, 0, 0);
@@ -391,6 +429,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
if (nfs_have_delegation(inode, FMODE_WRITE))
nfsi->change_attr++;
}
+ SetPagePrivate(req->wb_page);
nfsi->npages++;
atomic_inc(&req->wb_count);
return 0;
@@ -407,6 +446,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
BUG_ON (!NFS_WBACK_BUSY(req));
spin_lock(&nfsi->req_lock);
+ ClearPagePrivate(req->wb_page);
radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
nfsi->npages--;
if (!nfsi->npages) {
@@ -499,8 +539,7 @@ nfs_mark_request_commit(struct nfs_page *req)
*
* Interruptible by signals only if mounted with intr flag.
*/
-static int
-nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int npages)
+static int nfs_wait_on_requests_locked(struct inode *inode, unsigned long idx_start, unsigned int npages)
{
struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_page *req;
@@ -513,7 +552,6 @@ nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int
else
idx_end = idx_start + npages - 1;
- spin_lock(&nfsi->req_lock);
next = idx_start;
while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) {
if (req->wb_index > idx_end)
@@ -526,15 +564,25 @@ nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int
spin_unlock(&nfsi->req_lock);
error = nfs_wait_on_request(req);
nfs_release_request(req);
+ spin_lock(&nfsi->req_lock);
if (error < 0)
return error;
- spin_lock(&nfsi->req_lock);
res++;
}
- spin_unlock(&nfsi->req_lock);
return res;
}
+static int nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int npages)
+{
+ struct nfs_inode *nfsi = NFS_I(inode);
+ int ret;
+
+ spin_lock(&nfsi->req_lock);
+ ret = nfs_wait_on_requests_locked(inode, idx_start, npages);
+ spin_unlock(&nfsi->req_lock);
+ return ret;
+}
+
/*
* nfs_scan_dirty - Scan an inode for dirty requests
* @inode: NFS inode to scan
@@ -586,6 +634,11 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_st
}
return res;
}
+#else
+static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
+{
+ return 0;
+}
#endif
static int nfs_wait_on_write_congestion(struct address_space *mapping, int intr)
@@ -598,6 +651,9 @@ static int nfs_wait_on_write_congestion(struct address_space *mapping, int intr)
if (!bdi_write_congested(bdi))
return 0;
+
+ nfs_inc_stats(mapping->host, NFSIOS_CONGESTIONWAIT);
+
if (intr) {
struct rpc_clnt *clnt = NFS_CLIENT(mapping->host);
sigset_t oldset;
@@ -653,8 +709,11 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
spin_unlock(&nfsi->req_lock);
error = nfs_wait_on_request(req);
nfs_release_request(req);
- if (error < 0)
+ if (error < 0) {
+ if (new)
+ nfs_release_request(new);
return ERR_PTR(error);
+ }
continue;
}
spin_unlock(&nfsi->req_lock);
@@ -748,6 +807,8 @@ int nfs_updatepage(struct file *file, struct page *page,
struct nfs_page *req;
int status = 0;
+ nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE);
+
dprintk("NFS: nfs_updatepage(%s/%s %d@%Ld)\n",
file->f_dentry->d_parent->d_name.name,
file->f_dentry->d_name.name, count,
@@ -857,10 +918,12 @@ static inline int flush_task_priority(int how)
*/
static void nfs_write_rpcsetup(struct nfs_page *req,
struct nfs_write_data *data,
+ const struct rpc_call_ops *call_ops,
unsigned int count, unsigned int offset,
int how)
{
struct inode *inode;
+ int flags;
/* Set up the RPC argument and reply structs
* NB: take care not to mess about with data->commit et al. */
@@ -881,6 +944,9 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
data->res.verf = &data->verf;
nfs_fattr_init(&data->fattr);
+ /* Set up the initial task struct. */
+ flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
+ rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data);
NFS_PROTO(inode)->write_setup(data, how);
data->task.tk_priority = flush_task_priority(how);
@@ -910,7 +976,7 @@ static void nfs_execute_write(struct nfs_write_data *data)
* Generate multiple small requests to write out a single
* contiguous dirty area on one page.
*/
-static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how)
+static int nfs_flush_multi(struct inode *inode, struct list_head *head, int how)
{
struct nfs_page *req = nfs_list_entry(head->next);
struct page *page = req->wb_page;
@@ -944,14 +1010,15 @@ static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how)
list_del_init(&data->pages);
data->pagevec[0] = page;
- data->complete = nfs_writeback_done_partial;
if (nbytes > wsize) {
- nfs_write_rpcsetup(req, data, wsize, offset, how);
+ nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
+ wsize, offset, how);
offset += wsize;
nbytes -= wsize;
} else {
- nfs_write_rpcsetup(req, data, nbytes, offset, how);
+ nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
+ nbytes, offset, how);
nbytes = 0;
}
nfs_execute_write(data);
@@ -978,16 +1045,13 @@ out_bad:
* This is the case if nfs_updatepage detects a conflicting request
* that has been written but not committed.
*/
-static int nfs_flush_one(struct list_head *head, struct inode *inode, int how)
+static int nfs_flush_one(struct inode *inode, struct list_head *head, int how)
{
struct nfs_page *req;
struct page **pages;
struct nfs_write_data *data;
unsigned int count;
- if (NFS_SERVER(inode)->wsize < PAGE_CACHE_SIZE)
- return nfs_flush_multi(head, inode, how);
-
data = nfs_writedata_alloc(NFS_SERVER(inode)->wpages);
if (!data)
goto out_bad;
@@ -1005,9 +1069,8 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how)
}
req = nfs_list_entry(data->pages.next);
- data->complete = nfs_writeback_done_full;
/* Set up the argument struct */
- nfs_write_rpcsetup(req, data, count, 0, how);
+ nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how);
nfs_execute_write(data);
return 0;
@@ -1021,24 +1084,32 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how)
return -ENOMEM;
}
-static int
-nfs_flush_list(struct list_head *head, int wpages, int how)
+static int nfs_flush_list(struct inode *inode, struct list_head *head, int npages, int how)
{
LIST_HEAD(one_request);
- struct nfs_page *req;
- int error = 0;
- unsigned int pages = 0;
+ int (*flush_one)(struct inode *, struct list_head *, int);
+ struct nfs_page *req;
+ int wpages = NFS_SERVER(inode)->wpages;
+ int wsize = NFS_SERVER(inode)->wsize;
+ int error;
- while (!list_empty(head)) {
- pages += nfs_coalesce_requests(head, &one_request, wpages);
+ flush_one = nfs_flush_one;
+ if (wsize < PAGE_CACHE_SIZE)
+ flush_one = nfs_flush_multi;
+ /* For single writes, FLUSH_STABLE is more efficient */
+ if (npages <= wpages && npages == NFS_I(inode)->npages
+ && nfs_list_entry(head->next)->wb_bytes <= wsize)
+ how |= FLUSH_STABLE;
+
+ do {
+ nfs_coalesce_requests(head, &one_request, wpages);
req = nfs_list_entry(one_request.next);
- error = nfs_flush_one(&one_request, req->wb_context->dentry->d_inode, how);
+ error = flush_one(inode, &one_request, how);
if (error < 0)
- break;
- }
- if (error >= 0)
- return pages;
-
+ goto out_err;
+ } while (!list_empty(head));
+ return 0;
+out_err:
while (!list_empty(head)) {
req = nfs_list_entry(head->next);
nfs_list_remove_request(req);
@@ -1051,8 +1122,9 @@ nfs_flush_list(struct list_head *head, int wpages, int how)
/*
* Handle a write reply that flushed part of a page.
*/
-static void nfs_writeback_done_partial(struct nfs_write_data *data, int status)
+static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
{
+ struct nfs_write_data *data = calldata;
struct nfs_page *req = data->req;
struct page *page = req->wb_page;
@@ -1062,11 +1134,14 @@ static void nfs_writeback_done_partial(struct nfs_write_data *data, int status)
req->wb_bytes,
(long long)req_offset(req));
- if (status < 0) {
+ if (nfs_writeback_done(task, data) != 0)
+ return;
+
+ if (task->tk_status < 0) {
ClearPageUptodate(page);
SetPageError(page);
- req->wb_context->error = status;
- dprintk(", error = %d\n", status);
+ req->wb_context->error = task->tk_status;
+ dprintk(", error = %d\n", task->tk_status);
} else {
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
if (data->verf.committed < NFS_FILE_SYNC) {
@@ -1087,6 +1162,11 @@ static void nfs_writeback_done_partial(struct nfs_write_data *data, int status)
nfs_writepage_release(req);
}
+static const struct rpc_call_ops nfs_write_partial_ops = {
+ .rpc_call_done = nfs_writeback_done_partial,
+ .rpc_release = nfs_writedata_release,
+};
+
/*
* Handle a write reply that flushes a whole page.
*
@@ -1094,11 +1174,15 @@ static void nfs_writeback_done_partial(struct nfs_write_data *data, int status)
* writebacks since the page->count is kept > 1 for as long
* as the page has a write request pending.
*/
-static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
+static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
{
+ struct nfs_write_data *data = calldata;
struct nfs_page *req;
struct page *page;
+ if (nfs_writeback_done(task, data) != 0)
+ return;
+
/* Update attributes as result of writeback. */
while (!list_empty(&data->pages)) {
req = nfs_list_entry(data->pages.next);
@@ -1111,13 +1195,13 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
req->wb_bytes,
(long long)req_offset(req));
- if (status < 0) {
+ if (task->tk_status < 0) {
ClearPageUptodate(page);
SetPageError(page);
- req->wb_context->error = status;
+ req->wb_context->error = task->tk_status;
end_page_writeback(page);
nfs_inode_remove_request(req);
- dprintk(", error = %d\n", status);
+ dprintk(", error = %d\n", task->tk_status);
goto next;
}
end_page_writeback(page);
@@ -1139,18 +1223,30 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
}
}
+static const struct rpc_call_ops nfs_write_full_ops = {
+ .rpc_call_done = nfs_writeback_done_full,
+ .rpc_release = nfs_writedata_release,
+};
+
+
/*
* This function is called when the WRITE call is complete.
*/
-void nfs_writeback_done(struct rpc_task *task, void *calldata)
+int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
{
- struct nfs_write_data *data = calldata;
struct nfs_writeargs *argp = &data->args;
struct nfs_writeres *resp = &data->res;
+ int status;
dprintk("NFS: %4d nfs_writeback_done (status %d)\n",
task->tk_pid, task->tk_status);
+ /* Call the NFS version-specific code */
+ status = NFS_PROTO(data->inode)->write_done(task, data);
+ if (status != 0)
+ return status;
+ nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count);
+
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
if (resp->verf->committed < argp->stable && task->tk_status >= 0) {
/* We tried a write call, but the server did not
@@ -1176,6 +1272,8 @@ void nfs_writeback_done(struct rpc_task *task, void *calldata)
if (task->tk_status >= 0 && resp->count < argp->count) {
static unsigned long complain;
+ nfs_inc_stats(data->inode, NFSIOS_SHORTWRITE);
+
/* Has the server at least made some progress? */
if (resp->count != 0) {
/* Was this an NFSv2 write or an NFSv3 stable write? */
@@ -1191,7 +1289,7 @@ void nfs_writeback_done(struct rpc_task *task, void *calldata)
argp->stable = NFS_FILE_SYNC;
}
rpc_restart_call(task);
- return;
+ return -EAGAIN;
}
if (time_before(complain, jiffies)) {
printk(KERN_WARNING
@@ -1202,11 +1300,7 @@ void nfs_writeback_done(struct rpc_task *task, void *calldata)
/* Can't do anything about it except throw an error. */
task->tk_status = -EIO;
}
-
- /*
- * Process the nfs_page list
- */
- data->complete(data, task->tk_status);
+ return 0;
}
@@ -1220,10 +1314,12 @@ void nfs_commit_release(void *wdata)
* Set up the argument/result storage required for the RPC call.
*/
static void nfs_commit_rpcsetup(struct list_head *head,
- struct nfs_write_data *data, int how)
+ struct nfs_write_data *data,
+ int how)
{
struct nfs_page *first;
struct inode *inode;
+ int flags;
/* Set up the RPC argument and reply structs
* NB: take care not to mess about with data->commit et al. */
@@ -1243,7 +1339,10 @@ static void nfs_commit_rpcsetup(struct list_head *head,
data->res.fattr = &data->fattr;
data->res.verf = &data->verf;
nfs_fattr_init(&data->fattr);
-
+
+ /* Set up the initial task struct. */
+ flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
+ rpc_init_task(&data->task, NFS_CLIENT(inode), flags, &nfs_commit_ops, data);
NFS_PROTO(inode)->commit_setup(data, how);
data->task.tk_priority = flush_task_priority(how);
@@ -1284,7 +1383,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
/*
* COMMIT call returned
*/
-void nfs_commit_done(struct rpc_task *task, void *calldata)
+static void nfs_commit_done(struct rpc_task *task, void *calldata)
{
struct nfs_write_data *data = calldata;
struct nfs_page *req;
@@ -1293,6 +1392,10 @@ void nfs_commit_done(struct rpc_task *task, void *calldata)
dprintk("NFS: %4d nfs_commit_done (status %d)\n",
task->tk_pid, task->tk_status);
+ /* Call the NFS version-specific code */
+ if (NFS_PROTO(data->inode)->commit_done(task, data) != 0)
+ return;
+
while (!list_empty(&data->pages)) {
req = nfs_list_entry(data->pages.next);
nfs_list_remove_request(req);
@@ -1326,6 +1429,16 @@ void nfs_commit_done(struct rpc_task *task, void *calldata)
}
sub_page_state(nr_unstable,res);
}
+
+static const struct rpc_call_ops nfs_commit_ops = {
+ .rpc_call_done = nfs_commit_done,
+ .rpc_release = nfs_commit_release,
+};
+#else
+static inline int nfs_commit_list(struct inode *inode, struct list_head *head, int how)
+{
+ return 0;
+}
#endif
static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
@@ -1333,24 +1446,16 @@ static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
{
struct nfs_inode *nfsi = NFS_I(inode);
LIST_HEAD(head);
- int res,
- error = 0;
+ int res;
spin_lock(&nfsi->req_lock);
res = nfs_scan_dirty(inode, &head, idx_start, npages);
spin_unlock(&nfsi->req_lock);
if (res) {
- struct nfs_server *server = NFS_SERVER(inode);
-
- /* For single writes, FLUSH_STABLE is more efficient */
- if (res == nfsi->npages && nfsi->npages <= server->wpages) {
- if (res > 1 || nfs_list_entry(head.next)->wb_bytes <= server->wsize)
- how |= FLUSH_STABLE;
- }
- error = nfs_flush_list(&head, server->wpages, how);
+ int error = nfs_flush_list(inode, &head, res, how);
+ if (error < 0)
+ return error;
}
- if (error < 0)
- return error;
return res;
}
@@ -1359,14 +1464,13 @@ int nfs_commit_inode(struct inode *inode, int how)
{
struct nfs_inode *nfsi = NFS_I(inode);
LIST_HEAD(head);
- int res,
- error = 0;
+ int res;
spin_lock(&nfsi->req_lock);
res = nfs_scan_commit(inode, &head, 0, 0);
spin_unlock(&nfsi->req_lock);
if (res) {
- error = nfs_commit_list(inode, &head, how);
+ int error = nfs_commit_list(inode, &head, how);
if (error < 0)
return error;
}
@@ -1374,28 +1478,38 @@ int nfs_commit_inode(struct inode *inode, int how)
}
#endif
-int nfs_sync_inode(struct inode *inode, unsigned long idx_start,
- unsigned int npages, int how)
+int nfs_sync_inode_wait(struct inode *inode, unsigned long idx_start,
+ unsigned int npages, int how)
{
+ struct nfs_inode *nfsi = NFS_I(inode);
+ LIST_HEAD(head);
int nocommit = how & FLUSH_NOCOMMIT;
- int wait = how & FLUSH_WAIT;
- int error;
-
- how &= ~(FLUSH_WAIT|FLUSH_NOCOMMIT);
+ int pages, ret;
+ how &= ~FLUSH_NOCOMMIT;
+ spin_lock(&nfsi->req_lock);
do {
- if (wait) {
- error = nfs_wait_on_requests(inode, idx_start, npages);
- if (error != 0)
- continue;
- }
- error = nfs_flush_inode(inode, idx_start, npages, how);
- if (error != 0)
+ ret = nfs_wait_on_requests_locked(inode, idx_start, npages);
+ if (ret != 0)
continue;
- if (!nocommit)
- error = nfs_commit_inode(inode, how);
- } while (error > 0);
- return error;
+ pages = nfs_scan_dirty(inode, &head, idx_start, npages);
+ if (pages != 0) {
+ spin_unlock(&nfsi->req_lock);
+ ret = nfs_flush_list(inode, &head, pages, how);
+ spin_lock(&nfsi->req_lock);
+ continue;
+ }
+ if (nocommit)
+ break;
+ pages = nfs_scan_commit(inode, &head, 0, 0);
+ if (pages == 0)
+ break;
+ spin_unlock(&nfsi->req_lock);
+ ret = nfs_commit_list(inode, &head, how);
+ spin_lock(&nfsi->req_lock);
+ } while (ret >= 0);
+ spin_unlock(&nfsi->req_lock);
+ return ret;
}
int nfs_init_writepagecache(void)
@@ -1407,17 +1521,13 @@ int nfs_init_writepagecache(void)
if (nfs_wdata_cachep == NULL)
return -ENOMEM;
- nfs_wdata_mempool = mempool_create(MIN_POOL_WRITE,
- mempool_alloc_slab,
- mempool_free_slab,
- nfs_wdata_cachep);
+ nfs_wdata_mempool = mempool_create_slab_pool(MIN_POOL_WRITE,
+ nfs_wdata_cachep);
if (nfs_wdata_mempool == NULL)
return -ENOMEM;
- nfs_commit_mempool = mempool_create(MIN_POOL_COMMIT,
- mempool_alloc_slab,
- mempool_free_slab,
- nfs_wdata_cachep);
+ nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT,
+ nfs_wdata_cachep);
if (nfs_commit_mempool == NULL)
return -ENOMEM;
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 417ec02df44..c340be0a3f5 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -57,27 +57,17 @@ static int exp_verify_string(char *cp, int max);
#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
static struct cache_head *expkey_table[EXPKEY_HASHMAX];
-static inline int svc_expkey_hash(struct svc_expkey *item)
+static void expkey_put(struct kref *ref)
{
- int hash = item->ek_fsidtype;
- char * cp = (char*)item->ek_fsid;
- int len = key_len(item->ek_fsidtype);
+ struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
- hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
- hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
- return hash & EXPKEY_HASHMASK;
-}
-
-void expkey_put(struct cache_head *item, struct cache_detail *cd)
-{
- if (cache_put(item, cd)) {
- struct svc_expkey *key = container_of(item, struct svc_expkey, h);
- if (test_bit(CACHE_VALID, &item->flags) &&
- !test_bit(CACHE_NEGATIVE, &item->flags))
- exp_put(key->ek_export);
- auth_domain_put(key->ek_client);
- kfree(key);
+ if (test_bit(CACHE_VALID, &key->h.flags) &&
+ !test_bit(CACHE_NEGATIVE, &key->h.flags)) {
+ dput(key->ek_dentry);
+ mntput(key->ek_mnt);
}
+ auth_domain_put(key->ek_client);
+ kfree(key);
}
static void expkey_request(struct cache_detail *cd,
@@ -95,7 +85,10 @@ static void expkey_request(struct cache_detail *cd,
(*bpp)[-1] = '\n';
}
-static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *, int);
+static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old);
+static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *);
+static struct cache_detail svc_expkey_cache;
+
static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
{
/* client fsidtype fsid [path] */
@@ -106,6 +99,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
int fsidtype;
char *ep;
struct svc_expkey key;
+ struct svc_expkey *ek;
if (mesg[mlen-1] != '\n')
return -EINVAL;
@@ -150,40 +144,38 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
key.ek_fsidtype = fsidtype;
memcpy(key.ek_fsid, buf, len);
+ ek = svc_expkey_lookup(&key);
+ err = -ENOMEM;
+ if (!ek)
+ goto out;
+
/* now we want a pathname, or empty meaning NEGATIVE */
+ err = -EINVAL;
if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0)
goto out;
dprintk("Path seems to be <%s>\n", buf);
err = 0;
if (len == 0) {
- struct svc_expkey *ek;
set_bit(CACHE_NEGATIVE, &key.h.flags);
- ek = svc_expkey_lookup(&key, 1);
+ ek = svc_expkey_update(&key, ek);
if (ek)
- expkey_put(&ek->h, &svc_expkey_cache);
+ cache_put(&ek->h, &svc_expkey_cache);
+ else err = -ENOMEM;
} else {
struct nameidata nd;
- struct svc_expkey *ek;
- struct svc_export *exp;
err = path_lookup(buf, 0, &nd);
if (err)
goto out;
dprintk("Found the path %s\n", buf);
- exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
-
- err = -ENOENT;
- if (!exp)
- goto out_nd;
- key.ek_export = exp;
- dprintk("And found export\n");
+ key.ek_mnt = nd.mnt;
+ key.ek_dentry = nd.dentry;
- ek = svc_expkey_lookup(&key, 1);
+ ek = svc_expkey_update(&key, ek);
if (ek)
- expkey_put(&ek->h, &svc_expkey_cache);
- exp_put(exp);
- err = 0;
- out_nd:
+ cache_put(&ek->h, &svc_expkey_cache);
+ else
+ err = -ENOMEM;
path_release(&nd);
}
cache_flush();
@@ -214,35 +206,31 @@ static int expkey_show(struct seq_file *m,
if (test_bit(CACHE_VALID, &h->flags) &&
!test_bit(CACHE_NEGATIVE, &h->flags)) {
seq_printf(m, " ");
- seq_path(m, ek->ek_export->ex_mnt, ek->ek_export->ex_dentry, "\\ \t\n");
+ seq_path(m, ek->ek_mnt, ek->ek_dentry, "\\ \t\n");
}
seq_printf(m, "\n");
return 0;
}
-
-struct cache_detail svc_expkey_cache = {
- .owner = THIS_MODULE,
- .hash_size = EXPKEY_HASHMAX,
- .hash_table = expkey_table,
- .name = "nfsd.fh",
- .cache_put = expkey_put,
- .cache_request = expkey_request,
- .cache_parse = expkey_parse,
- .cache_show = expkey_show,
-};
-static inline int svc_expkey_match (struct svc_expkey *a, struct svc_expkey *b)
+static inline int expkey_match (struct cache_head *a, struct cache_head *b)
{
- if (a->ek_fsidtype != b->ek_fsidtype ||
- a->ek_client != b->ek_client ||
- memcmp(a->ek_fsid, b->ek_fsid, key_len(a->ek_fsidtype)) != 0)
+ struct svc_expkey *orig = container_of(a, struct svc_expkey, h);
+ struct svc_expkey *new = container_of(b, struct svc_expkey, h);
+
+ if (orig->ek_fsidtype != new->ek_fsidtype ||
+ orig->ek_client != new->ek_client ||
+ memcmp(orig->ek_fsid, new->ek_fsid, key_len(orig->ek_fsidtype)) != 0)
return 0;
return 1;
}
-static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *item)
+static inline void expkey_init(struct cache_head *cnew,
+ struct cache_head *citem)
{
- cache_get(&item->ek_client->h);
+ struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
+ struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
+
+ kref_get(&item->ek_client->ref);
new->ek_client = item->ek_client;
new->ek_fsidtype = item->ek_fsidtype;
new->ek_fsid[0] = item->ek_fsid[0];
@@ -250,39 +238,94 @@ static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *it
new->ek_fsid[2] = item->ek_fsid[2];
}
-static inline void svc_expkey_update(struct svc_expkey *new, struct svc_expkey *item)
+static inline void expkey_update(struct cache_head *cnew,
+ struct cache_head *citem)
+{
+ struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
+ struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
+
+ new->ek_mnt = mntget(item->ek_mnt);
+ new->ek_dentry = dget(item->ek_dentry);
+}
+
+static struct cache_head *expkey_alloc(void)
{
- cache_get(&item->ek_export->h);
- new->ek_export = item->ek_export;
+ struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL);
+ if (i)
+ return &i->h;
+ else
+ return NULL;
}
-static DefineSimpleCacheLookup(svc_expkey,0) /* no inplace updates */
+static struct cache_detail svc_expkey_cache = {
+ .owner = THIS_MODULE,
+ .hash_size = EXPKEY_HASHMAX,
+ .hash_table = expkey_table,
+ .name = "nfsd.fh",
+ .cache_put = expkey_put,
+ .cache_request = expkey_request,
+ .cache_parse = expkey_parse,
+ .cache_show = expkey_show,
+ .match = expkey_match,
+ .init = expkey_init,
+ .update = expkey_update,
+ .alloc = expkey_alloc,
+};
-#define EXPORT_HASHBITS 8
-#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
-#define EXPORT_HASHMASK (EXPORT_HASHMAX -1)
+static struct svc_expkey *
+svc_expkey_lookup(struct svc_expkey *item)
+{
+ struct cache_head *ch;
+ int hash = item->ek_fsidtype;
+ char * cp = (char*)item->ek_fsid;
+ int len = key_len(item->ek_fsidtype);
-static struct cache_head *export_table[EXPORT_HASHMAX];
+ hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
+ hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
+ hash &= EXPKEY_HASHMASK;
-static inline int svc_export_hash(struct svc_export *item)
+ ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h,
+ hash);
+ if (ch)
+ return container_of(ch, struct svc_expkey, h);
+ else
+ return NULL;
+}
+
+static struct svc_expkey *
+svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old)
{
- int rv;
+ struct cache_head *ch;
+ int hash = new->ek_fsidtype;
+ char * cp = (char*)new->ek_fsid;
+ int len = key_len(new->ek_fsidtype);
- rv = hash_ptr(item->ex_client, EXPORT_HASHBITS);
- rv ^= hash_ptr(item->ex_dentry, EXPORT_HASHBITS);
- rv ^= hash_ptr(item->ex_mnt, EXPORT_HASHBITS);
- return rv;
+ hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
+ hash ^= hash_ptr(new->ek_client, EXPKEY_HASHBITS);
+ hash &= EXPKEY_HASHMASK;
+
+ ch = sunrpc_cache_update(&svc_expkey_cache, &new->h,
+ &old->h, hash);
+ if (ch)
+ return container_of(ch, struct svc_expkey, h);
+ else
+ return NULL;
}
-void svc_export_put(struct cache_head *item, struct cache_detail *cd)
+
+#define EXPORT_HASHBITS 8
+#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
+#define EXPORT_HASHMASK (EXPORT_HASHMAX -1)
+
+static struct cache_head *export_table[EXPORT_HASHMAX];
+
+static void svc_export_put(struct kref *ref)
{
- if (cache_put(item, cd)) {
- struct svc_export *exp = container_of(item, struct svc_export, h);
- dput(exp->ex_dentry);
- mntput(exp->ex_mnt);
- auth_domain_put(exp->ex_client);
- kfree(exp);
- }
+ struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
+ dput(exp->ex_dentry);
+ mntput(exp->ex_mnt);
+ auth_domain_put(exp->ex_client);
+ kfree(exp);
}
static void svc_export_request(struct cache_detail *cd,
@@ -304,7 +347,9 @@ static void svc_export_request(struct cache_detail *cd,
(*bpp)[-1] = '\n';
}
-static struct svc_export *svc_export_lookup(struct svc_export *, int);
+static struct svc_export *svc_export_update(struct svc_export *new,
+ struct svc_export *old);
+static struct svc_export *svc_export_lookup(struct svc_export *);
static int check_export(struct inode *inode, int flags)
{
@@ -417,11 +462,16 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
if (err) goto out;
}
- expp = svc_export_lookup(&exp, 1);
+ expp = svc_export_lookup(&exp);
if (expp)
- exp_put(expp);
- err = 0;
+ expp = svc_export_update(&exp, expp);
+ else
+ err = -ENOMEM;
cache_flush();
+ if (expp == NULL)
+ err = -ENOMEM;
+ else
+ exp_put(expp);
out:
if (nd.dentry)
path_release(&nd);
@@ -455,6 +505,46 @@ static int svc_export_show(struct seq_file *m,
seq_puts(m, ")\n");
return 0;
}
+static int svc_export_match(struct cache_head *a, struct cache_head *b)
+{
+ struct svc_export *orig = container_of(a, struct svc_export, h);
+ struct svc_export *new = container_of(b, struct svc_export, h);
+ return orig->ex_client == new->ex_client &&
+ orig->ex_dentry == new->ex_dentry &&
+ orig->ex_mnt == new->ex_mnt;
+}
+
+static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
+{
+ struct svc_export *new = container_of(cnew, struct svc_export, h);
+ struct svc_export *item = container_of(citem, struct svc_export, h);
+
+ kref_get(&item->ex_client->ref);
+ new->ex_client = item->ex_client;
+ new->ex_dentry = dget(item->ex_dentry);
+ new->ex_mnt = mntget(item->ex_mnt);
+}
+
+static void export_update(struct cache_head *cnew, struct cache_head *citem)
+{
+ struct svc_export *new = container_of(cnew, struct svc_export, h);
+ struct svc_export *item = container_of(citem, struct svc_export, h);
+
+ new->ex_flags = item->ex_flags;
+ new->ex_anon_uid = item->ex_anon_uid;
+ new->ex_anon_gid = item->ex_anon_gid;
+ new->ex_fsid = item->ex_fsid;
+}
+
+static struct cache_head *svc_export_alloc(void)
+{
+ struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL);
+ if (i)
+ return &i->h;
+ else
+ return NULL;
+}
+
struct cache_detail svc_export_cache = {
.owner = THIS_MODULE,
.hash_size = EXPORT_HASHMAX,
@@ -464,34 +554,49 @@ struct cache_detail svc_export_cache = {
.cache_request = svc_export_request,
.cache_parse = svc_export_parse,
.cache_show = svc_export_show,
+ .match = svc_export_match,
+ .init = svc_export_init,
+ .update = export_update,
+ .alloc = svc_export_alloc,
};
-static inline int svc_export_match(struct svc_export *a, struct svc_export *b)
+static struct svc_export *
+svc_export_lookup(struct svc_export *exp)
{
- return a->ex_client == b->ex_client &&
- a->ex_dentry == b->ex_dentry &&
- a->ex_mnt == b->ex_mnt;
-}
-static inline void svc_export_init(struct svc_export *new, struct svc_export *item)
-{
- cache_get(&item->ex_client->h);
- new->ex_client = item->ex_client;
- new->ex_dentry = dget(item->ex_dentry);
- new->ex_mnt = mntget(item->ex_mnt);
+ struct cache_head *ch;
+ int hash;
+ hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS);
+ hash ^= hash_ptr(exp->ex_dentry, EXPORT_HASHBITS);
+ hash ^= hash_ptr(exp->ex_mnt, EXPORT_HASHBITS);
+
+ ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h,
+ hash);
+ if (ch)
+ return container_of(ch, struct svc_export, h);
+ else
+ return NULL;
}
-static inline void svc_export_update(struct svc_export *new, struct svc_export *item)
+static struct svc_export *
+svc_export_update(struct svc_export *new, struct svc_export *old)
{
- new->ex_flags = item->ex_flags;
- new->ex_anon_uid = item->ex_anon_uid;
- new->ex_anon_gid = item->ex_anon_gid;
- new->ex_fsid = item->ex_fsid;
+ struct cache_head *ch;
+ int hash;
+ hash = hash_ptr(old->ex_client, EXPORT_HASHBITS);
+ hash ^= hash_ptr(old->ex_dentry, EXPORT_HASHBITS);
+ hash ^= hash_ptr(old->ex_mnt, EXPORT_HASHBITS);
+
+ ch = sunrpc_cache_update(&svc_export_cache, &new->h,
+ &old->h,
+ hash);
+ if (ch)
+ return container_of(ch, struct svc_export, h);
+ else
+ return NULL;
}
-static DefineSimpleCacheLookup(svc_export,1) /* allow inplace updates */
-
-struct svc_expkey *
+static struct svc_expkey *
exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
{
struct svc_expkey key, *ek;
@@ -504,7 +609,7 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
key.ek_fsidtype = fsid_type;
memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
- ek = svc_expkey_lookup(&key, 0);
+ ek = svc_expkey_lookup(&key);
if (ek != NULL)
if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp)))
ek = ERR_PTR(err);
@@ -519,13 +624,16 @@ static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
key.ek_client = clp;
key.ek_fsidtype = fsid_type;
memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
- key.ek_export = exp;
+ key.ek_mnt = exp->ex_mnt;
+ key.ek_dentry = exp->ex_dentry;
key.h.expiry_time = NEVER;
key.h.flags = 0;
- ek = svc_expkey_lookup(&key, 1);
+ ek = svc_expkey_lookup(&key);
+ if (ek)
+ ek = svc_expkey_update(&key,ek);
if (ek) {
- expkey_put(&ek->h, &svc_expkey_cache);
+ cache_put(&ek->h, &svc_expkey_cache);
return 0;
}
return -ENOMEM;
@@ -573,7 +681,7 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
key.ex_mnt = mnt;
key.ex_dentry = dentry;
- exp = svc_export_lookup(&key, 0);
+ exp = svc_export_lookup(&key);
if (exp != NULL)
switch (cache_check(&svc_export_cache, &exp->h, reqp)) {
case 0: break;
@@ -654,7 +762,7 @@ static void exp_fsid_unhash(struct svc_export *exp)
ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
if (ek && !IS_ERR(ek)) {
ek->h.expiry_time = get_seconds()-1;
- expkey_put(&ek->h, &svc_expkey_cache);
+ cache_put(&ek->h, &svc_expkey_cache);
}
svc_expkey_cache.nextcheck = get_seconds();
}
@@ -692,7 +800,7 @@ static void exp_unhash(struct svc_export *exp)
ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
if (ek && !IS_ERR(ek)) {
ek->h.expiry_time = get_seconds()-1;
- expkey_put(&ek->h, &svc_expkey_cache);
+ cache_put(&ek->h, &svc_expkey_cache);
}
svc_expkey_cache.nextcheck = get_seconds();
}
@@ -741,8 +849,8 @@ exp_export(struct nfsctl_export *nxp)
if ((nxp->ex_flags & NFSEXP_FSID) &&
(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
!IS_ERR(fsid_key) &&
- fsid_key->ek_export &&
- fsid_key->ek_export != exp)
+ fsid_key->ek_mnt &&
+ (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) )
goto finish;
if (exp) {
@@ -775,13 +883,13 @@ exp_export(struct nfsctl_export *nxp)
new.ex_anon_gid = nxp->ex_anon_gid;
new.ex_fsid = nxp->ex_dev;
- exp = svc_export_lookup(&new, 1);
+ exp = svc_export_lookup(&new);
+ if (exp)
+ exp = svc_export_update(&new, exp);
- if (exp == NULL)
+ if (!exp)
goto finish;
- err = 0;
-
if (exp_hash(clp, exp) ||
exp_fsid_hash(clp, exp)) {
/* failed to create at least one index */
@@ -794,7 +902,7 @@ finish:
if (exp)
exp_put(exp);
if (fsid_key && !IS_ERR(fsid_key))
- expkey_put(&fsid_key->h, &svc_expkey_cache);
+ cache_put(&fsid_key->h, &svc_expkey_cache);
if (clp)
auth_domain_put(clp);
path_release(&nd);
@@ -912,6 +1020,24 @@ out:
return err;
}
+struct svc_export *
+exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
+ struct cache_req *reqp)
+{
+ struct svc_export *exp;
+ struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
+ if (!ek || IS_ERR(ek))
+ return ERR_PTR(PTR_ERR(ek));
+
+ exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp);
+ cache_put(&ek->h, &svc_expkey_cache);
+
+ if (!exp || IS_ERR(exp))
+ return ERR_PTR(PTR_ERR(exp));
+ return exp;
+}
+
+
/*
* Called when we need the filehandle for the root of the pseudofs,
* for a given NFSv4 client. The root is defined to be the
@@ -922,6 +1048,7 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
struct cache_req *creq)
{
struct svc_expkey *fsid_key;
+ struct svc_export *exp;
int rv;
u32 fsidv[2];
@@ -933,9 +1060,15 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
if (!fsid_key || IS_ERR(fsid_key))
return nfserr_perm;
- rv = fh_compose(fhp, fsid_key->ek_export,
- fsid_key->ek_export->ex_dentry, NULL);
- expkey_put(&fsid_key->h, &svc_expkey_cache);
+ exp = exp_get_by_name(clp, fsid_key->ek_mnt, fsid_key->ek_dentry, creq);
+ if (exp == NULL)
+ rv = nfserr_perm;
+ else if (IS_ERR(exp))
+ rv = nfserrno(PTR_ERR(exp));
+ else
+ rv = fh_compose(fhp, exp,
+ fsid_key->ek_dentry, NULL);
+ cache_put(&fsid_key->h, &svc_expkey_cache);
return rv;
}
@@ -1054,7 +1187,7 @@ static int e_show(struct seq_file *m, void *p)
cache_get(&exp->h);
if (cache_check(&svc_export_cache, &exp->h, NULL))
return 0;
- if (cache_put(&exp->h, &svc_export_cache)) BUG();
+ cache_put(&exp->h, &svc_export_cache);
return svc_export_show(m, &svc_export_cache, cp);
}
@@ -1129,7 +1262,6 @@ exp_delclient(struct nfsctl_client *ncp)
*/
if (dom) {
err = auth_unix_forget_old(dom);
- dom->h.expiry_time = get_seconds();
auth_domain_put(dom);
}
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 8d3d23c8a4d..c872bd07fc1 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -326,6 +326,8 @@ out:
.p_encode = (kxdrproc_t) nfs4_xdr_##argtype, \
.p_decode = (kxdrproc_t) nfs4_xdr_##restype, \
.p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2, \
+ .p_statidx = NFSPROC4_CB_##call, \
+ .p_name = #proc, \
}
static struct rpc_procinfo nfs4_cb_procedures[] = {
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 13369650cdf..4b6aa60dfce 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -76,21 +76,18 @@ struct ent {
char authname[IDMAP_NAMESZ];
};
-#define DefineSimpleCacheLookupMap(STRUCT, FUNC) \
- DefineCacheLookup(struct STRUCT, h, FUNC##_lookup, \
- (struct STRUCT *item, int set), /*no setup */, \
- & FUNC##_cache, FUNC##_hash(item), FUNC##_match(item, tmp), \
- STRUCT##_init(new, item), STRUCT##_update(tmp, item), 0)
-
/* Common entry handling */
#define ENT_HASHBITS 8
#define ENT_HASHMAX (1 << ENT_HASHBITS)
#define ENT_HASHMASK (ENT_HASHMAX - 1)
-static inline void
-ent_init(struct ent *new, struct ent *itm)
+static void
+ent_init(struct cache_head *cnew, struct cache_head *citm)
{
+ struct ent *new = container_of(cnew, struct ent, h);
+ struct ent *itm = container_of(citm, struct ent, h);
+
new->id = itm->id;
new->type = itm->type;
@@ -98,19 +95,21 @@ ent_init(struct ent *new, struct ent *itm)
strlcpy(new->authname, itm->authname, sizeof(new->name));
}
-static inline void
-ent_update(struct ent *new, struct ent *itm)
+static void
+ent_put(struct kref *ref)
{
- ent_init(new, itm);
+ struct ent *map = container_of(ref, struct ent, h.ref);
+ kfree(map);
}
-static void
-ent_put(struct cache_head *ch, struct cache_detail *cd)
+static struct cache_head *
+ent_alloc(void)
{
- if (cache_put(ch, cd)) {
- struct ent *map = container_of(ch, struct ent, h);
- kfree(map);
- }
+ struct ent *e = kmalloc(sizeof(*e), GFP_KERNEL);
+ if (e)
+ return &e->h;
+ else
+ return NULL;
}
/*
@@ -149,9 +148,12 @@ idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
(*bpp)[-1] = '\n';
}
-static inline int
-idtoname_match(struct ent *a, struct ent *b)
+static int
+idtoname_match(struct cache_head *ca, struct cache_head *cb)
{
+ struct ent *a = container_of(ca, struct ent, h);
+ struct ent *b = container_of(cb, struct ent, h);
+
return (a->id == b->id && a->type == b->type &&
strcmp(a->authname, b->authname) == 0);
}
@@ -184,7 +186,8 @@ warn_no_idmapd(struct cache_detail *detail)
static int idtoname_parse(struct cache_detail *, char *, int);
-static struct ent *idtoname_lookup(struct ent *, int);
+static struct ent *idtoname_lookup(struct ent *);
+static struct ent *idtoname_update(struct ent *, struct ent *);
static struct cache_detail idtoname_cache = {
.owner = THIS_MODULE,
@@ -196,6 +199,10 @@ static struct cache_detail idtoname_cache = {
.cache_parse = idtoname_parse,
.cache_show = idtoname_show,
.warn_no_listener = warn_no_idmapd,
+ .match = idtoname_match,
+ .init = ent_init,
+ .update = ent_init,
+ .alloc = ent_alloc,
};
int
@@ -238,6 +245,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
if (ent.h.expiry_time == 0)
goto out;
+ error = -ENOMEM;
+ res = idtoname_lookup(&ent);
+ if (!res)
+ goto out;
+
/* Name */
error = qword_get(&buf, buf1, PAGE_SIZE);
if (error == -EINVAL)
@@ -252,10 +264,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
memcpy(ent.name, buf1, sizeof(ent.name));
}
error = -ENOMEM;
- if ((res = idtoname_lookup(&ent, 1)) == NULL)
+ res = idtoname_update(&ent, res);
+ if (res == NULL)
goto out;
- ent_put(&res->h, &idtoname_cache);
+ cache_put(&res->h, &idtoname_cache);
error = 0;
out:
@@ -264,7 +277,31 @@ out:
return error;
}
-static DefineSimpleCacheLookupMap(ent, idtoname);
+
+static struct ent *
+idtoname_lookup(struct ent *item)
+{
+ struct cache_head *ch = sunrpc_cache_lookup(&idtoname_cache,
+ &item->h,
+ idtoname_hash(item));
+ if (ch)
+ return container_of(ch, struct ent, h);
+ else
+ return NULL;
+}
+
+static struct ent *
+idtoname_update(struct ent *new, struct ent *old)
+{
+ struct cache_head *ch = sunrpc_cache_update(&idtoname_cache,
+ &new->h, &old->h,
+ idtoname_hash(new));
+ if (ch)
+ return container_of(ch, struct ent, h);
+ else
+ return NULL;
+}
+
/*
* Name -> ID cache
@@ -291,9 +328,12 @@ nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
(*bpp)[-1] = '\n';
}
-static inline int
-nametoid_match(struct ent *a, struct ent *b)
+static int
+nametoid_match(struct cache_head *ca, struct cache_head *cb)
{
+ struct ent *a = container_of(ca, struct ent, h);
+ struct ent *b = container_of(cb, struct ent, h);
+
return (a->type == b->type && strcmp(a->name, b->name) == 0 &&
strcmp(a->authname, b->authname) == 0);
}
@@ -317,7 +357,8 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
return 0;
}
-static struct ent *nametoid_lookup(struct ent *, int);
+static struct ent *nametoid_lookup(struct ent *);
+static struct ent *nametoid_update(struct ent *, struct ent *);
static int nametoid_parse(struct cache_detail *, char *, int);
static struct cache_detail nametoid_cache = {
@@ -330,6 +371,10 @@ static struct cache_detail nametoid_cache = {
.cache_parse = nametoid_parse,
.cache_show = nametoid_show,
.warn_no_listener = warn_no_idmapd,
+ .match = nametoid_match,
+ .init = ent_init,
+ .update = ent_init,
+ .alloc = ent_alloc,
};
static int
@@ -379,10 +424,14 @@ nametoid_parse(struct cache_detail *cd, char *buf, int buflen)
set_bit(CACHE_NEGATIVE, &ent.h.flags);
error = -ENOMEM;
- if ((res = nametoid_lookup(&ent, 1)) == NULL)
+ res = nametoid_lookup(&ent);
+ if (res == NULL)
+ goto out;
+ res = nametoid_update(&ent, res);
+ if (res == NULL)
goto out;
- ent_put(&res->h, &nametoid_cache);
+ cache_put(&res->h, &nametoid_cache);
error = 0;
out:
kfree(buf1);
@@ -390,7 +439,30 @@ out:
return (error);
}
-static DefineSimpleCacheLookupMap(ent, nametoid);
+
+static struct ent *
+nametoid_lookup(struct ent *item)
+{
+ struct cache_head *ch = sunrpc_cache_lookup(&nametoid_cache,
+ &item->h,
+ nametoid_hash(item));
+ if (ch)
+ return container_of(ch, struct ent, h);
+ else
+ return NULL;
+}
+
+static struct ent *
+nametoid_update(struct ent *new, struct ent *old)
+{
+ struct cache_head *ch = sunrpc_cache_update(&nametoid_cache,
+ &new->h, &old->h,
+ nametoid_hash(new));
+ if (ch)
+ return container_of(ch, struct ent, h);
+ else
+ return NULL;
+}
/*
* Exported API
@@ -458,24 +530,24 @@ idmap_defer(struct cache_req *req)
}
static inline int
-do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *, int), struct ent *key,
+do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *), struct ent *key,
struct cache_detail *detail, struct ent **item,
struct idmap_defer_req *mdr)
{
- *item = lookup_fn(key, 0);
+ *item = lookup_fn(key);
if (!*item)
return -ENOMEM;
return cache_check(detail, &(*item)->h, &mdr->req);
}
static inline int
-do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int),
+do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *),
struct ent *key, struct cache_detail *detail,
struct ent **item)
{
int ret = -ENOMEM;
- *item = lookup_fn(key, 0);
+ *item = lookup_fn(key);
if (!*item)
goto out_err;
ret = -ETIMEDOUT;
@@ -488,7 +560,7 @@ do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int),
goto out_put;
return 0;
out_put:
- ent_put(&(*item)->h, detail);
+ cache_put(&(*item)->h, detail);
out_err:
*item = NULL;
return ret;
@@ -496,7 +568,7 @@ out_err:
static int
idmap_lookup(struct svc_rqst *rqstp,
- struct ent *(*lookup_fn)(struct ent *, int), struct ent *key,
+ struct ent *(*lookup_fn)(struct ent *), struct ent *key,
struct cache_detail *detail, struct ent **item)
{
struct idmap_defer_req *mdr;
@@ -539,7 +611,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
if (ret)
return ret;
*id = item->id;
- ent_put(&item->h, &nametoid_cache);
+ cache_put(&item->h, &nametoid_cache);
return 0;
}
@@ -561,7 +633,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
ret = strlen(item->name);
BUG_ON(ret > IDMAP_NAMESZ);
memcpy(name, item->name, ret);
- ent_put(&item->h, &idtoname_cache);
+ cache_put(&item->h, &idtoname_cache);
return ret;
}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 1143cfb6454..47ec112b266 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -49,6 +49,7 @@
#include <linux/nfsd/state.h>
#include <linux/nfsd/xdr4.h>
#include <linux/namei.h>
+#include <linux/mutex.h>
#define NFSDDBG_FACILITY NFSDDBG_PROC
@@ -77,11 +78,11 @@ static void nfs4_set_recdir(char *recdir);
/* Locking:
*
- * client_sema:
+ * client_mutex:
* protects clientid_hashtbl[], clientstr_hashtbl[],
* unconfstr_hashtbl[], uncofid_hashtbl[].
*/
-static DECLARE_MUTEX(client_sema);
+static DEFINE_MUTEX(client_mutex);
static kmem_cache_t *stateowner_slab = NULL;
static kmem_cache_t *file_slab = NULL;
@@ -91,13 +92,13 @@ static kmem_cache_t *deleg_slab = NULL;
void
nfs4_lock_state(void)
{
- down(&client_sema);
+ mutex_lock(&client_mutex);
}
void
nfs4_unlock_state(void)
{
- up(&client_sema);
+ mutex_unlock(&client_mutex);
}
static inline u32
@@ -2639,7 +2640,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
struct nfs4_stateid *lock_stp;
struct file *filp;
struct file_lock file_lock;
- struct file_lock *conflock;
+ struct file_lock conflock;
int status = 0;
unsigned int strhashval;
@@ -2749,37 +2750,31 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
* Note: locks.c uses the BKL to protect the inode's lock list.
*/
- status = posix_lock_file(filp, &file_lock);
- dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status);
+ /* XXX?: Just to divert the locks_release_private at the start of
+ * locks_copy_lock: */
+ conflock.fl_ops = NULL;
+ conflock.fl_lmops = NULL;
+ status = posix_lock_file_conf(filp, &file_lock, &conflock);
+ dprintk("NFSD: nfsd4_lock: posix_lock_file_conf status %d\n",status);
switch (-status) {
case 0: /* success! */
update_stateid(&lock_stp->st_stateid);
memcpy(&lock->lk_resp_stateid, &lock_stp->st_stateid,
sizeof(stateid_t));
- goto out;
- case (EAGAIN):
- goto conflicting_lock;
+ break;
+ case (EAGAIN): /* conflock holds conflicting lock */
+ status = nfserr_denied;
+ dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
+ nfs4_set_lock_denied(&conflock, &lock->lk_denied);
+ break;
case (EDEADLK):
status = nfserr_deadlock;
- dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
- goto out;
+ break;
default:
- status = nfserrno(status);
- dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
- goto out;
- }
-
-conflicting_lock:
- dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
- status = nfserr_denied;
- /* XXX There is a race here. Future patch needed to provide
- * an atomic posix_lock_and_test_file
- */
- if (!(conflock = posix_test_lock(filp, &file_lock))) {
- status = nfserr_serverfault;
- goto out;
+ dprintk("NFSD: nfsd4_lock: posix_lock_file_conf() failed! status %d\n",status);
+ status = nfserr_resource;
+ break;
}
- nfs4_set_lock_denied(conflock, &lock->lk_denied);
out:
if (status && lock->lk_is_new && lock_sop)
release_stateowner(lock_sop);
@@ -2800,7 +2795,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
struct inode *inode;
struct file file;
struct file_lock file_lock;
- struct file_lock *conflicting_lock;
+ struct file_lock conflock;
int status;
if (nfs4_in_grace())
@@ -2864,10 +2859,9 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
file.f_dentry = current_fh->fh_dentry;
status = nfs_ok;
- conflicting_lock = posix_test_lock(&file, &file_lock);
- if (conflicting_lock) {
+ if (posix_test_lock(&file, &file_lock, &conflock)) {
status = nfserr_denied;
- nfs4_set_lock_denied(conflicting_lock, &lockt->lt_denied);
+ nfs4_set_lock_denied(&conflock, &lockt->lt_denied);
}
out:
nfs4_unlock_state();
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index c8960aff096..3ef017b3b5b 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -134,7 +134,7 @@ static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size
return simple_transaction_read(file, buf, size, pos);
}
-static struct file_operations transaction_ops = {
+static const struct file_operations transaction_ops = {
.write = nfsctl_transaction_write,
.read = nfsctl_transaction_read,
.release = simple_transaction_release,
@@ -146,7 +146,7 @@ static int exports_open(struct inode *inode, struct file *file)
return seq_open(file, &nfs_exports_op);
}
-static struct file_operations exports_operations = {
+static const struct file_operations exports_operations = {
.open = exports_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 7a3e397b4ed..3f2ec2e6d06 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -506,7 +506,7 @@ fh_put(struct svc_fh *fhp)
nfsd_nr_put++;
}
if (exp) {
- svc_export_put(&exp->h, &svc_export_cache);
+ cache_put(&exp->h, &svc_export_cache);
fhp->fh_export = NULL;
}
return;
diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c
index 1cf955bcc52..57265d56380 100644
--- a/fs/nfsd/stats.c
+++ b/fs/nfsd/stats.c
@@ -80,7 +80,7 @@ static int nfsd_proc_open(struct inode *inode, struct file *file)
return single_open(file, nfsd_proc_show, NULL);
}
-static struct file_operations nfsd_proc_fops = {
+static const struct file_operations nfsd_proc_fops = {
.owner = THIS_MODULE,
.open = nfsd_proc_open,
.read = seq_read,
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 5320e5afadd..31018333dc3 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -706,7 +706,7 @@ nfsd_close(struct file *filp)
* after it.
*/
static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
- struct file_operations *fop)
+ const struct file_operations *fop)
{
struct inode *inode = dp->d_inode;
int (*fsync) (struct file *, struct dentry *, int);
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c
index 9d9ed3fe371..d1e2c6f9f05 100644
--- a/fs/ntfs/dir.c
+++ b/fs/ntfs/dir.c
@@ -1553,7 +1553,7 @@ static int ntfs_dir_fsync(struct file *filp, struct dentry *dentry,
#endif /* NTFS_RW */
-struct file_operations ntfs_dir_ops = {
+const struct file_operations ntfs_dir_ops = {
.llseek = generic_file_llseek, /* Seek inside directory. */
.read = generic_read_dir, /* Return -EISDIR. */
.readdir = ntfs_readdir, /* Read directory contents. */
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index f5d057e4acc..c63a83e8da9 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2294,7 +2294,7 @@ static int ntfs_file_fsync(struct file *filp, struct dentry *dentry,
#endif /* NTFS_RW */
-struct file_operations ntfs_file_ops = {
+const struct file_operations ntfs_file_ops = {
.llseek = generic_file_llseek, /* Seek inside file. */
.read = generic_file_read, /* Read from file. */
.aio_read = generic_file_aio_read, /* Async read from file. */
@@ -2337,6 +2337,6 @@ struct inode_operations ntfs_file_inode_ops = {
#endif /* NTFS_RW */
};
-struct file_operations ntfs_empty_file_ops = {};
+const struct file_operations ntfs_empty_file_ops = {};
struct inode_operations ntfs_empty_inode_ops = {};
diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c
index 0fd70295cca..4af2ad1193e 100644
--- a/fs/ntfs/logfile.c
+++ b/fs/ntfs/logfile.c
@@ -515,10 +515,10 @@ BOOL ntfs_check_logfile(struct inode *log_vi, RESTART_PAGE_HEADER **rp)
log_page_size = PAGE_CACHE_SIZE;
log_page_mask = log_page_size - 1;
/*
- * Use generic_ffs() instead of ffs() to enable the compiler to
+ * Use ntfs_ffs() instead of ffs() to enable the compiler to
* optimize log_page_size and log_page_bits into constants.
*/
- log_page_bits = generic_ffs(log_page_size) - 1;
+ log_page_bits = ntfs_ffs(log_page_size) - 1;
size &= ~(s64)(log_page_size - 1);
/*
* Ensure the log file is big enough to store at least the two restart
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index 4e72bc7afdf..2438c00ec0c 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -2670,7 +2670,7 @@ mft_rec_already_initialized:
ni->name_len = 4;
ni->itype.index.block_size = 4096;
- ni->itype.index.block_size_bits = generic_ffs(4096) - 1;
+ ni->itype.index.block_size_bits = ntfs_ffs(4096) - 1;
ni->itype.index.collation_rule = COLLATION_FILE_NAME;
if (vol->cluster_size <= ni->itype.index.block_size) {
ni->itype.index.vcn_size = vol->cluster_size;
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h
index 0624c8ef4d9..bf7b3d7c093 100644
--- a/fs/ntfs/ntfs.h
+++ b/fs/ntfs/ntfs.h
@@ -60,13 +60,13 @@ extern struct kmem_cache *ntfs_index_ctx_cache;
extern struct address_space_operations ntfs_aops;
extern struct address_space_operations ntfs_mst_aops;
-extern struct file_operations ntfs_file_ops;
+extern const struct file_operations ntfs_file_ops;
extern struct inode_operations ntfs_file_inode_ops;
-extern struct file_operations ntfs_dir_ops;
+extern const struct file_operations ntfs_dir_ops;
extern struct inode_operations ntfs_dir_inode_ops;
-extern struct file_operations ntfs_empty_file_ops;
+extern const struct file_operations ntfs_empty_file_ops;
extern struct inode_operations ntfs_empty_inode_ops;
extern struct export_operations ntfs_export_ops;
@@ -132,4 +132,33 @@ extern int ntfs_ucstonls(const ntfs_volume *vol, const ntfschar *ins,
/* From fs/ntfs/upcase.c */
extern ntfschar *generate_default_upcase(void);
+static inline int ntfs_ffs(int x)
+{
+ int r = 1;
+
+ if (!x)
+ return 0;
+ if (!(x & 0xffff)) {
+ x >>= 16;
+ r += 16;
+ }
+ if (!(x & 0xff)) {
+ x >>= 8;
+ r += 8;
+ }
+ if (!(x & 0xf)) {
+ x >>= 4;
+ r += 4;
+ }
+ if (!(x & 3)) {
+ x >>= 2;
+ r += 2;
+ }
+ if (!(x & 1)) {
+ x >>= 1;
+ r += 1;
+ }
+ return r;
+}
+
#endif /* _LINUX_NTFS_H */
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 6b9812db377..edaab05a93e 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -566,9 +566,8 @@ static int ocfs2_do_insert_extent(struct ocfs2_super *osb,
next_free = le16_to_cpu(el->l_next_free_rec);
if (next_free == 0) {
ocfs2_error(inode->i_sb,
- "Dinode %"MLFu64" has a bad "
- "extent list",
- OCFS2_I(inode)->ip_blkno);
+ "Dinode %llu has a bad extent list",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
status = -EIO;
goto bail;
}
@@ -611,9 +610,8 @@ static int ocfs2_do_insert_extent(struct ocfs2_super *osb,
next_free = le16_to_cpu(el->l_next_free_rec);
if (next_free == 0) {
ocfs2_error(inode->i_sb,
- "Dinode %"MLFu64" has a bad "
- "extent list",
- OCFS2_I(inode)->ip_blkno);
+ "Dinode %llu has a bad extent list",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
status = -EIO;
goto bail;
}
@@ -652,8 +650,9 @@ static int ocfs2_do_insert_extent(struct ocfs2_super *osb,
/* having an empty extent at eof is legal. */
if (el->l_recs[i].e_cpos != fe->i_clusters) {
ocfs2_error(inode->i_sb,
- "Dinode %"MLFu64" trailing extent is bad: "
+ "Dinode %llu trailing extent is bad: "
"cpos (%u) != number of clusters (%u)",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
le32_to_cpu(el->l_recs[i].e_cpos),
le32_to_cpu(fe->i_clusters));
status = -EIO;
@@ -747,19 +746,19 @@ static int ocfs2_find_branch_target(struct ocfs2_super *osb,
while(le16_to_cpu(el->l_tree_depth) > 1) {
if (le16_to_cpu(el->l_next_free_rec) == 0) {
- ocfs2_error(inode->i_sb, "Dinode %"MLFu64" has empty "
+ ocfs2_error(inode->i_sb, "Dinode %llu has empty "
"extent list (next_free_rec == 0)",
- OCFS2_I(inode)->ip_blkno);
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
status = -EIO;
goto bail;
}
i = le16_to_cpu(el->l_next_free_rec) - 1;
blkno = le64_to_cpu(el->l_recs[i].e_blkno);
if (!blkno) {
- ocfs2_error(inode->i_sb, "Dinode %"MLFu64" has extent "
+ ocfs2_error(inode->i_sb, "Dinode %llu has extent "
"list where extent # %d has no physical "
"block start",
- OCFS2_I(inode)->ip_blkno, i);
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, i);
status = -EIO;
goto bail;
}
@@ -826,9 +825,9 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
mlog_entry_void();
- mlog(0, "add %u clusters starting at block %"MLFu64" to "
- "inode %"MLFu64"\n",
- new_clusters, start_blk, OCFS2_I(inode)->ip_blkno);
+ mlog(0, "add %u clusters starting at block %llu to inode %llu\n",
+ new_clusters, (unsigned long long)start_blk,
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
fe = (struct ocfs2_dinode *) fe_bh->b_data;
el = &fe->id2.i_list;
@@ -963,8 +962,8 @@ static int ocfs2_truncate_log_append(struct ocfs2_super *osb,
struct ocfs2_dinode *di;
struct ocfs2_truncate_log *tl;
- mlog_entry("start_blk = %"MLFu64", num_clusters = %u\n", start_blk,
- num_clusters);
+ mlog_entry("start_blk = %llu, num_clusters = %u\n",
+ (unsigned long long)start_blk, num_clusters);
BUG_ON(mutex_trylock(&tl_inode->i_mutex));
@@ -981,8 +980,9 @@ static int ocfs2_truncate_log_append(struct ocfs2_super *osb,
tl_count = le16_to_cpu(tl->tl_count);
mlog_bug_on_msg(tl_count > ocfs2_truncate_recs_per_inode(osb->sb) ||
tl_count == 0,
- "Truncate record count on #%"MLFu64" invalid ("
- "wanted %u, actual %u\n", OCFS2_I(tl_inode)->ip_blkno,
+ "Truncate record count on #%llu invalid "
+ "wanted %u, actual %u\n",
+ (unsigned long long)OCFS2_I(tl_inode)->ip_blkno,
ocfs2_truncate_recs_per_inode(osb->sb),
le16_to_cpu(tl->tl_count));
@@ -1002,8 +1002,8 @@ static int ocfs2_truncate_log_append(struct ocfs2_super *osb,
}
mlog(0, "Log truncate of %u clusters starting at cluster %u to "
- "%"MLFu64" (index = %d)\n", num_clusters, start_cluster,
- OCFS2_I(tl_inode)->ip_blkno, index);
+ "%llu (index = %d)\n", num_clusters, start_cluster,
+ (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, index);
if (ocfs2_truncate_log_can_coalesce(tl, start_cluster)) {
/*
@@ -1134,8 +1134,8 @@ static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
}
num_to_flush = le16_to_cpu(tl->tl_used);
- mlog(0, "Flush %u records from truncate log #%"MLFu64"\n",
- num_to_flush, OCFS2_I(tl_inode)->ip_blkno);
+ mlog(0, "Flush %u records from truncate log #%llu\n",
+ num_to_flush, (unsigned long long)OCFS2_I(tl_inode)->ip_blkno);
if (!num_to_flush) {
status = 0;
goto bail;
@@ -1360,8 +1360,8 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
tl = &tl_copy->id2.i_dealloc;
num_recs = le16_to_cpu(tl->tl_used);
- mlog(0, "cleanup %u records from %"MLFu64"\n", num_recs,
- tl_copy->i_blkno);
+ mlog(0, "cleanup %u records from %llu\n", num_recs,
+ (unsigned long long)tl_copy->i_blkno);
mutex_lock(&tl_inode->i_mutex);
for(i = 0; i < num_recs; i++) {
@@ -1529,7 +1529,8 @@ static int ocfs2_find_new_last_ext_blk(struct ocfs2_super *osb,
*new_last_eb = bh;
get_bh(*new_last_eb);
- mlog(0, "returning block %"MLFu64"\n", le64_to_cpu(eb->h_blkno));
+ mlog(0, "returning block %llu\n",
+ (unsigned long long)le64_to_cpu(eb->h_blkno));
bail:
if (bh)
brelse(bh);
@@ -1646,8 +1647,8 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
/* if our tree depth > 0, update all the tree blocks below us. */
while (depth) {
- mlog(0, "traveling tree (depth = %d, next_eb = %"MLFu64")\n",
- depth, next_eb);
+ mlog(0, "traveling tree (depth = %d, next_eb = %llu)\n",
+ depth, (unsigned long long)next_eb);
status = ocfs2_read_block(osb, next_eb, &eb_bh,
OCFS2_BH_CACHED, inode);
if (status < 0) {
@@ -1674,12 +1675,12 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
i = le16_to_cpu(el->l_next_free_rec) - 1;
- mlog(0, "extent block %"MLFu64", before: record %d: "
- "(%u, %u, %"MLFu64"), next = %u\n",
- le64_to_cpu(eb->h_blkno), i,
+ mlog(0, "extent block %llu, before: record %d: "
+ "(%u, %u, %llu), next = %u\n",
+ (unsigned long long)le64_to_cpu(eb->h_blkno), i,
le32_to_cpu(el->l_recs[i].e_cpos),
le32_to_cpu(el->l_recs[i].e_clusters),
- le64_to_cpu(el->l_recs[i].e_blkno),
+ (unsigned long long)le64_to_cpu(el->l_recs[i].e_blkno),
le16_to_cpu(el->l_next_free_rec));
BUG_ON(le32_to_cpu(el->l_recs[i].e_clusters) < clusters_to_del);
@@ -1697,12 +1698,12 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
BUG_ON(!el->l_next_free_rec);
le16_add_cpu(&el->l_next_free_rec, -1);
}
- mlog(0, "extent block %"MLFu64", after: record %d: "
- "(%u, %u, %"MLFu64"), next = %u\n",
- le64_to_cpu(eb->h_blkno), i,
+ mlog(0, "extent block %llu, after: record %d: "
+ "(%u, %u, %llu), next = %u\n",
+ (unsigned long long)le64_to_cpu(eb->h_blkno), i,
le32_to_cpu(el->l_recs[i].e_cpos),
le32_to_cpu(el->l_recs[i].e_clusters),
- le64_to_cpu(el->l_recs[i].e_blkno),
+ (unsigned long long)le64_to_cpu(el->l_recs[i].e_blkno),
le16_to_cpu(el->l_next_free_rec));
status = ocfs2_journal_dirty(handle, eb_bh);
@@ -1792,10 +1793,10 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
last_eb = le64_to_cpu(fe->i_last_eb_blk);
start:
mlog(0, "ocfs2_commit_truncate: fe->i_clusters = %u, "
- "last_eb = %"MLFu64", fe->i_last_eb_blk = %"MLFu64", "
+ "last_eb = %llu, fe->i_last_eb_blk = %llu, "
"fe->id2.i_list.l_tree_depth = %u last_eb_bh = %p\n",
- le32_to_cpu(fe->i_clusters), last_eb,
- le64_to_cpu(fe->i_last_eb_blk),
+ le32_to_cpu(fe->i_clusters), (unsigned long long)last_eb,
+ (unsigned long long)le64_to_cpu(fe->i_last_eb_blk),
le16_to_cpu(fe->id2.i_list.l_tree_depth), last_eb_bh);
if (last_eb != le64_to_cpu(fe->i_last_eb_blk)) {
@@ -1934,16 +1935,17 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
fe = (struct ocfs2_dinode *) fe_bh->b_data;
mlog(0, "fe->i_clusters = %u, new_i_clusters = %u, fe->i_size ="
- "%"MLFu64"\n", fe->i_clusters, new_i_clusters, fe->i_size);
+ "%llu\n", fe->i_clusters, new_i_clusters,
+ (unsigned long long)fe->i_size);
if (le32_to_cpu(fe->i_clusters) <= new_i_clusters) {
- ocfs2_error(inode->i_sb, "Dinode %"MLFu64" has cluster count "
- "%u and size %"MLFu64" whereas struct inode has "
+ ocfs2_error(inode->i_sb, "Dinode %llu has cluster count "
+ "%u and size %llu whereas struct inode has "
"cluster count %u and size %llu which caused an "
"invalid truncate to %u clusters.",
- le64_to_cpu(fe->i_blkno),
+ (unsigned long long)le64_to_cpu(fe->i_blkno),
le32_to_cpu(fe->i_clusters),
- le64_to_cpu(fe->i_size),
+ (unsigned long long)le64_to_cpu(fe->i_size),
OCFS2_I(inode)->ip_clusters, i_size_read(inode),
new_i_clusters);
mlog_meta_lvb(ML_ERROR, &OCFS2_I(inode)->ip_meta_lockres);
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 8f4467a930a..0d858d0b25b 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -74,8 +74,8 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
fe = (struct ocfs2_dinode *) bh->b_data;
if (!OCFS2_IS_VALID_DINODE(fe)) {
- mlog(ML_ERROR, "Invalid dinode #%"MLFu64": signature = %.*s\n",
- fe->i_blkno, 7, fe->i_signature);
+ mlog(ML_ERROR, "Invalid dinode #%llu: signature = %.*s\n",
+ (unsigned long long)fe->i_blkno, 7, fe->i_signature);
goto bail;
}
@@ -162,8 +162,8 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
NULL);
if (err) {
mlog(ML_ERROR, "Error %d from get_blocks(0x%p, %llu, 1, "
- "%"MLFu64", NULL)\n", err, inode,
- (unsigned long long)iblock, p_blkno);
+ "%llu, NULL)\n", err, inode, (unsigned long long)iblock,
+ (unsigned long long)p_blkno);
goto bail;
}
@@ -171,13 +171,15 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
if (bh_result->b_blocknr == 0) {
err = -EIO;
- mlog(ML_ERROR, "iblock = %llu p_blkno = %"MLFu64" "
- "blkno=(%"MLFu64")\n", (unsigned long long)iblock,
- p_blkno, OCFS2_I(inode)->ip_blkno);
+ mlog(ML_ERROR, "iblock = %llu p_blkno = %llu blkno=(%llu)\n",
+ (unsigned long long)iblock,
+ (unsigned long long)p_blkno,
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
}
past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode));
- mlog(0, "Inode %lu, past_eof = %"MLFu64"\n", inode->i_ino, past_eof);
+ mlog(0, "Inode %lu, past_eof = %llu\n", inode->i_ino,
+ (unsigned long long)past_eof);
if (create && (iblock >= past_eof))
set_buffer_new(bh_result);
@@ -538,7 +540,6 @@ bail:
* fs_count, map_bh, dio->rw == WRITE);
*/
static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
- unsigned long max_blocks,
struct buffer_head *bh_result, int create)
{
int ret;
@@ -546,6 +547,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
u64 p_blkno;
int contig_blocks;
unsigned char blocksize_bits;
+ unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
if (!inode || !bh_result) {
mlog(ML_ERROR, "inode or bh_result is null\n");
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c
index bae3d7548be..9a24adf9be6 100644
--- a/fs/ocfs2/buffer_head_io.c
+++ b/fs/ocfs2/buffer_head_io.c
@@ -97,8 +97,8 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
int i, ignore_cache = 0;
struct buffer_head *bh;
- mlog_entry("(block=(%"MLFu64"), nr=(%d), flags=%d, inode=%p)\n",
- block, nr, flags, inode);
+ mlog_entry("(block=(%llu), nr=(%d), flags=%d, inode=%p)\n",
+ (unsigned long long)block, nr, flags, inode);
if (osb == NULL || osb->sb == NULL || bhs == NULL) {
status = -EINVAL;
@@ -143,9 +143,9 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
if (flags & OCFS2_BH_CACHED &&
!ocfs2_buffer_uptodate(inode, bh)) {
mlog(ML_UPTODATE,
- "bh (%llu), inode %"MLFu64" not uptodate\n",
+ "bh (%llu), inode %llu not uptodate\n",
(unsigned long long)bh->b_blocknr,
- OCFS2_I(inode)->ip_blkno);
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
ignore_cache = 1;
}
@@ -222,7 +222,8 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
if (inode)
mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
- mlog(ML_BH_IO, "block=(%"MLFu64"), nr=(%d), cached=%s\n", block, nr,
+ mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s\n",
+ (unsigned long long)block, nr,
(!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes");
bail:
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index d08971d29b6..bff0f0d0686 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -449,11 +449,11 @@ static u32 o2hb_compute_block_crc_le(struct o2hb_region *reg,
static void o2hb_dump_slot(struct o2hb_disk_heartbeat_block *hb_block)
{
- mlog(ML_ERROR, "Dump slot information: seq = 0x%"MLFx64", node = %u, "
- "cksum = 0x%x, generation 0x%"MLFx64"\n",
- le64_to_cpu(hb_block->hb_seq), hb_block->hb_node,
- le32_to_cpu(hb_block->hb_cksum),
- le64_to_cpu(hb_block->hb_generation));
+ mlog(ML_ERROR, "Dump slot information: seq = 0x%llx, node = %u, "
+ "cksum = 0x%x, generation 0x%llx\n",
+ (long long)le64_to_cpu(hb_block->hb_seq),
+ hb_block->hb_node, le32_to_cpu(hb_block->hb_cksum),
+ (long long)le64_to_cpu(hb_block->hb_generation));
}
static int o2hb_verify_crc(struct o2hb_region *reg,
@@ -516,8 +516,9 @@ static inline void o2hb_prepare_block(struct o2hb_region *reg,
hb_block->hb_cksum = cpu_to_le32(o2hb_compute_block_crc_le(reg,
hb_block));
- mlog(ML_HB_BIO, "our node generation = 0x%"MLFx64", cksum = 0x%x\n",
- cpu_to_le64(generation), le32_to_cpu(hb_block->hb_cksum));
+ mlog(ML_HB_BIO, "our node generation = 0x%llx, cksum = 0x%x\n",
+ (long long)cpu_to_le64(generation),
+ le32_to_cpu(hb_block->hb_cksum));
}
static void o2hb_fire_callbacks(struct o2hb_callback *hbcall,
@@ -686,19 +687,20 @@ static int o2hb_check_slot(struct o2hb_region *reg,
if (slot->ds_last_generation != le64_to_cpu(hb_block->hb_generation)) {
gen_changed = 1;
slot->ds_equal_samples = 0;
- mlog(ML_HEARTBEAT, "Node %d changed generation (0x%"MLFx64" "
- "to 0x%"MLFx64")\n", slot->ds_node_num,
- slot->ds_last_generation,
- le64_to_cpu(hb_block->hb_generation));
+ mlog(ML_HEARTBEAT, "Node %d changed generation (0x%llx "
+ "to 0x%llx)\n", slot->ds_node_num,
+ (long long)slot->ds_last_generation,
+ (long long)le64_to_cpu(hb_block->hb_generation));
}
slot->ds_last_generation = le64_to_cpu(hb_block->hb_generation);
- mlog(ML_HEARTBEAT, "Slot %d gen 0x%"MLFx64" cksum 0x%x "
- "seq %"MLFu64" last %"MLFu64" changed %u equal %u\n",
- slot->ds_node_num, slot->ds_last_generation,
- le32_to_cpu(hb_block->hb_cksum), le64_to_cpu(hb_block->hb_seq),
- slot->ds_last_time, slot->ds_changed_samples,
+ mlog(ML_HEARTBEAT, "Slot %d gen 0x%llx cksum 0x%x "
+ "seq %llu last %llu changed %u equal %u\n",
+ slot->ds_node_num, (long long)slot->ds_last_generation,
+ le32_to_cpu(hb_block->hb_cksum),
+ (unsigned long long)le64_to_cpu(hb_block->hb_seq),
+ (unsigned long long)slot->ds_last_time, slot->ds_changed_samples,
slot->ds_equal_samples);
spin_lock(&o2hb_live_lock);
@@ -708,8 +710,8 @@ fire_callbacks:
* changes at any time during their dead time */
if (list_empty(&slot->ds_live_item) &&
slot->ds_changed_samples >= O2HB_LIVE_THRESHOLD) {
- mlog(ML_HEARTBEAT, "Node %d (id 0x%"MLFx64") joined my "
- "region\n", slot->ds_node_num, slot->ds_last_generation);
+ mlog(ML_HEARTBEAT, "Node %d (id 0x%llx) joined my region\n",
+ slot->ds_node_num, (long long)slot->ds_last_generation);
/* first on the list generates a callback */
if (list_empty(&o2hb_live_slots[slot->ds_node_num])) {
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index 2cadc3009c8..73edad78253 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -256,16 +256,6 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits;
} \
} while (0)
-#if (BITS_PER_LONG == 32) || defined(CONFIG_X86_64) || (defined(CONFIG_UML_X86) && defined(CONFIG_64BIT))
-#define MLFi64 "lld"
-#define MLFu64 "llu"
-#define MLFx64 "llx"
-#else
-#define MLFi64 "ld"
-#define MLFu64 "lu"
-#define MLFx64 "lx"
-#endif
-
#include <linux/kobject.h>
#include <linux/sysfs.h>
int mlog_sys_init(struct subsystem *o2cb_subsys);
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index bd85182e97b..1a01380e387 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -64,15 +64,16 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry,
/* did we or someone else delete this inode? */
if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) {
spin_unlock(&OCFS2_I(inode)->ip_lock);
- mlog(0, "inode (%"MLFu64") deleted, returning false\n",
- OCFS2_I(inode)->ip_blkno);
+ mlog(0, "inode (%llu) deleted, returning false\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
goto bail;
}
spin_unlock(&OCFS2_I(inode)->ip_lock);
if (!inode->i_nlink) {
- mlog(0, "Inode %"MLFu64" orphaned, returning false "
- "dir = %d\n", OCFS2_I(inode)->ip_blkno,
+ mlog(0, "Inode %llu orphaned, returning false "
+ "dir = %d\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
S_ISDIR(inode->i_mode));
goto bail;
}
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 57158fa75d9..ae47f450792 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -83,7 +83,8 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
struct super_block * sb = inode->i_sb;
int have_disk_lock = 0;
- mlog_entry("dirino=%"MLFu64"\n", OCFS2_I(inode)->ip_blkno);
+ mlog_entry("dirino=%llu\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
stored = 0;
bh = NULL;
@@ -104,9 +105,9 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
blk = (filp->f_pos) >> sb->s_blocksize_bits;
bh = ocfs2_bread(inode, blk, &err, 0);
if (!bh) {
- mlog(ML_ERROR, "directory #%"MLFu64" contains a hole "
- "at offset %lld\n",
- OCFS2_I(inode)->ip_blkno,
+ mlog(ML_ERROR,
+ "directory #%llu contains a hole at offset %lld\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
filp->f_pos);
filp->f_pos += sb->s_blocksize - offset;
continue;
@@ -214,9 +215,9 @@ int ocfs2_find_files_on_disk(const char *name,
int status = -ENOENT;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
- mlog_entry("(osb=%p, parent=%"MLFu64", name='%.*s', blkno=%p, "
- "inode=%p)\n",
- osb, OCFS2_I(inode)->ip_blkno, namelen, name, blkno, inode);
+ mlog_entry("(osb=%p, parent=%llu, name='%.*s', blkno=%p, inode=%p)\n",
+ osb, (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ namelen, name, blkno, inode);
*dirent_bh = ocfs2_find_entry(name, namelen, inode, dirent);
if (!*dirent_bh || !*dirent) {
@@ -255,8 +256,8 @@ int ocfs2_check_dir_for_entry(struct inode *dir,
struct buffer_head *dirent_bh = NULL;
struct ocfs2_dir_entry *dirent = NULL;
- mlog_entry("dir %"MLFu64", name '%.*s'\n", OCFS2_I(dir)->ip_blkno,
- namelen, name);
+ mlog_entry("dir %llu, name '%.*s'\n",
+ (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name);
ret = -EEXIST;
dirent_bh = ocfs2_find_entry(name, namelen, dir, &dirent);
@@ -287,9 +288,8 @@ int ocfs2_empty_dir(struct inode *inode)
if ((i_size_read(inode) <
(OCFS2_DIR_REC_LEN(1) + OCFS2_DIR_REC_LEN(2))) ||
!(bh = ocfs2_bread(inode, 0, &err, 0))) {
- mlog(ML_ERROR, "bad directory (dir #%"MLFu64") - "
- "no data block\n",
- OCFS2_I(inode)->ip_blkno);
+ mlog(ML_ERROR, "bad directory (dir #%llu) - no data block\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
return 1;
}
@@ -300,9 +300,8 @@ int ocfs2_empty_dir(struct inode *inode)
!le64_to_cpu(de1->inode) ||
strcmp(".", de->name) ||
strcmp("..", de1->name)) {
- mlog(ML_ERROR, "bad directory (dir #%"MLFu64") - "
- "no `.' or `..'\n",
- OCFS2_I(inode)->ip_blkno);
+ mlog(ML_ERROR, "bad directory (dir #%llu) - no `.' or `..'\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
brelse(bh);
return 1;
}
@@ -314,9 +313,8 @@ int ocfs2_empty_dir(struct inode *inode)
bh = ocfs2_bread(inode,
offset >> sb->s_blocksize_bits, &err, 0);
if (!bh) {
- mlog(ML_ERROR, "directory #%"MLFu64" contains "
- "a hole at offset %lu\n",
- OCFS2_I(inode)->ip_blkno, offset);
+ mlog(ML_ERROR, "dir %llu has a hole at %lu\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, offset);
offset += sb->s_blocksize;
continue;
}
@@ -406,8 +404,8 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
mlog_entry_void();
dir_i_size = i_size_read(dir);
- mlog(0, "extending dir %"MLFu64" (i_size = %lld)\n",
- OCFS2_I(dir)->ip_blkno, dir_i_size);
+ mlog(0, "extending dir %llu (i_size = %lld)\n",
+ (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size);
handle = ocfs2_alloc_handle(osb);
if (handle == NULL) {
@@ -531,8 +529,8 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
mlog_entry_void();
- mlog(0, "getting ready to insert namelen %d into dir %"MLFu64"\n",
- namelen, OCFS2_I(dir)->ip_blkno);
+ mlog(0, "getting ready to insert namelen %d into dir %llu\n",
+ namelen, (unsigned long long)OCFS2_I(dir)->ip_blkno);
BUG_ON(!S_ISDIR(dir->i_mode));
fe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
diff --git a/fs/ocfs2/dlm/dlmast.c b/fs/ocfs2/dlm/dlmast.c
index 8d17d28ef91..355593dd8ef 100644
--- a/fs/ocfs2/dlm/dlmast.c
+++ b/fs/ocfs2/dlm/dlmast.c
@@ -307,8 +307,11 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data)
if (past->type != DLM_AST &&
past->type != DLM_BAST) {
- mlog(ML_ERROR, "Unknown ast type! %d, cookie=%"MLFu64", "
- "name=%.*s\n", past->type, cookie, locklen, name);
+ mlog(ML_ERROR, "Unknown ast type! %d, cookie=%u:%llu"
+ "name=%.*s\n", past->type,
+ dlm_get_lock_cookie_node(cookie),
+ dlm_get_lock_cookie_seq(cookie),
+ locklen, name);
ret = DLM_IVLOCKID;
goto leave;
}
@@ -316,9 +319,11 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data)
res = dlm_lookup_lockres(dlm, name, locklen);
if (!res) {
mlog(ML_ERROR, "got %sast for unknown lockres! "
- "cookie=%"MLFu64", name=%.*s, namelen=%u\n",
+ "cookie=%u:%llu, name=%.*s, namelen=%u\n",
past->type == DLM_AST ? "" : "b",
- cookie, locklen, name, locklen);
+ dlm_get_lock_cookie_node(cookie),
+ dlm_get_lock_cookie_seq(cookie),
+ locklen, name, locklen);
ret = DLM_IVLOCKID;
goto leave;
}
@@ -360,9 +365,12 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data)
goto do_ast;
}
- mlog(ML_ERROR, "got %sast for unknown lock! cookie=%"MLFu64", "
- "name=%.*s, namelen=%u\n",
- past->type == DLM_AST ? "" : "b", cookie, locklen, name, locklen);
+ mlog(ML_ERROR, "got %sast for unknown lock! cookie=%u:%llu, "
+ "name=%.*s, namelen=%u\n",
+ past->type == DLM_AST ? "" : "b",
+ dlm_get_lock_cookie_node(cookie),
+ dlm_get_lock_cookie_seq(cookie),
+ locklen, name, locklen);
ret = DLM_NORMAL;
unlock_out:
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
index 9c772583744..88cc43df18f 100644
--- a/fs/ocfs2/dlm/dlmcommon.h
+++ b/fs/ocfs2/dlm/dlmcommon.h
@@ -630,6 +630,21 @@ __dlm_lockres_state_to_status(struct dlm_lock_resource *res)
return status;
}
+static inline u8 dlm_get_lock_cookie_node(u64 cookie)
+{
+ u8 ret;
+ cookie >>= 56;
+ ret = (u8)(cookie & 0xffULL);
+ return ret;
+}
+
+static inline unsigned long long dlm_get_lock_cookie_seq(u64 cookie)
+{
+ unsigned long long ret;
+ ret = ((unsigned long long)cookie) & 0x00ffffffffffffffULL;
+ return ret;
+}
+
struct dlm_lock * dlm_new_lock(int type, u8 node, u64 cookie,
struct dlm_lockstatus *lksb);
void dlm_lock_get(struct dlm_lock *lock);
@@ -658,6 +673,7 @@ void dlm_complete_thread(struct dlm_ctxt *dlm);
int dlm_launch_recovery_thread(struct dlm_ctxt *dlm);
void dlm_complete_recovery_thread(struct dlm_ctxt *dlm);
void dlm_wait_for_recovery(struct dlm_ctxt *dlm);
+void dlm_kick_recovery_thread(struct dlm_ctxt *dlm);
int dlm_is_node_dead(struct dlm_ctxt *dlm, u8 node);
int dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout);
@@ -762,6 +778,11 @@ int dlm_request_all_locks_handler(struct o2net_msg *msg, u32 len, void *data);
int dlm_reco_data_done_handler(struct o2net_msg *msg, u32 len, void *data);
int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data);
int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_do_master_requery(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
+ u8 nodenum, u8 *real_master);
+int dlm_lockres_master_requery(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res, u8 *real_master);
+
int dlm_dispatch_assert_master(struct dlm_ctxt *dlm,
struct dlm_lock_resource *res,
diff --git a/fs/ocfs2/dlm/dlmconvert.c b/fs/ocfs2/dlm/dlmconvert.c
index f66e2d818cc..8285228d9e3 100644
--- a/fs/ocfs2/dlm/dlmconvert.c
+++ b/fs/ocfs2/dlm/dlmconvert.c
@@ -284,8 +284,10 @@ enum dlm_status dlmconvert_remote(struct dlm_ctxt *dlm,
if (lock->ml.convert_type != LKM_IVMODE) {
__dlm_print_one_lock_resource(res);
mlog(ML_ERROR, "converting a remote lock that is already "
- "converting! (cookie=%"MLFu64", conv=%d)\n",
- lock->ml.cookie, lock->ml.convert_type);
+ "converting! (cookie=%u:%llu, conv=%d)\n",
+ dlm_get_lock_cookie_node(lock->ml.cookie),
+ dlm_get_lock_cookie_seq(lock->ml.cookie),
+ lock->ml.convert_type);
status = DLM_DENIED;
goto bail;
}
@@ -513,8 +515,9 @@ int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data)
leave:
if (!lock)
mlog(ML_ERROR, "did not find lock to convert on grant queue! "
- "cookie=%"MLFu64"\n",
- cnv->cookie);
+ "cookie=%u:%llu\n",
+ dlm_get_lock_cookie_node(cnv->cookie),
+ dlm_get_lock_cookie_seq(cnv->cookie));
else
dlm_lock_put(lock);
diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c
index 54f61b76ab5..c7eae5d3324 100644
--- a/fs/ocfs2/dlm/dlmdebug.c
+++ b/fs/ocfs2/dlm/dlmdebug.c
@@ -72,8 +72,10 @@ void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
lock = list_entry(iter2, struct dlm_lock, list);
spin_lock(&lock->spinlock);
mlog(ML_NOTICE, " type=%d, conv=%d, node=%u, "
- "cookie=%"MLFu64", ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",
- lock->ml.type, lock->ml.convert_type, lock->ml.node, lock->ml.cookie,
+ "cookie=%u:%llu, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",
+ lock->ml.type, lock->ml.convert_type, lock->ml.node,
+ dlm_get_lock_cookie_node(lock->ml.cookie),
+ dlm_get_lock_cookie_seq(lock->ml.cookie),
list_empty(&lock->ast_list) ? 'y' : 'n',
lock->ast_pending ? 'y' : 'n',
list_empty(&lock->bast_list) ? 'y' : 'n',
@@ -85,8 +87,10 @@ void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
lock = list_entry(iter2, struct dlm_lock, list);
spin_lock(&lock->spinlock);
mlog(ML_NOTICE, " type=%d, conv=%d, node=%u, "
- "cookie=%"MLFu64", ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",
- lock->ml.type, lock->ml.convert_type, lock->ml.node, lock->ml.cookie,
+ "cookie=%u:%llu, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",
+ lock->ml.type, lock->ml.convert_type, lock->ml.node,
+ dlm_get_lock_cookie_node(lock->ml.cookie),
+ dlm_get_lock_cookie_seq(lock->ml.cookie),
list_empty(&lock->ast_list) ? 'y' : 'n',
lock->ast_pending ? 'y' : 'n',
list_empty(&lock->bast_list) ? 'y' : 'n',
@@ -98,8 +102,10 @@ void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
lock = list_entry(iter2, struct dlm_lock, list);
spin_lock(&lock->spinlock);
mlog(ML_NOTICE, " type=%d, conv=%d, node=%u, "
- "cookie=%"MLFu64", ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",
- lock->ml.type, lock->ml.convert_type, lock->ml.node, lock->ml.cookie,
+ "cookie=%u:%llu, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",
+ lock->ml.type, lock->ml.convert_type, lock->ml.node,
+ dlm_get_lock_cookie_node(lock->ml.cookie),
+ dlm_get_lock_cookie_seq(lock->ml.cookie),
list_empty(&lock->ast_list) ? 'y' : 'n',
lock->ast_pending ? 'y' : 'n',
list_empty(&lock->bast_list) ? 'y' : 'n',
diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
index 671d4ff222c..6fea28318d6 100644
--- a/fs/ocfs2/dlm/dlmlock.c
+++ b/fs/ocfs2/dlm/dlmlock.c
@@ -141,13 +141,23 @@ static enum dlm_status dlmlock_master(struct dlm_ctxt *dlm,
res->lockname.len)) {
kick_thread = 1;
call_ast = 1;
+ } else {
+ mlog(0, "%s: returning DLM_NORMAL to "
+ "node %u for reco lock\n", dlm->name,
+ lock->ml.node);
}
} else {
/* for NOQUEUE request, unless we get the
* lock right away, return DLM_NOTQUEUED */
- if (flags & LKM_NOQUEUE)
+ if (flags & LKM_NOQUEUE) {
status = DLM_NOTQUEUED;
- else {
+ if (dlm_is_recovery_lock(res->lockname.name,
+ res->lockname.len)) {
+ mlog(0, "%s: returning NOTQUEUED to "
+ "node %u for reco lock\n", dlm->name,
+ lock->ml.node);
+ }
+ } else {
dlm_lock_get(lock);
list_add_tail(&lock->list, &res->blocked);
kick_thread = 1;
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 847dd3cc4cf..940be4c13b1 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -239,6 +239,8 @@ static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
static int dlm_mark_lockres_migrating(struct dlm_ctxt *dlm,
struct dlm_lock_resource *res,
u8 target);
+static int dlm_pre_master_reco_lockres(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res);
int dlm_is_host_down(int errno)
@@ -677,6 +679,7 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm,
struct dlm_node_iter iter;
unsigned int namelen;
int tries = 0;
+ int bit, wait_on_recovery = 0;
BUG_ON(!lockid);
@@ -762,6 +765,18 @@ lookup:
dlm_init_mle(mle, DLM_MLE_MASTER, dlm, res, NULL, 0);
set_bit(dlm->node_num, mle->maybe_map);
list_add(&mle->list, &dlm->master_list);
+
+ /* still holding the dlm spinlock, check the recovery map
+ * to see if there are any nodes that still need to be
+ * considered. these will not appear in the mle nodemap
+ * but they might own this lockres. wait on them. */
+ bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0);
+ if (bit < O2NM_MAX_NODES) {
+ mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to"
+ "recover before lock mastery can begin\n",
+ dlm->name, namelen, (char *)lockid, bit);
+ wait_on_recovery = 1;
+ }
}
/* at this point there is either a DLM_MLE_BLOCK or a
@@ -779,6 +794,39 @@ lookup:
spin_unlock(&dlm->master_lock);
spin_unlock(&dlm->spinlock);
+ while (wait_on_recovery) {
+ /* any cluster changes that occurred after dropping the
+ * dlm spinlock would be detectable be a change on the mle,
+ * so we only need to clear out the recovery map once. */
+ if (dlm_is_recovery_lock(lockid, namelen)) {
+ mlog(ML_NOTICE, "%s: recovery map is not empty, but "
+ "must master $RECOVERY lock now\n", dlm->name);
+ if (!dlm_pre_master_reco_lockres(dlm, res))
+ wait_on_recovery = 0;
+ else {
+ mlog(0, "%s: waiting 500ms for heartbeat state "
+ "change\n", dlm->name);
+ msleep(500);
+ }
+ continue;
+ }
+
+ dlm_kick_recovery_thread(dlm);
+ msleep(100);
+ dlm_wait_for_recovery(dlm);
+
+ spin_lock(&dlm->spinlock);
+ bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0);
+ if (bit < O2NM_MAX_NODES) {
+ mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to"
+ "recover before lock mastery can begin\n",
+ dlm->name, namelen, (char *)lockid, bit);
+ wait_on_recovery = 1;
+ } else
+ wait_on_recovery = 0;
+ spin_unlock(&dlm->spinlock);
+ }
+
/* must wait for lock to be mastered elsewhere */
if (blocked)
goto wait;
@@ -792,7 +840,15 @@ redo_request:
mlog_errno(ret);
if (mle->master != O2NM_MAX_NODES) {
/* found a master ! */
- break;
+ if (mle->master <= nodenum)
+ break;
+ /* if our master request has not reached the master
+ * yet, keep going until it does. this is how the
+ * master will know that asserts are needed back to
+ * the lower nodes. */
+ mlog(0, "%s:%.*s: requests only up to %u but master "
+ "is %u, keep going\n", dlm->name, namelen,
+ lockid, nodenum, mle->master);
}
}
@@ -860,7 +916,19 @@ recheck:
/* check if another node has already become the owner */
spin_lock(&res->spinlock);
if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN) {
+ mlog(0, "%s:%.*s: owner is suddenly %u\n", dlm->name,
+ res->lockname.len, res->lockname.name, res->owner);
spin_unlock(&res->spinlock);
+ /* this will cause the master to re-assert across
+ * the whole cluster, freeing up mles */
+ ret = dlm_do_master_request(mle, res->owner);
+ if (ret < 0) {
+ /* give recovery a chance to run */
+ mlog(ML_ERROR, "link to %u went down?: %d\n", res->owner, ret);
+ msleep(500);
+ goto recheck;
+ }
+ ret = 0;
goto leave;
}
spin_unlock(&res->spinlock);
@@ -1244,13 +1312,14 @@ int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data)
{
u8 response = DLM_MASTER_RESP_MAYBE;
struct dlm_ctxt *dlm = data;
- struct dlm_lock_resource *res;
+ struct dlm_lock_resource *res = NULL;
struct dlm_master_request *request = (struct dlm_master_request *) msg->buf;
struct dlm_master_list_entry *mle = NULL, *tmpmle = NULL;
char *name;
unsigned int namelen;
int found, ret;
int set_maybe;
+ int dispatch_assert = 0;
if (!dlm_grab(dlm))
return DLM_MASTER_RESP_NO;
@@ -1287,7 +1356,6 @@ way_up_top:
}
if (res->owner == dlm->node_num) {
- u32 flags = DLM_ASSERT_MASTER_MLE_CLEANUP;
spin_unlock(&res->spinlock);
// mlog(0, "this node is the master\n");
response = DLM_MASTER_RESP_YES;
@@ -1300,16 +1368,7 @@ way_up_top:
* caused all nodes up to this one to
* create mles. this node now needs to
* go back and clean those up. */
- mlog(0, "%u is the owner of %.*s, cleaning everyone else\n",
- dlm->node_num, res->lockname.len, res->lockname.name);
- ret = dlm_dispatch_assert_master(dlm, res, 1,
- request->node_idx,
- flags);
- if (ret < 0) {
- mlog(ML_ERROR, "failed to dispatch assert "
- "master work\n");
- response = DLM_MASTER_RESP_ERROR;
- }
+ dispatch_assert = 1;
goto send_response;
} else if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN) {
spin_unlock(&res->spinlock);
@@ -1357,9 +1416,13 @@ way_up_top:
}
} else if (tmpmle->master != DLM_LOCK_RES_OWNER_UNKNOWN) {
set_maybe = 0;
- if (tmpmle->master == dlm->node_num)
+ if (tmpmle->master == dlm->node_num) {
response = DLM_MASTER_RESP_YES;
- else
+ /* this node will be the owner.
+ * go back and clean the mles on any
+ * other nodes */
+ dispatch_assert = 1;
+ } else
response = DLM_MASTER_RESP_NO;
} else {
// mlog(0, "this node is attempting to "
@@ -1398,8 +1461,8 @@ way_up_top:
mle = (struct dlm_master_list_entry *)
kmem_cache_alloc(dlm_mle_cache, GFP_KERNEL);
if (!mle) {
- // bad bad bad... this sucks.
response = DLM_MASTER_RESP_ERROR;
+ mlog_errno(-ENOMEM);
goto send_response;
}
spin_lock(&dlm->spinlock);
@@ -1418,25 +1481,19 @@ way_up_top:
// mlog(0, "mle was found\n");
set_maybe = 1;
spin_lock(&tmpmle->spinlock);
+ if (tmpmle->master == dlm->node_num) {
+ mlog(ML_ERROR, "no lockres, but an mle with this node as master!\n");
+ BUG();
+ }
if (tmpmle->type == DLM_MLE_BLOCK)
response = DLM_MASTER_RESP_NO;
else if (tmpmle->type == DLM_MLE_MIGRATION) {
mlog(0, "migration mle was found (%u->%u)\n",
tmpmle->master, tmpmle->new_master);
- if (tmpmle->master == dlm->node_num) {
- mlog(ML_ERROR, "no lockres, but migration mle "
- "says that this node is master!\n");
- BUG();
- }
/* real master can respond on its own */
response = DLM_MASTER_RESP_NO;
- } else {
- if (tmpmle->master == dlm->node_num) {
- response = DLM_MASTER_RESP_YES;
- set_maybe = 0;
- } else
- response = DLM_MASTER_RESP_MAYBE;
- }
+ } else
+ response = DLM_MASTER_RESP_MAYBE;
if (set_maybe)
set_bit(request->node_idx, tmpmle->maybe_map);
spin_unlock(&tmpmle->spinlock);
@@ -1449,6 +1506,24 @@ way_up_top:
dlm_put_mle(tmpmle);
}
send_response:
+
+ if (dispatch_assert) {
+ if (response != DLM_MASTER_RESP_YES)
+ mlog(ML_ERROR, "invalid response %d\n", response);
+ if (!res) {
+ mlog(ML_ERROR, "bad lockres while trying to assert!\n");
+ BUG();
+ }
+ mlog(0, "%u is the owner of %.*s, cleaning everyone else\n",
+ dlm->node_num, res->lockname.len, res->lockname.name);
+ ret = dlm_dispatch_assert_master(dlm, res, 0, request->node_idx,
+ DLM_ASSERT_MASTER_MLE_CLEANUP);
+ if (ret < 0) {
+ mlog(ML_ERROR, "failed to dispatch assert master work\n");
+ response = DLM_MASTER_RESP_ERROR;
+ }
+ }
+
dlm_put(dlm);
return response;
}
@@ -1471,8 +1546,11 @@ static int dlm_do_assert_master(struct dlm_ctxt *dlm, const char *lockname,
int to, tmpret;
struct dlm_node_iter iter;
int ret = 0;
+ int reassert;
BUG_ON(namelen > O2NM_MAX_NAME_LEN);
+again:
+ reassert = 0;
/* note that if this nodemap is empty, it returns 0 */
dlm_node_iter_init(nodemap, &iter);
@@ -1504,9 +1582,17 @@ static int dlm_do_assert_master(struct dlm_ctxt *dlm, const char *lockname,
"got %d.\n", namelen, lockname, to, r);
dlm_dump_lock_resources(dlm);
BUG();
+ } else if (r == EAGAIN) {
+ mlog(0, "%.*s: node %u create mles on other "
+ "nodes and requests a re-assert\n",
+ namelen, lockname, to);
+ reassert = 1;
}
}
+ if (reassert)
+ goto again;
+
return ret;
}
@@ -1528,6 +1614,8 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data)
char *name;
unsigned int namelen;
u32 flags;
+ int master_request = 0;
+ int ret = 0;
if (!dlm_grab(dlm))
return 0;
@@ -1642,11 +1730,22 @@ ok:
// mlog(0, "woo! got an assert_master from node %u!\n",
// assert->node_idx);
if (mle) {
- int extra_ref;
+ int extra_ref = 0;
+ int nn = -1;
spin_lock(&mle->spinlock);
- extra_ref = !!(mle->type == DLM_MLE_BLOCK
- || mle->type == DLM_MLE_MIGRATION);
+ if (mle->type == DLM_MLE_BLOCK || mle->type == DLM_MLE_MIGRATION)
+ extra_ref = 1;
+ else {
+ /* MASTER mle: if any bits set in the response map
+ * then the calling node needs to re-assert to clear
+ * up nodes that this node contacted */
+ while ((nn = find_next_bit (mle->response_map, O2NM_MAX_NODES,
+ nn+1)) < O2NM_MAX_NODES) {
+ if (nn != dlm->node_num && nn != assert->node_idx)
+ master_request = 1;
+ }
+ }
mle->master = assert->node_idx;
atomic_set(&mle->woken, 1);
wake_up(&mle->wq);
@@ -1677,10 +1776,15 @@ ok:
}
done:
+ ret = 0;
if (res)
dlm_lockres_put(res);
dlm_put(dlm);
- return 0;
+ if (master_request) {
+ mlog(0, "need to tell master to reassert\n");
+ ret = EAGAIN; // positive. negative would shoot down the node.
+ }
+ return ret;
kill:
/* kill the caller! */
@@ -1713,6 +1817,10 @@ int dlm_dispatch_assert_master(struct dlm_ctxt *dlm,
item->u.am.request_from = request_from;
item->u.am.flags = flags;
+ if (ignore_higher)
+ mlog(0, "IGNORE HIGHER: %.*s\n", res->lockname.len,
+ res->lockname.name);
+
spin_lock(&dlm->work_lock);
list_add_tail(&item->list, &dlm->work_list);
spin_unlock(&dlm->work_lock);
@@ -1775,6 +1883,61 @@ static void dlm_assert_master_worker(struct dlm_work_item *item, void *data)
mlog(0, "finished with dlm_assert_master_worker\n");
}
+/* SPECIAL CASE for the $RECOVERY lock used by the recovery thread.
+ * We cannot wait for node recovery to complete to begin mastering this
+ * lockres because this lockres is used to kick off recovery! ;-)
+ * So, do a pre-check on all living nodes to see if any of those nodes
+ * think that $RECOVERY is currently mastered by a dead node. If so,
+ * we wait a short time to allow that node to get notified by its own
+ * heartbeat stack, then check again. All $RECOVERY lock resources
+ * mastered by dead nodes are purged when the hearbeat callback is
+ * fired, so we can know for sure that it is safe to continue once
+ * the node returns a live node or no node. */
+static int dlm_pre_master_reco_lockres(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res)
+{
+ struct dlm_node_iter iter;
+ int nodenum;
+ int ret = 0;
+ u8 master = DLM_LOCK_RES_OWNER_UNKNOWN;
+
+ spin_lock(&dlm->spinlock);
+ dlm_node_iter_init(dlm->domain_map, &iter);
+ spin_unlock(&dlm->spinlock);
+
+ while ((nodenum = dlm_node_iter_next(&iter)) >= 0) {
+ /* do not send to self */
+ if (nodenum == dlm->node_num)
+ continue;
+ ret = dlm_do_master_requery(dlm, res, nodenum, &master);
+ if (ret < 0) {
+ mlog_errno(ret);
+ if (!dlm_is_host_down(ret))
+ BUG();
+ /* host is down, so answer for that node would be
+ * DLM_LOCK_RES_OWNER_UNKNOWN. continue. */
+ }
+
+ if (master != DLM_LOCK_RES_OWNER_UNKNOWN) {
+ /* check to see if this master is in the recovery map */
+ spin_lock(&dlm->spinlock);
+ if (test_bit(master, dlm->recovery_map)) {
+ mlog(ML_NOTICE, "%s: node %u has not seen "
+ "node %u go down yet, and thinks the "
+ "dead node is mastering the recovery "
+ "lock. must wait.\n", dlm->name,
+ nodenum, master);
+ ret = -EAGAIN;
+ }
+ spin_unlock(&dlm->spinlock);
+ mlog(0, "%s: reco lock master is %u\n", dlm->name,
+ master);
+ break;
+ }
+ }
+ return ret;
+}
+
/*
* DLM_MIGRATE_LOCKRES
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 1e232000f3f..805cbabac05 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -58,7 +58,7 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node);
static int dlm_recovery_thread(void *data);
void dlm_complete_recovery_thread(struct dlm_ctxt *dlm);
int dlm_launch_recovery_thread(struct dlm_ctxt *dlm);
-static void dlm_kick_recovery_thread(struct dlm_ctxt *dlm);
+void dlm_kick_recovery_thread(struct dlm_ctxt *dlm);
static int dlm_do_recovery(struct dlm_ctxt *dlm);
static int dlm_pick_recovery_master(struct dlm_ctxt *dlm);
@@ -78,15 +78,9 @@ static int dlm_send_mig_lockres_msg(struct dlm_ctxt *dlm,
u8 send_to,
struct dlm_lock_resource *res,
int total_locks);
-static int dlm_lockres_master_requery(struct dlm_ctxt *dlm,
- struct dlm_lock_resource *res,
- u8 *real_master);
static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
struct dlm_lock_resource *res,
struct dlm_migratable_lockres *mres);
-static int dlm_do_master_requery(struct dlm_ctxt *dlm,
- struct dlm_lock_resource *res,
- u8 nodenum, u8 *real_master);
static int dlm_send_finalize_reco_message(struct dlm_ctxt *dlm);
static int dlm_send_all_done_msg(struct dlm_ctxt *dlm,
u8 dead_node, u8 send_to);
@@ -165,7 +159,7 @@ void dlm_dispatch_work(void *data)
* RECOVERY THREAD
*/
-static void dlm_kick_recovery_thread(struct dlm_ctxt *dlm)
+void dlm_kick_recovery_thread(struct dlm_ctxt *dlm)
{
/* wake the recovery thread
* this will wake the reco thread in one of three places
@@ -750,10 +744,12 @@ static void dlm_request_all_locks_worker(struct dlm_work_item *item, void *data)
dlm->name, dlm->reco.dead_node, dlm->reco.new_master,
dead_node, reco_master);
mlog(ML_ERROR, "%s: name=%.*s master=%u locks=%u/%u flags=%u "
- "entry[0]={c=%"MLFu64",l=%u,f=%u,t=%d,ct=%d,hb=%d,n=%u}\n",
+ "entry[0]={c=%u:%llu,l=%u,f=%u,t=%d,ct=%d,hb=%d,n=%u}\n",
dlm->name, mres->lockname_len, mres->lockname, mres->master,
mres->num_locks, mres->total_locks, mres->flags,
- mres->ml[0].cookie, mres->ml[0].list, mres->ml[0].flags,
+ dlm_get_lock_cookie_node(mres->ml[0].cookie),
+ dlm_get_lock_cookie_seq(mres->ml[0].cookie),
+ mres->ml[0].list, mres->ml[0].flags,
mres->ml[0].type, mres->ml[0].convert_type,
mres->ml[0].highest_blocked, mres->ml[0].node);
BUG();
@@ -1316,9 +1312,8 @@ leave:
-static int dlm_lockres_master_requery(struct dlm_ctxt *dlm,
- struct dlm_lock_resource *res,
- u8 *real_master)
+int dlm_lockres_master_requery(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res, u8 *real_master)
{
struct dlm_node_iter iter;
int nodenum;
@@ -1360,8 +1355,10 @@ static int dlm_lockres_master_requery(struct dlm_ctxt *dlm,
ret = dlm_do_master_requery(dlm, res, nodenum, real_master);
if (ret < 0) {
mlog_errno(ret);
- BUG();
- /* TODO: need to figure a way to restart this */
+ if (!dlm_is_host_down(ret))
+ BUG();
+ /* host is down, so answer for that node would be
+ * DLM_LOCK_RES_OWNER_UNKNOWN. continue. */
}
if (*real_master != DLM_LOCK_RES_OWNER_UNKNOWN) {
mlog(0, "lock master is %u\n", *real_master);
@@ -1372,9 +1369,8 @@ static int dlm_lockres_master_requery(struct dlm_ctxt *dlm,
}
-static int dlm_do_master_requery(struct dlm_ctxt *dlm,
- struct dlm_lock_resource *res,
- u8 nodenum, u8 *real_master)
+int dlm_do_master_requery(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
+ u8 nodenum, u8 *real_master)
{
int ret = -EINVAL;
struct dlm_master_requery req;
@@ -1519,9 +1515,11 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
/* lock is always created locally first, and
* destroyed locally last. it must be on the list */
if (!lock) {
+ u64 c = ml->cookie;
mlog(ML_ERROR, "could not find local lock "
- "with cookie %"MLFu64"!\n",
- ml->cookie);
+ "with cookie %u:%llu!\n",
+ dlm_get_lock_cookie_node(c),
+ dlm_get_lock_cookie_seq(c));
BUG();
}
BUG_ON(lock->ml.node != ml->node);
@@ -1739,6 +1737,13 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm,
} else
continue;
+ if (!list_empty(&res->recovering)) {
+ mlog(0, "%s:%.*s: lockres was "
+ "marked RECOVERING, owner=%u\n",
+ dlm->name, res->lockname.len,
+ res->lockname.name, res->owner);
+ list_del_init(&res->recovering);
+ }
spin_lock(&res->spinlock);
dlm_change_lockres_owner(dlm, res, new_master);
res->state &= ~DLM_LOCK_RES_RECOVERING;
@@ -2258,7 +2263,10 @@ int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data)
mlog(0, "%u not in domain/live_nodes map "
"so setting it in reco map manually\n",
br->dead_node);
- set_bit(br->dead_node, dlm->recovery_map);
+ /* force the recovery cleanup in __dlm_hb_node_down
+ * both of these will be cleared in a moment */
+ set_bit(br->dead_node, dlm->domain_map);
+ set_bit(br->dead_node, dlm->live_nodes_map);
__dlm_hb_node_down(dlm, br->dead_node);
}
spin_unlock(&dlm->spinlock);
diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c
index c95f08d2e92..7b1a2754267 100644
--- a/fs/ocfs2/dlm/dlmunlock.c
+++ b/fs/ocfs2/dlm/dlmunlock.c
@@ -244,8 +244,10 @@ leave:
if (actions & DLM_UNLOCK_FREE_LOCK) {
/* this should always be coupled with list removal */
BUG_ON(!(actions & DLM_UNLOCK_REMOVE_LOCK));
- mlog(0, "lock %"MLFu64" should be gone now! refs=%d\n",
- lock->ml.cookie, atomic_read(&lock->lock_refs.refcount)-1);
+ mlog(0, "lock %u:%llu should be gone now! refs=%d\n",
+ dlm_get_lock_cookie_node(lock->ml.cookie),
+ dlm_get_lock_cookie_seq(lock->ml.cookie),
+ atomic_read(&lock->lock_refs.refcount)-1);
dlm_lock_put(lock);
}
if (actions & DLM_UNLOCK_CALL_AST)
@@ -493,8 +495,9 @@ int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data)
not_found:
if (!found)
mlog(ML_ERROR, "failed to find lock to unlock! "
- "cookie=%"MLFu64"\n",
- unlock->cookie);
+ "cookie=%u:%llu\n",
+ dlm_get_lock_cookie_node(unlock->cookie),
+ dlm_get_lock_cookie_seq(unlock->cookie));
else {
/* send the lksb->status back to the other node */
status = lksb->status;
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index e971ec2f840..64cd52860c8 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -231,9 +231,9 @@ static void ocfs2_build_lock_name(enum ocfs2_lock_type type,
BUG_ON(type >= OCFS2_NUM_LOCK_TYPES);
- len = snprintf(name, OCFS2_LOCK_ID_MAX_LEN, "%c%s%016"MLFx64"%08x",
- ocfs2_lock_type_char(type), OCFS2_LOCK_ID_PAD, blkno,
- generation);
+ len = snprintf(name, OCFS2_LOCK_ID_MAX_LEN, "%c%s%016llx%08x",
+ ocfs2_lock_type_char(type), OCFS2_LOCK_ID_PAD,
+ (long long)blkno, generation);
BUG_ON(len != (OCFS2_LOCK_ID_MAX_LEN - 1));
@@ -533,8 +533,8 @@ static void ocfs2_inode_ast_func(void *opaque)
inode = ocfs2_lock_res_inode(lockres);
- mlog(0, "AST fired for inode %"MLFu64", l_action = %u, type = %s\n",
- OCFS2_I(inode)->ip_blkno, lockres->l_action,
+ mlog(0, "AST fired for inode %llu, l_action = %u, type = %s\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, lockres->l_action,
ocfs2_lock_type_string(lockres->l_type));
BUG_ON(!ocfs2_is_inode_lock(lockres));
@@ -544,8 +544,8 @@ static void ocfs2_inode_ast_func(void *opaque)
lksb = &(lockres->l_lksb);
if (lksb->status != DLM_NORMAL) {
mlog(ML_ERROR, "ocfs2_inode_ast_func: lksb status value of %u "
- "on inode %"MLFu64"\n", lksb->status,
- OCFS2_I(inode)->ip_blkno);
+ "on inode %llu\n", lksb->status,
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
spin_unlock_irqrestore(&lockres->l_lock, flags);
mlog_exit_void();
return;
@@ -646,10 +646,9 @@ static void ocfs2_inode_bast_func(void *opaque, int level)
inode = ocfs2_lock_res_inode(lockres);
osb = OCFS2_SB(inode->i_sb);
- mlog(0, "BAST fired for inode %"MLFu64", blocking = %d, level = %d "
- "type = %s\n", OCFS2_I(inode)->ip_blkno, level,
- lockres->l_level,
- ocfs2_lock_type_string(lockres->l_type));
+ mlog(0, "BAST fired for inode %llu, blocking %d, level %d type %s\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, level,
+ lockres->l_level, ocfs2_lock_type_string(lockres->l_type));
ocfs2_generic_bast_func(osb, lockres, level);
@@ -1104,7 +1103,7 @@ int ocfs2_create_new_inode_locks(struct inode *inode)
mlog_entry_void();
- mlog(0, "Inode %"MLFu64"\n", OCFS2_I(inode)->ip_blkno);
+ mlog(0, "Inode %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno);
/* NOTE: That we don't increment any of the holder counts, nor
* do we add anything to a journal handle. Since this is
@@ -1149,8 +1148,8 @@ int ocfs2_rw_lock(struct inode *inode, int write)
mlog_entry_void();
- mlog(0, "inode %"MLFu64" take %s RW lock\n",
- OCFS2_I(inode)->ip_blkno,
+ mlog(0, "inode %llu take %s RW lock\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
write ? "EXMODE" : "PRMODE");
lockres = &OCFS2_I(inode)->ip_rw_lockres;
@@ -1173,8 +1172,8 @@ void ocfs2_rw_unlock(struct inode *inode, int write)
mlog_entry_void();
- mlog(0, "inode %"MLFu64" drop %s RW lock\n",
- OCFS2_I(inode)->ip_blkno,
+ mlog(0, "inode %llu drop %s RW lock\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
write ? "EXMODE" : "PRMODE");
ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
@@ -1193,8 +1192,8 @@ int ocfs2_data_lock_full(struct inode *inode,
mlog_entry_void();
- mlog(0, "inode %"MLFu64" take %s DATA lock\n",
- OCFS2_I(inode)->ip_blkno,
+ mlog(0, "inode %llu take %s DATA lock\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
write ? "EXMODE" : "PRMODE");
/* We'll allow faking a readonly data lock for
@@ -1278,8 +1277,8 @@ void ocfs2_data_unlock(struct inode *inode,
mlog_entry_void();
- mlog(0, "inode %"MLFu64" drop %s DATA lock\n",
- OCFS2_I(inode)->ip_blkno,
+ mlog(0, "inode %llu drop %s DATA lock\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
write ? "EXMODE" : "PRMODE");
if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)))
@@ -1462,9 +1461,9 @@ static int ocfs2_meta_lock_update(struct inode *inode,
spin_lock(&oi->ip_lock);
if (oi->ip_flags & OCFS2_INODE_DELETED) {
- mlog(0, "Orphaned inode %"MLFu64" was deleted while we "
+ mlog(0, "Orphaned inode %llu was deleted while we "
"were waiting on a lock. ip_flags = 0x%x\n",
- oi->ip_blkno, oi->ip_flags);
+ (unsigned long long)oi->ip_blkno, oi->ip_flags);
spin_unlock(&oi->ip_lock);
status = -ENOENT;
goto bail;
@@ -1485,8 +1484,8 @@ static int ocfs2_meta_lock_update(struct inode *inode,
ocfs2_extent_map_trunc(inode, 0);
if (ocfs2_meta_lvb_is_trustable(lockres)) {
- mlog(0, "Trusting LVB on inode %"MLFu64"\n",
- oi->ip_blkno);
+ mlog(0, "Trusting LVB on inode %llu\n",
+ (unsigned long long)oi->ip_blkno);
ocfs2_refresh_inode_from_lvb(inode);
} else {
/* Boo, we have to go to disk. */
@@ -1514,15 +1513,16 @@ static int ocfs2_meta_lock_update(struct inode *inode,
}
mlog_bug_on_msg(inode->i_generation !=
le32_to_cpu(fe->i_generation),
- "Invalid dinode %"MLFu64" disk generation: %u "
+ "Invalid dinode %llu disk generation: %u "
"inode->i_generation: %u\n",
- oi->ip_blkno, le32_to_cpu(fe->i_generation),
+ (unsigned long long)oi->ip_blkno,
+ le32_to_cpu(fe->i_generation),
inode->i_generation);
mlog_bug_on_msg(le64_to_cpu(fe->i_dtime) ||
!(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL)),
- "Stale dinode %"MLFu64" dtime: %"MLFu64" "
- "flags: 0x%x\n", oi->ip_blkno,
- le64_to_cpu(fe->i_dtime),
+ "Stale dinode %llu dtime: %llu flags: 0x%x\n",
+ (unsigned long long)oi->ip_blkno,
+ (unsigned long long)le64_to_cpu(fe->i_dtime),
le32_to_cpu(fe->i_flags));
ocfs2_refresh_inode(inode, fe);
@@ -1581,8 +1581,8 @@ int ocfs2_meta_lock_full(struct inode *inode,
mlog_entry_void();
- mlog(0, "inode %"MLFu64", take %s META lock\n",
- OCFS2_I(inode)->ip_blkno,
+ mlog(0, "inode %llu, take %s META lock\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
ex ? "EXMODE" : "PRMODE");
status = 0;
@@ -1716,8 +1716,8 @@ void ocfs2_meta_unlock(struct inode *inode,
mlog_entry_void();
- mlog(0, "inode %"MLFu64" drop %s META lock\n",
- OCFS2_I(inode)->ip_blkno,
+ mlog(0, "inode %llu drop %s META lock\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
ex ? "EXMODE" : "PRMODE");
if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)))
@@ -2017,7 +2017,7 @@ out:
return ret;
}
-static struct file_operations ocfs2_dlm_debug_fops = {
+static const struct file_operations ocfs2_dlm_debug_fops = {
.open = ocfs2_dlm_debug_open,
.release = ocfs2_dlm_debug_release,
.read = seq_read,
@@ -2686,8 +2686,8 @@ static void ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
mapping = inode->i_mapping;
if (filemap_fdatawrite(mapping)) {
- mlog(ML_ERROR, "Could not sync inode %"MLFu64" for downconvert!",
- OCFS2_I(inode)->ip_blkno);
+ mlog(ML_ERROR, "Could not sync inode %llu for downconvert!",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
}
sync_mapping_buffers(mapping);
if (blocking == LKM_EXMODE) {
@@ -2717,7 +2717,8 @@ int ocfs2_unblock_data(struct ocfs2_lock_res *lockres,
inode = ocfs2_lock_res_inode(lockres);
osb = OCFS2_SB(inode->i_sb);
- mlog(0, "unblock inode %"MLFu64"\n", OCFS2_I(inode)->ip_blkno);
+ mlog(0, "unblock inode %llu\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
status = ocfs2_generic_unblock_lock(osb,
lockres,
@@ -2726,8 +2727,8 @@ int ocfs2_unblock_data(struct ocfs2_lock_res *lockres,
if (status < 0)
mlog_errno(status);
- mlog(0, "inode %"MLFu64", requeue = %d\n",
- OCFS2_I(inode)->ip_blkno, *requeue);
+ mlog(0, "inode %llu, requeue = %d\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, *requeue);
mlog_exit(status);
return status;
@@ -2767,14 +2768,15 @@ int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres,
inode = ocfs2_lock_res_inode(lockres);
- mlog(0, "unblock inode %"MLFu64"\n", OCFS2_I(inode)->ip_blkno);
+ mlog(0, "unblock inode %llu\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
status = ocfs2_do_unblock_meta(inode, requeue);
if (status < 0)
mlog_errno(status);
- mlog(0, "inode %"MLFu64", requeue = %d\n",
- OCFS2_I(inode)->ip_blkno, *requeue);
+ mlog(0, "inode %llu, requeue = %d\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, *requeue);
mlog_exit(status);
return status;
@@ -2893,12 +2895,13 @@ void ocfs2_dump_meta_lvb_info(u64 level,
lockres->l_name, function, line);
mlog(level, "version: %u, clusters: %u\n",
be32_to_cpu(lvb->lvb_version), be32_to_cpu(lvb->lvb_iclusters));
- mlog(level, "size: %"MLFu64", uid %u, gid %u, mode 0x%x\n",
- be64_to_cpu(lvb->lvb_isize), be32_to_cpu(lvb->lvb_iuid),
- be32_to_cpu(lvb->lvb_igid), be16_to_cpu(lvb->lvb_imode));
- mlog(level, "nlink %u, atime_packed 0x%"MLFx64", "
- "ctime_packed 0x%"MLFx64", mtime_packed 0x%"MLFx64"\n",
- be16_to_cpu(lvb->lvb_inlink), be64_to_cpu(lvb->lvb_iatime_packed),
- be64_to_cpu(lvb->lvb_ictime_packed),
- be64_to_cpu(lvb->lvb_imtime_packed));
+ mlog(level, "size: %llu, uid %u, gid %u, mode 0x%x\n",
+ (unsigned long long)be64_to_cpu(lvb->lvb_isize),
+ be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid),
+ be16_to_cpu(lvb->lvb_imode));
+ mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, "
+ "mtime_packed 0x%llx\n", be16_to_cpu(lvb->lvb_inlink),
+ (long long)be64_to_cpu(lvb->lvb_iatime_packed),
+ (long long)be64_to_cpu(lvb->lvb_ictime_packed),
+ (long long)be64_to_cpu(lvb->lvb_imtime_packed));
}
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c
index 5810160d92a..ec55ab3c121 100644
--- a/fs/ocfs2/export.c
+++ b/fs/ocfs2/export.c
@@ -95,8 +95,8 @@ static struct dentry *ocfs2_get_parent(struct dentry *child)
mlog_entry("(0x%p, '%.*s')\n", child,
child->d_name.len, child->d_name.name);
- mlog(0, "find parent of directory %"MLFu64"\n",
- OCFS2_I(dir)->ip_blkno);
+ mlog(0, "find parent of directory %llu\n",
+ (unsigned long long)OCFS2_I(dir)->ip_blkno);
status = ocfs2_meta_lock(dir, NULL, NULL, 0);
if (status < 0) {
@@ -115,7 +115,8 @@ static struct dentry *ocfs2_get_parent(struct dentry *child)
inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno);
if (IS_ERR(inode)) {
- mlog(ML_ERROR, "Unable to create inode %"MLFu64"\n", blkno);
+ mlog(ML_ERROR, "Unable to create inode %llu\n",
+ (unsigned long long)blkno);
parent = ERR_PTR(-EACCES);
goto bail_unlock;
}
@@ -160,8 +161,8 @@ static int ocfs2_encode_fh(struct dentry *dentry, __be32 *fh, int *max_len,
blkno = OCFS2_I(inode)->ip_blkno;
generation = inode->i_generation;
- mlog(0, "Encoding fh: blkno: %"MLFu64", generation: %u\n",
- blkno, generation);
+ mlog(0, "Encoding fh: blkno: %llu, generation: %u\n",
+ (unsigned long long)blkno, generation);
len = 3;
fh[0] = cpu_to_le32((u32)(blkno >> 32));
@@ -186,8 +187,8 @@ static int ocfs2_encode_fh(struct dentry *dentry, __be32 *fh, int *max_len,
len = 6;
type = 2;
- mlog(0, "Encoding parent: blkno: %"MLFu64", generation: %u\n",
- blkno, generation);
+ mlog(0, "Encoding parent: blkno: %llu, generation: %u\n",
+ (unsigned long long)blkno, generation);
}
*max_len = len;
@@ -220,16 +221,17 @@ static struct dentry *ocfs2_decode_fh(struct super_block *sb, __be32 *fh,
parent.ih_blkno |= (u64)le32_to_cpu(fh[4]);
parent.ih_generation = le32_to_cpu(fh[5]);
- mlog(0, "Decoding parent: blkno: %"MLFu64", generation: %u\n",
- parent.ih_blkno, parent.ih_generation);
+ mlog(0, "Decoding parent: blkno: %llu, generation: %u\n",
+ (unsigned long long)parent.ih_blkno,
+ parent.ih_generation);
}
handle.ih_blkno = (u64)le32_to_cpu(fh[0]) << 32;
handle.ih_blkno |= (u64)le32_to_cpu(fh[1]);
handle.ih_generation = le32_to_cpu(fh[2]);
- mlog(0, "Encoding fh: blkno: %"MLFu64", generation: %u\n",
- handle.ih_blkno, handle.ih_generation);
+ mlog(0, "Encoding fh: blkno: %llu, generation: %u\n",
+ (unsigned long long)handle.ih_blkno, handle.ih_generation);
ret = ocfs2_export_ops.find_exported_dentry(sb, &handle, &parent,
acceptable, context);
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index e6f207eebab..4601fc256f1 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -182,10 +182,10 @@ static int ocfs2_extent_map_find_leaf(struct inode *inode,
if (rec_end > OCFS2_I(inode)->ip_clusters) {
mlog_errno(ret);
ocfs2_error(inode->i_sb,
- "Extent %d at e_blkno %"MLFu64" of inode %"MLFu64" goes past ip_clusters of %u\n",
+ "Extent %d at e_blkno %llu of inode %llu goes past ip_clusters of %u\n",
i,
- le64_to_cpu(rec->e_blkno),
- OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)le64_to_cpu(rec->e_blkno),
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
OCFS2_I(inode)->ip_clusters);
goto out_free;
}
@@ -233,11 +233,11 @@ static int ocfs2_extent_map_find_leaf(struct inode *inode,
if (blkno) {
mlog_errno(ret);
ocfs2_error(inode->i_sb,
- "Multiple extents for (cpos = %u, clusters = %u) on inode %"MLFu64"; e_blkno %"MLFu64" and rec %d at e_blkno %"MLFu64"\n",
+ "Multiple extents for (cpos = %u, clusters = %u) on inode %llu; e_blkno %llu and rec %d at e_blkno %llu\n",
cpos, clusters,
- OCFS2_I(inode)->ip_blkno,
- blkno, i,
- le64_to_cpu(rec->e_blkno));
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)blkno, i,
+ (unsigned long long)le64_to_cpu(rec->e_blkno));
goto out_free;
}
@@ -251,9 +251,9 @@ static int ocfs2_extent_map_find_leaf(struct inode *inode,
ret = -EBADR;
if (!blkno) {
ocfs2_error(inode->i_sb,
- "No record found for (cpos = %u, clusters = %u) on inode %"MLFu64"\n",
+ "No record found for (cpos = %u, clusters = %u) on inode %llu\n",
cpos, clusters,
- OCFS2_I(inode)->ip_blkno);
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
mlog_errno(ret);
goto out_free;
}
@@ -288,10 +288,10 @@ static int ocfs2_extent_map_find_leaf(struct inode *inode,
ret = -EBADR;
mlog_errno(ret);
ocfs2_error(inode->i_sb,
- "Extent %d at e_blkno %"MLFu64" of inode %"MLFu64" goes past ip_clusters of %u\n",
+ "Extent %d at e_blkno %llu of inode %llu goes past ip_clusters of %u\n",
i,
- le64_to_cpu(rec->e_blkno),
- OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)le64_to_cpu(rec->e_blkno),
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
OCFS2_I(inode)->ip_clusters);
return ret;
}
@@ -557,9 +557,9 @@ static int ocfs2_extent_map_insert(struct inode *inode,
ret = -EBADR;
mlog_errno(ret);
ocfs2_error(inode->i_sb,
- "Zero e_clusters on non-tail extent record at e_blkno %"MLFu64" on inode %"MLFu64"\n",
- le64_to_cpu(rec->e_blkno),
- OCFS2_I(inode)->ip_blkno);
+ "Zero e_clusters on non-tail extent record at e_blkno %llu on inode %llu\n",
+ (unsigned long long)le64_to_cpu(rec->e_blkno),
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
return ret;
}
@@ -660,10 +660,10 @@ int ocfs2_extent_map_append(struct inode *inode,
mlog_bug_on_msg((le32_to_cpu(rec->e_cpos) +
le32_to_cpu(rec->e_clusters)) !=
(em->em_clusters + new_clusters),
- "Inode %"MLFu64":\n"
+ "Inode %llu:\n"
"rec->e_cpos = %u + rec->e_clusters = %u = %u\n"
"em->em_clusters = %u + new_clusters = %u = %u\n",
- OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
le32_to_cpu(rec->e_cpos), le32_to_cpu(rec->e_clusters),
le32_to_cpu(rec->e_cpos) + le32_to_cpu(rec->e_clusters),
em->em_clusters, new_clusters,
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 8a4048b55fd..34e903a6a46 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -220,8 +220,9 @@ static int ocfs2_truncate_file(struct inode *inode,
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_truncate_context *tc = NULL;
- mlog_entry("(inode = %"MLFu64", new_i_size = %"MLFu64"\n",
- OCFS2_I(inode)->ip_blkno, new_i_size);
+ mlog_entry("(inode = %llu, new_i_size = %llu\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)new_i_size);
truncate_inode_pages(inode->i_mapping, new_i_size);
@@ -233,23 +234,26 @@ static int ocfs2_truncate_file(struct inode *inode,
}
mlog_bug_on_msg(le64_to_cpu(fe->i_size) != i_size_read(inode),
- "Inode %"MLFu64", inode i_size = %lld != di "
- "i_size = %"MLFu64", i_flags = 0x%x\n",
- OCFS2_I(inode)->ip_blkno,
+ "Inode %llu, inode i_size = %lld != di "
+ "i_size = %llu, i_flags = 0x%x\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
i_size_read(inode),
- le64_to_cpu(fe->i_size), le32_to_cpu(fe->i_flags));
+ (unsigned long long)le64_to_cpu(fe->i_size),
+ le32_to_cpu(fe->i_flags));
if (new_i_size > le64_to_cpu(fe->i_size)) {
- mlog(0, "asked to truncate file with size (%"MLFu64") "
- "to size (%"MLFu64")!\n",
- le64_to_cpu(fe->i_size), new_i_size);
+ mlog(0, "asked to truncate file with size (%llu) to size (%llu)!\n",
+ (unsigned long long)le64_to_cpu(fe->i_size),
+ (unsigned long long)new_i_size);
status = -EINVAL;
mlog_errno(status);
goto bail;
}
- mlog(0, "inode %"MLFu64", i_size = %"MLFu64", new_i_size = %"MLFu64"\n",
- le64_to_cpu(fe->i_blkno), le64_to_cpu(fe->i_size), new_i_size);
+ mlog(0, "inode %llu, i_size = %llu, new_i_size = %llu\n",
+ (unsigned long long)le64_to_cpu(fe->i_blkno),
+ (unsigned long long)le64_to_cpu(fe->i_size),
+ (unsigned long long)new_i_size);
/* lets handle the simple truncate cases before doing any more
* cluster locking. */
@@ -378,8 +382,8 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
}
block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
- mlog(0, "Allocating %u clusters at block %u for inode %"MLFu64"\n",
- num_bits, bit_off, OCFS2_I(inode)->ip_blkno);
+ mlog(0, "Allocating %u clusters at block %u for inode %llu\n",
+ num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
status = ocfs2_insert_extent(osb, handle, inode, fe_bh, block,
num_bits, meta_ac);
if (status < 0) {
@@ -449,9 +453,9 @@ static int ocfs2_extend_allocation(struct inode *inode,
restart_all:
BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters);
- mlog(0, "extend inode %"MLFu64", i_size = %lld, fe->i_clusters = %u, "
+ mlog(0, "extend inode %llu, i_size = %lld, fe->i_clusters = %u, "
"clusters_to_add = %u\n",
- OCFS2_I(inode)->ip_blkno, i_size_read(inode),
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, i_size_read(inode),
fe->i_clusters, clusters_to_add);
handle = ocfs2_alloc_handle(osb);
@@ -569,8 +573,8 @@ restarted_transaction:
}
}
- mlog(0, "fe: i_clusters = %u, i_size=%"MLFu64"\n",
- fe->i_clusters, fe->i_size);
+ mlog(0, "fe: i_clusters = %u, i_size=%llu\n",
+ fe->i_clusters, (unsigned long long)fe->i_size);
mlog(0, "inode: ip_clusters=%u, i_size=%lld\n",
OCFS2_I(inode)->ip_clusters, i_size_read(inode));
@@ -865,8 +869,8 @@ static int ocfs2_write_remove_suid(struct inode *inode)
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_dinode *di;
- mlog_entry("(Inode %"MLFu64", mode 0%o)\n", oi->ip_blkno,
- inode->i_mode);
+ mlog_entry("(Inode %llu, mode 0%o)\n",
+ (unsigned long long)oi->ip_blkno, inode->i_mode);
handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS);
if (handle == NULL) {
@@ -1172,7 +1176,7 @@ struct inode_operations ocfs2_special_file_iops = {
.getattr = ocfs2_getattr,
};
-struct file_operations ocfs2_fops = {
+const struct file_operations ocfs2_fops = {
.read = do_sync_read,
.write = do_sync_write,
.sendfile = generic_file_sendfile,
@@ -1184,7 +1188,7 @@ struct file_operations ocfs2_fops = {
.aio_write = ocfs2_file_aio_write,
};
-struct file_operations ocfs2_dops = {
+const struct file_operations ocfs2_dops = {
.read = generic_read_dir,
.readdir = ocfs2_readdir,
.fsync = ocfs2_sync_file,
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index a5ea33b2406..740c9e7ca59 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -26,8 +26,8 @@
#ifndef OCFS2_FILE_H
#define OCFS2_FILE_H
-extern struct file_operations ocfs2_fops;
-extern struct file_operations ocfs2_dops;
+extern const struct file_operations ocfs2_fops;
+extern const struct file_operations ocfs2_dops;
extern struct inode_operations ocfs2_file_iops;
extern struct inode_operations ocfs2_special_file_iops;
struct ocfs2_alloc_context;
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index 315472a5c19..327a5b7b86e 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -95,7 +95,7 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno)
struct super_block *sb = osb->sb;
struct ocfs2_find_inode_args args;
- mlog_entry("(blkno = %"MLFu64")\n", blkno);
+ mlog_entry("(blkno = %llu)\n", (unsigned long long)blkno);
/* Ok. By now we've either got the offsets passed to us by the
* caller, or we just pulled them off the bh. Lets do some
@@ -134,8 +134,8 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno)
bail:
if (!IS_ERR(inode)) {
- mlog(0, "returning inode with number %"MLFu64"\n",
- OCFS2_I(inode)->ip_blkno);
+ mlog(0, "returning inode with number %llu\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
mlog_exit_ptr(inode);
} else
mlog_errno(PTR_ERR(inode));
@@ -219,7 +219,8 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
struct ocfs2_super *osb;
int status = -EINVAL;
- mlog_entry("(0x%p, size:%"MLFu64")\n", inode, fe->i_size);
+ mlog_entry("(0x%p, size:%llu)\n", inode,
+ (unsigned long long)fe->i_size);
sb = inode->i_sb;
osb = OCFS2_SB(sb);
@@ -228,9 +229,10 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
* today. change if needed. */
if (!OCFS2_IS_VALID_DINODE(fe) ||
!(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
- mlog(ML_ERROR, "Invalid dinode: i_ino=%lu, i_blkno=%"MLFu64", "
+ mlog(ML_ERROR, "Invalid dinode: i_ino=%lu, i_blkno=%llu, "
"signature = %.*s, flags = 0x%x\n",
- inode->i_ino, le64_to_cpu(fe->i_blkno), 7,
+ inode->i_ino,
+ (unsigned long long)le64_to_cpu(fe->i_blkno), 7,
fe->i_signature, le32_to_cpu(fe->i_flags));
goto bail;
}
@@ -268,8 +270,9 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
if (OCFS2_I(inode)->ip_blkno != le64_to_cpu(fe->i_blkno))
mlog(ML_ERROR,
- "ip_blkno %"MLFu64" != i_blkno %"MLFu64"!\n",
- OCFS2_I(inode)->ip_blkno, fe->i_blkno);
+ "ip_blkno %llu != i_blkno %llu!\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)fe->i_blkno);
OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
OCFS2_I(inode)->ip_orphaned_slot = OCFS2_INVALID_SLOT;
@@ -278,8 +281,8 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
inode->i_ino = ino_from_blkno(inode->i_sb,
le64_to_cpu(fe->i_blkno));
- mlog(0, "blkno = %"MLFu64", ino = %lu, create_ino = %s\n",
- fe->i_blkno, inode->i_ino, create_ino ? "true" : "false");
+ mlog(0, "blkno = %llu, ino = %lu, create_ino = %s\n",
+ (unsigned long long)fe->i_blkno, inode->i_ino, create_ino ? "true" : "false");
inode->i_nlink = le16_to_cpu(fe->i_links_count);
@@ -371,8 +374,8 @@ static int ocfs2_read_locked_inode(struct inode *inode,
fe = (struct ocfs2_dinode *) bh->b_data;
if (!OCFS2_IS_VALID_DINODE(fe)) {
- mlog(ML_ERROR, "Invalid dinode #%"MLFu64": signature = %.*s\n",
- fe->i_blkno, 7, fe->i_signature);
+ mlog(ML_ERROR, "Invalid dinode #%llu: signature = %.*s\n",
+ (unsigned long long)fe->i_blkno, 7, fe->i_signature);
make_bad_inode(inode);
goto bail;
}
@@ -386,8 +389,8 @@ static int ocfs2_read_locked_inode(struct inode *inode,
status = -EINVAL;
if (ocfs2_populate_inode(inode, fe, 0) < 0) {
- mlog(ML_ERROR, "populate inode failed! i_blkno=%"MLFu64", "
- "i_ino=%lu\n", fe->i_blkno, inode->i_ino);
+ mlog(ML_ERROR, "populate failed! i_blkno=%llu, i_ino=%lu\n",
+ (unsigned long long)fe->i_blkno, inode->i_ino);
make_bad_inode(inode);
goto bail;
}
@@ -675,8 +678,8 @@ static int ocfs2_inode_is_valid_to_delete(struct inode *inode)
* never get here as system file inodes should always have a
* positive link count. */
if (oi->ip_flags & OCFS2_INODE_SYSTEM_FILE) {
- mlog(ML_ERROR, "Skipping delete of system file %"MLFu64".\n",
- oi->ip_blkno);
+ mlog(ML_ERROR, "Skipping delete of system file %llu\n",
+ (unsigned long long)oi->ip_blkno);
goto bail_unlock;
}
@@ -715,16 +718,16 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
* ocfs2_delete_inode, another node might have asked to delete
* the inode. Recheck our flags to catch this. */
if (!ocfs2_inode_is_valid_to_delete(inode)) {
- mlog(0, "Skipping delete of %"MLFu64" because flags changed\n",
- oi->ip_blkno);
+ mlog(0, "Skipping delete of %llu because flags changed\n",
+ (unsigned long long)oi->ip_blkno);
goto bail;
}
/* Now that we have an up to date inode, we can double check
* the link count. */
if (inode->i_nlink) {
- mlog(0, "Skipping delete of %"MLFu64" because nlink = %u\n",
- oi->ip_blkno, inode->i_nlink);
+ mlog(0, "Skipping delete of %llu because nlink = %u\n",
+ (unsigned long long)oi->ip_blkno, inode->i_nlink);
goto bail;
}
@@ -734,9 +737,11 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
/* for lack of a better error? */
status = -EEXIST;
mlog(ML_ERROR,
- "Inode %"MLFu64" (on-disk %"MLFu64") not orphaned! "
+ "Inode %llu (on-disk %llu) not orphaned! "
"Disk flags 0x%x, inode flags 0x%x\n",
- oi->ip_blkno, di->i_blkno, di->i_flags, oi->ip_flags);
+ (unsigned long long)oi->ip_blkno,
+ (unsigned long long)di->i_blkno, di->i_flags,
+ oi->ip_flags);
goto bail;
}
@@ -753,8 +758,8 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
* disk and let them worry about deleting it. */
if (status == -EBUSY) {
status = 0;
- mlog(0, "Skipping delete of %"MLFu64" because it is in use on"
- "other nodes\n", oi->ip_blkno);
+ mlog(0, "Skipping delete of %llu because it is in use on"
+ "other nodes\n", (unsigned long long)oi->ip_blkno);
goto bail;
}
if (status < 0) {
@@ -768,13 +773,13 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
* into. This may happen during node death and
* recovery knows how to clean it up so we can safely
* ignore this inode for now on. */
- mlog(0, "Nobody knew where inode %"MLFu64" was orphaned!\n",
- oi->ip_blkno);
+ mlog(0, "Nobody knew where inode %llu was orphaned!\n",
+ (unsigned long long)oi->ip_blkno);
} else {
*wipe = 1;
- mlog(0, "Inode %"MLFu64" is ok to wipe from orphan dir %d\n",
- oi->ip_blkno, oi->ip_orphaned_slot);
+ mlog(0, "Inode %llu is ok to wipe from orphan dir %d\n",
+ (unsigned long long)oi->ip_blkno, oi->ip_orphaned_slot);
}
spin_unlock(&oi->ip_lock);
@@ -788,8 +793,8 @@ bail:
static void ocfs2_cleanup_delete_inode(struct inode *inode,
int sync_data)
{
- mlog(0, "Cleanup inode %"MLFu64", sync = %d\n",
- OCFS2_I(inode)->ip_blkno, sync_data);
+ mlog(0, "Cleanup inode %llu, sync = %d\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, sync_data);
if (sync_data)
write_inode_now(inode, 1);
truncate_inode_pages(&inode->i_data, 0);
@@ -897,8 +902,8 @@ void ocfs2_clear_inode(struct inode *inode)
if (!inode)
goto bail;
- mlog(0, "Clearing inode: %"MLFu64", nlink = %u\n",
- OCFS2_I(inode)->ip_blkno, inode->i_nlink);
+ mlog(0, "Clearing inode: %llu, nlink = %u\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_nlink);
mlog_bug_on_msg(OCFS2_SB(inode->i_sb) == NULL,
"Inode=%lu\n", inode->i_ino);
@@ -919,8 +924,8 @@ void ocfs2_clear_inode(struct inode *inode)
ocfs2_checkpoint_inode(inode);
mlog_bug_on_msg(!list_empty(&oi->ip_io_markers),
- "Clear inode of %"MLFu64", inode has io markers\n",
- oi->ip_blkno);
+ "Clear inode of %llu, inode has io markers\n",
+ (unsigned long long)oi->ip_blkno);
ocfs2_extent_map_drop(inode, 0);
ocfs2_extent_map_init(inode);
@@ -936,20 +941,20 @@ void ocfs2_clear_inode(struct inode *inode)
ocfs2_metadata_cache_purge(inode);
mlog_bug_on_msg(oi->ip_metadata_cache.ci_num_cached,
- "Clear inode of %"MLFu64", inode has %u cache items\n",
- oi->ip_blkno, oi->ip_metadata_cache.ci_num_cached);
+ "Clear inode of %llu, inode has %u cache items\n",
+ (unsigned long long)oi->ip_blkno, oi->ip_metadata_cache.ci_num_cached);
mlog_bug_on_msg(!(oi->ip_flags & OCFS2_INODE_CACHE_INLINE),
- "Clear inode of %"MLFu64", inode has a bad flag\n",
- oi->ip_blkno);
+ "Clear inode of %llu, inode has a bad flag\n",
+ (unsigned long long)oi->ip_blkno);
mlog_bug_on_msg(spin_is_locked(&oi->ip_lock),
- "Clear inode of %"MLFu64", inode is locked\n",
- oi->ip_blkno);
+ "Clear inode of %llu, inode is locked\n",
+ (unsigned long long)oi->ip_blkno);
mlog_bug_on_msg(!mutex_trylock(&oi->ip_io_mutex),
- "Clear inode of %"MLFu64", io_mutex is locked\n",
- oi->ip_blkno);
+ "Clear inode of %llu, io_mutex is locked\n",
+ (unsigned long long)oi->ip_blkno);
mutex_unlock(&oi->ip_io_mutex);
/*
@@ -957,19 +962,19 @@ void ocfs2_clear_inode(struct inode *inode)
* kernel 1, world 0
*/
mlog_bug_on_msg(!down_write_trylock(&oi->ip_alloc_sem),
- "Clear inode of %"MLFu64", alloc_sem is locked\n",
- oi->ip_blkno);
+ "Clear inode of %llu, alloc_sem is locked\n",
+ (unsigned long long)oi->ip_blkno);
up_write(&oi->ip_alloc_sem);
mlog_bug_on_msg(oi->ip_open_count,
- "Clear inode of %"MLFu64" has open count %d\n",
- oi->ip_blkno, oi->ip_open_count);
+ "Clear inode of %llu has open count %d\n",
+ (unsigned long long)oi->ip_blkno, oi->ip_open_count);
mlog_bug_on_msg(!list_empty(&oi->ip_handle_list),
- "Clear inode of %"MLFu64" has non empty handle list\n",
- oi->ip_blkno);
+ "Clear inode of %llu has non empty handle list\n",
+ (unsigned long long)oi->ip_blkno);
mlog_bug_on_msg(oi->ip_handle,
- "Clear inode of %"MLFu64" has non empty handle pointer\n",
- oi->ip_blkno);
+ "Clear inode of %llu has non empty handle pointer\n",
+ (unsigned long long)oi->ip_blkno);
/* Clear all other flags. */
oi->ip_flags = OCFS2_INODE_CACHE_INLINE;
@@ -991,8 +996,8 @@ void ocfs2_drop_inode(struct inode *inode)
mlog_entry_void();
- mlog(0, "Drop inode %"MLFu64", nlink = %u, ip_flags = 0x%x\n",
- oi->ip_blkno, inode->i_nlink, oi->ip_flags);
+ mlog(0, "Drop inode %llu, nlink = %u, ip_flags = 0x%x\n",
+ (unsigned long long)oi->ip_blkno, inode->i_nlink, oi->ip_flags);
/* Testing ip_orphaned_slot here wouldn't work because we may
* not have gotten a delete_inode vote from any other nodes
@@ -1069,8 +1074,8 @@ int ocfs2_inode_revalidate(struct dentry *dentry)
struct inode *inode = dentry->d_inode;
int status = 0;
- mlog_entry("(inode = 0x%p, ino = %"MLFu64")\n", inode,
- inode ? OCFS2_I(inode)->ip_blkno : 0ULL);
+ mlog_entry("(inode = 0x%p, ino = %llu)\n", inode,
+ inode ? (unsigned long long)OCFS2_I(inode)->ip_blkno : 0ULL);
if (!inode) {
mlog(0, "eep, no inode!\n");
@@ -1114,7 +1119,8 @@ int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle,
int status;
struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data;
- mlog_entry("(inode %"MLFu64")\n", OCFS2_I(inode)->ip_blkno);
+ mlog_entry("(inode %llu)\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
status = ocfs2_journal_access(handle, inode, bh,
OCFS2_JOURNAL_ACCESS_WRITE);
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 4be801f4559..6a610ae5358 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -377,7 +377,7 @@ int ocfs2_journal_access(struct ocfs2_journal_handle *handle,
BUG_ON(!bh);
BUG_ON(!(handle->flags & OCFS2_HANDLE_STARTED));
- mlog_entry("bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %hu\n",
+ mlog_entry("bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %zu\n",
(unsigned long long)bh->b_blocknr, type,
(type == OCFS2_JOURNAL_ACCESS_CREATE) ?
"OCFS2_JOURNAL_ACCESS_CREATE" :
@@ -503,8 +503,8 @@ static void ocfs2_handle_cleanup_locks(struct ocfs2_journal *journal,
ocfs2_meta_unlock(inode, 1);
if (atomic_read(&inode->i_count) == 1)
mlog(ML_ERROR,
- "Inode %"MLFu64", I'm doing a last iput for!",
- OCFS2_I(inode)->ip_blkno);
+ "Inode %llu, I'm doing a last iput for!",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
iput(inode);
kmem_cache_free(ocfs2_lock_cache, lock);
}
@@ -582,7 +582,8 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty)
}
mlog(0, "inode->i_size = %lld\n", inode->i_size);
- mlog(0, "inode->i_blocks = %lu\n", inode->i_blocks);
+ mlog(0, "inode->i_blocks = %llu\n",
+ (unsigned long long)inode->i_blocks);
mlog(0, "inode->ip_clusters = %u\n", OCFS2_I(inode)->ip_clusters);
/* call the kernels journal init function now */
@@ -640,8 +641,9 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
/* This is called from startup/shutdown which will
* handle the errors in a specific manner, so no need
* to call ocfs2_error() here. */
- mlog(ML_ERROR, "Journal dinode %"MLFu64" has invalid "
- "signature: %.*s", fe->i_blkno, 7, fe->i_signature);
+ mlog(ML_ERROR, "Journal dinode %llu has invalid "
+ "signature: %.*s", (unsigned long long)fe->i_blkno, 7,
+ fe->i_signature);
status = -EIO;
goto out;
}
@@ -849,8 +851,9 @@ static int ocfs2_force_read_journal(struct inode *inode)
memset(bhs, 0, sizeof(struct buffer_head *) * CONCURRENT_JOURNAL_FILL);
- mlog(0, "Force reading %lu blocks\n",
- (inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9)));
+ mlog(0, "Force reading %llu blocks\n",
+ (unsigned long long)(inode->i_blocks >>
+ (inode->i_sb->s_blocksize_bits - 9)));
v_blkno = 0;
while (v_blkno <
@@ -934,8 +937,8 @@ void ocfs2_complete_recovery(void *data)
la_dinode = item->lri_la_dinode;
if (la_dinode) {
- mlog(0, "Clean up local alloc %"MLFu64"\n",
- la_dinode->i_blkno);
+ mlog(0, "Clean up local alloc %llu\n",
+ (unsigned long long)la_dinode->i_blkno);
ret = ocfs2_complete_local_alloc_recovery(osb,
la_dinode);
@@ -947,8 +950,8 @@ void ocfs2_complete_recovery(void *data)
tl_dinode = item->lri_tl_dinode;
if (tl_dinode) {
- mlog(0, "Clean up truncate log %"MLFu64"\n",
- tl_dinode->i_blkno);
+ mlog(0, "Clean up truncate log %llu\n",
+ (unsigned long long)tl_dinode->i_blkno);
ret = ocfs2_complete_truncate_log_recovery(osb,
tl_dinode);
@@ -1473,11 +1476,11 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb,
if (de->file_type > OCFS2_FT_MAX) {
mlog(ML_ERROR,
"block %llu contains invalid de: "
- "inode = %"MLFu64", rec_len = %u, "
+ "inode = %llu, rec_len = %u, "
"name_len = %u, file_type = %u, "
"name='%.*s'\n",
(unsigned long long)bh->b_blocknr,
- le64_to_cpu(de->inode),
+ (unsigned long long)le64_to_cpu(de->inode),
le16_to_cpu(de->rec_len),
de->name_len,
de->file_type,
@@ -1494,8 +1497,8 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb,
if (IS_ERR(iter))
continue;
- mlog(0, "queue orphan %"MLFu64"\n",
- OCFS2_I(iter)->ip_blkno);
+ mlog(0, "queue orphan %llu\n",
+ (unsigned long long)OCFS2_I(iter)->ip_blkno);
/* No locking is required for the next_orphan
* queue as there is only ever a single
* process doing orphan recovery. */
@@ -1588,7 +1591,7 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb,
while (inode) {
oi = OCFS2_I(inode);
- mlog(0, "iput orphan %"MLFu64"\n", oi->ip_blkno);
+ mlog(0, "iput orphan %llu\n", (unsigned long long)oi->ip_blkno);
iter = oi->ip_next_orphan;
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index 149b3518166..0d1973ea32b 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
@@ -143,8 +143,8 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb)
if (!(le32_to_cpu(alloc->i_flags) &
(OCFS2_LOCAL_ALLOC_FL|OCFS2_BITMAP_FL))) {
- mlog(ML_ERROR, "Invalid local alloc inode, %"MLFu64"\n",
- OCFS2_I(inode)->ip_blkno);
+ mlog(ML_ERROR, "Invalid local alloc inode, %llu\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
status = -EINVAL;
goto bail;
}
@@ -493,9 +493,9 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
if (le32_to_cpu(alloc->id1.bitmap1.i_used) !=
ocfs2_local_alloc_count_bits(alloc)) {
- ocfs2_error(osb->sb, "local alloc inode %"MLFu64" says it has "
+ ocfs2_error(osb->sb, "local alloc inode %llu says it has "
"%u free bits, but a count shows %u",
- le64_to_cpu(alloc->i_blkno),
+ (unsigned long long)le64_to_cpu(alloc->i_blkno),
le32_to_cpu(alloc->id1.bitmap1.i_used),
ocfs2_local_alloc_count_bits(alloc));
status = -EIO;
@@ -753,10 +753,11 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
ocfs2_clusters_to_blocks(osb->sb,
start - count);
- mlog(0, "freeing %u bits starting at local "
- "alloc bit %u (la_start_blk = %"MLFu64", "
- "blkno = %"MLFu64")\n", count, start - count,
- la_start_blk, blkno);
+ mlog(0, "freeing %u bits starting at local alloc bit "
+ "%u (la_start_blk = %llu, blkno = %llu)\n",
+ count, start - count,
+ (unsigned long long)la_start_blk,
+ (unsigned long long)blkno);
status = ocfs2_free_clusters(handle, main_bm_inode,
main_bm_bh, blkno, count);
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index f6b77ff1d2b..0673862c8bd 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -161,8 +161,8 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
goto bail;
}
- mlog(0, "find name %.*s in directory %"MLFu64"\n", dentry->d_name.len,
- dentry->d_name.name, OCFS2_I(dir)->ip_blkno);
+ mlog(0, "find name %.*s in directory %llu\n", dentry->d_name.len,
+ dentry->d_name.name, (unsigned long long)OCFS2_I(dir)->ip_blkno);
status = ocfs2_meta_lock(dir, NULL, NULL, 0);
if (status < 0) {
@@ -180,7 +180,8 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno);
if (IS_ERR(inode)) {
- mlog(ML_ERROR, "Unable to create inode %"MLFu64"\n", blkno);
+ mlog(ML_ERROR, "Unable to create inode %llu\n",
+ (unsigned long long)blkno);
ret = ERR_PTR(-EACCES);
goto bail_unlock;
}
@@ -310,8 +311,8 @@ static int ocfs2_mknod(struct inode *dir,
osb = OCFS2_SB(dir->i_sb);
if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) {
- mlog(ML_ERROR, "inode %"MLFu64" has i_nlink of %u\n",
- OCFS2_I(dir)->ip_blkno, dir->i_nlink);
+ mlog(ML_ERROR, "inode %llu has i_nlink of %u\n",
+ (unsigned long long)OCFS2_I(dir)->ip_blkno, dir->i_nlink);
status = -EMLINK;
goto leave;
}
@@ -562,9 +563,9 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
if (ocfs2_populate_inode(inode, fe, 1) < 0) {
mlog(ML_ERROR, "populate inode failed! bh->b_blocknr=%llu, "
- "i_blkno=%"MLFu64", i_ino=%lu\n",
+ "i_blkno=%llu, i_ino=%lu\n",
(unsigned long long) (*new_fe_bh)->b_blocknr,
- fe->i_blkno, inode->i_ino);
+ (unsigned long long)fe->i_blkno, inode->i_ino);
BUG();
}
@@ -765,7 +766,7 @@ static int ocfs2_unlink(struct inode *dir,
BUG_ON(dentry->d_parent->d_inode != dir);
- mlog(0, "ino = %"MLFu64"\n", OCFS2_I(inode)->ip_blkno);
+ mlog(0, "ino = %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno);
if (inode == osb->root_inode) {
mlog(0, "Cannot delete the root directory\n");
@@ -799,9 +800,9 @@ static int ocfs2_unlink(struct inode *dir,
if (OCFS2_I(inode)->ip_blkno != blkno) {
status = -ENOENT;
- mlog(0, "ip_blkno (%"MLFu64") != dirent blkno (%"MLFu64") "
- "ip_flags = %x\n", OCFS2_I(inode)->ip_blkno, blkno,
- OCFS2_I(inode)->ip_flags);
+ mlog(0, "ip_blkno %llu != dirent blkno %llu ip_flags = %x\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)blkno, OCFS2_I(inode)->ip_flags);
goto leave;
}
@@ -946,8 +947,9 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
struct buffer_head **tmpbh;
struct inode *tmpinode;
- mlog_entry("(inode1 = %"MLFu64", inode2 = %"MLFu64")\n",
- oi1->ip_blkno, oi2->ip_blkno);
+ mlog_entry("(inode1 = %llu, inode2 = %llu)\n",
+ (unsigned long long)oi1->ip_blkno,
+ (unsigned long long)oi2->ip_blkno);
BUG_ON(!handle);
@@ -1187,9 +1189,9 @@ static int ocfs2_rename(struct inode *old_dir,
if (OCFS2_I(new_inode)->ip_blkno != newfe_blkno) {
status = -EACCES;
- mlog(0, "Inode blkno (%"MLFu64") and dir (%"MLFu64") "
- "disagree. ip_flags = %x\n",
- OCFS2_I(new_inode)->ip_blkno, newfe_blkno,
+ mlog(0, "Inode %llu and dir %llu disagree. flags = %x\n",
+ (unsigned long long)OCFS2_I(new_inode)->ip_blkno,
+ (unsigned long long)newfe_blkno,
OCFS2_I(new_inode)->ip_flags);
goto bail;
}
@@ -1215,9 +1217,9 @@ static int ocfs2_rename(struct inode *old_dir,
newfe = (struct ocfs2_dinode *) newfe_bh->b_data;
- mlog(0, "aha rename over existing... new_de=%p "
- "new_blkno=%"MLFu64" newfebh=%p bhblocknr=%llu\n",
- new_de, newfe_blkno, newfe_bh, newfe_bh ?
+ mlog(0, "aha rename over existing... new_de=%p new_blkno=%llu "
+ "newfebh=%p bhblocknr=%llu\n", new_de,
+ (unsigned long long)newfe_blkno, newfe_bh, newfe_bh ?
(unsigned long long)newfe_bh->b_blocknr : 0ULL);
if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) {
@@ -1354,8 +1356,8 @@ static int ocfs2_rename(struct inode *old_dir,
if (new_dir_nlink != new_dir->i_nlink) {
if (!new_dir_bh) {
mlog(ML_ERROR, "need to change nlink for new "
- "dir %"MLFu64" from %d to %d but bh is "
- "NULL\n", OCFS2_I(new_dir)->ip_blkno,
+ "dir %llu from %d to %d but bh is NULL\n",
+ (unsigned long long)OCFS2_I(new_dir)->ip_blkno,
(int)new_dir_nlink, new_dir->i_nlink);
} else {
struct ocfs2_dinode *fe;
@@ -1372,10 +1374,9 @@ static int ocfs2_rename(struct inode *old_dir,
if (old_dir_nlink != old_dir->i_nlink) {
if (!old_dir_bh) {
mlog(ML_ERROR, "need to change nlink for old dir "
- "%"MLFu64" from %d to %d but bh is NULL!\n",
- OCFS2_I(old_dir)->ip_blkno,
- (int)old_dir_nlink,
- old_dir->i_nlink);
+ "%llu from %d to %d but bh is NULL!\n",
+ (unsigned long long)OCFS2_I(old_dir)->ip_blkno,
+ (int)old_dir_nlink, old_dir->i_nlink);
} else {
struct ocfs2_dinode *fe;
status = ocfs2_journal_access(handle, old_dir,
@@ -1443,8 +1444,9 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
* write i_size + 1 bytes. */
blocks = (bytes_left + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
- mlog_entry("i_blocks = %lu, i_size = %llu, blocks = %d\n",
- inode->i_blocks, i_size_read(inode), blocks);
+ mlog_entry("i_blocks = %llu, i_size = %llu, blocks = %d\n",
+ (unsigned long long)inode->i_blocks,
+ i_size_read(inode), blocks);
/* Sanity check -- make sure we're going to fit. */
if (bytes_left >
@@ -1634,9 +1636,9 @@ static int ocfs2_symlink(struct inode *dir,
NULL);
if (status < 0) {
if (status != -ENOSPC && status != -EINTR) {
- mlog(ML_ERROR, "Failed to extend file to "
- "%"MLFu64"\n",
- newsize);
+ mlog(ML_ERROR,
+ "Failed to extend file to %llu\n",
+ (unsigned long long)newsize);
mlog_errno(status);
status = -ENOSPC;
}
@@ -1716,10 +1718,11 @@ int ocfs2_check_dir_entry(struct inode * dir,
error_msg = "directory entry across blocks";
if (error_msg != NULL)
- mlog(ML_ERROR, "bad entry in directory #%"MLFu64": %s - "
- "offset=%lu, inode=%"MLFu64", rec_len=%d, name_len=%d\n",
- OCFS2_I(dir)->ip_blkno, error_msg, offset,
- le64_to_cpu(de->inode), rlen, de->name_len);
+ mlog(ML_ERROR, "bad entry in directory #%llu: %s - "
+ "offset=%lu, inode=%llu, rec_len=%d, name_len=%d\n",
+ (unsigned long long)OCFS2_I(dir)->ip_blkno, error_msg,
+ offset, (unsigned long long)le64_to_cpu(de->inode), rlen,
+ de->name_len);
return error_msg == NULL ? 1 : 0;
}
@@ -2021,8 +2024,8 @@ static int ocfs2_blkno_stringify(u64 blkno, char *name)
mlog_entry_void();
- namelen = snprintf(name, OCFS2_ORPHAN_NAMELEN + 1, "%016"MLFx64,
- blkno);
+ namelen = snprintf(name, OCFS2_ORPHAN_NAMELEN + 1, "%016llx",
+ (long long)blkno);
if (namelen <= 0) {
if (namelen)
status = namelen;
@@ -2167,8 +2170,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
OCFS2_I(inode)->ip_orphaned_slot = osb->slot_num;
spin_unlock(&OCFS2_I(inode)->ip_lock);
- mlog(0, "Inode %"MLFu64" orphaned in slot %d\n",
- OCFS2_I(inode)->ip_blkno, osb->slot_num);
+ mlog(0, "Inode %llu orphaned in slot %d\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num);
leave:
if (orphan_dir_inode)
@@ -2202,8 +2205,9 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
goto leave;
}
- mlog(0, "removing '%s' from orphan dir %"MLFu64" (namelen=%d)\n",
- name, OCFS2_I(orphan_dir_inode)->ip_blkno, OCFS2_ORPHAN_NAMELEN);
+ mlog(0, "removing '%s' from orphan dir %llu (namelen=%d)\n",
+ name, (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno,
+ OCFS2_ORPHAN_NAMELEN);
/* find it's spot in the orphan directory */
target_de_bh = ocfs2_find_entry(name, OCFS2_ORPHAN_NAMELEN,
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index e89de9b6e49..da1093039c0 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -357,8 +357,8 @@ static inline int ocfs2_is_soft_readonly(struct ocfs2_super *osb)
#define OCFS2_RO_ON_INVALID_DINODE(__sb, __di) do { \
typeof(__di) ____di = (__di); \
ocfs2_error((__sb), \
- "Dinode # %"MLFu64" has bad signature %.*s", \
- (____di)->i_blkno, 7, \
+ "Dinode # %llu has bad signature %.*s", \
+ (unsigned long long)(____di)->i_blkno, 7, \
(____di)->i_signature); \
} while (0);
@@ -368,8 +368,8 @@ static inline int ocfs2_is_soft_readonly(struct ocfs2_super *osb)
#define OCFS2_RO_ON_INVALID_EXTENT_BLOCK(__sb, __eb) do { \
typeof(__eb) ____eb = (__eb); \
ocfs2_error((__sb), \
- "Extent Block # %"MLFu64" has bad signature %.*s", \
- (____eb)->h_blkno, 7, \
+ "Extent Block # %llu has bad signature %.*s", \
+ (unsigned long long)(____eb)->h_blkno, 7, \
(____eb)->h_signature); \
} while (0);
@@ -379,8 +379,8 @@ static inline int ocfs2_is_soft_readonly(struct ocfs2_super *osb)
#define OCFS2_RO_ON_INVALID_GROUP_DESC(__sb, __gd) do { \
typeof(__gd) ____gd = (__gd); \
ocfs2_error((__sb), \
- "Group Descriptor # %"MLFu64" has bad signature %.*s", \
- (____gd)->bg_blkno, 7, \
+ "Group Descriptor # %llu has bad signature %.*s", \
+ (unsigned long long)(____gd)->bg_blkno, 7, \
(____gd)->bg_signature); \
} while (0);
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index c46c164aefb..195523090c8 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -157,8 +157,9 @@ static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle,
mlog_entry_void();
if (((unsigned long long) bg_bh->b_blocknr) != group_blkno) {
- ocfs2_error(alloc_inode->i_sb, "group block (%"MLFu64") "
- "!= b_blocknr (%llu)", group_blkno,
+ ocfs2_error(alloc_inode->i_sb, "group block (%llu) != "
+ "b_blocknr (%llu)",
+ (unsigned long long)group_blkno,
(unsigned long long) bg_bh->b_blocknr);
status = -EIO;
goto bail;
@@ -280,8 +281,8 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
/* setup the group */
bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off);
- mlog(0, "new descriptor, record %u, at block %"MLFu64"\n",
- alloc_rec, bg_blkno);
+ mlog(0, "new descriptor, record %u, at block %llu\n",
+ alloc_rec, (unsigned long long)bg_blkno);
bg_bh = sb_getblk(osb->sb, bg_blkno);
if (!bg_bh) {
@@ -382,8 +383,8 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
goto bail;
}
if (!(fe->i_flags & cpu_to_le32(OCFS2_CHAIN_FL))) {
- ocfs2_error(alloc_inode->i_sb, "Invalid chain allocator "
- "# %"MLFu64, le64_to_cpu(fe->i_blkno));
+ ocfs2_error(alloc_inode->i_sb, "Invalid chain allocator %llu",
+ (unsigned long long)le64_to_cpu(fe->i_blkno));
status = -EIO;
goto bail;
}
@@ -829,9 +830,10 @@ static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle,
goto out;
}
- mlog(0, "In suballoc %"MLFu64", chain %u, move group %"MLFu64" to "
- "top, prev = %"MLFu64"\n",
- fe->i_blkno, chain, bg->bg_blkno, prev_bg->bg_blkno);
+ mlog(0, "Suballoc %llu, chain %u, move group %llu to top, prev = %llu\n",
+ (unsigned long long)fe->i_blkno, chain,
+ (unsigned long long)bg->bg_blkno,
+ (unsigned long long)prev_bg->bg_blkno);
fe_ptr = le64_to_cpu(fe->id2.i_chain.cl_recs[chain].c_blkno);
bg_ptr = le64_to_cpu(bg->bg_next_group);
@@ -974,8 +976,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
struct ocfs2_group_desc *bg;
chain = ac->ac_chain;
- mlog(0, "trying to alloc %u bits from chain %u, inode %"MLFu64"\n",
- bits_wanted, chain, OCFS2_I(alloc_inode)->ip_blkno);
+ mlog(0, "trying to alloc %u bits from chain %u, inode %llu\n",
+ bits_wanted, chain,
+ (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno);
status = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb),
le64_to_cpu(cl->cl_recs[chain].c_blkno),
@@ -1027,8 +1030,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
goto bail;
}
- mlog(0, "alloc succeeds: we give %u bits from block group %"MLFu64"\n",
- tmp_bits, bg->bg_blkno);
+ mlog(0, "alloc succeeds: we give %u bits from block group %llu\n",
+ tmp_bits, (unsigned long long)bg->bg_blkno);
*num_bits = tmp_bits;
@@ -1092,8 +1095,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
goto bail;
}
- mlog(0, "Allocated %u bits from suballocator %"MLFu64"\n",
- *num_bits, fe->i_blkno);
+ mlog(0, "Allocated %u bits from suballocator %llu\n", *num_bits,
+ (unsigned long long)fe->i_blkno);
*bg_blkno = le64_to_cpu(bg->bg_blkno);
bail:
@@ -1134,9 +1137,9 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
}
if (le32_to_cpu(fe->id1.bitmap1.i_used) >=
le32_to_cpu(fe->id1.bitmap1.i_total)) {
- ocfs2_error(osb->sb, "Chain allocator dinode %"MLFu64" has %u"
- "used bits but only %u total.",
- le64_to_cpu(fe->i_blkno),
+ ocfs2_error(osb->sb, "Chain allocator dinode %llu has %u used "
+ "bits but only %u total.",
+ (unsigned long long)le64_to_cpu(fe->i_blkno),
le32_to_cpu(fe->id1.bitmap1.i_used),
le32_to_cpu(fe->id1.bitmap1.i_total));
status = -EIO;
@@ -1479,10 +1482,9 @@ static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle,
}
BUG_ON((count + start_bit) > ocfs2_bits_per_group(cl));
- mlog(0, "suballocator %"MLFu64": freeing %u bits from group %"MLFu64
- ", starting at %u\n",
- OCFS2_I(alloc_inode)->ip_blkno, count, bg_blkno,
- start_bit);
+ mlog(0, "%llu: freeing %u bits from group %llu, starting at %u\n",
+ (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno, count,
+ (unsigned long long)bg_blkno, start_bit);
status = ocfs2_read_block(osb, bg_blkno, &group_bh, OCFS2_BH_CACHED,
alloc_inode);
@@ -1592,10 +1594,10 @@ int ocfs2_free_clusters(struct ocfs2_journal_handle *handle,
ocfs2_block_to_cluster_group(bitmap_inode, start_blk, &bg_blkno,
&bg_start_bit);
- mlog(0, "want to free %u clusters starting at block %"MLFu64"\n",
- num_clusters, start_blk);
- mlog(0, "bg_blkno = %"MLFu64", bg_start_bit = %u\n",
- bg_blkno, bg_start_bit);
+ mlog(0, "want to free %u clusters starting at block %llu\n",
+ num_clusters, (unsigned long long)start_blk);
+ mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n",
+ (unsigned long long)bg_blkno, bg_start_bit);
status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
bg_start_bit, bg_blkno,
@@ -1616,18 +1618,22 @@ static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg)
printk("bg_free_bits_count: %u\n", bg->bg_free_bits_count);
printk("bg_chain: %u\n", bg->bg_chain);
printk("bg_generation: %u\n", le32_to_cpu(bg->bg_generation));
- printk("bg_next_group: %"MLFu64"\n", bg->bg_next_group);
- printk("bg_parent_dinode: %"MLFu64"\n", bg->bg_parent_dinode);
- printk("bg_blkno: %"MLFu64"\n", bg->bg_blkno);
+ printk("bg_next_group: %llu\n",
+ (unsigned long long)bg->bg_next_group);
+ printk("bg_parent_dinode: %llu\n",
+ (unsigned long long)bg->bg_parent_dinode);
+ printk("bg_blkno: %llu\n",
+ (unsigned long long)bg->bg_blkno);
}
static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe)
{
int i;
- printk("Suballoc Inode %"MLFu64":\n", fe->i_blkno);
+ printk("Suballoc Inode %llu:\n", (unsigned long long)fe->i_blkno);
printk("i_signature: %s\n", fe->i_signature);
- printk("i_size: %"MLFu64"\n", fe->i_size);
+ printk("i_size: %llu\n",
+ (unsigned long long)fe->i_size);
printk("i_clusters: %u\n", fe->i_clusters);
printk("i_generation: %u\n",
le32_to_cpu(fe->i_generation));
@@ -1645,7 +1651,7 @@ static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe)
fe->id2.i_chain.cl_recs[i].c_free);
printk("fe->id2.i_chain.cl_recs[%d].c_total: %u\n", i,
fe->id2.i_chain.cl_recs[i].c_total);
- printk("fe->id2.i_chain.cl_recs[%d].c_blkno: %"MLFu64"\n", i,
- fe->id2.i_chain.cl_recs[i].c_blkno);
+ printk("fe->id2.i_chain.cl_recs[%d].c_blkno: %llu\n", i,
+ (unsigned long long)fe->id2.i_chain.cl_recs[i].c_blkno);
}
}
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 44d8b524823..949b3dac30f 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1428,8 +1428,9 @@ static int ocfs2_initialize_super(struct super_block *sb,
osb->fs_generation = le32_to_cpu(di->i_fs_generation);
mlog(0, "vol_label: %s\n", osb->vol_label);
mlog(0, "uuid: %s\n", osb->uuid_str);
- mlog(0, "root_blkno=%"MLFu64", system_dir_blkno=%"MLFu64"\n",
- osb->root_blkno, osb->system_dir_blkno);
+ mlog(0, "root_blkno=%llu, system_dir_blkno=%llu\n",
+ (unsigned long long)osb->root_blkno,
+ (unsigned long long)osb->system_dir_blkno);
osb->osb_dlm_debug = ocfs2_new_dlm_debug();
if (!osb->osb_dlm_debug) {
@@ -1472,8 +1473,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
osb->bitmap_cpg = le16_to_cpu(di->id2.i_chain.cl_cpg);
osb->num_clusters = le32_to_cpu(di->id1.bitmap1.i_total);
brelse(bitmap_bh);
- mlog(0, "cluster bitmap inode: %"MLFu64", clusters per group: %u\n",
- osb->bitmap_blkno, osb->bitmap_cpg);
+ mlog(0, "cluster bitmap inode: %llu, clusters per group: %u\n",
+ (unsigned long long)osb->bitmap_blkno, osb->bitmap_cpg);
status = ocfs2_init_slot_info(osb);
if (status < 0) {
@@ -1531,8 +1532,9 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di,
OCFS2_MINOR_REV_LEVEL);
} else if (bh->b_blocknr != le64_to_cpu(di->i_blkno)) {
mlog(ML_ERROR, "bad block number on superblock: "
- "found %"MLFu64", should be %llu\n",
- di->i_blkno, (unsigned long long)bh->b_blocknr);
+ "found %llu, should be %llu\n",
+ (unsigned long long)di->i_blkno,
+ (unsigned long long)bh->b_blocknr);
} else if (le32_to_cpu(di->id2.i_super.s_clustersize_bits) < 12 ||
le32_to_cpu(di->id2.i_super.s_clustersize_bits) > 20) {
mlog(ML_ERROR, "bad cluster size found: %u\n",
diff --git a/fs/ocfs2/super.h b/fs/ocfs2/super.h
index c564177dfbd..783f5270f2a 100644
--- a/fs/ocfs2/super.h
+++ b/fs/ocfs2/super.h
@@ -33,12 +33,16 @@ int ocfs2_publish_get_mount_state(struct ocfs2_super *osb,
void __ocfs2_error(struct super_block *sb,
const char *function,
- const char *fmt, ...);
+ const char *fmt, ...)
+ __attribute__ ((format (printf, 3, 4)));
+
#define ocfs2_error(sb, fmt, args...) __ocfs2_error(sb, __PRETTY_FUNCTION__, fmt, ##args)
void __ocfs2_abort(struct super_block *sb,
const char *function,
- const char *fmt, ...);
+ const char *fmt, ...)
+ __attribute__ ((format (printf, 3, 4)));
+
#define ocfs2_abort(sb, fmt, args...) __ocfs2_abort(sb, __PRETTY_FUNCTION__, fmt, ##args)
#endif /* OCFS2_SUPER_H */
diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c
index 300b5bedfb2..04a684dfdd9 100644
--- a/fs/ocfs2/uptodate.c
+++ b/fs/ocfs2/uptodate.c
@@ -119,8 +119,8 @@ void ocfs2_metadata_cache_purge(struct inode *inode)
tree = !(oi->ip_flags & OCFS2_INODE_CACHE_INLINE);
to_purge = ci->ci_num_cached;
- mlog(0, "Purge %u %s items from Inode %"MLFu64"\n", to_purge,
- tree ? "array" : "tree", oi->ip_blkno);
+ mlog(0, "Purge %u %s items from Inode %llu\n", to_purge,
+ tree ? "array" : "tree", (unsigned long long)oi->ip_blkno);
/* If we're a tree, save off the root so that we can safely
* initialize the cache. We do the work to free tree members
@@ -136,8 +136,8 @@ void ocfs2_metadata_cache_purge(struct inode *inode)
* easily detect counting errors. Unfortunately, this is only
* meaningful for trees. */
if (tree && purged != to_purge)
- mlog(ML_ERROR, "Inode %"MLFu64", count = %u, purged = %u\n",
- oi->ip_blkno, to_purge, purged);
+ mlog(ML_ERROR, "Inode %llu, count = %u, purged = %u\n",
+ (unsigned long long)oi->ip_blkno, to_purge, purged);
}
/* Returns the index in the cache array, -1 if not found.
@@ -186,8 +186,9 @@ static int ocfs2_buffer_cached(struct ocfs2_inode_info *oi,
spin_lock(&oi->ip_lock);
- mlog(0, "Inode %"MLFu64", query block %llu (inline = %u)\n",
- oi->ip_blkno, (unsigned long long) bh->b_blocknr,
+ mlog(0, "Inode %llu, query block %llu (inline = %u)\n",
+ (unsigned long long)oi->ip_blkno,
+ (unsigned long long) bh->b_blocknr,
!!(oi->ip_flags & OCFS2_INODE_CACHE_INLINE));
if (oi->ip_flags & OCFS2_INODE_CACHE_INLINE)
@@ -293,12 +294,12 @@ static void ocfs2_expand_cache(struct ocfs2_inode_info *oi,
struct ocfs2_caching_info *ci = &oi->ip_metadata_cache;
mlog_bug_on_msg(ci->ci_num_cached != OCFS2_INODE_MAX_CACHE_ARRAY,
- "Inode %"MLFu64", num cached = %u, should be %u\n",
- oi->ip_blkno, ci->ci_num_cached,
+ "Inode %llu, num cached = %u, should be %u\n",
+ (unsigned long long)oi->ip_blkno, ci->ci_num_cached,
OCFS2_INODE_MAX_CACHE_ARRAY);
mlog_bug_on_msg(!(oi->ip_flags & OCFS2_INODE_CACHE_INLINE),
- "Inode %"MLFu64" not marked as inline anymore!\n",
- oi->ip_blkno);
+ "Inode %llu not marked as inline anymore!\n",
+ (unsigned long long)oi->ip_blkno);
assert_spin_locked(&oi->ip_lock);
/* Be careful to initialize the tree members *first* because
@@ -316,8 +317,8 @@ static void ocfs2_expand_cache(struct ocfs2_inode_info *oi,
tree[i] = NULL;
}
- mlog(0, "Expanded %"MLFu64" to a tree cache: flags 0x%x, num = %u\n",
- oi->ip_blkno, oi->ip_flags, ci->ci_num_cached);
+ mlog(0, "Expanded %llu to a tree cache: flags 0x%x, num = %u\n",
+ (unsigned long long)oi->ip_blkno, oi->ip_flags, ci->ci_num_cached);
}
/* Slow path function - memory allocation is necessary. See the
@@ -332,8 +333,9 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi,
struct ocfs2_meta_cache_item *tree[OCFS2_INODE_MAX_CACHE_ARRAY] =
{ NULL, };
- mlog(0, "Inode %"MLFu64", block %llu, expand = %d\n",
- oi->ip_blkno, (unsigned long long) block, expand_tree);
+ mlog(0, "Inode %llu, block %llu, expand = %d\n",
+ (unsigned long long)oi->ip_blkno,
+ (unsigned long long)block, expand_tree);
new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_KERNEL);
if (!new) {
@@ -414,8 +416,9 @@ void ocfs2_set_buffer_uptodate(struct inode *inode,
if (ocfs2_buffer_cached(oi, bh))
return;
- mlog(0, "Inode %"MLFu64", inserting block %llu\n", oi->ip_blkno,
- (unsigned long long) bh->b_blocknr);
+ mlog(0, "Inode %llu, inserting block %llu\n",
+ (unsigned long long)oi->ip_blkno,
+ (unsigned long long)bh->b_blocknr);
/* No need to recheck under spinlock - insertion is guarded by
* ip_io_mutex */
@@ -504,8 +507,9 @@ void ocfs2_remove_from_cache(struct inode *inode,
struct ocfs2_caching_info *ci = &oi->ip_metadata_cache;
spin_lock(&oi->ip_lock);
- mlog(0, "Inode %"MLFu64", remove %llu, items = %u, array = %u\n",
- oi->ip_blkno, (unsigned long long) block, ci->ci_num_cached,
+ mlog(0, "Inode %llu, remove %llu, items = %u, array = %u\n",
+ (unsigned long long)oi->ip_blkno,
+ (unsigned long long) block, ci->ci_num_cached,
oi->ip_flags & OCFS2_INODE_CACHE_INLINE);
if (oi->ip_flags & OCFS2_INODE_CACHE_INLINE) {
diff --git a/fs/ocfs2/vote.c b/fs/ocfs2/vote.c
index 021978e0576..53049a20419 100644
--- a/fs/ocfs2/vote.c
+++ b/fs/ocfs2/vote.c
@@ -190,20 +190,21 @@ static int ocfs2_process_delete_request(struct inode *inode,
OCFS2_INVALID_SLOT &&
OCFS2_I(inode)->ip_orphaned_slot !=
(*orphaned_slot),
- "Inode %"MLFu64": This node thinks it's "
+ "Inode %llu: This node thinks it's "
"orphaned in slot %d, messaged it's in %d\n",
- OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
OCFS2_I(inode)->ip_orphaned_slot,
*orphaned_slot);
- mlog(0, "Setting orphaned slot for inode %"MLFu64" to %d\n",
- OCFS2_I(inode)->ip_blkno, *orphaned_slot);
+ mlog(0, "Setting orphaned slot for inode %llu to %d\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ *orphaned_slot);
OCFS2_I(inode)->ip_orphaned_slot = *orphaned_slot;
} else {
- mlog(0, "Sending back orphaned slot %d for inode %"MLFu64"\n",
+ mlog(0, "Sending back orphaned slot %d for inode %llu\n",
OCFS2_I(inode)->ip_orphaned_slot,
- OCFS2_I(inode)->ip_blkno);
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
*orphaned_slot = OCFS2_I(inode)->ip_orphaned_slot;
}
@@ -226,8 +227,8 @@ static int ocfs2_process_delete_request(struct inode *inode,
}
if (filemap_fdatawrite(inode->i_mapping)) {
- mlog(ML_ERROR, "Could not sync inode %"MLFu64" for delete!\n",
- OCFS2_I(inode)->ip_blkno);
+ mlog(ML_ERROR, "Could not sync inode %llu for delete!\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
goto done;
}
sync_mapping_buffers(inode->i_mapping);
@@ -302,8 +303,8 @@ static void ocfs2_process_dentry_request(struct inode *inode,
struct list_head *p;
struct ocfs2_inode_info *oi = OCFS2_I(inode);
- mlog(0, "parent %"MLFu64", namelen = %u, name = %.*s\n", parent_blkno,
- namelen, namelen, name);
+ mlog(0, "parent %llu, namelen = %u, name = %.*s\n",
+ (unsigned long long)parent_blkno, namelen, namelen, name);
spin_lock(&dcache_lock);
@@ -370,9 +371,10 @@ static void ocfs2_process_vote(struct ocfs2_super *osb,
if (request == OCFS2_VOTE_REQ_DELETE)
orphaned_slot = be32_to_cpu(msg->md1.v_orphaned_slot);
- mlog(0, "processing vote: request = %u, blkno = %"MLFu64", "
+ mlog(0, "processing vote: request = %u, blkno = %llu, "
"generation = %u, node_num = %u, priv1 = %u\n", request,
- blkno, generation, node_num, be32_to_cpu(msg->md1.v_generic1));
+ (unsigned long long)blkno, generation, node_num,
+ be32_to_cpu(msg->md1.v_generic1));
if (!ocfs2_is_valid_vote_request(request)) {
mlog(ML_ERROR, "Invalid vote request %d from node %u\n",
@@ -419,11 +421,12 @@ static void ocfs2_process_vote(struct ocfs2_super *osb,
* we had not found an inode in the first place. */
if (inode->i_generation != generation) {
mlog(0, "generation passed %u != inode generation = %u, "
- "ip_flags = %x, ip_blkno = %"MLFu64", msg %"MLFu64", "
- "i_count = %u, message type = %u\n",
- generation, inode->i_generation, OCFS2_I(inode)->ip_flags,
- OCFS2_I(inode)->ip_blkno, blkno,
- atomic_read(&inode->i_count), request);
+ "ip_flags = %x, ip_blkno = %llu, msg %llu, i_count = %u, "
+ "message type = %u\n", generation, inode->i_generation,
+ OCFS2_I(inode)->ip_flags,
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)blkno, atomic_read(&inode->i_count),
+ request);
iput(inode);
inode = NULL;
goto respond;
@@ -830,8 +833,9 @@ static void ocfs2_delete_response_cb(void *priv,
orphaned_slot = be32_to_cpu(resp->r_orphaned_slot);
node = be32_to_cpu(resp->r_hdr.h_node_num);
- mlog(0, "node %d tells us that inode %"MLFu64" is orphaned in slot "
- "%d\n", node, OCFS2_I(inode)->ip_blkno, orphaned_slot);
+ mlog(0, "node %d tells us that inode %llu is orphaned in slot %d\n",
+ node, (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ orphaned_slot);
/* The other node may not actually know which slot the inode
* is orphaned in. */
@@ -845,9 +849,9 @@ static void ocfs2_delete_response_cb(void *priv,
spin_lock(&OCFS2_I(inode)->ip_lock);
mlog_bug_on_msg(OCFS2_I(inode)->ip_orphaned_slot != orphaned_slot &&
OCFS2_I(inode)->ip_orphaned_slot
- != OCFS2_INVALID_SLOT, "Inode %"MLFu64": Node %d "
- "says it's orphaned in slot %d, we think it's in %d\n",
- OCFS2_I(inode)->ip_blkno,
+ != OCFS2_INVALID_SLOT, "Inode %llu: Node %d says it's "
+ "orphaned in slot %d, we think it's in %d\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
be32_to_cpu(resp->r_hdr.h_node_num),
orphaned_slot, OCFS2_I(inode)->ip_orphaned_slot);
@@ -869,8 +873,8 @@ int ocfs2_request_delete_vote(struct inode *inode)
delete_cb.rc_cb = ocfs2_delete_response_cb;
delete_cb.rc_priv = inode;
- mlog(0, "Inode %"MLFu64", we start thinking orphaned slot is %d\n",
- OCFS2_I(inode)->ip_blkno, orphaned_slot);
+ mlog(0, "Inode %llu, we start thinking orphaned slot is %d\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, orphaned_slot);
status = -ENOMEM;
request = ocfs2_new_vote_request(osb, OCFS2_I(inode)->ip_blkno,
@@ -895,8 +899,8 @@ static void ocfs2_setup_unlink_vote(struct ocfs2_vote_msg *request,
* d_delete against it. Parent directory block and full name
* should suffice. */
- mlog(0, "unlink/rename request: parent: %"MLFu64" name: %.*s\n",
- OCFS2_I(parent)->ip_blkno, dentry->d_name.len,
+ mlog(0, "unlink/rename request: parent: %llu name: %.*s\n",
+ (unsigned long long)OCFS2_I(parent)->ip_blkno, dentry->d_name.len,
dentry->d_name.name);
request->v_unlink_parent = cpu_to_be64(OCFS2_I(parent)->ip_blkno);
@@ -1082,7 +1086,8 @@ static int ocfs2_handle_response_message(struct o2net_msg *msg,
mlog(0, "received response message:\n");
mlog(0, "h_response_id = %u\n", response_id);
mlog(0, "h_request = %u\n", be32_to_cpu(resp->r_hdr.h_request));
- mlog(0, "h_blkno = %"MLFu64"\n", be64_to_cpu(resp->r_hdr.h_blkno));
+ mlog(0, "h_blkno = %llu\n",
+ (unsigned long long)be64_to_cpu(resp->r_hdr.h_blkno));
mlog(0, "h_generation = %u\n", be32_to_cpu(resp->r_hdr.h_generation));
mlog(0, "h_node_num = %u\n", node_num);
mlog(0, "r_response = %d\n", response_status);
@@ -1138,8 +1143,8 @@ static int ocfs2_handle_vote_message(struct o2net_msg *msg,
mlog(0, "h_response_id = %u\n",
be32_to_cpu(work->w_msg.v_hdr.h_response_id));
mlog(0, "h_request = %u\n", be32_to_cpu(work->w_msg.v_hdr.h_request));
- mlog(0, "h_blkno = %"MLFu64"\n",
- be64_to_cpu(work->w_msg.v_hdr.h_blkno));
+ mlog(0, "h_blkno = %llu\n",
+ (unsigned long long)be64_to_cpu(work->w_msg.v_hdr.h_blkno));
mlog(0, "h_generation = %u\n",
be32_to_cpu(work->w_msg.v_hdr.h_generation));
mlog(0, "h_node_num = %u\n",
diff --git a/fs/open.c b/fs/open.c
index 1091dadd6c3..c32c89d6d8d 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -27,6 +27,7 @@
#include <linux/pagemap.h>
#include <linux/syscalls.h>
#include <linux/rcupdate.h>
+#include <linux/audit.h>
#include <asm/unistd.h>
@@ -626,6 +627,8 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
dentry = file->f_dentry;
inode = dentry->d_inode;
+ audit_inode(NULL, inode, 0);
+
err = -EROFS;
if (IS_RDONLY(inode))
goto out_putf;
@@ -775,7 +778,10 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
file = fget(fd);
if (file) {
- error = chown_common(file->f_dentry, user, group);
+ struct dentry * dentry;
+ dentry = file->f_dentry;
+ audit_inode(NULL, dentry->d_inode, 0);
+ error = chown_common(dentry, user, group);
fput(file);
}
return error;
@@ -890,6 +896,10 @@ EXPORT_SYMBOL(filp_open);
* a fully instantiated struct file to the caller.
* This function is meant to be called from within a filesystem's
* lookup method.
+ * Beware of calling it for non-regular files! Those ->open methods might block
+ * (e.g. in fifo_open), leaving you with parent locked (and in case of fifo,
+ * leading to a deadlock, as nobody can open that fifo anymore, because
+ * another process to open fifo will block on locked parent when doing lookup).
* Note that in case of error, nd->intent.open.file is destroyed, but the
* path information remains valid.
* If the open callback is set to NULL, then the standard f_op->open()
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index aeb0106890e..0f14276a2e5 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -581,17 +581,17 @@ int property_release (struct inode *inode, struct file *filp)
return 0;
}
-static struct file_operations openpromfs_prop_ops = {
+static const struct file_operations openpromfs_prop_ops = {
.read = property_read,
.write = property_write,
.release = property_release,
};
-static struct file_operations openpromfs_nodenum_ops = {
+static const struct file_operations openpromfs_nodenum_ops = {
.read = nodenum_read,
};
-static struct file_operations openprom_operations = {
+static const struct file_operations openprom_operations = {
.read = generic_read_dir,
.readdir = openpromfs_readdir,
};
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index f924f459bdb..af0cb4b9e78 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -297,6 +297,25 @@ struct kobj_type ktype_part = {
.sysfs_ops = &part_sysfs_ops,
};
+static inline void partition_sysfs_add_subdir(struct hd_struct *p)
+{
+ struct kobject *k;
+
+ k = kobject_get(&p->kobj);
+ p->holder_dir = kobject_add_dir(k, "holders");
+ kobject_put(k);
+}
+
+static inline void disk_sysfs_add_subdirs(struct gendisk *disk)
+{
+ struct kobject *k;
+
+ k = kobject_get(&disk->kobj);
+ disk->holder_dir = kobject_add_dir(k, "holders");
+ disk->slave_dir = kobject_add_dir(k, "slaves");
+ kobject_put(k);
+}
+
void delete_partition(struct gendisk *disk, int part)
{
struct hd_struct *p = disk->part[part-1];
@@ -310,6 +329,8 @@ void delete_partition(struct gendisk *disk, int part)
p->ios[0] = p->ios[1] = 0;
p->sectors[0] = p->sectors[1] = 0;
devfs_remove("%s/part%d", disk->devfs_name, part);
+ if (p->holder_dir)
+ kobject_unregister(p->holder_dir);
kobject_unregister(&p->kobj);
}
@@ -337,6 +358,7 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
p->kobj.parent = &disk->kobj;
p->kobj.ktype = &ktype_part;
kobject_register(&p->kobj);
+ partition_sysfs_add_subdir(p);
disk->part[part-1] = p;
}
@@ -383,6 +405,7 @@ void register_disk(struct gendisk *disk)
if ((err = kobject_add(&disk->kobj)))
return;
disk_sysfs_symlinks(disk);
+ disk_sysfs_add_subdirs(disk);
kobject_uevent(&disk->kobj, KOBJ_ADD);
/* No minors to use for partitions */
@@ -483,6 +506,10 @@ void del_gendisk(struct gendisk *disk)
devfs_remove_disk(disk);
+ if (disk->holder_dir)
+ kobject_unregister(disk->holder_dir);
+ if (disk->slave_dir)
+ kobject_unregister(disk->slave_dir);
if (disk->driverfs_dev) {
char *disk_name = make_block_name(disk);
sysfs_remove_link(&disk->kobj, "device");
diff --git a/fs/partitions/devfs.c b/fs/partitions/devfs.c
index 87f50444fd3..3f0a780c9ce 100644
--- a/fs/partitions/devfs.c
+++ b/fs/partitions/devfs.c
@@ -6,7 +6,7 @@
#include <linux/vmalloc.h>
#include <linux/genhd.h>
#include <linux/bitops.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
struct unique_numspace {
@@ -16,7 +16,7 @@ struct unique_numspace {
struct semaphore mutex;
};
-static DECLARE_MUTEX(numspace_mutex);
+static DEFINE_MUTEX(numspace_mutex);
static int expand_numspace(struct unique_numspace *s)
{
@@ -48,7 +48,7 @@ static int alloc_unique_number(struct unique_numspace *s)
{
int rval = 0;
- down(&numspace_mutex);
+ mutex_lock(&numspace_mutex);
if (s->num_free < 1)
rval = expand_numspace(s);
if (!rval) {
@@ -56,7 +56,7 @@ static int alloc_unique_number(struct unique_numspace *s)
--s->num_free;
__set_bit(rval, s->bits);
}
- up(&numspace_mutex);
+ mutex_unlock(&numspace_mutex);
return rval;
}
@@ -66,11 +66,11 @@ static void dealloc_unique_number(struct unique_numspace *s, int number)
int old_val;
if (number >= 0) {
- down(&numspace_mutex);
+ mutex_lock(&numspace_mutex);
old_val = __test_and_clear_bit(number, s->bits);
if (old_val)
++s->num_free;
- up(&numspace_mutex);
+ mutex_unlock(&numspace_mutex);
}
}
diff --git a/fs/partitions/mac.c b/fs/partitions/mac.c
index bb22cdd0cb1..813292f2121 100644
--- a/fs/partitions/mac.c
+++ b/fs/partitions/mac.c
@@ -12,6 +12,7 @@
#include "mac.h"
#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
extern void note_bootable_part(dev_t dev, int part, int goodness);
#endif
@@ -79,7 +80,7 @@ int mac_partition(struct parsed_partitions *state, struct block_device *bdev)
* If this is the first bootable partition, tell the
* setup code, in case it wants to make this the root.
*/
- if (_machine == _MACH_Pmac) {
+ if (machine_is(powermac)) {
int goodness = 0;
mac_fix_string(part->processor, 16);
diff --git a/fs/pipe.c b/fs/pipe.c
index 8aada8e426f..e2f4f1d9ffc 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -568,7 +568,7 @@ pipe_rdwr_open(struct inode *inode, struct file *filp)
* The file_operations structs are not static because they
* are also used in linux/fs/fifo.c to do operations on FIFOs.
*/
-struct file_operations read_fifo_fops = {
+const struct file_operations read_fifo_fops = {
.llseek = no_llseek,
.read = pipe_read,
.readv = pipe_readv,
@@ -580,7 +580,7 @@ struct file_operations read_fifo_fops = {
.fasync = pipe_read_fasync,
};
-struct file_operations write_fifo_fops = {
+const struct file_operations write_fifo_fops = {
.llseek = no_llseek,
.read = bad_pipe_r,
.write = pipe_write,
@@ -592,7 +592,7 @@ struct file_operations write_fifo_fops = {
.fasync = pipe_write_fasync,
};
-struct file_operations rdwr_fifo_fops = {
+const struct file_operations rdwr_fifo_fops = {
.llseek = no_llseek,
.read = pipe_read,
.readv = pipe_readv,
@@ -662,10 +662,9 @@ struct inode* pipe_new(struct inode* inode)
{
struct pipe_inode_info *info;
- info = kmalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
+ info = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
if (!info)
goto fail_page;
- memset(info, 0, sizeof(*info));
inode->i_pipe = info;
init_waitqueue_head(PIPE_WAIT(*inode));
@@ -676,7 +675,7 @@ fail_page:
return NULL;
}
-static struct vfsmount *pipe_mnt;
+static struct vfsmount *pipe_mnt __read_mostly;
static int pipefs_delete_dentry(struct dentry *dentry)
{
return 1;
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 7eb1bd7f800..7a76ad57023 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -330,7 +330,6 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
unsigned long min_flt = 0, maj_flt = 0;
cputime_t cutime, cstime, utime, stime;
unsigned long rsslim = 0;
- DEFINE_KTIME(it_real_value);
struct task_struct *t;
char tcomm[sizeof(task->comm)];
@@ -386,7 +385,6 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
utime = cputime_add(utime, task->signal->utime);
stime = cputime_add(stime, task->signal->stime);
}
- it_real_value = task->signal->real_timer.expires;
}
ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0;
read_unlock(&tasklist_lock);
@@ -413,7 +411,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
start_time = nsec_to_clock_t(start_time);
res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
-%lu %lu %lu %lu %lu %ld %ld %ld %ld %d %ld %llu %lu %ld %lu %lu %lu %lu %lu \
+%lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
%lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu\n",
task->pid,
tcomm,
@@ -435,7 +433,6 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
priority,
nice,
num_threads,
- (long) ktime_to_clock_t(it_real_value),
start_time,
vsize,
mm ? get_mm_rss(mm) : 0,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 20feb7568de..8f1f49ceebe 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -104,6 +104,7 @@ enum pid_directory_inos {
PROC_TGID_MAPS,
PROC_TGID_NUMA_MAPS,
PROC_TGID_MOUNTS,
+ PROC_TGID_MOUNTSTATS,
PROC_TGID_WCHAN,
#ifdef CONFIG_MMU
PROC_TGID_SMAPS,
@@ -144,6 +145,7 @@ enum pid_directory_inos {
PROC_TID_MAPS,
PROC_TID_NUMA_MAPS,
PROC_TID_MOUNTS,
+ PROC_TID_MOUNTSTATS,
PROC_TID_WCHAN,
#ifdef CONFIG_MMU
PROC_TID_SMAPS,
@@ -201,6 +203,7 @@ static struct pid_entry tgid_base_stuff[] = {
E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO),
E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO),
E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
+ E(PROC_TGID_MOUNTSTATS, "mountstats", S_IFREG|S_IRUSR),
#ifdef CONFIG_MMU
E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
#endif
@@ -732,6 +735,38 @@ static struct file_operations proc_mounts_operations = {
.poll = mounts_poll,
};
+extern struct seq_operations mountstats_op;
+static int mountstats_open(struct inode *inode, struct file *file)
+{
+ struct task_struct *task = proc_task(inode);
+ int ret = seq_open(file, &mountstats_op);
+
+ if (!ret) {
+ struct seq_file *m = file->private_data;
+ struct namespace *namespace;
+ task_lock(task);
+ namespace = task->namespace;
+ if (namespace)
+ get_namespace(namespace);
+ task_unlock(task);
+
+ if (namespace)
+ m->private = namespace;
+ else {
+ seq_release(inode, file);
+ ret = -EINVAL;
+ }
+ }
+ return ret;
+}
+
+static struct file_operations proc_mountstats_operations = {
+ .open = mountstats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = mounts_release,
+};
+
#define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */
static ssize_t proc_info_read(struct file * file, char __user * buf,
@@ -1730,6 +1765,10 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
inode->i_fop = &proc_smaps_operations;
break;
#endif
+ case PROC_TID_MOUNTSTATS:
+ case PROC_TGID_MOUNTSTATS:
+ inode->i_fop = &proc_mountstats_operations;
+ break;
#ifdef CONFIG_SECURITY
case PROC_TID_ATTR:
inode->i_nlink = 2;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 20e5c4509a4..4ba03009cf7 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -19,6 +19,7 @@
#include <linux/idr.h>
#include <linux/namei.h>
#include <linux/bitops.h>
+#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include "internal.h"
@@ -29,6 +30,8 @@ static ssize_t proc_file_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos);
static loff_t proc_file_lseek(struct file *, loff_t, int);
+DEFINE_SPINLOCK(proc_subdir_lock);
+
int proc_match(int len, const char *name, struct proc_dir_entry *de)
{
if (de->namelen != len)
@@ -277,7 +280,9 @@ static int xlate_proc_name(const char *name,
const char *cp = name, *next;
struct proc_dir_entry *de;
int len;
+ int rtn = 0;
+ spin_lock(&proc_subdir_lock);
de = &proc_root;
while (1) {
next = strchr(cp, '/');
@@ -289,13 +294,17 @@ static int xlate_proc_name(const char *name,
if (proc_match(len, cp, de))
break;
}
- if (!de)
- return -ENOENT;
+ if (!de) {
+ rtn = -ENOENT;
+ goto out;
+ }
cp += len + 1;
}
*residual = cp;
*ret = de;
- return 0;
+out:
+ spin_unlock(&proc_subdir_lock);
+ return rtn;
}
static DEFINE_IDR(proc_inum_idr);
@@ -380,6 +389,7 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam
int error = -ENOENT;
lock_kernel();
+ spin_lock(&proc_subdir_lock);
de = PDE(dir);
if (de) {
for (de = de->subdir; de ; de = de->next) {
@@ -388,12 +398,15 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam
if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
unsigned int ino = de->low_ino;
+ spin_unlock(&proc_subdir_lock);
error = -EINVAL;
inode = proc_get_inode(dir->i_sb, ino, de);
+ spin_lock(&proc_subdir_lock);
break;
}
}
}
+ spin_unlock(&proc_subdir_lock);
unlock_kernel();
if (inode) {
@@ -447,11 +460,13 @@ int proc_readdir(struct file * filp,
filp->f_pos++;
/* fall through */
default:
+ spin_lock(&proc_subdir_lock);
de = de->subdir;
i -= 2;
for (;;) {
if (!de) {
ret = 1;
+ spin_unlock(&proc_subdir_lock);
goto out;
}
if (!i)
@@ -461,12 +476,16 @@ int proc_readdir(struct file * filp,
}
do {
+ /* filldir passes info to user space */
+ spin_unlock(&proc_subdir_lock);
if (filldir(dirent, de->name, de->namelen, filp->f_pos,
de->low_ino, de->mode >> 12) < 0)
goto out;
+ spin_lock(&proc_subdir_lock);
filp->f_pos++;
de = de->next;
} while (de);
+ spin_unlock(&proc_subdir_lock);
}
ret = 1;
out: unlock_kernel();
@@ -500,9 +519,13 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp
if (i == 0)
return -EAGAIN;
dp->low_ino = i;
+
+ spin_lock(&proc_subdir_lock);
dp->next = dir->subdir;
dp->parent = dir;
dir->subdir = dp;
+ spin_unlock(&proc_subdir_lock);
+
if (S_ISDIR(dp->mode)) {
if (dp->proc_iops == NULL) {
dp->proc_fops = &proc_dir_operations;
@@ -537,7 +560,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de)
struct file * filp = list_entry(p, struct file, f_u.fu_list);
struct dentry * dentry = filp->f_dentry;
struct inode * inode;
- struct file_operations *fops;
+ const struct file_operations *fops;
if (dentry->d_op != &proc_dentry_operations)
continue;
@@ -694,6 +717,8 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
goto out;
len = strlen(fn);
+
+ spin_lock(&proc_subdir_lock);
for (p = &parent->subdir; *p; p=&(*p)->next ) {
if (!proc_match(len, fn, *p))
continue;
@@ -714,6 +739,7 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
}
break;
}
+ spin_unlock(&proc_subdir_lock);
out:
return;
}
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 95a1cf32b83..0502f17b860 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -30,7 +30,7 @@ do { \
#endif
-extern void create_seq_entry(char *name, mode_t mode, struct file_operations *f);
+extern void create_seq_entry(char *name, mode_t mode, const struct file_operations *f);
extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **);
extern int proc_tid_stat(struct task_struct *, char *);
extern int proc_tgid_stat(struct task_struct *, char *);
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index adc2cd95169..17f6e8fa139 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -31,7 +31,7 @@ static int open_kcore(struct inode * inode, struct file * filp)
static ssize_t read_kcore(struct file *, char __user *, size_t, loff_t *);
-struct file_operations proc_kcore_operations = {
+const struct file_operations proc_kcore_operations = {
.read = read_kcore,
.open = open_kcore,
};
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index 10d37bf2520..ff3b90b56e9 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -47,7 +47,7 @@ static unsigned int kmsg_poll(struct file *file, poll_table *wait)
}
-struct file_operations proc_kmsg_operations = {
+const struct file_operations proc_kmsg_operations = {
.read = kmsg_read,
.poll = kmsg_poll,
.open = kmsg_open,
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 9bdd077d6f5..abdf068bc27 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -52,7 +52,8 @@ static int property_read_proc(char *page, char **start, off_t off,
* Add a property to a node
*/
static struct proc_dir_entry *
-__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp)
+__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp,
+ const char *name)
{
struct proc_dir_entry *ent;
@@ -60,14 +61,14 @@ __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp)
* Unfortunately proc_register puts each new entry
* at the beginning of the list. So we rearrange them.
*/
- ent = create_proc_read_entry(pp->name,
- strncmp(pp->name, "security-", 9)
+ ent = create_proc_read_entry(name,
+ strncmp(name, "security-", 9)
? S_IRUGO : S_IRUSR, de,
property_read_proc, pp);
if (ent == NULL)
return NULL;
- if (!strncmp(pp->name, "security-", 9))
+ if (!strncmp(name, "security-", 9))
ent->size = 0; /* don't leak number of password chars */
else
ent->size = pp->length;
@@ -78,7 +79,7 @@ __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp)
void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop)
{
- __proc_device_tree_add_prop(pde, prop);
+ __proc_device_tree_add_prop(pde, prop, prop->name);
}
void proc_device_tree_remove_prop(struct proc_dir_entry *pde,
@@ -106,6 +107,69 @@ void proc_device_tree_update_prop(struct proc_dir_entry *pde,
}
/*
+ * Various dodgy firmware might give us nodes and/or properties with
+ * conflicting names. That's generally ok, except for exporting via /proc,
+ * so munge names here to ensure they're unique.
+ */
+
+static int duplicate_name(struct proc_dir_entry *de, const char *name)
+{
+ struct proc_dir_entry *ent;
+ int found = 0;
+
+ spin_lock(&proc_subdir_lock);
+
+ for (ent = de->subdir; ent != NULL; ent = ent->next) {
+ if (strcmp(ent->name, name) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ spin_unlock(&proc_subdir_lock);
+
+ return found;
+}
+
+static const char *fixup_name(struct device_node *np, struct proc_dir_entry *de,
+ const char *name)
+{
+ char *fixed_name;
+ int fixup_len = strlen(name) + 2 + 1; /* name + #x + \0 */
+ int i = 1, size;
+
+realloc:
+ fixed_name = kmalloc(fixup_len, GFP_KERNEL);
+ if (fixed_name == NULL) {
+ printk(KERN_ERR "device-tree: Out of memory trying to fixup "
+ "name \"%s\"\n", name);
+ return name;
+ }
+
+retry:
+ size = snprintf(fixed_name, fixup_len, "%s#%d", name, i);
+ size++; /* account for NULL */
+
+ if (size > fixup_len) {
+ /* We ran out of space, free and reallocate. */
+ kfree(fixed_name);
+ fixup_len = size;
+ goto realloc;
+ }
+
+ if (duplicate_name(de, fixed_name)) {
+ /* Multiple duplicates. Retry with a different offset. */
+ i++;
+ goto retry;
+ }
+
+ printk(KERN_WARNING "device-tree: Duplicate name in %s, "
+ "renamed to \"%s\"\n", np->full_name, fixed_name);
+
+ return fixed_name;
+}
+
+/*
* Process a node, adding entries for its children and its properties.
*/
void proc_device_tree_add_node(struct device_node *np,
@@ -118,35 +182,30 @@ void proc_device_tree_add_node(struct device_node *np,
set_node_proc_entry(np, de);
for (child = NULL; (child = of_get_next_child(np, child));) {
+ /* Use everything after the last slash, or the full name */
p = strrchr(child->full_name, '/');
if (!p)
p = child->full_name;
else
++p;
+
+ if (duplicate_name(de, p))
+ p = fixup_name(np, de, p);
+
ent = proc_mkdir(p, de);
if (ent == 0)
break;
proc_device_tree_add_node(child, ent);
}
of_node_put(child);
+
for (pp = np->properties; pp != 0; pp = pp->next) {
- /*
- * Yet another Apple device-tree bogosity: on some machines,
- * they have properties & nodes with the same name. Those
- * properties are quite unimportant for us though, thus we
- * simply "skip" them here, but we do have to check.
- */
- for (ent = de->subdir; ent != NULL; ent = ent->next)
- if (!strcmp(ent->name, pp->name))
- break;
- if (ent != NULL) {
- printk(KERN_WARNING "device-tree: property \"%s\" name"
- " conflicts with node in %s\n", pp->name,
- np->full_name);
- continue;
- }
+ p = pp->name;
+
+ if (duplicate_name(de, p))
+ p = fixup_name(np, de, p);
- ent = __proc_device_tree_add_prop(de, pp);
+ ent = __proc_device_tree_add_prop(de, pp, p);
if (ent == 0)
break;
}
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 826c131994c..ef5a3323f4b 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -485,6 +485,40 @@ static struct file_operations proc_slabinfo_operations = {
.llseek = seq_lseek,
.release = seq_release,
};
+
+#ifdef CONFIG_DEBUG_SLAB_LEAK
+extern struct seq_operations slabstats_op;
+static int slabstats_open(struct inode *inode, struct file *file)
+{
+ unsigned long *n = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ int ret = -ENOMEM;
+ if (n) {
+ ret = seq_open(file, &slabstats_op);
+ if (!ret) {
+ struct seq_file *m = file->private_data;
+ *n = PAGE_SIZE / (2 * sizeof(unsigned long));
+ m->private = n;
+ n = NULL;
+ }
+ kfree(n);
+ }
+ return ret;
+}
+
+static int slabstats_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *m = file->private_data;
+ kfree(m->private);
+ return seq_release(inode, file);
+}
+
+static struct file_operations proc_slabstats_operations = {
+ .open = slabstats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = slabstats_release,
+};
+#endif
#endif
static int show_stat(struct seq_file *p, void *v)
@@ -500,7 +534,7 @@ static int show_stat(struct seq_file *p, void *v)
if (wall_to_monotonic.tv_nsec)
--jif;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
int j;
user = cputime64_add(user, kstat_cpu(i).cpustat.user);
@@ -697,7 +731,7 @@ static struct file_operations proc_sysrq_trigger_operations = {
struct proc_dir_entry *proc_root_kcore;
-void create_seq_entry(char *name, mode_t mode, struct file_operations *f)
+void create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
{
struct proc_dir_entry *entry;
entry = create_proc_entry(name, mode, NULL);
@@ -744,6 +778,9 @@ void __init proc_misc_init(void)
create_seq_entry("interrupts", 0, &proc_interrupts_operations);
#ifdef CONFIG_SLAB
create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
+#ifdef CONFIG_DEBUG_SLAB_LEAK
+ create_seq_entry("slab_allocators", 0 ,&proc_slabstats_operations);
+#endif
#endif
create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 4063fb32f78..7efa73d44c9 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -172,7 +172,7 @@ static int open_vmcore(struct inode *inode, struct file *filp)
return 0;
}
-struct file_operations proc_vmcore_operations = {
+const struct file_operations proc_vmcore_operations = {
.read = read_vmcore,
.open = open_vmcore,
};
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index 7a8f5595c26..9031948fefd 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -81,7 +81,7 @@ out:
return 0;
}
-struct file_operations qnx4_dir_operations =
+const struct file_operations qnx4_dir_operations =
{
.read = generic_read_dir,
.readdir = qnx4_readdir,
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c
index c33963fded9..62af4b1348b 100644
--- a/fs/qnx4/file.c
+++ b/fs/qnx4/file.c
@@ -19,7 +19,7 @@
* We have mostly NULL's here: the current defaults are ok for
* the qnx4 filesystem.
*/
-struct file_operations qnx4_file_operations =
+const struct file_operations qnx4_file_operations =
{
.llseek = generic_file_llseek,
.read = generic_file_read,
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index 6ada2095b9a..00a933eb820 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -32,7 +32,7 @@ struct address_space_operations ramfs_aops = {
.commit_write = simple_commit_write
};
-struct file_operations ramfs_file_operations = {
+const struct file_operations ramfs_file_operations = {
.read = generic_file_read,
.write = generic_file_write,
.mmap = generic_file_mmap,
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index b1ca234068f..f443a84b98a 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -33,7 +33,7 @@ struct address_space_operations ramfs_aops = {
.commit_write = simple_commit_write
};
-struct file_operations ramfs_file_operations = {
+const struct file_operations ramfs_file_operations = {
.mmap = ramfs_nommu_mmap,
.get_unmapped_area = ramfs_nommu_get_unmapped_area,
.read = generic_file_read,
diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h
index 272c8a7120b..313237631b4 100644
--- a/fs/ramfs/internal.h
+++ b/fs/ramfs/internal.h
@@ -11,5 +11,5 @@
extern struct address_space_operations ramfs_aops;
-extern struct file_operations ramfs_file_operations;
+extern const struct file_operations ramfs_file_operations;
extern struct inode_operations ramfs_file_inode_operations;
diff --git a/fs/read_write.c b/fs/read_write.c
index 3f7a1a62165..6256ca81a71 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -19,7 +19,7 @@
#include <asm/uaccess.h>
#include <asm/unistd.h>
-struct file_operations generic_ro_fops = {
+const struct file_operations generic_ro_fops = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.mmap = generic_file_readonly_mmap,
@@ -470,7 +470,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
* verify all the pointers
*/
ret = -EINVAL;
- if ((nr_segs > UIO_MAXIOV) || (nr_segs <= 0))
+ if (nr_segs > UIO_MAXIOV)
goto out;
if (!file->f_op)
goto out;
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
index d71ac657928..973c819f803 100644
--- a/fs/reiserfs/dir.c
+++ b/fs/reiserfs/dir.c
@@ -18,7 +18,7 @@ static int reiserfs_readdir(struct file *, void *, filldir_t);
static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
int datasync);
-struct file_operations reiserfs_dir_operations = {
+const struct file_operations reiserfs_dir_operations = {
.read = generic_read_dir,
.readdir = reiserfs_readdir,
.fsync = reiserfs_dir_fsync,
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index be12879bb17..010094d14da 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1532,7 +1532,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
buf += write_bytes;
*ppos = pos += write_bytes;
count -= write_bytes;
- balance_dirty_pages_ratelimited(inode->i_mapping);
+ balance_dirty_pages_ratelimited_nr(inode->i_mapping, num_pages);
}
/* this is only true on error */
@@ -1546,10 +1546,10 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
}
}
- if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
- res =
- generic_osync_inode(inode, file->f_mapping,
- OSYNC_METADATA | OSYNC_DATA);
+ if (likely(res >= 0) &&
+ (unlikely((file->f_flags & O_SYNC) || IS_SYNC(inode))))
+ res = generic_osync_inode(inode, file->f_mapping,
+ OSYNC_METADATA | OSYNC_DATA);
mutex_unlock(&inode->i_mutex);
reiserfs_async_progress_wait(inode->i_sb);
@@ -1566,7 +1566,7 @@ static ssize_t reiserfs_aio_write(struct kiocb *iocb, const char __user * buf,
return generic_file_aio_write(iocb, buf, count, pos);
}
-struct file_operations reiserfs_file_operations = {
+const struct file_operations reiserfs_file_operations = {
.read = generic_file_read,
.write = reiserfs_file_write,
.ioctl = reiserfs_ioctl,
diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c
index aa22588019e..5600d3d60cf 100644
--- a/fs/reiserfs/fix_node.c
+++ b/fs/reiserfs/fix_node.c
@@ -191,9 +191,7 @@ static void create_virtual_node(struct tree_balance *tb, int h)
"vs-8045: create_virtual_node: rdkey %k, affected item==%d (mode==%c) Must be %c",
key, vn->vn_affected_item_num,
vn->vn_mode, M_DELETE);
- } else
- /* we can delete directory item, that has only one directory entry in it */
- ;
+ }
}
#endif
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index d60f6238c66..9857e50f85e 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -466,7 +466,6 @@ static int reiserfs_get_block_create_0(struct inode *inode, sector_t block,
direct_IO request. */
static int reiserfs_get_blocks_direct_io(struct inode *inode,
sector_t iblock,
- unsigned long max_blocks,
struct buffer_head *bh_result,
int create)
{
@@ -2793,7 +2792,7 @@ static int invalidatepage_can_drop(struct inode *inode, struct buffer_head *bh)
}
/* clm -- taken from fs/buffer.c:block_invalidate_page */
-static int reiserfs_invalidatepage(struct page *page, unsigned long offset)
+static void reiserfs_invalidatepage(struct page *page, unsigned long offset)
{
struct buffer_head *head, *bh, *next;
struct inode *inode = page->mapping->host;
@@ -2832,10 +2831,12 @@ static int reiserfs_invalidatepage(struct page *page, unsigned long offset)
* The get_block cached value has been unconditionally invalidated,
* so real IO is not possible anymore.
*/
- if (!offset && ret)
+ if (!offset && ret) {
ret = try_to_release_page(page, 0);
+ /* maybe should BUG_ON(!ret); - neilb */
+ }
out:
- return ret;
+ return;
}
static int reiserfs_set_page_dirty(struct page *page)
diff --git a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c
index e237cd668e5..7a88adbceef 100644
--- a/fs/reiserfs/item_ops.c
+++ b/fs/reiserfs/item_ops.c
@@ -275,7 +275,7 @@ static void indirect_print_item(struct item_head *ih, char *item)
int j;
__le32 *unp;
__u32 prev = INT_MAX;
- int num;
+ int num = 0;
unp = (__le32 *) item;
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 5a9d2722fa0..1b73529b809 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -2227,6 +2227,9 @@ static int journal_read_transaction(struct super_block *p_s_sb,
journal->j_start = cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb);
journal->j_last_flush_trans_id = trans_id;
journal->j_trans_id = trans_id + 1;
+ /* check for trans_id overflow */
+ if (journal->j_trans_id == 0)
+ journal->j_trans_id = 10;
brelse(c_bh);
brelse(d_bh);
kfree(log_blocks);
@@ -2450,6 +2453,9 @@ static int journal_read(struct super_block *p_s_sb)
journal->j_start = le32_to_cpu(jh->j_first_unflushed_offset);
journal->j_trans_id =
le32_to_cpu(jh->j_last_flush_trans_id) + 1;
+ /* check for trans_id overflow */
+ if (journal->j_trans_id == 0)
+ journal->j_trans_id = 10;
journal->j_last_flush_trans_id =
le32_to_cpu(jh->j_last_flush_trans_id);
journal->j_mount_id = le32_to_cpu(jh->j_mount_id) + 1;
@@ -3873,8 +3879,8 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
int cur_write_start = 0; /* start index of current log write */
int old_start;
int i;
- int flush = flags & FLUSH_ALL;
- int wait_on_commit = flags & WAIT;
+ int flush;
+ int wait_on_commit;
struct reiserfs_journal_list *jl, *temp_jl;
struct list_head *entry, *safe;
unsigned long jindex;
@@ -3884,6 +3890,13 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
BUG_ON(th->t_refcount > 1);
BUG_ON(!th->t_trans_id);
+ /* protect flush_older_commits from doing mistakes if the
+ transaction ID counter gets overflowed. */
+ if (th->t_trans_id == ~0UL)
+ flags |= FLUSH_ALL | COMMIT_NOW | WAIT;
+ flush = flags & FLUSH_ALL;
+ wait_on_commit = flags & WAIT;
+
put_fs_excl();
current->journal_info = th->t_handle_save;
reiserfs_check_lock_depth(p_s_sb, "journal end");
@@ -4105,7 +4118,9 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
journal->j_first = NULL;
journal->j_len = 0;
journal->j_trans_start_time = 0;
- journal->j_trans_id++;
+ /* check for trans_id overflow */
+ if (++journal->j_trans_id == 0)
+ journal->j_trans_id = 10;
journal->j_current_jl->j_trans_id = journal->j_trans_id;
journal->j_must_wait = 0;
journal->j_len_alloc = 0;
diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c
index 78b40621b88..27bd3a1df2a 100644
--- a/fs/reiserfs/prints.c
+++ b/fs/reiserfs/prints.c
@@ -143,7 +143,7 @@ static void sprintf_buffer_head(char *buf, struct buffer_head *bh)
char b[BDEVNAME_SIZE];
sprintf(buf,
- "dev %s, size %d, blocknr %llu, count %d, state 0x%lx, page %p, (%s, %s, %s)",
+ "dev %s, size %zd, blocknr %llu, count %d, state 0x%lx, page %p, (%s, %s, %s)",
bdevname(bh->b_bdev, b), bh->b_size,
(unsigned long long)bh->b_blocknr, atomic_read(&(bh->b_count)),
bh->b_state, bh->b_page,
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index ef6caed9336..731688e1cfe 100644
--- a/fs/reiserfs/procfs.c
+++ b/fs/reiserfs/procfs.c
@@ -470,7 +470,7 @@ static int r_open(struct inode *inode, struct file *file)
return ret;
}
-static struct file_operations r_file_operations = {
+static const struct file_operations r_file_operations = {
.open = r_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index e2d08d7bcff..d2b25e1ba6e 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -981,6 +981,8 @@ static inline int prepare_for_direntry_item(struct path *path,
return M_CUT;
}
+#define JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD (2 * JOURNAL_PER_BALANCE_CNT + 1)
+
/* If the path points to a directory or direct item, calculate mode and the size cut, for balance.
If the path points to an indirect item, remove some number of its unformatted nodes.
In case of file truncate calculate whether this item must be deleted/truncated or last
@@ -1020,148 +1022,79 @@ static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, st
/* Case of an indirect item. */
{
- int n_unfm_number, /* Number of the item unformatted nodes. */
- n_counter, n_blk_size;
- __le32 *p_n_unfm_pointer; /* Pointer to the unformatted node number. */
- __u32 tmp;
- struct item_head s_ih; /* Item header. */
- char c_mode; /* Returned mode of the balance. */
- int need_research;
-
- n_blk_size = p_s_sb->s_blocksize;
-
- /* Search for the needed object indirect item until there are no unformatted nodes to be removed. */
- do {
- need_research = 0;
- p_s_bh = PATH_PLAST_BUFFER(p_s_path);
- /* Copy indirect item header to a temp variable. */
- copy_item_head(&s_ih, PATH_PITEM_HEAD(p_s_path));
- /* Calculate number of unformatted nodes in this item. */
- n_unfm_number = I_UNFM_NUM(&s_ih);
-
- RFALSE(!is_indirect_le_ih(&s_ih) || !n_unfm_number ||
- pos_in_item(p_s_path) + 1 != n_unfm_number,
- "PAP-5240: invalid item %h "
- "n_unfm_number = %d *p_n_pos_in_item = %d",
- &s_ih, n_unfm_number, pos_in_item(p_s_path));
-
- /* Calculate balance mode and position in the item to remove unformatted nodes. */
- if (n_new_file_length == max_reiserfs_offset(inode)) { /* Case of delete. */
- pos_in_item(p_s_path) = 0;
- *p_n_cut_size = -(IH_SIZE + ih_item_len(&s_ih));
- c_mode = M_DELETE;
- } else { /* Case of truncate. */
- if (n_new_file_length < le_ih_k_offset(&s_ih)) {
- pos_in_item(p_s_path) = 0;
- *p_n_cut_size =
- -(IH_SIZE + ih_item_len(&s_ih));
- c_mode = M_DELETE; /* Delete this item. */
- } else {
- /* indirect item must be truncated starting from *p_n_pos_in_item-th position */
- pos_in_item(p_s_path) =
- (n_new_file_length + n_blk_size -
- le_ih_k_offset(&s_ih)) >> p_s_sb->
- s_blocksize_bits;
-
- RFALSE(pos_in_item(p_s_path) >
- n_unfm_number,
- "PAP-5250: invalid position in the item");
-
- /* Either convert last unformatted node of indirect item to direct item or increase
- its free space. */
- if (pos_in_item(p_s_path) ==
- n_unfm_number) {
- *p_n_cut_size = 0; /* Nothing to cut. */
- return M_CONVERT; /* Maybe convert last unformatted node to the direct item. */
- }
- /* Calculate size to cut. */
- *p_n_cut_size =
- -(ih_item_len(&s_ih) -
- pos_in_item(p_s_path) *
- UNFM_P_SIZE);
-
- c_mode = M_CUT; /* Cut from this indirect item. */
- }
- }
+ int blk_size = p_s_sb->s_blocksize;
+ struct item_head s_ih;
+ int need_re_search;
+ int delete = 0;
+ int result = M_CUT;
+ int pos = 0;
+
+ if ( n_new_file_length == max_reiserfs_offset (inode) ) {
+ /* prepare_for_delete_or_cut() is called by
+ * reiserfs_delete_item() */
+ n_new_file_length = 0;
+ delete = 1;
+ }
+
+ do {
+ need_re_search = 0;
+ *p_n_cut_size = 0;
+ p_s_bh = PATH_PLAST_BUFFER(p_s_path);
+ copy_item_head(&s_ih, PATH_PITEM_HEAD(p_s_path));
+ pos = I_UNFM_NUM(&s_ih);
- RFALSE(n_unfm_number <= pos_in_item(p_s_path),
- "PAP-5260: invalid position in the indirect item");
-
- /* pointers to be cut */
- n_unfm_number -= pos_in_item(p_s_path);
- /* Set pointer to the last unformatted node pointer that is to be cut. */
- p_n_unfm_pointer =
- (__le32 *) B_I_PITEM(p_s_bh,
- &s_ih) + I_UNFM_NUM(&s_ih) -
- 1 - *p_n_removed;
-
- /* We go through the unformatted nodes pointers of the indirect
- item and look for the unformatted nodes in the cache. If we
- found some of them we free it, zero corresponding indirect item
- entry and log buffer containing that indirect item. For this we
- need to prepare last path element for logging. If some
- unformatted node has b_count > 1 we must not free this
- unformatted node since it is in use. */
- reiserfs_prepare_for_journal(p_s_sb, p_s_bh, 1);
- // note: path could be changed, first line in for loop takes care
- // of it
+ while (le_ih_k_offset (&s_ih) + (pos - 1) * blk_size > n_new_file_length) {
+ __u32 *unfm, block;
- for (n_counter = *p_n_removed;
- n_counter < n_unfm_number;
- n_counter++, p_n_unfm_pointer--) {
+ /* Each unformatted block deletion may involve one additional
+ * bitmap block into the transaction, thereby the initial
+ * journal space reservation might not be enough. */
+ if (!delete && (*p_n_cut_size) != 0 &&
+ reiserfs_transaction_free_space(th) < JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD) {
+ break;
+ }
- cond_resched();
- if (item_moved(&s_ih, p_s_path)) {
- need_research = 1;
- break;
- }
- RFALSE(p_n_unfm_pointer <
- (__le32 *) B_I_PITEM(p_s_bh, &s_ih)
- || p_n_unfm_pointer >
- (__le32 *) B_I_PITEM(p_s_bh,
- &s_ih) +
- I_UNFM_NUM(&s_ih) - 1,
- "vs-5265: pointer out of range");
-
- /* Hole, nothing to remove. */
- if (!get_block_num(p_n_unfm_pointer, 0)) {
- (*p_n_removed)++;
- continue;
- }
+ unfm = (__u32 *)B_I_PITEM(p_s_bh, &s_ih) + pos - 1;
+ block = get_block_num(unfm, 0);
- (*p_n_removed)++;
+ if (block != 0) {
+ reiserfs_prepare_for_journal(p_s_sb, p_s_bh, 1);
+ put_block_num(unfm, 0, 0);
+ journal_mark_dirty (th, p_s_sb, p_s_bh);
+ reiserfs_free_block(th, inode, block, 1);
+ }
- tmp = get_block_num(p_n_unfm_pointer, 0);
- put_block_num(p_n_unfm_pointer, 0, 0);
- journal_mark_dirty(th, p_s_sb, p_s_bh);
- reiserfs_free_block(th, inode, tmp, 1);
- if (item_moved(&s_ih, p_s_path)) {
- need_research = 1;
- break;
- }
- }
+ cond_resched();
- /* a trick. If the buffer has been logged, this
- ** will do nothing. If we've broken the loop without
- ** logging it, it will restore the buffer
- **
- */
- reiserfs_restore_prepared_buffer(p_s_sb, p_s_bh);
-
- /* This loop can be optimized. */
- } while ((*p_n_removed < n_unfm_number || need_research) &&
- search_for_position_by_key(p_s_sb, p_s_item_key,
- p_s_path) ==
- POSITION_FOUND);
-
- RFALSE(*p_n_removed < n_unfm_number,
- "PAP-5310: indirect item is not found");
- RFALSE(item_moved(&s_ih, p_s_path),
- "after while, comp failed, retry");
-
- if (c_mode == M_CUT)
- pos_in_item(p_s_path) *= UNFM_P_SIZE;
- return c_mode;
+ if (item_moved (&s_ih, p_s_path)) {
+ need_re_search = 1;
+ break;
+ }
+
+ pos --;
+ (*p_n_removed) ++;
+ (*p_n_cut_size) -= UNFM_P_SIZE;
+
+ if (pos == 0) {
+ (*p_n_cut_size) -= IH_SIZE;
+ result = M_DELETE;
+ break;
+ }
+ }
+ /* a trick. If the buffer has been logged, this will do nothing. If
+ ** we've broken the loop without logging it, it will restore the
+ ** buffer */
+ reiserfs_restore_prepared_buffer(p_s_sb, p_s_bh);
+ } while (need_re_search &&
+ search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path) == POSITION_FOUND);
+ pos_in_item(p_s_path) = pos * UNFM_P_SIZE;
+
+ if (*p_n_cut_size == 0) {
+ /* Nothing were cut. maybe convert last unformatted node to the
+ * direct item? */
+ result = M_CONVERT;
+ }
+ return result;
}
}
@@ -1948,7 +1881,8 @@ int reiserfs_do_truncate(struct reiserfs_transaction_handle *th, struct inode *p
** sure the file is consistent before ending the current trans
** and starting a new one
*/
- if (journal_transaction_should_end(th, th->t_blocks_allocated)) {
+ if (journal_transaction_should_end(th, 0) ||
+ reiserfs_transaction_free_space(th) <= JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD) {
int orig_len_alloc = th->t_blocks_allocated;
decrement_counters_in_path(&s_search_path);
@@ -1962,7 +1896,7 @@ int reiserfs_do_truncate(struct reiserfs_transaction_handle *th, struct inode *p
if (err)
goto out;
err = journal_begin(th, p_s_inode->i_sb,
- JOURNAL_PER_BALANCE_CNT * 6);
+ JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD + JOURNAL_PER_BALANCE_CNT * 4) ;
if (err)
goto out;
reiserfs_update_inode_transaction(p_s_inode);
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 93e6ef9360e..cae2abbc0c7 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -685,14 +685,14 @@ static const arg_desc_t logging_mode[] = {
(1 << REISERFS_DATA_ORDERED | 1 << REISERFS_DATA_WRITEBACK)},
{"writeback", 1 << REISERFS_DATA_WRITEBACK,
(1 << REISERFS_DATA_ORDERED | 1 << REISERFS_DATA_LOG)},
- {NULL, 0}
+ {.value = NULL}
};
/* possible values for -o barrier= */
static const arg_desc_t barrier_mode[] = {
{"none", 1 << REISERFS_BARRIER_NONE, 1 << REISERFS_BARRIER_FLUSH},
{"flush", 1 << REISERFS_BARRIER_FLUSH, 1 << REISERFS_BARRIER_NONE},
- {NULL, 0}
+ {.value = NULL}
};
/* possible values for "-o block-allocator=" and bits which are to be set in
@@ -890,7 +890,7 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
{"acl",.setmask = 1 << REISERFS_UNSUPPORTED_OPT},
{"noacl",.clrmask = 1 << REISERFS_UNSUPPORTED_OPT},
#endif
- {"nolog",}, /* This is unsupported */
+ {.option_name = "nolog"},
{"replayonly",.setmask = 1 << REPLAYONLY},
{"block-allocator",.arg_required = 'a',.values = balloc},
{"data",.arg_required = 'd',.values = logging_mode},
@@ -908,7 +908,7 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
{"grpjquota",.arg_required =
'g' | (1 << REISERFS_OPT_ALLOWEMPTY),.values = NULL},
{"jqfmt",.arg_required = 'f',.values = NULL},
- {NULL,}
+ {.option_name = NULL}
};
*blocks = 0;
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index ab8894c3b9e..58c418fbca2 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -182,7 +182,7 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
{
char *name, *value;
struct posix_acl *acl, **p_acl;
- size_t size;
+ int size;
int retval;
struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
@@ -206,7 +206,7 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
return posix_acl_dup(*p_acl);
size = reiserfs_xattr_get(inode, name, NULL, 0);
- if ((int)size < 0) {
+ if (size < 0) {
if (size == -ENODATA || size == -ENOSYS) {
*p_acl = ERR_PTR(-ENODATA);
return NULL;
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index c2fc424d7d5..9b9eda7b335 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -463,7 +463,7 @@ static struct address_space_operations romfs_aops = {
.readpage = romfs_readpage
};
-static struct file_operations romfs_dir_operations = {
+static const struct file_operations romfs_dir_operations = {
.read = generic_read_dir,
.readdir = romfs_readdir,
};
diff --git a/fs/select.c b/fs/select.c
index 1815a57d225..b3a3a1326af 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -29,12 +29,6 @@
#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
-struct poll_table_entry {
- struct file * filp;
- wait_queue_t wait;
- wait_queue_head_t * wait_address;
-};
-
struct poll_table_page {
struct poll_table_page * next;
struct poll_table_entry * entry;
@@ -64,13 +58,23 @@ void poll_initwait(struct poll_wqueues *pwq)
init_poll_funcptr(&pwq->pt, __pollwait);
pwq->error = 0;
pwq->table = NULL;
+ pwq->inline_index = 0;
}
EXPORT_SYMBOL(poll_initwait);
+static void free_poll_entry(struct poll_table_entry *entry)
+{
+ remove_wait_queue(entry->wait_address,&entry->wait);
+ fput(entry->filp);
+}
+
void poll_freewait(struct poll_wqueues *pwq)
{
struct poll_table_page * p = pwq->table;
+ int i;
+ for (i = 0; i < pwq->inline_index; i++)
+ free_poll_entry(pwq->inline_entries + i);
while (p) {
struct poll_table_entry * entry;
struct poll_table_page *old;
@@ -78,8 +82,7 @@ void poll_freewait(struct poll_wqueues *pwq)
entry = p->entry;
do {
entry--;
- remove_wait_queue(entry->wait_address,&entry->wait);
- fput(entry->filp);
+ free_poll_entry(entry);
} while (entry > p->entries);
old = p;
p = p->next;
@@ -89,12 +92,14 @@ void poll_freewait(struct poll_wqueues *pwq)
EXPORT_SYMBOL(poll_freewait);
-static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
- poll_table *_p)
+static struct poll_table_entry *poll_get_entry(poll_table *_p)
{
struct poll_wqueues *p = container_of(_p, struct poll_wqueues, pt);
struct poll_table_page *table = p->table;
+ if (p->inline_index < N_INLINE_POLL_ENTRIES)
+ return p->inline_entries + p->inline_index++;
+
if (!table || POLL_TABLE_FULL(table)) {
struct poll_table_page *new_table;
@@ -102,7 +107,7 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
if (!new_table) {
p->error = -ENOMEM;
__set_current_state(TASK_RUNNING);
- return;
+ return NULL;
}
new_table->entry = new_table->entries;
new_table->next = table;
@@ -110,16 +115,21 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
table = new_table;
}
- /* Add a new entry */
- {
- struct poll_table_entry * entry = table->entry;
- table->entry = entry+1;
- get_file(filp);
- entry->filp = filp;
- entry->wait_address = wait_address;
- init_waitqueue_entry(&entry->wait, current);
- add_wait_queue(wait_address,&entry->wait);
- }
+ return table->entry++;
+}
+
+/* Add a new entry */
+static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
+ poll_table *p)
+{
+ struct poll_table_entry *entry = poll_get_entry(p);
+ if (!entry)
+ return;
+ get_file(filp);
+ entry->filp = filp;
+ entry->wait_address = wait_address;
+ init_waitqueue_entry(&entry->wait, current);
+ add_wait_queue(wait_address,&entry->wait);
}
#define FDS_IN(fds, n) (fds->in + n)
@@ -210,7 +220,7 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout)
for (i = 0; i < n; ++rinp, ++routp, ++rexp) {
unsigned long in, out, ex, all_bits, bit = 1, mask, j;
unsigned long res_in = 0, res_out = 0, res_ex = 0;
- struct file_operations *f_op = NULL;
+ const struct file_operations *f_op = NULL;
struct file *file = NULL;
in = *inp++; out = *outp++; ex = *exp++;
@@ -221,17 +231,18 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout)
}
for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) {
+ int fput_needed;
if (i >= n)
break;
if (!(bit & all_bits))
continue;
- file = fget(i);
+ file = fget_light(i, &fput_needed);
if (file) {
f_op = file->f_op;
mask = DEFAULT_POLLMASK;
if (f_op && f_op->poll)
mask = (*f_op->poll)(file, retval ? NULL : wait);
- fput(file);
+ fput_light(file, fput_needed);
if ((mask & POLLIN_SET) && (in & bit)) {
res_in |= bit;
retval++;
@@ -284,16 +295,6 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout)
return retval;
}
-static void *select_bits_alloc(int size)
-{
- return kmalloc(6 * size, GFP_KERNEL);
-}
-
-static void select_bits_free(void *bits, int size)
-{
- kfree(bits);
-}
-
/*
* We can actually return ERESTARTSYS instead of EINTR, but I'd
* like to be certain this leads to no problems. So I return
@@ -312,6 +313,8 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
char *bits;
int ret, size, max_fdset;
struct fdtable *fdt;
+ /* Allocate small arguments on the stack to save memory and be faster */
+ char stack_fds[SELECT_STACK_ALLOC];
ret = -EINVAL;
if (n < 0)
@@ -332,7 +335,10 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
*/
ret = -ENOMEM;
size = FDS_BYTES(n);
- bits = select_bits_alloc(size);
+ if (6*size < SELECT_STACK_ALLOC)
+ bits = stack_fds;
+ else
+ bits = kmalloc(6 * size, GFP_KERNEL);
if (!bits)
goto out_nofds;
fds.in = (unsigned long *) bits;
@@ -367,7 +373,8 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
ret = -EFAULT;
out:
- select_bits_free(bits, size);
+ if (bits != stack_fds)
+ kfree(bits);
out_nofds:
return ret;
}
@@ -551,14 +558,15 @@ static void do_pollfd(unsigned int num, struct pollfd * fdpage,
fdp = fdpage+i;
fd = fdp->fd;
if (fd >= 0) {
- struct file * file = fget(fd);
+ int fput_needed;
+ struct file * file = fget_light(fd, &fput_needed);
mask = POLLNVAL;
if (file != NULL) {
mask = DEFAULT_POLLMASK;
if (file->f_op && file->f_op->poll)
mask = file->f_op->poll(file, *pwait);
mask &= fdp->events | POLLERR | POLLHUP;
- fput(file);
+ fput_light(file, fput_needed);
}
if (mask) {
*pwait = NULL;
@@ -619,6 +627,9 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
return count;
}
+#define N_STACK_PPS ((sizeof(stack_pps) - sizeof(struct poll_list)) / \
+ sizeof(struct pollfd))
+
int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
{
struct poll_wqueues table;
@@ -628,6 +639,9 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
struct poll_list *walk;
struct fdtable *fdt;
int max_fdset;
+ /* Allocate small arguments on the stack to save memory and be faster */
+ char stack_pps[POLL_STACK_ALLOC];
+ struct poll_list *stack_pp = NULL;
/* Do a sanity check on nfds ... */
rcu_read_lock();
@@ -645,14 +659,23 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
err = -ENOMEM;
while(i!=0) {
struct poll_list *pp;
- pp = kmalloc(sizeof(struct poll_list)+
- sizeof(struct pollfd)*
- (i>POLLFD_PER_PAGE?POLLFD_PER_PAGE:i),
- GFP_KERNEL);
- if(pp==NULL)
- goto out_fds;
+ int num, size;
+ if (stack_pp == NULL)
+ num = N_STACK_PPS;
+ else
+ num = POLLFD_PER_PAGE;
+ if (num > i)
+ num = i;
+ size = sizeof(struct poll_list) + sizeof(struct pollfd)*num;
+ if (!stack_pp)
+ stack_pp = pp = (struct poll_list *)stack_pps;
+ else {
+ pp = kmalloc(size, GFP_KERNEL);
+ if (!pp)
+ goto out_fds;
+ }
pp->next=NULL;
- pp->len = (i>POLLFD_PER_PAGE?POLLFD_PER_PAGE:i);
+ pp->len = num;
if (head == NULL)
head = pp;
else
@@ -660,7 +683,7 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
walk = pp;
if (copy_from_user(pp->entries, ufds + nfds-i,
- sizeof(struct pollfd)*pp->len)) {
+ sizeof(struct pollfd)*num)) {
err = -EFAULT;
goto out_fds;
}
@@ -689,7 +712,8 @@ out_fds:
walk = head;
while(walk!=NULL) {
struct poll_list *pp = walk->next;
- kfree(walk);
+ if (walk != stack_pp)
+ kfree(walk);
walk = pp;
}
poll_freewait(&table);
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index 0424d06b147..34c7a11d91f 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -34,7 +34,7 @@ static int smb_rename(struct inode *, struct dentry *,
static int smb_make_node(struct inode *,struct dentry *,int,dev_t);
static int smb_link(struct dentry *, struct inode *, struct dentry *);
-struct file_operations smb_dir_operations =
+const struct file_operations smb_dir_operations =
{
.read = generic_read_dir,
.readdir = smb_readdir,
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index 7042e62726a..c56bd99a970 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -401,7 +401,7 @@ smb_file_permission(struct inode *inode, int mask, struct nameidata *nd)
return error;
}
-struct file_operations smb_file_operations =
+const struct file_operations smb_file_operations =
{
.llseek = remote_llseek,
.read = smb_file_read,
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 44ed1d418b4..fdeabc0a34f 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -217,7 +217,7 @@ smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
if (inode->i_mtime.tv_sec != last_time || inode->i_size != last_sz) {
VERBOSE("%ld changed, old=%ld, new=%ld, oz=%ld, nz=%ld\n",
inode->i_ino,
- (long) last_time, (long) inode->i_mtime,
+ (long) last_time, (long) inode->i_mtime.tv_sec,
(long) last_sz, (long) inode->i_size);
if (!S_ISDIR(inode->i_mode))
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h
index e866ec8660d..47664597e6b 100644
--- a/fs/smbfs/proto.h
+++ b/fs/smbfs/proto.h
@@ -35,7 +35,7 @@ extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const
extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry);
extern void smb_install_null_ops(struct smb_ops *ops);
/* dir.c */
-extern struct file_operations smb_dir_operations;
+extern const struct file_operations smb_dir_operations;
extern struct inode_operations smb_dir_inode_operations;
extern struct inode_operations smb_dir_inode_operations_unix;
extern void smb_new_dentry(struct dentry *dentry);
@@ -64,7 +64,7 @@ extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
/* file.c */
extern struct address_space_operations smb_file_aops;
-extern struct file_operations smb_file_operations;
+extern const struct file_operations smb_file_operations;
extern struct inode_operations smb_file_inode_operations;
/* ioctl.c */
extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
diff --git a/fs/super.c b/fs/super.c
index 37554b87618..a66f66bb804 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -37,6 +37,7 @@
#include <linux/writeback.h> /* for the emergency remount stuff */
#include <linux/idr.h>
#include <linux/kobject.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
@@ -55,11 +56,10 @@ DEFINE_SPINLOCK(sb_lock);
*/
static struct super_block *alloc_super(void)
{
- struct super_block *s = kmalloc(sizeof(struct super_block), GFP_USER);
+ struct super_block *s = kzalloc(sizeof(struct super_block), GFP_USER);
static struct super_operations default_op;
if (s) {
- memset(s, 0, sizeof(struct super_block));
if (security_sb_alloc(s)) {
kfree(s);
s = NULL;
@@ -381,9 +381,9 @@ restart:
void sync_filesystems(int wait)
{
struct super_block *sb;
- static DECLARE_MUTEX(mutex);
+ static DEFINE_MUTEX(mutex);
- down(&mutex); /* Could be down_interruptible */
+ mutex_lock(&mutex); /* Could be down_interruptible */
spin_lock(&sb_lock);
list_for_each_entry(sb, &super_blocks, s_list) {
if (!sb->s_op->sync_fs)
@@ -412,7 +412,7 @@ restart:
goto restart;
}
spin_unlock(&sb_lock);
- up(&mutex);
+ mutex_unlock(&mutex);
}
/**
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 78899eeab97..c16a93c353c 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -163,7 +163,7 @@ static int release(struct inode * inode, struct file * file)
return 0;
}
-struct file_operations bin_fops = {
+const struct file_operations bin_fops = {
.read = read,
.write = write,
.mmap = mmap,
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 9ee95686444..f26880a4785 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -503,7 +503,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
return offset;
}
-struct file_operations sysfs_dir_operations = {
+const struct file_operations sysfs_dir_operations = {
.open = sysfs_dir_open,
.release = sysfs_dir_close,
.llseek = sysfs_dir_lseek,
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 5e83e724678..830f76fa098 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -348,7 +348,7 @@ static int sysfs_release(struct inode * inode, struct file * filp)
return 0;
}
-struct file_operations sysfs_file_operations = {
+const struct file_operations sysfs_file_operations = {
.read = sysfs_read_file,
.write = sysfs_write_file,
.llseek = generic_file_llseek,
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index cf11d5b789d..32958a7c50e 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -21,9 +21,9 @@ extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
extern struct rw_semaphore sysfs_rename_sem;
extern struct super_block * sysfs_sb;
-extern struct file_operations sysfs_dir_operations;
-extern struct file_operations sysfs_file_operations;
-extern struct file_operations bin_fops;
+extern const struct file_operations sysfs_dir_operations;
+extern const struct file_operations sysfs_file_operations;
+extern const struct file_operations bin_fops;
extern struct inode_operations sysfs_dir_inode_operations;
extern struct inode_operations sysfs_symlink_inode_operations;
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index cce8b05cba5..8c66e9270dd 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -20,7 +20,7 @@
static int sysv_readdir(struct file *, void *, filldir_t);
-struct file_operations sysv_dir_operations = {
+const struct file_operations sysv_dir_operations = {
.read = generic_read_dir,
.readdir = sysv_readdir,
.fsync = sysv_sync_file,
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index da69abc0624..a59e303135f 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -19,7 +19,7 @@
* We have mostly NULLs here: the current defaults are OK for
* the coh filesystem.
*/
-struct file_operations sysv_file_operations = {
+const struct file_operations sysv_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index b7f9b4a42aa..393a480e4de 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -159,8 +159,8 @@ extern ino_t sysv_inode_by_name(struct dentry *);
extern struct inode_operations sysv_file_inode_operations;
extern struct inode_operations sysv_dir_inode_operations;
extern struct inode_operations sysv_fast_symlink_inode_operations;
-extern struct file_operations sysv_file_operations;
-extern struct file_operations sysv_dir_operations;
+extern const struct file_operations sysv_file_operations;
+extern const struct file_operations sysv_dir_operations;
extern struct address_space_operations sysv_aops;
extern struct super_operations sysv_sops;
extern struct dentry_operations sysv_dentry_operations;
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index f5222527fe3..8c28efa3b8f 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -42,7 +42,7 @@ static int do_udf_readdir(struct inode *, struct file *, filldir_t, void *);
/* readdir and lookup functions */
-struct file_operations udf_dir_operations = {
+const struct file_operations udf_dir_operations = {
.read = generic_read_dir,
.readdir = udf_readdir,
.ioctl = udf_ioctl,
diff --git a/fs/udf/file.c b/fs/udf/file.c
index a6f2acc1f15..e34b00e303f 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -248,7 +248,7 @@ static int udf_release_file(struct inode * inode, struct file * filp)
return 0;
}
-struct file_operations udf_file_operations = {
+const struct file_operations udf_file_operations = {
.read = generic_file_read,
.ioctl = udf_ioctl,
.open = generic_file_open,
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index d04cff2273b..81e0e8459af 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1341,13 +1341,11 @@ udf_update_inode(struct inode *inode, int do_sync)
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET))
fe->uid = cpu_to_le32(-1);
- else if (inode->i_uid != UDF_SB(inode->i_sb)->s_uid)
- fe->uid = cpu_to_le32(inode->i_uid);
+ else fe->uid = cpu_to_le32(inode->i_uid);
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_FORGET))
fe->gid = cpu_to_le32(-1);
- else if (inode->i_gid != UDF_SB(inode->i_sb)->s_gid)
- fe->gid = cpu_to_le32(inode->i_gid);
+ else fe->gid = cpu_to_le32(inode->i_gid);
udfperms = ((inode->i_mode & S_IRWXO) ) |
((inode->i_mode & S_IRWXG) << 2) |
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 1d5800e0cbe..023e19ba5a2 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -44,9 +44,9 @@ struct buffer_head;
struct super_block;
extern struct inode_operations udf_dir_inode_operations;
-extern struct file_operations udf_dir_operations;
+extern const struct file_operations udf_dir_operations;
extern struct inode_operations udf_file_inode_operations;
-extern struct file_operations udf_file_operations;
+extern const struct file_operations udf_file_operations;
extern struct address_space_operations udf_aops;
extern struct address_space_operations udf_adinicb_aops;
extern struct address_space_operations udf_symlink_aops;
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 7c10c68902a..1a561202d3f 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -620,7 +620,7 @@ int ufs_empty_dir (struct inode * inode)
return 1;
}
-struct file_operations ufs_dir_operations = {
+const struct file_operations ufs_dir_operations = {
.read = generic_read_dir,
.readdir = ufs_readdir,
.fsync = file_fsync,
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
index 62ad481810e..312fd3f8631 100644
--- a/fs/ufs/file.c
+++ b/fs/ufs/file.c
@@ -31,7 +31,7 @@
* the ufs filesystem.
*/
-struct file_operations ufs_file_operations = {
+const struct file_operations ufs_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index d257644a1ae..db98a4c71e6 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -575,7 +575,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
if (!silent)
printk("You didn't specify the type of your ufs filesystem\n\n"
"mount -t ufs -o ufstype="
- "sun|sunx86|44bsd|ufs2|5xbsd|old|hp|nextstep|netxstep-cd|openstep ...\n\n"
+ "sun|sunx86|44bsd|ufs2|5xbsd|old|hp|nextstep|nextstep-cd|openstep ...\n\n"
">>>WARNING<<< Wrong ufstype may corrupt your filesystem, "
"default is ufstype=old\n");
ufs_set_opt (sbi->s_mount_opt, UFSTYPE_OLD);
diff --git a/fs/xattr.c b/fs/xattr.c
index 80eca7d3d69..e416190f5e9 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -17,6 +17,7 @@
#include <linux/syscalls.h>
#include <linux/module.h>
#include <linux/fsnotify.h>
+#include <linux/audit.h>
#include <asm/uaccess.h>
@@ -234,12 +235,15 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
size_t size, int flags)
{
struct file *f;
+ struct dentry *dentry;
int error = -EBADF;
f = fget(fd);
if (!f)
return error;
- error = setxattr(f->f_dentry, name, value, size, flags);
+ dentry = f->f_dentry;
+ audit_inode(NULL, dentry->d_inode, 0);
+ error = setxattr(dentry, name, value, size, flags);
fput(f);
return error;
}
@@ -458,12 +462,15 @@ asmlinkage long
sys_fremovexattr(int fd, char __user *name)
{
struct file *f;
+ struct dentry *dentry;
int error = -EBADF;
f = fget(fd);
if (!f)
return error;
- error = removexattr(f->f_dentry, name);
+ dentry = f->f_dentry;
+ audit_inode(NULL, dentry->d_inode, 0);
+ error = removexattr(dentry, name);
fput(f);
return error;
}
diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/linux-2.6/mrlock.h
index 16b44c3c236..1b262b790d9 100644
--- a/fs/xfs/linux-2.6/mrlock.h
+++ b/fs/xfs/linux-2.6/mrlock.h
@@ -79,7 +79,7 @@ static inline void mrdemote(mrlock_t *mrp)
* Debug-only routine, without some platform-specific asm code, we can
* now only answer requests regarding whether we hold the lock for write
* (reader state is outside our visibility, we only track writer state).
- * Note: means !ismrlocked would give false positivies, so don't do that.
+ * Note: means !ismrlocked would give false positives, so don't do that.
*/
static inline int ismrlocked(mrlock_t *mrp, int type)
{
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 97fc056130e..6cbbd165c60 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -372,7 +372,7 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)
* assumes that all buffers on the page are started at the same time.
*
* The fix is two passes across the ioend list - one to start writeback on the
- * bufferheads, and then the second one submit them for I/O.
+ * buffer_heads, and then submit them for I/O on the second pass.
*/
STATIC void
xfs_submit_ioend(
@@ -699,7 +699,7 @@ xfs_convert_page(
/*
* page_dirty is initially a count of buffers on the page before
- * EOF and is decrememted as we move each into a cleanable state.
+ * EOF and is decremented as we move each into a cleanable state.
*
* Derivation:
*
@@ -842,7 +842,7 @@ xfs_cluster_write(
* page if possible.
* The bh->b_state's cannot know if any of the blocks or which block for
* that matter are dirty due to mmap writes, and therefore bh uptodate is
- * only vaild if the page itself isn't completely uptodate. Some layers
+ * only valid if the page itself isn't completely uptodate. Some layers
* may clear the page dirty flag prior to calling write page, under the
* assumption the entire page will be written out; by not writing out the
* whole page the page can be reused before all valid dirty data is
@@ -892,7 +892,7 @@ xfs_page_state_convert(
/*
* page_dirty is initially a count of buffers on the page before
- * EOF and is decrememted as we move each into a cleanable state.
+ * EOF and is decremented as we move each into a cleanable state.
*
* Derivation:
*
@@ -1223,10 +1223,9 @@ free_buffers:
}
STATIC int
-__xfs_get_block(
+__xfs_get_blocks(
struct inode *inode,
sector_t iblock,
- unsigned long blocks,
struct buffer_head *bh_result,
int create,
int direct,
@@ -1236,22 +1235,17 @@ __xfs_get_block(
xfs_iomap_t iomap;
xfs_off_t offset;
ssize_t size;
- int retpbbm = 1;
+ int niomap = 1;
int error;
offset = (xfs_off_t)iblock << inode->i_blkbits;
- if (blocks)
- size = (ssize_t) min_t(xfs_off_t, LONG_MAX,
- (xfs_off_t)blocks << inode->i_blkbits);
- else
- size = 1 << inode->i_blkbits;
-
+ ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
+ size = bh_result->b_size;
VOP_BMAP(vp, offset, size,
- create ? flags : BMAPI_READ, &iomap, &retpbbm, error);
+ create ? flags : BMAPI_READ, &iomap, &niomap, error);
if (error)
return -error;
-
- if (retpbbm == 0)
+ if (niomap == 0)
return 0;
if (iomap.iomap_bn != IOMAP_DADDR_NULL) {
@@ -1271,12 +1265,16 @@ __xfs_get_block(
}
}
- /* If this is a realtime file, data might be on a new device */
+ /*
+ * If this is a realtime file, data may be on a different device.
+ * to that pointed to from the buffer_head b_bdev currently.
+ */
bh_result->b_bdev = iomap.iomap_target->bt_bdev;
- /* If we previously allocated a block out beyond eof and
- * we are now coming back to use it then we will need to
- * flag it as new even if it has a disk address.
+ /*
+ * If we previously allocated a block out beyond eof and we are
+ * now coming back to use it then we will need to flag it as new
+ * even if it has a disk address.
*/
if (create &&
((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) ||
@@ -1292,38 +1290,36 @@ __xfs_get_block(
}
}
- if (blocks) {
+ if (direct || size > (1 << inode->i_blkbits)) {
ASSERT(iomap.iomap_bsize - iomap.iomap_delta > 0);
offset = min_t(xfs_off_t,
- iomap.iomap_bsize - iomap.iomap_delta,
- (xfs_off_t)blocks << inode->i_blkbits);
- bh_result->b_size = (u32) min_t(xfs_off_t, UINT_MAX, offset);
+ iomap.iomap_bsize - iomap.iomap_delta, size);
+ bh_result->b_size = (ssize_t)min_t(xfs_off_t, LONG_MAX, offset);
}
return 0;
}
int
-xfs_get_block(
+xfs_get_blocks(
struct inode *inode,
sector_t iblock,
struct buffer_head *bh_result,
int create)
{
- return __xfs_get_block(inode, iblock, 0, bh_result,
- create, 0, BMAPI_WRITE);
+ return __xfs_get_blocks(inode, iblock,
+ bh_result, create, 0, BMAPI_WRITE);
}
STATIC int
xfs_get_blocks_direct(
struct inode *inode,
sector_t iblock,
- unsigned long max_blocks,
struct buffer_head *bh_result,
int create)
{
- return __xfs_get_block(inode, iblock, max_blocks, bh_result,
- create, 1, BMAPI_WRITE|BMAPI_DIRECT);
+ return __xfs_get_blocks(inode, iblock,
+ bh_result, create, 1, BMAPI_WRITE|BMAPI_DIRECT);
}
STATIC void
@@ -1338,9 +1334,9 @@ xfs_end_io_direct(
/*
* Non-NULL private data means we need to issue a transaction to
* convert a range from unwritten to written extents. This needs
- * to happen from process contect but aio+dio I/O completion
+ * to happen from process context but aio+dio I/O completion
* happens from irq context so we need to defer it to a workqueue.
- * This is not nessecary for synchronous direct I/O, but we do
+ * This is not necessary for synchronous direct I/O, but we do
* it anyway to keep the code uniform and simpler.
*
* The core direct I/O code might be changed to always call the
@@ -1357,7 +1353,7 @@ xfs_end_io_direct(
}
/*
- * blockdev_direct_IO can return an error even afer the I/O
+ * blockdev_direct_IO can return an error even after the I/O
* completion handler was called. Thus we need to protect
* against double-freeing.
*/
@@ -1404,7 +1400,7 @@ xfs_vm_prepare_write(
unsigned int from,
unsigned int to)
{
- return block_prepare_write(page, from, to, xfs_get_block);
+ return block_prepare_write(page, from, to, xfs_get_blocks);
}
STATIC sector_t
@@ -1421,7 +1417,7 @@ xfs_vm_bmap(
VOP_RWLOCK(vp, VRWLOCK_READ);
VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error);
VOP_RWUNLOCK(vp, VRWLOCK_READ);
- return generic_block_bmap(mapping, block, xfs_get_block);
+ return generic_block_bmap(mapping, block, xfs_get_blocks);
}
STATIC int
@@ -1429,7 +1425,7 @@ xfs_vm_readpage(
struct file *unused,
struct page *page)
{
- return mpage_readpage(page, xfs_get_block);
+ return mpage_readpage(page, xfs_get_blocks);
}
STATIC int
@@ -1439,17 +1435,17 @@ xfs_vm_readpages(
struct list_head *pages,
unsigned nr_pages)
{
- return mpage_readpages(mapping, pages, nr_pages, xfs_get_block);
+ return mpage_readpages(mapping, pages, nr_pages, xfs_get_blocks);
}
-STATIC int
+STATIC void
xfs_vm_invalidatepage(
struct page *page,
unsigned long offset)
{
xfs_page_trace(XFS_INVALIDPAGE_ENTER,
page->mapping->host, page, offset);
- return block_invalidatepage(page, offset);
+ block_invalidatepage(page, offset);
}
struct address_space_operations xfs_address_space_operations = {
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h
index 795699f121d..60716543c68 100644
--- a/fs/xfs/linux-2.6/xfs_aops.h
+++ b/fs/xfs/linux-2.6/xfs_aops.h
@@ -41,6 +41,6 @@ typedef struct xfs_ioend {
} xfs_ioend_t;
extern struct address_space_operations xfs_address_space_operations;
-extern int xfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
+extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int);
#endif /* __XFS_IOPS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_export.h b/fs/xfs/linux-2.6/xfs_export.h
index e5b0559700a..e794ca4efc7 100644
--- a/fs/xfs/linux-2.6/xfs_export.h
+++ b/fs/xfs/linux-2.6/xfs_export.h
@@ -54,7 +54,7 @@
* Note, the NFS filehandle also includes an fsid portion which
* may have an inode number in it. That number is hardcoded to
* 32bits and there is no way for XFS to intercept it. In
- * practice this means when exporting an XFS filesytem with 64bit
+ * practice this means when exporting an XFS filesystem with 64bit
* inodes you should either export the mountpoint (rather than
* a subdirectory) or use the "fsid" export option.
*/
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 185567a6a56..85997b1205f 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -528,7 +528,7 @@ open_exec_out:
}
#endif /* HAVE_FOP_OPEN_EXEC */
-struct file_operations xfs_file_operations = {
+const struct file_operations xfs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
@@ -550,7 +550,7 @@ struct file_operations xfs_file_operations = {
#endif
};
-struct file_operations xfs_invis_file_operations = {
+const struct file_operations xfs_invis_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
@@ -570,7 +570,7 @@ struct file_operations xfs_invis_file_operations = {
};
-struct file_operations xfs_dir_file_operations = {
+const struct file_operations xfs_dir_file_operations = {
.read = generic_read_dir,
.readdir = xfs_file_readdir,
.unlocked_ioctl = xfs_file_ioctl,
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index b6321abd9a8..251bfe451a3 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -72,7 +72,7 @@ xfs_ioctl32_flock(
copy_in_user(&p->l_pid, &p32->l_pid, sizeof(u32)) ||
copy_in_user(&p->l_pad, &p32->l_pad, 4*sizeof(u32)))
return -EFAULT;
-
+
return (unsigned long)p;
}
@@ -107,11 +107,15 @@ xfs_ioctl32_bulkstat(
#endif
STATIC long
-xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
+xfs_compat_ioctl(
+ int mode,
+ struct file *file,
+ unsigned cmd,
+ unsigned long arg)
{
+ struct inode *inode = file->f_dentry->d_inode;
+ vnode_t *vp = vn_from_inode(inode);
int error;
- struct inode *inode = f->f_dentry->d_inode;
- vnode_t *vp = vn_to_inode(inode);
switch (cmd) {
case XFS_IOC_DIOINFO:
@@ -189,7 +193,7 @@ xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
return -ENOIOCTLCMD;
}
- VOP_IOCTL(vp, inode, f, mode, cmd, (void __user *)arg, error);
+ VOP_IOCTL(vp, inode, file, mode, cmd, (void __user *)arg, error);
VMODIFY(vp);
return error;
@@ -197,18 +201,18 @@ xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
long
xfs_file_compat_ioctl(
- struct file *f,
+ struct file *file,
unsigned cmd,
unsigned long arg)
{
- return xfs_compat_ioctl(0, f, cmd, arg);
+ return xfs_compat_ioctl(0, file, cmd, arg);
}
long
xfs_file_compat_invis_ioctl(
- struct file *f,
+ struct file *file,
unsigned cmd,
unsigned long arg)
{
- return xfs_compat_ioctl(IO_INVIS, f, cmd, arg);
+ return xfs_compat_ioctl(IO_INVIS, file, cmd, arg);
}
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index af487437bd7..149237304fb 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -708,7 +708,7 @@ STATIC void
xfs_vn_truncate(
struct inode *inode)
{
- block_truncate_page(inode->i_mapping, inode->i_size, xfs_get_block);
+ block_truncate_page(inode->i_mapping, inode->i_size, xfs_get_blocks);
}
STATIC int
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h
index a8417d7af5f..ad6173da567 100644
--- a/fs/xfs/linux-2.6/xfs_iops.h
+++ b/fs/xfs/linux-2.6/xfs_iops.h
@@ -22,9 +22,9 @@ extern struct inode_operations xfs_inode_operations;
extern struct inode_operations xfs_dir_inode_operations;
extern struct inode_operations xfs_symlink_inode_operations;
-extern struct file_operations xfs_file_operations;
-extern struct file_operations xfs_dir_file_operations;
-extern struct file_operations xfs_invis_file_operations;
+extern const struct file_operations xfs_file_operations;
+extern const struct file_operations xfs_dir_file_operations;
+extern const struct file_operations xfs_invis_file_operations;
extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
int, unsigned int, void __user *);
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 0169360475c..84ddf189389 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -681,7 +681,7 @@ start:
eventsent = 1;
/*
- * The iolock was dropped and reaquired in XFS_SEND_DATA
+ * The iolock was dropped and reacquired in XFS_SEND_DATA
* so we have to recheck the size when appending.
* We will only "goto start;" once, since having sent the
* event prevents another call to XFS_SEND_DATA, which is
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 8355faf8ffd..1884300417e 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -375,9 +375,8 @@ xfs_init_zones(void)
if (!xfs_ioend_zone)
goto out_destroy_vnode_zone;
- xfs_ioend_pool = mempool_create(4 * MAX_BUF_PER_PAGE,
- mempool_alloc_slab, mempool_free_slab,
- xfs_ioend_zone);
+ xfs_ioend_pool = mempool_create_slab_pool(4 * MAX_BUF_PER_PAGE,
+ xfs_ioend_zone);
if (!xfs_ioend_pool)
goto out_free_ioend_zone;
return 0;
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index 8fed356db05..841200c0309 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -92,7 +92,7 @@ typedef enum {
#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */
#define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */
#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
-#define SYNC_QUIESCE 0x0100 /* quiesce fileystem for a snapshot */
+#define SYNC_QUIESCE 0x0100 /* quiesce filesystem for a snapshot */
typedef int (*vfs_mount_t)(bhv_desc_t *,
struct xfs_mount_args *, struct cred *);
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index e4e5f05b841..546f48af882 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -221,7 +221,7 @@ xfs_qm_dqunpin_wait(
* as possible.
*
* We must not be holding the AIL_LOCK at this point. Calling incore() to
- * search the buffercache can be a time consuming thing, and AIL_LOCK is a
+ * search the buffer cache can be a time consuming thing, and AIL_LOCK is a
* spinlock.
*/
STATIC void
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 1fb757ef3f4..73c1e5e80c0 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -289,7 +289,7 @@ xfs_qm_rele_quotafs_ref(
/*
* This is called at mount time from xfs_mountfs to initialize the quotainfo
- * structure and start the global quotamanager (xfs_Gqm) if it hasn't done
+ * structure and start the global quota manager (xfs_Gqm) if it hasn't done
* so already. Note that the superblock has not been read in yet.
*/
void
@@ -807,7 +807,7 @@ xfs_qm_dqattach_one(
* Given a udquot and gdquot, attach a ptr to the group dquot in the
* udquot as a hint for future lookups. The idea sounds simple, but the
* execution isn't, because the udquot might have a group dquot attached
- * already and getting rid of that gets us into lock ordering contraints.
+ * already and getting rid of that gets us into lock ordering constraints.
* The process is complicated more by the fact that the dquots may or may not
* be locked on entry.
*/
@@ -1094,10 +1094,10 @@ xfs_qm_sync(
}
/*
* If we can't grab the flush lock then if the caller
- * really wanted us to give this our best shot,
+ * really wanted us to give this our best shot, so
* see if we can give a push to the buffer before we wait
* on the flush lock. At this point, we know that
- * eventhough the dquot is being flushed,
+ * even though the dquot is being flushed,
* it has (new) dirty data.
*/
xfs_qm_dqflock_pushbuf_wait(dqp);
@@ -1491,7 +1491,7 @@ xfs_qm_reset_dqcounts(
/*
* Do a sanity check, and if needed, repair the dqblk. Don't
* output any warnings because it's perfectly possible to
- * find unitialized dquot blks. See comment in xfs_qm_dqcheck.
+ * find uninitialised dquot blks. See comment in xfs_qm_dqcheck.
*/
(void) xfs_qm_dqcheck(ddq, id+j, type, XFS_QMOPT_DQREPAIR,
"xfs_quotacheck");
@@ -1580,7 +1580,7 @@ xfs_qm_dqiterate(
error = 0;
/*
- * This looks racey, but we can't keep an inode lock across a
+ * This looks racy, but we can't keep an inode lock across a
* trans_reserve. But, this gets called during quotacheck, and that
* happens only at mount time which is single threaded.
*/
@@ -1824,7 +1824,7 @@ xfs_qm_dqusage_adjust(
* we have to start from the beginning anyway.
* Once we're done, we'll log all the dquot bufs.
*
- * The *QUOTA_ON checks below may look pretty racey, but quotachecks
+ * The *QUOTA_ON checks below may look pretty racy, but quotachecks
* and quotaoffs don't race. (Quotachecks happen at mount time only).
*/
if (XFS_IS_UQUOTA_ON(mp)) {
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 676884394aa..c55db463bbf 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -912,7 +912,7 @@ xfs_qm_export_dquot(
/*
* Internally, we don't reset all the timers when quota enforcement
- * gets turned off. No need to confuse the userlevel code,
+ * gets turned off. No need to confuse the user level code,
* so return zeroes in that case.
*/
if (! XFS_IS_QUOTA_ENFORCED(mp)) {
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 3290975d31f..d8e131ec0aa 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -804,7 +804,7 @@ xfs_trans_reserve_quota_bydquots(
}
/*
- * Didnt change anything critical, so, no need to log
+ * Didn't change anything critical, so, no need to log
*/
return (0);
}
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 4ff0f4e41c6..2539af34eb6 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -395,7 +395,7 @@ xfs_acl_allow_set(
* The access control process to determine the access permission:
* if uid == file owner id, use the file owner bits.
* if gid == file owner group id, use the file group bits.
- * scan ACL for a maching user or group, and use matched entry
+ * scan ACL for a matching user or group, and use matched entry
* permission. Use total permissions of all matching group entries,
* until all acl entries are exhausted. The final permission produced
* by matching acl entry or entries needs to be & with group permission.
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index a96e2ffce0c..dc2361dd740 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -179,7 +179,7 @@ typedef struct xfs_perag
{
char pagf_init; /* this agf's entry is initialized */
char pagi_init; /* this agi's entry is initialized */
- char pagf_metadata; /* the agf is prefered to be metadata */
+ char pagf_metadata; /* the agf is preferred to be metadata */
char pagi_inodeok; /* The agi is ok for inodes */
__uint8_t pagf_levels[XFS_BTNUM_AGF];
/* # of levels in bno & cnt btree */
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index f4328e1e2a7..64ee07db0d5 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -511,7 +511,7 @@ STATIC void
xfs_alloc_trace_busy(
char *name, /* function tag string */
char *str, /* additional string */
- xfs_mount_t *mp, /* file system mount poing */
+ xfs_mount_t *mp, /* file system mount point */
xfs_agnumber_t agno, /* allocation group number */
xfs_agblock_t agbno, /* a.g. relative block number */
xfs_extlen_t len, /* length of extent */
@@ -1843,7 +1843,7 @@ xfs_alloc_fix_freelist(
} else
agbp = NULL;
- /* If this is a metadata prefered pag and we are user data
+ /* If this is a metadata preferred pag and we are user data
* then try somewhere else if we are not being asked to
* try harder at this point
*/
@@ -2458,7 +2458,7 @@ error0:
/*
* AG Busy list management
* The busy list contains block ranges that have been freed but whose
- * transacations have not yet hit disk. If any block listed in a busy
+ * transactions have not yet hit disk. If any block listed in a busy
* list is reused, the transaction that freed it must be forced to disk
* before continuing to use the block.
*
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h
index 3546dea27b7..2d1f8928b26 100644
--- a/fs/xfs/xfs_alloc.h
+++ b/fs/xfs/xfs_alloc.h
@@ -68,7 +68,7 @@ typedef struct xfs_alloc_arg {
xfs_alloctype_t otype; /* original allocation type */
char wasdel; /* set if allocation was prev delayed */
char wasfromfl; /* set if allocation is from freelist */
- char isfl; /* set if is freelist blocks - !actg */
+ char isfl; /* set if is freelist blocks - !acctg */
char userdata; /* set if this is user data */
} xfs_alloc_arg_t;
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 093fac476bd..b6e1e02bbb2 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -294,7 +294,7 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
xfs_trans_ihold(args.trans, dp);
/*
- * If the attribute list is non-existant or a shortform list,
+ * If the attribute list is non-existent or a shortform list,
* upgrade it to a single-leaf-block attribute list.
*/
if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) ||
@@ -1584,7 +1584,7 @@ out:
* Fill in the disk block numbers in the state structure for the buffers
* that are attached to the state structure.
* This is done so that we can quickly reattach ourselves to those buffers
- * after some set of transaction commit's has released these buffers.
+ * after some set of transaction commits have released these buffers.
*/
STATIC int
xfs_attr_fillstate(xfs_da_state_t *state)
@@ -1631,7 +1631,7 @@ xfs_attr_fillstate(xfs_da_state_t *state)
/*
* Reattach the buffers to the state structure based on the disk block
* numbers stored in the state structure.
- * This is done after some set of transaction commit's has released those
+ * This is done after some set of transaction commits have released those
* buffers from our grip.
*/
STATIC int
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 717682747bd..9462be86aa1 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -524,7 +524,7 @@ xfs_attr_shortform_compare(const void *a, const void *b)
/*
* Copy out entries of shortform attribute lists for attr_list().
- * Shortform atrtribute lists are not stored in hashval sorted order.
+ * Shortform attribute lists are not stored in hashval sorted order.
* If the output buffer is not large enough to hold them all, then we
* we have to calculate each entries' hashvalue and sort them before
* we can begin returning them to the user.
@@ -1541,7 +1541,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)
/*
* Check for the degenerate case of the block being empty.
* If the block is empty, we'll simply delete it, no need to
- * coalesce it with a sibling block. We choose (aribtrarily)
+ * coalesce it with a sibling block. We choose (arbitrarily)
* to merge with the forward block unless it is NULL.
*/
if (count == 0) {
diff --git a/fs/xfs/xfs_behavior.c b/fs/xfs/xfs_behavior.c
index 9880adae393..f4fe3715a80 100644
--- a/fs/xfs/xfs_behavior.c
+++ b/fs/xfs/xfs_behavior.c
@@ -31,7 +31,7 @@
* The behavior chain is ordered based on the 'position' number which
* lives in the first field of the ops vector (higher numbers first).
*
- * Attemps to insert duplicate ops result in an EINVAL return code.
+ * Attempts to insert duplicate ops result in an EINVAL return code.
* Otherwise, return 0 to indicate success.
*/
int
@@ -84,7 +84,7 @@ bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp)
/*
* Remove a behavior descriptor from a position in a behavior chain;
- * the postition is guaranteed not to be the first position.
+ * the position is guaranteed not to be the first position.
* Should only be called by the bhv_remove() macro.
*/
void
diff --git a/fs/xfs/xfs_behavior.h b/fs/xfs/xfs_behavior.h
index 2cd89bb5ab1..1d8ff103201 100644
--- a/fs/xfs/xfs_behavior.h
+++ b/fs/xfs/xfs_behavior.h
@@ -39,7 +39,7 @@
* behaviors is synchronized with operations-in-progress (oip's) so that
* the oip's always see a consistent view of the chain.
*
- * The term "interpostion" is used to refer to the act of inserting
+ * The term "interposition" is used to refer to the act of inserting
* a behavior such that it interposes on (i.e., is inserted in front
* of) a particular other behavior. A key example of this is when a
* system implementing distributed single system image wishes to
@@ -51,7 +51,7 @@
*
* Behavior synchronization is logic which is necessary under certain
* circumstances that there is no conflict between ongoing operations
- * traversing the behavior chain and those dunamically modifying the
+ * traversing the behavior chain and those dynamically modifying the
* behavior chain. Because behavior synchronization adds extra overhead
* to virtual operation invocation, we want to restrict, as much as
* we can, the requirement for this extra code, to those situations
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 2d702e4a74a..d384e489705 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -3467,113 +3467,6 @@ done:
return error;
}
-xfs_bmbt_rec_t * /* pointer to found extent entry */
-xfs_bmap_do_search_extents(
- xfs_bmbt_rec_t *base, /* base of extent list */
- xfs_extnum_t lastx, /* last extent index used */
- xfs_extnum_t nextents, /* number of file extents */
- xfs_fileoff_t bno, /* block number searched for */
- int *eofp, /* out: end of file found */
- xfs_extnum_t *lastxp, /* out: last extent index */
- xfs_bmbt_irec_t *gotp, /* out: extent entry found */
- xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */
-{
- xfs_bmbt_rec_t *ep; /* extent list entry pointer */
- xfs_bmbt_irec_t got; /* extent list entry, decoded */
- int high; /* high index of binary search */
- int low; /* low index of binary search */
-
- /*
- * Initialize the extent entry structure to catch access to
- * uninitialized br_startblock field.
- */
- got.br_startoff = 0xffa5a5a5a5a5a5a5LL;
- got.br_blockcount = 0xa55a5a5a5a5a5a5aLL;
- got.br_state = XFS_EXT_INVALID;
-
-#if XFS_BIG_BLKNOS
- got.br_startblock = 0xffffa5a5a5a5a5a5LL;
-#else
- got.br_startblock = 0xffffa5a5;
-#endif
-
- if (lastx != NULLEXTNUM && lastx < nextents)
- ep = base + lastx;
- else
- ep = NULL;
- prevp->br_startoff = NULLFILEOFF;
- if (ep && bno >= (got.br_startoff = xfs_bmbt_get_startoff(ep)) &&
- bno < got.br_startoff +
- (got.br_blockcount = xfs_bmbt_get_blockcount(ep)))
- *eofp = 0;
- else if (ep && lastx < nextents - 1 &&
- bno >= (got.br_startoff = xfs_bmbt_get_startoff(ep + 1)) &&
- bno < got.br_startoff +
- (got.br_blockcount = xfs_bmbt_get_blockcount(ep + 1))) {
- lastx++;
- ep++;
- *eofp = 0;
- } else if (nextents == 0)
- *eofp = 1;
- else if (bno == 0 &&
- (got.br_startoff = xfs_bmbt_get_startoff(base)) == 0) {
- ep = base;
- lastx = 0;
- got.br_blockcount = xfs_bmbt_get_blockcount(ep);
- *eofp = 0;
- } else {
- low = 0;
- high = nextents - 1;
- /* binary search the extents array */
- while (low <= high) {
- XFS_STATS_INC(xs_cmp_exlist);
- lastx = (low + high) >> 1;
- ep = base + lastx;
- got.br_startoff = xfs_bmbt_get_startoff(ep);
- got.br_blockcount = xfs_bmbt_get_blockcount(ep);
- if (bno < got.br_startoff)
- high = lastx - 1;
- else if (bno >= got.br_startoff + got.br_blockcount)
- low = lastx + 1;
- else {
- got.br_startblock = xfs_bmbt_get_startblock(ep);
- got.br_state = xfs_bmbt_get_state(ep);
- *eofp = 0;
- *lastxp = lastx;
- *gotp = got;
- return ep;
- }
- }
- if (bno >= got.br_startoff + got.br_blockcount) {
- lastx++;
- if (lastx == nextents) {
- *eofp = 1;
- got.br_startblock = xfs_bmbt_get_startblock(ep);
- got.br_state = xfs_bmbt_get_state(ep);
- *prevp = got;
- ep = NULL;
- } else {
- *eofp = 0;
- xfs_bmbt_get_all(ep, prevp);
- ep++;
- got.br_startoff = xfs_bmbt_get_startoff(ep);
- got.br_blockcount = xfs_bmbt_get_blockcount(ep);
- }
- } else {
- *eofp = 0;
- if (ep > base)
- xfs_bmbt_get_all(ep - 1, prevp);
- }
- }
- if (ep) {
- got.br_startblock = xfs_bmbt_get_startblock(ep);
- got.br_state = xfs_bmbt_get_state(ep);
- }
- *lastxp = lastx;
- *gotp = got;
- return ep;
-}
-
/*
* Search the extent records for the entry containing block bno.
* If bno lies in a hole, point to the next entry. If bno lies
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 011ccaa9a1c..f83399c89ce 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -362,14 +362,6 @@ xfs_bmbt_rec_t *
xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *,
xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *);
-/*
- * Search an extent list for the extent which includes block
- * bno.
- */
-xfs_bmbt_rec_t *xfs_bmap_do_search_extents(xfs_bmbt_rec_t *,
- xfs_extnum_t, xfs_extnum_t, xfs_fileoff_t, int *,
- xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *);
-
#endif /* __KERNEL__ */
#endif /* __XFS_BMAP_H__ */
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 07e2324152b..5fed15682dd 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -98,12 +98,12 @@ xfs_buf_item_flush_log_debug(
}
/*
- * This function is called to verify that our caller's have logged
+ * This function is called to verify that our callers have logged
* all the bytes that they changed.
*
* It does this by comparing the original copy of the buffer stored in
* the buf log item's bli_orig array to the current copy of the buffer
- * and ensuring that all bytes which miscompare are set in the bli_logged
+ * and ensuring that all bytes which mismatch are set in the bli_logged
* array of the buf log item.
*/
STATIC void
diff --git a/fs/xfs/xfs_cap.h b/fs/xfs/xfs_cap.h
index 433ec537f9b..d0035c6e951 100644
--- a/fs/xfs/xfs_cap.h
+++ b/fs/xfs/xfs_cap.h
@@ -38,7 +38,7 @@ typedef struct xfs_cap_set {
/*
* For Linux, we take the bitfields directly from capability.h
* and no longer attempt to keep this attribute ondisk compatible
- * with IRIX. Since this attribute is only set on exectuables,
+ * with IRIX. Since this attribute is only set on executables,
* it just doesn't make much sense to try. We do use a different
* named attribute though, to avoid confusion.
*/
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 4bae3a76c67..8988b905117 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -840,7 +840,7 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action)
/*
* Check for the degenerate case of the block being empty.
* If the block is empty, we'll simply delete it, no need to
- * coalesce it with a sibling block. We choose (aribtrarily)
+ * coalesce it with a sibling block. We choose (arbitrarily)
* to merge with the forward block unless it is NULL.
*/
if (count == 0) {
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index bd5cee6aa51..972ded59547 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -533,7 +533,7 @@ xfs_dir2_block_getdents(
/*
* Reached the end of the block.
- * Set the offset to a nonexistent block 1 and return.
+ * Set the offset to a non-existent block 1 and return.
*/
*eofp = 1;
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 08648b18265..0f5e2f2ce6e 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -515,7 +515,7 @@ xfs_dir2_leaf_addname(
ASSERT(be32_to_cpu(leaf->ents[highstale].address) ==
XFS_DIR2_NULL_DATAPTR);
/*
- * Copy entries down to copver the stale entry
+ * Copy entries down to cover the stale entry
* and make room for the new entry.
*/
if (highstale - index > 0)
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index af556f16a0c..ac511ab9c52 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -830,7 +830,7 @@ xfs_dir2_leafn_rebalance(
state->inleaf = 1;
blk2->index = 0;
cmn_err(CE_ALERT,
- "xfs_dir2_leafn_rebalance: picked the wrong leaf? reverting orignal leaf: "
+ "xfs_dir2_leafn_rebalance: picked the wrong leaf? reverting original leaf: "
"blk1->index %d\n",
blk1->index);
}
diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c
index ee88751c3be..6d711869262 100644
--- a/fs/xfs/xfs_dir_leaf.c
+++ b/fs/xfs/xfs_dir_leaf.c
@@ -1341,7 +1341,7 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action)
/*
* Check for the degenerate case of the block being empty.
* If the block is empty, we'll simply delete it, no need to
- * coalesce it with a sibling block. We choose (aribtrarily)
+ * coalesce it with a sibling block. We choose (arbitrarily)
* to merge with the forward block unless it is NULL.
*/
if (count == 0) {
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 56caa88713a..dfa3527b20a 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -477,7 +477,7 @@ xfs_fs_counts(
*
* xfs_reserve_blocks is called to set m_resblks
* in the in-core mount table. The number of unused reserved blocks
- * is kept in m_resbls_avail.
+ * is kept in m_resblks_avail.
*
* Reserve the requested number of blocks if available. Otherwise return
* as many as possible to satisfy the request. The actual number
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 0024892841a..4eeb856183b 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -136,7 +136,7 @@ xfs_ialloc_ag_alloc(
int ninodes; /* num inodes per buf */
xfs_agino_t thisino; /* current inode number, for loop */
int version; /* inode version number to use */
- int isaligned; /* inode allocation at stripe unit */
+ int isaligned = 0; /* inode allocation at stripe unit */
/* boundary */
args.tp = tp;
@@ -152,47 +152,75 @@ xfs_ialloc_ag_alloc(
return XFS_ERROR(ENOSPC);
args.minlen = args.maxlen = XFS_IALLOC_BLOCKS(args.mp);
/*
- * Set the alignment for the allocation.
- * If stripe alignment is turned on then align at stripe unit
- * boundary.
- * If the cluster size is smaller than a filesystem block
- * then we're doing I/O for inodes in filesystem block size pieces,
- * so don't need alignment anyway.
- */
- isaligned = 0;
- if (args.mp->m_sinoalign) {
- ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
- args.alignment = args.mp->m_dalign;
- isaligned = 1;
- } else if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) &&
- args.mp->m_sb.sb_inoalignmt >=
- XFS_B_TO_FSBT(args.mp, XFS_INODE_CLUSTER_SIZE(args.mp)))
- args.alignment = args.mp->m_sb.sb_inoalignmt;
- else
- args.alignment = 1;
+ * First try to allocate inodes contiguous with the last-allocated
+ * chunk of inodes. If the filesystem is striped, this will fill
+ * an entire stripe unit with inodes.
+ */
agi = XFS_BUF_TO_AGI(agbp);
- /*
- * Need to figure out where to allocate the inode blocks.
- * Ideally they should be spaced out through the a.g.
- * For now, just allocate blocks up front.
- */
- args.agbno = be32_to_cpu(agi->agi_root);
- args.fsbno = XFS_AGB_TO_FSB(args.mp, be32_to_cpu(agi->agi_seqno),
- args.agbno);
- /*
- * Allocate a fixed-size extent of inodes.
- */
- args.type = XFS_ALLOCTYPE_NEAR_BNO;
- args.mod = args.total = args.wasdel = args.isfl = args.userdata =
- args.minalignslop = 0;
- args.prod = 1;
- /*
- * Allow space for the inode btree to split.
- */
- args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
- if ((error = xfs_alloc_vextent(&args)))
- return error;
+ newino = be32_to_cpu(agi->agi_newino);
+ if(likely(newino != NULLAGINO)) {
+ args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
+ XFS_IALLOC_BLOCKS(args.mp);
+ args.fsbno = XFS_AGB_TO_FSB(args.mp,
+ be32_to_cpu(agi->agi_seqno), args.agbno);
+ args.type = XFS_ALLOCTYPE_THIS_BNO;
+ args.mod = args.total = args.wasdel = args.isfl =
+ args.userdata = args.minalignslop = 0;
+ args.prod = 1;
+ args.alignment = 1;
+ /*
+ * Allow space for the inode btree to split.
+ */
+ args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
+ if ((error = xfs_alloc_vextent(&args)))
+ return error;
+ } else
+ args.fsbno = NULLFSBLOCK;
+ if (unlikely(args.fsbno == NULLFSBLOCK)) {
+ /*
+ * Set the alignment for the allocation.
+ * If stripe alignment is turned on then align at stripe unit
+ * boundary.
+ * If the cluster size is smaller than a filesystem block
+ * then we're doing I/O for inodes in filesystem block size
+ * pieces, so don't need alignment anyway.
+ */
+ isaligned = 0;
+ if (args.mp->m_sinoalign) {
+ ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
+ args.alignment = args.mp->m_dalign;
+ isaligned = 1;
+ } else if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) &&
+ args.mp->m_sb.sb_inoalignmt >=
+ XFS_B_TO_FSBT(args.mp,
+ XFS_INODE_CLUSTER_SIZE(args.mp)))
+ args.alignment = args.mp->m_sb.sb_inoalignmt;
+ else
+ args.alignment = 1;
+ /*
+ * Need to figure out where to allocate the inode blocks.
+ * Ideally they should be spaced out through the a.g.
+ * For now, just allocate blocks up front.
+ */
+ args.agbno = be32_to_cpu(agi->agi_root);
+ args.fsbno = XFS_AGB_TO_FSB(args.mp,
+ be32_to_cpu(agi->agi_seqno), args.agbno);
+ /*
+ * Allocate a fixed-size extent of inodes.
+ */
+ args.type = XFS_ALLOCTYPE_NEAR_BNO;
+ args.mod = args.total = args.wasdel = args.isfl =
+ args.userdata = args.minalignslop = 0;
+ args.prod = 1;
+ /*
+ * Allow space for the inode btree to split.
+ */
+ args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
+ if ((error = xfs_alloc_vextent(&args)))
+ return error;
+ }
+
/*
* If stripe alignment is turned on, then try again with cluster
* alignment.
@@ -1023,7 +1051,7 @@ xfs_difree(
rec.ir_freecount++;
/*
- * When an inode cluster is free, it becomes elgible for removal
+ * When an inode cluster is free, it becomes eligible for removal
*/
if ((mp->m_flags & XFS_MOUNT_IDELETE) &&
(rec.ir_freecount == XFS_IALLOC_INODES(mp))) {
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 3ce35a6f700..bb33113eef9 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -509,7 +509,7 @@ retry:
} else {
/*
* If the inode is not fully constructed due to
- * filehandle mistmatches wait for the inode to go
+ * filehandle mismatches wait for the inode to go
* away and try again.
*
* iget_locked will call __wait_on_freeing_inode
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 88a517fad07..48146bdc6bd 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -160,7 +160,7 @@ xfs_inotobp(
xfs_dinode_t *dip;
/*
- * Call the space managment code to find the location of the
+ * Call the space management code to find the location of the
* inode on disk.
*/
imap.im_blkno = 0;
@@ -837,7 +837,7 @@ xfs_dic2xflags(
/*
* Given a mount structure and an inode number, return a pointer
- * to a newly allocated in-core inode coresponding to the given
+ * to a newly allocated in-core inode corresponding to the given
* inode number.
*
* Initialize the inode's attributes and extent pointers if it
@@ -2723,7 +2723,7 @@ xfs_ipin(
/*
* Decrement the pin count of the given inode, and wake up
* anyone in xfs_iwait_unpin() if the count goes to 0. The
- * inode must have been previoulsy pinned with a call to xfs_ipin().
+ * inode must have been previously pinned with a call to xfs_ipin().
*/
void
xfs_iunpin(
@@ -3690,7 +3690,7 @@ void
xfs_iext_add(
xfs_ifork_t *ifp, /* inode fork pointer */
xfs_extnum_t idx, /* index to begin adding exts */
- int ext_diff) /* nubmer of extents to add */
+ int ext_diff) /* number of extents to add */
{
int byte_diff; /* new bytes being added */
int new_size; /* size of extents after adding */
@@ -4038,7 +4038,7 @@ xfs_iext_remove_indirect(
xfs_extnum_t ext_diff; /* extents to remove in current list */
xfs_extnum_t nex1; /* number of extents before idx */
xfs_extnum_t nex2; /* extents after idx + count */
- int nlists; /* entries in indirecton array */
+ int nlists; /* entries in indirection array */
int page_idx = idx; /* index in target extent list */
ASSERT(ifp->if_flags & XFS_IFEXTIREC);
@@ -4291,9 +4291,9 @@ xfs_iext_bno_to_ext(
xfs_filblks_t blockcount = 0; /* number of blocks in extent */
xfs_bmbt_rec_t *ep = NULL; /* pointer to target extent */
xfs_ext_irec_t *erp = NULL; /* indirection array pointer */
- int high; /* upper boundry in search */
+ int high; /* upper boundary in search */
xfs_extnum_t idx = 0; /* index of target extent */
- int low; /* lower boundry in search */
+ int low; /* lower boundary in search */
xfs_extnum_t nextents; /* number of file extents */
xfs_fileoff_t startoff = 0; /* start offset of extent */
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 36aa1fcb90a..7497a481b2f 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -580,7 +580,7 @@ xfs_inode_item_unpin_remove(
* been or is in the process of being flushed, then (ideally) we'd like to
* see if the inode's buffer is still incore, and if so give it a nudge.
* We delay doing so until the pushbuf routine, though, to avoid holding
- * the AIL lock across a call to the blackhole which is the buffercache.
+ * the AIL lock across a call to the blackhole which is the buffer cache.
* Also we don't want to sleep in any device strategy routines, which can happen
* if we do the subsequent bawrite in here.
*/
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 32247b6bfee..94068d014f2 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -272,7 +272,7 @@ xfs_bulkstat(
size_t statstruct_size, /* sizeof struct filling */
char __user *ubuffer, /* buffer with inode stats */
int flags, /* defined in xfs_itable.h */
- int *done) /* 1 if there're more stats to get */
+ int *done) /* 1 if there are more stats to get */
{
xfs_agblock_t agbno=0;/* allocation group block number */
xfs_buf_t *agbp; /* agi header buffer */
@@ -676,7 +676,7 @@ xfs_bulkstat_single(
xfs_mount_t *mp, /* mount point for filesystem */
xfs_ino_t *lastinop, /* inode to return */
char __user *buffer, /* buffer with inode stats */
- int *done) /* 1 if there're more stats to get */
+ int *done) /* 1 if there are more stats to get */
{
int count; /* count value for bulkstat call */
int error; /* return value */
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index 047d834ed21..11eb4e1b18c 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -60,7 +60,7 @@ xfs_bulkstat(
size_t statstruct_size,/* sizeof struct that we're filling */
char __user *ubuffer,/* buffer with inode stats */
int flags, /* flag to control access method */
- int *done); /* 1 if there're more stats to get */
+ int *done); /* 1 if there are more stats to get */
int
xfs_bulkstat_single(
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 9176995160e..32e841d2f26 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -59,7 +59,7 @@ STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp,
int num_bblks);
STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes);
STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog);
-STATIC void xlog_unalloc_log(xlog_t *log);
+STATIC void xlog_dealloc_log(xlog_t *log);
STATIC int xlog_write(xfs_mount_t *mp, xfs_log_iovec_t region[],
int nentries, xfs_log_ticket_t tic,
xfs_lsn_t *start_lsn,
@@ -304,7 +304,7 @@ xfs_log_done(xfs_mount_t *mp,
if ((ticket->t_flags & XLOG_TIC_PERM_RESERV) == 0 ||
(flags & XFS_LOG_REL_PERM_RESERV)) {
/*
- * Release ticket if not permanent reservation or a specifc
+ * Release ticket if not permanent reservation or a specific
* request has been made to release a permanent reservation.
*/
xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)");
@@ -511,7 +511,7 @@ xfs_log_mount(xfs_mount_t *mp,
vfsp->vfs_flag |= VFS_RDONLY;
if (error) {
cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error);
- xlog_unalloc_log(mp->m_log);
+ xlog_dealloc_log(mp->m_log);
return error;
}
}
@@ -667,7 +667,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
*
* Go through the motions of sync'ing and releasing
* the iclog, even though no I/O will actually happen,
- * we need to wait for other log I/O's that may already
+ * we need to wait for other log I/Os that may already
* be in progress. Do this as a separate section of
* code so we'll know if we ever get stuck here that
* we're in this odd situation of trying to unmount
@@ -704,7 +704,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
void
xfs_log_unmount_dealloc(xfs_mount_t *mp)
{
- xlog_unalloc_log(mp->m_log);
+ xlog_dealloc_log(mp->m_log);
}
/*
@@ -1492,7 +1492,7 @@ xlog_sync(xlog_t *log,
ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize);
- /* account for internal log which does't start at block #0 */
+ /* account for internal log which doesn't start at block #0 */
XFS_BUF_SET_ADDR(bp, XFS_BUF_ADDR(bp) + log->l_logBBstart);
XFS_BUF_WRITE(bp);
if ((error = XFS_bwrite(bp))) {
@@ -1506,10 +1506,10 @@ xlog_sync(xlog_t *log,
/*
- * Unallocate a log structure
+ * Deallocate a log structure
*/
void
-xlog_unalloc_log(xlog_t *log)
+xlog_dealloc_log(xlog_t *log)
{
xlog_in_core_t *iclog, *next_iclog;
xlog_ticket_t *tic, *next_tic;
@@ -1539,7 +1539,7 @@ xlog_unalloc_log(xlog_t *log)
if ((log->l_ticket_cnt != log->l_ticket_tcnt) &&
!XLOG_FORCED_SHUTDOWN(log)) {
xfs_fs_cmn_err(CE_WARN, log->l_mp,
- "xlog_unalloc_log: (cnt: %d, total: %d)",
+ "xlog_dealloc_log: (cnt: %d, total: %d)",
log->l_ticket_cnt, log->l_ticket_tcnt);
/* ASSERT(log->l_ticket_cnt == log->l_ticket_tcnt); */
@@ -1562,7 +1562,7 @@ xlog_unalloc_log(xlog_t *log)
#endif
log->l_mp->m_log = NULL;
kmem_free(log, sizeof(xlog_t));
-} /* xlog_unalloc_log */
+} /* xlog_dealloc_log */
/*
* Update counters atomically now that memcpy is done.
@@ -2829,7 +2829,7 @@ xlog_state_release_iclog(xlog_t *log,
/*
* We let the log lock go, so it's possible that we hit a log I/O
- * error or someother SHUTDOWN condition that marks the iclog
+ * error or some other SHUTDOWN condition that marks the iclog
* as XLOG_STATE_IOERROR before the bwrite. However, we know that
* this iclog has consistent data, so we ignore IOERROR
* flags after this point.
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 4b2ac88dbb8..eacb3d4987f 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -27,7 +27,7 @@
#ifdef __KERNEL__
/*
- * By comparing each compnent, we don't have to worry about extra
+ * By comparing each component, we don't have to worry about extra
* endian issues in treating two 32 bit numbers as one 64 bit number
*/
static inline xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2)
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index add13f507ed..1f0016b0b4e 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -583,7 +583,7 @@ xlog_find_head(
* x | x ... | x - 1 | x
* Another case that fits this picture would be
* x | x + 1 | x ... | x
- * In this case the head really is somwhere at the end of the
+ * In this case the head really is somewhere at the end of the
* log, as one of the latest writes at the beginning was
* incomplete.
* One more case is
@@ -2799,7 +2799,7 @@ xlog_recover_do_trans(
* we don't need to worry about the block number being
* truncated in > 1 TB buffers because in user-land,
* we're now n32 or 64-bit so xfs_daddr_t is 64-bits so
- * the blkno's will get through the user-mode buffer
+ * the blknos will get through the user-mode buffer
* cache properly. The only bad case is o32 kernels
* where xfs_daddr_t is 32-bits but mount will warn us
* off a > 1 TB filesystem before we get here.
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 20e8abc16d1..72e7e78bfff 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -393,7 +393,7 @@ xfs_initialize_perag(
break;
}
- /* This ag is prefered for inodes */
+ /* This ag is preferred for inodes */
pag = &mp->m_perag[index];
pag->pagi_inodeok = 1;
if (index < max_metadata)
@@ -1728,7 +1728,7 @@ xfs_mount_log_sbunit(
* We cannot use the hotcpu_register() function because it does
* not allow notifier instances. We need a notifier per filesystem
* as we need to be able to identify the filesystem to balance
- * the counters out. This is acheived by having a notifier block
+ * the counters out. This is achieved by having a notifier block
* embedded in the xfs_mount_t and doing pointer magic to get the
* mount pointer from the notifier block address.
*/
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index ebd73960e9d..66cbee79864 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -379,7 +379,7 @@ typedef struct xfs_mount {
#endif
int m_dalign; /* stripe unit */
int m_swidth; /* stripe width */
- int m_sinoalign; /* stripe unit inode alignmnt */
+ int m_sinoalign; /* stripe unit inode alignment */
int m_attr_magicpct;/* 37% of the blocksize */
int m_dir_magicpct; /* 37% of the dir blocksize */
__uint8_t m_mk_sharedro; /* mark shared ro on unmount */
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 82a08baf437..4f6a034de7f 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -31,7 +31,7 @@
typedef __uint32_t xfs_dqid_t;
/*
- * Eventhough users may not have quota limits occupying all 64-bits,
+ * Even though users may not have quota limits occupying all 64-bits,
* they may need 64-bit accounting. Hence, 64-bit quota-counters,
* and quota-limits. This is a waste in the common case, but hey ...
*/
@@ -246,7 +246,7 @@ typedef struct xfs_qoff_logformat {
#ifdef __KERNEL__
/*
* This check is done typically without holding the inode lock;
- * that may seem racey, but it is harmless in the context that it is used.
+ * that may seem racy, but it is harmless in the context that it is used.
* The inode cannot go inactive as long a reference is kept, and
* therefore if dquot(s) were attached, they'll stay consistent.
* If, for example, the ownership of the inode changes while
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 2918956553a..8d056cef5d1 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -490,7 +490,7 @@ xfs_trans_mod_sb(
case XFS_TRANS_SB_RES_FREXTENTS:
/*
* The allocation has already been applied to the
- * in-core superblocks's counter. This should only
+ * in-core superblock's counter. This should only
* be applied to the on-disk superblock.
*/
ASSERT(delta < 0);
@@ -611,7 +611,7 @@ xfs_trans_apply_sb_deltas(
if (whole)
/*
- * Log the whole thing, the fields are discontiguous.
+ * Log the whole thing, the fields are noncontiguous.
*/
xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_sb_t) - 1);
else
@@ -669,7 +669,7 @@ xfs_trans_unreserve_and_mod_sb(
/*
* Apply any superblock modifications to the in-core version.
* The t_res_fdblocks_delta and t_res_frextents_delta fields are
- * explicity NOT applied to the in-core superblock.
+ * explicitly NOT applied to the in-core superblock.
* The idea is that that has already been done.
*/
if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index e48befa4e33..100d9a4b38e 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -354,7 +354,7 @@ typedef struct xfs_trans {
xfs_lsn_t t_commit_lsn; /* log seq num of end of
* transaction. */
struct xfs_mount *t_mountp; /* ptr to fs mount struct */
- struct xfs_dquot_acct *t_dqinfo; /* accting info for dquots */
+ struct xfs_dquot_acct *t_dqinfo; /* acctg info for dquots */
xfs_trans_callback_t t_callback; /* transaction callback */
void *t_callarg; /* callback arg */
unsigned int t_flags; /* misc flags */
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index e341409172d..7c5894d59f8 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -272,7 +272,7 @@ xfs_trans_log_inode(
* This is to coordinate with the xfs_iflush() and xfs_iflush_done()
* routines in the eventual clearing of the ilf_fields bits.
* See the big comment in xfs_iflush() for an explanation of
- * this coorination mechanism.
+ * this coordination mechanism.
*/
flags |= ip->i_itemp->ili_last_fields;
ip->i_itemp->ili_format.ilf_fields |= flags;
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index d4ec4dfaf19..504d2a80747 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -880,10 +880,10 @@ xfs_statvfs(
* determine if they should be flushed sync, async, or
* delwri.
* SYNC_CLOSE - This flag is passed when the system is being
- * unmounted. We should sync and invalidate everthing.
+ * unmounted. We should sync and invalidate everything.
* SYNC_FSDATA - This indicates that the caller would like to make
* sure the superblock is safe on disk. We can ensure
- * this by simply makeing sure the log gets flushed
+ * this by simply making sure the log gets flushed
* if SYNC_BDFLUSH is set, and by actually writing it
* out otherwise.
*
@@ -908,7 +908,7 @@ xfs_sync(
*
* This routine supports all of the flags defined for the generic VFS_SYNC
* interface as explained above under xfs_sync. In the interests of not
- * changing interfaces within the 6.5 family, additional internallly-
+ * changing interfaces within the 6.5 family, additional internally-
* required functions are specified within a separate xflags parameter,
* only available by calling this routine.
*
@@ -1090,7 +1090,7 @@ xfs_sync_inodes(
* If this is just vfs_sync() or pflushd() calling
* then we can skip inodes for which it looks like
* there is nothing to do. Since we don't have the
- * inode locked this is racey, but these are periodic
+ * inode locked this is racy, but these are periodic
* calls so it doesn't matter. For the others we want
* to know for sure, so we at least try to lock them.
*/
@@ -1429,7 +1429,7 @@ xfs_sync_inodes(
*
* This routine supports all of the flags defined for the generic VFS_SYNC
* interface as explained above under xfs_sync. In the interests of not
- * changing interfaces within the 6.5 family, additional internallly-
+ * changing interfaces within the 6.5 family, additional internally-
* required functions are specified within a separate xflags parameter,
* only available by calling this routine.
*
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 0f0a64e81db..de49601919c 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -848,7 +848,7 @@ xfs_setattr(
* If this is a synchronous mount, make sure that the
* transaction goes to disk before returning to the user.
* This is slightly sub-optimal in that truncates require
- * two sync transactions instead of one for wsync filesytems.
+ * two sync transactions instead of one for wsync filesystems.
* One for the truncate and one for the timestamps since we
* don't want to change the timestamps unless we're sure the
* truncate worked. Truncates are less than 1% of the laddis
@@ -1170,7 +1170,7 @@ xfs_fsync(
/*
* If this inode is on the RT dev we need to flush that
- * cache aswell.
+ * cache as well.
*/
if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME)
xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp);
@@ -1380,7 +1380,7 @@ xfs_inactive_symlink_rmt(
*/
ntp = xfs_trans_dup(tp);
/*
- * Commit the transaction containing extent freeing and EFD's.
+ * Commit the transaction containing extent freeing and EFDs.
* If we get an error on the commit here or on the reserve below,
* we need to unlock the inode since the new transaction doesn't
* have the inode attached.
@@ -2023,7 +2023,7 @@ xfs_create(
XFS_QM_DQRELE(mp, gdqp);
/*
- * Propogate the fact that the vnode changed after the
+ * Propagate the fact that the vnode changed after the
* xfs_inode locks have been released.
*/
VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_TRUNCATED, 3);
@@ -2370,7 +2370,7 @@ xfs_remove(
* for a log reservation. Since we'll have to wait for the
* inactive code to complete before returning from xfs_iget,
* we need to make sure that we don't have log space reserved
- * when we call xfs_iget. Instead we get an unlocked referece
+ * when we call xfs_iget. Instead we get an unlocked reference
* to the inode before getting our log reservation.
*/
error = xfs_get_dir_entry(dentry, &ip);
@@ -3020,7 +3020,7 @@ xfs_rmdir(
* for a log reservation. Since we'll have to wait for the
* inactive code to complete before returning from xfs_iget,
* we need to make sure that we don't have log space reserved
- * when we call xfs_iget. Instead we get an unlocked referece
+ * when we call xfs_iget. Instead we get an unlocked reference
* to the inode before getting our log reservation.
*/
error = xfs_get_dir_entry(dentry, &cdp);
diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h
index 302201f1a09..3f88715e811 100644
--- a/include/asm-alpha/bitops.h
+++ b/include/asm-alpha/bitops.h
@@ -261,7 +261,7 @@ static inline unsigned long ffz_b(unsigned long x)
static inline unsigned long ffz(unsigned long word)
{
-#if defined(__alpha_cix__) && defined(__alpha_fix__)
+#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67)
/* Whee. EV67 can calculate it directly. */
return __kernel_cttz(~word);
#else
@@ -281,7 +281,7 @@ static inline unsigned long ffz(unsigned long word)
*/
static inline unsigned long __ffs(unsigned long word)
{
-#if defined(__alpha_cix__) && defined(__alpha_fix__)
+#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67)
/* Whee. EV67 can calculate it directly. */
return __kernel_cttz(word);
#else
@@ -313,20 +313,20 @@ static inline int ffs(int word)
/*
* fls: find last bit set.
*/
-#if defined(__alpha_cix__) && defined(__alpha_fix__)
+#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67)
static inline int fls(int word)
{
return 64 - __kernel_ctlz(word & 0xffffffff);
}
#else
-#define fls generic_fls
+#include <asm-generic/bitops/fls.h>
#endif
-#define fls64 generic_fls64
+#include <asm-generic/bitops/fls64.h>
/* Compute powers of two for the given integer. */
static inline long floor_log2(unsigned long word)
{
-#if defined(__alpha_cix__) && defined(__alpha_fix__)
+#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67)
return 63 - __kernel_ctlz(word);
#else
long bit;
@@ -347,7 +347,7 @@ static inline long ceil_log2(unsigned long word)
* of bits set) of a N-bit word
*/
-#if defined(__alpha_cix__) && defined(__alpha_fix__)
+#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67)
/* Whee. EV67 can calculate it directly. */
static inline unsigned long hweight64(unsigned long w)
{
@@ -358,112 +358,12 @@ static inline unsigned long hweight64(unsigned long w)
#define hweight16(x) (unsigned int) hweight64((x) & 0xfffful)
#define hweight8(x) (unsigned int) hweight64((x) & 0xfful)
#else
-static inline unsigned long hweight64(unsigned long w)
-{
- unsigned long result;
- for (result = 0; w ; w >>= 1)
- result += (w & 1);
- return result;
-}
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/hweight.h>
#endif
#endif /* __KERNEL__ */
-/*
- * Find next zero bit in a bitmap reasonably efficiently..
- */
-static inline unsigned long
-find_next_zero_bit(const void *addr, unsigned long size, unsigned long offset)
-{
- const unsigned long *p = addr;
- unsigned long result = offset & ~63UL;
- unsigned long tmp;
-
- p += offset >> 6;
- if (offset >= size)
- return size;
- size -= result;
- offset &= 63UL;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (64-offset);
- if (size < 64)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 64;
- result += 64;
- }
- while (size & ~63UL) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += 64;
- size -= 64;
- }
- if (!size)
- return result;
- tmp = *p;
- found_first:
- tmp |= ~0UL << size;
- if (tmp == ~0UL) /* Are any bits zero? */
- return result + size; /* Nope. */
- found_middle:
- return result + ffz(tmp);
-}
-
-/*
- * Find next one bit in a bitmap reasonably efficiently.
- */
-static inline unsigned long
-find_next_bit(const void * addr, unsigned long size, unsigned long offset)
-{
- const unsigned long *p = addr;
- unsigned long result = offset & ~63UL;
- unsigned long tmp;
-
- p += offset >> 6;
- if (offset >= size)
- return size;
- size -= result;
- offset &= 63UL;
- if (offset) {
- tmp = *(p++);
- tmp &= ~0UL << offset;
- if (size < 64)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= 64;
- result += 64;
- }
- while (size & ~63UL) {
- if ((tmp = *(p++)))
- goto found_middle;
- result += 64;
- size -= 64;
- }
- if (!size)
- return result;
- tmp = *p;
- found_first:
- tmp &= ~0UL >> (64 - size);
- if (!tmp)
- return result + size;
- found_middle:
- return result + __ffs(tmp);
-}
-
-/*
- * The optimizer actually does good code for this case.
- */
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
-#define find_first_bit(addr, size) \
- find_next_bit((addr), (size), 0)
+#include <asm-generic/bitops/find.h>
#ifdef __KERNEL__
@@ -487,21 +387,12 @@ sched_find_first_bit(unsigned long b[3])
return __ffs(b0) + ofs;
}
+#include <asm-generic/bitops/ext2-non-atomic.h>
-#define ext2_set_bit __test_and_set_bit
#define ext2_set_bit_atomic(l,n,a) test_and_set_bit(n,a)
-#define ext2_clear_bit __test_and_clear_bit
#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
-#define ext2_test_bit test_bit
-#define ext2_find_first_zero_bit find_first_zero_bit
-#define ext2_find_next_zero_bit find_next_zero_bit
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) __set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+
+#include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-alpha/fpu.h b/include/asm-alpha/fpu.h
index c203fc2fa5c..ecb17a72acc 100644
--- a/include/asm-alpha/fpu.h
+++ b/include/asm-alpha/fpu.h
@@ -130,7 +130,7 @@ rdfpcr(void)
{
unsigned long tmp, ret;
-#if defined(__alpha_cix__) || defined(__alpha_fix__)
+#if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67)
__asm__ __volatile__ (
"ftoit $f0,%0\n\t"
"mf_fpcr $f0\n\t"
@@ -154,7 +154,7 @@ wrfpcr(unsigned long val)
{
unsigned long tmp;
-#if defined(__alpha_cix__) || defined(__alpha_fix__)
+#if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67)
__asm__ __volatile__ (
"ftoit $f0,%0\n\t"
"itoft %1,$f0\n\t"
diff --git a/include/asm-alpha/mmzone.h b/include/asm-alpha/mmzone.h
index a011ef4cf3d..192d80c875b 100644
--- a/include/asm-alpha/mmzone.h
+++ b/include/asm-alpha/mmzone.h
@@ -59,9 +59,6 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
#define kvaddr_to_nid(kaddr) pa_to_nid(__pa(kaddr))
#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
-#define local_mapnr(kvaddr) \
- ((__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)))
-
/*
* Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory
* and returns the kaddr corresponding to first physical page in the
@@ -86,8 +83,7 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
pte_t pte; \
unsigned long pfn; \
\
- pfn = ((unsigned long)((page)-page_zone(page)->zone_mem_map)) << 32; \
- pfn += page_zone(page)->zone_start_pfn << 32; \
+ pfn = page_to_pfn(page) << 32; \
pte_val(pte) = pfn | pgprot_val(pgprot); \
\
pte; \
@@ -104,19 +100,8 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
__xx; \
})
-#define pfn_to_page(pfn) \
-({ \
- unsigned long kaddr = (unsigned long)__va((pfn) << PAGE_SHIFT); \
- (NODE_DATA(kvaddr_to_nid(kaddr))->node_mem_map + local_mapnr(kaddr)); \
-})
-
-#define page_to_pfn(page) \
- ((page) - page_zone(page)->zone_mem_map + \
- (page_zone(page)->zone_start_pfn))
-
#define page_to_pa(page) \
- ((( (page) - page_zone(page)->zone_mem_map ) \
- + page_zone(page)->zone_start_pfn) << PAGE_SHIFT)
+ (page_to_pfn(page) << PAGE_SHIFT)
#define pfn_to_nid(pfn) pa_to_nid(((u64)(pfn) << PAGE_SHIFT))
#define pfn_valid(pfn) \
diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h
index fa0b41b164a..61bcf70b5ea 100644
--- a/include/asm-alpha/page.h
+++ b/include/asm-alpha/page.h
@@ -85,8 +85,6 @@ typedef unsigned long pgprot_t;
#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
#ifndef CONFIG_DISCONTIGMEM
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define pfn_valid(pfn) ((pfn) < max_mapnr)
@@ -95,9 +93,9 @@ typedef unsigned long pgprot_t;
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _ALPHA_PAGE_H */
diff --git a/include/asm-alpha/poll.h b/include/asm-alpha/poll.h
index 34f333b762a..76f89356b6a 100644
--- a/include/asm-alpha/poll.h
+++ b/include/asm-alpha/poll.h
@@ -12,7 +12,9 @@
#define POLLWRNORM (1 << 8)
#define POLLWRBAND (1 << 9)
#define POLLMSG (1 << 10)
-#define POLLREMOVE (1 << 11)
+#define POLLREMOVE (1 << 12)
+#define POLLRDHUP (1 << 13)
+
struct pollfd {
int fd;
diff --git a/include/asm-arm/arch-aaec2000/uncompress.h b/include/asm-arm/arch-aaec2000/uncompress.h
index fff0c94b75c..300f4bf3bc7 100644
--- a/include/asm-arm/arch-aaec2000/uncompress.h
+++ b/include/asm-arm/arch-aaec2000/uncompress.h
@@ -15,7 +15,7 @@
#define UART(x) (*(volatile unsigned long *)(serial_port + (x)))
-static void putstr( const char *s )
+static void putc(int c)
{
unsigned long serial_port;
do {
@@ -28,17 +28,16 @@ static void putstr( const char *s )
return;
} while (0);
- for (; *s; s++) {
- /* wait for space in the UART's transmitter */
- while ((UART(UART_SR) & UART_SR_TxFF));
- /* send the character out. */
- UART(UART_DR) = *s;
- /* if a LF, also do CR... */
- if (*s == 10) {
- while ((UART(UART_SR) & UART_SR_TxFF));
- UART(UART_DR) = 13;
- }
- }
+ /* wait for space in the UART's transmitter */
+ while ((UART(UART_SR) & UART_SR_TxFF))
+ barrier();
+
+ /* send the character out. */
+ UART(UART_DR) = c;
+}
+
+static inline void flush(void)
+{
}
#define arch_decomp_setup()
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_emac.h b/include/asm-arm/arch-at91rm9200/at91rm9200_emac.h
new file mode 100644
index 00000000000..fbc091e61e2
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_emac.h
@@ -0,0 +1,138 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_emac.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Ethernet MAC registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * 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.
+ */
+
+#ifndef AT91RM9200_EMAC_H
+#define AT91RM9200_EMAC_H
+
+#define AT91_EMAC_CTL 0x00 /* Control Register */
+#define AT91_EMAC_LB (1 << 0) /* Loopback */
+#define AT91_EMAC_LBL (1 << 1) /* Loopback Local */
+#define AT91_EMAC_RE (1 << 2) /* Receive Enable */
+#define AT91_EMAC_TE (1 << 3) /* Transmit Enable */
+#define AT91_EMAC_MPE (1 << 4) /* Management Port Enable */
+#define AT91_EMAC_CSR (1 << 5) /* Clear Statistics Registers */
+#define AT91_EMAC_INCSTAT (1 << 6) /* Increment Statistics Registers */
+#define AT91_EMAC_WES (1 << 7) /* Write Enable for Statistics Registers */
+#define AT91_EMAC_BP (1 << 8) /* Back Pressure */
+
+#define AT91_EMAC_CFG 0x04 /* Configuration Register */
+#define AT91_EMAC_SPD (1 << 0) /* Speed */
+#define AT91_EMAC_FD (1 << 1) /* Full Duplex */
+#define AT91_EMAC_BR (1 << 2) /* Bit Rate */
+#define AT91_EMAC_CAF (1 << 4) /* Copy All Frames */
+#define AT91_EMAC_NBC (1 << 5) /* No Broadcast */
+#define AT91_EMAC_MTI (1 << 6) /* Multicast Hash Enable */
+#define AT91_EMAC_UNI (1 << 7) /* Unicast Hash Enable */
+#define AT91_EMAC_BIG (1 << 8) /* Receive 1522 Bytes */
+#define AT91_EMAC_EAE (1 << 9) /* External Address Match Enable */
+#define AT91_EMAC_CLK (3 << 10) /* MDC Clock Divisor */
+#define AT91_EMAC_CLK_DIV8 (0 << 10)
+#define AT91_EMAC_CLK_DIV16 (1 << 10)
+#define AT91_EMAC_CLK_DIV32 (2 << 10)
+#define AT91_EMAC_CLK_DIV64 (3 << 10)
+#define AT91_EMAC_RTY (1 << 12) /* Retry Test */
+#define AT91_EMAC_RMII (1 << 13) /* Reduce MII (RMII) */
+
+#define AT91_EMAC_SR 0x08 /* Status Register */
+#define AT91_EMAC_SR_LINK (1 << 0) /* Link */
+#define AT91_EMAC_SR_MDIO (1 << 1) /* MDIO pin */
+#define AT91_EMAC_SR_IDLE (1 << 2) /* PHY idle */
+
+#define AT91_EMAC_TAR 0x0c /* Transmit Address Register */
+
+#define AT91_EMAC_TCR 0x10 /* Transmit Control Register */
+#define AT91_EMAC_LEN (0x7ff << 0) /* Transmit Frame Length */
+#define AT91_EMAC_NCRC (1 << 15) /* No CRC */
+
+#define AT91_EMAC_TSR 0x14 /* Transmit Status Register */
+#define AT91_EMAC_TSR_OVR (1 << 0) /* Transmit Buffer Overrun */
+#define AT91_EMAC_TSR_COL (1 << 1) /* Collision Occurred */
+#define AT91_EMAC_TSR_RLE (1 << 2) /* Retry Limit Exceeded */
+#define AT91_EMAC_TSR_IDLE (1 << 3) /* Transmitter Idle */
+#define AT91_EMAC_TSR_BNQ (1 << 4) /* Transmit Buffer not Queued */
+#define AT91_EMAC_TSR_COMP (1 << 5) /* Transmit Complete */
+#define AT91_EMAC_TSR_UND (1 << 6) /* Transmit Underrun */
+
+#define AT91_EMAC_RBQP 0x18 /* Receive Buffer Queue Pointer */
+
+#define AT91_EMAC_RSR 0x20 /* Receive Status Register */
+#define AT91_EMAC_RSR_BNA (1 << 0) /* Buffer Not Available */
+#define AT91_EMAC_RSR_REC (1 << 1) /* Frame Received */
+#define AT91_EMAC_RSR_OVR (1 << 2) /* RX Overrun */
+
+#define AT91_EMAC_ISR 0x24 /* Interrupt Status Register */
+#define AT91_EMAC_DONE (1 << 0) /* Management Done */
+#define AT91_EMAC_RCOM (1 << 1) /* Receive Complete */
+#define AT91_EMAC_RBNA (1 << 2) /* Receive Buffer Not Available */
+#define AT91_EMAC_TOVR (1 << 3) /* Transmit Buffer Overrun */
+#define AT91_EMAC_TUND (1 << 4) /* Transmit Buffer Underrun */
+#define AT91_EMAC_RTRY (1 << 5) /* Retry Limit */
+#define AT91_EMAC_TBRE (1 << 6) /* Transmit Buffer Register Empty */
+#define AT91_EMAC_TCOM (1 << 7) /* Transmit Complete */
+#define AT91_EMAC_TIDLE (1 << 8) /* Transmit Idle */
+#define AT91_EMAC_LINK (1 << 9) /* Link */
+#define AT91_EMAC_ROVR (1 << 10) /* RX Overrun */
+#define AT91_EMAC_ABT (1 << 11) /* Abort */
+
+#define AT91_EMAC_IER 0x28 /* Interrupt Enable Register */
+#define AT91_EMAC_IDR 0x2c /* Interrupt Disable Register */
+#define AT91_EMAC_IMR 0x30 /* Interrupt Mask Register */
+
+#define AT91_EMAC_MAN 0x34 /* PHY Maintenance Register */
+#define AT91_EMAC_DATA (0xffff << 0) /* MDIO Data */
+#define AT91_EMAC_REGA (0x1f << 18) /* MDIO Register */
+#define AT91_EMAC_PHYA (0x1f << 23) /* MDIO PHY Address */
+#define AT91_EMAC_RW (3 << 28) /* Read/Write operation */
+#define AT91_EMAC_RW_W (1 << 28)
+#define AT91_EMAC_RW_R (2 << 28)
+#define AT91_EMAC_MAN_802_3 0x40020000 /* IEEE 802.3 value */
+
+/*
+ * Statistics Registers.
+ */
+#define AT91_EMAC_FRA 0x40 /* Frames Transmitted OK */
+#define AT91_EMAC_SCOL 0x44 /* Single Collision Frame */
+#define AT91_EMAC_MCOL 0x48 /* Multiple Collision Frame */
+#define AT91_EMAC_OK 0x4c /* Frames Received OK */
+#define AT91_EMAC_SEQE 0x50 /* Frame Check Sequence Error */
+#define AT91_EMAC_ALE 0x54 /* Alignmemt Error */
+#define AT91_EMAC_DTE 0x58 /* Deffered Transmission Frame */
+#define AT91_EMAC_LCOL 0x5c /* Late Collision */
+#define AT91_EMAC_ECOL 0x60 /* Excessive Collision */
+#define AT91_EMAC_TUE 0x64 /* Transmit Underrun Error */
+#define AT91_EMAC_CSE 0x68 /* Carrier Sense Error */
+#define AT91_EMAC_DRFC 0x6c /* Discard RX Frame */
+#define AT91_EMAC_ROV 0x70 /* Receive Overrun */
+#define AT91_EMAC_CDE 0x74 /* Code Error */
+#define AT91_EMAC_ELR 0x78 /* Excessive Length Error */
+#define AT91_EMAC_RJB 0x7c /* Receive Jabber */
+#define AT91_EMAC_USF 0x80 /* Undersize Frame */
+#define AT91_EMAC_SQEE 0x84 /* SQE Test Error */
+
+/*
+ * Address Registers.
+ */
+#define AT91_EMAC_HSL 0x90 /* Hash Address Low [31:0] */
+#define AT91_EMAC_HSH 0x94 /* Hash Address High [63:32] */
+#define AT91_EMAC_SA1L 0x98 /* Specific Address 1 Low, bytes 0-3 */
+#define AT91_EMAC_SA1H 0x9c /* Specific Address 1 High, bytes 4-5 */
+#define AT91_EMAC_SA2L 0xa0 /* Specific Address 2 Low, bytes 0-3 */
+#define AT91_EMAC_SA2H 0xa4 /* Specific Address 2 High, bytes 4-5 */
+#define AT91_EMAC_SA3L 0xa8 /* Specific Address 3 Low, bytes 0-3 */
+#define AT91_EMAC_SA3H 0xac /* Specific Address 3 High, bytes 4-5 */
+#define AT91_EMAC_SA4L 0xb0 /* Specific Address 4 Low, bytes 0-3 */
+#define AT91_EMAC_SA4H 0xb4 /* Specific Address 4 High, bytes 4-5 */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
index 9bfffdbf1e0..2910d359f91 100644
--- a/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
@@ -172,6 +172,7 @@
#define AT91_PMC_MDIV_4 (3 << 8)
#define AT91_PMC_PCKR(n) (AT91_PMC + 0x40 + ((n) * 4)) /* Programmable Clock 0-3 Registers */
+
#define AT91_PMC_IER (AT91_PMC + 0x60) /* Interrupt Enable Register */
#define AT91_PMC_IDR (AT91_PMC + 0x64) /* Interrupt Disable Register */
#define AT91_PMC_SR (AT91_PMC + 0x68) /* Status Register */
@@ -286,8 +287,32 @@
#define AT91_MC_RCB (1 << 0) /* Remap Command Bit */
#define AT91_MC_ASR (AT91_MC + 0x04) /* MC Abort Status Register */
+#define AT91_MC_UNADD (1 << 0) /* Undefined Address Abort Status */
+#define AT91_MC_MISADD (1 << 1) /* Misaligned Address Abort Status */
+#define AT91_MC_ABTSZ (3 << 8) /* Abort Size Status */
+#define AT91_MC_ABTSZ_BYTE (0 << 8)
+#define AT91_MC_ABTSZ_HALFWORD (1 << 8)
+#define AT91_MC_ABTSZ_WORD (2 << 8)
+#define AT91_MC_ABTTYP (3 << 10) /* Abort Type Status */
+#define AT91_MC_ABTTYP_DATAREAD (0 << 10)
+#define AT91_MC_ABTTYP_DATAWRITE (1 << 10)
+#define AT91_MC_ABTTYP_FETCH (2 << 10)
+#define AT91_MC_MST0 (1 << 16) /* ARM920T Abort Source */
+#define AT91_MC_MST1 (1 << 17) /* PDC Abort Source */
+#define AT91_MC_MST2 (1 << 18) /* UHP Abort Source */
+#define AT91_MC_MST3 (1 << 19) /* EMAC Abort Source */
+#define AT91_MC_SVMST0 (1 << 24) /* Saved ARM920T Abort Source */
+#define AT91_MC_SVMST1 (1 << 25) /* Saved PDC Abort Source */
+#define AT91_MC_SVMST2 (1 << 26) /* Saved UHP Abort Source */
+#define AT91_MC_SVMST3 (1 << 27) /* Saved EMAC Abort Source */
+
#define AT91_MC_AASR (AT91_MC + 0x08) /* MC Abort Address Status Register */
+
#define AT91_MC_MPR (AT91_MC + 0x0c) /* MC Master Priority Register */
+#define AT91_MPR_MSTP0 (7 << 0) /* ARM920T Priority */
+#define AT91_MPR_MSTP1 (7 << 4) /* PDC Priority */
+#define AT91_MPR_MSTP2 (7 << 8) /* UHP Priority */
+#define AT91_MPR_MSTP3 (7 << 12) /* EMAC Priority */
/* External Bus Interface (EBI) registers */
#define AT91_EBI_CSA (AT91_MC + 0x60) /* Chip Select Assignment Register */
@@ -309,8 +334,10 @@
/* Static Memory Controller (SMC) registers */
#define AT91_SMC_CSR(n) (AT91_MC + 0x70 + ((n) * 4))/* SMC Chip Select Register */
#define AT91_SMC_NWS (0x7f << 0) /* Number of Wait States */
+#define AT91_SMC_NWS_(x) ((x) << 0)
#define AT91_SMC_WSEN (1 << 7) /* Wait State Enable */
#define AT91_SMC_TDF (0xf << 8) /* Data Float Time */
+#define AT91_SMC_TDF_(x) ((x) << 8)
#define AT91_SMC_BAT (1 << 12) /* Byte Access Type */
#define AT91_SMC_DBW (3 << 13) /* Data Bus Width */
#define AT91_SMC_DBW_16 (1 << 13)
@@ -322,7 +349,78 @@
#define AT91_SMC_ACSS_2 (2 << 16)
#define AT91_SMC_ACSS_3 (3 << 16)
#define AT91_SMC_RWSETUP (7 << 24) /* Read & Write Signal Time Setup */
+#define AT91_SMC_RWSETUP_(x) ((x) << 24)
#define AT91_SMC_RWHOLD (7 << 28) /* Read & Write Signal Hold Time */
-
+#define AT91_SMC_RWHOLD_(x) ((x) << 28)
+
+/* SDRAM Controller registers */
+#define AT91_SDRAMC_MR (AT91_MC + 0x90) /* Mode Register */
+#define AT91_SDRAMC_MODE (0xf << 0) /* Command Mode */
+#define AT91_SDRAMC_MODE_NORMAL (0 << 0)
+#define AT91_SDRAMC_MODE_NOP (1 << 0)
+#define AT91_SDRAMC_MODE_PRECHARGE (2 << 0)
+#define AT91_SDRAMC_MODE_LMR (3 << 0)
+#define AT91_SDRAMC_MODE_REFRESH (4 << 0)
+#define AT91_SDRAMC_DBW (1 << 4) /* Data Bus Width */
+#define AT91_SDRAMC_DBW_32 (0 << 4)
+#define AT91_SDRAMC_DBW_16 (1 << 4)
+
+#define AT91_SDRAMC_TR (AT91_MC + 0x94) /* Refresh Timer Register */
+#define AT91_SDRAMC_COUNT (0xfff << 0) /* Refresh Timer Count */
+
+#define AT91_SDRAMC_CR (AT91_MC + 0x98) /* Configuration Register */
+#define AT91_SDRAMC_NC (3 << 0) /* Number of Column Bits */
+#define AT91_SDRAMC_NC_8 (0 << 0)
+#define AT91_SDRAMC_NC_9 (1 << 0)
+#define AT91_SDRAMC_NC_10 (2 << 0)
+#define AT91_SDRAMC_NC_11 (3 << 0)
+#define AT91_SDRAMC_NR (3 << 2) /* Number of Row Bits */
+#define AT91_SDRAMC_NR_11 (0 << 2)
+#define AT91_SDRAMC_NR_12 (1 << 2)
+#define AT91_SDRAMC_NR_13 (2 << 2)
+#define AT91_SDRAMC_NB (1 << 4) /* Number of Banks */
+#define AT91_SDRAMC_NB_2 (0 << 4)
+#define AT91_SDRAMC_NB_4 (1 << 4)
+#define AT91_SDRAMC_CAS (3 << 5) /* CAS Latency */
+#define AT91_SDRAMC_CAS_2 (2 << 5)
+#define AT91_SDRAMC_TWR (0xf << 7) /* Write Recovery Delay */
+#define AT91_SDRAMC_TRC (0xf << 11) /* Row Cycle Delay */
+#define AT91_SDRAMC_TRP (0xf << 15) /* Row Precharge Delay */
+#define AT91_SDRAMC_TRCD (0xf << 19) /* Row to Column Delay */
+#define AT91_SDRAMC_TRAS (0xf << 23) /* Active to Precharge Delay */
+#define AT91_SDRAMC_TXSR (0xf << 27) /* Exit Self Refresh to Active Delay */
+
+#define AT91_SDRAMC_SRR (AT91_MC + 0x9c) /* Self Refresh Register */
+#define AT91_SDRAMC_LPR (AT91_MC + 0xa0) /* Low Power Register */
+#define AT91_SDRAMC_IER (AT91_MC + 0xa4) /* Interrupt Enable Register */
+#define AT91_SDRAMC_IDR (AT91_MC + 0xa8) /* Interrupt Disable Register */
+#define AT91_SDRAMC_IMR (AT91_MC + 0xac) /* Interrupt Mask Register */
+#define AT91_SDRAMC_ISR (AT91_MC + 0xb0) /* Interrupt Status Register */
+
+/* Burst Flash Controller register */
+#define AT91_BFC_MR (AT91_MC + 0xc0) /* Mode Register */
+#define AT91_BFC_BFCOM (3 << 0) /* Burst Flash Controller Operating Mode */
+#define AT91_BFC_BFCOM_DISABLED (0 << 0)
+#define AT91_BFC_BFCOM_ASYNC (1 << 0)
+#define AT91_BFC_BFCOM_BURST (2 << 0)
+#define AT91_BFC_BFCC (3 << 2) /* Burst Flash Controller Clock */
+#define AT91_BFC_BFCC_MCK (1 << 2)
+#define AT91_BFC_BFCC_DIV2 (2 << 2)
+#define AT91_BFC_BFCC_DIV4 (3 << 2)
+#define AT91_BFC_AVL (0xf << 4) /* Address Valid Latency */
+#define AT91_BFC_PAGES (7 << 8) /* Page Size */
+#define AT91_BFC_PAGES_NO_PAGE (0 << 8)
+#define AT91_BFC_PAGES_16 (1 << 8)
+#define AT91_BFC_PAGES_32 (2 << 8)
+#define AT91_BFC_PAGES_64 (3 << 8)
+#define AT91_BFC_PAGES_128 (4 << 8)
+#define AT91_BFC_PAGES_256 (5 << 8)
+#define AT91_BFC_PAGES_512 (6 << 8)
+#define AT91_BFC_PAGES_1024 (7 << 8)
+#define AT91_BFC_OEL (3 << 12) /* Output Enable Latency */
+#define AT91_BFC_BAAEN (1 << 16) /* Burst Address Advance Enable */
+#define AT91_BFC_BFOEH (1 << 17) /* Burst Flash Output Enable Handling */
+#define AT91_BFC_MUXEN (1 << 18) /* Multiplexed Bus Enable */
+#define AT91_BFC_RDYEN (1 << 19) /* Ready Enable Mode */
#endif
diff --git a/include/asm-arm/arch-at91rm9200/uncompress.h b/include/asm-arm/arch-at91rm9200/uncompress.h
index b30dd552071..7b38497c24b 100644
--- a/include/asm-arm/arch-at91rm9200/uncompress.h
+++ b/include/asm-arm/arch-at91rm9200/uncompress.h
@@ -31,21 +31,22 @@
*
* This does not append a newline
*/
-static void putstr(const char *s)
+static void putc(int c)
+{
+ void __iomem *sys = (void __iomem *) AT91_BASE_SYS; /* physical address */
+
+ while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY))
+ barrier();
+ __raw_writel(c, sys + AT91_DBGU_THR);
+}
+
+static inline void flush(void)
{
void __iomem *sys = (void __iomem *) AT91_BASE_SYS; /* physical address */
- while (*s) {
- while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY)) { barrier(); }
- __raw_writel(*s, sys + AT91_DBGU_THR);
- if (*s == '\n') {
- while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY)) { barrier(); }
- __raw_writel('\r', sys + AT91_DBGU_THR);
- }
- s++;
- }
/* wait for transmission to complete */
- while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY)) { barrier(); }
+ while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY))
+ barrier();
}
#define arch_decomp_setup()
diff --git a/include/asm-arm/arch-cl7500/uncompress.h b/include/asm-arm/arch-cl7500/uncompress.h
index 68601b3e3b9..c437e0c88c3 100644
--- a/include/asm-arm/arch-cl7500/uncompress.h
+++ b/include/asm-arm/arch-cl7500/uncompress.h
@@ -3,27 +3,19 @@
*
* Copyright (C) 1999, 2000 Nexus Electronics Ltd.
*/
-
#define BASE 0x03010000
#define SERBASE (BASE + (0x2f8 << 2))
-static __inline__ void putc(char c)
+static inline void putc(char c)
{
- while (!(*((volatile unsigned int *)(SERBASE + 0x14)) & 0x20));
+ while (!(*((volatile unsigned int *)(SERBASE + 0x14)) & 0x20))
+ barrier();
+
*((volatile unsigned int *)(SERBASE)) = c;
}
-/*
- * This does not append a newline
- */
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
static __inline__ void arch_decomp_setup(void)
diff --git a/include/asm-arm/arch-clps711x/uncompress.h b/include/asm-arm/arch-clps711x/uncompress.h
index 9fc4bcfa168..07157b7e4b2 100644
--- a/include/asm-arm/arch-clps711x/uncompress.h
+++ b/include/asm-arm/arch-clps711x/uncompress.h
@@ -25,7 +25,6 @@
#undef CLPS7111_BASE
#define CLPS7111_BASE CLPS7111_PHYS_BASE
-#define barrier() __asm__ __volatile__("": : :"memory")
#define __raw_readl(p) (*(unsigned long *)(p))
#define __raw_writel(v,p) (*(unsigned long *)(p) = (v))
@@ -40,21 +39,15 @@
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static inline void putc(int c)
{
- char c;
-
- while ((c = *s++) != '\0') {
- while (clps_readl(SYSFLGx) & SYSFLG_UTXFF)
- barrier();
- clps_writel(c, UARTDRx);
+ while (clps_readl(SYSFLGx) & SYSFLG_UTXFF)
+ barrier();
+ clps_writel(c, UARTDRx);
+}
- if (c == '\n') {
- while (clps_readl(SYSFLGx) & SYSFLG_UTXFF)
- barrier();
- clps_writel('\r', UARTDRx);
- }
- }
+static inline void flush(void)
+{
while (clps_readl(SYSFLGx) & SYSFLG_UBUSY)
barrier();
}
diff --git a/include/asm-arm/arch-ebsa110/uncompress.h b/include/asm-arm/arch-ebsa110/uncompress.h
index eee95581a92..66b19c7fd90 100644
--- a/include/asm-arm/arch-ebsa110/uncompress.h
+++ b/include/asm-arm/arch-ebsa110/uncompress.h
@@ -8,33 +8,34 @@
* published by the Free Software Foundation.
*/
+#include <linux/serial_reg.h>
+
+#define SERIAL_BASE ((unsigned char *)0xfe000be0)
+
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static inline void putc(int c)
+{
+ unsigned char v, *base = SERIAL_BASE;
+
+ do {
+ v = base[UART_LSR << 2];
+ barrier();
+ } while (!(v & UART_LSR_THRE));
+
+ base[UART_TX << 2] = c;
+}
+
+static inline void flush(void)
{
- unsigned long tmp1, tmp2;
- __asm__ __volatile__(
- "ldrb %0, [%2], #1\n"
-" teq %0, #0\n"
-" beq 3f\n"
-"1: strb %0, [%3]\n"
-"2: ldrb %1, [%3, #0x14]\n"
-" and %1, %1, #0x60\n"
-" teq %1, #0x60\n"
-" bne 2b\n"
-" teq %0, #'\n'\n"
-" moveq %0, #'\r'\n"
-" beq 1b\n"
-" ldrb %0, [%2], #1\n"
-" teq %0, #0\n"
-" bne 1b\n"
-"3: ldrb %1, [%3, #0x14]\n"
-" and %1, %1, #0x60\n"
-" teq %1, #0x60\n"
-" bne 3b"
- : "=&r" (tmp1), "=&r" (tmp2)
- : "r" (s), "r" (0xf0000be0) : "cc");
+ unsigned char v, *base = SERIAL_BASE;
+
+ do {
+ v = base[UART_LSR << 2];
+ barrier();
+ } while ((v & (UART_LSR_TEMT|UART_LSR_THRE)) !=
+ (UART_LSR_TEMT|UART_LSR_THRE));
}
/*
diff --git a/include/asm-arm/arch-ebsa285/uncompress.h b/include/asm-arm/arch-ebsa285/uncompress.h
index c2fd84e2d90..86142c882b3 100644
--- a/include/asm-arm/arch-ebsa285/uncompress.h
+++ b/include/asm-arm/arch-ebsa285/uncompress.h
@@ -15,10 +15,11 @@
#define DC21285_BASE ((volatile unsigned int *)0x42000160)
#define SER0_BASE ((volatile unsigned char *)0x7c0003f8)
-static __inline__ void putc(char c)
+static inline void putc(char c)
{
if (machine_is_netwinder()) {
- while ((SER0_BASE[5] & 0x60) != 0x60);
+ while ((SER0_BASE[5] & 0x60) != 0x60)
+ barrier();
SER0_BASE[0] = c;
} else {
while (DC21285_BASE[6] & 8);
@@ -26,17 +27,8 @@ static __inline__ void putc(char c)
}
}
-/*
- * This does not append a newline
- */
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
/*
diff --git a/include/asm-arm/arch-ep93xx/uncompress.h b/include/asm-arm/arch-ep93xx/uncompress.h
index 4410d217077..c15274c85d5 100644
--- a/include/asm-arm/arch-ep93xx/uncompress.h
+++ b/include/asm-arm/arch-ep93xx/uncompress.h
@@ -16,17 +16,27 @@ static unsigned char __raw_readb(unsigned int ptr)
return *((volatile unsigned char *)ptr);
}
+static unsigned int __raw_readl(unsigned int ptr)
+{
+ return *((volatile unsigned int *)ptr);
+}
+
static void __raw_writeb(unsigned char value, unsigned int ptr)
{
*((volatile unsigned char *)ptr) = value;
}
+static void __raw_writel(unsigned int value, unsigned int ptr)
+{
+ *((volatile unsigned int *)ptr) = value;
+}
+
#define PHYS_UART1_DATA 0x808c0000
#define PHYS_UART1_FLAG 0x808c0018
#define UART1_FLAG_TXFF 0x20
-static __inline__ void putc(char c)
+static inline void putc(int c)
{
int i;
@@ -39,15 +49,37 @@ static __inline__ void putc(char c)
__raw_writeb(c, PHYS_UART1_DATA);
}
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
-#define arch_decomp_setup()
+
+/*
+ * Some bootloaders don't turn off DMA from the ethernet MAC before
+ * jumping to linux, which means that we might end up with bits of RX
+ * status and packet data scribbled over the uncompressed kernel image.
+ * Work around this by resetting the ethernet MAC before we uncompress.
+ */
+#define PHYS_ETH_SELF_CTL 0x80010020
+#define ETH_SELF_CTL_RESET 0x00000001
+
+static void ethernet_reset(void)
+{
+ unsigned int v;
+
+ /* Reset the ethernet MAC. */
+ v = __raw_readl(PHYS_ETH_SELF_CTL);
+ __raw_writel(v | ETH_SELF_CTL_RESET, PHYS_ETH_SELF_CTL);
+
+ /* Wait for reset to finish. */
+ while (__raw_readl(PHYS_ETH_SELF_CTL) & ETH_SELF_CTL_RESET)
+ ;
+}
+
+
+static void arch_decomp_setup(void)
+{
+ ethernet_reset();
+}
+
#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-h720x/uncompress.h b/include/asm-arm/arch-h720x/uncompress.h
index 9535764bcc7..18c69e0f358 100644
--- a/include/asm-arm/arch-h720x/uncompress.h
+++ b/include/asm-arm/arch-h720x/uncompress.h
@@ -12,22 +12,20 @@
#define LSR 0x14
#define TEMPTY 0x40
-static void putstr(const char *s)
+static inline void putc(int c)
{
- char c;
volatile unsigned char *p = (volatile unsigned char *)(IO_PHYS+0x20000);
- while ( (c = *s++) != '\0') {
- /* wait until transmit buffer is empty */
- while((p[LSR] & TEMPTY) == 0x0);
- /* write next character */
- *p = c;
-
- if(c == '\n') {
- while((p[LSR] & TEMPTY) == 0x0);
- *p = '\r';
- }
- }
+ /* wait until transmit buffer is empty */
+ while((p[LSR] & TEMPTY) == 0x0)
+ barrier();
+
+ /* write next character */
+ *p = c;
+}
+
+static inline void flush(void)
+{
}
/*
diff --git a/include/asm-arm/arch-imx/uncompress.h b/include/asm-arm/arch-imx/uncompress.h
index 096077f2750..da333f69136 100644
--- a/include/asm-arm/arch-imx/uncompress.h
+++ b/include/asm-arm/arch-imx/uncompress.h
@@ -39,8 +39,7 @@
*
* This does not append a newline
*/
-static void
-putstr(const char *s)
+static void putc(int c)
{
unsigned long serial_port;
@@ -54,20 +53,14 @@ putstr(const char *s)
return;
} while(0);
- while (*s) {
- while ( !(UART(USR2) & USR2_TXFE) )
- barrier();
+ while (!(UART(USR2) & USR2_TXFE))
+ barrier();
- UART(TXR) = *s;
-
- if (*s == '\n') {
- while ( !(UART(USR2) & USR2_TXFE) )
- barrier();
+ UART(TXR) = c;
+}
- UART(TXR) = '\r';
- }
- s++;
- }
+static inline void flush(void)
+{
}
/*
diff --git a/include/asm-arm/arch-integrator/uncompress.h b/include/asm-arm/arch-integrator/uncompress.h
index 3957402741d..f61825c4d90 100644
--- a/include/asm-arm/arch-integrator/uncompress.h
+++ b/include/asm-arm/arch-integrator/uncompress.h
@@ -28,21 +28,18 @@
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static void putc(int c)
{
- while (*s) {
- while (AMBA_UART_FR & (1 << 5));
+ while (AMBA_UART_FR & (1 << 5))
+ barrier();
- AMBA_UART_DR = *s;
-
- if (*s == '\n') {
- while (AMBA_UART_FR & (1 << 5));
+ AMBA_UART_DR = c;
+}
- AMBA_UART_DR = '\r';
- }
- s++;
- }
- while (AMBA_UART_FR & (1 << 3));
+static inline void flush(void)
+{
+ while (AMBA_UART_FR & (1 << 3))
+ barrier();
}
/*
diff --git a/include/asm-arm/arch-iop3xx/uncompress.h b/include/asm-arm/arch-iop3xx/uncompress.h
index 82b88762c3c..c98eb6254b1 100644
--- a/include/asm-arm/arch-iop3xx/uncompress.h
+++ b/include/asm-arm/arch-iop3xx/uncompress.h
@@ -19,23 +19,15 @@ static volatile UTYPE uart_base;
#define TX_DONE (UART_LSR_TEMT|UART_LSR_THRE)
-static __inline__ void putc(char c)
+static inline void putc(char c)
{
- while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE);
+ while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
+ barrier();
*uart_base = c;
}
-/*
- * This does not append a newline
- */
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
static __inline__ void __arch_decomp_setup(unsigned long arch_id)
diff --git a/include/asm-arm/arch-ixp2000/uncompress.h b/include/asm-arm/arch-ixp2000/uncompress.h
index 3d3d5b2ed6e..f66b408f363 100644
--- a/include/asm-arm/arch-ixp2000/uncompress.h
+++ b/include/asm-arm/arch-ixp2000/uncompress.h
@@ -29,23 +29,18 @@
#define UARTSR PHYS(0x14) /* Status reg */
-static __inline__ void putc(char c)
+static inline void putc(int c)
{
int j = 0x1000;
- while (--j && !(*UARTSR & UART_LSR_THRE));
+ while (--j && !(*UARTSR & UART_LSR_THRE))
+ barrier();
+
*UARTDR = c;
}
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s)
- {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
#define arch_decomp_setup()
diff --git a/include/asm-arm/arch-ixp23xx/debug-macro.S b/include/asm-arm/arch-ixp23xx/debug-macro.S
new file mode 100644
index 00000000000..eb99fd69fd2
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/debug-macro.S
@@ -0,0 +1,23 @@
+/*
+ * include/asm-arm/arch-ixp23xx/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <asm/arch/ixp23xx.h>
+
+ .macro addruart,rx
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ mmu enabled?
+ ldreq \rx, =IXP23XX_PERIPHERAL_PHYS @ physical
+ ldrne \rx, =IXP23XX_PERIPHERAL_VIRT @ virtual
+ .endm
+
+#define UART_SHIFT 2
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-ixp23xx/dma.h b/include/asm-arm/arch-ixp23xx/dma.h
new file mode 100644
index 00000000000..2f4335e3b83
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/dma.h
@@ -0,0 +1,3 @@
+/*
+ * include/asm-arm/arch-ixp23xx/dma.h
+ */
diff --git a/include/asm-arm/arch-ixp23xx/entry-macro.S b/include/asm-arm/arch-ixp23xx/entry-macro.S
new file mode 100644
index 00000000000..0ef4e6016ac
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/entry-macro.S
@@ -0,0 +1,31 @@
+/*
+ * include/asm-arm/arch-ixp23xx/entry-macro.S
+ */
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \irqnr, =(IXP23XX_INTC_VIRT + IXP23XX_INTR_IRQ_ENC_ST_OFFSET)
+ ldr \irqnr, [\irqnr] @ get interrupt number
+ cmp \irqnr, #0x0 @ suprious interrupt ?
+ movne \irqnr, \irqnr, lsr #2 @ skip unwanted low order bits
+ subne \irqnr, \irqnr, #1 @ convert to 0 based
+
+#if 0
+ cmp \irqnr, #IRQ_IXP23XX_PCI_INT_RPH
+ bne 1001f
+ mov \irqnr, #IRQ_IXP23XX_INTA
+
+ ldr \irqnr, =0xf5000030
+
+ mov \tmp, #(1<<26)
+ tst \irqnr, \tmp
+ movne \irqnr, #IRQ_IXP23XX_INTB
+
+ mov \tmp, #(1<<27)
+ tst \irqnr, \tmp
+ movne \irqnr, #IRQ_IXP23XX_INTA
+1001:
+#endif
+ .endm
diff --git a/include/asm-arm/arch-ixp23xx/hardware.h b/include/asm-arm/arch-ixp23xx/hardware.h
new file mode 100644
index 00000000000..c0010d21a68
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/hardware.h
@@ -0,0 +1,37 @@
+/*
+ * include/asm-arm/arch-ixp23xx/hardware.h
+ *
+ * Copyright (C) 2002-2004 Intel Corporation.
+ * Copyricht (C) 2005 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Hardware definitions for IXP23XX based systems
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+/* PCI IO info */
+#define PCIO_BASE IXP23XX_PCI_IO_VIRT
+#define PCIBIOS_MIN_IO 0x00000000
+#define PCIBIOS_MIN_MEM 0xe0000000
+
+#include "ixp23xx.h"
+
+#define pcibios_assign_all_busses() 0
+
+/*
+ * Platform helper functions
+ */
+#include "platform.h"
+
+/*
+ * Platform-specific headers
+ */
+#include "ixdp2351.h"
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/io.h b/include/asm-arm/arch-ixp23xx/io.h
new file mode 100644
index 00000000000..18415a81ac7
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/io.h
@@ -0,0 +1,54 @@
+/*
+ * include/asm-arm/arch-ixp23xx/io.h
+ *
+ * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2003-2005 Intel Corp.
+ * Copyright (C) 2005 MontaVista Software, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_IO_H
+#define __ASM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(p) ((void __iomem*)((p) + IXP23XX_PCI_IO_VIRT))
+#define __mem_pci(a) (a)
+
+#include <linux/kernel.h> /* For BUG */
+
+static inline void __iomem *
+ixp23xx_ioremap(unsigned long addr, unsigned long size, unsigned long flags)
+{
+ if (addr >= IXP23XX_PCI_MEM_START &&
+ addr <= IXP23XX_PCI_MEM_START + IXP23XX_PCI_MEM_SIZE) {
+ if (addr + size > IXP23XX_PCI_MEM_START + IXP23XX_PCI_MEM_SIZE)
+ return NULL;
+
+ return (void __iomem *)
+ ((addr - IXP23XX_PCI_MEM_START) + IXP23XX_PCI_MEM_VIRT);
+ }
+
+ return __ioremap(addr, size, flags);
+}
+
+static inline void
+ixp23xx_iounmap(void __iomem *addr)
+{
+ if ((((u32)addr) >= IXP23XX_PCI_MEM_VIRT) &&
+ (((u32)addr) < IXP23XX_PCI_MEM_VIRT + IXP23XX_PCI_MEM_SIZE))
+ return;
+
+ __iounmap(addr);
+}
+
+#define __arch_ioremap(a,s,f) ixp23xx_ioremap(a,s,f)
+#define __arch_iounmap(a) ixp23xx_iounmap(a)
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/irqs.h b/include/asm-arm/arch-ixp23xx/irqs.h
new file mode 100644
index 00000000000..e6963958572
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/irqs.h
@@ -0,0 +1,223 @@
+/*
+ * include/asm-arm/arch-ixp23xx/irqs.h
+ *
+ * IRQ definitions for IXP23XX based systems
+ *
+ * Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ *
+ * Copyright (C) 2003-2004 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define NR_IXP23XX_IRQS IRQ_IXP23XX_INTB+1
+#define IRQ_IXP23XX_EXTIRQS NR_IXP23XX_IRQS
+
+
+#define IRQ_IXP23XX_DBG0 0 /* Debug/Execution/MBox */
+#define IRQ_IXP23XX_DBG1 1 /* Debug/Execution/MBox */
+#define IRQ_IXP23XX_NPE_TRG 2 /* npe_trigger */
+#define IRQ_IXP23XX_TIMER1 3 /* Timer[0] */
+#define IRQ_IXP23XX_TIMER2 4 /* Timer[1] */
+#define IRQ_IXP23XX_TIMESTAMP 5 /* Timer[2], Time-stamp */
+#define IRQ_IXP23XX_WDOG 6 /* Time[3], Watchdog Timer */
+#define IRQ_IXP23XX_PCI_DBELL 7 /* PCI Doorbell */
+#define IRQ_IXP23XX_PCI_DMA1 8 /* PCI DMA Channel 1 */
+#define IRQ_IXP23XX_PCI_DMA2 9 /* PCI DMA Channel 2 */
+#define IRQ_IXP23XX_PCI_DMA3 10 /* PCI DMA Channel 3 */
+#define IRQ_IXP23XX_PCI_INT_RPH 11 /* pcxg_pci_int_rph */
+#define IRQ_IXP23XX_CPP_PMU 12 /* xpxg_pm_int_rpl */
+#define IRQ_IXP23XX_SWINT0 13 /* S/W Interrupt0 */
+#define IRQ_IXP23XX_SWINT1 14 /* S/W Interrupt1 */
+#define IRQ_IXP23XX_UART2 15 /* UART1 Interrupt */
+#define IRQ_IXP23XX_UART1 16 /* UART0 Interrupt */
+#define IRQ_IXP23XX_XSI_PMU_ROLLOVER 17 /* AHB Performance M. Unit counter rollover */
+#define IRQ_IXP23XX_XSI_AHB_PM0 18 /* intr_pm_o */
+#define IRQ_IXP23XX_XSI_AHB_ECE0 19 /* intr_ece_o */
+#define IRQ_IXP23XX_XSI_AHB_GASKET 20 /* gas_intr_o */
+#define IRQ_IXP23XX_XSI_CPP 21 /* xsi2cpp_int */
+#define IRQ_IXP23XX_CPP_XSI 22 /* cpp2xsi_int */
+#define IRQ_IXP23XX_ME_ATTN0 23 /* ME_ATTN */
+#define IRQ_IXP23XX_ME_ATTN1 24 /* ME_ATTN */
+#define IRQ_IXP23XX_ME_ATTN2 25 /* ME_ATTN */
+#define IRQ_IXP23XX_ME_ATTN3 26 /* ME_ATTN */
+#define IRQ_IXP23XX_PCI_ERR_RPH 27 /* PCXG_PCI_ERR_RPH */
+#define IRQ_IXP23XX_D0XG_ECC_CORR 28 /* D0XG_DRAM_ECC_CORR */
+#define IRQ_IXP23XX_D0XG_ECC_UNCORR 29 /* D0XG_DRAM_ECC_UNCORR */
+#define IRQ_IXP23XX_SRAM_ERR1 30 /* SRAM1_ERR */
+#define IRQ_IXP23XX_SRAM_ERR0 31 /* SRAM0_ERR */
+#define IRQ_IXP23XX_MEDIA_ERR 32 /* MEDIA_ERR */
+#define IRQ_IXP23XX_STH_DRAM_ECC_MAJ 33 /* STH_DRAM0_ECC_MAJ */
+#define IRQ_IXP23XX_GPIO6 34 /* GPIO0 interrupts */
+#define IRQ_IXP23XX_GPIO7 35 /* GPIO1 interrupts */
+#define IRQ_IXP23XX_GPIO8 36 /* GPIO2 interrupts */
+#define IRQ_IXP23XX_GPIO9 37 /* GPIO3 interrupts */
+#define IRQ_IXP23XX_GPIO10 38 /* GPIO4 interrupts */
+#define IRQ_IXP23XX_GPIO11 39 /* GPIO5 interrupts */
+#define IRQ_IXP23XX_GPIO12 40 /* GPIO6 interrupts */
+#define IRQ_IXP23XX_GPIO13 41 /* GPIO7 interrupts */
+#define IRQ_IXP23XX_GPIO14 42 /* GPIO8 interrupts */
+#define IRQ_IXP23XX_GPIO15 43 /* GPIO9 interrupts */
+#define IRQ_IXP23XX_SHAC_RING0 44 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING1 45 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING2 46 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING3 47 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING4 48 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING5 49 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING6 50 /* SHAC RING Full */
+#define IRQ_IXP23XX_SHAC_RING7 51 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING8 52 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING9 53 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING10 54 /* SHAC Ring Full */
+#define IRQ_IXP23XX_SHAC_RING11 55 /* SHAC Ring Full */
+#define IRQ_IXP23XX_ME_THREAD_A0_ME0 56 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A1_ME0 57 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A2_ME0 58 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A3_ME0 59 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A4_ME0 60 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A5_ME0 61 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A6_ME0 62 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A7_ME0 63 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A8_ME1 64 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A9_ME1 65 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A10_ME1 66 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A11_ME1 67 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A12_ME1 68 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A13_ME1 69 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A14_ME1 70 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A15_ME1 71 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A16_ME2 72 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A17_ME2 73 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A18_ME2 74 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A19_ME2 75 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A20_ME2 76 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A21_ME2 77 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A22_ME2 78 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A23_ME2 79 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A24_ME3 80 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A25_ME3 81 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A26_ME3 82 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A27_ME3 83 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A28_ME3 84 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A29_ME3 85 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A30_ME3 86 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_A31_ME3 87 /* ME_THREAD_A */
+#define IRQ_IXP23XX_ME_THREAD_B0_ME0 88 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B1_ME0 89 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B2_ME0 90 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B3_ME0 91 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B4_ME0 92 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B5_ME0 93 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B6_ME0 94 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B7_ME0 95 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B8_ME1 96 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B9_ME1 97 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B10_ME1 98 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B11_ME1 99 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B12_ME1 100 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B13_ME1 101 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B14_ME1 102 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B15_ME1 103 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B16_ME2 104 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B17_ME2 105 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B18_ME2 106 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B19_ME2 107 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B20_ME2 108 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B21_ME2 109 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B22_ME2 110 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B23_ME2 111 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B24_ME3 112 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B25_ME3 113 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B26_ME3 114 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B27_ME3 115 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B28_ME3 116 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B29_ME3 117 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B30_ME3 118 /* ME_THREAD_B */
+#define IRQ_IXP23XX_ME_THREAD_B31_ME3 119 /* ME_THREAD_B */
+
+#define NUM_IXP23XX_RAW_IRQS 120
+
+#define IRQ_IXP23XX_INTA 120 /* Indirect pcxg_pci_int_rph */
+#define IRQ_IXP23XX_INTB 121 /* Indirect pcxg_pci_int_rph */
+
+#define NR_IXP23XX_IRQ (IRQ_IXP23XX_INTB + 1)
+
+/*
+ * We default to 32 per-board IRQs. Increase this number if you need
+ * more, but keep it realistic.
+ */
+#define NR_IXP23XX_MACH_IRQS 32
+
+#define NR_IRQS NR_IXP23XX_IRQS + NR_IXP23XX_MACH_IRQS
+
+#define IXP23XX_MACH_IRQ(irq) (NR_IXP23XX_IRQ + (irq))
+
+
+/*
+ * IXDP2351-specific interrupts
+ */
+
+/*
+ * External PCI interrupts signaled through INTB
+ *
+ */
+#define IXDP2351_INTB_IRQ_BASE 0
+#define IRQ_IXDP2351_INTA_82546 IXP23XX_MACH_IRQ(0)
+#define IRQ_IXDP2351_INTB_82546 IXP23XX_MACH_IRQ(1)
+#define IRQ_IXDP2351_SPCI_DB_0 IXP23XX_MACH_IRQ(2)
+#define IRQ_IXDP2351_SPCI_DB_1 IXP23XX_MACH_IRQ(3)
+#define IRQ_IXDP2351_SPCI_PMC_INTA IXP23XX_MACH_IRQ(4)
+#define IRQ_IXDP2351_SPCI_PMC_INTB IXP23XX_MACH_IRQ(5)
+#define IRQ_IXDP2351_SPCI_PMC_INTC IXP23XX_MACH_IRQ(6)
+#define IRQ_IXDP2351_SPCI_PMC_INTD IXP23XX_MACH_IRQ(7)
+#define IRQ_IXDP2351_SPCI_FIC IXP23XX_MACH_IRQ(8)
+
+#define IXDP2351_INTB_IRQ_BIT(irq) (irq - IXP23XX_MACH_IRQ(0))
+#define IXDP2351_INTB_IRQ_MASK(irq) (1 << IXDP2351_INTB_IRQ_BIT(irq))
+#define IXDP2351_INTB_IRQ_VALID 0x01FF
+#define IXDP2351_INTB_IRQ_NUM 16
+
+/*
+ * Other external interrupts signaled through INTA
+ */
+#define IXDP2351_INTA_IRQ_BASE 16
+#define IRQ_IXDP2351_IPMI_FROM IXP23XX_MACH_IRQ(16)
+#define IRQ_IXDP2351_125US IXP23XX_MACH_IRQ(17)
+#define IRQ_IXDP2351_DB_0_ADD IXP23XX_MACH_IRQ(18)
+#define IRQ_IXDP2351_DB_1_ADD IXP23XX_MACH_IRQ(19)
+#define IRQ_IXDP2351_DEBUG1 IXP23XX_MACH_IRQ(20)
+#define IRQ_IXDP2351_ADD_UART IXP23XX_MACH_IRQ(21)
+#define IRQ_IXDP2351_FIC_ADD IXP23XX_MACH_IRQ(24)
+#define IRQ_IXDP2351_CS8900 IXP23XX_MACH_IRQ(25)
+#define IRQ_IXDP2351_BBSRAM IXP23XX_MACH_IRQ(26)
+#define IRQ_IXDP2351_CONFIG_MEDIA IXP23XX_MACH_IRQ(27)
+#define IRQ_IXDP2351_CLOCK_REF IXP23XX_MACH_IRQ(28)
+#define IRQ_IXDP2351_A10_NP IXP23XX_MACH_IRQ(29)
+#define IRQ_IXDP2351_A11_NP IXP23XX_MACH_IRQ(30)
+#define IRQ_IXDP2351_DEBUG_NP IXP23XX_MACH_IRQ(31)
+
+#define IXDP2351_INTA_IRQ_BIT(irq) (irq - IXP23XX_MACH_IRQ(16))
+#define IXDP2351_INTA_IRQ_MASK(irq) (1 << IXDP2351_INTA_IRQ_BIT(irq))
+#define IXDP2351_INTA_IRQ_VALID 0xFF3F
+#define IXDP2351_INTA_IRQ_NUM 16
+
+
+/*
+ * ADI RoadRunner IRQs
+ */
+#define IRQ_ROADRUNNER_PCI_INTA IRQ_IXP23XX_INTA
+#define IRQ_ROADRUNNER_PCI_INTB IRQ_IXP23XX_INTB
+#define IRQ_ROADRUNNER_PCI_INTC IRQ_IXP23XX_GPIO11
+#define IRQ_ROADRUNNER_PCI_INTD IRQ_IXP23XX_GPIO12
+
+/*
+ * Put new board definitions here
+ */
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/ixdp2351.h b/include/asm-arm/arch-ixp23xx/ixdp2351.h
new file mode 100644
index 00000000000..4a24f8f1565
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/ixdp2351.h
@@ -0,0 +1,89 @@
+/*
+ * include/asm-arm/arch-ixp23xx/ixdp2351.h
+ *
+ * Register and other defines for IXDP2351
+ *
+ * Copyright (c) 2002-2004 Intel Corp.
+ * Copytight (c) 2005 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_ARCH_IXDP2351_H
+#define __ASM_ARCH_IXDP2351_H
+
+/*
+ * NP module memory map
+ */
+#define IXDP2351_NP_PHYS_BASE (IXP23XX_EXP_BUS_CS4_BASE)
+#define IXDP2351_NP_PHYS_SIZE 0x00100000
+#define IXDP2351_NP_VIRT_BASE 0xeff00000
+
+#define IXDP2351_VIRT_CS8900_BASE (IXDP2351_NP_VIRT_BASE)
+#define IXDP2351_VIRT_CS8900_END (IXDP2351_VIRT_CS8900_BASE + 16)
+
+#define IXDP2351_VIRT_NP_CPLD_BASE (IXP23XX_EXP_BUS_CS4_BASE_VIRT + 0x00010000)
+
+#define IXDP2351_NP_CPLD_REG(reg) ((volatile u16 *)(IXDP2351_VIRT_NP_CPLD_BASE + reg))
+
+#define IXDP2351_NP_CPLD_RESET1_REG IXDP2351_NP_CPLD_REG(0x00)
+#define IXDP2351_NP_CPLD_LED_REG IXDP2351_NP_CPLD_REG(0x02)
+#define IXDP2351_NP_CPLD_VERSION_REG IXDP2351_NP_CPLD_REG(0x04)
+
+/*
+ * Base board module memory map
+ */
+
+#define IXDP2351_BB_BASE_PHYS (IXP23XX_EXP_BUS_CS5_BASE)
+#define IXDP2351_BB_SIZE 0x01000000
+#define IXDP2351_BB_BASE_VIRT (0xee000000)
+
+#define IXDP2351_BB_AREA_BASE(offset) (IXDP2351_BB_BASE_VIRT + offset)
+
+#define IXDP2351_VIRT_NVRAM_BASE IXDP2351_BB_AREA_BASE(0x0)
+#define IXDP2351_NVRAM_SIZE (0x20000)
+
+#define IXDP2351_VIRT_MB_IXF1104_BASE IXDP3251_BB_AREA_BASE(0x00020000)
+#define IXDP2351_VIRT_ADD_UART_BASE IXDP2351_BB_AREA_BASE(0x000240C0)
+#define IXDP2351_VIRT_FIC_BASE IXDP2351_BB_AREA_BASE(0x00200000)
+#define IXDP2351_VIRT_DB0_BASE IXDP2351_BB_AREA_BASE(0x00400000)
+#define IXDP2351_VIRT_DB1_BASE IXDP2351_BB_AREA_BASE(0x00600000)
+#define IXDP2351_VIRT_CPLD_BASE IXDP2351_BB_AREA_BASE(0x00024000)
+
+/*
+ * On board CPLD registers
+ */
+#define IXDP2351_CPLD_BB_REG(reg) ((volatile u16 *)(IXDP2351_VIRT_CPLD_BASE + reg))
+
+#define IXDP2351_CPLD_RESET0_REG IXDP2351_CPLD_BB_REG(0x00)
+#define IXDP2351_CPLD_RESET1_REG IXDP2351_CPLD_BB_REG(0x04)
+
+#define IXDP2351_CPLD_RESET1_MAGIC 0x55AA
+#define IXDP2351_CPLD_RESET1_ENABLE 0x8000
+
+#define IXDP2351_CPLD_FPGA_CONFIG_REG IXDP2351_CPLD_BB_REG(0x08)
+#define IXDP2351_CPLD_INTB_MASK_SET_REG IXDP2351_CPLD_BB_REG(0x10)
+#define IXDP2351_CPLD_INTA_MASK_SET_REG IXDP2351_CPLD_BB_REG(0x14)
+#define IXDP2351_CPLD_INTB_STAT_REG IXDP2351_CPLD_BB_REG(0x18)
+#define IXDP2351_CPLD_INTA_STAT_REG IXDP2351_CPLD_BB_REG(0x1C)
+#define IXDP2351_CPLD_INTB_RAW_REG IXDP2351_CPLD_BB_REG(0x20) /* read */
+#define IXDP2351_CPLD_INTA_RAW_REG IXDP2351_CPLD_BB_REG(0x24) /* read */
+#define IXDP2351_CPLD_INTB_MASK_CLR_REG IXDP2351_CPLD_INTB_RAW_REG /* write */
+#define IXDP2351_CPLD_INTA_MASK_CLR_REG IXDP2351_CPLD_INTA_RAW_REG /* write */
+#define IXDP2351_CPLD_INTB_SIM_REG IXDP2351_CPLD_BB_REG(0x28)
+#define IXDP2351_CPLD_INTA_SIM_REG IXDP2351_CPLD_BB_REG(0x2C)
+ /* Interrupt bits are defined in irqs.h */
+#define IXDP2351_CPLD_BB_GBE0_REG IXDP2351_CPLD_BB_REG(0x30)
+#define IXDP2351_CPLD_BB_GBE1_REG IXDP2351_CPLD_BB_REG(0x34)
+
+/* #define IXDP2351_CPLD_BB_MISC_REG IXDP2351_CPLD_REG(0x1C) */
+/* #define IXDP2351_CPLD_BB_MISC_REV_MASK 0xFF */
+/* #define IXDP2351_CPLD_BB_GDXCS0_REG IXDP2351_CPLD_REG(0x24) */
+/* #define IXDP2351_CPLD_BB_GDXCS1_REG IXDP2351_CPLD_REG(0x28) */
+/* #define IXDP2351_CPLD_BB_CLOCK_REG IXDP2351_CPLD_REG(0x04) */
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/ixp23xx.h b/include/asm-arm/arch-ixp23xx/ixp23xx.h
new file mode 100644
index 00000000000..e49e1ca61b1
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/ixp23xx.h
@@ -0,0 +1,306 @@
+/*
+ * include/asm-arm/arch-ixp23xx/ixp23xx.h
+ *
+ * Register definitions for IXP23XX
+ *
+ * Copyright (C) 2003-2005 Intel Corporation.
+ * Copyright (C) 2005 MontaVista Software, Inc.
+ *
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * 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_IXP23XX_H
+#define __ASM_ARCH_IXP23XX_H
+
+/*
+ * IXP2300 linux memory map:
+ *
+ * virt phys size
+ * fffd0000 a0000000 64K XSI2CPP_CSR
+ * fffc0000 c4000000 4K EXP_CFG
+ * fff00000 c8000000 64K PERIPHERAL
+ * fe000000 1c0000000 16M CAP_CSR
+ * fd000000 1c8000000 16M MSF_CSR
+ * fb000000 16M ---
+ * fa000000 1d8000000 32M PCI_IO
+ * f8000000 1da000000 32M PCI_CFG
+ * f6000000 1de000000 32M PCI_CREG
+ * f4000000 32M ---
+ * f0000000 1e0000000 64M PCI_MEM
+ * e[c-f]000000 per-platform mappings
+ */
+
+
+/****************************************************************************
+ * Static mappings.
+ ****************************************************************************/
+#define IXP23XX_XSI2CPP_CSR_PHYS 0xa0000000
+#define IXP23XX_XSI2CPP_CSR_VIRT 0xfffd0000
+#define IXP23XX_XSI2CPP_CSR_SIZE 0x00010000
+
+#define IXP23XX_EXP_CFG_PHYS 0xc4000000
+#define IXP23XX_EXP_CFG_VIRT 0xfffc0000
+#define IXP23XX_EXP_CFG_SIZE 0x00001000
+
+#define IXP23XX_PERIPHERAL_PHYS 0xc8000000
+#define IXP23XX_PERIPHERAL_VIRT 0xfff00000
+#define IXP23XX_PERIPHERAL_SIZE 0x00010000
+
+#define IXP23XX_CAP_CSR_PHYS 0x1c0000000ULL
+#define IXP23XX_CAP_CSR_VIRT 0xfe000000
+#define IXP23XX_CAP_CSR_SIZE 0x01000000
+
+#define IXP23XX_MSF_CSR_PHYS 0x1c8000000ULL
+#define IXP23XX_MSF_CSR_VIRT 0xfd000000
+#define IXP23XX_MSF_CSR_SIZE 0x01000000
+
+#define IXP23XX_PCI_IO_PHYS 0x1d8000000ULL
+#define IXP23XX_PCI_IO_VIRT 0xfa000000
+#define IXP23XX_PCI_IO_SIZE 0x02000000
+
+#define IXP23XX_PCI_CFG_PHYS 0x1da000000ULL
+#define IXP23XX_PCI_CFG_VIRT 0xf8000000
+#define IXP23XX_PCI_CFG_SIZE 0x02000000
+#define IXP23XX_PCI_CFG0_VIRT IXP23XX_PCI_CFG_VIRT
+#define IXP23XX_PCI_CFG1_VIRT (IXP23XX_PCI_CFG_VIRT + 0x01000000)
+
+#define IXP23XX_PCI_CREG_PHYS 0x1de000000ULL
+#define IXP23XX_PCI_CREG_VIRT 0xf6000000
+#define IXP23XX_PCI_CREG_SIZE 0x02000000
+#define IXP23XX_PCI_CSR_VIRT (IXP23XX_PCI_CREG_VIRT + 0x01000000)
+
+#define IXP23XX_PCI_MEM_START 0xe0000000
+#define IXP23XX_PCI_MEM_PHYS 0x1e0000000ULL
+#define IXP23XX_PCI_MEM_VIRT 0xf0000000
+#define IXP23XX_PCI_MEM_SIZE 0x04000000
+
+
+/****************************************************************************
+ * XSI2CPP CSRs.
+ ****************************************************************************/
+#define IXP23XX_XSI2CPP_REG(x) ((volatile unsigned long *)(IXP23XX_XSI2CPP_CSR_VIRT + (x)))
+#define IXP23XX_CPP2XSI_CURR_XFER_REG3 IXP23XX_XSI2CPP_REG(0xf8)
+#define IXP23XX_CPP2XSI_ADDR_31 (1 << 19)
+#define IXP23XX_CPP2XSI_PSH_OFF (1 << 20)
+#define IXP23XX_CPP2XSI_COH_OFF (1 << 21)
+
+
+/****************************************************************************
+ * Expansion Bus Config.
+ ****************************************************************************/
+#define IXP23XX_EXP_CFG_REG(x) ((volatile unsigned long *)(IXP23XX_EXP_CFG_VIRT + (x)))
+#define IXP23XX_EXP_CS0 IXP23XX_EXP_CFG_REG(0x00)
+#define IXP23XX_EXP_CS1 IXP23XX_EXP_CFG_REG(0x04)
+#define IXP23XX_EXP_CS2 IXP23XX_EXP_CFG_REG(0x08)
+#define IXP23XX_EXP_CS3 IXP23XX_EXP_CFG_REG(0x0c)
+#define IXP23XX_EXP_CS4 IXP23XX_EXP_CFG_REG(0x10)
+#define IXP23XX_EXP_CS5 IXP23XX_EXP_CFG_REG(0x14)
+#define IXP23XX_EXP_CS6 IXP23XX_EXP_CFG_REG(0x18)
+#define IXP23XX_EXP_CS7 IXP23XX_EXP_CFG_REG(0x1c)
+#define IXP23XX_FLASH_WRITABLE (0x2)
+#define IXP23XX_FLASH_BUS8 (0x1)
+
+#define IXP23XX_EXP_CFG0 IXP23XX_EXP_CFG_REG(0x20)
+#define IXP23XX_EXP_CFG1 IXP23XX_EXP_CFG_REG(0x24)
+#define IXP23XX_EXP_CFG0_MEM_MAP (1 << 31)
+#define IXP23XX_EXP_CFG0_XSCALE_SPEED_SEL (3 << 22)
+#define IXP23XX_EXP_CFG0_XSCALE_SPEED_EN (1 << 21)
+#define IXP23XX_EXP_CFG0_CPP_SPEED_SEL (3 << 19)
+#define IXP23XX_EXP_CFG0_CPP_SPEED_EN (1 << 18)
+#define IXP23XX_EXP_CFG0_PCI_SWIN (3 << 16)
+#define IXP23XX_EXP_CFG0_PCI_DWIN (3 << 14)
+#define IXP23XX_EXP_CFG0_PCI33_MODE (1 << 13)
+#define IXP23XX_EXP_CFG0_QDR_SPEED_SEL (1 << 12)
+#define IXP23XX_EXP_CFG0_CPP_DIV_SEL (1 << 5)
+#define IXP23XX_EXP_CFG0_XSI_NOT_PRES (1 << 4)
+#define IXP23XX_EXP_CFG0_PROM_BOOT (1 << 3)
+#define IXP23XX_EXP_CFG0_PCI_ARB (1 << 2)
+#define IXP23XX_EXP_CFG0_PCI_HOST (1 << 1)
+#define IXP23XX_EXP_CFG0_FLASH_WIDTH (1 << 0)
+
+#define IXP23XX_EXP_UNIT_FUSE IXP23XX_EXP_CFG_REG(0x28)
+#define IXP23XX_EXP_MSF_MUX IXP23XX_EXP_CFG_REG(0x30)
+
+#define IXP23XX_EXP_BUS_PHYS 0x90000000
+#define IXP23XX_EXP_BUS_WINDOW_SIZE 0x01000000
+
+#define IXP23XX_EXP_BUS_CS0_BASE (IXP23XX_EXP_BUS_PHYS + 0x00000000)
+#define IXP23XX_EXP_BUS_CS1_BASE (IXP23XX_EXP_BUS_PHYS + 0x01000000)
+#define IXP23XX_EXP_BUS_CS2_BASE (IXP23XX_EXP_BUS_PHYS + 0x02000000)
+#define IXP23XX_EXP_BUS_CS3_BASE (IXP23XX_EXP_BUS_PHYS + 0x03000000)
+#define IXP23XX_EXP_BUS_CS4_BASE (IXP23XX_EXP_BUS_PHYS + 0x04000000)
+#define IXP23XX_EXP_BUS_CS5_BASE (IXP23XX_EXP_BUS_PHYS + 0x05000000)
+#define IXP23XX_EXP_BUS_CS6_BASE (IXP23XX_EXP_BUS_PHYS + 0x06000000)
+#define IXP23XX_EXP_BUS_CS7_BASE (IXP23XX_EXP_BUS_PHYS + 0x07000000)
+
+
+/****************************************************************************
+ * Peripherals.
+ ****************************************************************************/
+#define IXP23XX_UART1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x0000)
+#define IXP23XX_UART2_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x1000)
+#define IXP23XX_PMU_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x2000)
+#define IXP23XX_INTC_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x3000)
+#define IXP23XX_GPIO_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x4000)
+#define IXP23XX_TIMER_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x5000)
+#define IXP23XX_NPE0_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x6000)
+#define IXP23XX_DSR_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x7000)
+#define IXP23XX_NPE1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x8000)
+#define IXP23XX_ETH0_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x9000)
+#define IXP23XX_ETH1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xA000)
+#define IXP23XX_GIG0_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xB000)
+#define IXP23XX_GIG1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xC000)
+#define IXP23XX_DDRS_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xD000)
+
+#define IXP23XX_UART1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x0000)
+#define IXP23XX_UART2_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x1000)
+#define IXP23XX_PMU_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x2000)
+#define IXP23XX_INTC_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x3000)
+#define IXP23XX_GPIO_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x4000)
+#define IXP23XX_TIMER_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x5000)
+#define IXP23XX_NPE0_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x6000)
+#define IXP23XX_DSR_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x7000)
+#define IXP23XX_NPE1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x8000)
+#define IXP23XX_ETH0_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x9000)
+#define IXP23XX_ETH1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xA000)
+#define IXP23XX_GIG0_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xB000)
+#define IXP23XX_GIG1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xC000)
+#define IXP23XX_DDRS_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xD000)
+
+
+/****************************************************************************
+ * Interrupt controller.
+ ****************************************************************************/
+#define IXP23XX_INTC_REG(x) ((volatile unsigned long *)(IXP23XX_INTC_VIRT + (x)))
+#define IXP23XX_INTR_ST1 IXP23XX_INTC_REG(0x00)
+#define IXP23XX_INTR_ST2 IXP23XX_INTC_REG(0x04)
+#define IXP23XX_INTR_ST3 IXP23XX_INTC_REG(0x08)
+#define IXP23XX_INTR_ST4 IXP23XX_INTC_REG(0x0c)
+#define IXP23XX_INTR_EN1 IXP23XX_INTC_REG(0x10)
+#define IXP23XX_INTR_EN2 IXP23XX_INTC_REG(0x14)
+#define IXP23XX_INTR_EN3 IXP23XX_INTC_REG(0x18)
+#define IXP23XX_INTR_EN4 IXP23XX_INTC_REG(0x1c)
+#define IXP23XX_INTR_SEL1 IXP23XX_INTC_REG(0x20)
+#define IXP23XX_INTR_SEL2 IXP23XX_INTC_REG(0x24)
+#define IXP23XX_INTR_SEL3 IXP23XX_INTC_REG(0x28)
+#define IXP23XX_INTR_SEL4 IXP23XX_INTC_REG(0x2c)
+#define IXP23XX_INTR_IRQ_ST1 IXP23XX_INTC_REG(0x30)
+#define IXP23XX_INTR_IRQ_ST2 IXP23XX_INTC_REG(0x34)
+#define IXP23XX_INTR_IRQ_ST3 IXP23XX_INTC_REG(0x38)
+#define IXP23XX_INTR_IRQ_ST4 IXP23XX_INTC_REG(0x3c)
+#define IXP23XX_INTR_IRQ_ENC_ST_OFFSET 0x54
+
+
+/****************************************************************************
+ * GPIO.
+ ****************************************************************************/
+#define IXP23XX_GPIO_REG(x) ((volatile unsigned long *)(IXP23XX_GPIO_VIRT + (x)))
+#define IXP23XX_GPIO_GPOUTR IXP23XX_GPIO_REG(0x00)
+#define IXP23XX_GPIO_GPOER IXP23XX_GPIO_REG(0x04)
+#define IXP23XX_GPIO_GPINR IXP23XX_GPIO_REG(0x08)
+#define IXP23XX_GPIO_GPISR IXP23XX_GPIO_REG(0x0c)
+#define IXP23XX_GPIO_GPIT1R IXP23XX_GPIO_REG(0x10)
+#define IXP23XX_GPIO_GPIT2R IXP23XX_GPIO_REG(0x14)
+#define IXP23XX_GPIO_GPCLKR IXP23XX_GPIO_REG(0x18)
+#define IXP23XX_GPIO_GPDBSELR IXP23XX_GPIO_REG(0x1c)
+
+#define IXP23XX_GPIO_STYLE_MASK 0x7
+#define IXP23XX_GPIO_STYLE_ACTIVE_HIGH 0x0
+#define IXP23XX_GPIO_STYLE_ACTIVE_LOW 0x1
+#define IXP23XX_GPIO_STYLE_RISING_EDGE 0x2
+#define IXP23XX_GPIO_STYLE_FALLING_EDGE 0x3
+#define IXP23XX_GPIO_STYLE_TRANSITIONAL 0x4
+
+#define IXP23XX_GPIO_STYLE_SIZE 3
+
+
+/****************************************************************************
+ * Timer.
+ ****************************************************************************/
+#define IXP23XX_TIMER_REG(x) ((volatile unsigned long *)(IXP23XX_TIMER_VIRT + (x)))
+#define IXP23XX_TIMER_CONT IXP23XX_TIMER_REG(0x00)
+#define IXP23XX_TIMER1_TIMESTAMP IXP23XX_TIMER_REG(0x04)
+#define IXP23XX_TIMER1_RELOAD IXP23XX_TIMER_REG(0x08)
+#define IXP23XX_TIMER2_TIMESTAMP IXP23XX_TIMER_REG(0x0c)
+#define IXP23XX_TIMER2_RELOAD IXP23XX_TIMER_REG(0x10)
+#define IXP23XX_TIMER_WDOG IXP23XX_TIMER_REG(0x14)
+#define IXP23XX_TIMER_WDOG_EN IXP23XX_TIMER_REG(0x18)
+#define IXP23XX_TIMER_WDOG_KEY IXP23XX_TIMER_REG(0x1c)
+#define IXP23XX_TIMER_WDOG_KEY_MAGIC 0x482e
+#define IXP23XX_TIMER_STATUS IXP23XX_TIMER_REG(0x20)
+#define IXP23XX_TIMER_SOFT_RESET IXP23XX_TIMER_REG(0x24)
+#define IXP23XX_TIMER_SOFT_RESET_EN IXP23XX_TIMER_REG(0x28)
+
+#define IXP23XX_TIMER_ENABLE (1 << 0)
+#define IXP23XX_TIMER_ONE_SHOT (1 << 1)
+/* Low order bits of reload value ignored */
+#define IXP23XX_TIMER_RELOAD_MASK (0x3)
+#define IXP23XX_TIMER_DISABLED (0x0)
+#define IXP23XX_TIMER1_INT_PEND (1 << 0)
+#define IXP23XX_TIMER2_INT_PEND (1 << 1)
+#define IXP23XX_TIMER_STATUS_TS_PEND (1 << 2)
+#define IXP23XX_TIMER_STATUS_WDOG_PEND (1 << 3)
+#define IXP23XX_TIMER_STATUS_WARM_RESET (1 << 4)
+
+
+/****************************************************************************
+ * CAP CSRs.
+ ****************************************************************************/
+#define IXP23XX_GLOBAL_REG(x) ((volatile unsigned long *)(IXP23XX_CAP_CSR_VIRT + 0x4a00 + (x)))
+#define IXP23XX_PROD_IDG IXP23XX_GLOBAL_REG(0x00)
+#define IXP23XX_MISC_CONTROL IXP23XX_GLOBAL_REG(0x04)
+#define IXP23XX_MSF_CLK_CNTRL IXP23XX_GLOBAL_REG(0x08)
+#define IXP23XX_RESET0 IXP23XX_GLOBAL_REG(0x0c)
+#define IXP23XX_RESET1 IXP23XX_GLOBAL_REG(0x10)
+#define IXP23XX_STRAP_OPTIONS IXP23XX_GLOBAL_REG(0x18)
+
+#define IXP23XX_ENABLE_WATCHDOG (1 << 24)
+#define IXP23XX_SHPC_INIT_COMP (1 << 21)
+#define IXP23XX_RST_ALL (1 << 16)
+#define IXP23XX_RESET_PCI (1 << 2)
+#define IXP23XX_PCI_UNIT_RESET (1 << 1)
+#define IXP23XX_XSCALE_RESET (1 << 0)
+
+
+/****************************************************************************
+ * PCI CSRs.
+ ****************************************************************************/
+#define IXP23XX_PCI_CREG(x) ((volatile unsigned long *)(IXP23XX_PCI_CREG_VIRT + (x)))
+#define IXP23XX_PCI_CMDSTAT IXP23XX_PCI_CREG(0x04)
+#define IXP23XX_PCI_SRAM_BAR IXP23XX_PCI_CREG(0x14)
+#define IXP23XX_PCI_SDRAM_BAR IXP23XX_PCI_CREG(0x18)
+
+
+#define IXP23XX_PCI_CSR(x) ((volatile unsigned long *)(IXP23XX_PCI_CREG_VIRT + 0x01000000 + (x)))
+#define IXP23XX_PCI_OUT_INT_STATUS IXP23XX_PCI_CSR(0x0030)
+#define IXP23XX_PCI_OUT_INT_MASK IXP23XX_PCI_CSR(0x0034)
+#define IXP23XX_PCI_SRAM_BASE_ADDR_MASK IXP23XX_PCI_CSR(0x00fc)
+#define IXP23XX_PCI_DRAM_BASE_ADDR_MASK IXP23XX_PCI_CSR(0x0100)
+#define IXP23XX_PCI_CONTROL IXP23XX_PCI_CSR(0x013c)
+#define IXP23XX_PCI_ADDR_EXT IXP23XX_PCI_CSR(0x0140)
+#define IXP23XX_PCI_ME_PUSH_STATUS IXP23XX_PCI_CSR(0x0148)
+#define IXP23XX_PCI_ME_PUSH_EN IXP23XX_PCI_CSR(0x014c)
+#define IXP23XX_PCI_ERR_STATUS IXP23XX_PCI_CSR(0x0150)
+#define IXP23XX_PCI_ERROR_STATUS IXP23XX_PCI_CSR(0x0150)
+#define IXP23XX_PCI_ERR_ENABLE IXP23XX_PCI_CSR(0x0154)
+#define IXP23XX_PCI_XSCALE_INT_STATUS IXP23XX_PCI_CSR(0x0158)
+#define IXP23XX_PCI_XSCALE_INT_ENABLE IXP23XX_PCI_CSR(0x015c)
+#define IXP23XX_PCI_CPP_ADDR_BITS IXP23XX_PCI_CSR(0x0160)
+
+
+#ifndef __ASSEMBLY__
+/*
+ * Is system memory on the XSI or CPP bus?
+ */
+static inline unsigned ixp23xx_cpp_boot(void)
+{
+ return (*IXP23XX_EXP_CFG0 & IXP23XX_EXP_CFG0_XSI_NOT_PRES);
+}
+#endif
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/memory.h b/include/asm-arm/arch-ixp23xx/memory.h
new file mode 100644
index 00000000000..bebcf0aa0d7
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/memory.h
@@ -0,0 +1,46 @@
+/*
+ * include/asm-arm/arch-ixp23xx/memory.h
+ *
+ * Copyright (c) 2003-2004 Intel Corp.
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#include <asm/hardware.h>
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET (0x00000000)
+
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ * address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ * to an address that the kernel can use.
+ */
+#ifndef __ASSEMBLY__
+
+#define __virt_to_bus(v) \
+ ({ unsigned int ret; \
+ ret = ((__virt_to_phys(v) - 0x00000000) + \
+ (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0)); \
+ ret; })
+
+#define __bus_to_virt(b) \
+ ({ unsigned int data; \
+ data = *((volatile int *)IXP23XX_PCI_SDRAM_BAR); \
+ __phys_to_virt((((b - (data & 0xfffffff0)) + 0x00000000))); })
+
+#endif
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/platform.h b/include/asm-arm/arch-ixp23xx/platform.h
new file mode 100644
index 00000000000..f85b4685a49
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/platform.h
@@ -0,0 +1,31 @@
+/*
+ * include/asm-arm/arch-ixp23xx/platform.h
+ *
+ * Various bits of code used by platform-level code.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __ASSEMBLY__
+
+struct pci_sys_data;
+
+void ixp23xx_map_io(void);
+void ixp23xx_init_irq(void);
+void ixp23xx_sys_init(void);
+int ixp23xx_pci_setup(int, struct pci_sys_data *);
+void ixp23xx_pci_preinit(void);
+struct pci_bus *ixp23xx_pci_scan_bus(int, struct pci_sys_data*);
+
+extern struct sys_timer ixp23xx_timer;
+
+#define IXP23XX_UART_XTAL 14745600
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/system.h b/include/asm-arm/arch-ixp23xx/system.h
new file mode 100644
index 00000000000..925e6b0c338
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/system.h
@@ -0,0 +1,33 @@
+/*
+ * include/asm-arm/arch-ixp23xx/system.h
+ *
+ * Copyright (C) 2003 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+static inline void arch_idle(void)
+{
+#if 0
+ if (!hlt_counter)
+ cpu_do_idle();
+#endif
+}
+
+static inline void arch_reset(char mode)
+{
+ /* First try machine specific support */
+ if (machine_is_ixdp2351()) {
+ *IXDP2351_CPLD_RESET1_REG = IXDP2351_CPLD_RESET1_MAGIC;
+ (void) *IXDP2351_CPLD_RESET1_REG;
+ *IXDP2351_CPLD_RESET1_REG = IXDP2351_CPLD_RESET1_ENABLE;
+ }
+
+ /* Use on-chip reset capability */
+ *IXP23XX_RESET0 |= IXP23XX_RST_ALL;
+}
diff --git a/include/asm-arm/arch-ixp23xx/time.h b/include/asm-arm/arch-ixp23xx/time.h
new file mode 100644
index 00000000000..f6828fdd288
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/time.h
@@ -0,0 +1,3 @@
+/*
+ * include/asm-arm/arch-ixp23xx/time.h
+ */
diff --git a/include/asm-arm/arch-ixp23xx/timex.h b/include/asm-arm/arch-ixp23xx/timex.h
new file mode 100644
index 00000000000..516f72fe608
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/timex.h
@@ -0,0 +1,7 @@
+/*
+ * include/asm-arm/arch-ixp23xx/timex.h
+ *
+ * XScale architecture timex specifications
+ */
+
+#define CLOCK_TICK_RATE 75000000
diff --git a/include/asm-arm/arch-ixp23xx/uncompress.h b/include/asm-arm/arch-ixp23xx/uncompress.h
new file mode 100644
index 00000000000..62623fa9b2f
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/uncompress.h
@@ -0,0 +1,45 @@
+/*
+ * include/asm-arm/arch-ixp23xx/uncompress.h
+ *
+ * Copyright (C) 2002-2004 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <asm/hardware.h>
+#include <linux/serial_reg.h>
+
+#define UART_BASE ((volatile u32 *)IXP23XX_UART1_PHYS)
+
+static __inline__ void putc(char c)
+{
+ int j;
+
+ for (j = 0; j < 0x1000; j++) {
+ if (UART_BASE[UART_LSR] & UART_LSR_THRE)
+ break;
+ }
+
+ UART_BASE[UART_TX] = c;
+}
+
+static void putstr(const char *s)
+{
+ while (*s) {
+ putc(*s);
+ if (*s == '\n')
+ putc('\r');
+ s++;
+ }
+}
+
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/vmalloc.h b/include/asm-arm/arch-ixp23xx/vmalloc.h
new file mode 100644
index 00000000000..9f256665854
--- /dev/null
+++ b/include/asm-arm/arch-ixp23xx/vmalloc.h
@@ -0,0 +1,10 @@
+/*
+ * include/asm-arm/arch-ixp23xx/vmalloc.h
+ *
+ * Copyright (c) 2005 MontaVista Software, Inc.
+ *
+ * NPU mappings end at 0xf0000000 and we allocate 64MB for board
+ * specific static I/O.
+ */
+
+#define VMALLOC_END (0xec000000)
diff --git a/include/asm-arm/arch-ixp4xx/uncompress.h b/include/asm-arm/arch-ixp4xx/uncompress.h
index 960c35810a2..09ae6c91be6 100644
--- a/include/asm-arm/arch-ixp4xx/uncompress.h
+++ b/include/asm-arm/arch-ixp4xx/uncompress.h
@@ -21,26 +21,18 @@
static volatile u32* uart_base;
-static __inline__ void putc(char c)
+static inline void putc(int c)
{
/* Check THRE and TEMT bits before we transmit the character.
*/
- while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE);
+ while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
+ barrier();
+
*uart_base = c;
}
-/*
- * This does not append a newline
- */
-static void putstr(const char *s)
+static void flush(void)
{
- while (*s)
- {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
static __inline__ void __arch_decomp_setup(unsigned long arch_id)
diff --git a/include/asm-arm/arch-l7200/uncompress.h b/include/asm-arm/arch-l7200/uncompress.h
index 1caa2b560f5..9fcd40aee3e 100644
--- a/include/asm-arm/arch-l7200/uncompress.h
+++ b/include/asm-arm/arch-l7200/uncompress.h
@@ -16,22 +16,17 @@
#define __raw_writeb(v,p) (*(volatile unsigned char *)(p) = (v))
#define __raw_readb(p) (*(volatile unsigned char *)(p))
-static __inline__ void putc(char c)
+static inline void putc(int c)
{
while(__raw_readb(IO_UART + 0x18) & 0x20 ||
- __raw_readb(IO_UART + 0x18) & 0x08);
+ __raw_readb(IO_UART + 0x18) & 0x08)
+ barrier();
+
__raw_writeb(c, IO_UART + 0x00);
}
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- if (*s == 10) { /* If a LF, add CR */
- putc(10);
- putc(13);
- }
- putc(*(s++));
- }
}
static __inline__ void arch_decomp_setup(void)
diff --git a/include/asm-arm/arch-lh7a40x/uncompress.h b/include/asm-arm/arch-lh7a40x/uncompress.h
index ec8ab67122f..f8053346f60 100644
--- a/include/asm-arm/arch-lh7a40x/uncompress.h
+++ b/include/asm-arm/arch-lh7a40x/uncompress.h
@@ -22,20 +22,15 @@
#define UART_STATUS (*(volatile unsigned long*) (UART2_PHYS + UART_R_STATUS))
#define UART_DATA (*(volatile unsigned long*) (UART2_PHYS + UART_R_DATA))
-static __inline__ void putc (char ch)
+static inline void putc(int ch)
{
while (UART_STATUS & nTxRdy)
- ;
+ barrier();
UART_DATA = ch;
}
-static void putstr (const char* sz)
+static inline void flush(void)
{
- for (; *sz; ++sz) {
- putc (*sz);
- if (*sz == '\n')
- putc ('\r');
- }
}
/* NULL functions; we don't presently need them */
diff --git a/include/asm-arm/arch-omap/uncompress.h b/include/asm-arm/arch-omap/uncompress.h
index c718264affb..ca2c8bec82e 100644
--- a/include/asm-arm/arch-omap/uncompress.h
+++ b/include/asm-arm/arch-omap/uncompress.h
@@ -30,8 +30,7 @@ unsigned int system_rev;
#define check_port(base, shift) ((base[UART_OMAP_MDR1 << shift] & 7) == 0)
#define omap_get_id() ((*(volatile unsigned int *)(0xfffed404)) >> 12) & ID_MASK
-static void
-putstr(const char *s)
+static void putc(int c)
{
volatile u8 * uart = 0;
int shift = 2;
@@ -69,16 +68,13 @@ putstr(const char *s)
/*
* Now, xmit each character
*/
- while (*s) {
- while (!(uart[UART_LSR << shift] & UART_LSR_THRE))
- barrier();
- uart[UART_TX << shift] = *s;
- if (*s++ == '\n') {
- while (!(uart[UART_LSR << shift] & UART_LSR_THRE))
- barrier();
- uart[UART_TX << shift] = '\r';
- }
- }
+ while (!(uart[UART_LSR << shift] & UART_LSR_THRE))
+ barrier();
+ uart[UART_TX << shift] = c;
+}
+
+static inline void flush(void)
+{
}
/*
diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
index 05c4b702759..67af238a8f8 100644
--- a/include/asm-arm/arch-pxa/irqs.h
+++ b/include/asm-arm/arch-pxa/irqs.h
@@ -176,6 +176,7 @@
#elif defined(CONFIG_SHARP_LOCOMO)
#define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1)
#elif defined(CONFIG_ARCH_LUBBOCK) || \
+ defined(CONFIG_MACH_LOGICPD_PXA270) || \
defined(CONFIG_MACH_MAINSTONE)
#define NR_IRQS (IRQ_BOARD_END)
#else
@@ -196,6 +197,11 @@
#define LUBBOCK_USB_DISC_IRQ LUBBOCK_IRQ(6) /* usb disconnect */
#define LUBBOCK_LAST_IRQ LUBBOCK_IRQ(6)
+#define LPD270_IRQ(x) (IRQ_BOARD_START + (x))
+#define LPD270_USBC_IRQ LPD270_IRQ(2)
+#define LPD270_ETHERNET_IRQ LPD270_IRQ(3)
+#define LPD270_AC97_IRQ LPD270_IRQ(4)
+
#define MAINSTONE_IRQ(x) (IRQ_BOARD_START + (x))
#define MAINSTONE_MMC_IRQ MAINSTONE_IRQ(0)
#define MAINSTONE_USIM_IRQ MAINSTONE_IRQ(1)
diff --git a/include/asm-arm/arch-pxa/lpd270.h b/include/asm-arm/arch-pxa/lpd270.h
new file mode 100644
index 00000000000..501d240ac12
--- /dev/null
+++ b/include/asm-arm/arch-pxa/lpd270.h
@@ -0,0 +1,38 @@
+/*
+ * include/asm-arm/arch-pxa/lpd270.h
+ *
+ * Author: Lennert Buytenhek
+ * Created: Feb 10, 2006
+ *
+ * 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_LPD270_H
+#define __ASM_ARCH_LPD270_H
+
+#define LPD270_CPLD_PHYS PXA_CS2_PHYS
+#define LPD270_CPLD_VIRT 0xf0000000
+#define LPD270_CPLD_SIZE 0x00100000
+
+#define LPD270_ETH_PHYS (PXA_CS2_PHYS + 0x01000000)
+
+/* CPLD registers */
+#define LPD270_CPLD_REG(x) ((unsigned long)(LPD270_CPLD_VIRT + (x)))
+#define LPD270_CONTROL LPD270_CPLD_REG(0x00)
+#define LPD270_PERIPHERAL0 LPD270_CPLD_REG(0x04)
+#define LPD270_PERIPHERAL1 LPD270_CPLD_REG(0x08)
+#define LPD270_CPLD_REVISION LPD270_CPLD_REG(0x14)
+#define LPD270_EEPROM_SPI_ITF LPD270_CPLD_REG(0x20)
+#define LPD270_MODE_PINS LPD270_CPLD_REG(0x24)
+#define LPD270_EGPIO LPD270_CPLD_REG(0x30)
+#define LPD270_INT_MASK LPD270_CPLD_REG(0x40)
+#define LPD270_INT_STATUS LPD270_CPLD_REG(0x50)
+
+#define LPD270_INT_AC97 (1 << 4) /* AC'97 CODEC IRQ */
+#define LPD270_INT_ETHERNET (1 << 3) /* Ethernet controller IRQ */
+#define LPD270_INT_USBC (1 << 2) /* USB client cable detection IRQ */
+
+
+#endif
diff --git a/include/asm-arm/arch-pxa/uncompress.h b/include/asm-arm/arch-pxa/uncompress.h
index fe38090444e..178aa2e073a 100644
--- a/include/asm-arm/arch-pxa/uncompress.h
+++ b/include/asm-arm/arch-pxa/uncompress.h
@@ -17,23 +17,18 @@
#define UART FFUART
-static __inline__ void putc(char c)
+static inline void putc(char c)
{
- while (!(UART[5] & 0x20));
+ while (!(UART[5] & 0x20))
+ barrier();
UART[0] = c;
}
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
/*
diff --git a/include/asm-arm/arch-realview/uncompress.h b/include/asm-arm/arch-realview/uncompress.h
index b5e4d360665..f05631d7674 100644
--- a/include/asm-arm/arch-realview/uncompress.h
+++ b/include/asm-arm/arch-realview/uncompress.h
@@ -27,22 +27,16 @@
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static inline void putc(int c)
{
- while (*s) {
- while (AMBA_UART_FR & (1 << 5))
- barrier();
-
- AMBA_UART_DR = *s;
+ while (AMBA_UART_FR & (1 << 5))
+ barrier();
- if (*s == '\n') {
- while (AMBA_UART_FR & (1 << 5))
- barrier();
+ AMBA_UART_DR = c;
+}
- AMBA_UART_DR = '\r';
- }
- s++;
- }
+static inline void flush(void)
+{
while (AMBA_UART_FR & (1 << 3))
barrier();
}
diff --git a/include/asm-arm/arch-rpc/uncompress.h b/include/asm-arm/arch-rpc/uncompress.h
index 43035fec64d..06231ede54e 100644
--- a/include/asm-arm/arch-rpc/uncompress.h
+++ b/include/asm-arm/arch-rpc/uncompress.h
@@ -67,31 +67,28 @@ extern __attribute__((pure)) struct param_struct *params(void);
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static void putc(int c)
{
extern void ll_write_char(char *, char c, char white);
int x,y;
- unsigned char c;
char *ptr;
x = params->video_x;
y = params->video_y;
- while ( ( c = *(unsigned char *)s++ ) != '\0' ) {
- if ( c == '\n' ) {
+ if (c == '\n') {
+ if (++y >= video_num_lines)
+ y--;
+ } else if (c == '\r') {
+ x = 0;
+ } else {
+ ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h);
+ ll_write_char(ptr, c, white);
+ if (++x >= video_num_columns) {
x = 0;
if ( ++y >= video_num_lines ) {
y--;
}
- } else {
- ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h);
- ll_write_char(ptr, c, white);
- if ( ++x >= video_num_columns ) {
- x = 0;
- if ( ++y >= video_num_lines ) {
- y--;
- }
- }
}
}
@@ -99,6 +96,10 @@ static void putstr(const char *s)
params->video_y = y;
}
+static inline void flush(void)
+{
+}
+
static void error(char *x);
/*
diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h
index 4367ec054b5..a6f6a0e44af 100644
--- a/include/asm-arm/arch-s3c2410/uncompress.h
+++ b/include/asm-arm/arch-s3c2410/uncompress.h
@@ -67,8 +67,7 @@ uart_rd(unsigned int reg)
* waiting for tx to happen...
*/
-static void
-putc(char ch)
+static void putc(int ch)
{
int cpuid = S3C2410_GSTATUS1_2410;
@@ -77,9 +76,6 @@ putc(char ch)
cpuid &= S3C2410_GSTATUS1_IDMASK;
#endif
- if (ch == '\n')
- putc('\r'); /* expand newline to \r\n */
-
if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) {
int level;
@@ -101,19 +97,16 @@ putc(char ch)
} else {
/* not using fifos */
- while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE);
+ while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE)
+ barrier();
}
/* write byte to transmission register */
uart_wr(S3C2410_UTXH, ch);
}
-static void
-putstr(const char *ptr)
+static inline void flush(void)
{
- for (; *ptr != '\0'; ptr++) {
- putc(*ptr);
- }
}
#define __raw_writel(d,ad) do { *((volatile unsigned int *)(ad)) = (d); } while(0)
diff --git a/include/asm-arm/arch-sa1100/uncompress.h b/include/asm-arm/arch-sa1100/uncompress.h
index 43453501ee6..2601a77a6dd 100644
--- a/include/asm-arm/arch-sa1100/uncompress.h
+++ b/include/asm-arm/arch-sa1100/uncompress.h
@@ -17,7 +17,7 @@
#define UART(x) (*(volatile unsigned long *)(serial_port + (x)))
-static void putstr( const char *s )
+static void putc(int c)
{
unsigned long serial_port;
@@ -31,19 +31,16 @@ static void putstr( const char *s )
return;
} while (0);
- for (; *s; s++) {
- /* wait for space in the UART's transmitter */
- while (!(UART(UTSR1) & UTSR1_TNF));
+ /* wait for space in the UART's transmitter */
+ while (!(UART(UTSR1) & UTSR1_TNF))
+ barrier();
- /* send the character out. */
- UART(UTDR) = *s;
+ /* send the character out. */
+ UART(UTDR) = c;
+}
- /* if a LF, also do CR... */
- if (*s == 10) {
- while (!(UART(UTSR1) & UTSR1_TNF));
- UART(UTDR) = 13;
- }
- }
+static inline void flush(void)
+{
}
/*
diff --git a/include/asm-arm/arch-shark/uncompress.h b/include/asm-arm/arch-shark/uncompress.h
index 910a8e0a0ca..7eca6534f1b 100644
--- a/include/asm-arm/arch-shark/uncompress.h
+++ b/include/asm-arm/arch-shark/uncompress.h
@@ -9,7 +9,7 @@
#define SERIAL_BASE ((volatile unsigned char *)0x400003f8)
-static __inline__ void putc(char c)
+static inline void putc(int c)
{
int t;
@@ -18,17 +18,8 @@ static __inline__ void putc(char c)
while (t--);
}
-/*
- * This does not append a newline
- */
-static void putstr(const char *s)
+static inline void flush(void)
{
- while (*s) {
- putc(*s);
- if (*s == '\n')
- putc('\r');
- s++;
- }
}
#ifdef DEBUG
diff --git a/include/asm-arm/arch-versatile/uncompress.h b/include/asm-arm/arch-versatile/uncompress.h
index 2f57499c7b9..7215133d051 100644
--- a/include/asm-arm/arch-versatile/uncompress.h
+++ b/include/asm-arm/arch-versatile/uncompress.h
@@ -25,22 +25,16 @@
/*
* This does not append a newline
*/
-static void putstr(const char *s)
+static inline void putc(int c)
{
- while (*s) {
- while (AMBA_UART_FR & (1 << 5))
- barrier();
-
- AMBA_UART_DR = *s;
+ while (AMBA_UART_FR & (1 << 5))
+ barrier();
- if (*s == '\n') {
- while (AMBA_UART_FR & (1 << 5))
- barrier();
+ AMBA_UART_DR = c;
+}
- AMBA_UART_DR = '\r';
- }
- s++;
- }
+static inline void flush(void)
+{
while (AMBA_UART_FR & (1 << 3))
barrier();
}
diff --git a/include/asm-arm/assembler.h b/include/asm-arm/assembler.h
index f31ac92b6c7..d53bafa9bf1 100644
--- a/include/asm-arm/assembler.h
+++ b/include/asm-arm/assembler.h
@@ -80,16 +80,33 @@
instr regs
/*
- * Save the current IRQ state and disable IRQs. Note that this macro
- * assumes FIQs are enabled, and that the processor is in SVC mode.
+ * Enable and disable interrupts
*/
- .macro save_and_disable_irqs, oldcpsr
- mrs \oldcpsr, cpsr
#if __LINUX_ARM_ARCH__ >= 6
+ .macro disable_irq
cpsid i
+ .endm
+
+ .macro enable_irq
+ cpsie i
+ .endm
#else
- msr cpsr_c, #PSR_I_BIT | MODE_SVC
+ .macro disable_irq
+ msr cpsr_c, #PSR_I_BIT | SVC_MODE
+ .endm
+
+ .macro enable_irq
+ msr cpsr_c, #SVC_MODE
+ .endm
#endif
+
+/*
+ * Save the current IRQ state and disable IRQs. Note that this macro
+ * assumes FIQs are enabled, and that the processor is in SVC mode.
+ */
+ .macro save_and_disable_irqs, oldcpsr
+ mrs \oldcpsr, cpsr
+ disable_irq
.endm
/*
diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
index d02de721ecc..0ac54b1a8ba 100644
--- a/include/asm-arm/bitops.h
+++ b/include/asm-arm/bitops.h
@@ -117,65 +117,7 @@ ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
return res & mask;
}
-/*
- * Now the non-atomic variants. We let the compiler handle all
- * optimisations for these. These are all _native_ endian.
- */
-static inline void __set_bit(int nr, volatile unsigned long *p)
-{
- p[nr >> 5] |= (1UL << (nr & 31));
-}
-
-static inline void __clear_bit(int nr, volatile unsigned long *p)
-{
- p[nr >> 5] &= ~(1UL << (nr & 31));
-}
-
-static inline void __change_bit(int nr, volatile unsigned long *p)
-{
- p[nr >> 5] ^= (1UL << (nr & 31));
-}
-
-static inline int __test_and_set_bit(int nr, volatile unsigned long *p)
-{
- unsigned long oldval, mask = 1UL << (nr & 31);
-
- p += nr >> 5;
-
- oldval = *p;
- *p = oldval | mask;
- return oldval & mask;
-}
-
-static inline int __test_and_clear_bit(int nr, volatile unsigned long *p)
-{
- unsigned long oldval, mask = 1UL << (nr & 31);
-
- p += nr >> 5;
-
- oldval = *p;
- *p = oldval & ~mask;
- return oldval & mask;
-}
-
-static inline int __test_and_change_bit(int nr, volatile unsigned long *p)
-{
- unsigned long oldval, mask = 1UL << (nr & 31);
-
- p += nr >> 5;
-
- oldval = *p;
- *p = oldval ^ mask;
- return oldval & mask;
-}
-
-/*
- * This routine doesn't need to be atomic.
- */
-static inline int __test_bit(int nr, const volatile unsigned long * p)
-{
- return (p[nr >> 5] >> (nr & 31)) & 1UL;
-}
+#include <asm-generic/bitops/non-atomic.h>
/*
* A note about Endian-ness.
@@ -261,7 +203,6 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
#define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
#define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
#define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
-#define test_bit(nr,p) __test_bit(nr,p)
#define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off)
#define find_first_bit(p,sz) _find_first_bit_le(p,sz)
@@ -280,7 +221,6 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
#define test_and_set_bit(nr,p) ATOMIC_BITOP_BE(test_and_set_bit,nr,p)
#define test_and_clear_bit(nr,p) ATOMIC_BITOP_BE(test_and_clear_bit,nr,p)
#define test_and_change_bit(nr,p) ATOMIC_BITOP_BE(test_and_change_bit,nr,p)
-#define test_bit(nr,p) __test_bit(nr,p)
#define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz)
#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off)
#define find_first_bit(p,sz) _find_first_bit_be(p,sz)
@@ -292,57 +232,41 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
#if __LINUX_ARM_ARCH__ < 5
-/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- */
-static inline unsigned long ffz(unsigned long word)
-{
- int k;
-
- word = ~word;
- k = 31;
- if (word & 0x0000ffff) { k -= 16; word <<= 16; }
- if (word & 0x00ff0000) { k -= 8; word <<= 8; }
- if (word & 0x0f000000) { k -= 4; word <<= 4; }
- if (word & 0x30000000) { k -= 2; word <<= 2; }
- if (word & 0x40000000) { k -= 1; }
- return k;
-}
-
-/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- */
-static inline unsigned long __ffs(unsigned long word)
-{
- int k;
-
- k = 31;
- if (word & 0x0000ffff) { k -= 16; word <<= 16; }
- if (word & 0x00ff0000) { k -= 8; word <<= 8; }
- if (word & 0x0f000000) { k -= 4; word <<= 4; }
- if (word & 0x30000000) { k -= 2; word <<= 2; }
- if (word & 0x40000000) { k -= 1; }
- return k;
-}
-
-/*
- * fls: find last bit set.
- */
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/ffs.h>
-#define fls(x) generic_fls(x)
-#define fls64(x) generic_fls64(x)
-
-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
+#else
-#define ffs(x) generic_ffs(x)
+static inline int constant_fls(int x)
+{
+ int r = 32;
-#else
+ if (!x)
+ return 0;
+ if (!(x & 0xffff0000u)) {
+ x <<= 16;
+ r -= 16;
+ }
+ if (!(x & 0xff000000u)) {
+ x <<= 8;
+ r -= 8;
+ }
+ if (!(x & 0xf0000000u)) {
+ x <<= 4;
+ r -= 4;
+ }
+ if (!(x & 0xc0000000u)) {
+ x <<= 2;
+ r -= 2;
+ }
+ if (!(x & 0x80000000u)) {
+ x <<= 1;
+ r -= 1;
+ }
+ return r;
+}
/*
* On ARMv5 and above those functions can be implemented around
@@ -350,39 +274,18 @@ static inline unsigned long __ffs(unsigned long word)
*/
#define fls(x) \
- ( __builtin_constant_p(x) ? generic_fls(x) : \
+ ( __builtin_constant_p(x) ? constant_fls(x) : \
({ int __r; asm("clz\t%0, %1" : "=r"(__r) : "r"(x) : "cc"); 32-__r; }) )
-#define fls64(x) generic_fls64(x)
#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
#define __ffs(x) (ffs(x) - 1)
#define ffz(x) __ffs( ~(x) )
#endif
-/*
- * Find first bit set in a 168-bit bitmap, where the first
- * 128 bits are unlikely to be set.
- */
-static inline int sched_find_first_bit(const unsigned long *b)
-{
- unsigned long v;
- unsigned int off;
-
- for (off = 0; v = b[off], off < 4; off++) {
- if (unlikely(v))
- break;
- }
- return __ffs(v) + off * 32;
-}
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
+#include <asm-generic/bitops/fls64.h>
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
/*
* Ext2 is defined to use little-endian byte ordering.
@@ -397,7 +300,7 @@ static inline int sched_find_first_bit(const unsigned long *b)
#define ext2_clear_bit_atomic(lock,nr,p) \
test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
#define ext2_test_bit(nr,p) \
- __test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
#define ext2_find_first_zero_bit(p,sz) \
_find_first_zero_bit_le(p,sz)
#define ext2_find_next_zero_bit(p,sz,off) \
@@ -410,7 +313,7 @@ static inline int sched_find_first_bit(const unsigned long *b)
#define minix_set_bit(nr,p) \
__set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
#define minix_test_bit(nr,p) \
- __test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
#define minix_test_and_set_bit(nr,p) \
__test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
#define minix_test_and_clear_bit(nr,p) \
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 09e19a783a5..746be56b1b7 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -71,6 +71,14 @@
# endif
#endif
+#if defined(CONFIG_CPU_XSC3)
+# ifdef _CACHE
+# define MULTI_CACHE 1
+# else
+# define _CACHE xsc3
+# endif
+#endif
+
#if defined(CONFIG_CPU_V6)
//# ifdef _CACHE
# define MULTI_CACHE 1
diff --git a/include/asm-arm/domain.h b/include/asm-arm/domain.h
index da1d960387d..f8ea2de4848 100644
--- a/include/asm-arm/domain.h
+++ b/include/asm-arm/domain.h
@@ -16,11 +16,29 @@
* DOMAIN_IO - domain 2 includes all IO only
* DOMAIN_USER - domain 1 includes all user memory only
* DOMAIN_KERNEL - domain 0 includes all kernel memory only
+ *
+ * The domain numbering depends on whether we support 36 physical
+ * address for I/O or not. Addresses above the 32 bit boundary can
+ * only be mapped using supersections and supersections can only
+ * be set for domain 0. We could just default to DOMAIN_IO as zero,
+ * but there may be systems with supersection support and no 36-bit
+ * addressing. In such cases, we want to map system memory with
+ * supersections to reduce TLB misses and footprint.
+ *
+ * 36-bit addressing and supersections are only available on
+ * CPUs based on ARMv6+ or the Intel XSC3 core.
*/
+#ifndef CONFIG_IO_36
#define DOMAIN_KERNEL 0
#define DOMAIN_TABLE 0
#define DOMAIN_USER 1
#define DOMAIN_IO 2
+#else
+#define DOMAIN_KERNEL 2
+#define DOMAIN_TABLE 2
+#define DOMAIN_USER 1
+#define DOMAIN_IO 0
+#endif
/*
* Domain types
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index b4e1146ab68..afa5c3ea077 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -172,9 +172,7 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
* virt_addr_valid(k) indicates whether a virtual address is valid
*/
#ifndef CONFIG_DISCONTIGMEM
-
-#define page_to_pfn(page) (((page) - mem_map) + PHYS_PFN_OFFSET)
-#define pfn_to_page(pfn) ((mem_map + (pfn)) - PHYS_PFN_OFFSET)
+#define ARCH_PFN_OFFSET (PHYS_PFN_OFFSET)
#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
#define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
@@ -189,13 +187,8 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
* around in memory.
*/
#include <linux/numa.h>
-
-#define page_to_pfn(page) \
- (( (page) - page_zone(page)->zone_mem_map) \
- + page_zone(page)->zone_start_pfn)
-
-#define pfn_to_page(pfn) \
- (PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT))
+#define arch_pfn_to_nid(pfn) (PFN_TO_NID(pfn))
+#define arch_local_page_offset(pfn, nid) (LOCAL_MAP_NR((pfn) << PAGE_OFFSET))
#define pfn_valid(pfn) \
({ \
@@ -243,4 +236,6 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
#endif
+#include <asm-generic/memory_model.h>
+
#endif
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h
index 416320d9541..a404d2bf0c6 100644
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -40,6 +40,7 @@
* v4wb - ARMv4 with writeback cache, without minicache
* v4_mc - ARMv4 with minicache
* xscale - Xscale
+ * xsc3 - XScalev3
*/
#undef _USER
#undef MULTI_USER
@@ -84,6 +85,14 @@
# endif
#endif
+#ifdef CONFIG_CPU_XSC3
+# ifdef _USER
+# define MULTI_USER 1
+# else
+# define _USER xsc3_mc
+# endif
+#endif
+
#ifdef CONFIG_CPU_COPY_V6
# define MULTI_USER 1
#endif
diff --git a/include/asm-arm/pgalloc.h b/include/asm-arm/pgalloc.h
index bc18ff40518..c4ac2e67768 100644
--- a/include/asm-arm/pgalloc.h
+++ b/include/asm-arm/pgalloc.h
@@ -10,10 +10,15 @@
#ifndef _ASMARM_PGALLOC_H
#define _ASMARM_PGALLOC_H
+#include <asm/domain.h>
+#include <asm/pgtable-hwdef.h>
#include <asm/processor.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
+#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER))
+#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL))
+
/*
* Since we have only two-level page tables, these are trivial
*/
diff --git a/include/asm-arm/pgtable-hwdef.h b/include/asm-arm/pgtable-hwdef.h
new file mode 100644
index 00000000000..1d033495cc7
--- /dev/null
+++ b/include/asm-arm/pgtable-hwdef.h
@@ -0,0 +1,88 @@
+/*
+ * linux/include/asm-arm/pgtable-hwdef.h
+ *
+ * Copyright (C) 1995-2002 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _ASMARM_PGTABLE_HWDEF_H
+#define _ASMARM_PGTABLE_HWDEF_H
+
+/*
+ * Hardware page table definitions.
+ *
+ * + Level 1 descriptor (PMD)
+ * - common
+ */
+#define PMD_TYPE_MASK (3 << 0)
+#define PMD_TYPE_FAULT (0 << 0)
+#define PMD_TYPE_TABLE (1 << 0)
+#define PMD_TYPE_SECT (2 << 0)
+#define PMD_BIT4 (1 << 4)
+#define PMD_DOMAIN(x) ((x) << 5)
+#define PMD_PROTECTION (1 << 9) /* v5 */
+/*
+ * - section
+ */
+#define PMD_SECT_BUFFERABLE (1 << 2)
+#define PMD_SECT_CACHEABLE (1 << 3)
+#define PMD_SECT_AP_WRITE (1 << 10)
+#define PMD_SECT_AP_READ (1 << 11)
+#define PMD_SECT_TEX(x) ((x) << 12) /* v5 */
+#define PMD_SECT_APX (1 << 15) /* v6 */
+#define PMD_SECT_S (1 << 16) /* v6 */
+#define PMD_SECT_nG (1 << 17) /* v6 */
+#define PMD_SECT_SUPER (1 << 18) /* v6 */
+
+#define PMD_SECT_UNCACHED (0)
+#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE)
+#define PMD_SECT_WT (PMD_SECT_CACHEABLE)
+#define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
+#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE)
+#define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
+#define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2))
+
+/*
+ * - coarse table (not used)
+ */
+
+/*
+ * + Level 2 descriptor (PTE)
+ * - common
+ */
+#define PTE_TYPE_MASK (3 << 0)
+#define PTE_TYPE_FAULT (0 << 0)
+#define PTE_TYPE_LARGE (1 << 0)
+#define PTE_TYPE_SMALL (2 << 0)
+#define PTE_TYPE_EXT (3 << 0) /* v5 */
+#define PTE_BUFFERABLE (1 << 2)
+#define PTE_CACHEABLE (1 << 3)
+
+/*
+ * - extended small page/tiny page
+ */
+#define PTE_EXT_XN (1 << 0) /* v6 */
+#define PTE_EXT_AP_MASK (3 << 4)
+#define PTE_EXT_AP0 (1 << 4)
+#define PTE_EXT_AP1 (2 << 4)
+#define PTE_EXT_AP_UNO_SRO (0 << 4)
+#define PTE_EXT_AP_UNO_SRW (PTE_EXT_AP0)
+#define PTE_EXT_AP_URO_SRW (PTE_EXT_AP1)
+#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0)
+#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */
+#define PTE_EXT_APX (1 << 9) /* v6 */
+#define PTE_EXT_SHARED (1 << 10) /* v6 */
+#define PTE_EXT_NG (1 << 11) /* v6 */
+
+/*
+ * - small page
+ */
+#define PTE_SMALL_AP_MASK (0xff << 4)
+#define PTE_SMALL_AP_UNO_SRO (0x00 << 4)
+#define PTE_SMALL_AP_UNO_SRW (0x55 << 4)
+#define PTE_SMALL_AP_URO_SRW (0xaa << 4)
+#define PTE_SMALL_AP_URW_SRW (0xff << 4)
+
+#endif
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 70e00d08345..e595ae24efe 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -137,81 +137,6 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#define SUPERSECTION_MASK (~(SUPERSECTION_SIZE-1))
/*
- * Hardware page table definitions.
- *
- * + Level 1 descriptor (PMD)
- * - common
- */
-#define PMD_TYPE_MASK (3 << 0)
-#define PMD_TYPE_FAULT (0 << 0)
-#define PMD_TYPE_TABLE (1 << 0)
-#define PMD_TYPE_SECT (2 << 0)
-#define PMD_BIT4 (1 << 4)
-#define PMD_DOMAIN(x) ((x) << 5)
-#define PMD_PROTECTION (1 << 9) /* v5 */
-/*
- * - section
- */
-#define PMD_SECT_BUFFERABLE (1 << 2)
-#define PMD_SECT_CACHEABLE (1 << 3)
-#define PMD_SECT_AP_WRITE (1 << 10)
-#define PMD_SECT_AP_READ (1 << 11)
-#define PMD_SECT_TEX(x) ((x) << 12) /* v5 */
-#define PMD_SECT_APX (1 << 15) /* v6 */
-#define PMD_SECT_S (1 << 16) /* v6 */
-#define PMD_SECT_nG (1 << 17) /* v6 */
-#define PMD_SECT_SUPER (1 << 18) /* v6 */
-
-#define PMD_SECT_UNCACHED (0)
-#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE)
-#define PMD_SECT_WT (PMD_SECT_CACHEABLE)
-#define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
-#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE)
-#define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE)
-#define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2))
-
-/*
- * - coarse table (not used)
- */
-
-/*
- * + Level 2 descriptor (PTE)
- * - common
- */
-#define PTE_TYPE_MASK (3 << 0)
-#define PTE_TYPE_FAULT (0 << 0)
-#define PTE_TYPE_LARGE (1 << 0)
-#define PTE_TYPE_SMALL (2 << 0)
-#define PTE_TYPE_EXT (3 << 0) /* v5 */
-#define PTE_BUFFERABLE (1 << 2)
-#define PTE_CACHEABLE (1 << 3)
-
-/*
- * - extended small page/tiny page
- */
-#define PTE_EXT_XN (1 << 0) /* v6 */
-#define PTE_EXT_AP_MASK (3 << 4)
-#define PTE_EXT_AP0 (1 << 4)
-#define PTE_EXT_AP1 (2 << 4)
-#define PTE_EXT_AP_UNO_SRO (0 << 4)
-#define PTE_EXT_AP_UNO_SRW (PTE_EXT_AP0)
-#define PTE_EXT_AP_URO_SRW (PTE_EXT_AP1)
-#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0)
-#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */
-#define PTE_EXT_APX (1 << 9) /* v6 */
-#define PTE_EXT_SHARED (1 << 10) /* v6 */
-#define PTE_EXT_NG (1 << 11) /* v6 */
-
-/*
- * - small page
- */
-#define PTE_SMALL_AP_MASK (0xff << 4)
-#define PTE_SMALL_AP_UNO_SRO (0x00 << 4)
-#define PTE_SMALL_AP_UNO_SRW (0x55 << 4)
-#define PTE_SMALL_AP_URO_SRW (0xaa << 4)
-#define PTE_SMALL_AP_URW_SRW (0xff << 4)
-
-/*
* "Linux" PTE definitions.
*
* We keep two sets of PTEs - the hardware and the linux version.
@@ -236,11 +161,6 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#ifndef __ASSEMBLY__
-#include <asm/domain.h>
-
-#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER))
-#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL))
-
/*
* The following macros handle the cache and bufferable bits...
*/
diff --git a/include/asm-arm/poll.h b/include/asm-arm/poll.h
index 2744ca831f5..5030b2b232a 100644
--- a/include/asm-arm/poll.h
+++ b/include/asm-arm/poll.h
@@ -16,6 +16,7 @@
#define POLLWRBAND 0x0200
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h
index 7bef2bf6be5..106045edb86 100644
--- a/include/asm-arm/proc-fns.h
+++ b/include/asm-arm/proc-fns.h
@@ -138,6 +138,14 @@
# define CPU_NAME cpu_xscale
# endif
# endif
+# ifdef CONFIG_CPU_XSC3
+# ifdef CPU_NAME
+# undef MULTI_CPU
+# define MULTI_CPU
+# else
+# define CPU_NAME cpu_xsc3
+# endif
+# endif
# ifdef CONFIG_CPU_V6
# ifdef CPU_NAME
# undef MULTI_CPU
diff --git a/include/asm-arm/rtc.h b/include/asm-arm/rtc.h
index 370dfe77589..1a5c9232a91 100644
--- a/include/asm-arm/rtc.h
+++ b/include/asm-arm/rtc.h
@@ -25,9 +25,6 @@ struct rtc_ops {
int (*proc)(char *buf);
};
-void rtc_time_to_tm(unsigned long, struct rtc_time *);
-int rtc_tm_to_time(struct rtc_time *, unsigned long *);
-int rtc_valid_tm(struct rtc_time *);
void rtc_next_alarm_time(struct rtc_time *, struct rtc_time *, struct rtc_time *);
void rtc_update(unsigned long, unsigned long);
int register_rtc(struct rtc_ops *);
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index ec91d1ff032..95b3abf4851 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -108,6 +108,25 @@ extern void __show_regs(struct pt_regs *);
extern int cpu_architecture(void);
extern void cpu_init(void);
+/*
+ * Intel's XScale3 core supports some v6 features (supersections, L2)
+ * but advertises itself as v5 as it does not support the v6 ISA. For
+ * this reason, we need a way to explicitly test for this type of CPU.
+ */
+#ifndef CONFIG_CPU_XSC3
+#define cpu_is_xsc3() 0
+#else
+static inline int cpu_is_xsc3(void)
+{
+ extern unsigned int processor_id;
+
+ if ((processor_id & 0xffffe000) == 0x69056000)
+ return 1;
+
+ return 0;
+}
+#endif
+
#define set_cr(x) \
__asm__ __volatile__( \
"mcr p15, 0, %0, c1, c0, 0 @ set CR" \
diff --git a/include/asm-arm/tlb.h b/include/asm-arm/tlb.h
index f49bfb78c22..cb740025d41 100644
--- a/include/asm-arm/tlb.h
+++ b/include/asm-arm/tlb.h
@@ -19,6 +19,14 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
+
+#ifndef CONFIG_MMU
+
+#include <linux/pagemap.h>
+#include <asm-generic/tlb.h>
+
+#else /* !CONFIG_MMU */
+
#include <asm/pgalloc.h>
/*
@@ -82,4 +90,5 @@ tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
#define tlb_migrate_finish(mm) do { } while (0)
+#endif /* CONFIG_MMU */
#endif
diff --git a/include/asm-arm/tlbflush.h b/include/asm-arm/tlbflush.h
index 0c2acc944a0..728992451dd 100644
--- a/include/asm-arm/tlbflush.h
+++ b/include/asm-arm/tlbflush.h
@@ -11,6 +11,13 @@
#define _ASMARM_TLBFLUSH_H
#include <linux/config.h>
+
+#ifndef CONFIG_MMU
+
+#define tlb_flush(tlb) ((void) tlb)
+
+#else /* CONFIG_MMU */
+
#include <asm/glue.h>
#define TLB_V3_PAGE (1 << 0)
@@ -423,4 +430,6 @@ extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte
#endif
+#endif /* CONFIG_MMU */
+
#endif
diff --git a/include/asm-arm26/bitops.h b/include/asm-arm26/bitops.h
index d87f8634e62..19a69573a65 100644
--- a/include/asm-arm26/bitops.h
+++ b/include/asm-arm26/bitops.h
@@ -117,65 +117,7 @@ ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
return res & mask;
}
-/*
- * Now the non-atomic variants. We let the compiler handle all
- * optimisations for these. These are all _native_ endian.
- */
-static inline void __set_bit(int nr, volatile unsigned long *p)
-{
- p[nr >> 5] |= (1UL << (nr & 31));
-}
-
-static inline void __clear_bit(int nr, volatile unsigned long *p)
-{
- p[nr >> 5] &= ~(1UL << (nr & 31));
-}
-
-static inline void __change_bit(int nr, volatile unsigned long *p)
-{
- p[nr >> 5] ^= (1UL << (nr & 31));
-}
-
-static inline int __test_and_set_bit(int nr, volatile unsigned long *p)
-{
- unsigned long oldval, mask = 1UL << (nr & 31);
-
- p += nr >> 5;
-
- oldval = *p;
- *p = oldval | mask;
- return oldval & mask;
-}
-
-static inline int __test_and_clear_bit(int nr, volatile unsigned long *p)
-{
- unsigned long oldval, mask = 1UL << (nr & 31);
-
- p += nr >> 5;
-
- oldval = *p;
- *p = oldval & ~mask;
- return oldval & mask;
-}
-
-static inline int __test_and_change_bit(int nr, volatile unsigned long *p)
-{
- unsigned long oldval, mask = 1UL << (nr & 31);
-
- p += nr >> 5;
-
- oldval = *p;
- *p = oldval ^ mask;
- return oldval & mask;
-}
-
-/*
- * This routine doesn't need to be atomic.
- */
-static inline int __test_bit(int nr, const volatile unsigned long * p)
-{
- return (p[nr >> 5] >> (nr & 31)) & 1UL;
-}
+#include <asm-generic/bitops/non-atomic.h>
/*
* Little endian assembly bitops. nr = 0 -> byte 0 bit 0.
@@ -211,7 +153,6 @@ extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
#define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
#define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
#define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
-#define test_bit(nr,p) __test_bit(nr,p)
#define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz)
#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off)
#define find_first_bit(p,sz) _find_first_bit_le(p,sz)
@@ -219,80 +160,13 @@ extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
#define WORD_BITOFF_TO_LE(x) ((x))
-/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- */
-static inline unsigned long ffz(unsigned long word)
-{
- int k;
-
- word = ~word;
- k = 31;
- if (word & 0x0000ffff) { k -= 16; word <<= 16; }
- if (word & 0x00ff0000) { k -= 8; word <<= 8; }
- if (word & 0x0f000000) { k -= 4; word <<= 4; }
- if (word & 0x30000000) { k -= 2; word <<= 2; }
- if (word & 0x40000000) { k -= 1; }
- return k;
-}
-
-/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- */
-static inline unsigned long __ffs(unsigned long word)
-{
- int k;
-
- k = 31;
- if (word & 0x0000ffff) { k -= 16; word <<= 16; }
- if (word & 0x00ff0000) { k -= 8; word <<= 8; }
- if (word & 0x0f000000) { k -= 4; word <<= 4; }
- if (word & 0x30000000) { k -= 2; word <<= 2; }
- if (word & 0x40000000) { k -= 1; }
- return k;
-}
-
-/*
- * fls: find last bit set.
- */
-
-#define fls(x) generic_fls(x)
-#define fls64(x) generic_fls64(x)
-
-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-
-#define ffs(x) generic_ffs(x)
-
-/*
- * Find first bit set in a 168-bit bitmap, where the first
- * 128 bits are unlikely to be set.
- */
-static inline int sched_find_first_bit(unsigned long *b)
-{
- unsigned long v;
- unsigned int off;
-
- for (off = 0; v = b[off], off < 4; off++) {
- if (unlikely(v))
- break;
- }
- return __ffs(v) + off * 32;
-}
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
/*
* Ext2 is defined to use little-endian byte ordering.
@@ -307,7 +181,7 @@ static inline int sched_find_first_bit(unsigned long *b)
#define ext2_clear_bit_atomic(lock,nr,p) \
test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
#define ext2_test_bit(nr,p) \
- __test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
#define ext2_find_first_zero_bit(p,sz) \
_find_first_zero_bit_le(p,sz)
#define ext2_find_next_zero_bit(p,sz,off) \
@@ -320,7 +194,7 @@ static inline int sched_find_first_bit(unsigned long *b)
#define minix_set_bit(nr,p) \
__set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
#define minix_test_bit(nr,p) \
- __test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
+ test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
#define minix_test_and_set_bit(nr,p) \
__test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
#define minix_test_and_clear_bit(nr,p) \
diff --git a/include/asm-arm26/memory.h b/include/asm-arm26/memory.h
index 20d78616f65..a65f10b80df 100644
--- a/include/asm-arm26/memory.h
+++ b/include/asm-arm26/memory.h
@@ -81,8 +81,7 @@ static inline void *phys_to_virt(unsigned long x)
* virt_to_page(k) convert a _valid_ virtual address to struct page *
* virt_addr_valid(k) indicates whether a virtual address is valid
*/
-#define page_to_pfn(page) (((page) - mem_map) + PHYS_PFN_OFFSET)
-#define pfn_to_page(pfn) ((mem_map + (pfn)) - PHYS_PFN_OFFSET)
+#define ARCH_PFN_OFFSET (PHYS_PFN_OFFSET)
#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
#define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
@@ -98,4 +97,5 @@ static inline void *phys_to_virt(unsigned long x)
*/
#define page_to_bus(page) (page_address(page))
+#include <asm-generic/memory_model.h>
#endif
diff --git a/include/asm-arm26/poll.h b/include/asm-arm26/poll.h
index fdfdab064a6..9ccb7f4190c 100644
--- a/include/asm-arm26/poll.h
+++ b/include/asm-arm26/poll.h
@@ -15,6 +15,7 @@
#define POLLWRNORM 0x0100
#define POLLWRBAND 0x0200
#define POLLMSG 0x0400
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-cris/bitops.h b/include/asm-cris/bitops.h
index b7fef1572dc..a569065113d 100644
--- a/include/asm-cris/bitops.h
+++ b/include/asm-cris/bitops.h
@@ -39,8 +39,6 @@ struct __dummy { unsigned long a[100]; };
#define set_bit(nr, addr) (void)test_and_set_bit(nr, addr)
-#define __set_bit(nr, addr) (void)__test_and_set_bit(nr, addr)
-
/*
* clear_bit - Clears a bit in memory
* @nr: Bit to clear
@@ -54,8 +52,6 @@ struct __dummy { unsigned long a[100]; };
#define clear_bit(nr, addr) (void)test_and_clear_bit(nr, addr)
-#define __clear_bit(nr, addr) (void)__test_and_clear_bit(nr, addr)
-
/*
* change_bit - Toggle a bit in memory
* @nr: Bit to change
@@ -68,18 +64,6 @@ struct __dummy { unsigned long a[100]; };
#define change_bit(nr, addr) (void)test_and_change_bit(nr, addr)
-/*
- * __change_bit - Toggle a bit in memory
- * @nr: the bit to change
- * @addr: the address to start counting from
- *
- * Unlike change_bit(), this function is non-atomic and may be reordered.
- * If it's called on the same region of memory simultaneously, the effect
- * may be that only one operation succeeds.
- */
-
-#define __change_bit(nr, addr) (void)__test_and_change_bit(nr, addr)
-
/**
* test_and_set_bit - Set a bit and return its old value
* @nr: Bit to set
@@ -101,19 +85,6 @@ static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
retval = (mask & *adr) != 0;
*adr |= mask;
cris_atomic_restore(addr, flags);
- local_irq_restore(flags);
- return retval;
-}
-
-static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
-{
- unsigned int mask, retval;
- unsigned int *adr = (unsigned int *)addr;
-
- adr += nr >> 5;
- mask = 1 << (nr & 0x1f);
- retval = (mask & *adr) != 0;
- *adr |= mask;
return retval;
}
@@ -148,27 +119,6 @@ static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
}
/**
- * __test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to clear
- * @addr: Address to count from
- *
- * This operation is non-atomic and can be reordered.
- * If two examples of this operation race, one can appear to succeed
- * but actually fail. You must protect multiple accesses with a lock.
- */
-
-static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
-{
- unsigned int mask, retval;
- unsigned int *adr = (unsigned int *)addr;
-
- adr += nr >> 5;
- mask = 1 << (nr & 0x1f);
- retval = (mask & *adr) != 0;
- *adr &= ~mask;
- return retval;
-}
-/**
* test_and_change_bit - Change a bit and return its old value
* @nr: Bit to change
* @addr: Address to count from
@@ -191,42 +141,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
return retval;
}
-/* WARNING: non atomic and it can be reordered! */
-
-static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
-{
- unsigned int mask, retval;
- unsigned int *adr = (unsigned int *)addr;
-
- adr += nr >> 5;
- mask = 1 << (nr & 0x1f);
- retval = (mask & *adr) != 0;
- *adr ^= mask;
-
- return retval;
-}
-
-/**
- * test_bit - Determine whether a bit is set
- * @nr: bit number to test
- * @addr: Address to start counting from
- *
- * This routine doesn't need to be atomic.
- */
-
-static inline int test_bit(int nr, const volatile unsigned long *addr)
-{
- unsigned int mask;
- unsigned int *adr = (unsigned int *)addr;
-
- adr += nr >> 5;
- mask = 1 << (nr & 0x1f);
- return ((mask & *adr) != 0);
-}
-
-/*
- * Find-bit routines..
- */
+#include <asm-generic/bitops/non-atomic.h>
/*
* Since we define it "external", it collides with the built-in
@@ -235,152 +150,18 @@ static inline int test_bit(int nr, const volatile unsigned long *addr)
*/
#define ffs kernel_ffs
-/*
- * fls: find last bit set.
- */
-
-#define fls(x) generic_fls(x)
-#define fls64(x) generic_fls64(x)
-
-/*
- * hweightN - returns the hamming weight of a N-bit word
- * @x: the word to weigh
- *
- * The Hamming Weight of a number is the total number of bits set in it.
- */
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/find.h>
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/ext2-non-atomic.h>
-/**
- * find_next_zero_bit - find the first zero bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-static inline int find_next_zero_bit (const unsigned long * addr, int size, int offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (32-offset);
- if (size < 32)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size & ~31UL) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
- found_first:
- tmp |= ~0UL << size;
- found_middle:
- return result + ffz(tmp);
-}
-
-/**
- * find_next_bit - find the first set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-static __inline__ int find_next_bit(const unsigned long *addr, int size, int offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *(p++);
- tmp &= (~0UL << offset);
- if (size < 32)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size & ~31UL) {
- if ((tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp &= (~0UL >> (32 - size));
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
-found_middle:
- return result + __ffs(tmp);
-}
-
-/**
- * find_first_zero_bit - find the first zero bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first zero bit, not the number of the byte
- * containing a bit.
- */
-
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
-#define find_first_bit(addr, size) \
- find_next_bit((addr), (size), 0)
-
-#define ext2_set_bit test_and_set_bit
#define ext2_set_bit_atomic(l,n,a) test_and_set_bit(n,a)
-#define ext2_clear_bit test_and_clear_bit
#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
-#define ext2_test_bit test_bit
-#define ext2_find_first_zero_bit find_first_zero_bit
-#define ext2_find_next_zero_bit find_next_zero_bit
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_set_bit(nr,addr) test_and_set_bit(nr,addr)
-#define minix_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
-static inline int sched_find_first_bit(const unsigned long *b)
-{
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (unlikely(b[3]))
- return __ffs(b[3]) + 96;
- if (b[4])
- return __ffs(b[4]) + 128;
- return __ffs(b[5]) + 32 + 128;
-}
+#include <asm-generic/bitops/minix.h>
+#include <asm-generic/bitops/sched.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h
index c99c478c482..3787633e620 100644
--- a/include/asm-cris/page.h
+++ b/include/asm-cris/page.h
@@ -43,8 +43,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
/* On CRIS the PFN numbers doesn't start at 0 so we have to compensate */
/* for that before indexing into the page table starting at mem_map */
-#define pfn_to_page(pfn) (mem_map + ((pfn) - (PAGE_OFFSET >> PAGE_SHIFT)))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + (PAGE_OFFSET >> PAGE_SHIFT))
+#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
#define pfn_valid(pfn) (((pfn) - (PAGE_OFFSET >> PAGE_SHIFT)) < max_mapnr)
/* to index into the page map. our pages all start at physical addr PAGE_OFFSET so
@@ -77,6 +76,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _CRIS_PAGE_H */
diff --git a/include/asm-cris/poll.h b/include/asm-cris/poll.h
index 1c0efc3e4be..1b25d4cf498 100644
--- a/include/asm-cris/poll.h
+++ b/include/asm-cris/poll.h
@@ -15,6 +15,7 @@
#define POLLWRBAND 512
#define POLLMSG 1024
#define POLLREMOVE 4096
+#define POLLRDHUP 8192
struct pollfd {
int fd;
diff --git a/include/asm-frv/bitops.h b/include/asm-frv/bitops.h
index f686b519878..6344d06390b 100644
--- a/include/asm-frv/bitops.h
+++ b/include/asm-frv/bitops.h
@@ -22,20 +22,7 @@
#ifdef __KERNEL__
-/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- */
-static inline unsigned long ffz(unsigned long word)
-{
- unsigned long result = 0;
-
- while (word & 1) {
- result++;
- word >>= 1;
- }
- return result;
-}
+#include <asm-generic/bitops/ffz.h>
/*
* clear_bit() doesn't provide any barrier for the compiler.
@@ -171,51 +158,9 @@ static inline int __test_bit(int nr, const volatile void * addr)
__constant_test_bit((nr),(addr)) : \
__test_bit((nr),(addr)))
-extern int find_next_bit(const unsigned long *addr, int size, int offset);
-
-#define find_first_bit(addr, size) find_next_bit(addr, size, 0)
-
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
-
-static inline int find_next_zero_bit(const void *addr, int size, int offset)
-{
- const unsigned long *p = ((const unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (32-offset);
- if (size < 32)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size & ~31UL) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp |= ~0UL << size;
-found_middle:
- return result + ffz(tmp);
-}
-
-#define ffs(x) generic_ffs(x)
-#define __ffs(x) (ffs(x) - 1)
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/find.h>
/*
* fls: find last bit set.
@@ -228,114 +173,17 @@ found_middle:
\
bit ? 33 - bit : bit; \
})
-#define fls64(x) generic_fls64(x)
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-static inline int sched_find_first_bit(const unsigned long *b)
-{
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
-}
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/ext2-non-atomic.h>
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
-
-#define ext2_set_bit(nr, addr) test_and_set_bit ((nr) ^ 0x18, (addr))
-#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x18, (addr))
-
-#define ext2_set_bit_atomic(lock,nr,addr) ext2_set_bit((nr), addr)
-#define ext2_clear_bit_atomic(lock,nr,addr) ext2_clear_bit((nr), addr)
-
-static inline int ext2_test_bit(int nr, const volatile void * addr)
-{
- const volatile unsigned char *ADDR = (const unsigned char *) addr;
- int mask;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- return ((mask & *ADDR) != 0);
-}
-
-#define ext2_find_first_zero_bit(addr, size) \
- ext2_find_next_zero_bit((addr), (size), 0)
-
-static inline unsigned long ext2_find_next_zero_bit(const void *addr,
- unsigned long size,
- unsigned long offset)
-{
- const unsigned long *p = ((const unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if(offset) {
- /* We hold the little endian value in tmp, but then the
- * shift is illegal. So we could keep a big endian value
- * in tmp, like this:
- *
- * tmp = __swab32(*(p++));
- * tmp |= ~0UL >> (32-offset);
- *
- * but this would decrease preformance, so we change the
- * shift:
- */
- tmp = *(p++);
- tmp |= __swab32(~0UL >> (32-offset));
- if(size < 32)
- goto found_first;
- if(~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while(size & ~31UL) {
- if(~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if(!size)
- return result;
- tmp = *p;
-
-found_first:
- /* tmp is little endian, so we would have to swab the shift,
- * see above. But then we have to swab tmp below for ffz, so
- * we might as well do this here.
- */
- return result + ffz(__swab32(tmp) | (~0UL << size));
-found_middle:
- return result + ffz(__swab32(tmp));
-}
+#define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit ((nr) ^ 0x18, (addr))
+#define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr) ^ 0x18, (addr))
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) ext2_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) ext2_set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) ext2_test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
+#include <asm-generic/bitops/minix-le.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-frv/futex.h b/include/asm-frv/futex.h
index fca9d90e32c..08b3d1da358 100644
--- a/include/asm-frv/futex.h
+++ b/include/asm-frv/futex.h
@@ -9,5 +9,11 @@
extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr);
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ return -ENOSYS;
+}
+
#endif
#endif
diff --git a/include/asm-frv/page.h b/include/asm-frv/page.h
index b8221b611b5..dc0f7e08a4c 100644
--- a/include/asm-frv/page.h
+++ b/include/asm-frv/page.h
@@ -57,13 +57,9 @@ extern unsigned long min_low_pfn;
extern unsigned long max_pfn;
#ifdef CONFIG_MMU
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long) ((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
-
#else
-#define pfn_to_page(pfn) (&mem_map[(pfn) - (PAGE_OFFSET >> PAGE_SHIFT)])
-#define page_to_pfn(page) ((PAGE_OFFSET >> PAGE_SHIFT) + (unsigned long) ((page) - mem_map))
+#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
#define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) < max_low_pfn)
#endif
@@ -87,6 +83,7 @@ extern unsigned long max_pfn;
#define WANT_PAGE_VIRTUAL 1
#endif
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _ASM_PAGE_H */
diff --git a/include/asm-frv/poll.h b/include/asm-frv/poll.h
index 8cbcd60e334..c8fe8801d07 100644
--- a/include/asm-frv/poll.h
+++ b/include/asm-frv/poll.h
@@ -12,6 +12,7 @@
#define POLLRDBAND 128
#define POLLWRBAND 256
#define POLLMSG 0x0400
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-generic/bitops.h b/include/asm-generic/bitops.h
index 0e6d9852008..1f9d99193df 100644
--- a/include/asm-generic/bitops.h
+++ b/include/asm-generic/bitops.h
@@ -5,77 +5,27 @@
* For the benefit of those who are trying to port Linux to another
* architecture, here are some C-language equivalents. You should
* recode these in the native assembly language, if at all possible.
- * To guarantee atomicity, these routines call cli() and sti() to
- * disable interrupts while they operate. (You have to provide inline
- * routines to cli() and sti().)
- *
- * Also note, these routines assume that you have 32 bit longs.
- * You will have to change this if you are trying to port Linux to the
- * Alpha architecture or to a Cray. :-)
*
* C language equivalents written by Theodore Ts'o, 9/26/92
*/
-extern __inline__ int set_bit(int nr,long * addr)
-{
- int mask, retval;
-
- addr += nr >> 5;
- mask = 1 << (nr & 0x1f);
- cli();
- retval = (mask & *addr) != 0;
- *addr |= mask;
- sti();
- return retval;
-}
-
-extern __inline__ int clear_bit(int nr, long * addr)
-{
- int mask, retval;
-
- addr += nr >> 5;
- mask = 1 << (nr & 0x1f);
- cli();
- retval = (mask & *addr) != 0;
- *addr &= ~mask;
- sti();
- return retval;
-}
-
-extern __inline__ int test_bit(int nr, const unsigned long * addr)
-{
- int mask;
-
- addr += nr >> 5;
- mask = 1 << (nr & 0x1f);
- return ((mask & *addr) != 0);
-}
-
-/*
- * fls: find last bit set.
- */
-
-#define fls(x) generic_fls(x)
-#define fls64(x) generic_fls64(x)
+#include <asm-generic/bitops/atomic.h>
+#include <asm-generic/bitops/non-atomic.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
#ifdef __KERNEL__
-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-
-#define ffs(x) generic_ffs(x)
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/hweight.h>
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+#include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-generic/bitops/__ffs.h b/include/asm-generic/bitops/__ffs.h
new file mode 100644
index 00000000000..9a3274aecf8
--- /dev/null
+++ b/include/asm-generic/bitops/__ffs.h
@@ -0,0 +1,43 @@
+#ifndef _ASM_GENERIC_BITOPS___FFS_H_
+#define _ASM_GENERIC_BITOPS___FFS_H_
+
+#include <asm/types.h>
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+ int num = 0;
+
+#if BITS_PER_LONG == 64
+ if ((word & 0xffffffff) == 0) {
+ num += 32;
+ word >>= 32;
+ }
+#endif
+ if ((word & 0xffff) == 0) {
+ num += 16;
+ word >>= 16;
+ }
+ if ((word & 0xff) == 0) {
+ num += 8;
+ word >>= 8;
+ }
+ if ((word & 0xf) == 0) {
+ num += 4;
+ word >>= 4;
+ }
+ if ((word & 0x3) == 0) {
+ num += 2;
+ word >>= 2;
+ }
+ if ((word & 0x1) == 0)
+ num += 1;
+ return num;
+}
+
+#endif /* _ASM_GENERIC_BITOPS___FFS_H_ */
diff --git a/include/asm-generic/bitops/atomic.h b/include/asm-generic/bitops/atomic.h
new file mode 100644
index 00000000000..78339319ba0
--- /dev/null
+++ b/include/asm-generic/bitops/atomic.h
@@ -0,0 +1,191 @@
+#ifndef _ASM_GENERIC_BITOPS_ATOMIC_H_
+#define _ASM_GENERIC_BITOPS_ATOMIC_H_
+
+#include <asm/types.h>
+
+#define BITOP_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
+
+#ifdef CONFIG_SMP
+#include <asm/spinlock.h>
+#include <asm/cache.h> /* we use L1_CACHE_BYTES */
+
+/* Use an array of spinlocks for our atomic_ts.
+ * Hash function to index into a different SPINLOCK.
+ * Since "a" is usually an address, use one spinlock per cacheline.
+ */
+# define ATOMIC_HASH_SIZE 4
+# define ATOMIC_HASH(a) (&(__atomic_hash[ (((unsigned long) a)/L1_CACHE_BYTES) & (ATOMIC_HASH_SIZE-1) ]))
+
+extern raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;
+
+/* Can't use raw_spin_lock_irq because of #include problems, so
+ * this is the substitute */
+#define _atomic_spin_lock_irqsave(l,f) do { \
+ raw_spinlock_t *s = ATOMIC_HASH(l); \
+ local_irq_save(f); \
+ __raw_spin_lock(s); \
+} while(0)
+
+#define _atomic_spin_unlock_irqrestore(l,f) do { \
+ raw_spinlock_t *s = ATOMIC_HASH(l); \
+ __raw_spin_unlock(s); \
+ local_irq_restore(f); \
+} while(0)
+
+
+#else
+# define _atomic_spin_lock_irqsave(l,f) do { local_irq_save(f); } while (0)
+# define _atomic_spin_unlock_irqrestore(l,f) do { local_irq_restore(f); } while (0)
+#endif
+
+/*
+ * NMI events can occur at any time, including when interrupts have been
+ * disabled by *_irqsave(). So you can get NMI events occurring while a
+ * *_bit function is holding a spin lock. If the NMI handler also wants
+ * to do bit manipulation (and they do) then you can get a deadlock
+ * between the original caller of *_bit() and the NMI handler.
+ *
+ * by Keith Owens
+ */
+
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered. See __set_bit()
+ * if you do not require the atomic guarantees.
+ *
+ * Note: there are no guarantees that this function will not be reordered
+ * on non x86 architectures, so if you are writting portable code,
+ * make sure not to rely on its reordering guarantees.
+ *
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static inline void set_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long flags;
+
+ _atomic_spin_lock_irqsave(p, flags);
+ *p |= mask;
+ _atomic_spin_unlock_irqrestore(p, flags);
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered. However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+static inline void clear_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long flags;
+
+ _atomic_spin_lock_irqsave(p, flags);
+ *p &= ~mask;
+ _atomic_spin_unlock_irqrestore(p, flags);
+}
+
+/**
+ * change_bit - Toggle a bit in memory
+ * @nr: Bit to change
+ * @addr: Address to start counting from
+ *
+ * change_bit() is atomic and may not be reordered. It may be
+ * reordered on other architectures than x86.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static inline void change_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long flags;
+
+ _atomic_spin_lock_irqsave(p, flags);
+ *p ^= mask;
+ _atomic_spin_unlock_irqrestore(p, flags);
+}
+
+/**
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It may be reordered on other architectures than x86.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long old;
+ unsigned long flags;
+
+ _atomic_spin_lock_irqsave(p, flags);
+ old = *p;
+ *p = old | mask;
+ _atomic_spin_unlock_irqrestore(p, flags);
+
+ return (old & mask) != 0;
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It can be reorderdered on other architectures other than x86.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long old;
+ unsigned long flags;
+
+ _atomic_spin_lock_irqsave(p, flags);
+ old = *p;
+ *p = old & ~mask;
+ _atomic_spin_unlock_irqrestore(p, flags);
+
+ return (old & mask) != 0;
+}
+
+/**
+ * test_and_change_bit - Change a bit and return its old value
+ * @nr: Bit to change
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long old;
+ unsigned long flags;
+
+ _atomic_spin_lock_irqsave(p, flags);
+ old = *p;
+ *p = old ^ mask;
+ _atomic_spin_unlock_irqrestore(p, flags);
+
+ return (old & mask) != 0;
+}
+
+#endif /* _ASM_GENERIC_BITOPS_ATOMIC_H */
diff --git a/include/asm-generic/bitops/ext2-atomic.h b/include/asm-generic/bitops/ext2-atomic.h
new file mode 100644
index 00000000000..ab1c875efb7
--- /dev/null
+++ b/include/asm-generic/bitops/ext2-atomic.h
@@ -0,0 +1,22 @@
+#ifndef _ASM_GENERIC_BITOPS_EXT2_ATOMIC_H_
+#define _ASM_GENERIC_BITOPS_EXT2_ATOMIC_H_
+
+#define ext2_set_bit_atomic(lock, nr, addr) \
+ ({ \
+ int ret; \
+ spin_lock(lock); \
+ ret = ext2_set_bit((nr), (unsigned long *)(addr)); \
+ spin_unlock(lock); \
+ ret; \
+ })
+
+#define ext2_clear_bit_atomic(lock, nr, addr) \
+ ({ \
+ int ret; \
+ spin_lock(lock); \
+ ret = ext2_clear_bit((nr), (unsigned long *)(addr)); \
+ spin_unlock(lock); \
+ ret; \
+ })
+
+#endif /* _ASM_GENERIC_BITOPS_EXT2_ATOMIC_H_ */
diff --git a/include/asm-generic/bitops/ext2-non-atomic.h b/include/asm-generic/bitops/ext2-non-atomic.h
new file mode 100644
index 00000000000..1697404afa0
--- /dev/null
+++ b/include/asm-generic/bitops/ext2-non-atomic.h
@@ -0,0 +1,18 @@
+#ifndef _ASM_GENERIC_BITOPS_EXT2_NON_ATOMIC_H_
+#define _ASM_GENERIC_BITOPS_EXT2_NON_ATOMIC_H_
+
+#include <asm-generic/bitops/le.h>
+
+#define ext2_set_bit(nr,addr) \
+ generic___test_and_set_le_bit((nr),(unsigned long *)(addr))
+#define ext2_clear_bit(nr,addr) \
+ generic___test_and_clear_le_bit((nr),(unsigned long *)(addr))
+
+#define ext2_test_bit(nr,addr) \
+ generic_test_le_bit((nr),(unsigned long *)(addr))
+#define ext2_find_first_zero_bit(addr, size) \
+ generic_find_first_zero_le_bit((unsigned long *)(addr), (size))
+#define ext2_find_next_zero_bit(addr, size, off) \
+ generic_find_next_zero_le_bit((unsigned long *)(addr), (size), (off))
+
+#endif /* _ASM_GENERIC_BITOPS_EXT2_NON_ATOMIC_H_ */
diff --git a/include/asm-generic/bitops/ffs.h b/include/asm-generic/bitops/ffs.h
new file mode 100644
index 00000000000..fbbb43af7dc
--- /dev/null
+++ b/include/asm-generic/bitops/ffs.h
@@ -0,0 +1,41 @@
+#ifndef _ASM_GENERIC_BITOPS_FFS_H_
+#define _ASM_GENERIC_BITOPS_FFS_H_
+
+/**
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+static inline int ffs(int x)
+{
+ int r = 1;
+
+ if (!x)
+ return 0;
+ if (!(x & 0xffff)) {
+ x >>= 16;
+ r += 16;
+ }
+ if (!(x & 0xff)) {
+ x >>= 8;
+ r += 8;
+ }
+ if (!(x & 0xf)) {
+ x >>= 4;
+ r += 4;
+ }
+ if (!(x & 3)) {
+ x >>= 2;
+ r += 2;
+ }
+ if (!(x & 1)) {
+ x >>= 1;
+ r += 1;
+ }
+ return r;
+}
+
+#endif /* _ASM_GENERIC_BITOPS_FFS_H_ */
diff --git a/include/asm-generic/bitops/ffz.h b/include/asm-generic/bitops/ffz.h
new file mode 100644
index 00000000000..6744bd4cdf4
--- /dev/null
+++ b/include/asm-generic/bitops/ffz.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_GENERIC_BITOPS_FFZ_H_
+#define _ASM_GENERIC_BITOPS_FFZ_H_
+
+/*
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+#define ffz(x) __ffs(~(x))
+
+#endif /* _ASM_GENERIC_BITOPS_FFZ_H_ */
diff --git a/include/asm-generic/bitops/find.h b/include/asm-generic/bitops/find.h
new file mode 100644
index 00000000000..72a51e5a12e
--- /dev/null
+++ b/include/asm-generic/bitops/find.h
@@ -0,0 +1,13 @@
+#ifndef _ASM_GENERIC_BITOPS_FIND_H_
+#define _ASM_GENERIC_BITOPS_FIND_H_
+
+extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
+ size, unsigned long offset);
+
+extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned
+ long size, unsigned long offset);
+
+#define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
+#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
+
+#endif /*_ASM_GENERIC_BITOPS_FIND_H_ */
diff --git a/include/asm-generic/bitops/fls.h b/include/asm-generic/bitops/fls.h
new file mode 100644
index 00000000000..850859bc506
--- /dev/null
+++ b/include/asm-generic/bitops/fls.h
@@ -0,0 +1,41 @@
+#ifndef _ASM_GENERIC_BITOPS_FLS_H_
+#define _ASM_GENERIC_BITOPS_FLS_H_
+
+/**
+ * fls - find last (most-significant) bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ */
+
+static inline int fls(int x)
+{
+ int r = 32;
+
+ if (!x)
+ return 0;
+ if (!(x & 0xffff0000u)) {
+ x <<= 16;
+ r -= 16;
+ }
+ if (!(x & 0xff000000u)) {
+ x <<= 8;
+ r -= 8;
+ }
+ if (!(x & 0xf0000000u)) {
+ x <<= 4;
+ r -= 4;
+ }
+ if (!(x & 0xc0000000u)) {
+ x <<= 2;
+ r -= 2;
+ }
+ if (!(x & 0x80000000u)) {
+ x <<= 1;
+ r -= 1;
+ }
+ return r;
+}
+
+#endif /* _ASM_GENERIC_BITOPS_FLS_H_ */
diff --git a/include/asm-generic/bitops/fls64.h b/include/asm-generic/bitops/fls64.h
new file mode 100644
index 00000000000..1b6b17ce242
--- /dev/null
+++ b/include/asm-generic/bitops/fls64.h
@@ -0,0 +1,14 @@
+#ifndef _ASM_GENERIC_BITOPS_FLS64_H_
+#define _ASM_GENERIC_BITOPS_FLS64_H_
+
+#include <asm/types.h>
+
+static inline int fls64(__u64 x)
+{
+ __u32 h = x >> 32;
+ if (h)
+ return fls(h) + 32;
+ return fls(x);
+}
+
+#endif /* _ASM_GENERIC_BITOPS_FLS64_H_ */
diff --git a/include/asm-generic/bitops/hweight.h b/include/asm-generic/bitops/hweight.h
new file mode 100644
index 00000000000..fbbc383771d
--- /dev/null
+++ b/include/asm-generic/bitops/hweight.h
@@ -0,0 +1,11 @@
+#ifndef _ASM_GENERIC_BITOPS_HWEIGHT_H_
+#define _ASM_GENERIC_BITOPS_HWEIGHT_H_
+
+#include <asm/types.h>
+
+extern unsigned int hweight32(unsigned int w);
+extern unsigned int hweight16(unsigned int w);
+extern unsigned int hweight8(unsigned int w);
+extern unsigned long hweight64(__u64 w);
+
+#endif /* _ASM_GENERIC_BITOPS_HWEIGHT_H_ */
diff --git a/include/asm-generic/bitops/le.h b/include/asm-generic/bitops/le.h
new file mode 100644
index 00000000000..b9c7e5d2d2a
--- /dev/null
+++ b/include/asm-generic/bitops/le.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_GENERIC_BITOPS_LE_H_
+#define _ASM_GENERIC_BITOPS_LE_H_
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+
+#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
+#define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7)
+
+#if defined(__LITTLE_ENDIAN)
+
+#define generic_test_le_bit(nr, addr) test_bit(nr, addr)
+#define generic___set_le_bit(nr, addr) __set_bit(nr, addr)
+#define generic___clear_le_bit(nr, addr) __clear_bit(nr, addr)
+
+#define generic_test_and_set_le_bit(nr, addr) test_and_set_bit(nr, addr)
+#define generic_test_and_clear_le_bit(nr, addr) test_and_clear_bit(nr, addr)
+
+#define generic___test_and_set_le_bit(nr, addr) __test_and_set_bit(nr, addr)
+#define generic___test_and_clear_le_bit(nr, addr) __test_and_clear_bit(nr, addr)
+
+#define generic_find_next_zero_le_bit(addr, size, offset) find_next_zero_bit(addr, size, offset)
+
+#elif defined(__BIG_ENDIAN)
+
+#define generic_test_le_bit(nr, addr) \
+ test_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+#define generic___set_le_bit(nr, addr) \
+ __set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+#define generic___clear_le_bit(nr, addr) \
+ __clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+
+#define generic_test_and_set_le_bit(nr, addr) \
+ test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+#define generic_test_and_clear_le_bit(nr, addr) \
+ test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+
+#define generic___test_and_set_le_bit(nr, addr) \
+ __test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+#define generic___test_and_clear_le_bit(nr, addr) \
+ __test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+
+extern unsigned long generic_find_next_zero_le_bit(const unsigned long *addr,
+ unsigned long size, unsigned long offset);
+
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+
+#define generic_find_first_zero_le_bit(addr, size) \
+ generic_find_next_zero_le_bit((addr), (size), 0)
+
+#endif /* _ASM_GENERIC_BITOPS_LE_H_ */
diff --git a/include/asm-generic/bitops/minix-le.h b/include/asm-generic/bitops/minix-le.h
new file mode 100644
index 00000000000..4a981c1bb1a
--- /dev/null
+++ b/include/asm-generic/bitops/minix-le.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_GENERIC_BITOPS_MINIX_LE_H_
+#define _ASM_GENERIC_BITOPS_MINIX_LE_H_
+
+#include <asm-generic/bitops/le.h>
+
+#define minix_test_and_set_bit(nr,addr) \
+ generic___test_and_set_le_bit((nr),(unsigned long *)(addr))
+#define minix_set_bit(nr,addr) \
+ generic___set_le_bit((nr),(unsigned long *)(addr))
+#define minix_test_and_clear_bit(nr,addr) \
+ generic___test_and_clear_le_bit((nr),(unsigned long *)(addr))
+#define minix_test_bit(nr,addr) \
+ generic_test_le_bit((nr),(unsigned long *)(addr))
+#define minix_find_first_zero_bit(addr,size) \
+ generic_find_first_zero_le_bit((unsigned long *)(addr),(size))
+
+#endif /* _ASM_GENERIC_BITOPS_MINIX_LE_H_ */
diff --git a/include/asm-generic/bitops/minix.h b/include/asm-generic/bitops/minix.h
new file mode 100644
index 00000000000..91f42e87aa5
--- /dev/null
+++ b/include/asm-generic/bitops/minix.h
@@ -0,0 +1,15 @@
+#ifndef _ASM_GENERIC_BITOPS_MINIX_H_
+#define _ASM_GENERIC_BITOPS_MINIX_H_
+
+#define minix_test_and_set_bit(nr,addr) \
+ __test_and_set_bit((nr),(unsigned long *)(addr))
+#define minix_set_bit(nr,addr) \
+ __set_bit((nr),(unsigned long *)(addr))
+#define minix_test_and_clear_bit(nr,addr) \
+ __test_and_clear_bit((nr),(unsigned long *)(addr))
+#define minix_test_bit(nr,addr) \
+ test_bit((nr),(unsigned long *)(addr))
+#define minix_find_first_zero_bit(addr,size) \
+ find_first_zero_bit((unsigned long *)(addr),(size))
+
+#endif /* _ASM_GENERIC_BITOPS_MINIX_H_ */
diff --git a/include/asm-generic/bitops/non-atomic.h b/include/asm-generic/bitops/non-atomic.h
new file mode 100644
index 00000000000..46a825cf2ae
--- /dev/null
+++ b/include/asm-generic/bitops/non-atomic.h
@@ -0,0 +1,111 @@
+#ifndef _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
+#define _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
+
+#include <asm/types.h>
+
+#define BITOP_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
+
+/**
+ * __set_bit - Set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Unlike set_bit(), this function is non-atomic and may be reordered.
+ * If it's called on the same region of memory simultaneously, the effect
+ * may be that only one operation succeeds.
+ */
+static inline void __set_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+
+ *p |= mask;
+}
+
+static inline void __clear_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+
+ *p &= ~mask;
+}
+
+/**
+ * __change_bit - Toggle a bit in memory
+ * @nr: the bit to change
+ * @addr: the address to start counting from
+ *
+ * Unlike change_bit(), this function is non-atomic and may be reordered.
+ * If it's called on the same region of memory simultaneously, the effect
+ * may be that only one operation succeeds.
+ */
+static inline void __change_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+
+ *p ^= mask;
+}
+
+/**
+ * __test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail. You must protect multiple accesses with a lock.
+ */
+static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long old = *p;
+
+ *p = old | mask;
+ return (old & mask) != 0;
+}
+
+/**
+ * __test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail. You must protect multiple accesses with a lock.
+ */
+static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long old = *p;
+
+ *p = old & ~mask;
+ return (old & mask) != 0;
+}
+
+/* WARNING: non atomic and it can be reordered! */
+static inline int __test_and_change_bit(int nr,
+ volatile unsigned long *addr)
+{
+ unsigned long mask = BITOP_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+ unsigned long old = *p;
+
+ *p = old ^ mask;
+ return (old & mask) != 0;
+}
+
+/**
+ * test_bit - Determine whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static inline int test_bit(int nr, const volatile unsigned long *addr)
+{
+ return 1UL & (addr[BITOP_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
+}
+
+#endif /* _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ */
diff --git a/include/asm-generic/bitops/sched.h b/include/asm-generic/bitops/sched.h
new file mode 100644
index 00000000000..5ef93a4d009
--- /dev/null
+++ b/include/asm-generic/bitops/sched.h
@@ -0,0 +1,36 @@
+#ifndef _ASM_GENERIC_BITOPS_SCHED_H_
+#define _ASM_GENERIC_BITOPS_SCHED_H_
+
+#include <linux/compiler.h> /* unlikely() */
+#include <asm/types.h>
+
+/*
+ * Every architecture must define this function. It's the fastest
+ * way of searching a 140-bit bitmap where the first 100 bits are
+ * unlikely to be set. It's guaranteed that at least one of the 140
+ * bits is cleared.
+ */
+static inline int sched_find_first_bit(const unsigned long *b)
+{
+#if BITS_PER_LONG == 64
+ if (unlikely(b[0]))
+ return __ffs(b[0]);
+ if (unlikely(b[1]))
+ return __ffs(b[1]) + 64;
+ return __ffs(b[2]) + 128;
+#elif BITS_PER_LONG == 32
+ if (unlikely(b[0]))
+ return __ffs(b[0]);
+ if (unlikely(b[1]))
+ return __ffs(b[1]) + 32;
+ if (unlikely(b[2]))
+ return __ffs(b[2]) + 64;
+ if (b[3])
+ return __ffs(b[3]) + 96;
+ return __ffs(b[4]) + 128;
+#else
+#error BITS_PER_LONG not defined
+#endif
+}
+
+#endif /* _ASM_GENERIC_BITOPS_SCHED_H_ */
diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
index 3ae2c734754..df893c16031 100644
--- a/include/asm-generic/futex.h
+++ b/include/asm-generic/futex.h
@@ -49,5 +49,11 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
return ret;
}
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ return -ENOSYS;
+}
+
#endif
#endif
diff --git a/include/asm-generic/local.h b/include/asm-generic/local.h
index 16fc00360f7..de4614840c2 100644
--- a/include/asm-generic/local.h
+++ b/include/asm-generic/local.h
@@ -4,28 +4,28 @@
#include <linux/config.h>
#include <linux/percpu.h>
#include <linux/hardirq.h>
+#include <asm/atomic.h>
#include <asm/types.h>
/* An unsigned long type for operations which are atomic for a single
* CPU. Usually used in combination with per-cpu variables. */
-#if BITS_PER_LONG == 32
/* Implement in terms of atomics. */
/* Don't use typedef: don't want them to be mixed with atomic_t's. */
typedef struct
{
- atomic_t a;
+ atomic_long_t a;
} local_t;
-#define LOCAL_INIT(i) { ATOMIC_INIT(i) }
+#define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) }
-#define local_read(l) ((unsigned long)atomic_read(&(l)->a))
-#define local_set(l,i) atomic_set((&(l)->a),(i))
-#define local_inc(l) atomic_inc(&(l)->a)
-#define local_dec(l) atomic_dec(&(l)->a)
-#define local_add(i,l) atomic_add((i),(&(l)->a))
-#define local_sub(i,l) atomic_sub((i),(&(l)->a))
+#define local_read(l) ((unsigned long)atomic_long_read(&(l)->a))
+#define local_set(l,i) atomic_long_set((&(l)->a),(i))
+#define local_inc(l) atomic_long_inc(&(l)->a)
+#define local_dec(l) atomic_long_dec(&(l)->a)
+#define local_add(i,l) atomic_long_add((i),(&(l)->a))
+#define local_sub(i,l) atomic_long_sub((i),(&(l)->a))
/* Non-atomic variants, ie. preemption disabled and won't be touched
* in interrupt, etc. Some archs can optimize this case well. */
@@ -34,68 +34,6 @@ typedef struct
#define __local_add(i,l) local_set((l), local_read(l) + (i))
#define __local_sub(i,l) local_set((l), local_read(l) - (i))
-#else /* ... can't use atomics. */
-/* Implement in terms of three variables.
- Another option would be to use local_irq_save/restore. */
-
-typedef struct
-{
- /* 0 = in hardirq, 1 = in softirq, 2 = usermode. */
- unsigned long v[3];
-} local_t;
-
-#define _LOCAL_VAR(l) ((l)->v[!in_interrupt() + !in_irq()])
-
-#define LOCAL_INIT(i) { { (i), 0, 0 } }
-
-static inline unsigned long local_read(local_t *l)
-{
- return l->v[0] + l->v[1] + l->v[2];
-}
-
-static inline void local_set(local_t *l, unsigned long v)
-{
- l->v[0] = v;
- l->v[1] = l->v[2] = 0;
-}
-
-static inline void local_inc(local_t *l)
-{
- preempt_disable();
- _LOCAL_VAR(l)++;
- preempt_enable();
-}
-
-static inline void local_dec(local_t *l)
-{
- preempt_disable();
- _LOCAL_VAR(l)--;
- preempt_enable();
-}
-
-static inline void local_add(unsigned long v, local_t *l)
-{
- preempt_disable();
- _LOCAL_VAR(l) += v;
- preempt_enable();
-}
-
-static inline void local_sub(unsigned long v, local_t *l)
-{
- preempt_disable();
- _LOCAL_VAR(l) -= v;
- preempt_enable();
-}
-
-/* Non-atomic variants, ie. preemption disabled and won't be touched
- * in interrupt, etc. Some archs can optimize this case well. */
-#define __local_inc(l) ((l)->v[0]++)
-#define __local_dec(l) ((l)->v[0]--)
-#define __local_add(i,l) ((l)->v[0] += (i))
-#define __local_sub(i,l) ((l)->v[0] -= (i))
-
-#endif /* Non-atomic implementation */
-
/* Use these for per-cpu local_t variables: on some archs they are
* much more efficient than these naive implementations. Note they take
* a variable (eg. mystruct.foo), not an address.
diff --git a/include/asm-generic/memory_model.h b/include/asm-generic/memory_model.h
new file mode 100644
index 00000000000..0cfb086dd37
--- /dev/null
+++ b/include/asm-generic/memory_model.h
@@ -0,0 +1,77 @@
+#ifndef __ASM_MEMORY_MODEL_H
+#define __ASM_MEMORY_MODEL_H
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#if defined(CONFIG_FLATMEM)
+
+#ifndef ARCH_PFN_OFFSET
+#define ARCH_PFN_OFFSET (0UL)
+#endif
+
+#elif defined(CONFIG_DISCONTIGMEM)
+
+#ifndef arch_pfn_to_nid
+#define arch_pfn_to_nid(pfn) pfn_to_nid(pfn)
+#endif
+
+#ifndef arch_local_page_offset
+#define arch_local_page_offset(pfn, nid) \
+ ((pfn) - NODE_DATA(nid)->node_start_pfn)
+#endif
+
+#endif /* CONFIG_DISCONTIGMEM */
+
+#ifdef CONFIG_OUT_OF_LINE_PFN_TO_PAGE
+struct page;
+/* this is useful when inlined pfn_to_page is too big */
+extern struct page *pfn_to_page(unsigned long pfn);
+extern unsigned long page_to_pfn(struct page *page);
+#else
+/*
+ * supports 3 memory models.
+ */
+#if defined(CONFIG_FLATMEM)
+
+#define pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET))
+#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + \
+ ARCH_PFN_OFFSET)
+#elif defined(CONFIG_DISCONTIGMEM)
+
+#define pfn_to_page(pfn) \
+({ unsigned long __pfn = (pfn); \
+ unsigned long __nid = arch_pfn_to_nid(pfn); \
+ NODE_DATA(__nid)->node_mem_map + arch_local_page_offset(__pfn, __nid);\
+})
+
+#define page_to_pfn(pg) \
+({ struct page *__pg = (pg); \
+ struct pglist_data *__pgdat = NODE_DATA(page_to_nid(__pg)); \
+ (unsigned long)(__pg - __pgdat->node_mem_map) + \
+ __pgdat->node_start_pfn; \
+})
+
+#elif defined(CONFIG_SPARSEMEM)
+/*
+ * Note: section's mem_map is encorded to reflect its start_pfn.
+ * section[i].section_mem_map == mem_map's address - start_pfn;
+ */
+#define page_to_pfn(pg) \
+({ struct page *__pg = (pg); \
+ int __sec = page_to_section(__pg); \
+ __pg - __section_mem_map_addr(__nr_to_section(__sec)); \
+})
+
+#define pfn_to_page(pfn) \
+({ unsigned long __pfn = (pfn); \
+ struct mem_section *__sec = __pfn_to_section(__pfn); \
+ __section_mem_map_addr(__sec) + __pfn; \
+})
+#endif /* CONFIG_FLATMEM/DISCONTIGMEM/SPARSEMEM */
+#endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index 78cf45547e3..c0caf433a7d 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -19,7 +19,7 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
#define percpu_modcopy(pcpudst, src, size) \
do { \
unsigned int __i; \
- for_each_cpu(__i) \
+ for_each_possible_cpu(__i) \
memcpy((pcpudst)+__per_cpu_offset[__i], \
(src), (size)); \
} while (0)
diff --git a/include/asm-h8300/bitops.h b/include/asm-h8300/bitops.h
index ff7c2b72159..574f57b6c4d 100644
--- a/include/asm-h8300/bitops.h
+++ b/include/asm-h8300/bitops.h
@@ -8,7 +8,6 @@
#include <linux/config.h>
#include <linux/compiler.h>
-#include <asm/byteorder.h> /* swab32 */
#include <asm/system.h>
#ifdef __KERNEL__
@@ -177,10 +176,7 @@ H8300_GEN_TEST_BITOP(test_and_change_bit,"bnot")
#undef H8300_GEN_TEST_BITOP_CONST_INT
#undef H8300_GEN_TEST_BITOP
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
-
-#define ffs(x) generic_ffs(x)
+#include <asm-generic/bitops/ffs.h>
static __inline__ unsigned long __ffs(unsigned long word)
{
@@ -196,216 +192,16 @@ static __inline__ unsigned long __ffs(unsigned long word)
return result;
}
-static __inline__ int find_next_zero_bit (const unsigned long * addr, int size, int offset)
-{
- unsigned long *p = (unsigned long *)(((unsigned long)addr + (offset >> 3)) & ~3);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (32-offset);
- if (size < 32)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size & ~31UL) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp |= ~0UL << size;
-found_middle:
- return result + ffz(tmp);
-}
-
-static __inline__ unsigned long find_next_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset)
-{
- unsigned long *p = (unsigned long *)(((unsigned long)addr + (offset >> 3)) & ~3);
- unsigned int result = offset & ~31UL;
- unsigned int tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *(p++);
- tmp &= ~0UL << offset;
- if (size < 32)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size >= 32) {
- if ((tmp = *p++) != 0)
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp &= ~0UL >> (32 - size);
- if (tmp == 0UL)
- return result + size;
-found_middle:
- return result + __ffs(tmp);
-}
-
-#define find_first_bit(addr, size) find_next_bit(addr, size, 0)
-
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-static inline int sched_find_first_bit(unsigned long *b)
-{
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
-}
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
-
-static __inline__ int ext2_set_bit(int nr, volatile void * addr)
-{
- int mask, retval;
- unsigned long flags;
- volatile unsigned char *ADDR = (unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- local_irq_save(flags);
- retval = (mask & *ADDR) != 0;
- *ADDR |= mask;
- local_irq_restore(flags);
- return retval;
-}
-#define ext2_set_bit_atomic(lock, nr, addr) ext2_set_bit(nr, addr)
-
-static __inline__ int ext2_clear_bit(int nr, volatile void * addr)
-{
- int mask, retval;
- unsigned long flags;
- volatile unsigned char *ADDR = (unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- local_irq_save(flags);
- retval = (mask & *ADDR) != 0;
- *ADDR &= ~mask;
- local_irq_restore(flags);
- return retval;
-}
-#define ext2_clear_bit_atomic(lock, nr, addr) ext2_set_bit(nr, addr)
-
-static __inline__ int ext2_test_bit(int nr, const volatile void * addr)
-{
- int mask;
- const volatile unsigned char *ADDR = (const unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- return ((mask & *ADDR) != 0);
-}
-
-#define ext2_find_first_zero_bit(addr, size) \
- ext2_find_next_zero_bit((addr), (size), 0)
-
-static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if(offset) {
- /* We hold the little endian value in tmp, but then the
- * shift is illegal. So we could keep a big endian value
- * in tmp, like this:
- *
- * tmp = __swab32(*(p++));
- * tmp |= ~0UL >> (32-offset);
- *
- * but this would decrease performance, so we change the
- * shift:
- */
- tmp = *(p++);
- tmp |= __swab32(~0UL >> (32-offset));
- if(size < 32)
- goto found_first;
- if(~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while(size & ~31UL) {
- if(~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if(!size)
- return result;
- tmp = *p;
-
-found_first:
- /* tmp is little endian, so we would have to swab the shift,
- * see above. But then we have to swab tmp below for ffz, so
- * we might as well do this here.
- */
- return result + ffz(__swab32(tmp) | (~0UL << size));
-found_middle:
- return result + ffz(__swab32(tmp));
-}
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+#include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */
-#define fls(x) generic_fls(x)
-#define fls64(x) generic_fls64(x)
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
#endif /* _H8300_BITOPS_H */
diff --git a/include/asm-h8300/page.h b/include/asm-h8300/page.h
index cd35b1cc6cd..6472c9f8822 100644
--- a/include/asm-h8300/page.h
+++ b/include/asm-h8300/page.h
@@ -71,8 +71,7 @@ extern unsigned long memory_end;
#define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
#define pfn_valid(page) (page < max_mapnr)
-#define pfn_to_page(pfn) virt_to_page(pfn_to_virt(pfn))
-#define page_to_pfn(page) virt_to_pfn(page_to_virt(page))
+#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
((void *)(kaddr) < (void *)memory_end))
@@ -81,6 +80,7 @@ extern unsigned long memory_end;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _H8300_PAGE_H */
diff --git a/include/asm-h8300/poll.h b/include/asm-h8300/poll.h
index bf49ab8ad6d..fc52103b276 100644
--- a/include/asm-h8300/poll.h
+++ b/include/asm-h8300/poll.h
@@ -12,6 +12,7 @@
#define POLLRDBAND 128
#define POLLWRBAND 256
#define POLLMSG 0x0400
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-h8300/types.h b/include/asm-h8300/types.h
index bf91e0d4dde..da2402b8654 100644
--- a/include/asm-h8300/types.h
+++ b/include/asm-h8300/types.h
@@ -58,6 +58,9 @@ typedef u32 dma_addr_t;
#define HAVE_SECTOR_T
typedef u64 sector_t;
+#define HAVE_BLKCNT_T
+typedef u64 blkcnt_t;
+
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h
index 7d20b95edb3..08deaeee6be 100644
--- a/include/asm-i386/bitops.h
+++ b/include/asm-i386/bitops.h
@@ -362,28 +362,9 @@ static inline unsigned long ffz(unsigned long word)
return word;
}
-#define fls64(x) generic_fls64(x)
-
#ifdef __KERNEL__
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-static inline int sched_find_first_bit(const unsigned long *b)
-{
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
-}
+#include <asm-generic/bitops/sched.h>
/**
* ffs - find first bit set
@@ -421,42 +402,22 @@ static inline int fls(int x)
return r+1;
}
-/**
- * hweightN - returns the hamming weight of a N-bit word
- * @x: the word to weigh
- *
- * The Hamming Weight of a number is the total number of bits set in it.
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/hweight.h>
#endif /* __KERNEL__ */
+#include <asm-generic/bitops/fls64.h>
+
#ifdef __KERNEL__
-#define ext2_set_bit(nr,addr) \
- __test_and_set_bit((nr),(unsigned long*)addr)
+#include <asm-generic/bitops/ext2-non-atomic.h>
+
#define ext2_set_bit_atomic(lock,nr,addr) \
test_and_set_bit((nr),(unsigned long*)addr)
-#define ext2_clear_bit(nr, addr) \
- __test_and_clear_bit((nr),(unsigned long*)addr)
#define ext2_clear_bit_atomic(lock,nr, addr) \
test_and_clear_bit((nr),(unsigned long*)addr)
-#define ext2_test_bit(nr, addr) test_bit((nr),(unsigned long*)addr)
-#define ext2_find_first_zero_bit(addr, size) \
- find_first_zero_bit((unsigned long*)addr, size)
-#define ext2_find_next_zero_bit(addr, size, off) \
- find_next_zero_bit((unsigned long*)addr, size, off)
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,(void*)addr)
-#define minix_set_bit(nr,addr) __set_bit(nr,(void*)addr)
-#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,(void*)addr)
-#define minix_test_bit(nr,addr) test_bit(nr,(void*)addr)
-#define minix_find_first_zero_bit(addr,size) \
- find_first_zero_bit((void*)addr,size)
+
+#include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-i386/dmi.h b/include/asm-i386/dmi.h
new file mode 100644
index 00000000000..38d4eeb7fc7
--- /dev/null
+++ b/include/asm-i386/dmi.h
@@ -0,0 +1,11 @@
+#ifndef _ASM_DMI_H
+#define _ASM_DMI_H 1
+
+#include <asm/io.h>
+
+/* Use early IO mappings for DMI because it's initialized early */
+#define dmi_ioremap bt_ioremap
+#define dmi_iounmap bt_iounmap
+#define dmi_alloc alloc_bootmem
+
+#endif
diff --git a/include/asm-i386/futex.h b/include/asm-i386/futex.h
index 44b9db80647..7b8ceefd010 100644
--- a/include/asm-i386/futex.h
+++ b/include/asm-i386/futex.h
@@ -104,5 +104,32 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
return ret;
}
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ __asm__ __volatile__(
+ "1: " LOCK_PREFIX "cmpxchgl %3, %1 \n"
+
+ "2: .section .fixup, \"ax\" \n"
+ "3: mov %2, %0 \n"
+ " jmp 2b \n"
+ " .previous \n"
+
+ " .section __ex_table, \"a\" \n"
+ " .align 8 \n"
+ " .long 1b,3b \n"
+ " .previous \n"
+
+ : "=a" (oldval), "=m" (*uaddr)
+ : "i" (-EFAULT), "r" (newval), "0" (oldval)
+ : "memory"
+ );
+
+ return oldval;
+}
+
#endif
#endif
diff --git a/include/asm-i386/kdebug.h b/include/asm-i386/kdebug.h
index 316138e8991..96d0828ce09 100644
--- a/include/asm-i386/kdebug.h
+++ b/include/asm-i386/kdebug.h
@@ -17,11 +17,9 @@ struct die_args {
int signr;
};
-/* Note - you should never unregister because that can race with NMIs.
- If you really want to do it first unregister - then synchronize_sched - then free.
- */
-int register_die_notifier(struct notifier_block *nb);
-extern struct notifier_block *i386die_chain;
+extern int register_die_notifier(struct notifier_block *);
+extern int unregister_die_notifier(struct notifier_block *);
+extern struct atomic_notifier_head i386die_chain;
/* Grossly misnamed. */
@@ -51,7 +49,7 @@ static inline int notify_die(enum die_val val, const char *str,
.trapnr = trap,
.signr = sig
};
- return notifier_call_chain(&i386die_chain, val, &args);
+ return atomic_notifier_call_chain(&i386die_chain, val, &args);
}
#endif
diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
index a0d2d74a7dd..57d157c5cf8 100644
--- a/include/asm-i386/kprobes.h
+++ b/include/asm-i386/kprobes.h
@@ -34,6 +34,7 @@ struct pt_regs;
typedef u8 kprobe_opcode_t;
#define BREAKPOINT_INSTRUCTION 0xcc
+#define RELATIVEJUMP_INSTRUCTION 0xe9
#define MAX_INSN_SIZE 16
#define MAX_STACK_SIZE 64
#define MIN_STACK_SIZE(ADDR) (((MAX_STACK_SIZE) < \
@@ -51,6 +52,11 @@ void kretprobe_trampoline(void);
struct arch_specific_insn {
/* copy of the original instruction */
kprobe_opcode_t *insn;
+ /*
+ * If this flag is not 0, this kprobe can be boost when its
+ * post_handler and break_handler is not set.
+ */
+ int boostable;
};
struct prev_kprobe {
diff --git a/include/asm-i386/mach-default/mach_time.h b/include/asm-i386/mach-default/mach_time.h
index b749aa44a86..31eb5de6f3d 100644
--- a/include/asm-i386/mach-default/mach_time.h
+++ b/include/asm-i386/mach-default/mach_time.h
@@ -82,21 +82,8 @@ static inline int mach_set_rtc_mmss(unsigned long nowtime)
static inline unsigned long mach_get_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- int i;
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
+ do {
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
hour = CMOS_READ(RTC_HOURS);
@@ -104,16 +91,18 @@ static inline unsigned long mach_get_cmos_time(void)
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
} while (sec != CMOS_READ(RTC_SECONDS));
- if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
- if ((year += 1900) < 1970)
+
+ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
+
+ year += 1900;
+ if (year < 1970)
year += 100;
return mktime(year, mon, day, hour, min, sec);
diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
index 74f595d8057..e33e9f9e4c6 100644
--- a/include/asm-i386/mmzone.h
+++ b/include/asm-i386/mmzone.h
@@ -70,8 +70,6 @@ static inline int pfn_to_nid(unsigned long pfn)
#endif
}
-#define node_localnr(pfn, nid) ((pfn) - node_data[nid]->node_start_pfn)
-
/*
* Following are macros that each numa implmentation must define.
*/
@@ -86,21 +84,6 @@ static inline int pfn_to_nid(unsigned long pfn)
/* XXX: FIXME -- wli */
#define kern_addr_valid(kaddr) (0)
-#define pfn_to_page(pfn) \
-({ \
- unsigned long __pfn = pfn; \
- int __node = pfn_to_nid(__pfn); \
- &NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)]; \
-})
-
-#define page_to_pfn(pg) \
-({ \
- struct page *__page = pg; \
- struct zone *__zone = page_zone(__page); \
- (unsigned long)(__page - __zone->zone_mem_map) \
- + __zone->zone_start_pfn; \
-})
-
#ifdef CONFIG_X86_NUMAQ /* we have contiguous memory on NUMA-Q */
#define pfn_valid(pfn) ((pfn) < num_physpages)
#else
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index 997ca5d1787..30f52a2263b 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -126,8 +126,6 @@ extern int page_is_ram(unsigned long pagenr);
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
#ifdef CONFIG_FLATMEM
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#endif /* CONFIG_FLATMEM */
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
@@ -141,6 +139,7 @@ extern int page_is_ram(unsigned long pagenr);
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _I386_PAGE_H */
diff --git a/include/asm-i386/poll.h b/include/asm-i386/poll.h
index aecc80a15d3..2cd4929abd4 100644
--- a/include/asm-i386/poll.h
+++ b/include/asm-i386/poll.h
@@ -16,6 +16,7 @@
#define POLLWRBAND 0x0200
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index feca5d961e2..805f0dcda46 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -20,6 +20,7 @@
#include <linux/config.h>
#include <linux/threads.h>
#include <asm/percpu.h>
+#include <linux/cpumask.h>
/* flag for disabling the tsc */
extern int tsc_disable;
@@ -67,6 +68,9 @@ struct cpuinfo_x86 {
char pad0;
int x86_power;
unsigned long loops_per_jiffy;
+#ifdef CONFIG_SMP
+ cpumask_t llc_shared_map; /* cpus sharing the last level cache */
+#endif
unsigned char x86_max_cores; /* cpuid returned max cores value */
unsigned char booted_cores; /* number of cores as seen by OS */
unsigned char apicid;
@@ -103,6 +107,7 @@ extern struct cpuinfo_x86 cpu_data[];
extern int phys_proc_id[NR_CPUS];
extern int cpu_core_id[NR_CPUS];
+extern int cpu_llc_id[NR_CPUS];
extern char ignore_fpu_irq;
extern void identify_cpu(struct cpuinfo_x86 *);
@@ -616,8 +621,6 @@ struct extended_sigtable {
unsigned int reserved[3];
struct extended_signature sigs[0];
};
-/* '6' because it used to be for P6 only (but now covers Pentium 4 as well) */
-#define MICROCODE_IOCFREE _IO('6',0)
/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
static inline void rep_nop(void)
diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h
index 826a8ca50ac..ee941457b55 100644
--- a/include/asm-i386/setup.h
+++ b/include/asm-i386/setup.h
@@ -6,9 +6,7 @@
#ifndef _i386_SETUP_H
#define _i386_SETUP_H
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
+#include <linux/pfn.h>
/*
* Reserved space for vmalloc and iomap - defined in asm/page.h
diff --git a/include/asm-i386/stat.h b/include/asm-i386/stat.h
index b464f8020ec..67eae78323b 100644
--- a/include/asm-i386/stat.h
+++ b/include/asm-i386/stat.h
@@ -58,8 +58,7 @@ struct stat64 {
long long st_size;
unsigned long st_blksize;
- unsigned long st_blocks; /* Number 512-byte blocks allocated. */
- unsigned long __pad4; /* future possible st_blocks high bits */
+ unsigned long long st_blocks; /* Number 512-byte blocks allocated. */
unsigned long st_atime;
unsigned long st_atime_nsec;
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h
index aa958c6ee83..b94e5eeef91 100644
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -112,4 +112,6 @@ extern unsigned long node_remap_size[];
#endif /* CONFIG_NUMA */
+extern cpumask_t cpu_coregroup_map(int cpu);
+
#endif /* _ASM_I386_TOPOLOGY_H */
diff --git a/include/asm-i386/types.h b/include/asm-i386/types.h
index ced00fe8fe6..e50a08bd7ce 100644
--- a/include/asm-i386/types.h
+++ b/include/asm-i386/types.h
@@ -63,6 +63,11 @@ typedef u64 sector_t;
#define HAVE_SECTOR_T
#endif
+#ifdef CONFIG_LSF
+typedef u64 blkcnt_t;
+#define HAVE_BLKCNT_T
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index d8afd0e3b81..014e3562895 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -316,8 +316,10 @@
#define __NR_pselect6 308
#define __NR_ppoll 309
#define __NR_unshare 310
+#define __NR_set_robust_list 311
+#define __NR_get_robust_list 312
-#define NR_syscalls 311
+#define NR_syscalls 313
/*
* user-visible error numbers are in the range -1 - -128: see
diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h
index f7a51765430..d734585a23c 100644
--- a/include/asm-ia64/acpi.h
+++ b/include/asm-ia64/acpi.h
@@ -111,7 +111,11 @@ extern int additional_cpus;
#ifdef CONFIG_ACPI_NUMA
/* Proximity bitmap length; _PXM is at most 255 (8 bit)*/
+#ifdef CONFIG_IA64_NR_NODES
+#define MAX_PXM_DOMAINS CONFIG_IA64_NR_NODES
+#else
#define MAX_PXM_DOMAINS (256)
+#endif
extern int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS];
extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
#endif
diff --git a/include/asm-ia64/asmmacro.h b/include/asm-ia64/asmmacro.h
index 77af457f4ad..d4cec32083d 100644
--- a/include/asm-ia64/asmmacro.h
+++ b/include/asm-ia64/asmmacro.h
@@ -51,6 +51,17 @@ name:
[99:] x
/*
+ * Tag MCA recoverable instruction ranges.
+ */
+
+ .section "__mca_table", "a" // declare section & section attributes
+ .previous
+
+# define MCA_RECOVER_RANGE(y) \
+ .xdata4 "__mca_table", y-., 99f-.; \
+ [99:]
+
+/*
* Mark instructions that need a load of a virtual address patched to be
* a load of a physical address. We use this either in critical performance
* path (ivt.S - TLB miss processing) or in places where it might not be
diff --git a/include/asm-ia64/bitops.h b/include/asm-ia64/bitops.h
index 36d0fb95ea8..90921e16279 100644
--- a/include/asm-ia64/bitops.h
+++ b/include/asm-ia64/bitops.h
@@ -5,8 +5,8 @@
* Copyright (C) 1998-2003 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*
- * 02/06/02 find_next_bit() and find_first_bit() added from Erich Focht's ia64 O(1)
- * scheduler patch
+ * 02/06/02 find_next_bit() and find_first_bit() added from Erich Focht's ia64
+ * O(1) scheduler patch
*/
#include <linux/compiler.h>
@@ -25,9 +25,9 @@
* restricted to acting on a single-word quantity.
*
* The address must be (at least) "long" aligned.
- * Note that there are driver (e.g., eepro100) which use these operations to operate on
- * hw-defined data-structures, so we can't easily change these operations to force a
- * bigger alignment.
+ * Note that there are driver (e.g., eepro100) which use these operations to
+ * operate on hw-defined data-structures, so we can't easily change these
+ * operations to force a bigger alignment.
*
* bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
*/
@@ -284,8 +284,8 @@ test_bit (int nr, const volatile void *addr)
* ffz - find the first zero bit in a long word
* @x: The long word to find the bit in
*
- * Returns the bit-number (0..63) of the first (least significant) zero bit. Undefined if
- * no zero exists, so code should check against ~0UL first...
+ * Returns the bit-number (0..63) of the first (least significant) zero bit.
+ * Undefined if no zero exists, so code should check against ~0UL first...
*/
static inline unsigned long
ffz (unsigned long x)
@@ -345,13 +345,14 @@ fls (int t)
x |= x >> 16;
return ia64_popcnt(x);
}
-#define fls64(x) generic_fls64(x)
+
+#include <asm-generic/bitops/fls64.h>
/*
- * ffs: find first bit set. This is defined the same way as the libc and compiler builtin
- * ffs routines, therefore differs in spirit from the above ffz (man ffs): it operates on
- * "int" values only and the result value is the bit number + 1. ffs(0) is defined to
- * return zero.
+ * ffs: find first bit set. This is defined the same way as the libc and
+ * compiler builtin ffs routines, therefore differs in spirit from the above
+ * ffz (man ffs): it operates on "int" values only and the result value is the
+ * bit number + 1. ffs(0) is defined to return zero.
*/
#define ffs(x) __builtin_ffs(x)
@@ -373,51 +374,17 @@ hweight64 (unsigned long x)
#endif /* __KERNEL__ */
-extern int __find_next_zero_bit (const void *addr, unsigned long size,
- unsigned long offset);
-extern int __find_next_bit(const void *addr, unsigned long size,
- unsigned long offset);
-
-#define find_next_zero_bit(addr, size, offset) \
- __find_next_zero_bit((addr), (size), (offset))
-#define find_next_bit(addr, size, offset) \
- __find_next_bit((addr), (size), (offset))
-
-/*
- * The optimizer actually does good code for this case..
- */
-#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
-
-#define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
+#include <asm-generic/bitops/find.h>
#ifdef __KERNEL__
-#define __clear_bit(nr, addr) clear_bit(nr, addr)
+#include <asm-generic/bitops/ext2-non-atomic.h>
-#define ext2_set_bit test_and_set_bit
#define ext2_set_bit_atomic(l,n,a) test_and_set_bit(n,a)
-#define ext2_clear_bit test_and_clear_bit
#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
-#define ext2_test_bit test_bit
-#define ext2_find_first_zero_bit find_first_zero_bit
-#define ext2_find_next_zero_bit find_next_zero_bit
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
-static inline int
-sched_find_first_bit (unsigned long *b)
-{
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return 64 + __ffs(b[1]);
- return __ffs(b[2]) + 128;
-}
+#include <asm-generic/bitops/minix.h>
+#include <asm-generic/bitops/sched.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h
index c0b19106665..40d01d80610 100644
--- a/include/asm-ia64/compat.h
+++ b/include/asm-ia64/compat.h
@@ -189,6 +189,12 @@ compat_ptr (compat_uptr_t uptr)
return (void __user *) (unsigned long) uptr;
}
+static inline compat_uptr_t
+ptr_to_compat(void __user *uptr)
+{
+ return (u32)(unsigned long)uptr;
+}
+
static __inline__ void __user *
compat_alloc_user_space (long len)
{
diff --git a/include/asm-ia64/dmi.h b/include/asm-ia64/dmi.h
new file mode 100644
index 00000000000..f3efaa22952
--- /dev/null
+++ b/include/asm-ia64/dmi.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_DMI_H
+#define _ASM_DMI_H 1
+
+#include <asm/io.h>
+
+#endif
diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
index b64fdb98549..c2e3742108b 100644
--- a/include/asm-ia64/io.h
+++ b/include/asm-ia64/io.h
@@ -88,8 +88,8 @@ phys_to_virt (unsigned long address)
}
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
-extern int valid_phys_addr_range (unsigned long addr, size_t *count); /* efi.c */
-extern int valid_mmap_phys_addr_range (unsigned long addr, size_t *count);
+extern int valid_phys_addr_range (unsigned long addr, size_t count); /* efi.c */
+extern int valid_mmap_phys_addr_range (unsigned long addr, size_t count);
/*
* The following two macros are deprecated and scheduled for removal.
@@ -416,24 +416,18 @@ __writeq (unsigned long val, volatile void __iomem *addr)
# define outl_p outl
#endif
-/*
- * An "address" in IO memory space is not clearly either an integer or a pointer. We will
- * accept both, thus the casts.
- *
- * On ia-64, we access the physical I/O memory space through the uncached kernel region.
- */
-static inline void __iomem *
-ioremap (unsigned long offset, unsigned long size)
-{
- return (void __iomem *) (__IA64_UNCACHED_OFFSET | (offset));
-}
+extern void __iomem * ioremap(unsigned long offset, unsigned long size);
+extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
static inline void
iounmap (volatile void __iomem *addr)
{
}
-#define ioremap_nocache(o,s) ioremap(o,s)
+/* Use normal IO mappings for DMI */
+#define dmi_ioremap ioremap
+#define dmi_iounmap(x,l) iounmap(x)
+#define dmi_alloc(l) kmalloc(l, GFP_ATOMIC)
# ifdef __KERNEL__
diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h
index 8b01a083dde..218c458ab60 100644
--- a/include/asm-ia64/kdebug.h
+++ b/include/asm-ia64/kdebug.h
@@ -40,7 +40,7 @@ struct die_args {
extern int register_die_notifier(struct notifier_block *);
extern int unregister_die_notifier(struct notifier_block *);
-extern struct notifier_block *ia64die_chain;
+extern struct atomic_notifier_head ia64die_chain;
enum die_val {
DIE_BREAK = 1,
@@ -81,7 +81,7 @@ static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs,
.signr = sig
};
- return notifier_call_chain(&ia64die_chain, val, &args);
+ return atomic_notifier_call_chain(&ia64die_chain, val, &args);
}
#endif
diff --git a/include/asm-ia64/machvec_dig.h b/include/asm-ia64/machvec_dig.h
index 4dc8522c974..8a0752f4098 100644
--- a/include/asm-ia64/machvec_dig.h
+++ b/include/asm-ia64/machvec_dig.h
@@ -2,7 +2,6 @@
#define _ASM_IA64_MACHVEC_DIG_h
extern ia64_mv_setup_t dig_setup;
-extern ia64_mv_irq_init_t dig_irq_init;
/*
* This stuff has dual use!
@@ -13,6 +12,5 @@ extern ia64_mv_irq_init_t dig_irq_init;
*/
#define platform_name "dig"
#define platform_setup dig_setup
-#define platform_irq_init dig_irq_init
#endif /* _ASM_IA64_MACHVEC_DIG_h */
diff --git a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h
index 3ae128fe082..dae6aeb7b11 100644
--- a/include/asm-ia64/numa.h
+++ b/include/asm-ia64/numa.h
@@ -23,7 +23,7 @@
#include <asm/mmzone.h>
-extern u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
+extern u16 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
extern cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
/* Stuff below this line could be architecture independent */
diff --git a/include/asm-ia64/numnodes.h b/include/asm-ia64/numnodes.h
index 21cff4da548..e9d356f549d 100644
--- a/include/asm-ia64/numnodes.h
+++ b/include/asm-ia64/numnodes.h
@@ -3,13 +3,18 @@
#ifdef CONFIG_IA64_DIG
/* Max 8 Nodes */
-#define NODES_SHIFT 3
+# define NODES_SHIFT 3
#elif defined(CONFIG_IA64_HP_ZX1) || defined(CONFIG_IA64_HP_ZX1_SWIOTLB)
/* Max 32 Nodes */
-#define NODES_SHIFT 5
+# define NODES_SHIFT 5
#elif defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
-/* Max 256 Nodes */
-#define NODES_SHIFT 8
+# if CONFIG_IA64_NR_NODES == 256
+# define NODES_SHIFT 8
+# elif CONFIG_IA64_NR_NODES <= 512
+# define NODES_SHIFT 9
+# elif CONFIG_IA64_NR_NODES <= 1024
+# define NODES_SHIFT 10
+# endif
#endif
#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 3ab27333dae..2087825eefa 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -106,17 +106,25 @@ extern int ia64_pfn_valid (unsigned long pfn);
# define ia64_pfn_valid(pfn) 1
#endif
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+extern struct page *vmem_map;
+#ifdef CONFIG_DISCONTIGMEM
+# define page_to_pfn(page) ((unsigned long) (page - vmem_map))
+# define pfn_to_page(pfn) (vmem_map + (pfn))
+#endif
+#endif
+
+#if defined(CONFIG_FLATMEM) || defined(CONFIG_SPARSEMEM)
+/* FLATMEM always configures mem_map (mem_map = vmem_map if necessary) */
+#include <asm-generic/memory_model.h>
+#endif
+
#ifdef CONFIG_FLATMEM
# define pfn_valid(pfn) (((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
-# define page_to_pfn(page) ((unsigned long) (page - mem_map))
-# define pfn_to_page(pfn) (mem_map + (pfn))
#elif defined(CONFIG_DISCONTIGMEM)
-extern struct page *vmem_map;
extern unsigned long min_low_pfn;
extern unsigned long max_low_pfn;
# define pfn_valid(pfn) (((pfn) >= min_low_pfn) && ((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
-# define page_to_pfn(page) ((unsigned long) (page - vmem_map))
-# define pfn_to_page(pfn) (vmem_map + (pfn))
#endif
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
@@ -149,7 +157,7 @@ typedef union ia64_va {
| (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT)))
# define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
# define is_hugepage_only_range(mm, addr, len) \
- (REGION_NUMBER(addr) == RGN_HPAGE && \
+ (REGION_NUMBER(addr) == RGN_HPAGE || \
REGION_NUMBER((addr)+(len)-1) == RGN_HPAGE)
extern unsigned int hpage_shift;
#endif
diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
index 7708ec669a3..4e7e6f23b08 100644
--- a/include/asm-ia64/pal.h
+++ b/include/asm-ia64/pal.h
@@ -1640,8 +1640,7 @@ ia64_pal_logical_to_phys(u64 proc_number, pal_logical_to_physical_t *mapping)
if (iprv.status == PAL_STATUS_SUCCESS)
{
- if (proc_number == 0)
- mapping->overview.overview_data = iprv.v0;
+ mapping->overview.overview_data = iprv.v0;
mapping->ppli1.ppli1_data = iprv.v1;
mapping->ppli2.ppli2_data = iprv.v2;
}
diff --git a/include/asm-ia64/poll.h b/include/asm-ia64/poll.h
index 160258a0528..bcaf9f14024 100644
--- a/include/asm-ia64/poll.h
+++ b/include/asm-ia64/poll.h
@@ -21,6 +21,7 @@
#define POLLWRBAND 0x0200
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
index 128fefd8056..b3bd58e8069 100644
--- a/include/asm-ia64/processor.h
+++ b/include/asm-ia64/processor.h
@@ -181,7 +181,6 @@ DECLARE_PER_CPU(struct cpuinfo_ia64, cpu_info);
#define local_cpu_data (&__ia64_per_cpu_var(cpu_info))
#define cpu_data(cpu) (&per_cpu(cpu_info, cpu))
-extern void identify_cpu (struct cpuinfo_ia64 *);
extern void print_cpu_info (struct cpuinfo_ia64 *);
typedef struct {
diff --git a/include/asm-ia64/sn/l1.h b/include/asm-ia64/sn/l1.h
index e3b819110d4..344bf44bb35 100644
--- a/include/asm-ia64/sn/l1.h
+++ b/include/asm-ia64/sn/l1.h
@@ -34,6 +34,8 @@
#define L1_BRICKTYPE_IA 0x6b /* k */
#define L1_BRICKTYPE_ATHENA 0x2b /* + */
#define L1_BRICKTYPE_DAYTONA 0x7a /* z */
+#define L1_BRICKTYPE_1932 0x2c /* . */
+#define L1_BRICKTYPE_191010 0x2e /* , */
/* board type response codes */
#define L1_BOARDTYPE_IP69 0x0100 /* CA */
@@ -46,5 +48,4 @@
#define L1_BOARDTYPE_DAYTONA 0x0800 /* AD */
#define L1_BOARDTYPE_INVAL (-1) /* invalid brick type */
-
#endif /* _ASM_IA64_SN_L1_H */
diff --git a/include/asm-ia64/sn/pcibr_provider.h b/include/asm-ia64/sn/pcibr_provider.h
index a601d3af39b..51260ab70d9 100644
--- a/include/asm-ia64/sn/pcibr_provider.h
+++ b/include/asm-ia64/sn/pcibr_provider.h
@@ -144,4 +144,5 @@ extern int sal_pcibr_slot_enable(struct pcibus_info *soft, int device,
void *resp);
extern int sal_pcibr_slot_disable(struct pcibus_info *soft, int device,
int action, void *resp);
+extern u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus);
#endif
diff --git a/include/asm-ia64/sn/pcidev.h b/include/asm-ia64/sn/pcidev.h
index 38cdffbc4c7..eac3561574b 100644
--- a/include/asm-ia64/sn/pcidev.h
+++ b/include/asm-ia64/sn/pcidev.h
@@ -76,6 +76,7 @@ extern void sn_pci_controller_fixup(int segment, int busnum,
struct pci_bus *bus);
extern void sn_bus_store_sysdata(struct pci_dev *dev);
extern void sn_bus_free_sysdata(void);
+extern void sn_generate_path(struct pci_bus *pci_bus, char *address);
extern void sn_pci_fixup_slot(struct pci_dev *dev);
extern void sn_pci_unfixup_slot(struct pci_dev *dev);
extern void sn_irq_lh_init(void);
diff --git a/include/asm-ia64/sn/sn_feature_sets.h b/include/asm-ia64/sn/sn_feature_sets.h
index ff33e3bd3f8..30dcfa442e5 100644
--- a/include/asm-ia64/sn/sn_feature_sets.h
+++ b/include/asm-ia64/sn/sn_feature_sets.h
@@ -30,8 +30,7 @@ extern int sn_prom_feature_available(int id);
#define PRF_PAL_CACHE_FLUSH_SAFE 0
#define PRF_DEVICE_FLUSH_LIST 1
-
-
+#define PRF_HOTPLUG_SUPPORT 2
/* --------------------- OS Features -------------------------------*/
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index b546de2fdce..bf4cc867a69 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -159,7 +159,7 @@
static inline u32
sn_sal_rev(void)
{
- struct ia64_sal_systab *systab = efi.sal_systab;
+ struct ia64_sal_systab *systab = __va(efi.sal_systab);
return (u32)(systab->sal_b_rev_major << 8 | systab->sal_b_rev_minor);
}
@@ -907,18 +907,22 @@ ia64_sn_sysctl_tio_clock_reset(nasid_t nasid)
/*
* Get the associated ioboard type for a given nasid.
*/
-static inline int
-ia64_sn_sysctl_ioboard_get(nasid_t nasid)
+static inline s64
+ia64_sn_sysctl_ioboard_get(nasid_t nasid, u16 *ioboard)
{
- struct ia64_sal_retval rv;
- SAL_CALL_REENTRANT(rv, SN_SAL_SYSCTL_OP, SAL_SYSCTL_OP_IOBOARD,
- nasid, 0, 0, 0, 0, 0);
- if (rv.v0 != 0)
- return (int)rv.v0;
- if (rv.v1 != 0)
- return (int)rv.v1;
-
- return 0;
+ struct ia64_sal_retval isrv;
+ SAL_CALL_REENTRANT(isrv, SN_SAL_SYSCTL_OP, SAL_SYSCTL_OP_IOBOARD,
+ nasid, 0, 0, 0, 0, 0);
+ if (isrv.v0 != 0) {
+ *ioboard = isrv.v0;
+ return isrv.status;
+ }
+ if (isrv.v1 != 0) {
+ *ioboard = isrv.v1;
+ return isrv.status;
+ }
+
+ return isrv.status;
}
/**
diff --git a/include/asm-m32r/bitops.h b/include/asm-m32r/bitops.h
index abea2fdd868..902a366101a 100644
--- a/include/asm-m32r/bitops.h
+++ b/include/asm-m32r/bitops.h
@@ -63,25 +63,6 @@ static __inline__ void set_bit(int nr, volatile void * addr)
}
/**
- * __set_bit - Set a bit in memory
- * @nr: the bit to set
- * @addr: the address to start counting from
- *
- * Unlike set_bit(), this function is non-atomic and may be reordered.
- * If it's called on the same region of memory simultaneously, the effect
- * may be that only one operation succeeds.
- */
-static __inline__ void __set_bit(int nr, volatile void * addr)
-{
- __u32 mask;
- volatile __u32 *a = addr;
-
- a += (nr >> 5);
- mask = (1 << (nr & 0x1F));
- *a |= mask;
-}
-
-/**
* clear_bit - Clears a bit in memory
* @nr: Bit to clear
* @addr: Address to start counting from
@@ -118,39 +99,10 @@ static __inline__ void clear_bit(int nr, volatile void * addr)
local_irq_restore(flags);
}
-static __inline__ void __clear_bit(int nr, volatile unsigned long * addr)
-{
- unsigned long mask;
- volatile unsigned long *a = addr;
-
- a += (nr >> 5);
- mask = (1 << (nr & 0x1F));
- *a &= ~mask;
-}
-
#define smp_mb__before_clear_bit() barrier()
#define smp_mb__after_clear_bit() barrier()
/**
- * __change_bit - Toggle a bit in memory
- * @nr: the bit to set
- * @addr: the address to start counting from
- *
- * Unlike change_bit(), this function is non-atomic and may be reordered.
- * If it's called on the same region of memory simultaneously, the effect
- * may be that only one operation succeeds.
- */
-static __inline__ void __change_bit(int nr, volatile void * addr)
-{
- __u32 mask;
- volatile __u32 *a = addr;
-
- a += (nr >> 5);
- mask = (1 << (nr & 0x1F));
- *a ^= mask;
-}
-
-/**
* change_bit - Toggle a bit in memory
* @nr: Bit to clear
* @addr: Address to start counting from
@@ -221,28 +173,6 @@ static __inline__ int test_and_set_bit(int nr, volatile void * addr)
}
/**
- * __test_and_set_bit - Set a bit and return its old value
- * @nr: Bit to set
- * @addr: Address to count from
- *
- * This operation is non-atomic and can be reordered.
- * If two examples of this operation race, one can appear to succeed
- * but actually fail. You must protect multiple accesses with a lock.
- */
-static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
-{
- __u32 mask, oldbit;
- volatile __u32 *a = addr;
-
- a += (nr >> 5);
- mask = (1 << (nr & 0x1F));
- oldbit = (*a & mask);
- *a |= mask;
-
- return (oldbit != 0);
-}
-
-/**
* test_and_clear_bit - Clear a bit and return its old value
* @nr: Bit to set
* @addr: Address to count from
@@ -280,42 +210,6 @@ static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
}
/**
- * __test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to set
- * @addr: Address to count from
- *
- * This operation is non-atomic and can be reordered.
- * If two examples of this operation race, one can appear to succeed
- * but actually fail. You must protect multiple accesses with a lock.
- */
-static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
-{
- __u32 mask, oldbit;
- volatile __u32 *a = addr;
-
- a += (nr >> 5);
- mask = (1 << (nr & 0x1F));
- oldbit = (*a & mask);
- *a &= ~mask;
-
- return (oldbit != 0);
-}
-
-/* WARNING: non atomic and it can be reordered! */
-static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
-{
- __u32 mask, oldbit;
- volatile __u32 *a = addr;
-
- a += (nr >> 5);
- mask = (1 << (nr & 0x1F));
- oldbit = (*a & mask);
- *a ^= mask;
-
- return (oldbit != 0);
-}
-
-/**
* test_and_change_bit - Change a bit and return its old value
* @nr: Bit to set
* @addr: Address to count from
@@ -350,353 +244,26 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
return (oldbit != 0);
}
-/**
- * test_bit - Determine whether a bit is set
- * @nr: bit number to test
- * @addr: Address to start counting from
- */
-static __inline__ int test_bit(int nr, const volatile void * addr)
-{
- __u32 mask;
- const volatile __u32 *a = addr;
-
- a += (nr >> 5);
- mask = (1 << (nr & 0x1F));
-
- return ((*a & mask) != 0);
-}
-
-/**
- * ffz - find first zero in word.
- * @word: The word to search
- *
- * Undefined if no zero exists, so code should check against ~0UL first.
- */
-static __inline__ unsigned long ffz(unsigned long word)
-{
- int k;
-
- word = ~word;
- k = 0;
- if (!(word & 0x0000ffff)) { k += 16; word >>= 16; }
- if (!(word & 0x000000ff)) { k += 8; word >>= 8; }
- if (!(word & 0x0000000f)) { k += 4; word >>= 4; }
- if (!(word & 0x00000003)) { k += 2; word >>= 2; }
- if (!(word & 0x00000001)) { k += 1; }
-
- return k;
-}
-
-/**
- * find_first_zero_bit - find the first zero bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first zero bit, not the number of the byte
- * containing a bit.
- */
-
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
-
-/**
- * find_next_zero_bit - find the first zero bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-static __inline__ int find_next_zero_bit(const unsigned long *addr,
- int size, int offset)
-{
- const unsigned long *p = addr + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (32-offset);
- if (size < 32)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size & ~31UL) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp |= ~0UL << size;
-found_middle:
- return result + ffz(tmp);
-}
-
-/**
- * __ffs - find first bit in word.
- * @word: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static __inline__ unsigned long __ffs(unsigned long word)
-{
- int k = 0;
-
- if (!(word & 0x0000ffff)) { k += 16; word >>= 16; }
- if (!(word & 0x000000ff)) { k += 8; word >>= 8; }
- if (!(word & 0x0000000f)) { k += 4; word >>= 4; }
- if (!(word & 0x00000003)) { k += 2; word >>= 2; }
- if (!(word & 0x00000001)) { k += 1;}
-
- return k;
-}
-
-/*
- * fls: find last bit set.
- */
-#define fls(x) generic_fls(x)
-#define fls64(x) generic_fls64(x)
+#include <asm-generic/bitops/non-atomic.h>
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
#ifdef __KERNEL__
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-static inline int sched_find_first_bit(unsigned long *b)
-{
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
-}
-
-/**
- * find_next_bit - find the first set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-static inline unsigned long find_next_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset)
-{
- unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
- unsigned int result = offset & ~31UL;
- unsigned int tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *p++;
- tmp &= ~0UL << offset;
- if (size < 32)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size >= 32) {
- if ((tmp = *p++) != 0)
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp &= ~0UL >> (32 - size);
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
-found_middle:
- return result + __ffs(tmp);
-}
-
-/**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first set bit, not the number of the byte
- * containing a bit.
- */
-#define find_first_bit(addr, size) \
- find_next_bit((addr), (size), 0)
-
-/**
- * ffs - find first bit set
- * @x: the word to search
- *
- * This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-#define ffs(x) generic_ffs(x)
-
-/**
- * hweightN - returns the hamming weight of a N-bit word
- * @x: the word to weigh
- *
- * The Hamming Weight of a number is the total number of bits set in it.
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/hweight.h>
#endif /* __KERNEL__ */
#ifdef __KERNEL__
-/*
- * ext2_XXXX function
- * orig: include/asm-sh/bitops.h
- */
-
-#ifdef __LITTLE_ENDIAN__
-#define ext2_set_bit test_and_set_bit
-#define ext2_clear_bit __test_and_clear_bit
-#define ext2_test_bit test_bit
-#define ext2_find_first_zero_bit find_first_zero_bit
-#define ext2_find_next_zero_bit find_next_zero_bit
-#else
-static inline int ext2_set_bit(int nr, volatile void * addr)
-{
- __u8 mask, oldbit;
- volatile __u8 *a = addr;
-
- a += (nr >> 3);
- mask = (1 << (nr & 0x07));
- oldbit = (*a & mask);
- *a |= mask;
-
- return (oldbit != 0);
-}
-
-static inline int ext2_clear_bit(int nr, volatile void * addr)
-{
- __u8 mask, oldbit;
- volatile __u8 *a = addr;
-
- a += (nr >> 3);
- mask = (1 << (nr & 0x07));
- oldbit = (*a & mask);
- *a &= ~mask;
-
- return (oldbit != 0);
-}
-
-static inline int ext2_test_bit(int nr, const volatile void * addr)
-{
- __u32 mask;
- const volatile __u8 *a = addr;
-
- a += (nr >> 3);
- mask = (1 << (nr & 0x07));
-
- return ((mask & *a) != 0);
-}
-
-#define ext2_find_first_zero_bit(addr, size) \
- ext2_find_next_zero_bit((addr), (size), 0)
-
-static inline unsigned long ext2_find_next_zero_bit(void *addr,
- unsigned long size, unsigned long offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if(offset) {
- /* We hold the little endian value in tmp, but then the
- * shift is illegal. So we could keep a big endian value
- * in tmp, like this:
- *
- * tmp = __swab32(*(p++));
- * tmp |= ~0UL >> (32-offset);
- *
- * but this would decrease preformance, so we change the
- * shift:
- */
- tmp = *(p++);
- tmp |= __swab32(~0UL >> (32-offset));
- if(size < 32)
- goto found_first;
- if(~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while(size & ~31UL) {
- if(~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if(!size)
- return result;
- tmp = *p;
-
-found_first:
- /* tmp is little endian, so we would have to swab the shift,
- * see above. But then we have to swab tmp below for ffz, so
- * we might as well do this here.
- */
- return result + ffz(__swab32(tmp) | (~0UL << size));
-found_middle:
- return result + ffz(__swab32(tmp));
-}
-#endif
-
-#define ext2_set_bit_atomic(lock, nr, addr) \
- ({ \
- int ret; \
- spin_lock(lock); \
- ret = ext2_set_bit((nr), (addr)); \
- spin_unlock(lock); \
- ret; \
- })
-
-#define ext2_clear_bit_atomic(lock, nr, addr) \
- ({ \
- int ret; \
- spin_lock(lock); \
- ret = ext2_clear_bit((nr), (addr)); \
- spin_unlock(lock); \
- ret; \
- })
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) __set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+#include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-m32r/mmzone.h b/include/asm-m32r/mmzone.h
index adc7970a77e..9f3b5accda8 100644
--- a/include/asm-m32r/mmzone.h
+++ b/include/asm-m32r/mmzone.h
@@ -21,20 +21,6 @@ extern struct pglist_data *node_data[];
__pgdat->node_start_pfn + __pgdat->node_spanned_pages - 1; \
})
-#define pfn_to_page(pfn) \
-({ \
- unsigned long __pfn = pfn; \
- int __node = pfn_to_nid(__pfn); \
- &NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)]; \
-})
-
-#define page_to_pfn(pg) \
-({ \
- struct page *__page = pg; \
- struct zone *__zone = page_zone(__page); \
- (unsigned long)(__page - __zone->zone_mem_map) \
- + __zone->zone_start_pfn; \
-})
#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
/*
* pfn_valid should be made as fast as possible, and the current definition
diff --git a/include/asm-m32r/page.h b/include/asm-m32r/page.h
index 4ab57887636..9ddbc087dbc 100644
--- a/include/asm-m32r/page.h
+++ b/include/asm-m32r/page.h
@@ -76,9 +76,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#ifndef CONFIG_DISCONTIGMEM
#define PFN_BASE (CONFIG_MEMORY_START >> PAGE_SHIFT)
-#define pfn_to_page(pfn) (mem_map + ((pfn) - PFN_BASE))
-#define page_to_pfn(page) \
- ((unsigned long)((page) - mem_map) + PFN_BASE)
+#define ARCH_PFN_OFFSET PFN_BASE
#define pfn_valid(pfn) (((pfn) - PFN_BASE) < max_mapnr)
#endif /* !CONFIG_DISCONTIGMEM */
@@ -92,6 +90,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _ASM_M32R_PAGE_H */
diff --git a/include/asm-m32r/poll.h b/include/asm-m32r/poll.h
index 43b7acf732d..9e0e700e727 100644
--- a/include/asm-m32r/poll.h
+++ b/include/asm-m32r/poll.h
@@ -21,6 +21,7 @@
#define POLLWRBAND 0x0200
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-m32r/setup.h b/include/asm-m32r/setup.h
index 5f028dc26a9..52f4fa29abf 100644
--- a/include/asm-m32r/setup.h
+++ b/include/asm-m32r/setup.h
@@ -24,10 +24,6 @@
#define RAMDISK_PROMPT_FLAG (0x8000)
#define RAMDISK_LOAD_FLAG (0x4000)
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
-
extern unsigned long memory_start;
extern unsigned long memory_end;
diff --git a/include/asm-m68k/bitops.h b/include/asm-m68k/bitops.h
index 13f4c004846..1a61fdb56aa 100644
--- a/include/asm-m68k/bitops.h
+++ b/include/asm-m68k/bitops.h
@@ -310,36 +310,10 @@ static inline int fls(int x)
return 32 - cnt;
}
-#define fls64(x) generic_fls64(x)
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-static inline int sched_find_first_bit(const unsigned long *b)
-{
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
-}
-
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
/* Bitmap functions for the minix filesystem */
@@ -365,9 +339,9 @@ static inline int minix_find_first_zero_bit(const void *vaddr, unsigned size)
return ((p - addr) << 4) + (res ^ 31);
}
-#define minix_test_and_set_bit(nr, addr) test_and_set_bit((nr) ^ 16, (unsigned long *)(addr))
-#define minix_set_bit(nr,addr) set_bit((nr) ^ 16, (unsigned long *)(addr))
-#define minix_test_and_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 16, (unsigned long *)(addr))
+#define minix_test_and_set_bit(nr, addr) __test_and_set_bit((nr) ^ 16, (unsigned long *)(addr))
+#define minix_set_bit(nr,addr) __set_bit((nr) ^ 16, (unsigned long *)(addr))
+#define minix_test_and_clear_bit(nr, addr) __test_and_clear_bit((nr) ^ 16, (unsigned long *)(addr))
static inline int minix_test_bit(int nr, const void *vaddr)
{
@@ -377,9 +351,9 @@ static inline int minix_test_bit(int nr, const void *vaddr)
/* Bitmap functions for the ext2 filesystem. */
-#define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 24, (unsigned long *)(addr))
+#define ext2_set_bit(nr, addr) __test_and_set_bit((nr) ^ 24, (unsigned long *)(addr))
#define ext2_set_bit_atomic(lock, nr, addr) test_and_set_bit((nr) ^ 24, (unsigned long *)(addr))
-#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr))
+#define ext2_clear_bit(nr, addr) __test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr))
#define ext2_clear_bit_atomic(lock, nr, addr) test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr))
static inline int ext2_test_bit(int nr, const void *vaddr)
diff --git a/include/asm-m68k/poll.h b/include/asm-m68k/poll.h
index c4b69c4a87e..0fb8843647f 100644
--- a/include/asm-m68k/poll.h
+++ b/include/asm-m68k/poll.h
@@ -13,6 +13,7 @@
#define POLLWRBAND 256
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-m68k/stat.h b/include/asm-m68k/stat.h
index c4c402a45e2..dd38bc2e9f9 100644
--- a/include/asm-m68k/stat.h
+++ b/include/asm-m68k/stat.h
@@ -60,8 +60,7 @@ struct stat64 {
long long st_size;
unsigned long st_blksize;
- unsigned long __pad4; /* future possible st_blocks high bits */
- unsigned long st_blocks; /* Number 512-byte blocks allocated. */
+ unsigned long long st_blocks; /* Number 512-byte blocks allocated. */
unsigned long st_atime;
unsigned long st_atime_nsec;
diff --git a/include/asm-m68knommu/bitops.h b/include/asm-m68knommu/bitops.h
index 25d8a3cfef9..0b68ccd327f 100644
--- a/include/asm-m68knommu/bitops.h
+++ b/include/asm-m68knommu/bitops.h
@@ -12,104 +12,10 @@
#ifdef __KERNEL__
-/*
- * Generic ffs().
- */
-static inline int ffs(int x)
-{
- int r = 1;
-
- if (!x)
- return 0;
- if (!(x & 0xffff)) {
- x >>= 16;
- r += 16;
- }
- if (!(x & 0xff)) {
- x >>= 8;
- r += 8;
- }
- if (!(x & 0xf)) {
- x >>= 4;
- r += 4;
- }
- if (!(x & 3)) {
- x >>= 2;
- r += 2;
- }
- if (!(x & 1)) {
- x >>= 1;
- r += 1;
- }
- return r;
-}
-
-/*
- * Generic __ffs().
- */
-static inline int __ffs(int x)
-{
- int r = 0;
-
- if (!x)
- return 0;
- if (!(x & 0xffff)) {
- x >>= 16;
- r += 16;
- }
- if (!(x & 0xff)) {
- x >>= 8;
- r += 8;
- }
- if (!(x & 0xf)) {
- x >>= 4;
- r += 4;
- }
- if (!(x & 3)) {
- x >>= 2;
- r += 2;
- }
- if (!(x & 1)) {
- x >>= 1;
- r += 1;
- }
- return r;
-}
-
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-static inline int sched_find_first_bit(unsigned long *b)
-{
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
-}
-
-/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- */
-static __inline__ unsigned long ffz(unsigned long word)
-{
- unsigned long result = 0;
-
- while(word & 1) {
- result++;
- word >>= 1;
- }
- return result;
-}
-
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/ffz.h>
static __inline__ void set_bit(int nr, volatile unsigned long * addr)
{
@@ -254,98 +160,8 @@ static __inline__ int __test_bit(int nr, const volatile unsigned long * addr)
__constant_test_bit((nr),(addr)) : \
__test_bit((nr),(addr)))
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
-#define find_first_bit(addr, size) \
- find_next_bit((addr), (size), 0)
-
-static __inline__ int find_next_zero_bit (const void * addr, int size, int offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (32-offset);
- if (size < 32)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size & ~31UL) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp |= ~0UL << size;
-found_middle:
- return result + ffz(tmp);
-}
-
-/*
- * Find next one bit in a bitmap reasonably efficiently.
- */
-static __inline__ unsigned long find_next_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset)
-{
- unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
- unsigned int result = offset & ~31UL;
- unsigned int tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *p++;
- tmp &= ~0UL << offset;
- if (size < 32)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size >= 32) {
- if ((tmp = *p++) != 0)
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp &= ~0UL >> (32 - size);
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
-found_middle:
- return result + __ffs(tmp);
-}
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
-
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/hweight.h>
static __inline__ int ext2_set_bit(int nr, volatile void * addr)
{
@@ -475,30 +291,11 @@ found_middle:
return result + ffz(__swab32(tmp));
}
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
-
-/**
- * hweightN - returns the hamming weight of a N-bit word
- * @x: the word to weigh
- *
- * The Hamming Weight of a number is the total number of bits set in it.
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */
-/*
- * fls: find last bit set.
- */
-#define fls(x) generic_fls(x)
-#define fls64(x) generic_fls64(x)
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
#endif /* _M68KNOMMU_BITOPS_H */
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index 8e802059fe6..a1728f8c070 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -105,22 +105,6 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
}
/*
- * __set_bit - Set a bit in memory
- * @nr: the bit to set
- * @addr: the address to start counting from
- *
- * Unlike set_bit(), this function is non-atomic and may be reordered.
- * If it's called on the same region of memory simultaneously, the effect
- * may be that only one operation succeeds.
- */
-static inline void __set_bit(unsigned long nr, volatile unsigned long * addr)
-{
- unsigned long * m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-
- *m |= 1UL << (nr & SZLONG_MASK);
-}
-
-/*
* clear_bit - Clears a bit in memory
* @nr: Bit to clear
* @addr: Address to start counting from
@@ -169,22 +153,6 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
}
/*
- * __clear_bit - Clears a bit in memory
- * @nr: Bit to clear
- * @addr: Address to start counting from
- *
- * Unlike clear_bit(), this function is non-atomic and may be reordered.
- * If it's called on the same region of memory simultaneously, the effect
- * may be that only one operation succeeds.
- */
-static inline void __clear_bit(unsigned long nr, volatile unsigned long * addr)
-{
- unsigned long * m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-
- *m &= ~(1UL << (nr & SZLONG_MASK));
-}
-
-/*
* change_bit - Toggle a bit in memory
* @nr: Bit to change
* @addr: Address to start counting from
@@ -235,22 +203,6 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
}
/*
- * __change_bit - Toggle a bit in memory
- * @nr: the bit to change
- * @addr: the address to start counting from
- *
- * Unlike change_bit(), this function is non-atomic and may be reordered.
- * If it's called on the same region of memory simultaneously, the effect
- * may be that only one operation succeeds.
- */
-static inline void __change_bit(unsigned long nr, volatile unsigned long * addr)
-{
- unsigned long * m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-
- *m ^= 1UL << (nr & SZLONG_MASK);
-}
-
-/*
* test_and_set_bit - Set a bit and return its old value
* @nr: Bit to set
* @addr: Address to count from
@@ -321,30 +273,6 @@ static inline int test_and_set_bit(unsigned long nr,
}
/*
- * __test_and_set_bit - Set a bit and return its old value
- * @nr: Bit to set
- * @addr: Address to count from
- *
- * This operation is non-atomic and can be reordered.
- * If two examples of this operation race, one can appear to succeed
- * but actually fail. You must protect multiple accesses with a lock.
- */
-static inline int __test_and_set_bit(unsigned long nr,
- volatile unsigned long *addr)
-{
- volatile unsigned long *a = addr;
- unsigned long mask;
- int retval;
-
- a += nr >> SZLONG_LOG;
- mask = 1UL << (nr & SZLONG_MASK);
- retval = (mask & *a) != 0;
- *a |= mask;
-
- return retval;
-}
-
-/*
* test_and_clear_bit - Clear a bit and return its old value
* @nr: Bit to clear
* @addr: Address to count from
@@ -417,30 +345,6 @@ static inline int test_and_clear_bit(unsigned long nr,
}
/*
- * __test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to clear
- * @addr: Address to count from
- *
- * This operation is non-atomic and can be reordered.
- * If two examples of this operation race, one can appear to succeed
- * but actually fail. You must protect multiple accesses with a lock.
- */
-static inline int __test_and_clear_bit(unsigned long nr,
- volatile unsigned long * addr)
-{
- volatile unsigned long *a = addr;
- unsigned long mask;
- int retval;
-
- a += (nr >> SZLONG_LOG);
- mask = 1UL << (nr & SZLONG_MASK);
- retval = ((mask & *a) != 0);
- *a &= ~mask;
-
- return retval;
-}
-
-/*
* test_and_change_bit - Change a bit and return its old value
* @nr: Bit to change
* @addr: Address to count from
@@ -509,43 +413,11 @@ static inline int test_and_change_bit(unsigned long nr,
}
}
-/*
- * __test_and_change_bit - Change a bit and return its old value
- * @nr: Bit to change
- * @addr: Address to count from
- *
- * This operation is non-atomic and can be reordered.
- * If two examples of this operation race, one can appear to succeed
- * but actually fail. You must protect multiple accesses with a lock.
- */
-static inline int __test_and_change_bit(unsigned long nr,
- volatile unsigned long *addr)
-{
- volatile unsigned long *a = addr;
- unsigned long mask;
- int retval;
-
- a += (nr >> SZLONG_LOG);
- mask = 1UL << (nr & SZLONG_MASK);
- retval = ((mask & *a) != 0);
- *a ^= mask;
-
- return retval;
-}
-
#undef __bi_flags
#undef __bi_local_irq_save
#undef __bi_local_irq_restore
-/*
- * test_bit - Determine whether a bit is set
- * @nr: bit number to test
- * @addr: Address to start counting from
- */
-static inline int test_bit(unsigned long nr, const volatile unsigned long *addr)
-{
- return 1UL & (addr[nr >> SZLONG_LOG] >> (nr & SZLONG_MASK));
-}
+#include <asm-generic/bitops/non-atomic.h>
/*
* Return the bit position (0..63) of the most significant 1 bit in a word
@@ -580,6 +452,8 @@ static inline int __ilog2(unsigned long x)
return 63 - lz;
}
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+
/*
* __ffs - find first bit in word.
* @word: The word to search
@@ -589,31 +463,7 @@ static inline int __ilog2(unsigned long x)
*/
static inline unsigned long __ffs(unsigned long word)
{
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
return __ilog2(word & -word);
-#else
- int b = 0, s;
-
-#ifdef CONFIG_32BIT
- s = 16; if (word << 16 != 0) s = 0; b += s; word >>= s;
- s = 8; if (word << 24 != 0) s = 0; b += s; word >>= s;
- s = 4; if (word << 28 != 0) s = 0; b += s; word >>= s;
- s = 2; if (word << 30 != 0) s = 0; b += s; word >>= s;
- s = 1; if (word << 31 != 0) s = 0; b += s;
-
- return b;
-#endif
-#ifdef CONFIG_64BIT
- s = 32; if (word << 32 != 0) s = 0; b += s; word >>= s;
- s = 16; if (word << 48 != 0) s = 0; b += s; word >>= s;
- s = 8; if (word << 56 != 0) s = 0; b += s; word >>= s;
- s = 4; if (word << 60 != 0) s = 0; b += s; word >>= s;
- s = 2; if (word << 62 != 0) s = 0; b += s; word >>= s;
- s = 1; if (word << 63 != 0) s = 0; b += s;
-
- return b;
-#endif
-#endif
}
/*
@@ -652,321 +502,38 @@ static inline unsigned long ffz(unsigned long word)
*/
static inline unsigned long fls(unsigned long word)
{
-#ifdef CONFIG_32BIT
#ifdef CONFIG_CPU_MIPS32
__asm__ ("clz %0, %1" : "=r" (word) : "r" (word));
return 32 - word;
-#else
- {
- int r = 32, s;
-
- if (word == 0)
- return 0;
-
- s = 16; if ((word & 0xffff0000)) s = 0; r -= s; word <<= s;
- s = 8; if ((word & 0xff000000)) s = 0; r -= s; word <<= s;
- s = 4; if ((word & 0xf0000000)) s = 0; r -= s; word <<= s;
- s = 2; if ((word & 0xc0000000)) s = 0; r -= s; word <<= s;
- s = 1; if ((word & 0x80000000)) s = 0; r -= s;
-
- return r;
- }
#endif
-#endif /* CONFIG_32BIT */
-#ifdef CONFIG_64BIT
#ifdef CONFIG_CPU_MIPS64
-
__asm__ ("dclz %0, %1" : "=r" (word) : "r" (word));
return 64 - word;
-#else
- {
- int r = 64, s;
-
- if (word == 0)
- return 0;
-
- s = 32; if ((word & 0xffffffff00000000UL)) s = 0; r -= s; word <<= s;
- s = 16; if ((word & 0xffff000000000000UL)) s = 0; r -= s; word <<= s;
- s = 8; if ((word & 0xff00000000000000UL)) s = 0; r -= s; word <<= s;
- s = 4; if ((word & 0xf000000000000000UL)) s = 0; r -= s; word <<= s;
- s = 2; if ((word & 0xc000000000000000UL)) s = 0; r -= s; word <<= s;
- s = 1; if ((word & 0x8000000000000000UL)) s = 0; r -= s;
-
- return r;
- }
#endif
-#endif /* CONFIG_64BIT */
}
-#define fls64(x) generic_fls64(x)
-
-/*
- * find_next_zero_bit - find the first zero bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-static inline unsigned long find_next_zero_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset)
-{
- const unsigned long *p = addr + (offset >> SZLONG_LOG);
- unsigned long result = offset & ~SZLONG_MASK;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= SZLONG_MASK;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (_MIPS_SZLONG-offset);
- if (size < _MIPS_SZLONG)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= _MIPS_SZLONG;
- result += _MIPS_SZLONG;
- }
- while (size & ~SZLONG_MASK) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += _MIPS_SZLONG;
- size -= _MIPS_SZLONG;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp |= ~0UL << size;
- if (tmp == ~0UL) /* Are any bits zero? */
- return result + size; /* Nope. */
-found_middle:
- return result + ffz(tmp);
-}
+#else
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/fls.h>
-/*
- * find_next_bit - find the next set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-static inline unsigned long find_next_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset)
-{
- const unsigned long *p = addr + (offset >> SZLONG_LOG);
- unsigned long result = offset & ~SZLONG_MASK;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= SZLONG_MASK;
- if (offset) {
- tmp = *(p++);
- tmp &= ~0UL << offset;
- if (size < _MIPS_SZLONG)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= _MIPS_SZLONG;
- result += _MIPS_SZLONG;
- }
- while (size & ~SZLONG_MASK) {
- if ((tmp = *(p++)))
- goto found_middle;
- result += _MIPS_SZLONG;
- size -= _MIPS_SZLONG;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp &= ~0UL >> (_MIPS_SZLONG - size);
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
-found_middle:
- return result + __ffs(tmp);
-}
+#endif /*defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) */
-/*
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first set bit, not the number of the byte
- * containing a bit.
- */
-#define find_first_bit(addr, size) \
- find_next_bit((addr), (size), 0)
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
#ifdef __KERNEL__
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-static inline int sched_find_first_bit(const unsigned long *b)
-{
-#ifdef CONFIG_32BIT
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
-#endif
-#ifdef CONFIG_64BIT
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 64;
- return __ffs(b[2]) + 128;
-#endif
-}
-
-/*
- * hweightN - returns the hamming weight of a N-bit word
- * @x: the word to weigh
- *
- * The Hamming Weight of a number is the total number of bits set in it.
- */
-
-#define hweight64(x) generic_hweight64(x)
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
-
-static inline int __test_and_set_le_bit(unsigned long nr, unsigned long *addr)
-{
- unsigned char *ADDR = (unsigned char *) addr;
- int mask, retval;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- retval = (mask & *ADDR) != 0;
- *ADDR |= mask;
-
- return retval;
-}
-
-static inline int __test_and_clear_le_bit(unsigned long nr, unsigned long *addr)
-{
- unsigned char *ADDR = (unsigned char *) addr;
- int mask, retval;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- retval = (mask & *ADDR) != 0;
- *ADDR &= ~mask;
-
- return retval;
-}
-
-static inline int test_le_bit(unsigned long nr, const unsigned long * addr)
-{
- const unsigned char *ADDR = (const unsigned char *) addr;
- int mask;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
-
- return ((mask & *ADDR) != 0);
-}
-
-static inline unsigned long find_next_zero_le_bit(unsigned long *addr,
- unsigned long size, unsigned long offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> SZLONG_LOG);
- unsigned long result = offset & ~SZLONG_MASK;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= SZLONG_MASK;
- if (offset) {
- tmp = cpu_to_lelongp(p++);
- tmp |= ~0UL >> (_MIPS_SZLONG-offset); /* bug or feature ? */
- if (size < _MIPS_SZLONG)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= _MIPS_SZLONG;
- result += _MIPS_SZLONG;
- }
- while (size & ~SZLONG_MASK) {
- if (~(tmp = cpu_to_lelongp(p++)))
- goto found_middle;
- result += _MIPS_SZLONG;
- size -= _MIPS_SZLONG;
- }
- if (!size)
- return result;
- tmp = cpu_to_lelongp(p);
-
-found_first:
- tmp |= ~0UL << size;
- if (tmp == ~0UL) /* Are any bits zero? */
- return result + size; /* Nope. */
-
-found_middle:
- return result + ffz(tmp);
-}
-
-#define find_first_zero_le_bit(addr, size) \
- find_next_zero_le_bit((addr), (size), 0)
-
-#define ext2_set_bit(nr,addr) \
- __test_and_set_le_bit((nr),(unsigned long*)addr)
-#define ext2_clear_bit(nr, addr) \
- __test_and_clear_le_bit((nr),(unsigned long*)addr)
- #define ext2_set_bit_atomic(lock, nr, addr) \
-({ \
- int ret; \
- spin_lock(lock); \
- ret = ext2_set_bit((nr), (addr)); \
- spin_unlock(lock); \
- ret; \
-})
-
-#define ext2_clear_bit_atomic(lock, nr, addr) \
-({ \
- int ret; \
- spin_lock(lock); \
- ret = ext2_clear_bit((nr), (addr)); \
- spin_unlock(lock); \
- ret; \
-})
-#define ext2_test_bit(nr, addr) test_le_bit((nr),(unsigned long*)addr)
-#define ext2_find_first_zero_bit(addr, size) \
- find_first_zero_le_bit((unsigned long*)addr, size)
-#define ext2_find_next_zero_bit(addr, size, off) \
- find_next_zero_le_bit((unsigned long*)addr, size, off)
-
-/*
- * Bitmap functions for the minix filesystem.
- *
- * FIXME: These assume that Minix uses the native byte/bitorder.
- * This limits the Minix filesystem's value for data exchange very much.
- */
-#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+#include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
index 0012bd804d2..986511db54a 100644
--- a/include/asm-mips/compat.h
+++ b/include/asm-mips/compat.h
@@ -133,6 +133,11 @@ static inline void __user *compat_ptr(compat_uptr_t uptr)
return (void __user *)(long)uptr;
}
+static inline compat_uptr_t ptr_to_compat(void __user *uptr)
+{
+ return (u32)(unsigned long)uptr;
+}
+
static inline void __user *compat_alloc_user_space(long len)
{
struct pt_regs *regs = (struct pt_regs *)
diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h
index 2454c44a8f5..a554089991f 100644
--- a/include/asm-mips/futex.h
+++ b/include/asm-mips/futex.h
@@ -99,5 +99,11 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
return ret;
}
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ return -ENOSYS;
+}
+
#endif
#endif
diff --git a/include/asm-mips/mc146818-time.h b/include/asm-mips/mc146818-time.h
index 47214861093..41ac8d363c6 100644
--- a/include/asm-mips/mc146818-time.h
+++ b/include/asm-mips/mc146818-time.h
@@ -86,43 +86,14 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime)
return retval;
}
-/*
- * Returns true if a clock update is in progress
- */
-static inline unsigned char rtc_is_updating(void)
-{
- unsigned char uip;
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
- spin_unlock_irqrestore(&rtc_lock, flags);
- return uip;
-}
-
static inline unsigned long mc146818_get_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- int i;
unsigned long flags;
- /*
- * The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
-
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (rtc_is_updating())
- break;
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!rtc_is_updating())
- break;
-
spin_lock_irqsave(&rtc_lock, flags);
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
+
+ do {
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
hour = CMOS_READ(RTC_HOURS);
diff --git a/include/asm-mips/mmzone.h b/include/asm-mips/mmzone.h
index 011caebac36..7bde4432092 100644
--- a/include/asm-mips/mmzone.h
+++ b/include/asm-mips/mmzone.h
@@ -22,20 +22,6 @@
NODE_DATA(__n)->node_spanned_pages) : 0);\
})
-#define pfn_to_page(pfn) \
-({ \
- unsigned long __pfn = (pfn); \
- pg_data_t *__pg = NODE_DATA(pfn_to_nid(__pfn)); \
- __pg->node_mem_map + (__pfn - __pg->node_start_pfn); \
-})
-
-#define page_to_pfn(p) \
-({ \
- struct page *__p = (p); \
- struct zone *__z = page_zone(__p); \
- ((__p - __z->zone_mem_map) + __z->zone_start_pfn); \
-})
-
/* XXX: FIXME -- wli */
#define kern_addr_valid(addr) (0)
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index ee25a779bf4..a1eab136ff6 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -140,8 +140,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
#ifndef CONFIG_NEED_MULTIPLE_NODES
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#endif
@@ -160,6 +158,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define WANT_PAGE_VIRTUAL
#endif
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _ASM_PAGE_H */
diff --git a/include/asm-mips/poll.h b/include/asm-mips/poll.h
index a000f1f789e..70881f8c5c5 100644
--- a/include/asm-mips/poll.h
+++ b/include/asm-mips/poll.h
@@ -17,6 +17,7 @@
/* These seem to be more or less nonstandard ... */
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h
index e796d75f027..7b236641220 100644
--- a/include/asm-mips/serial.h
+++ b/include/asm-mips/serial.h
@@ -103,88 +103,6 @@
#define IVR_SERIAL_PORT_DEFNS
#endif
-#ifdef CONFIG_SERIAL_AU1X00
-#include <asm/mach-au1x00/au1000.h>
-#ifdef CONFIG_SOC_AU1000
-#define AU1000_SERIAL_PORT_DEFNS \
- { .baud_base = 0, .port = UART0_ADDR, \
- .iomem_base = (unsigned char *)UART0_ADDR, \
- .irq = AU1000_UART0_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART1_ADDR, \
- .iomem_base = (unsigned char *)UART1_ADDR, \
- .irq = AU1000_UART1_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART2_ADDR, \
- .iomem_base = (unsigned char *)UART2_ADDR, \
- .irq = AU1000_UART2_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART3_ADDR, \
- .iomem_base = (unsigned char *)UART3_ADDR, \
- .irq = AU1000_UART3_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 },
-#endif
-
-#ifdef CONFIG_SOC_AU1500
-#define AU1000_SERIAL_PORT_DEFNS \
- { .baud_base = 0, .port = UART0_ADDR, \
- .iomem_base = (unsigned char *)UART0_ADDR, \
- .irq = AU1500_UART0_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART3_ADDR, \
- .iomem_base = (unsigned char *)UART3_ADDR, \
- .irq = AU1500_UART3_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 },
-#endif
-
-#ifdef CONFIG_SOC_AU1100
-#define AU1000_SERIAL_PORT_DEFNS \
- { .baud_base = 0, .port = UART0_ADDR, \
- .iomem_base = (unsigned char *)UART0_ADDR, \
- .irq = AU1100_UART0_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART1_ADDR, \
- .iomem_base = (unsigned char *)UART1_ADDR, \
- .irq = AU1100_UART1_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART3_ADDR, \
- .iomem_base = (unsigned char *)UART3_ADDR, \
- .irq = AU1100_UART3_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 },
-#endif
-
-#ifdef CONFIG_SOC_AU1550
-#define AU1000_SERIAL_PORT_DEFNS \
- { .baud_base = 0, .port = UART0_ADDR, \
- .iomem_base = (unsigned char *)UART0_ADDR, \
- .irq = AU1550_UART0_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART1_ADDR, \
- .iomem_base = (unsigned char *)UART1_ADDR, \
- .irq = AU1550_UART1_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART3_ADDR, \
- .iomem_base = (unsigned char *)UART3_ADDR, \
- .irq = AU1550_UART3_INT, .flags = STD_COM_FLAGS,\
- .iomem_reg_shift = 2 },
-#endif
-
-#ifdef CONFIG_SOC_AU1200
-#define AU1000_SERIAL_PORT_DEFNS \
- { .baud_base = 0, .port = UART0_ADDR, \
- .iomem_base = (unsigned char *)UART0_ADDR, \
- .irq = AU1200_UART0_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 }, \
- { .baud_base = 0, .port = UART1_ADDR, \
- .iomem_base = (unsigned char *)UART1_ADDR, \
- .irq = AU1200_UART1_INT, .flags = STD_COM_FLAGS, \
- .iomem_reg_shift = 2 },
-#endif
-
-#else
-#define AU1000_SERIAL_PORT_DEFNS
-#endif
-
#ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT
#define STD_SERIAL_PORT_DEFNS \
/* UART CLK PORT IRQ FLAGS */ \
@@ -331,7 +249,6 @@
MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS \
MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS \
MOMENCO_OCELOT_SERIAL_PORT_DEFNS \
- MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS \
- AU1000_SERIAL_PORT_DEFNS
+ MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS
#endif /* _ASM_SERIAL_H */
diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h
index 9cc3564cc2c..d897c8bb554 100644
--- a/include/asm-mips/time.h
+++ b/include/asm-mips/time.h
@@ -26,14 +26,14 @@ extern spinlock_t rtc_lock;
/*
* RTC ops. By default, they point to no-RTC functions.
- * rtc_get_time - mktime(year, mon, day, hour, min, sec) in seconds.
- * rtc_set_time - reverse the above translation and set time to RTC.
- * rtc_set_mmss - similar to rtc_set_time, but only min and sec need
+ * rtc_mips_get_time - mktime(year, mon, day, hour, min, sec) in seconds.
+ * rtc_mips_set_time - reverse the above translation and set time to RTC.
+ * rtc_mips_set_mmss - similar to rtc_set_time, but only min and sec need
* to be set. Used by RTC sync-up.
*/
-extern unsigned long (*rtc_get_time)(void);
-extern int (*rtc_set_time)(unsigned long);
-extern int (*rtc_set_mmss)(unsigned long);
+extern unsigned long (*rtc_mips_get_time)(void);
+extern int (*rtc_mips_set_time)(unsigned long);
+extern int (*rtc_mips_set_mmss)(unsigned long);
/*
* Timer interrupt functions.
diff --git a/include/asm-mips/types.h b/include/asm-mips/types.h
index 421b3aea14c..cd2813d8e13 100644
--- a/include/asm-mips/types.h
+++ b/include/asm-mips/types.h
@@ -99,6 +99,11 @@ typedef u64 sector_t;
#define HAVE_SECTOR_T
#endif
+#ifdef CONFIG_LSF
+typedef u64 blkcnt_t;
+#define HAVE_BLKCNT_T
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h
index 15d8c2b5158..900561922c4 100644
--- a/include/asm-parisc/bitops.h
+++ b/include/asm-parisc/bitops.h
@@ -35,13 +35,6 @@ static __inline__ void set_bit(int nr, volatile unsigned long * addr)
_atomic_spin_unlock_irqrestore(addr, flags);
}
-static __inline__ void __set_bit(unsigned long nr, volatile unsigned long * addr)
-{
- unsigned long *m = (unsigned long *) addr + (nr >> SHIFT_PER_LONG);
-
- *m |= 1UL << CHOP_SHIFTCOUNT(nr);
-}
-
static __inline__ void clear_bit(int nr, volatile unsigned long * addr)
{
unsigned long mask = ~(1UL << CHOP_SHIFTCOUNT(nr));
@@ -53,13 +46,6 @@ static __inline__ void clear_bit(int nr, volatile unsigned long * addr)
_atomic_spin_unlock_irqrestore(addr, flags);
}
-static __inline__ void __clear_bit(unsigned long nr, volatile unsigned long * addr)
-{
- unsigned long *m = (unsigned long *) addr + (nr >> SHIFT_PER_LONG);
-
- *m &= ~(1UL << CHOP_SHIFTCOUNT(nr));
-}
-
static __inline__ void change_bit(int nr, volatile unsigned long * addr)
{
unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
@@ -71,13 +57,6 @@ static __inline__ void change_bit(int nr, volatile unsigned long * addr)
_atomic_spin_unlock_irqrestore(addr, flags);
}
-static __inline__ void __change_bit(unsigned long nr, volatile unsigned long * addr)
-{
- unsigned long *m = (unsigned long *) addr + (nr >> SHIFT_PER_LONG);
-
- *m ^= 1UL << CHOP_SHIFTCOUNT(nr);
-}
-
static __inline__ int test_and_set_bit(int nr, volatile unsigned long * addr)
{
unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
@@ -93,18 +72,6 @@ static __inline__ int test_and_set_bit(int nr, volatile unsigned long * addr)
return (oldbit & mask) ? 1 : 0;
}
-static __inline__ int __test_and_set_bit(int nr, volatile unsigned long * address)
-{
- unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
- unsigned long oldbit;
- unsigned long *addr = (unsigned long *)address + (nr >> SHIFT_PER_LONG);
-
- oldbit = *addr;
- *addr = oldbit | mask;
-
- return (oldbit & mask) ? 1 : 0;
-}
-
static __inline__ int test_and_clear_bit(int nr, volatile unsigned long * addr)
{
unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
@@ -120,18 +87,6 @@ static __inline__ int test_and_clear_bit(int nr, volatile unsigned long * addr)
return (oldbit & mask) ? 1 : 0;
}
-static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long * address)
-{
- unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
- unsigned long *addr = (unsigned long *)address + (nr >> SHIFT_PER_LONG);
- unsigned long oldbit;
-
- oldbit = *addr;
- *addr = oldbit & ~mask;
-
- return (oldbit & mask) ? 1 : 0;
-}
-
static __inline__ int test_and_change_bit(int nr, volatile unsigned long * addr)
{
unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
@@ -147,25 +102,7 @@ static __inline__ int test_and_change_bit(int nr, volatile unsigned long * addr)
return (oldbit & mask) ? 1 : 0;
}
-static __inline__ int __test_and_change_bit(int nr, volatile unsigned long * address)
-{
- unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
- unsigned long *addr = (unsigned long *)address + (nr >> SHIFT_PER_LONG);
- unsigned long oldbit;
-
- oldbit = *addr;
- *addr = oldbit ^ mask;
-
- return (oldbit & mask) ? 1 : 0;
-}
-
-static __inline__ int test_bit(int nr, const volatile unsigned long *address)
-{
- unsigned long mask = 1UL << CHOP_SHIFTCOUNT(nr);
- const unsigned long *addr = (const unsigned long *)address + (nr >> SHIFT_PER_LONG);
-
- return !!(*addr & mask);
-}
+#include <asm-generic/bitops/non-atomic.h>
#ifdef __KERNEL__
@@ -219,8 +156,7 @@ static __inline__ unsigned long __ffs(unsigned long x)
return ret;
}
-/* Undefined if no bit is zero. */
-#define ffz(x) __ffs(~x)
+#include <asm-generic/bitops/ffz.h>
/*
* ffs: find first bit set. returns 1 to BITS_PER_LONG or 0 (if none set)
@@ -263,155 +199,22 @@ static __inline__ int fls(int x)
return ret;
}
-#define fls64(x) generic_fls64(x)
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-#define hweight64(x) generic_hweight64(x)
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
-
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-static inline int sched_find_first_bit(const unsigned long *b)
-{
-#ifdef __LP64__
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 64;
- return __ffs(b[2]) + 128;
-#else
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
-#endif
-}
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/sched.h>
#endif /* __KERNEL__ */
-/*
- * This implementation of find_{first,next}_zero_bit was stolen from
- * Linus' asm-alpha/bitops.h.
- */
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
-
-static __inline__ unsigned long find_next_zero_bit(const void * addr, unsigned long size, unsigned long offset)
-{
- const unsigned long * p = ((unsigned long *) addr) + (offset >> SHIFT_PER_LONG);
- unsigned long result = offset & ~(BITS_PER_LONG-1);
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= (BITS_PER_LONG-1);
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (BITS_PER_LONG-offset);
- if (size < BITS_PER_LONG)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= BITS_PER_LONG;
- result += BITS_PER_LONG;
- }
- while (size & ~(BITS_PER_LONG -1)) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- }
- if (!size)
- return result;
- tmp = *p;
-found_first:
- tmp |= ~0UL << size;
-found_middle:
- return result + ffz(tmp);
-}
-
-static __inline__ unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset)
-{
- const unsigned long *p = addr + (offset >> SHIFT_PER_LONG);
- unsigned long result = offset & ~(BITS_PER_LONG-1);
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= (BITS_PER_LONG-1);
- if (offset) {
- tmp = *(p++);
- tmp &= (~0UL << offset);
- if (size < BITS_PER_LONG)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= BITS_PER_LONG;
- result += BITS_PER_LONG;
- }
- while (size & ~(BITS_PER_LONG-1)) {
- if ((tmp = *(p++)))
- goto found_middle;
- result += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp &= (~0UL >> (BITS_PER_LONG - size));
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
-found_middle:
- return result + __ffs(tmp);
-}
-
-/**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first set bit, not the number of the byte
- * containing a bit.
- */
-#define find_first_bit(addr, size) \
- find_next_bit((addr), (size), 0)
-
-#define _EXT2_HAVE_ASM_BITOPS_
+#include <asm-generic/bitops/find.h>
#ifdef __KERNEL__
-/*
- * test_and_{set,clear}_bit guarantee atomicity without
- * disabling interrupts.
- */
+
+#include <asm-generic/bitops/ext2-non-atomic.h>
/* '3' is bits per byte */
#define LE_BYTE_ADDR ((sizeof(unsigned long) - 1) << 3)
-#define ext2_test_bit(nr, addr) \
- test_bit((nr) ^ LE_BYTE_ADDR, (unsigned long *)addr)
-#define ext2_set_bit(nr, addr) \
- __test_and_set_bit((nr) ^ LE_BYTE_ADDR, (unsigned long *)addr)
-#define ext2_clear_bit(nr, addr) \
- __test_and_clear_bit((nr) ^ LE_BYTE_ADDR, (unsigned long *)addr)
-
#define ext2_set_bit_atomic(l,nr,addr) \
test_and_set_bit((nr) ^ LE_BYTE_ADDR, (unsigned long *)addr)
#define ext2_clear_bit_atomic(l,nr,addr) \
@@ -419,77 +222,6 @@ found_middle:
#endif /* __KERNEL__ */
-
-#define ext2_find_first_zero_bit(addr, size) \
- ext2_find_next_zero_bit((addr), (size), 0)
-
-/* include/linux/byteorder does not support "unsigned long" type */
-static inline unsigned long ext2_swabp(unsigned long * x)
-{
-#ifdef __LP64__
- return (unsigned long) __swab64p((u64 *) x);
-#else
- return (unsigned long) __swab32p((u32 *) x);
-#endif
-}
-
-/* include/linux/byteorder doesn't support "unsigned long" type */
-static inline unsigned long ext2_swab(unsigned long y)
-{
-#ifdef __LP64__
- return (unsigned long) __swab64((u64) y);
-#else
- return (unsigned long) __swab32((u32) y);
-#endif
-}
-
-static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
-{
- unsigned long *p = (unsigned long *) addr + (offset >> SHIFT_PER_LONG);
- unsigned long result = offset & ~(BITS_PER_LONG - 1);
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= (BITS_PER_LONG - 1UL);
- if (offset) {
- tmp = ext2_swabp(p++);
- tmp |= (~0UL >> (BITS_PER_LONG - offset));
- if (size < BITS_PER_LONG)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= BITS_PER_LONG;
- result += BITS_PER_LONG;
- }
-
- while (size & ~(BITS_PER_LONG - 1)) {
- if (~(tmp = *(p++)))
- goto found_middle_swap;
- result += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- }
- if (!size)
- return result;
- tmp = ext2_swabp(p);
-found_first:
- tmp |= ~0UL << size;
- if (tmp == ~0UL) /* Are any bits zero? */
- return result + size; /* Nope. Skip ffz */
-found_middle:
- return result + ffz(tmp);
-
-found_middle_swap:
- return result + ffz(ext2_swab(tmp));
-}
-
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) ext2_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) ((void)ext2_set_bit(nr,addr))
-#define minix_test_and_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) ext2_test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
+#include <asm-generic/bitops/minix-le.h>
#endif /* _PARISC_BITOPS_H */
diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h
index 38b918feead..289624d8b2d 100644
--- a/include/asm-parisc/compat.h
+++ b/include/asm-parisc/compat.h
@@ -138,6 +138,11 @@ static inline void __user *compat_ptr(compat_uptr_t uptr)
return (void __user *)(unsigned long)uptr;
}
+static inline compat_uptr_t ptr_to_compat(void __user *uptr)
+{
+ return (u32)(unsigned long)uptr;
+}
+
static __inline__ void __user *compat_alloc_user_space(long len)
{
struct pt_regs *regs = &current->thread.regs;
diff --git a/include/asm-parisc/mmzone.h b/include/asm-parisc/mmzone.h
index ae039f4fd71..ceb9b73199d 100644
--- a/include/asm-parisc/mmzone.h
+++ b/include/asm-parisc/mmzone.h
@@ -25,23 +25,6 @@ extern struct node_map_data node_data[];
pg_data_t *__pgdat = NODE_DATA(nid); \
__pgdat->node_start_pfn + __pgdat->node_spanned_pages; \
})
-#define node_localnr(pfn, nid) ((pfn) - node_start_pfn(nid))
-
-#define pfn_to_page(pfn) \
-({ \
- unsigned long __pfn = (pfn); \
- int __node = pfn_to_nid(__pfn); \
- &NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)]; \
-})
-
-#define page_to_pfn(pg) \
-({ \
- struct page *__page = pg; \
- struct zone *__zone = page_zone(__page); \
- BUG_ON(__zone == NULL); \
- (unsigned long)(__page - __zone->zone_mem_map) \
- + __zone->zone_start_pfn; \
-})
/* We have these possible memory map layouts:
* Astro: 0-3.75, 67.75-68, 4-64
diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h
index 4a6752b0afe..9f303c0c3cd 100644
--- a/include/asm-parisc/page.h
+++ b/include/asm-parisc/page.h
@@ -130,8 +130,6 @@ extern int npmem_ranges;
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
#ifndef CONFIG_DISCONTIGMEM
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#endif /* CONFIG_DISCONTIGMEM */
@@ -152,6 +150,7 @@ extern int npmem_ranges;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _PARISC_PAGE_H */
diff --git a/include/asm-parisc/pdc.h b/include/asm-parisc/pdc.h
index 8e23e4c674f..0a3face6c48 100644
--- a/include/asm-parisc/pdc.h
+++ b/include/asm-parisc/pdc.h
@@ -333,7 +333,7 @@ struct pdc_model { /* for PDC_MODEL */
unsigned long curr_key;
};
-/* Values for PDC_MODEL_CAPABILITES non-equivalent virtual aliasing support */
+/* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */
#define PDC_MODEL_IOPDIR_FDC (1 << 2) /* see sba_iommu.c */
#define PDC_MODEL_NVA_MASK (3 << 4)
diff --git a/include/asm-parisc/poll.h b/include/asm-parisc/poll.h
index 1c1da86934c..20e4d03c74c 100644
--- a/include/asm-parisc/poll.h
+++ b/include/asm-parisc/poll.h
@@ -16,6 +16,7 @@
#define POLLWRBAND 0x0200
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h
index bf6941a810b..d1c2a440566 100644
--- a/include/asm-powerpc/bitops.h
+++ b/include/asm-powerpc/bitops.h
@@ -184,72 +184,7 @@ static __inline__ void set_bits(unsigned long mask, unsigned long *addr)
: "cc");
}
-/* Non-atomic versions */
-static __inline__ int test_bit(unsigned long nr,
- __const__ volatile unsigned long *addr)
-{
- return 1UL & (addr[BITOP_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
-}
-
-static __inline__ void __set_bit(unsigned long nr,
- volatile unsigned long *addr)
-{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
-
- *p |= mask;
-}
-
-static __inline__ void __clear_bit(unsigned long nr,
- volatile unsigned long *addr)
-{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
-
- *p &= ~mask;
-}
-
-static __inline__ void __change_bit(unsigned long nr,
- volatile unsigned long *addr)
-{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
-
- *p ^= mask;
-}
-
-static __inline__ int __test_and_set_bit(unsigned long nr,
- volatile unsigned long *addr)
-{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
- unsigned long old = *p;
-
- *p = old | mask;
- return (old & mask) != 0;
-}
-
-static __inline__ int __test_and_clear_bit(unsigned long nr,
- volatile unsigned long *addr)
-{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
- unsigned long old = *p;
-
- *p = old & ~mask;
- return (old & mask) != 0;
-}
-
-static __inline__ int __test_and_change_bit(unsigned long nr,
- volatile unsigned long *addr)
-{
- unsigned long mask = BITOP_MASK(nr);
- unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
- unsigned long old = *p;
-
- *p = old ^ mask;
- return (old & mask) != 0;
-}
+#include <asm-generic/bitops/non-atomic.h>
/*
* Return the zero-based bit position (LE, not IBM bit numbering) of
@@ -310,16 +245,9 @@ static __inline__ int fls(unsigned int x)
asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
return 32 - lz;
}
-#define fls64(x) generic_fls64(x)
+#include <asm-generic/bitops/fls64.h>
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-#define hweight64(x) generic_hweight64(x)
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/hweight.h>
#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
unsigned long find_next_zero_bit(const unsigned long *addr,
@@ -397,32 +325,7 @@ unsigned long find_next_zero_le_bit(const unsigned long *addr,
#define minix_find_first_zero_bit(addr,size) \
find_first_zero_le_bit((unsigned long *)addr, size)
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-static inline int sched_find_first_bit(const unsigned long *b)
-{
-#ifdef CONFIG_PPC64
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 64;
- return __ffs(b[2]) + 128;
-#else
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
-#endif
-}
+#include <asm-generic/bitops/sched.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h
index 99817a802ca..f44b529e329 100644
--- a/include/asm-powerpc/bug.h
+++ b/include/asm-powerpc/bug.h
@@ -30,34 +30,60 @@ struct bug_entry *find_bug(unsigned long bugaddr);
#ifdef CONFIG_BUG
+/*
+ * BUG_ON() and WARN_ON() do their best to cooperate with compile-time
+ * optimisations. However depending on the complexity of the condition
+ * some compiler versions may not produce optimal results.
+ */
+
#define BUG() do { \
__asm__ __volatile__( \
"1: twi 31,0,0\n" \
".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%0,%1,%2\n" \
+ "\t"PPC_LONG" 1b,%0,%1,%2\n" \
".previous" \
: : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \
} while (0)
#define BUG_ON(x) do { \
- __asm__ __volatile__( \
+ if (__builtin_constant_p(x)) { \
+ if (x) \
+ BUG(); \
+ } else { \
+ __asm__ __volatile__( \
"1: "PPC_TLNEI" %0,0\n" \
".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%1,%2,%3\n" \
+ "\t"PPC_LONG" 1b,%1,%2,%3\n" \
".previous" \
: : "r" ((long)(x)), "i" (__LINE__), \
"i" (__FILE__), "i" (__FUNCTION__)); \
+ } \
} while (0)
-#define WARN_ON(x) do { \
+#define __WARN() do { \
__asm__ __volatile__( \
+ "1: twi 31,0,0\n" \
+ ".section __bug_table,\"a\"\n" \
+ "\t"PPC_LONG" 1b,%0,%1,%2\n" \
+ ".previous" \
+ : : "i" (__LINE__ + BUG_WARNING_TRAP), \
+ "i" (__FILE__), "i" (__FUNCTION__)); \
+} while (0)
+
+#define WARN_ON(x) do { \
+ if (__builtin_constant_p(x)) { \
+ if (x) \
+ __WARN(); \
+ } else { \
+ __asm__ __volatile__( \
"1: "PPC_TLNEI" %0,0\n" \
".section __bug_table,\"a\"\n" \
- "\t"PPC_LONG" 1b,%1,%2,%3\n" \
+ "\t"PPC_LONG" 1b,%1,%2,%3\n" \
".previous" \
: : "r" ((long)(x)), \
"i" (__LINE__ + BUG_WARNING_TRAP), \
"i" (__FILE__), "i" (__FUNCTION__)); \
+ } \
} while (0)
#define HAVE_ARCH_BUG
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index fe45f6f3a4b..4321483cce5 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -188,153 +188,154 @@ extern void do_cpu_ftr_fixups(unsigned long offset);
!defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
!defined(CONFIG_BOOKE))
-enum {
- CPU_FTRS_PPC601 = CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE,
- CPU_FTRS_603 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
- CPU_FTR_MAYBE_CAN_NAP,
- CPU_FTRS_604 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE,
- CPU_FTRS_740_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
- CPU_FTRS_740 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
- CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
- CPU_FTRS_750 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
- CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
- CPU_FTRS_750FX1 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
- CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
- CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM,
- CPU_FTRS_750FX2 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
- CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
- CPU_FTR_NO_DPM,
- CPU_FTRS_750FX = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
- CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
- CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS,
- CPU_FTRS_750GX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
- CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS,
- CPU_FTRS_7400_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
- CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
- CPU_FTR_MAYBE_CAN_NAP,
- CPU_FTRS_7400 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
- CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
- CPU_FTR_MAYBE_CAN_NAP,
- CPU_FTRS_7450_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
- CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
- CPU_FTR_NEED_COHERENT,
- CPU_FTRS_7450_21 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB |
- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
- CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP |
- CPU_FTR_NEED_COHERENT,
- CPU_FTRS_7450_23 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB |
- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
- CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT,
- CPU_FTRS_7455_1 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB |
- CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
- CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS |
- CPU_FTR_NEED_COHERENT,
- CPU_FTRS_7455_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB |
- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
- CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP |
- CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS,
- CPU_FTRS_7455 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB |
- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
- CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
- CPU_FTR_NEED_COHERENT,
- CPU_FTRS_7447_10 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB |
- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
- CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
- CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC,
- CPU_FTRS_7447 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB |
- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
- CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
- CPU_FTR_NEED_COHERENT,
- CPU_FTRS_7447A = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB |
- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
- CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
- CPU_FTR_NEED_COHERENT,
- CPU_FTRS_82XX = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB,
- CPU_FTRS_G2_LE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
- CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
- CPU_FTRS_E300 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
- CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS |
- CPU_FTR_COMMON,
- CPU_FTRS_CLASSIC32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
- CPU_FTRS_POWER3_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
- CPU_FTRS_POWER4_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_NODSISRALIGN,
- CPU_FTRS_970_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
- CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_ALTIVEC_COMP |
- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN,
- CPU_FTRS_8XX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
- CPU_FTRS_40X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_NODSISRALIGN,
- CPU_FTRS_44X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_NODSISRALIGN,
- CPU_FTRS_E200 = CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN,
- CPU_FTRS_E500 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_NODSISRALIGN,
- CPU_FTRS_E500_2 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN,
- CPU_FTRS_GENERIC_32 = CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN,
+#define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE)
+#define CPU_FTRS_603 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
+ CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_604 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE)
+#define CPU_FTRS_740_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_740 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_750 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_750FX1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM)
+#define CPU_FTRS_750FX2 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+ CPU_FTR_NO_DPM)
+#define CPU_FTRS_750FX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_750GX (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_7400_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
+ CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_7400 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+ CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
+ CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_7450_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+ CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_7450_21 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | \
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
+ CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_7450_23 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | \
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_7455_1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | \
+ CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \
+ CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_7455_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | \
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
+ CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_7455 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | \
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
+ CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_7447_10 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | \
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
+ CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC)
+#define CPU_FTRS_7447 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | \
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
+ CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_7447A (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | \
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
+ CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_82XX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
+#define CPU_FTRS_G2_LE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+ CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_E300 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+ CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
+ CPU_FTR_COMMON)
+#define CPU_FTRS_CLASSIC32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
+#define CPU_FTRS_POWER3_32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
+#define CPU_FTRS_POWER4_32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_970_32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_ALTIVEC_COMP | \
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_8XX (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB)
+#define CPU_FTRS_40X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_44X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E500 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E500_2 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
#ifdef __powerpc64__
- CPU_FTRS_POWER3 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_IABR,
- CPU_FTRS_RS64 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
- CPU_FTR_MMCRA | CPU_FTR_CTRL,
- CPU_FTRS_POWER4 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA,
- CPU_FTRS_PPC970 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 |
- CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA,
- CPU_FTRS_POWER5 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 |
- CPU_FTR_MMCRA | CPU_FTR_SMT |
- CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
- CPU_FTR_MMCRA_SIHV | CPU_FTR_PURR,
- CPU_FTRS_CELL = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 |
- CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT |
- CPU_FTR_CTRL | CPU_FTR_PAUSE_ZERO,
- CPU_FTRS_COMPATIBLE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
- CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2,
+#define CPU_FTRS_POWER3 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_IABR)
+#define CPU_FTRS_RS64 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
+ CPU_FTR_MMCRA | CPU_FTR_CTRL)
+#define CPU_FTRS_POWER4 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA)
+#define CPU_FTRS_PPC970 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
+#define CPU_FTRS_POWER5 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+ CPU_FTR_MMCRA | CPU_FTR_SMT | \
+ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
+ CPU_FTR_MMCRA_SIHV | CPU_FTR_PURR)
+#define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
+ CPU_FTR_CTRL | CPU_FTR_PAUSE_ZERO)
+#define CPU_FTRS_COMPATIBLE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
#endif
- CPU_FTRS_POSSIBLE =
#ifdef __powerpc64__
- CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |
- CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_CELL |
- CPU_FTR_CI_LARGE_PAGE |
+#define CPU_FTRS_POSSIBLE \
+ (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | \
+ CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_CELL | \
+ CPU_FTR_CI_LARGE_PAGE)
#else
+enum {
+ CPU_FTRS_POSSIBLE =
#if CLASSIC_PPC
CPU_FTRS_PPC601 | CPU_FTRS_603 | CPU_FTRS_604 | CPU_FTRS_740_NOTAU |
CPU_FTRS_740 | CPU_FTRS_750 | CPU_FTRS_750FX1 |
@@ -368,14 +369,18 @@ enum {
#ifdef CONFIG_E500
CPU_FTRS_E500 | CPU_FTRS_E500_2 |
#endif
-#endif /* __powerpc64__ */
0,
+};
+#endif /* __powerpc64__ */
- CPU_FTRS_ALWAYS =
#ifdef __powerpc64__
- CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 &
- CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_CELL &
+#define CPU_FTRS_ALWAYS \
+ (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 & \
+ CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_CELL & \
+ CPU_FTRS_POSSIBLE)
#else
+enum {
+ CPU_FTRS_ALWAYS =
#if CLASSIC_PPC
CPU_FTRS_PPC601 & CPU_FTRS_603 & CPU_FTRS_604 & CPU_FTRS_740_NOTAU &
CPU_FTRS_740 & CPU_FTRS_750 & CPU_FTRS_750FX1 &
@@ -409,9 +414,9 @@ enum {
#ifdef CONFIG_E500
CPU_FTRS_E500 & CPU_FTRS_E500_2 &
#endif
-#endif /* __powerpc64__ */
CPU_FTRS_POSSIBLE,
};
+#endif /* __powerpc64__ */
static inline int cpu_has_feature(unsigned long feature)
{
diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h
index ce3788224ed..77069df92bf 100644
--- a/include/asm-powerpc/firmware.h
+++ b/include/asm-powerpc/firmware.h
@@ -82,13 +82,11 @@ enum {
/* This is used to identify firmware features which are available
* to the kernel.
*/
-extern unsigned long ppc64_firmware_features;
+extern unsigned long powerpc_firmware_features;
-static inline unsigned long firmware_has_feature(unsigned long feature)
-{
- return (FW_FEATURE_ALWAYS & feature) ||
- (FW_FEATURE_POSSIBLE & ppc64_firmware_features & feature);
-}
+#define firmware_has_feature(feature) \
+ ((FW_FEATURE_ALWAYS & (feature)) || \
+ (FW_FEATURE_POSSIBLE & powerpc_firmware_features & (feature)))
extern void system_reset_fwnmi(void);
extern void machine_check_fwnmi(void);
diff --git a/include/asm-powerpc/floppy.h b/include/asm-powerpc/floppy.h
index e258778ca42..608164c39ef 100644
--- a/include/asm-powerpc/floppy.h
+++ b/include/asm-powerpc/floppy.h
@@ -35,6 +35,7 @@
#ifdef CONFIG_PCI
#include <linux/pci.h>
+#include <asm/ppc-pci.h> /* for ppc64_isabridge_dev */
#define fd_dma_setup(addr,size,mode,io) powerpc_fd_dma_setup(addr,size,mode,io)
@@ -52,12 +53,12 @@ static __inline__ int powerpc_fd_dma_setup(char *addr, unsigned long size,
if (bus_addr
&& (addr != prev_addr || size != prev_size || dir != prev_dir)) {
/* different from last time -- unmap prev */
- pci_unmap_single(NULL, bus_addr, prev_size, prev_dir);
+ pci_unmap_single(ppc64_isabridge_dev, bus_addr, prev_size, prev_dir);
bus_addr = 0;
}
if (!bus_addr) /* need to map it */
- bus_addr = pci_map_single(NULL, addr, size, dir);
+ bus_addr = pci_map_single(ppc64_isabridge_dev, addr, size, dir);
/* remember this one as prev */
prev_addr = addr;
diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h
index 39e85f320a7..f1b3c00bc1c 100644
--- a/include/asm-powerpc/futex.h
+++ b/include/asm-powerpc/futex.h
@@ -81,5 +81,11 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
return ret;
}
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ return -ENOSYS;
+}
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_FUTEX_H */
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index 38ca9ad6110..b72c04f3f55 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -9,6 +9,7 @@
#define H_Closed 2 /* Resource closed */
#define H_Constrained 4 /* Resource request constrained to max allowed */
#define H_InProgress 14 /* Kind of like busy */
+#define H_Pending 17 /* returned from H_POLL_PENDING */
#define H_Continue 18 /* Returned from H_Join on success */
#define H_LongBusyStartRange 9900 /* Start of long busy range */
#define H_LongBusyOrder1msec 9900 /* Long busy, hint that 1msec is a good time to retry */
diff --git a/include/asm-powerpc/hvconsole.h b/include/asm-powerpc/hvconsole.h
index 34daf7b9b62..35ea69e8121 100644
--- a/include/asm-powerpc/hvconsole.h
+++ b/include/asm-powerpc/hvconsole.h
@@ -24,28 +24,18 @@
#ifdef __KERNEL__
/*
- * This is the max number of console adapters that can/will be found as
- * console devices on first stage console init. Any number beyond this range
- * can't be used as a console device but is still a valid tty device.
+ * PSeries firmware will only send/recv up to 16 bytes of character data per
+ * hcall.
*/
-#define MAX_NR_HVC_CONSOLES 16
+#define MAX_VIO_PUT_CHARS 16
+#define SIZE_VIO_GET_CHARS 16
-/* implemented by a low level driver */
-struct hv_ops {
- int (*get_chars)(uint32_t vtermno, char *buf, int count);
- int (*put_chars)(uint32_t vtermno, const char *buf, int count);
-};
+/*
+ * Vio firmware always attempts to fetch MAX_VIO_GET_CHARS chars. The 'count'
+ * parm is included to conform to put_chars() function pointer template
+ */
extern int hvc_get_chars(uint32_t vtermno, char *buf, int count);
extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count);
-struct hvc_struct;
-
-/* Register a vterm and a slot index for use as a console (console_init) */
-extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops);
-/* register a vterm for hvc tty operation (module_init or hotplug add) */
-extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq,
- struct hv_ops *ops);
-/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */
-extern int __devexit hvc_remove(struct hvc_struct *hp);
#endif /* __KERNEL__ */
#endif /* _PPC64_HVCONSOLE_H */
diff --git a/include/asm-powerpc/kdebug.h b/include/asm-powerpc/kdebug.h
index 7c16265568e..c01786ab5fa 100644
--- a/include/asm-powerpc/kdebug.h
+++ b/include/asm-powerpc/kdebug.h
@@ -16,13 +16,9 @@ struct die_args {
int signr;
};
-/*
- Note - you should never unregister because that can race with NMIs.
- If you really want to do it first unregister - then synchronize_sched -
- then free.
- */
-int register_die_notifier(struct notifier_block *nb);
-extern struct notifier_block *powerpc_die_chain;
+extern int register_die_notifier(struct notifier_block *);
+extern int unregister_die_notifier(struct notifier_block *);
+extern struct atomic_notifier_head powerpc_die_chain;
/* Grossly misnamed. */
enum die_val {
@@ -37,7 +33,7 @@ enum die_val {
static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig)
{
struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig };
- return notifier_call_chain(&powerpc_die_chain, val, &args);
+ return atomic_notifier_call_chain(&powerpc_die_chain, val, &args);
}
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 5348b820788..5ed84768075 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -47,6 +47,7 @@ struct smp_ops_t {
#endif
struct machdep_calls {
+ char *name;
#ifdef CONFIG_PPC64
void (*hpte_invalidate)(unsigned long slot,
unsigned long va,
@@ -85,9 +86,9 @@ struct machdep_calls {
void (*iommu_dev_setup)(struct pci_dev *dev);
void (*iommu_bus_setup)(struct pci_bus *bus);
void (*irq_bus_setup)(struct pci_bus *bus);
-#endif
+#endif /* CONFIG_PPC64 */
- int (*probe)(int platform);
+ int (*probe)(void);
void (*setup_arch)(void);
void (*init_early)(void);
/* Optional, may be NULL. */
@@ -158,6 +159,12 @@ struct machdep_calls {
/* Idle loop for this platform, leave empty for default idle loop */
void (*idle_loop)(void);
+ /*
+ * Function for waiting for work with reduced power in idle loop;
+ * called with interrupts disabled.
+ */
+ void (*power_save)(void);
+
/* Function to enable performance monitor counters for this
platform, called once per cpu. */
void (*enable_pmcs)(void);
@@ -170,13 +177,6 @@ struct machdep_calls {
May be NULL. */
void (*init)(void);
- void (*idle)(void);
- void (*power_save)(void);
-
- void (*heartbeat)(void);
- unsigned long heartbeat_reset;
- unsigned long heartbeat_count;
-
void (*setup_io_mappings)(void);
void (*early_serial_map)(void);
@@ -208,8 +208,6 @@ struct machdep_calls {
/* Called at then very end of pcibios_init() */
void (*pcibios_after_init)(void);
- /* this is for modules, since _machine can be a define -- Cort */
- int ppc_machine;
#endif /* CONFIG_PPC32 */
/* Called to shutdown machine specific hardware not already controlled
@@ -242,10 +240,29 @@ struct machdep_calls {
#endif /* CONFIG_KEXEC */
};
-extern void default_idle(void);
-extern void native_idle(void);
+extern void power4_idle(void);
+extern void ppc6xx_idle(void);
+/*
+ * ppc_md contains a copy of the machine description structure for the
+ * current platform. machine_id contains the initial address where the
+ * description was found during boot.
+ */
extern struct machdep_calls ppc_md;
+extern struct machdep_calls *machine_id;
+
+#define __machine_desc __attribute__ ((__section__ (".machine.desc")))
+
+#define define_machine(name) struct machdep_calls mach_##name __machine_desc =
+#define machine_is(name) \
+ ({ \
+ extern struct machdep_calls mach_##name \
+ __attribute__((weak)); \
+ machine_id == &mach_##name; \
+ })
+
+extern void probe_machine(void);
+
extern char cmd_line[COMMAND_LINE_SIZE];
#ifdef CONFIG_PPC_PMAC
diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h
index 338e6a7cff4..5b33994cd48 100644
--- a/include/asm-powerpc/oprofile_impl.h
+++ b/include/asm-powerpc/oprofile_impl.h
@@ -17,9 +17,6 @@
/* Per-counter configuration as set via oprofilefs. */
struct op_counter_config {
-#ifdef __powerpc64__
- unsigned long valid;
-#endif
unsigned long enabled;
unsigned long event;
unsigned long count;
@@ -38,9 +35,6 @@ struct op_system_config {
#endif
unsigned long enable_kernel;
unsigned long enable_user;
-#ifdef CONFIG_PPC64
- unsigned long backtrace_spinlocks;
-#endif
};
/* Per-arch configuration */
@@ -56,17 +50,12 @@ struct op_powerpc_model {
int num_counters;
};
-#ifdef CONFIG_FSL_BOOKE
extern struct op_powerpc_model op_model_fsl_booke;
-#else /* Otherwise, it's classic */
-
-#ifdef CONFIG_PPC64
extern struct op_powerpc_model op_model_rs64;
extern struct op_powerpc_model op_model_power4;
-
-#else /* Otherwise, CONFIG_PPC32 */
extern struct op_powerpc_model op_model_7450;
-#endif
+
+#ifndef CONFIG_FSL_BOOKE
/* All the classic PPC parts use these */
static inline unsigned int ctr_read(unsigned int i)
@@ -134,5 +123,7 @@ static inline void ctr_write(unsigned int i, unsigned int val)
}
#endif /* !CONFIG_FSL_BOOKE */
+extern void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth);
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_OPROFILE_IMPL_H */
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h
index 4465b95ebef..706325f99a8 100644
--- a/include/asm-powerpc/paca.h
+++ b/include/asm-powerpc/paca.h
@@ -105,5 +105,7 @@ struct paca_struct {
extern struct paca_struct paca[];
+void setup_boot_paca(void);
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_PACA_H */
diff --git a/include/asm-powerpc/page.h b/include/asm-powerpc/page.h
index 0b82df483f7..2fbecebe1c9 100644
--- a/include/asm-powerpc/page.h
+++ b/include/asm-powerpc/page.h
@@ -69,8 +69,6 @@
#endif
#ifdef CONFIG_FLATMEM
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#endif
@@ -200,6 +198,7 @@ extern void copy_user_page(void *to, void *from, unsigned long vaddr,
struct page *p);
extern int page_is_ram(unsigned long pfn);
+#include <asm-generic/memory_model.h>
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/percpu.h b/include/asm-powerpc/percpu.h
index 464301cd0d0..184a7a4d2fd 100644
--- a/include/asm-powerpc/percpu.h
+++ b/include/asm-powerpc/percpu.h
@@ -27,7 +27,7 @@
#define percpu_modcopy(pcpudst, src, size) \
do { \
unsigned int __i; \
- for_each_cpu(__i) \
+ for_each_possible_cpu(__i) \
memcpy((pcpudst)+__per_cpu_offset(__i), \
(src), (size)); \
} while (0)
diff --git a/include/asm-powerpc/pmac_feature.h b/include/asm-powerpc/pmac_feature.h
index 3221628130c..d3599cc9aa7 100644
--- a/include/asm-powerpc/pmac_feature.h
+++ b/include/asm-powerpc/pmac_feature.h
@@ -305,7 +305,7 @@ extern void pmac_feature_init(void);
extern void pmac_set_early_video_resume(void (*proc)(void *data), void *data);
extern void pmac_call_early_video_resume(void);
-#define PMAC_FTR_DEF(x) ((_MACH_Pmac << 16) | (x))
+#define PMAC_FTR_DEF(x) ((0x6660000) | (x))
/* The AGP driver registers itself here */
extern void pmac_register_agp_pm(struct pci_dev *bridge,
diff --git a/include/asm-powerpc/poll.h b/include/asm-powerpc/poll.h
index edd2054da86..9c7d1263103 100644
--- a/include/asm-powerpc/poll.h
+++ b/include/asm-powerpc/poll.h
@@ -13,6 +13,7 @@
#define POLLWRBAND 0x0200
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index 1c64a211cf1..93f83efeb31 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -22,22 +22,6 @@
* -- BenH.
*/
-/* Platforms codes (to be obsoleted) */
-#define PLATFORM_PSERIES 0x0100
-#define PLATFORM_PSERIES_LPAR 0x0101
-#define PLATFORM_ISERIES_LPAR 0x0201
-#define PLATFORM_LPAR 0x0001
-#define PLATFORM_POWERMAC 0x0400
-#define PLATFORM_MAPLE 0x0500
-#define PLATFORM_PREP 0x0600
-#define PLATFORM_CHRP 0x0700
-#define PLATFORM_CELL 0x1000
-
-/* Compat platform codes for 32 bits */
-#define _MACH_prep PLATFORM_PREP
-#define _MACH_Pmac PLATFORM_POWERMAC
-#define _MACH_chrp PLATFORM_CHRP
-
/* PREP sub-platform types see residual.h for these */
#define _PREP_Motorola 0x01 /* motorola prep */
#define _PREP_Firm 0x02 /* firmworks prep */
@@ -49,18 +33,14 @@
#define _CHRP_IBM 0x05 /* IBM chrp, the longtrail and longtrail 2 */
#define _CHRP_Pegasos 0x06 /* Genesi/bplan's Pegasos and Pegasos2 */
-#ifdef __KERNEL__
-#define platform_is_pseries() (_machine == PLATFORM_PSERIES || \
- _machine == PLATFORM_PSERIES_LPAR)
+#if defined(__KERNEL__) && defined(CONFIG_PPC32)
-#if defined(CONFIG_PPC_MULTIPLATFORM)
-extern int _machine;
+extern int _chrp_type;
-#ifdef CONFIG_PPC32
+#ifdef CONFIG_PPC_PREP
/* what kind of prep workstation we are */
extern int _prep_type;
-extern int _chrp_type;
/*
* This is used to identify the board type from a given PReP board
@@ -70,17 +50,14 @@ extern int _chrp_type;
extern unsigned char ucBoardRev;
extern unsigned char ucBoardRevMaj, ucBoardRevMin;
-#endif /* CONFIG_PPC32 */
+#endif /* CONFIG_PPC_PREP */
-#elif defined(CONFIG_PPC_ISERIES)
-/*
- * iSeries is soon to become MULTIPLATFORM hopefully ...
- */
-#define _machine PLATFORM_ISERIES_LPAR
-#else
+#ifndef CONFIG_PPC_MULTIPLATFORM
#define _machine 0
#endif /* CONFIG_PPC_MULTIPLATFORM */
-#endif /* __KERNEL__ */
+
+#endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */
+
/*
* Default implementation of macro that returns current
* instruction pointer ("program counter").
@@ -251,6 +228,10 @@ static inline unsigned long __pack_fe01(unsigned int fpmode)
#define cpu_relax() barrier()
#endif
+/* Check that a certain kernel stack pointer is valid in task_struct p */
+int validate_sp(unsigned long sp, struct task_struct *p,
+ unsigned long nbytes);
+
/*
* Prefetch macros.
*/
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 782e13a070a..97ef1cd71a4 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -149,12 +149,14 @@ extern struct device_node *of_node_get(struct device_node *node);
extern void of_node_put(struct device_node *node);
/* For scanning the flat device-tree at boot time */
-int __init of_scan_flat_dt(int (*it)(unsigned long node,
- const char *uname, int depth,
- void *data),
- void *data);
-void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
- unsigned long *size);
+extern int __init of_scan_flat_dt(int (*it)(unsigned long node,
+ const char *uname, int depth,
+ void *data),
+ void *data);
+extern void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
+ unsigned long *size);
+extern int __init of_flat_dt_is_compatible(unsigned long node, const char *name);
+extern unsigned long __init of_get_flat_dt_root(void);
/* For updating the device tree at runtime */
extern void of_attach_node(struct device_node *);
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 72bfe3af046..bd467bf5cf5 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -622,6 +622,10 @@ extern void ppc64_runlatch_off(void);
extern unsigned long scom970_read(unsigned int address);
extern void scom970_write(unsigned int address, unsigned long value);
+#else
+#define ppc64_runlatch_on()
+#define ppc64_runlatch_off()
+
#endif /* CONFIG_PPC64 */
#define __get_SP() ({unsigned long sp; \
diff --git a/include/asm-powerpc/smp.h b/include/asm-powerpc/smp.h
index 98581e5a827..4a716f707cf 100644
--- a/include/asm-powerpc/smp.h
+++ b/include/asm-powerpc/smp.h
@@ -29,7 +29,6 @@
#endif
extern int boot_cpuid;
-extern int boot_cpuid_phys;
extern void cpu_die(void);
@@ -99,6 +98,7 @@ extern void smp_release_cpus(void);
#else
/* 32-bit */
#ifndef CONFIG_SMP
+extern int boot_cpuid_phys;
#define get_hard_smp_processor_id(cpu) boot_cpuid_phys
#define set_hard_smp_processor_id(cpu, phys)
#endif
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index 38bacf2f6e0..f431d8b0b65 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -110,6 +110,7 @@ struct spu {
char *name;
unsigned long local_store_phys;
u8 *local_store;
+ unsigned long problem_phys;
struct spu_problem __iomem *problem;
struct spu_priv1 __iomem *priv1;
struct spu_priv2 __iomem *priv2;
@@ -137,6 +138,7 @@ struct spu {
void (* wbox_callback)(struct spu *spu);
void (* ibox_callback)(struct spu *spu);
void (* stop_callback)(struct spu *spu);
+ void (* mfc_callback)(struct spu *spu);
char irq_c0[8];
char irq_c1[8];
@@ -149,6 +151,14 @@ int spu_irq_class_0_bottom(struct spu *spu);
int spu_irq_class_1_bottom(struct spu *spu);
void spu_irq_setaffinity(struct spu *spu, int cpu);
+/* system callbacks from the SPU */
+struct spu_syscall_block {
+ u64 nr_ret;
+ u64 parm[6];
+};
+extern long spu_sys_callback(struct spu_syscall_block *s);
+
+/* syscalls implemented in spufs */
extern struct spufs_calls {
asmlinkage long (*create_thread)(const char __user *name,
unsigned int flags, mode_t mode);
@@ -399,7 +409,6 @@ struct spu_priv1 {
#define SPU_GET_REVISION_BITS(vr) (vr & SPU_REVISION_BITS)
u8 pad_0x28_0x100[0x100 - 0x28]; /* 0x28 */
-
/* Interrupt Area */
u64 int_mask_RW[3]; /* 0x100 */
#define CLASS0_ENABLE_DMA_ALIGNMENT_INTR 0x1L
diff --git a/include/asm-powerpc/string.h b/include/asm-powerpc/string.h
index 8606a696c08..faa407f33c6 100644
--- a/include/asm-powerpc/string.h
+++ b/include/asm-powerpc/string.h
@@ -15,7 +15,7 @@
#define __HAVE_ARCH_MEMCHR
extern int strcasecmp(const char *, const char *);
-extern int strncasecmp(const char *, const char *, int);
+extern int strncasecmp(const char *, const char *, __kernel_size_t);
extern char * strcpy(char *,const char *);
extern char * strncpy(char *,const char *, __kernel_size_t);
extern __kernel_size_t strlen(const char *);
diff --git a/include/asm-powerpc/syscalls.h b/include/asm-powerpc/syscalls.h
new file mode 100644
index 00000000000..c2fe79d4f90
--- /dev/null
+++ b/include/asm-powerpc/syscalls.h
@@ -0,0 +1,58 @@
+#ifndef __ASM_POWERPC_SYSCALLS_H
+#define __ASM_POWERPC_SYSCALLS_H
+#ifdef __KERNEL__
+
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <asm/signal.h>
+
+struct new_utsname;
+struct pt_regs;
+struct rtas_args;
+struct sigaction;
+
+asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, off_t offset);
+asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff);
+asmlinkage int sys_execve(unsigned long a0, unsigned long a1,
+ unsigned long a2, unsigned long a3, unsigned long a4,
+ unsigned long a5, struct pt_regs *regs);
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long usp,
+ int __user *parent_tidp, void __user *child_threadptr,
+ int __user *child_tidp, int p6, struct pt_regs *regs);
+asmlinkage int sys_fork(unsigned long p1, unsigned long p2,
+ unsigned long p3, unsigned long p4, unsigned long p5,
+ unsigned long p6, struct pt_regs *regs);
+asmlinkage int sys_vfork(unsigned long p1, unsigned long p2,
+ unsigned long p3, unsigned long p4, unsigned long p5,
+ unsigned long p6, struct pt_regs *regs);
+asmlinkage int sys_pipe(int __user *fildes);
+asmlinkage long sys_rt_sigaction(int sig,
+ const struct sigaction __user *act,
+ struct sigaction __user *oact, size_t sigsetsize);
+asmlinkage int sys_ipc(uint call, int first, unsigned long second,
+ long third, void __user *ptr, long fifth);
+asmlinkage long ppc64_personality(unsigned long personality);
+asmlinkage int ppc_rtas(struct rtas_args __user *uargs);
+asmlinkage time_t sys64_time(time_t __user * tloc);
+asmlinkage long ppc_newuname(struct new_utsname __user * name);
+
+asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset,
+ size_t sigsetsize);
+
+#ifndef __powerpc64__
+asmlinkage long sys_sigaltstack(const stack_t __user *uss,
+ stack_t __user *uoss, int r5, int r6, int r7, int r8,
+ struct pt_regs *regs);
+#else /* __powerpc64__ */
+asmlinkage long sys_sigaltstack(const stack_t __user *uss,
+ stack_t __user *uoss, unsigned long r5, unsigned long r6,
+ unsigned long r7, unsigned long r8, struct pt_regs *regs);
+#endif /* __powerpc64__ */
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_POWERPC_SYSCALLS_H */
diff --git a/include/asm-powerpc/types.h b/include/asm-powerpc/types.h
index ec3c2ee8bf8..baabba96e31 100644
--- a/include/asm-powerpc/types.h
+++ b/include/asm-powerpc/types.h
@@ -103,6 +103,11 @@ typedef u64 sector_t;
#define HAVE_SECTOR_T
#endif
+#ifdef CONFIG_LSF
+typedef u64 blkcnt_t;
+#define HAVE_BLKCNT_T
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index 35556993f06..1e990747dce 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -425,6 +425,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
#include <linux/types.h>
#include <linux/compiler.h>
#include <linux/linkage.h>
+#include <asm/syscalls.h>
#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
@@ -460,44 +461,10 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
* System call prototypes.
*/
#ifdef __KERNEL_SYSCALLS__
-extern pid_t setsid(void);
-extern int write(int fd, const char *buf, off_t count);
-extern int read(int fd, char *buf, off_t count);
-extern off_t lseek(int fd, off_t offset, int count);
-extern int dup(int fd);
extern int execve(const char *file, char **argv, char **envp);
-extern int open(const char *file, int flag, int mode);
-extern int close(int fd);
-extern pid_t waitpid(pid_t pid, int *wait_stat, int options);
#endif /* __KERNEL_SYSCALLS__ */
/*
- * Functions that implement syscalls.
- */
-unsigned long sys_mmap(unsigned long addr, size_t len, unsigned long prot,
- unsigned long flags, unsigned long fd, off_t offset);
-unsigned long sys_mmap2(unsigned long addr, size_t len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff);
-struct pt_regs;
-int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
- unsigned long a3, unsigned long a4, unsigned long a5,
- struct pt_regs *regs);
-int sys_clone(unsigned long clone_flags, unsigned long usp,
- int __user *parent_tidp, void __user *child_threadptr,
- int __user *child_tidp, int p6, struct pt_regs *regs);
-int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
- unsigned long p4, unsigned long p5, unsigned long p6,
- struct pt_regs *regs);
-int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
- unsigned long p4, unsigned long p5, unsigned long p6,
- struct pt_regs *regs);
-int sys_pipe(int __user *fildes);
-struct sigaction;
-long sys_rt_sigaction(int sig, const struct sigaction __user *act,
- struct sigaction __user *oact, size_t sigsetsize);
-
-/*
* "Conditional" syscalls
*
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
diff --git a/include/asm-powerpc/vdso_datapage.h b/include/asm-powerpc/vdso_datapage.h
index 7aa92086c3f..8a94f0eba5e 100644
--- a/include/asm-powerpc/vdso_datapage.h
+++ b/include/asm-powerpc/vdso_datapage.h
@@ -55,6 +55,9 @@ struct vdso_data {
__u32 minor; /* Minor number 0x14 */
} version;
+ /* Note about the platform flags: it now only contains the lpar
+ * bit. The actual platform number is dead and burried
+ */
__u32 platform; /* Platform flags 0x18 */
__u32 processor; /* Processor type 0x1C */
__u64 processorCount; /* # of physical processors 0x20 */
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
index a3e8a45e45a..e1a0a7b213d 100644
--- a/include/asm-ppc/machdep.h
+++ b/include/asm-ppc/machdep.h
@@ -19,6 +19,18 @@ struct pci_dev;
struct seq_file;
struct file;
+/*
+ * This is for compatibility with ARCH=powerpc.
+ */
+#define machine_is(x) __MACHINE_IS_##x
+#define __MACHINE_IS_powermac 0
+#define __MACHINE_IS_chrp 0
+#ifdef CONFIG_PPC_PREP
+#define __MACHINE_IS_prep 1
+#else
+#define __MACHINE_IS_prep 0
+#endif
+
/* We export this macro for external modules like Alsa to know if
* ppc_md.feature_call is implemented or not
*/
@@ -44,7 +56,7 @@ struct machdep_calls {
void (*power_off)(void);
void (*halt)(void);
- void (*idle)(void);
+ void (*idle_loop)(void);
void (*power_save)(void);
long (*time_init)(void); /* Optional, may be NULL */
@@ -104,9 +116,6 @@ struct machdep_calls {
unsigned long size,
pgprot_t vma_prot);
- /* this is for modules, since _machine can be a define -- Cort */
- int ppc_machine;
-
/* Motherboard/chipset features. This is a kind of general purpose
* hook used to control some machine specific features (like reset
* lines, chip power control, etc...).
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
index 6167f74635f..7e9842805a2 100644
--- a/include/asm-ppc/mpc52xx.h
+++ b/include/asm-ppc/mpc52xx.h
@@ -355,6 +355,7 @@ struct mpc52xx_xlb {
u32 snoop_window; /* XLB + 0x70 */
};
+#define MPC52xx_XLB_CFG_PLDIS (1 << 31)
#define MPC52xx_XLB_CFG_SNOOP (1 << 15)
/* Clock Distribution control */
@@ -427,6 +428,9 @@ extern void mpc52xx_calibrate_decr(void);
extern void mpc52xx_find_bridges(void);
+extern void mpc52xx_setup_cpu(void);
+
+
/* Matching of PSC function */
struct mpc52xx_psc_func {
diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h
index 538e0c8ab24..a70ba2ee552 100644
--- a/include/asm-ppc/page.h
+++ b/include/asm-ppc/page.h
@@ -149,8 +149,7 @@ extern int page_is_ram(unsigned long pfn);
#define __pa(x) ___pa((unsigned long)(x))
#define __va(x) ((void *)(___va((unsigned long)(x))))
-#define pfn_to_page(pfn) (mem_map + ((pfn) - PPC_PGSTART))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + PPC_PGSTART)
+#define ARCH_PFN_OFFSET (PPC_PGSTART)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT)
@@ -175,5 +174,6 @@ extern __inline__ int get_order(unsigned long size)
/* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */
#define __HAVE_ARCH_GATE_AREA 1
+#include <asm-generic/memory_model.h>
#endif /* __KERNEL__ */
#endif /* _PPC_PAGE_H */
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index e1c62da12e7..570b355162f 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -837,7 +837,8 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
*/
#define pgtable_cache_init() do { } while (0)
-extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep);
+extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep,
+ pmd_t **pmdp);
#include <asm-generic/pgtable.h>
diff --git a/include/asm-ppc/prom.h b/include/asm-ppc/prom.h
index 6d431d6fb02..adc5ae78492 100644
--- a/include/asm-ppc/prom.h
+++ b/include/asm-ppc/prom.h
@@ -8,126 +8,19 @@
#ifndef _PPC_PROM_H
#define _PPC_PROM_H
-#include <linux/config.h>
-#include <linux/types.h>
-
-typedef u32 phandle;
-typedef u32 ihandle;
-
-struct address_range {
- unsigned int space;
- unsigned int address;
- unsigned int size;
-};
-
-struct interrupt_info {
- int line;
- int sense; /* +ve/-ve logic, edge or level, etc. */
-};
-
+/* This is used in arch/ppc/mm/mem_pieces.h */
struct reg_property {
unsigned int address;
unsigned int size;
};
-struct property {
- char *name;
- int length;
- unsigned char *value;
- struct property *next;
-};
-
-/*
- * Note: don't change this structure for now or you'll break BootX !
- */
-struct device_node {
- char *name;
- char *type;
- phandle node;
- int n_addrs;
- struct address_range *addrs;
- int n_intrs;
- struct interrupt_info *intrs;
- char *full_name;
- struct property *properties;
- struct device_node *parent;
- struct device_node *child;
- struct device_node *sibling;
- struct device_node *next; /* next device of same type */
- struct device_node *allnext; /* next in list of all nodes */
-};
-
-struct prom_args;
-typedef void (*prom_entry)(struct prom_args *);
-
-/* OBSOLETE: Old style node lookup */
-extern struct device_node *find_devices(const char *name);
-extern struct device_node *find_type_devices(const char *type);
-extern struct device_node *find_path_device(const char *path);
-extern struct device_node *find_compatible_devices(const char *type,
- const char *compat);
-extern struct device_node *find_all_nodes(void);
-
-/* New style node lookup */
-extern struct device_node *of_find_node_by_name(struct device_node *from,
- const char *name);
-extern struct device_node *of_find_node_by_type(struct device_node *from,
- const char *type);
-extern struct device_node *of_find_compatible_node(struct device_node *from,
- const char *type, const char *compat);
-extern struct device_node *of_find_node_by_path(const char *path);
-extern struct device_node *of_find_all_nodes(struct device_node *prev);
-extern struct device_node *of_get_parent(const struct device_node *node);
-extern struct device_node *of_get_next_child(const struct device_node *node,
- struct device_node *prev);
-extern struct device_node *of_node_get(struct device_node *node);
-extern void of_node_put(struct device_node *node);
-
-/* Other Prototypes */
-extern void abort(void);
-extern unsigned long prom_init(int, int, prom_entry);
-extern void prom_print(const char *msg);
-extern void relocate_nodes(void);
-extern void finish_device_tree(void);
-extern int device_is_compatible(struct device_node *device, const char *);
-extern int machine_is_compatible(const char *compat);
-extern unsigned char *get_property(struct device_node *node, const char *name,
- int *lenp);
-extern int prom_add_property(struct device_node* np, struct property* prop);
-extern void prom_get_irq_senses(unsigned char *, int, int);
-extern int prom_n_addr_cells(struct device_node* np);
-extern int prom_n_size_cells(struct device_node* np);
-
-extern struct resource*
-request_OF_resource(struct device_node* node, int index, const char* name_postfix);
-extern int release_OF_resource(struct device_node* node, int index);
-
-extern void print_properties(struct device_node *node);
-extern int call_rtas(const char *service, int nargs, int nret,
- unsigned long *outputs, ...);
-
/*
- * PCI <-> OF matching functions
- */
-struct pci_bus;
-struct pci_dev;
-extern int pci_device_from_OF_node(struct device_node *node,
- u8* bus, u8* devfn);
-extern struct device_node* pci_busdev_to_OF_node(struct pci_bus *, int);
-extern struct device_node* pci_device_to_OF_node(struct pci_dev *);
-extern void pci_create_OF_bus_map(void);
-
-/*
- * When we call back to the Open Firmware client interface, we usually
- * have to do that before the kernel is relocated to its final location
- * (this is because we can't use OF after we have overwritten the
- * exception vectors with our exception handlers). These macros assist
- * in performing the address calculations that we need to do to access
- * data when the kernel is running at an address that is different from
- * the address that the kernel is linked at. The reloc_offset() function
- * returns the difference between these two addresses and the macros
- * simplify the process of adding or subtracting this offset to/from
- * pointer values. See arch/ppc/kernel/prom.c for how these are used.
+ * These macros assist in performing the address calculations that we
+ * need to do to access data when the kernel is running at an address
+ * that is different from the address that the kernel is linked at.
+ * The reloc_offset() function returns the difference between these
+ * two addresses and the macros simplify the process of adding or
+ * subtracting this offset to/from pointer values.
*/
extern unsigned long reloc_offset(void);
extern unsigned long add_reloc_offset(unsigned long);
@@ -136,45 +29,12 @@ extern unsigned long sub_reloc_offset(unsigned long);
#define PTRRELOC(x) ((typeof(x))add_reloc_offset((unsigned long)(x)))
#define PTRUNRELOC(x) ((typeof(x))sub_reloc_offset((unsigned long)(x)))
-
-/*
- * OF address retreival & translation
- */
-
-
-/* Translate an OF address block into a CPU physical address
- */
-#define OF_BAD_ADDR ((u64)-1)
-extern u64 of_translate_address(struct device_node *np, u32 *addr);
-
-/* Extract an address from a device, returns the region size and
- * the address space flags too. The PCI version uses a BAR number
- * instead of an absolute index
- */
-extern u32 *of_get_address(struct device_node *dev, int index,
- u64 *size, unsigned int *flags);
-extern u32 *of_get_pci_address(struct device_node *dev, int bar_no,
- u64 *size, unsigned int *flags);
-
-/* Get an address as a resource. Note that if your address is
- * a PIO address, the conversion will fail if the physical address
- * can't be internally converted to an IO token with
- * pci_address_to_pio(), that is because it's either called to early
- * or it can't be matched to any host bridge IO space
- */
-extern int of_address_to_resource(struct device_node *dev, int index,
- struct resource *r);
-extern int of_pci_address_to_resource(struct device_node *dev, int bar,
- struct resource *r);
-
-#ifndef CONFIG_PPC_OF
/*
- * Fallback definitions for builds where we don't have prom.c included.
+ * Fallback definitions since we don't support OF in arch/ppc any more.
*/
#define machine_is_compatible(x) 0
#define of_find_compatible_node(f, t, c) NULL
#define get_property(p, n, l) NULL
-#endif
#endif /* _PPC_PROM_H */
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h
index 485a924e4d0..b74af546156 100644
--- a/include/asm-ppc/serial.h
+++ b/include/asm-ppc/serial.h
@@ -41,15 +41,10 @@
#else
/*
- * XXX Assume for now it has PC-style ISA serial ports.
- * This is true for PReP and CHRP at least.
+ * XXX Assume it has PC-style ISA serial ports - true for PReP at least.
*/
#include <asm/pc_serial.h>
-#if defined(CONFIG_MAC_SERIAL)
-#define SERIAL_DEV_OFFSET ((_machine == _MACH_prep || _machine == _MACH_chrp) ? 0 : 2)
-#endif
-
#endif /* !CONFIG_GEMINI and others */
#endif /* __ASM_SERIAL_H__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
index 3628899f48b..ca092ffb7a9 100644
--- a/include/asm-s390/bitops.h
+++ b/include/asm-s390/bitops.h
@@ -828,35 +828,12 @@ static inline int sched_find_first_bit(unsigned long *b)
return find_first_bit(b, 140);
}
-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-#define ffs(x) generic_ffs(x)
+#include <asm-generic/bitops/ffs.h>
-/*
- * fls: find last bit set.
- */
-#define fls(x) generic_fls(x)
-#define fls64(x) generic_fls64(x)
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-#define hweight64(x) \
-({ \
- unsigned long __x = (x); \
- unsigned int __w; \
- __w = generic_hweight32((unsigned int) __x); \
- __w += generic_hweight32((unsigned int) (__x>>32)); \
- __w; \
-})
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/hweight.h>
#ifdef __KERNEL__
@@ -871,11 +848,11 @@ static inline int sched_find_first_bit(unsigned long *b)
*/
#define ext2_set_bit(nr, addr) \
- test_and_set_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
+ __test_and_set_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
#define ext2_set_bit_atomic(lock, nr, addr) \
test_and_set_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
#define ext2_clear_bit(nr, addr) \
- test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
+ __test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
#define ext2_clear_bit_atomic(lock, nr, addr) \
test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
#define ext2_test_bit(nr, addr) \
@@ -1011,18 +988,7 @@ ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset)
return offset + ext2_find_first_zero_bit(p, size);
}
-/* Bitmap functions for the minix filesystem. */
-/* FIXME !!! */
-#define minix_test_and_set_bit(nr,addr) \
- test_and_set_bit(nr,(unsigned long *)addr)
-#define minix_set_bit(nr,addr) \
- set_bit(nr,(unsigned long *)addr)
-#define minix_test_and_clear_bit(nr,addr) \
- test_and_clear_bit(nr,(unsigned long *)addr)
-#define minix_test_bit(nr,addr) \
- test_bit(nr,(unsigned long *)addr)
-#define minix_find_first_zero_bit(addr,size) \
- find_first_zero_bit(addr,size)
+#include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-s390/compat.h b/include/asm-s390/compat.h
index a007715f4ae..356a0b18353 100644
--- a/include/asm-s390/compat.h
+++ b/include/asm-s390/compat.h
@@ -128,6 +128,11 @@ static inline void __user *compat_ptr(compat_uptr_t uptr)
return (void __user *)(unsigned long)(uptr & 0x7fffffffUL);
}
+static inline compat_uptr_t ptr_to_compat(void __user *uptr)
+{
+ return (u32)(unsigned long)uptr;
+}
+
static inline void __user *compat_alloc_user_space(long len)
{
unsigned long stack;
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index 2430c561e02..3b1138ac7e7 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -181,8 +181,6 @@ page_get_storage_key(unsigned long addr)
#define PAGE_OFFSET 0x0UL
#define __pa(x) (unsigned long)(x)
#define __va(x) (void *)(unsigned long)(x)
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define pfn_valid(pfn) ((pfn) < max_mapnr)
@@ -193,6 +191,7 @@ page_get_storage_key(unsigned long addr)
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _S390_PAGE_H */
diff --git a/include/asm-s390/poll.h b/include/asm-s390/poll.h
index e90a5ca4206..6f7f65ac7d2 100644
--- a/include/asm-s390/poll.h
+++ b/include/asm-s390/poll.h
@@ -24,6 +24,7 @@
#define POLLWRBAND 0x0200
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-s390/types.h b/include/asm-s390/types.h
index d0be3e47701..5738ad63537 100644
--- a/include/asm-s390/types.h
+++ b/include/asm-s390/types.h
@@ -93,6 +93,11 @@ typedef u64 sector_t;
#define HAVE_SECTOR_T
#endif
+#ifdef CONFIG_LSF
+typedef u64 blkcnt_t;
+#define HAVE_BLKCNT_T
+#endif
+
#endif /* ! __s390x__ */
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-sh/addrspace.h b/include/asm-sh/addrspace.h
index dbb05d1a26d..720afc11c2c 100644
--- a/include/asm-sh/addrspace.h
+++ b/include/asm-sh/addrspace.h
@@ -13,7 +13,7 @@
#include <asm/cpu/addrspace.h>
-/* Memory segments (32bit Priviledged mode addresses) */
+/* Memory segments (32bit Privileged mode addresses) */
#define P0SEG 0x00000000
#define P1SEG 0x80000000
#define P2SEG 0xa0000000
diff --git a/include/asm-sh/bitops.h b/include/asm-sh/bitops.h
index 1c526086004..e34f8250856 100644
--- a/include/asm-sh/bitops.h
+++ b/include/asm-sh/bitops.h
@@ -19,16 +19,6 @@ static __inline__ void set_bit(int nr, volatile void * addr)
local_irq_restore(flags);
}
-static __inline__ void __set_bit(int nr, volatile void * addr)
-{
- int mask;
- volatile unsigned int *a = addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- *a |= mask;
-}
-
/*
* clear_bit() doesn't provide any barrier for the compiler.
*/
@@ -47,16 +37,6 @@ static __inline__ void clear_bit(int nr, volatile void * addr)
local_irq_restore(flags);
}
-static __inline__ void __clear_bit(int nr, volatile void * addr)
-{
- int mask;
- volatile unsigned int *a = addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- *a &= ~mask;
-}
-
static __inline__ void change_bit(int nr, volatile void * addr)
{
int mask;
@@ -70,16 +50,6 @@ static __inline__ void change_bit(int nr, volatile void * addr)
local_irq_restore(flags);
}
-static __inline__ void __change_bit(int nr, volatile void * addr)
-{
- int mask;
- volatile unsigned int *a = addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- *a ^= mask;
-}
-
static __inline__ int test_and_set_bit(int nr, volatile void * addr)
{
int mask, retval;
@@ -96,19 +66,6 @@ static __inline__ int test_and_set_bit(int nr, volatile void * addr)
return retval;
}
-static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
-{
- int mask, retval;
- volatile unsigned int *a = addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- retval = (mask & *a) != 0;
- *a |= mask;
-
- return retval;
-}
-
static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
{
int mask, retval;
@@ -125,19 +82,6 @@ static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
return retval;
}
-static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
-{
- int mask, retval;
- volatile unsigned int *a = addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- retval = (mask & *a) != 0;
- *a &= ~mask;
-
- return retval;
-}
-
static __inline__ int test_and_change_bit(int nr, volatile void * addr)
{
int mask, retval;
@@ -154,23 +98,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
return retval;
}
-static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
-{
- int mask, retval;
- volatile unsigned int *a = addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- retval = (mask & *a) != 0;
- *a ^= mask;
-
- return retval;
-}
-
-static __inline__ int test_bit(int nr, const volatile void *addr)
-{
- return 1UL & (((const volatile unsigned int *) addr)[nr >> 5] >> (nr & 31));
-}
+#include <asm-generic/bitops/non-atomic.h>
static __inline__ unsigned long ffz(unsigned long word)
{
@@ -206,271 +134,15 @@ static __inline__ unsigned long __ffs(unsigned long word)
return result;
}
-/**
- * find_next_bit - find the next set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-static __inline__ unsigned long find_next_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset)
-{
- unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
- unsigned int result = offset & ~31UL;
- unsigned int tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *p++;
- tmp &= ~0UL << offset;
- if (size < 32)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size >= 32) {
- if ((tmp = *p++) != 0)
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp &= ~0UL >> (32 - size);
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
-found_middle:
- return result + __ffs(tmp);
-}
-
-/**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first set bit, not the number of the byte
- * containing a bit.
- */
-#define find_first_bit(addr, size) \
- find_next_bit((addr), (size), 0)
-
-static __inline__ int find_next_zero_bit(const unsigned long *addr, int size, int offset)
-{
- const unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (32-offset);
- if (size < 32)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size & ~31UL) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp |= ~0UL << size;
-found_middle:
- return result + ffz(tmp);
-}
-
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
-
-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-
-#define ffs(x) generic_ffs(x)
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
-
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-
-static inline int sched_find_first_bit(const unsigned long *b)
-{
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
-}
-
-#ifdef __LITTLE_ENDIAN__
-#define ext2_set_bit(nr, addr) test_and_set_bit((nr), (addr))
-#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr), (addr))
-#define ext2_test_bit(nr, addr) test_bit((nr), (addr))
-#define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr), (size))
-#define ext2_find_next_zero_bit(addr, size, offset) \
- find_next_zero_bit((unsigned long *)(addr), (size), (offset))
-#else
-static __inline__ int ext2_set_bit(int nr, volatile void * addr)
-{
- int mask, retval;
- unsigned long flags;
- volatile unsigned char *ADDR = (unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- local_irq_save(flags);
- retval = (mask & *ADDR) != 0;
- *ADDR |= mask;
- local_irq_restore(flags);
- return retval;
-}
-
-static __inline__ int ext2_clear_bit(int nr, volatile void * addr)
-{
- int mask, retval;
- unsigned long flags;
- volatile unsigned char *ADDR = (unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- local_irq_save(flags);
- retval = (mask & *ADDR) != 0;
- *ADDR &= ~mask;
- local_irq_restore(flags);
- return retval;
-}
-
-static __inline__ int ext2_test_bit(int nr, const volatile void * addr)
-{
- int mask;
- const volatile unsigned char *ADDR = (const unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- return ((mask & *ADDR) != 0);
-}
-
-#define ext2_find_first_zero_bit(addr, size) \
- ext2_find_next_zero_bit((addr), (size), 0)
-
-static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if(offset) {
- /* We hold the little endian value in tmp, but then the
- * shift is illegal. So we could keep a big endian value
- * in tmp, like this:
- *
- * tmp = __swab32(*(p++));
- * tmp |= ~0UL >> (32-offset);
- *
- * but this would decrease preformance, so we change the
- * shift:
- */
- tmp = *(p++);
- tmp |= __swab32(~0UL >> (32-offset));
- if(size < 32)
- goto found_first;
- if(~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while(size & ~31UL) {
- if(~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if(!size)
- return result;
- tmp = *p;
-
-found_first:
- /* tmp is little endian, so we would have to swab the shift,
- * see above. But then we have to swab tmp below for ffz, so
- * we might as well do this here.
- */
- return result + ffz(__swab32(tmp) | (~0UL << size));
-found_middle:
- return result + ffz(__swab32(tmp));
-}
-#endif
-
-#define ext2_set_bit_atomic(lock, nr, addr) \
- ({ \
- int ret; \
- spin_lock(lock); \
- ret = ext2_set_bit((nr), (addr)); \
- spin_unlock(lock); \
- ret; \
- })
-
-#define ext2_clear_bit_atomic(lock, nr, addr) \
- ({ \
- int ret; \
- spin_lock(lock); \
- ret = ext2_clear_bit((nr), (addr)); \
- spin_unlock(lock); \
- ret; \
- })
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
-
-/*
- * fls: find last bit set.
- */
-
-#define fls(x) generic_fls(x)
-#define fls64(x) generic_fls64(x)
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+#include <asm-generic/bitops/minix.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index 972c3f655b2..9c89287c3e5 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -105,9 +105,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
/* PFN start number, because of __MEMORY_START */
#define PFN_START (__MEMORY_START >> PAGE_SHIFT)
-
-#define pfn_to_page(pfn) (mem_map + (pfn) - PFN_START)
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + PFN_START)
+#define ARCH_PFN_OFFSET (FPN_START)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define pfn_valid(pfn) (((pfn) - PFN_START) < max_mapnr)
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
@@ -117,6 +115,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* __ASM_SH_PAGE_H */
diff --git a/include/asm-sh/poll.h b/include/asm-sh/poll.h
index 52f95b9188d..dbca9b32f4a 100644
--- a/include/asm-sh/poll.h
+++ b/include/asm-sh/poll.h
@@ -16,6 +16,7 @@
#define POLLWRBAND 0x0200
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-sh/stat.h b/include/asm-sh/stat.h
index 914e3fcbbd3..6c41a60657f 100644
--- a/include/asm-sh/stat.h
+++ b/include/asm-sh/stat.h
@@ -60,13 +60,7 @@ struct stat64 {
long long st_size;
unsigned long st_blksize;
-#if defined(__BIG_ENDIAN__)
- unsigned long __pad4; /* Future possible st_blocks hi bits */
- unsigned long st_blocks; /* Number 512-byte blocks allocated. */
-#else /* Must be little */
- unsigned long st_blocks; /* Number 512-byte blocks allocated. */
- unsigned long __pad4; /* Future possible st_blocks hi bits */
-#endif
+ unsigned long long st_blocks; /* Number 512-byte blocks allocated. */
unsigned long st_atime;
unsigned long st_atime_nsec;
diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h
index 85f0c11b431..7345350d98c 100644
--- a/include/asm-sh/thread_info.h
+++ b/include/asm-sh/thread_info.h
@@ -18,7 +18,7 @@
struct thread_info {
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
- __u32 flags; /* low level flags */
+ unsigned long flags; /* low level flags */
__u32 cpu;
int preempt_count; /* 0 => preemptable, <0 => BUG */
struct restart_block restart_block;
diff --git a/include/asm-sh/types.h b/include/asm-sh/types.h
index cb7e183a0a6..488552f43b2 100644
--- a/include/asm-sh/types.h
+++ b/include/asm-sh/types.h
@@ -58,6 +58,11 @@ typedef u64 sector_t;
#define HAVE_SECTOR_T
#endif
+#ifdef CONFIG_LSF
+typedef u64 blkcnt_t;
+#define HAVE_BLKCNT_T
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-sh64/bitops.h b/include/asm-sh64/bitops.h
index ce9c3ad45fe..f3bdcdb5d04 100644
--- a/include/asm-sh64/bitops.h
+++ b/include/asm-sh64/bitops.h
@@ -31,16 +31,6 @@ static __inline__ void set_bit(int nr, volatile void * addr)
local_irq_restore(flags);
}
-static inline void __set_bit(int nr, void *addr)
-{
- int mask;
- unsigned int *a = addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- *a |= mask;
-}
-
/*
* clear_bit() doesn't provide any barrier for the compiler.
*/
@@ -58,15 +48,6 @@ static inline void clear_bit(int nr, volatile unsigned long *a)
local_irq_restore(flags);
}
-static inline void __clear_bit(int nr, volatile unsigned long *a)
-{
- int mask;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- *a &= ~mask;
-}
-
static __inline__ void change_bit(int nr, volatile void * addr)
{
int mask;
@@ -80,16 +61,6 @@ static __inline__ void change_bit(int nr, volatile void * addr)
local_irq_restore(flags);
}
-static __inline__ void __change_bit(int nr, volatile void * addr)
-{
- int mask;
- volatile unsigned int *a = addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- *a ^= mask;
-}
-
static __inline__ int test_and_set_bit(int nr, volatile void * addr)
{
int mask, retval;
@@ -106,19 +77,6 @@ static __inline__ int test_and_set_bit(int nr, volatile void * addr)
return retval;
}
-static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
-{
- int mask, retval;
- volatile unsigned int *a = addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- retval = (mask & *a) != 0;
- *a |= mask;
-
- return retval;
-}
-
static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
{
int mask, retval;
@@ -135,19 +93,6 @@ static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
return retval;
}
-static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
-{
- int mask, retval;
- volatile unsigned int *a = addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- retval = (mask & *a) != 0;
- *a &= ~mask;
-
- return retval;
-}
-
static __inline__ int test_and_change_bit(int nr, volatile void * addr)
{
int mask, retval;
@@ -164,23 +109,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
return retval;
}
-static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
-{
- int mask, retval;
- volatile unsigned int *a = addr;
-
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- retval = (mask & *a) != 0;
- *a ^= mask;
-
- return retval;
-}
-
-static __inline__ int test_bit(int nr, const volatile void *addr)
-{
- return 1UL & (((const volatile unsigned int *) addr)[nr >> 5] >> (nr & 31));
-}
+#include <asm-generic/bitops/non-atomic.h>
static __inline__ unsigned long ffz(unsigned long word)
{
@@ -204,313 +133,16 @@ static __inline__ unsigned long ffz(unsigned long word)
return result;
}
-/**
- * __ffs - find first bit in word
- * @word: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static inline unsigned long __ffs(unsigned long word)
-{
- int r = 0;
-
- if (!word)
- return 0;
- if (!(word & 0xffff)) {
- word >>= 16;
- r += 16;
- }
- if (!(word & 0xff)) {
- word >>= 8;
- r += 8;
- }
- if (!(word & 0xf)) {
- word >>= 4;
- r += 4;
- }
- if (!(word & 3)) {
- word >>= 2;
- r += 2;
- }
- if (!(word & 1)) {
- word >>= 1;
- r += 1;
- }
- return r;
-}
-
-/**
- * find_next_bit - find the next set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-static inline unsigned long find_next_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset)
-{
- unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
- unsigned int result = offset & ~31UL;
- unsigned int tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *p++;
- tmp &= ~0UL << offset;
- if (size < 32)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size >= 32) {
- if ((tmp = *p++) != 0)
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp &= ~0UL >> (32 - size);
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
-found_middle:
- return result + __ffs(tmp);
-}
-
-/**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first set bit, not the number of the byte
- * containing a bit.
- */
-#define find_first_bit(addr, size) \
- find_next_bit((addr), (size), 0)
-
-
-static inline int find_next_zero_bit(void *addr, int size, int offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (32-offset);
- if (size < 32)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size & ~31UL) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp |= ~0UL << size;
-found_middle:
- return result + ffz(tmp);
-}
-
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
-
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-
-static inline int sched_find_first_bit(unsigned long *b)
-{
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
-}
-
-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-
-#define ffs(x) generic_ffs(x)
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
-
-#ifdef __LITTLE_ENDIAN__
-#define ext2_set_bit(nr, addr) test_and_set_bit((nr), (addr))
-#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr), (addr))
-#define ext2_test_bit(nr, addr) test_bit((nr), (addr))
-#define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr), (size))
-#define ext2_find_next_zero_bit(addr, size, offset) \
- find_next_zero_bit((addr), (size), (offset))
-#else
-static __inline__ int ext2_set_bit(int nr, volatile void * addr)
-{
- int mask, retval;
- unsigned long flags;
- volatile unsigned char *ADDR = (unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- local_irq_save(flags);
- retval = (mask & *ADDR) != 0;
- *ADDR |= mask;
- local_irq_restore(flags);
- return retval;
-}
-
-static __inline__ int ext2_clear_bit(int nr, volatile void * addr)
-{
- int mask, retval;
- unsigned long flags;
- volatile unsigned char *ADDR = (unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- local_irq_save(flags);
- retval = (mask & *ADDR) != 0;
- *ADDR &= ~mask;
- local_irq_restore(flags);
- return retval;
-}
-
-static __inline__ int ext2_test_bit(int nr, const volatile void * addr)
-{
- int mask;
- const volatile unsigned char *ADDR = (const unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- return ((mask & *ADDR) != 0);
-}
-
-#define ext2_find_first_zero_bit(addr, size) \
- ext2_find_next_zero_bit((addr), (size), 0)
-
-static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if(offset) {
- /* We hold the little endian value in tmp, but then the
- * shift is illegal. So we could keep a big endian value
- * in tmp, like this:
- *
- * tmp = __swab32(*(p++));
- * tmp |= ~0UL >> (32-offset);
- *
- * but this would decrease preformance, so we change the
- * shift:
- */
- tmp = *(p++);
- tmp |= __swab32(~0UL >> (32-offset));
- if(size < 32)
- goto found_first;
- if(~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while(size & ~31UL) {
- if(~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if(!size)
- return result;
- tmp = *p;
-
-found_first:
- /* tmp is little endian, so we would have to swab the shift,
- * see above. But then we have to swab tmp below for ffz, so
- * we might as well do this here.
- */
- return result + ffz(__swab32(tmp) | (~0UL << size));
-found_middle:
- return result + ffz(__swab32(tmp));
-}
-#endif
-
-#define ext2_set_bit_atomic(lock, nr, addr) \
- ({ \
- int ret; \
- spin_lock(lock); \
- ret = ext2_set_bit((nr), (addr)); \
- spin_unlock(lock); \
- ret; \
- })
-
-#define ext2_clear_bit_atomic(lock, nr, addr) \
- ({ \
- int ret; \
- spin_lock(lock); \
- ret = ext2_clear_bit((nr), (addr)); \
- spin_unlock(lock); \
- ret; \
- })
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
-
-#define ffs(x) generic_ffs(x)
-#define fls(x) generic_fls(x)
-#define fls64(x) generic_fls64(x)
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+#include <asm-generic/bitops/minix.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-sh64/page.h b/include/asm-sh64/page.h
index c86df90f7cb..e4937cdabeb 100644
--- a/include/asm-sh64/page.h
+++ b/include/asm-sh64/page.h
@@ -105,9 +105,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
/* PFN start number, because of __MEMORY_START */
#define PFN_START (__MEMORY_START >> PAGE_SHIFT)
-
-#define pfn_to_page(pfn) (mem_map + (pfn) - PFN_START)
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map) + PFN_START)
+#define ARCH_PFN_OFFSET (PFN_START)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define pfn_valid(pfn) (((pfn) - PFN_START) < max_mapnr)
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
@@ -117,6 +115,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* __ASM_SH64_PAGE_H */
diff --git a/include/asm-sh64/platform.h b/include/asm-sh64/platform.h
index 7046a901402..bd0d9c405a8 100644
--- a/include/asm-sh64/platform.h
+++ b/include/asm-sh64/platform.h
@@ -61,9 +61,4 @@ extern int platform_int_priority[NR_INTC_IRQS];
#define code_resource (platform_parms.kram_res_p[STANDARD_KRAM_RESOURCES - 2])
#define data_resource (platform_parms.kram_res_p[STANDARD_KRAM_RESOURCES - 1])
-/* Be prepared to 64-bit sign extensions */
-#define PFN_UP(x) ((((x) + PAGE_SIZE-1) >> PAGE_SHIFT) & 0x000fffff)
-#define PFN_DOWN(x) (((x) >> PAGE_SHIFT) & 0x000fffff)
-#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
-
#endif /* __ASM_SH64_PLATFORM_H */
diff --git a/include/asm-sh64/poll.h b/include/asm-sh64/poll.h
index a420d14eb70..3a6cbad08d2 100644
--- a/include/asm-sh64/poll.h
+++ b/include/asm-sh64/poll.h
@@ -26,6 +26,7 @@
#define POLLWRNORM 0x0100
#define POLLWRBAND 0x0200
#define POLLMSG 0x0400
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-sparc/bitops.h b/include/asm-sparc/bitops.h
index 41722b5e45e..04aa3318f76 100644
--- a/include/asm-sparc/bitops.h
+++ b/include/asm-sparc/bitops.h
@@ -152,386 +152,22 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
: "memory", "cc");
}
-/*
- * non-atomic versions
- */
-static inline void __set_bit(int nr, volatile unsigned long *addr)
-{
- unsigned long mask = 1UL << (nr & 0x1f);
- unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
-
- *p |= mask;
-}
-
-static inline void __clear_bit(int nr, volatile unsigned long *addr)
-{
- unsigned long mask = 1UL << (nr & 0x1f);
- unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
-
- *p &= ~mask;
-}
-
-static inline void __change_bit(int nr, volatile unsigned long *addr)
-{
- unsigned long mask = 1UL << (nr & 0x1f);
- unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
-
- *p ^= mask;
-}
-
-static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
-{
- unsigned long mask = 1UL << (nr & 0x1f);
- unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
- unsigned long old = *p;
-
- *p = old | mask;
- return (old & mask) != 0;
-}
-
-static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
-{
- unsigned long mask = 1UL << (nr & 0x1f);
- unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
- unsigned long old = *p;
-
- *p = old & ~mask;
- return (old & mask) != 0;
-}
-
-static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
-{
- unsigned long mask = 1UL << (nr & 0x1f);
- unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
- unsigned long old = *p;
-
- *p = old ^ mask;
- return (old & mask) != 0;
-}
+#include <asm-generic/bitops/non-atomic.h>
#define smp_mb__before_clear_bit() do { } while(0)
#define smp_mb__after_clear_bit() do { } while(0)
-/* The following routine need not be atomic. */
-static inline int test_bit(int nr, __const__ volatile unsigned long *addr)
-{
- return (1UL & (((unsigned long *)addr)[nr >> 5] >> (nr & 31))) != 0UL;
-}
-
-/* The easy/cheese version for now. */
-static inline unsigned long ffz(unsigned long word)
-{
- unsigned long result = 0;
-
- while(word & 1) {
- result++;
- word >>= 1;
- }
- return result;
-}
-
-/**
- * __ffs - find first bit in word.
- * @word: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static inline int __ffs(unsigned long word)
-{
- int num = 0;
-
- if ((word & 0xffff) == 0) {
- num += 16;
- word >>= 16;
- }
- if ((word & 0xff) == 0) {
- num += 8;
- word >>= 8;
- }
- if ((word & 0xf) == 0) {
- num += 4;
- word >>= 4;
- }
- if ((word & 0x3) == 0) {
- num += 2;
- word >>= 2;
- }
- if ((word & 0x1) == 0)
- num += 1;
- return num;
-}
-
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-static inline int sched_find_first_bit(unsigned long *b)
-{
-
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
-}
-
-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-static inline int ffs(int x)
-{
- if (!x)
- return 0;
- return __ffs((unsigned long)x) + 1;
-}
-
-/*
- * fls: find last (most-significant) bit set.
- * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
- */
-#define fls(x) generic_fls(x)
-#define fls64(x) generic_fls64(x)
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
-
-/*
- * find_next_zero_bit() finds the first zero bit in a bit string of length
- * 'size' bits, starting the search at bit 'offset'. This is largely based
- * on Linus's ALPHA routines, which are pretty portable BTW.
- */
-static inline unsigned long find_next_zero_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset)
-{
- const unsigned long *p = addr + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *(p++);
- tmp |= ~0UL >> (32-offset);
- if (size < 32)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size & ~31UL) {
- if (~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp |= ~0UL << size;
- if (tmp == ~0UL) /* Are any bits zero? */
- return result + size; /* Nope. */
-found_middle:
- return result + ffz(tmp);
-}
-
-/*
- * Linus sez that gcc can optimize the following correctly, we'll see if this
- * holds on the Sparc as it does for the ALPHA.
- */
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
-
-/**
- * find_next_bit - find the first set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- *
- * Scheduler induced bitop, do not use.
- */
-static inline int find_next_bit(const unsigned long *addr, int size, int offset)
-{
- const unsigned long *p = addr + (offset >> 5);
- int num = offset & ~0x1f;
- unsigned long word;
-
- word = *p++;
- word &= ~((1 << (offset & 0x1f)) - 1);
- while (num < size) {
- if (word != 0) {
- return __ffs(word) + num;
- }
- word = *p++;
- num += 0x20;
- }
- return num;
-}
-
-/**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first set bit, not the number of the byte
- * containing a bit.
- */
-#define find_first_bit(addr, size) \
- find_next_bit((addr), (size), 0)
-
-/*
- */
-static inline int test_le_bit(int nr, __const__ unsigned long * addr)
-{
- __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
- return (ADDR[nr >> 3] >> (nr & 7)) & 1;
-}
-
-/*
- * non-atomic versions
- */
-static inline void __set_le_bit(int nr, unsigned long *addr)
-{
- unsigned char *ADDR = (unsigned char *)addr;
-
- ADDR += nr >> 3;
- *ADDR |= 1 << (nr & 0x07);
-}
-
-static inline void __clear_le_bit(int nr, unsigned long *addr)
-{
- unsigned char *ADDR = (unsigned char *)addr;
-
- ADDR += nr >> 3;
- *ADDR &= ~(1 << (nr & 0x07));
-}
-
-static inline int __test_and_set_le_bit(int nr, unsigned long *addr)
-{
- int mask, retval;
- unsigned char *ADDR = (unsigned char *)addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- retval = (mask & *ADDR) != 0;
- *ADDR |= mask;
- return retval;
-}
-
-static inline int __test_and_clear_le_bit(int nr, unsigned long *addr)
-{
- int mask, retval;
- unsigned char *ADDR = (unsigned char *)addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- retval = (mask & *ADDR) != 0;
- *ADDR &= ~mask;
- return retval;
-}
-
-static inline unsigned long find_next_zero_le_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset)
-{
- const unsigned long *p = addr + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if(offset) {
- tmp = *(p++);
- tmp |= __swab32(~0UL >> (32-offset));
- if(size < 32)
- goto found_first;
- if(~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while(size & ~31UL) {
- if(~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if(!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp = __swab32(tmp) | (~0UL << size);
- if (tmp == ~0UL) /* Are any bits zero? */
- return result + size; /* Nope. */
- return result + ffz(tmp);
-
-found_middle:
- return result + ffz(__swab32(tmp));
-}
-
-#define find_first_zero_le_bit(addr, size) \
- find_next_zero_le_bit((addr), (size), 0)
-
-#define ext2_set_bit(nr,addr) \
- __test_and_set_le_bit((nr),(unsigned long *)(addr))
-#define ext2_clear_bit(nr,addr) \
- __test_and_clear_le_bit((nr),(unsigned long *)(addr))
-
-#define ext2_set_bit_atomic(lock, nr, addr) \
- ({ \
- int ret; \
- spin_lock(lock); \
- ret = ext2_set_bit((nr), (unsigned long *)(addr)); \
- spin_unlock(lock); \
- ret; \
- })
-
-#define ext2_clear_bit_atomic(lock, nr, addr) \
- ({ \
- int ret; \
- spin_lock(lock); \
- ret = ext2_clear_bit((nr), (unsigned long *)(addr)); \
- spin_unlock(lock); \
- ret; \
- })
-
-#define ext2_test_bit(nr,addr) \
- test_le_bit((nr),(unsigned long *)(addr))
-#define ext2_find_first_zero_bit(addr, size) \
- find_first_zero_le_bit((unsigned long *)(addr), (size))
-#define ext2_find_next_zero_bit(addr, size, off) \
- find_next_zero_le_bit((unsigned long *)(addr), (size), (off))
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) \
- test_and_set_bit((nr),(unsigned long *)(addr))
-#define minix_set_bit(nr,addr) \
- set_bit((nr),(unsigned long *)(addr))
-#define minix_test_and_clear_bit(nr,addr) \
- test_and_clear_bit((nr),(unsigned long *)(addr))
-#define minix_test_bit(nr,addr) \
- test_bit((nr),(unsigned long *)(addr))
-#define minix_find_first_zero_bit(addr,size) \
- find_first_zero_bit((unsigned long *)(addr),(size))
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+#include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-sparc/cpudata.h b/include/asm-sparc/cpudata.h
index ec0d9ef90a3..a2c4d51d36c 100644
--- a/include/asm-sparc/cpudata.h
+++ b/include/asm-sparc/cpudata.h
@@ -18,6 +18,7 @@ typedef struct {
unsigned int counter;
int prom_node;
int mid;
+ int next;
} cpuinfo_sparc;
DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
diff --git a/include/asm-sparc/page.h b/include/asm-sparc/page.h
index 9122684f6c1..ec3274b7ddf 100644
--- a/include/asm-sparc/page.h
+++ b/include/asm-sparc/page.h
@@ -152,8 +152,7 @@ extern unsigned long pfn_base;
#define virt_to_phys __pa
#define phys_to_virt __va
-#define pfn_to_page(pfn) (mem_map + ((pfn)-(pfn_base)))
-#define page_to_pfn(page) ((unsigned long)(((page) - mem_map) + pfn_base))
+#define ARCH_PFN_OFFSET (pfn_base)
#define virt_to_page(kaddr) (mem_map + ((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT)))
#define pfn_valid(pfn) (((pfn) >= (pfn_base)) && (((pfn)-(pfn_base)) < max_mapnr))
@@ -164,6 +163,7 @@ extern unsigned long pfn_base;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _SPARC_PAGE_H */
diff --git a/include/asm-sparc/poll.h b/include/asm-sparc/poll.h
index 3ddcc6481f0..26f13fb3549 100644
--- a/include/asm-sparc/poll.h
+++ b/include/asm-sparc/poll.h
@@ -13,6 +13,7 @@
#define POLLWRBAND 256
#define POLLMSG 512
#define POLLREMOVE 1024
+#define POLLRDHUP 2048
struct pollfd {
int fd;
diff --git a/include/asm-sparc/smp.h b/include/asm-sparc/smp.h
index 580c51d011d..98c46e3fbe8 100644
--- a/include/asm-sparc/smp.h
+++ b/include/asm-sparc/smp.h
@@ -81,16 +81,9 @@ static inline int smp_call_function(void (*func)(void *info), void *info, int no
return 0;
}
-extern __volatile__ int __cpu_number_map[NR_CPUS];
-extern __volatile__ int __cpu_logical_map[NR_CPUS];
-
static inline int cpu_logical_map(int cpu)
{
- return __cpu_logical_map[cpu];
-}
-static inline int cpu_number_map(int cpu)
-{
- return __cpu_number_map[cpu];
+ return cpu;
}
static inline int hard_smp4m_processor_id(void)
diff --git a/include/asm-sparc/spinlock.h b/include/asm-sparc/spinlock.h
index e344c98a6f5..3350c90c786 100644
--- a/include/asm-sparc/spinlock.h
+++ b/include/asm-sparc/spinlock.h
@@ -94,7 +94,7 @@ static inline void __read_lock(raw_rwlock_t *rw)
#define __raw_read_lock(lock) \
do { unsigned long flags; \
local_irq_save(flags); \
- __raw_read_lock(lock); \
+ __read_lock(lock); \
local_irq_restore(flags); \
} while(0)
@@ -114,11 +114,11 @@ static inline void __read_unlock(raw_rwlock_t *rw)
#define __raw_read_unlock(lock) \
do { unsigned long flags; \
local_irq_save(flags); \
- __raw_read_unlock(lock); \
+ __read_unlock(lock); \
local_irq_restore(flags); \
} while(0)
-extern __inline__ void __raw_write_lock(raw_rwlock_t *rw)
+static inline void __raw_write_lock(raw_rwlock_t *rw)
{
register raw_rwlock_t *lp asm("g1");
lp = rw;
@@ -131,9 +131,28 @@ extern __inline__ void __raw_write_lock(raw_rwlock_t *rw)
: "g2", "g4", "memory", "cc");
}
+static inline int __raw_write_trylock(raw_rwlock_t *rw)
+{
+ unsigned int val;
+
+ __asm__ __volatile__("ldstub [%1 + 3], %0"
+ : "=r" (val)
+ : "r" (&rw->lock)
+ : "memory");
+
+ if (val == 0) {
+ val = rw->lock & ~0xff;
+ if (val)
+ ((volatile u8*)&rw->lock)[3] = 0;
+ }
+
+ return (val == 0);
+}
+
#define __raw_write_unlock(rw) do { (rw)->lock = 0; } while(0)
#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
#endif /* !(__ASSEMBLY__) */
diff --git a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h
index 6efc0162fb0..71944b0f09d 100644
--- a/include/asm-sparc64/bitops.h
+++ b/include/asm-sparc64/bitops.h
@@ -18,58 +18,7 @@ extern void set_bit(unsigned long nr, volatile unsigned long *addr);
extern void clear_bit(unsigned long nr, volatile unsigned long *addr);
extern void change_bit(unsigned long nr, volatile unsigned long *addr);
-/* "non-atomic" versions... */
-
-static inline void __set_bit(int nr, volatile unsigned long *addr)
-{
- unsigned long *m = ((unsigned long *)addr) + (nr >> 6);
-
- *m |= (1UL << (nr & 63));
-}
-
-static inline void __clear_bit(int nr, volatile unsigned long *addr)
-{
- unsigned long *m = ((unsigned long *)addr) + (nr >> 6);
-
- *m &= ~(1UL << (nr & 63));
-}
-
-static inline void __change_bit(int nr, volatile unsigned long *addr)
-{
- unsigned long *m = ((unsigned long *)addr) + (nr >> 6);
-
- *m ^= (1UL << (nr & 63));
-}
-
-static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
-{
- unsigned long *m = ((unsigned long *)addr) + (nr >> 6);
- unsigned long old = *m;
- unsigned long mask = (1UL << (nr & 63));
-
- *m = (old | mask);
- return ((old & mask) != 0);
-}
-
-static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
-{
- unsigned long *m = ((unsigned long *)addr) + (nr >> 6);
- unsigned long old = *m;
- unsigned long mask = (1UL << (nr & 63));
-
- *m = (old & ~mask);
- return ((old & mask) != 0);
-}
-
-static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
-{
- unsigned long *m = ((unsigned long *)addr) + (nr >> 6);
- unsigned long old = *m;
- unsigned long mask = (1UL << (nr & 63));
-
- *m = (old ^ mask);
- return ((old & mask) != 0);
-}
+#include <asm-generic/bitops/non-atomic.h>
#ifdef CONFIG_SMP
#define smp_mb__before_clear_bit() membar_storeload_loadload()
@@ -79,78 +28,15 @@ static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
#define smp_mb__after_clear_bit() barrier()
#endif
-static inline int test_bit(int nr, __const__ volatile unsigned long *addr)
-{
- return (1UL & (addr[nr >> 6] >> (nr & 63))) != 0UL;
-}
-
-/* The easy/cheese version for now. */
-static inline unsigned long ffz(unsigned long word)
-{
- unsigned long result;
-
- result = 0;
- while(word & 1) {
- result++;
- word >>= 1;
- }
- return result;
-}
-
-/**
- * __ffs - find first bit in word.
- * @word: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static inline unsigned long __ffs(unsigned long word)
-{
- unsigned long result = 0;
-
- while (!(word & 1UL)) {
- result++;
- word >>= 1;
- }
- return result;
-}
-
-/*
- * fls: find last bit set.
- */
-
-#define fls(x) generic_fls(x)
-#define fls64(x) generic_fls64(x)
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
#ifdef __KERNEL__
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-static inline int sched_find_first_bit(unsigned long *b)
-{
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(((unsigned int)b[1])))
- return __ffs(b[1]) + 64;
- if (b[1] >> 32)
- return __ffs(b[1] >> 32) + 96;
- return __ffs(b[2]) + 128;
-}
-
-/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-static inline int ffs(int x)
-{
- if (!x)
- return 0;
- return __ffs((unsigned long)x) + 1;
-}
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/ffs.h>
/*
* hweightN: returns the hamming weight (i.e. the number
@@ -193,102 +79,23 @@ static inline unsigned int hweight8(unsigned int w)
#else
-#define hweight64(x) generic_hweight64(x)
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/hweight.h>
#endif
#endif /* __KERNEL__ */
-/**
- * find_next_bit - find the next set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-extern unsigned long find_next_bit(const unsigned long *, unsigned long,
- unsigned long);
-
-/**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first set bit, not the number of the byte
- * containing a bit.
- */
-#define find_first_bit(addr, size) \
- find_next_bit((addr), (size), 0)
-
-/* find_next_zero_bit() finds the first zero bit in a bit string of length
- * 'size' bits, starting the search at bit 'offset'. This is largely based
- * on Linus's ALPHA routines, which are pretty portable BTW.
- */
-
-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)
-
-#define test_and_set_le_bit(nr,addr) \
- test_and_set_bit((nr) ^ 0x38, (addr))
-#define test_and_clear_le_bit(nr,addr) \
- test_and_clear_bit((nr) ^ 0x38, (addr))
-
-static inline int test_le_bit(int nr, __const__ unsigned long * addr)
-{
- int mask;
- __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- return ((mask & *ADDR) != 0);
-}
-
-#define find_first_zero_le_bit(addr, size) \
- find_next_zero_le_bit((addr), (size), 0)
-
-extern unsigned long find_next_zero_le_bit(unsigned long *, unsigned long, unsigned long);
+#include <asm-generic/bitops/find.h>
#ifdef __KERNEL__
-#define __set_le_bit(nr, addr) \
- __set_bit((nr) ^ 0x38, (addr))
-#define __clear_le_bit(nr, addr) \
- __clear_bit((nr) ^ 0x38, (addr))
-#define __test_and_clear_le_bit(nr, addr) \
- __test_and_clear_bit((nr) ^ 0x38, (addr))
-#define __test_and_set_le_bit(nr, addr) \
- __test_and_set_bit((nr) ^ 0x38, (addr))
+#include <asm-generic/bitops/ext2-non-atomic.h>
-#define ext2_set_bit(nr,addr) \
- __test_and_set_le_bit((nr),(unsigned long *)(addr))
#define ext2_set_bit_atomic(lock,nr,addr) \
- test_and_set_le_bit((nr),(unsigned long *)(addr))
-#define ext2_clear_bit(nr,addr) \
- __test_and_clear_le_bit((nr),(unsigned long *)(addr))
+ test_and_set_bit((nr) ^ 0x38,(unsigned long *)(addr))
#define ext2_clear_bit_atomic(lock,nr,addr) \
- test_and_clear_le_bit((nr),(unsigned long *)(addr))
-#define ext2_test_bit(nr,addr) \
- test_le_bit((nr),(unsigned long *)(addr))
-#define ext2_find_first_zero_bit(addr, size) \
- find_first_zero_le_bit((unsigned long *)(addr), (size))
-#define ext2_find_next_zero_bit(addr, size, off) \
- find_next_zero_le_bit((unsigned long *)(addr), (size), (off))
+ test_and_clear_bit((nr) ^ 0x38,(unsigned long *)(addr))
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) \
- test_and_set_bit((nr),(unsigned long *)(addr))
-#define minix_set_bit(nr,addr) \
- set_bit((nr),(unsigned long *)(addr))
-#define minix_test_and_clear_bit(nr,addr) \
- test_and_clear_bit((nr),(unsigned long *)(addr))
-#define minix_test_bit(nr,addr) \
- test_bit((nr),(unsigned long *)(addr))
-#define minix_find_first_zero_bit(addr,size) \
- find_first_zero_bit((unsigned long *)(addr),(size))
+#include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h
index 49d49a28594..6a95d5d0c57 100644
--- a/include/asm-sparc64/floppy.h
+++ b/include/asm-sparc64/floppy.h
@@ -738,7 +738,7 @@ static unsigned long __init sun_floppy_init(void)
if (!sun_floppy_types[0] && sun_floppy_types[1]) {
/*
* Set the drive exchange bit in FCR on NS87303,
- * make shure other bits are sane before doing so.
+ * make sure other bits are sane before doing so.
*/
ns87303_modify(config, FER, FER_EDM, 0);
ns87303_modify(config, ASC, ASC_DRV2_SEL, 0);
diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h
index 34c4b43d3f9..dee40206b22 100644
--- a/include/asm-sparc64/futex.h
+++ b/include/asm-sparc64/futex.h
@@ -83,4 +83,28 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
return ret;
}
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ __asm__ __volatile__(
+ "\n1: lduwa [%2] %%asi, %0\n"
+ "2: casa [%2] %%asi, %0, %1\n"
+ "3:\n"
+ " .section .fixup,#alloc,#execinstr\n"
+ " .align 4\n"
+ "4: ba 3b\n"
+ " mov %3, %0\n"
+ " .previous\n"
+ " .section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .word 1b, 4b\n"
+ " .word 2b, 4b\n"
+ " .previous\n"
+ : "=&r" (oldval)
+ : "r" (newval), "r" (uaddr), "i" (-EFAULT)
+ : "memory");
+
+ return oldval;
+}
+
#endif /* !(_SPARC64_FUTEX_H) */
diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
index 6321f5a0198..4040d127ac3 100644
--- a/include/asm-sparc64/kdebug.h
+++ b/include/asm-sparc64/kdebug.h
@@ -15,12 +15,9 @@ struct die_args {
int signr;
};
-/* Note - you should never unregister because that can race with NMIs.
- * If you really want to do it first unregister - then synchronize_sched
- * - then free.
- */
-int register_die_notifier(struct notifier_block *nb);
-extern struct notifier_block *sparc64die_chain;
+extern int register_die_notifier(struct notifier_block *);
+extern int unregister_die_notifier(struct notifier_block *);
+extern struct atomic_notifier_head sparc64die_chain;
extern void bad_trap(struct pt_regs *, long);
@@ -46,7 +43,7 @@ static inline int notify_die(enum die_val val,char *str, struct pt_regs *regs,
.trapnr = trap,
.signr = sig };
- return notifier_call_chain(&sparc64die_chain, val, &args);
+ return atomic_notifier_call_chain(&sparc64die_chain, val, &args);
}
#endif
diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h
index 66fe4ac59fd..aabb2190672 100644
--- a/include/asm-sparc64/page.h
+++ b/include/asm-sparc64/page.h
@@ -111,6 +111,8 @@ typedef unsigned long pgprot_t;
(_AC(0x0000000070000000,UL)) : \
(_AC(0xfffff80000000000,UL) + (1UL << 32UL)))
+#include <asm-generic/memory_model.h>
+
#endif /* !(__ASSEMBLY__) */
/* to align the pointer to the (next) page boundary */
diff --git a/include/asm-sparc64/poll.h b/include/asm-sparc64/poll.h
index 31b611aa746..ab6b0d1bb4a 100644
--- a/include/asm-sparc64/poll.h
+++ b/include/asm-sparc64/poll.h
@@ -13,6 +13,7 @@
#define POLLWRBAND 256
#define POLLMSG 512
#define POLLREMOVE 1024
+#define POLLRDHUP 2048
struct pollfd {
int fd;
diff --git a/include/asm-um/page.h b/include/asm-um/page.h
index 0229814af31..41364330aff 100644
--- a/include/asm-um/page.h
+++ b/include/asm-um/page.h
@@ -106,9 +106,6 @@ extern unsigned long uml_physmem;
#define __pa(virt) to_phys((void *) (unsigned long) (virt))
#define __va(phys) to_virt((unsigned long) (phys))
-#define page_to_pfn(page) ((page) - mem_map)
-#define pfn_to_page(pfn) (mem_map + (pfn))
-
#define phys_to_pfn(p) ((p) >> PAGE_SHIFT)
#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
@@ -121,6 +118,7 @@ extern struct page *arch_validate(struct page *page, gfp_t mask, int order);
extern void arch_free_page(struct page *page, int order);
#define HAVE_ARCH_FREE_PAGE
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif
diff --git a/include/asm-um/uaccess.h b/include/asm-um/uaccess.h
index 2ee028b8de9..4e460d6f5ac 100644
--- a/include/asm-um/uaccess.h
+++ b/include/asm-um/uaccess.h
@@ -41,16 +41,16 @@
#define __get_user(x, ptr) \
({ \
- const __typeof__(ptr) __private_ptr = ptr; \
- __typeof__(*(__private_ptr)) __private_val; \
- int __private_ret = -EFAULT; \
- (x) = (__typeof__(*(__private_ptr)))0; \
- if (__copy_from_user(&__private_val, (__private_ptr), \
- sizeof(*(__private_ptr))) == 0) {\
- (x) = (__typeof__(*(__private_ptr))) __private_val; \
- __private_ret = 0; \
- } \
- __private_ret; \
+ const __typeof__(ptr) __private_ptr = ptr; \
+ __typeof__(x) __private_val; \
+ int __private_ret = -EFAULT; \
+ (x) = (__typeof__(*(__private_ptr)))0; \
+ if (__copy_from_user((void *) &__private_val, (__private_ptr), \
+ sizeof(*(__private_ptr))) == 0) { \
+ (x) = (__typeof__(*(__private_ptr))) __private_val; \
+ __private_ret = 0; \
+ } \
+ __private_ret; \
})
#define get_user(x, ptr) \
@@ -89,14 +89,3 @@ struct exception_table_entry
};
#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-v850/bitops.h b/include/asm-v850/bitops.h
index 609b9e87222..1f6fd5ab417 100644
--- a/include/asm-v850/bitops.h
+++ b/include/asm-v850/bitops.h
@@ -22,25 +22,11 @@
#ifdef __KERNEL__
-/*
- * The __ functions are not atomic
- */
+#include <asm-generic/bitops/ffz.h>
/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
+ * The __ functions are not atomic
*/
-static inline unsigned long ffz (unsigned long word)
-{
- unsigned long result = 0;
-
- while (word & 1) {
- result++;
- word >>= 1;
- }
- return result;
-}
-
/* In the following constant-bit-op macros, a "g" constraint is used when
we really need an integer ("i" constraint). This is to avoid
@@ -153,203 +139,19 @@ static inline int __test_bit (int nr, const void *addr)
#define smp_mb__before_clear_bit() barrier ()
#define smp_mb__after_clear_bit() barrier ()
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit ((addr), (size), 0)
-
-static inline int find_next_zero_bit(const void *addr, int size, int offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = * (p++);
- tmp |= ~0UL >> (32-offset);
- if (size < 32)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size & ~31UL) {
- if (~ (tmp = * (p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
- found_first:
- tmp |= ~0UL << size;
- found_middle:
- return result + ffz (tmp);
-}
-
-
-/* This is the same as generic_ffs, but we can't use that because it's
- inline and the #include order mucks things up. */
-static inline int generic_ffs_for_find_next_bit(int x)
-{
- int r = 1;
-
- if (!x)
- return 0;
- if (!(x & 0xffff)) {
- x >>= 16;
- r += 16;
- }
- if (!(x & 0xff)) {
- x >>= 8;
- r += 8;
- }
- if (!(x & 0xf)) {
- x >>= 4;
- r += 4;
- }
- if (!(x & 3)) {
- x >>= 2;
- r += 2;
- }
- if (!(x & 1)) {
- x >>= 1;
- r += 1;
- }
- return r;
-}
-
-/*
- * Find next one bit in a bitmap reasonably efficiently.
- */
-static __inline__ unsigned long find_next_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset)
-{
- unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
- unsigned int result = offset & ~31UL;
- unsigned int tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *p++;
- tmp &= ~0UL << offset;
- if (size < 32)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size >= 32) {
- if ((tmp = *p++) != 0)
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp &= ~0UL >> (32 - size);
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
-found_middle:
- return result + generic_ffs_for_find_next_bit(tmp);
-}
-
-/*
- * find_first_bit - find the first set bit in a memory region
- */
-#define find_first_bit(addr, size) \
- find_next_bit((addr), (size), 0)
-
-
-#define ffs(x) generic_ffs (x)
-#define fls(x) generic_fls (x)
-#define fls64(x) generic_fls64(x)
-#define __ffs(x) ffs(x)
-
-
-/*
- * This is just `generic_ffs' from <linux/bitops.h>, except that it assumes
- * that at least one bit is set, and returns the real index of the bit
- * (rather than the bit index + 1, like ffs does).
- */
-static inline int sched_ffs(int x)
-{
- int r = 0;
-
- if (!(x & 0xffff)) {
- x >>= 16;
- r += 16;
- }
- if (!(x & 0xff)) {
- x >>= 8;
- r += 8;
- }
- if (!(x & 0xf)) {
- x >>= 4;
- r += 4;
- }
- if (!(x & 3)) {
- x >>= 2;
- r += 2;
- }
- if (!(x & 1)) {
- x >>= 1;
- r += 1;
- }
- return r;
-}
-
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is set.
- */
-static inline int sched_find_first_bit(unsigned long *b)
-{
- unsigned offs = 0;
- while (! *b) {
- b++;
- offs += 32;
- }
- return sched_ffs (*b) + offs;
-}
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-#define hweight32(x) generic_hweight32 (x)
-#define hweight16(x) generic_hweight16 (x)
-#define hweight8(x) generic_hweight8 (x)
-
-#define ext2_set_bit test_and_set_bit
+#include <asm-generic/bitops/ext2-non-atomic.h>
#define ext2_set_bit_atomic(l,n,a) test_and_set_bit(n,a)
-#define ext2_clear_bit test_and_clear_bit
#define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
-#define ext2_test_bit test_bit
-#define ext2_find_first_zero_bit find_first_zero_bit
-#define ext2_find_next_zero_bit find_next_zero_bit
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit test_and_set_bit
-#define minix_set_bit set_bit
-#define minix_test_and_clear_bit test_and_clear_bit
-#define minix_test_bit test_bit
-#define minix_find_first_zero_bit find_first_zero_bit
+#include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-v850/page.h b/include/asm-v850/page.h
index b4bc85e7b91..ad03c46a1f9 100644
--- a/include/asm-v850/page.h
+++ b/include/asm-v850/page.h
@@ -111,8 +111,7 @@ typedef unsigned long pgprot_t;
#define page_to_virt(page) \
((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
-#define pfn_to_page(pfn) virt_to_page (pfn_to_virt (pfn))
-#define page_to_pfn(page) virt_to_pfn (page_to_virt (page))
+#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#define virt_addr_valid(kaddr) \
@@ -125,6 +124,7 @@ typedef unsigned long pgprot_t;
#endif /* KERNEL */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* __V850_PAGE_H__ */
diff --git a/include/asm-v850/poll.h b/include/asm-v850/poll.h
index 0369562c7e1..c10176c2c28 100644
--- a/include/asm-v850/poll.h
+++ b/include/asm-v850/poll.h
@@ -13,6 +13,7 @@
#define POLLWRBAND 0x0100
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h
index decaa2d540e..5a48e9bcf21 100644
--- a/include/asm-x86_64/apicdef.h
+++ b/include/asm-x86_64/apicdef.h
@@ -39,6 +39,7 @@
#define APIC_SPIV_FOCUS_DISABLED (1<<9)
#define APIC_SPIV_APIC_ENABLED (1<<8)
#define APIC_ISR 0x100
+#define APIC_ISR_NR 0x8 /* Number of 32 bit ISR registers. */
#define APIC_TMR 0x180
#define APIC_IRR 0x200
#define APIC_ESR 0x280
diff --git a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h
index eb4df23e1e4..79212128d0f 100644
--- a/include/asm-x86_64/bitops.h
+++ b/include/asm-x86_64/bitops.h
@@ -356,14 +356,7 @@ static __inline__ unsigned long __fls(unsigned long word)
#ifdef __KERNEL__
-static inline int sched_find_first_bit(const unsigned long *b)
-{
- if (b[0])
- return __ffs(b[0]);
- if (b[1])
- return __ffs(b[1]) + 64;
- return __ffs(b[2]) + 128;
-}
+#include <asm-generic/bitops/sched.h>
/**
* ffs - find first bit set
@@ -412,43 +405,20 @@ static __inline__ int fls(int x)
return r+1;
}
-/**
- * hweightN - returns the hamming weight of a N-bit word
- * @x: the word to weigh
- *
- * The Hamming Weight of a number is the total number of bits set in it.
- */
-
-#define hweight64(x) generic_hweight64(x)
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#include <asm-generic/bitops/hweight.h>
#endif /* __KERNEL__ */
#ifdef __KERNEL__
-#define ext2_set_bit(nr,addr) \
- __test_and_set_bit((nr),(unsigned long*)addr)
+#include <asm-generic/bitops/ext2-non-atomic.h>
+
#define ext2_set_bit_atomic(lock,nr,addr) \
test_and_set_bit((nr),(unsigned long*)addr)
-#define ext2_clear_bit(nr, addr) \
- __test_and_clear_bit((nr),(unsigned long*)addr)
#define ext2_clear_bit_atomic(lock,nr,addr) \
test_and_clear_bit((nr),(unsigned long*)addr)
-#define ext2_test_bit(nr, addr) test_bit((nr),(unsigned long*)addr)
-#define ext2_find_first_zero_bit(addr, size) \
- find_first_zero_bit((unsigned long*)addr, size)
-#define ext2_find_next_zero_bit(addr, size, off) \
- find_next_zero_bit((unsigned long*)addr, size, off)
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,(void*)addr)
-#define minix_set_bit(nr,addr) __set_bit(nr,(void*)addr)
-#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,(void*)addr)
-#define minix_test_bit(nr,addr) test_bit(nr,(void*)addr)
-#define minix_find_first_zero_bit(addr,size) \
- find_first_zero_bit((void*)addr,size)
+
+#include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-x86_64/dmi.h b/include/asm-x86_64/dmi.h
new file mode 100644
index 00000000000..93b2b15d432
--- /dev/null
+++ b/include/asm-x86_64/dmi.h
@@ -0,0 +1,27 @@
+#ifndef _ASM_DMI_H
+#define _ASM_DMI_H 1
+
+#include <asm/io.h>
+
+extern void *dmi_ioremap(unsigned long addr, unsigned long size);
+extern void dmi_iounmap(void *addr, unsigned long size);
+
+#define DMI_MAX_DATA 2048
+
+extern int dmi_alloc_index;
+extern char dmi_alloc_data[DMI_MAX_DATA];
+
+/* This is so early that there is no good way to allocate dynamic memory.
+ Allocate data in an BSS array. */
+static inline void *dmi_alloc(unsigned len)
+{
+ int idx = dmi_alloc_index;
+ if ((dmi_alloc_index += len) > DMI_MAX_DATA)
+ return NULL;
+ return dmi_alloc_data + idx;
+}
+
+#define dmi_ioremap early_ioremap
+#define dmi_iounmap early_iounmap
+
+#endif
diff --git a/include/asm-x86_64/elf.h b/include/asm-x86_64/elf.h
index 43862cd6a56..c98633af07d 100644
--- a/include/asm-x86_64/elf.h
+++ b/include/asm-x86_64/elf.h
@@ -8,6 +8,7 @@
#include <asm/ptrace.h>
#include <asm/user.h>
#include <asm/processor.h>
+#include <asm/compat.h>
/* x86-64 relocation types */
#define R_X86_64_NONE 0 /* No reloc */
@@ -157,6 +158,9 @@ extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
+/* 1GB for 64bit, 8MB for 32bit */
+#define STACK_RND_MASK (is_compat_task() ? 0x7ff : 0x3fffff)
+
#endif
#endif
diff --git a/include/asm-x86_64/floppy.h b/include/asm-x86_64/floppy.h
index af7ded63b51..52825ce689f 100644
--- a/include/asm-x86_64/floppy.h
+++ b/include/asm-x86_64/floppy.h
@@ -155,7 +155,7 @@ static int fd_request_irq(void)
static unsigned long dma_mem_alloc(unsigned long size)
{
- return __get_dma_pages(GFP_KERNEL,get_order(size));
+ return __get_dma_pages(GFP_KERNEL|__GFP_NORETRY,get_order(size));
}
diff --git a/include/asm-x86_64/futex.h b/include/asm-x86_64/futex.h
index 8602c09bf89..9804bf07b09 100644
--- a/include/asm-x86_64/futex.h
+++ b/include/asm-x86_64/futex.h
@@ -94,5 +94,32 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
return ret;
}
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ __asm__ __volatile__(
+ "1: " LOCK_PREFIX "cmpxchgl %3, %1 \n"
+
+ "2: .section .fixup, \"ax\" \n"
+ "3: mov %2, %0 \n"
+ " jmp 2b \n"
+ " .previous \n"
+
+ " .section __ex_table, \"a\" \n"
+ " .align 8 \n"
+ " .quad 1b,3b \n"
+ " .previous \n"
+
+ : "=a" (oldval), "=m" (*uaddr)
+ : "i" (-EFAULT), "r" (newval), "0" (oldval)
+ : "memory"
+ );
+
+ return oldval;
+}
+
#endif
#endif
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index a85fe837082..cafdfb37f0d 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -135,6 +135,9 @@ static inline void __iomem * ioremap (unsigned long offset, unsigned long size)
return __ioremap(offset, size, 0);
}
+extern void *early_ioremap(unsigned long addr, unsigned long size);
+extern void early_iounmap(void *addr, unsigned long size);
+
/*
* This one maps high address device memory and turns off caching for that area.
* it's useful if some control registers are in such an area and write combining
@@ -143,11 +146,6 @@ static inline void __iomem * ioremap (unsigned long offset, unsigned long size)
extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
extern void iounmap(volatile void __iomem *addr);
-/* Use normal IO mappings for DMI */
-#define dmi_ioremap ioremap
-#define dmi_iounmap(x,l) iounmap(x)
-#define dmi_alloc(l) kmalloc(l, GFP_ATOMIC)
-
/*
* ISA I/O bus memory addresses are 1:1 with the physical address.
*/
@@ -202,23 +200,6 @@ static inline __u64 __readq(const volatile void __iomem *addr)
#define mmiowb()
-#ifdef CONFIG_UNORDERED_IO
-static inline void __writel(__u32 val, volatile void __iomem *addr)
-{
- volatile __u32 __iomem *target = addr;
- asm volatile("movnti %1,%0"
- : "=m" (*target)
- : "r" (val) : "memory");
-}
-
-static inline void __writeq(__u64 val, volatile void __iomem *addr)
-{
- volatile __u64 __iomem *target = addr;
- asm volatile("movnti %1,%0"
- : "=m" (*target)
- : "r" (val) : "memory");
-}
-#else
static inline void __writel(__u32 b, volatile void __iomem *addr)
{
*(__force volatile __u32 *)addr = b;
@@ -227,7 +208,6 @@ static inline void __writeq(__u64 b, volatile void __iomem *addr)
{
*(__force volatile __u64 *)addr = b;
}
-#endif
static inline void __writeb(__u8 b, volatile void __iomem *addr)
{
*(__force volatile __u8 *)addr = b;
diff --git a/include/asm-x86_64/kdebug.h b/include/asm-x86_64/kdebug.h
index b9ed4c0c878..cf795631d9b 100644
--- a/include/asm-x86_64/kdebug.h
+++ b/include/asm-x86_64/kdebug.h
@@ -5,21 +5,20 @@
struct pt_regs;
-struct die_args {
+struct die_args {
struct pt_regs *regs;
const char *str;
- long err;
+ long err;
int trapnr;
int signr;
-};
+};
+
+extern int register_die_notifier(struct notifier_block *);
+extern int unregister_die_notifier(struct notifier_block *);
+extern struct atomic_notifier_head die_chain;
-/* Note - you should never unregister because that can race with NMIs.
- If you really want to do it first unregister - then synchronize_sched - then free.
- */
-int register_die_notifier(struct notifier_block *nb);
-extern struct notifier_block *die_chain;
/* Grossly misnamed. */
-enum die_val {
+enum die_val {
DIE_OOPS = 1,
DIE_INT3,
DIE_DEBUG,
@@ -33,8 +32,8 @@ enum die_val {
DIE_CALL,
DIE_NMI_IPI,
DIE_PAGE_FAULT,
-};
-
+};
+
static inline int notify_die(enum die_val val, const char *str,
struct pt_regs *regs, long err, int trap, int sig)
{
@@ -45,7 +44,7 @@ static inline int notify_die(enum die_val val, const char *str,
.trapnr = trap,
.signr = sig
};
- return notifier_call_chain(&die_chain, val, &args);
+ return atomic_notifier_call_chain(&die_chain, val, &args);
}
extern int printk_address(unsigned long address);
diff --git a/include/asm-x86_64/local.h b/include/asm-x86_64/local.h
index 3e72c41727c..bf148037d4e 100644
--- a/include/asm-x86_64/local.h
+++ b/include/asm-x86_64/local.h
@@ -5,7 +5,7 @@
typedef struct
{
- volatile unsigned int counter;
+ volatile unsigned long counter;
} local_t;
#define LOCAL_INIT(i) { (i) }
@@ -16,7 +16,7 @@ typedef struct
static __inline__ void local_inc(local_t *v)
{
__asm__ __volatile__(
- "incl %0"
+ "incq %0"
:"=m" (v->counter)
:"m" (v->counter));
}
@@ -24,7 +24,7 @@ static __inline__ void local_inc(local_t *v)
static __inline__ void local_dec(local_t *v)
{
__asm__ __volatile__(
- "decl %0"
+ "decq %0"
:"=m" (v->counter)
:"m" (v->counter));
}
@@ -32,7 +32,7 @@ static __inline__ void local_dec(local_t *v)
static __inline__ void local_add(unsigned int i, local_t *v)
{
__asm__ __volatile__(
- "addl %1,%0"
+ "addq %1,%0"
:"=m" (v->counter)
:"ir" (i), "m" (v->counter));
}
@@ -40,7 +40,7 @@ static __inline__ void local_add(unsigned int i, local_t *v)
static __inline__ void local_sub(unsigned int i, local_t *v)
{
__asm__ __volatile__(
- "subl %1,%0"
+ "subq %1,%0"
:"=m" (v->counter)
:"ir" (i), "m" (v->counter));
}
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h
index 972c9359f7d..6b18cd8f293 100644
--- a/include/asm-x86_64/mmzone.h
+++ b/include/asm-x86_64/mmzone.h
@@ -15,8 +15,13 @@
#define NODEMAPSIZE 0xfff
/* Simple perfect hash to map physical addresses to node numbers */
-extern int memnode_shift;
-extern u8 memnodemap[NODEMAPSIZE];
+struct memnode {
+ int shift;
+ u8 map[NODEMAPSIZE];
+} ____cacheline_aligned;
+extern struct memnode memnode;
+#define memnode_shift memnode.shift
+#define memnodemap memnode.map
extern struct pglist_data *node_data[];
@@ -39,12 +44,8 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
#define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT)
#define kvaddr_to_nid(kaddr) phys_to_nid(__pa(kaddr))
-extern struct page *pfn_to_page(unsigned long pfn);
-extern unsigned long page_to_pfn(struct page *page);
extern int pfn_valid(unsigned long pfn);
#endif
-#define local_mapnr(kvaddr) \
- ( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) )
#endif
#endif
diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h
index dffe276ca2d..f6cbb4cbb5a 100644
--- a/include/asm-x86_64/numa.h
+++ b/include/asm-x86_64/numa.h
@@ -4,11 +4,11 @@
#include <linux/nodemask.h>
#include <asm/numnodes.h>
-struct node {
+struct bootnode {
u64 start,end;
};
-extern int compute_hash_shift(struct node *nodes, int numnodes);
+extern int compute_hash_shift(struct bootnode *nodes, int numnodes);
extern int pxm_to_node(int nid);
#define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index 615e3e49492..408185bac35 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -123,8 +123,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define __boot_va(x) __va(x)
#define __boot_pa(x) __pa(x)
#ifdef CONFIG_FLATMEM
-#define pfn_to_page(pfn) (mem_map + (pfn))
-#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < end_pfn)
#endif
@@ -140,6 +138,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
#endif /* _X86_64_PAGE_H */
diff --git a/include/asm-x86_64/pda.h b/include/asm-x86_64/pda.h
index c7ab38a601a..b47c3df9ed1 100644
--- a/include/asm-x86_64/pda.h
+++ b/include/asm-x86_64/pda.h
@@ -22,8 +22,8 @@ struct x8664_pda {
int nodenumber; /* number of current node */
unsigned int __softirq_pending;
unsigned int __nmi_count; /* number of NMI on this CPUs */
- struct mm_struct *active_mm;
int mmu_state;
+ struct mm_struct *active_mm;
unsigned apic_timer_irqs;
} ____cacheline_aligned_in_smp;
diff --git a/include/asm-x86_64/pgalloc.h b/include/asm-x86_64/pgalloc.h
index 08cad2482bc..43d4c333a8b 100644
--- a/include/asm-x86_64/pgalloc.h
+++ b/include/asm-x86_64/pgalloc.h
@@ -45,12 +45,39 @@ static inline void pud_free (pud_t *pud)
free_page((unsigned long)pud);
}
+static inline void pgd_list_add(pgd_t *pgd)
+{
+ struct page *page = virt_to_page(pgd);
+
+ spin_lock(&pgd_lock);
+ page->index = (pgoff_t)pgd_list;
+ if (pgd_list)
+ pgd_list->private = (unsigned long)&page->index;
+ pgd_list = page;
+ page->private = (unsigned long)&pgd_list;
+ spin_unlock(&pgd_lock);
+}
+
+static inline void pgd_list_del(pgd_t *pgd)
+{
+ struct page *next, **pprev, *page = virt_to_page(pgd);
+
+ spin_lock(&pgd_lock);
+ next = (struct page *)page->index;
+ pprev = (struct page **)page->private;
+ *pprev = next;
+ if (next)
+ next->private = (unsigned long)pprev;
+ spin_unlock(&pgd_lock);
+}
+
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
unsigned boundary;
pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
if (!pgd)
return NULL;
+ pgd_list_add(pgd);
/*
* Copy kernel pointers in from init.
* Could keep a freelist or slab cache of those because the kernel
@@ -67,6 +94,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
static inline void pgd_free(pgd_t *pgd)
{
BUG_ON((unsigned long)pgd & (PAGE_SIZE-1));
+ pgd_list_del(pgd);
free_page((unsigned long)pgd);
}
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index def90328719..31e83c3bd02 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -420,6 +420,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+extern spinlock_t pgd_lock;
+extern struct page *pgd_list;
+void vmalloc_sync_all(void);
+
#endif /* !__ASSEMBLY__ */
extern int kern_addr_valid(unsigned long addr);
diff --git a/include/asm-x86_64/poll.h b/include/asm-x86_64/poll.h
index c43cbba3191..c0475a9d8bb 100644
--- a/include/asm-x86_64/poll.h
+++ b/include/asm-x86_64/poll.h
@@ -16,6 +16,7 @@
#define POLLWRBAND 0x0200
#define POLLMSG 0x0400
#define POLLREMOVE 0x1000
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index 8c8d88c036e..37a3ec433ee 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -20,6 +20,7 @@
#include <asm/mmsegment.h>
#include <asm/percpu.h>
#include <linux/personality.h>
+#include <linux/cpumask.h>
#define TF_MASK 0x00000100
#define IF_MASK 0x00000200
@@ -65,6 +66,9 @@ struct cpuinfo_x86 {
__u32 x86_power;
__u32 extended_cpuid_level; /* Max extended CPUID function supported */
unsigned long loops_per_jiffy;
+#ifdef CONFIG_SMP
+ cpumask_t llc_shared_map; /* cpus sharing the last level cache */
+#endif
__u8 apicid;
__u8 booted_cores; /* number of cores as seen by OS */
} ____cacheline_aligned;
@@ -354,9 +358,6 @@ struct extended_sigtable {
struct extended_signature sigs[0];
};
-/* '6' because it used to be for P6 only (but now covers Pentium 4 as well) */
-#define MICROCODE_IOCFREE _IO('6',0)
-
#define ASM_NOP1 K8_NOP1
#define ASM_NOP2 K8_NOP2
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index 3ba8fd45fcb..8abf2a43c94 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -53,8 +53,6 @@ extern int sysctl_vsyscall;
extern int nohpet;
extern unsigned long vxtime_hz;
-extern void do_softirq_thunk(void);
-
extern int numa_setup(char *opt);
extern int setup_early_printk(char *);
@@ -129,7 +127,6 @@ extern int fix_aperture;
#define iommu_aperture 0
#define iommu_aperture_allowed 0
#endif
-extern int force_iommu;
extern int reboot_force;
extern int notsc_setup(char *);
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
index 9ccbb2cfd5c..a4fdaeb5c39 100644
--- a/include/asm-x86_64/smp.h
+++ b/include/asm-x86_64/smp.h
@@ -56,6 +56,7 @@ extern cpumask_t cpu_sibling_map[NR_CPUS];
extern cpumask_t cpu_core_map[NR_CPUS];
extern u8 phys_proc_id[NR_CPUS];
extern u8 cpu_core_id[NR_CPUS];
+extern u8 cpu_llc_id[NR_CPUS];
#define SMP_TRAMPOLINE_BASE 0x6000
diff --git a/include/asm-x86_64/string.h b/include/asm-x86_64/string.h
index a3493ee282b..ee6bf275349 100644
--- a/include/asm-x86_64/string.h
+++ b/include/asm-x86_64/string.h
@@ -40,26 +40,15 @@ extern void *__memcpy(void *to, const void *from, size_t len);
#define __HAVE_ARCH_MEMSET
-#define memset __builtin_memset
+void *memset(void *s, int c, size_t n);
#define __HAVE_ARCH_MEMMOVE
void * memmove(void * dest,const void *src,size_t count);
-/* Use C out of line version for memcmp */
-#define memcmp __builtin_memcmp
int memcmp(const void * cs,const void * ct,size_t count);
-
-/* out of line string functions use always C versions */
-#define strlen __builtin_strlen
size_t strlen(const char * s);
-
-#define strcpy __builtin_strcpy
-char * strcpy(char * dest,const char *src);
-
-#define strcat __builtin_strcat
-char * strcat(char * dest, const char * src);
-
-#define strcmp __builtin_strcmp
+char *strcpy(char * dest,const char *src);
+char *strcat(char * dest, const char * src);
int strcmp(const char * cs,const char * ct);
#endif /* __KERNEL__ */
diff --git a/include/asm-x86_64/suspend.h b/include/asm-x86_64/suspend.h
index bb9f40597d0..bc7f81715e5 100644
--- a/include/asm-x86_64/suspend.h
+++ b/include/asm-x86_64/suspend.h
@@ -39,9 +39,7 @@ extern unsigned long saved_context_r12, saved_context_r13, saved_context_r14, sa
extern unsigned long saved_context_eflags;
#define loaddebug(thread,register) \
- __asm__("movq %0,%%db" #register \
- : /* no output */ \
- :"r" ((thread)->debugreg##register))
+ set_debugreg((thread)->debugreg##register, register)
extern void fix_processor_context(void);
diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h
index b7f66034ae7..39759898022 100644
--- a/include/asm-x86_64/system.h
+++ b/include/asm-x86_64/system.h
@@ -70,12 +70,6 @@ extern void load_gs_index(unsigned);
".previous" \
: :"r" (value), "r" (0))
-#define set_debug(value,register) \
- __asm__("movq %0,%%db" #register \
- : /* no output */ \
- :"r" ((unsigned long) value))
-
-
#ifdef __KERNEL__
struct alt_instr {
__u8 *instr; /* original instruction */
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h
index c642f5d9882..9db54e9d17b 100644
--- a/include/asm-x86_64/topology.h
+++ b/include/asm-x86_64/topology.h
@@ -68,4 +68,6 @@ extern int __node_distance(int, int);
#include <asm-generic/topology.h>
+extern cpumask_t cpu_coregroup_map(int cpu);
+
#endif
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index da0341c5794..fcc51635308 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -605,8 +605,12 @@ __SYSCALL(__NR_pselect6, sys_ni_syscall) /* for now */
__SYSCALL(__NR_ppoll, sys_ni_syscall) /* for now */
#define __NR_unshare 272
__SYSCALL(__NR_unshare, sys_unshare)
+#define __NR_set_robust_list 273
+__SYSCALL(__NR_set_robust_list, sys_set_robust_list)
+#define __NR_get_robust_list 274
+__SYSCALL(__NR_get_robust_list, sys_get_robust_list)
-#define __NR_syscall_max __NR_unshare
+#define __NR_syscall_max __NR_get_robust_list
#ifndef __NO_STUBS
diff --git a/include/asm-xtensa/bitops.h b/include/asm-xtensa/bitops.h
index 0a2065f1a37..d815649617a 100644
--- a/include/asm-xtensa/bitops.h
+++ b/include/asm-xtensa/bitops.h
@@ -23,156 +23,11 @@
# error SMP not supported on this architecture
#endif
-static __inline__ void set_bit(int nr, volatile void * addr)
-{
- unsigned long mask = 1 << (nr & 0x1f);
- unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
- unsigned long flags;
-
- local_irq_save(flags);
- *a |= mask;
- local_irq_restore(flags);
-}
-
-static __inline__ void __set_bit(int nr, volatile unsigned long * addr)
-{
- unsigned long mask = 1 << (nr & 0x1f);
- unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
-
- *a |= mask;
-}
-
-static __inline__ void clear_bit(int nr, volatile void * addr)
-{
- unsigned long mask = 1 << (nr & 0x1f);
- unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
- unsigned long flags;
-
- local_irq_save(flags);
- *a &= ~mask;
- local_irq_restore(flags);
-}
-
-static __inline__ void __clear_bit(int nr, volatile unsigned long *addr)
-{
- unsigned long mask = 1 << (nr & 0x1f);
- unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
-
- *a &= ~mask;
-}
-
-/*
- * clear_bit() doesn't provide any barrier for the compiler.
- */
-
#define smp_mb__before_clear_bit() barrier()
#define smp_mb__after_clear_bit() barrier()
-static __inline__ void change_bit(int nr, volatile void * addr)
-{
- unsigned long mask = 1 << (nr & 0x1f);
- unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
- unsigned long flags;
-
- local_irq_save(flags);
- *a ^= mask;
- local_irq_restore(flags);
-}
-
-static __inline__ void __change_bit(int nr, volatile void * addr)
-{
- unsigned long mask = 1 << (nr & 0x1f);
- unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
-
- *a ^= mask;
-}
-
-static __inline__ int test_and_set_bit(int nr, volatile void * addr)
-{
- unsigned long retval;
- unsigned long mask = 1 << (nr & 0x1f);
- unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
- unsigned long flags;
-
- local_irq_save(flags);
- retval = (mask & *a) != 0;
- *a |= mask;
- local_irq_restore(flags);
-
- return retval;
-}
-
-static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
-{
- unsigned long retval;
- unsigned long mask = 1 << (nr & 0x1f);
- unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
-
- retval = (mask & *a) != 0;
- *a |= mask;
-
- return retval;
-}
-
-static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
-{
- unsigned long retval;
- unsigned long mask = 1 << (nr & 0x1f);
- unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
- unsigned long flags;
-
- local_irq_save(flags);
- retval = (mask & *a) != 0;
- *a &= ~mask;
- local_irq_restore(flags);
-
- return retval;
-}
-
-static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
-{
- unsigned long mask = 1 << (nr & 0x1f);
- unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
- unsigned long old = *a;
-
- *a = old & ~mask;
- return (old & mask) != 0;
-}
-
-static __inline__ int test_and_change_bit(int nr, volatile void * addr)
-{
- unsigned long retval;
- unsigned long mask = 1 << (nr & 0x1f);
- unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
- unsigned long flags;
-
- local_irq_save(flags);
-
- retval = (mask & *a) != 0;
- *a ^= mask;
- local_irq_restore(flags);
-
- return retval;
-}
-
-/*
- * non-atomic version; can be reordered
- */
-
-static __inline__ int __test_and_change_bit(int nr, volatile void *addr)
-{
- unsigned long mask = 1 << (nr & 0x1f);
- unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
- unsigned long old = *a;
-
- *a = old ^ mask;
- return (old & mask) != 0;
-}
-
-static __inline__ int test_bit(int nr, const volatile void *addr)
-{
- return 1UL & (((const volatile unsigned int *)addr)[nr>>5] >> (nr&31));
-}
+#include <asm-generic/bitops/atomic.h>
+#include <asm-generic/bitops/non-atomic.h>
#if XCHAL_HAVE_NSA
@@ -245,202 +100,23 @@ static __inline__ int fls (unsigned int x)
{
return __cntlz(x);
}
-#define fls64(x) generic_fls64(x)
-
-static __inline__ int
-find_next_bit(const unsigned long *addr, int size, int offset)
-{
- const unsigned long *p = addr + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *p++;
- tmp &= ~0UL << offset;
- if (size < 32)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size >= 32) {
- if ((tmp = *p++) != 0)
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp &= ~0UL >> (32 - size);
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
-found_middle:
- return result + __ffs(tmp);
-}
-
-/**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first set bit, not the number of the byte
- * containing a bit.
- */
-
-#define find_first_bit(addr, size) \
- find_next_bit((addr), (size), 0)
-
-static __inline__ int
-find_next_zero_bit(const unsigned long *addr, int size, int offset)
-{
- const unsigned long *p = addr + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if (offset) {
- tmp = *p++;
- tmp |= ~0UL >> (32-offset);
- if (size < 32)
- goto found_first;
- if (~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while (size & ~31UL) {
- if (~(tmp = *p++))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp |= ~0UL << size;
-found_middle:
- return result + ffz(tmp);
-}
-
-#define find_first_zero_bit(addr, size) \
- find_next_zero_bit((addr), (size), 0)
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/ext2-non-atomic.h>
#ifdef __XTENSA_EL__
-# define ext2_set_bit(nr,addr) __test_and_set_bit((nr), (addr))
# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr),(addr))
-# define ext2_clear_bit(nr,addr) __test_and_clear_bit((nr), (addr))
# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr),(addr))
-# define ext2_test_bit(nr,addr) test_bit((nr), (addr))
-# define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr),(size))
-# define ext2_find_next_zero_bit(addr, size, offset) \
- find_next_zero_bit((addr), (size), (offset))
#elif defined(__XTENSA_EB__)
-# define ext2_set_bit(nr,addr) __test_and_set_bit((nr) ^ 0x18, (addr))
# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr) ^ 0x18, (addr))
-# define ext2_clear_bit(nr,addr) __test_and_clear_bit((nr) ^ 18, (addr))
# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr)^0x18,(addr))
-# define ext2_test_bit(nr,addr) test_bit((nr) ^ 0x18, (addr))
-# define ext2_find_first_zero_bit(addr, size) \
- ext2_find_next_zero_bit((addr), (size), 0)
-
-static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
-{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
- unsigned long result = offset & ~31UL;
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= 31UL;
- if(offset) {
- /* We hold the little endian value in tmp, but then the
- * shift is illegal. So we could keep a big endian value
- * in tmp, like this:
- *
- * tmp = __swab32(*(p++));
- * tmp |= ~0UL >> (32-offset);
- *
- * but this would decrease preformance, so we change the
- * shift:
- */
- tmp = *(p++);
- tmp |= __swab32(~0UL >> (32-offset));
- if(size < 32)
- goto found_first;
- if(~tmp)
- goto found_middle;
- size -= 32;
- result += 32;
- }
- while(size & ~31UL) {
- if(~(tmp = *(p++)))
- goto found_middle;
- result += 32;
- size -= 32;
- }
- if(!size)
- return result;
- tmp = *p;
-
-found_first:
- /* tmp is little endian, so we would have to swab the shift,
- * see above. But then we have to swab tmp below for ffz, so
- * we might as well do this here.
- */
- return result + ffz(__swab32(tmp) | (~0UL << size));
-found_middle:
- return result + ffz(__swab32(tmp));
-}
-
#else
# error processor byte order undefined!
#endif
-
-#define hweight32(x) generic_hweight32(x)
-#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
-
-/*
- * Find the first bit set in a 140-bit bitmap.
- * The first 100 bits are unlikely to be set.
- */
-
-static inline int sched_find_first_bit(const unsigned long *b)
-{
- if (unlikely(b[0]))
- return __ffs(b[0]);
- if (unlikely(b[1]))
- return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
- return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
-}
-
-
-/* Bitmap functions for the minix filesystem. */
-
-#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/minix.h>
#endif /* __KERNEL__ */
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
index 8ded36f255a..992bac5c125 100644
--- a/include/asm-xtensa/page.h
+++ b/include/asm-xtensa/page.h
@@ -109,10 +109,7 @@ void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page);
#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
#define pfn_valid(pfn) ((unsigned long)pfn < max_mapnr)
-#ifndef CONFIG_DISCONTIGMEM
-# define pfn_to_page(pfn) (mem_map + (pfn))
-# define page_to_pfn(page) ((unsigned long)((page) - mem_map))
-#else
+#ifdef CONFIG_DISCONTIGMEM
# error CONFIG_DISCONTIGMEM not supported
#endif
@@ -130,4 +127,5 @@ void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page);
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#endif /* __KERNEL__ */
+#include <asm-generic/memory_model.h>
#endif /* _XTENSA_PAGE_H */
diff --git a/include/asm-xtensa/poll.h b/include/asm-xtensa/poll.h
index dffe447534e..6fd94773e86 100644
--- a/include/asm-xtensa/poll.h
+++ b/include/asm-xtensa/poll.h
@@ -27,6 +27,7 @@
#define POLLMSG 0x0400
#define POLLREMOVE 0x0800
+#define POLLRDHUP 0x2000
struct pollfd {
int fd;
diff --git a/include/linux/adb.h b/include/linux/adb.h
index e9fdc63483c..b7305b17827 100644
--- a/include/linux/adb.h
+++ b/include/linux/adb.h
@@ -85,7 +85,7 @@ enum adb_message {
ADB_MSG_POST_RESET /* Called after resetting the bus (re-do init & register) */
};
extern struct adb_driver *adb_controller;
-extern struct notifier_block *adb_client_list;
+extern struct blocking_notifier_head adb_client_list;
int adb_request(struct adb_request *req, void (*done)(struct adb_request *),
int flags, int nbytes, ...);
diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
index dc726ffcceb..48ee32a18ac 100644
--- a/include/linux/amba/serial.h
+++ b/include/linux/amba/serial.h
@@ -158,4 +158,10 @@
#define UART01x_RSR_ANY (UART01x_RSR_OE|UART01x_RSR_BE|UART01x_RSR_PE|UART01x_RSR_FE)
#define UART01x_FR_MODEM_ANY (UART01x_FR_DCD|UART01x_FR_DSR|UART01x_FR_CTS)
+#ifndef __ASSEMBLY__
+struct amba_pl010_data {
+ void (*set_mctrl)(struct amba_device *dev, void __iomem *base, unsigned int mctrl);
+};
+#endif
+
#endif
diff --git a/include/linux/audit.h b/include/linux/audit.h
index da3c01955f3..1c47c59058c 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -33,27 +33,42 @@
* 1200 - 1299 messages internal to the audit daemon
* 1300 - 1399 audit event messages
* 1400 - 1499 SE Linux use
- * 1500 - 1999 future use
- * 2000 is for otherwise unclassified kernel audit messages
+ * 1500 - 1599 kernel LSPP events
+ * 1600 - 1699 kernel crypto events
+ * 1700 - 1799 kernel anomaly records
+ * 1800 - 1999 future kernel use (maybe integrity labels and related events)
+ * 2000 is for otherwise unclassified kernel audit messages (legacy)
+ * 2001 - 2099 unused (kernel)
+ * 2100 - 2199 user space anomaly records
+ * 2200 - 2299 user space actions taken in response to anomalies
+ * 2300 - 2399 user space generated LSPP events
+ * 2400 - 2499 user space crypto events
+ * 2500 - 2999 future user space (maybe integrity labels and related events)
*
- * Messages from 1000-1199 are bi-directional. 1200-1299 are exclusively user
- * space. Anything over that is kernel --> user space communication.
+ * Messages from 1000-1199 are bi-directional. 1200-1299 & 2100 - 2999 are
+ * exclusively user space. 1300-2099 is kernel --> user space
+ * communication.
*/
#define AUDIT_GET 1000 /* Get status */
#define AUDIT_SET 1001 /* Set status (enable/disable/auditd) */
-#define AUDIT_LIST 1002 /* List syscall filtering rules */
-#define AUDIT_ADD 1003 /* Add syscall filtering rule */
-#define AUDIT_DEL 1004 /* Delete syscall filtering rule */
+#define AUDIT_LIST 1002 /* List syscall rules -- deprecated */
+#define AUDIT_ADD 1003 /* Add syscall rule -- deprecated */
+#define AUDIT_DEL 1004 /* Delete syscall rule -- deprecated */
#define AUDIT_USER 1005 /* Message from userspace -- deprecated */
#define AUDIT_LOGIN 1006 /* Define the login id and information */
#define AUDIT_WATCH_INS 1007 /* Insert file/dir watch entry */
#define AUDIT_WATCH_REM 1008 /* Remove file/dir watch entry */
#define AUDIT_WATCH_LIST 1009 /* List all file/dir watches */
#define AUDIT_SIGNAL_INFO 1010 /* Get info about sender of signal to auditd */
+#define AUDIT_ADD_RULE 1011 /* Add syscall filtering rule */
+#define AUDIT_DEL_RULE 1012 /* Delete syscall filtering rule */
+#define AUDIT_LIST_RULES 1013 /* List syscall filtering rules */
#define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */
#define AUDIT_USER_AVC 1107 /* We filter this differently */
#define AUDIT_LAST_USER_MSG 1199
+#define AUDIT_FIRST_USER_MSG2 2100 /* More user space messages */
+#define AUDIT_LAST_USER_MSG2 2999
#define AUDIT_DAEMON_START 1200 /* Daemon startup record */
#define AUDIT_DAEMON_END 1201 /* Daemon normal stop record */
@@ -72,6 +87,13 @@
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
#define AUDIT_AVC_PATH 1402 /* dentry, vfsmount pair from avc */
+#define AUDIT_MAC_POLICY_LOAD 1403 /* Policy file load */
+#define AUDIT_MAC_STATUS 1404 /* Changed enforcing,permissive,off */
+#define AUDIT_MAC_CONFIG_CHANGE 1405 /* Changes to booleans */
+
+#define AUDIT_FIRST_KERN_ANOM_MSG 1700
+#define AUDIT_LAST_KERN_ANOM_MSG 1799
+#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
#define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */
@@ -81,8 +103,9 @@
#define AUDIT_FILTER_ENTRY 0x02 /* Apply rule at syscall entry */
#define AUDIT_FILTER_WATCH 0x03 /* Apply rule to file system watches */
#define AUDIT_FILTER_EXIT 0x04 /* Apply rule at syscall exit */
+#define AUDIT_FILTER_TYPE 0x05 /* Apply rule at audit_log_start */
-#define AUDIT_NR_FILTERS 5
+#define AUDIT_NR_FILTERS 6
#define AUDIT_FILTER_PREPEND 0x10 /* Prepend to front of list */
@@ -98,6 +121,13 @@
#define AUDIT_WORD(nr) ((__u32)((nr)/32))
#define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(nr)*32))
+/* This bitmask is used to validate user input. It represents all bits that
+ * are currently used in an audit field constant understood by the kernel.
+ * If you are adding a new #define AUDIT_<whatever>, please ensure that
+ * AUDIT_UNUSED_BITS is updated if need be. */
+#define AUDIT_UNUSED_BITS 0x0FFFFC00
+
+
/* Rule fields */
/* These are useful when checking the
* task structure at task creation time
@@ -114,6 +144,7 @@
#define AUDIT_LOGINUID 9
#define AUDIT_PERS 10
#define AUDIT_ARCH 11
+#define AUDIT_MSGTYPE 12
/* These are ONLY useful when checking
* at syscall exit time (AUDIT_AT_EXIT). */
@@ -128,8 +159,28 @@
#define AUDIT_ARG2 (AUDIT_ARG0+2)
#define AUDIT_ARG3 (AUDIT_ARG0+3)
-#define AUDIT_NEGATE 0x80000000
+#define AUDIT_NEGATE 0x80000000
+/* These are the supported operators.
+ * 4 2 1
+ * = > <
+ * -------
+ * 0 0 0 0 nonsense
+ * 0 0 1 1 <
+ * 0 1 0 2 >
+ * 0 1 1 3 !=
+ * 1 0 0 4 =
+ * 1 0 1 5 <=
+ * 1 1 0 6 >=
+ * 1 1 1 7 all operators
+ */
+#define AUDIT_LESS_THAN 0x10000000
+#define AUDIT_GREATER_THAN 0x20000000
+#define AUDIT_NOT_EQUAL 0x30000000
+#define AUDIT_EQUAL 0x40000000
+#define AUDIT_LESS_THAN_OR_EQUAL (AUDIT_LESS_THAN|AUDIT_EQUAL)
+#define AUDIT_GREATER_THAN_OR_EQUAL (AUDIT_GREATER_THAN|AUDIT_EQUAL)
+#define AUDIT_OPERATORS (AUDIT_EQUAL|AUDIT_NOT_EQUAL)
/* Status symbols */
/* Mask values */
@@ -186,6 +237,26 @@ struct audit_status {
__u32 backlog; /* messages waiting in queue */
};
+/* audit_rule_data supports filter rules with both integer and string
+ * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
+ * AUDIT_LIST_RULES requests.
+ */
+struct audit_rule_data {
+ __u32 flags; /* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
+ __u32 action; /* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
+ __u32 field_count;
+ __u32 mask[AUDIT_BITMASK_SIZE]; /* syscall(s) affected */
+ __u32 fields[AUDIT_MAX_FIELDS];
+ __u32 values[AUDIT_MAX_FIELDS];
+ __u32 fieldflags[AUDIT_MAX_FIELDS];
+ __u32 buflen; /* total length of string fields */
+ char buf[0]; /* string fields buffer */
+};
+
+/* audit_rule is supported to maintain backward compatibility with
+ * userspace. It supports integer fields only and corresponds to
+ * AUDIT_ADD, AUDIT_DEL and AUDIT_LIST requests.
+ */
struct audit_rule { /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
__u32 flags; /* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
__u32 action; /* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
@@ -222,22 +293,33 @@ extern void audit_syscall_entry(struct task_struct *task, int arch,
extern void audit_syscall_exit(struct task_struct *task, int failed, long return_code);
extern void audit_getname(const char *name);
extern void audit_putname(const char *name);
-extern void audit_inode(const char *name, const struct inode *inode, unsigned flags);
+extern void __audit_inode(const char *name, const struct inode *inode, unsigned flags);
+extern void __audit_inode_child(const char *dname, const struct inode *inode,
+ unsigned long pino);
+static inline void audit_inode(const char *name, const struct inode *inode,
+ unsigned flags) {
+ if (unlikely(current->audit_context))
+ __audit_inode(name, inode, flags);
+}
+static inline void audit_inode_child(const char *dname,
+ const struct inode *inode,
+ unsigned long pino) {
+ if (unlikely(current->audit_context))
+ __audit_inode_child(dname, inode, pino);
+}
/* Private API (for audit.c only) */
-extern int audit_receive_filter(int type, int pid, int uid, int seq,
- void *data, uid_t loginuid);
extern unsigned int audit_serial(void);
extern void auditsc_get_stamp(struct audit_context *ctx,
struct timespec *t, unsigned int *serial);
extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid);
extern uid_t audit_get_loginuid(struct audit_context *ctx);
-extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
+extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp);
extern int audit_socketcall(int nargs, unsigned long *args);
extern int audit_sockaddr(int len, void *addr);
extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
extern void audit_signal_info(int sig, struct task_struct *t);
-extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
+extern int audit_set_macxattr(const char *name);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
@@ -245,16 +327,18 @@ extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
#define audit_syscall_exit(t,f,r) do { ; } while (0)
#define audit_getname(n) do { ; } while (0)
#define audit_putname(n) do { ; } while (0)
+#define __audit_inode(n,i,f) do { ; } while (0)
+#define __audit_inode_child(d,i,p) do { ; } while (0)
#define audit_inode(n,i,f) do { ; } while (0)
-#define audit_receive_filter(t,p,u,s,d,l) ({ -EOPNOTSUPP; })
+#define audit_inode_child(d,i,p) do { ; } while (0)
#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
#define audit_get_loginuid(c) ({ -1; })
-#define audit_ipc_perms(q,u,g,m) ({ 0; })
+#define audit_ipc_perms(q,u,g,m,i) ({ 0; })
#define audit_socketcall(n,a) ({ 0; })
#define audit_sockaddr(len, addr) ({ 0; })
#define audit_avc_path(dentry, mnt) ({ 0; })
#define audit_signal_info(s,t) do { ; } while (0)
-#define audit_filter_user(cb,t) ({ 1; })
+#define audit_set_macxattr(n) do { ; } while (0)
#endif
#ifdef CONFIG_AUDIT
@@ -278,12 +362,11 @@ extern void audit_log_d_path(struct audit_buffer *ab,
const char *prefix,
struct dentry *dentry,
struct vfsmount *vfsmnt);
- /* Private API (for auditsc.c only) */
-extern void audit_send_reply(int pid, int seq, int type,
- int done, int multi,
- void *payload, int size);
-extern void audit_log_lost(const char *message);
-extern struct semaphore audit_netlink_sem;
+ /* Private API (for audit.c only) */
+extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
+extern int audit_filter_type(int type);
+extern int audit_receive_filter(int type, int pid, int uid, int seq,
+ void *data, size_t datasz, uid_t loginuid);
#else
#define audit_log(c,g,t,f,...) do { ; } while (0)
#define audit_log_start(c,g,t) ({ NULL; })
@@ -293,6 +376,7 @@ extern struct semaphore audit_netlink_sem;
#define audit_log_hex(a,b,l) do { ; } while (0)
#define audit_log_untrustedstring(a,s) do { ; } while (0)
#define audit_log_d_path(b,p,d,v) do { ; } while (0)
+#define audit_panic(m) do { ; } while (0)
#endif
#endif
#endif
diff --git a/include/linux/auto_fs4.h b/include/linux/auto_fs4.h
index 9343c89d843..0a6bc52ffe8 100644
--- a/include/linux/auto_fs4.h
+++ b/include/linux/auto_fs4.h
@@ -19,18 +19,37 @@
#undef AUTOFS_MIN_PROTO_VERSION
#undef AUTOFS_MAX_PROTO_VERSION
-#define AUTOFS_PROTO_VERSION 4
+#define AUTOFS_PROTO_VERSION 5
#define AUTOFS_MIN_PROTO_VERSION 3
-#define AUTOFS_MAX_PROTO_VERSION 4
+#define AUTOFS_MAX_PROTO_VERSION 5
-#define AUTOFS_PROTO_SUBVERSION 7
+#define AUTOFS_PROTO_SUBVERSION 0
/* Mask for expire behaviour */
#define AUTOFS_EXP_IMMEDIATE 1
#define AUTOFS_EXP_LEAVES 2
-/* New message type */
-#define autofs_ptype_expire_multi 2 /* Expire entry (umount request) */
+/* Daemon notification packet types */
+enum autofs_notify {
+ NFY_NONE,
+ NFY_MOUNT,
+ NFY_EXPIRE
+};
+
+/* Kernel protocol version 4 packet types */
+
+/* Expire entry (umount request) */
+#define autofs_ptype_expire_multi 2
+
+/* Kernel protocol version 5 packet types */
+
+/* Indirect mount missing and expire requests. */
+#define autofs_ptype_missing_indirect 3
+#define autofs_ptype_expire_indirect 4
+
+/* Direct mount missing and expire requests */
+#define autofs_ptype_missing_direct 5
+#define autofs_ptype_expire_direct 6
/* v4 multi expire (via pipe) */
struct autofs_packet_expire_multi {
@@ -40,14 +59,36 @@ struct autofs_packet_expire_multi {
char name[NAME_MAX+1];
};
+/* autofs v5 common packet struct */
+struct autofs_v5_packet {
+ struct autofs_packet_hdr hdr;
+ autofs_wqt_t wait_queue_token;
+ __u32 dev;
+ __u64 ino;
+ __u32 uid;
+ __u32 gid;
+ __u32 pid;
+ __u32 tgid;
+ __u32 len;
+ char name[NAME_MAX+1];
+};
+
+typedef struct autofs_v5_packet autofs_packet_missing_indirect_t;
+typedef struct autofs_v5_packet autofs_packet_expire_indirect_t;
+typedef struct autofs_v5_packet autofs_packet_missing_direct_t;
+typedef struct autofs_v5_packet autofs_packet_expire_direct_t;
+
union autofs_packet_union {
struct autofs_packet_hdr hdr;
struct autofs_packet_missing missing;
struct autofs_packet_expire expire;
struct autofs_packet_expire_multi expire_multi;
+ struct autofs_v5_packet v5_packet;
};
#define AUTOFS_IOC_EXPIRE_MULTI _IOW(0x93,0x66,int)
+#define AUTOFS_IOC_EXPIRE_INDIRECT AUTOFS_IOC_EXPIRE_MULTI
+#define AUTOFS_IOC_EXPIRE_DIRECT AUTOFS_IOC_EXPIRE_MULTI
#define AUTOFS_IOC_PROTOSUBVER _IOR(0x93,0x67,int)
#define AUTOFS_IOC_ASKREGHOST _IOR(0x93,0x68,int)
#define AUTOFS_IOC_TOGGLEREGHOST _IOR(0x93,0x69,int)
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 208650b1ad3..5d1eabcde5d 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -3,88 +3,11 @@
#include <asm/types.h>
/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
- */
-
-static inline int generic_ffs(int x)
-{
- int r = 1;
-
- if (!x)
- return 0;
- if (!(x & 0xffff)) {
- x >>= 16;
- r += 16;
- }
- if (!(x & 0xff)) {
- x >>= 8;
- r += 8;
- }
- if (!(x & 0xf)) {
- x >>= 4;
- r += 4;
- }
- if (!(x & 3)) {
- x >>= 2;
- r += 2;
- }
- if (!(x & 1)) {
- x >>= 1;
- r += 1;
- }
- return r;
-}
-
-/*
- * fls: find last bit set.
- */
-
-static __inline__ int generic_fls(int x)
-{
- int r = 32;
-
- if (!x)
- return 0;
- if (!(x & 0xffff0000u)) {
- x <<= 16;
- r -= 16;
- }
- if (!(x & 0xff000000u)) {
- x <<= 8;
- r -= 8;
- }
- if (!(x & 0xf0000000u)) {
- x <<= 4;
- r -= 4;
- }
- if (!(x & 0xc0000000u)) {
- x <<= 2;
- r -= 2;
- }
- if (!(x & 0x80000000u)) {
- x <<= 1;
- r -= 1;
- }
- return r;
-}
-
-/*
* Include this here because some architectures need generic_ffs/fls in
* scope
*/
#include <asm/bitops.h>
-
-static inline int generic_fls64(__u64 x)
-{
- __u32 h = x >> 32;
- if (h)
- return fls(h) + 32;
- return fls(x);
-}
-
static __inline__ int get_bitmask_order(unsigned int count)
{
int order;
@@ -103,54 +26,9 @@ static __inline__ int get_count_order(unsigned int count)
return order;
}
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-static inline unsigned int generic_hweight32(unsigned int w)
-{
- unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
- res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
- res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
- res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
- return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
-}
-
-static inline unsigned int generic_hweight16(unsigned int w)
-{
- unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555);
- res = (res & 0x3333) + ((res >> 2) & 0x3333);
- res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
- return (res & 0x00FF) + ((res >> 8) & 0x00FF);
-}
-
-static inline unsigned int generic_hweight8(unsigned int w)
-{
- unsigned int res = (w & 0x55) + ((w >> 1) & 0x55);
- res = (res & 0x33) + ((res >> 2) & 0x33);
- return (res & 0x0F) + ((res >> 4) & 0x0F);
-}
-
-static inline unsigned long generic_hweight64(__u64 w)
-{
-#if BITS_PER_LONG < 64
- return generic_hweight32((unsigned int)(w >> 32)) +
- generic_hweight32((unsigned int)w);
-#else
- u64 res;
- res = (w & 0x5555555555555555ul) + ((w >> 1) & 0x5555555555555555ul);
- res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
- res = (res & 0x0F0F0F0F0F0F0F0Ful) + ((res >> 4) & 0x0F0F0F0F0F0F0F0Ful);
- res = (res & 0x00FF00FF00FF00FFul) + ((res >> 8) & 0x00FF00FF00FF00FFul);
- res = (res & 0x0000FFFF0000FFFFul) + ((res >> 16) & 0x0000FFFF0000FFFFul);
- return (res & 0x00000000FFFFFFFFul) + ((res >> 32) & 0x00000000FFFFFFFFul);
-#endif
-}
-
static inline unsigned long hweight_long(unsigned long w)
{
- return sizeof(w) == 4 ? generic_hweight32(w) : generic_hweight64(w);
+ return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
}
/*
@@ -175,4 +53,11 @@ static inline __u32 ror32(__u32 word, unsigned int shift)
return (word >> shift) | (word << (32 - shift));
}
+static inline unsigned fls_long(unsigned long l)
+{
+ if (sizeof(l) == 4)
+ return fls(l);
+ return fls64(l);
+}
+
#endif
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index c179966f1a2..d0cac8b58de 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -55,25 +55,29 @@ struct as_io_context {
struct cfq_queue;
struct cfq_io_context {
- /*
- * circular list of cfq_io_contexts belonging to a process io context
- */
- struct list_head list;
- struct cfq_queue *cfqq[2];
+ struct rb_node rb_node;
void *key;
+ struct cfq_queue *cfqq[2];
+
struct io_context *ioc;
unsigned long last_end_request;
- unsigned long last_queue;
+ sector_t last_request_pos;
+ unsigned long last_queue;
+
unsigned long ttime_total;
unsigned long ttime_samples;
unsigned long ttime_mean;
+ unsigned int seek_samples;
+ u64 seek_total;
+ sector_t seek_mean;
+
struct list_head queue_list;
- void (*dtor)(struct cfq_io_context *);
- void (*exit)(struct cfq_io_context *);
+ void (*dtor)(struct io_context *); /* destructor */
+ void (*exit)(struct io_context *); /* called on task exit */
};
/*
@@ -94,7 +98,7 @@ struct io_context {
int nr_batch_requests; /* Number of requests left in the batch */
struct as_io_context *aic;
- struct cfq_io_context *cic;
+ struct rb_root cic_root;
};
void put_io_context(struct io_context *ioc);
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index 993da8cc970..de3eb8d8ae2 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -38,6 +38,7 @@ typedef struct bootmem_data {
unsigned long last_pos;
unsigned long last_success; /* Previous allocation point. To speed
* up searching */
+ struct list_head list;
} bootmem_data_t;
extern unsigned long __init bootmem_bootmap_pages (unsigned long);
@@ -51,6 +52,9 @@ extern void * __init __alloc_bootmem_low_node(pg_data_t *pgdat,
unsigned long size,
unsigned long align,
unsigned long goal);
+extern void * __init __alloc_bootmem_core(struct bootmem_data *bdata,
+ unsigned long size, unsigned long align, unsigned long goal,
+ unsigned long limit);
#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
extern void __init reserve_bootmem (unsigned long addr, unsigned long size);
#define alloc_bootmem(x) \
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 9f159baf153..fb7e9b7ccbe 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -46,25 +46,28 @@ struct address_space;
typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate);
/*
- * Keep related fields in common cachelines. The most commonly accessed
- * field (b_state) goes at the start so the compiler does not generate
- * indexed addressing for it.
+ * Historically, a buffer_head was used to map a single block
+ * within a page, and of course as the unit of I/O through the
+ * filesystem and block layers. Nowadays the basic I/O unit
+ * is the bio, and buffer_heads are used for extracting block
+ * mappings (via a get_block_t call), for tracking state within
+ * a page (via a page_mapping) and for wrapping bio submission
+ * for backward compatibility reasons (e.g. submit_bh).
*/
struct buffer_head {
- /* First cache line: */
unsigned long b_state; /* buffer state bitmap (see above) */
struct buffer_head *b_this_page;/* circular list of page's buffers */
struct page *b_page; /* the page this bh is mapped to */
- atomic_t b_count; /* users using this block */
- u32 b_size; /* block size */
- sector_t b_blocknr; /* block number */
- char *b_data; /* pointer to data block */
+ sector_t b_blocknr; /* start block number */
+ size_t b_size; /* size of mapping */
+ char *b_data; /* pointer to data within the page */
struct block_device *b_bdev;
bh_end_io_t *b_end_io; /* I/O completion */
void *b_private; /* reserved for b_end_io */
struct list_head b_assoc_buffers; /* associated with another mapping */
+ atomic_t b_count; /* users using this buffer_head */
};
/*
@@ -189,8 +192,8 @@ extern int buffer_heads_over_limit;
* address_spaces.
*/
int try_to_release_page(struct page * page, gfp_t gfp_mask);
-int block_invalidatepage(struct page *page, unsigned long offset);
-int do_invalidatepage(struct page *page, unsigned long offset);
+void block_invalidatepage(struct page *page, unsigned long offset);
+void do_invalidatepage(struct page *page, unsigned long offset);
int block_write_full_page(struct page *page, get_block_t *get_block,
struct writeback_control *wbc);
int block_read_full_page(struct page*, get_block_t*);
@@ -200,7 +203,7 @@ int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*,
int generic_cont_expand(struct inode *inode, loff_t size);
int generic_cont_expand_simple(struct inode *inode, loff_t size);
int block_commit_write(struct page *page, unsigned from, unsigned to);
-int block_sync_page(struct page *);
+void block_sync_page(struct page *);
sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
int block_truncate_page(struct address_space *, loff_t, get_block_t *);
@@ -277,6 +280,7 @@ map_bh(struct buffer_head *bh, struct super_block *sb, sector_t block)
set_buffer_mapped(bh);
bh->b_bdev = sb->s_bdev;
bh->b_blocknr = block;
+ bh->b_size = sb->s_blocksize;
}
/*
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 5a23ce75262..6548b35ab9f 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -357,7 +357,8 @@ static inline kernel_cap_t cap_invert(kernel_cap_t c)
#define cap_is_fs_cap(c) (CAP_TO_MASK(c) & CAP_FS_MASK)
-extern int capable(int cap);
+int capable(int cap);
+int __capable(struct task_struct *t, int cap);
#endif /* __KERNEL__ */
diff --git a/include/linux/cdev.h b/include/linux/cdev.h
index 8da37e29cb8..2216638962d 100644
--- a/include/linux/cdev.h
+++ b/include/linux/cdev.h
@@ -5,13 +5,13 @@
struct cdev {
struct kobject kobj;
struct module *owner;
- struct file_operations *ops;
+ const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
-void cdev_init(struct cdev *, struct file_operations *);
+void cdev_init(struct cdev *, const struct file_operations *);
struct cdev *cdev_alloc(void);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 12848f81bb3..5ca8c6fddb5 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -8,8 +8,8 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#ifndef ASMARM_CLOCK_H
-#define ASMARM_CLOCK_H
+#ifndef __LINUX_CLK_H
+#define __LINUX_CLK_H
struct device;
diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
index cc621ec409d..b3ecf8f71d9 100644
--- a/include/linux/coda_linux.h
+++ b/include/linux/coda_linux.h
@@ -30,9 +30,9 @@ extern struct inode_operations coda_ioctl_inode_operations;
extern struct address_space_operations coda_file_aops;
extern struct address_space_operations coda_symlink_aops;
-extern struct file_operations coda_dir_operations;
-extern struct file_operations coda_file_operations;
-extern struct file_operations coda_ioctl_operations;
+extern const struct file_operations coda_dir_operations;
+extern const struct file_operations coda_file_operations;
+extern const struct file_operations coda_ioctl_operations;
/* operations shared over more than one file */
int coda_open(struct inode *i, struct file *f);
diff --git a/include/linux/compat.h b/include/linux/compat.h
index c9ab2a26348..6d3a654be1a 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -45,6 +45,32 @@ struct compat_tms {
compat_clock_t tms_cstime;
};
+struct compat_timex {
+ compat_uint_t modes;
+ compat_long_t offset;
+ compat_long_t freq;
+ compat_long_t maxerror;
+ compat_long_t esterror;
+ compat_int_t status;
+ compat_long_t constant;
+ compat_long_t precision;
+ compat_long_t tolerance;
+ struct compat_timeval time;
+ compat_long_t tick;
+ compat_long_t ppsfreq;
+ compat_long_t jitter;
+ compat_int_t shift;
+ compat_long_t stabil;
+ compat_long_t jitcnt;
+ compat_long_t calcnt;
+ compat_long_t errcnt;
+ compat_long_t stbcnt;
+
+ compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32;
+ compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32;
+ compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32;
+};
+
#define _COMPAT_NSIG_WORDS (_COMPAT_NSIG / _COMPAT_NSIG_BPW)
typedef struct {
@@ -121,6 +147,24 @@ typedef struct compat_sigevent {
} _sigev_un;
} compat_sigevent_t;
+struct compat_robust_list {
+ compat_uptr_t next;
+};
+
+struct compat_robust_list_head {
+ struct compat_robust_list list;
+ compat_long_t futex_offset;
+ compat_uptr_t list_op_pending;
+};
+
+extern void compat_exit_robust_list(struct task_struct *curr);
+
+asmlinkage long
+compat_sys_set_robust_list(struct compat_robust_list_head __user *head,
+ compat_size_t len);
+asmlinkage long
+compat_sys_get_robust_list(int pid, compat_uptr_t *head_ptr,
+ compat_size_t __user *len_ptr);
long compat_sys_semctl(int first, int second, int third, void __user *uptr);
long compat_sys_msgsnd(int first, int second, int third, void __user *uptr);
@@ -181,5 +225,7 @@ static inline int compat_timespec_compare(struct compat_timespec *lhs,
return lhs->tv_nsec - rhs->tv_nsec;
}
+asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp);
+
#endif /* CONFIG_COMPAT */
#endif /* _LINUX_COMPAT_H */
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
index efb518f16bb..89ab677cb99 100644
--- a/include/linux/compat_ioctl.h
+++ b/include/linux/compat_ioctl.h
@@ -140,6 +140,7 @@ COMPATIBLE_IOCTL(DM_TABLE_DEPS_32)
COMPATIBLE_IOCTL(DM_TABLE_STATUS_32)
COMPATIBLE_IOCTL(DM_LIST_VERSIONS_32)
COMPATIBLE_IOCTL(DM_TARGET_MSG_32)
+COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY_32)
COMPATIBLE_IOCTL(DM_VERSION)
COMPATIBLE_IOCTL(DM_REMOVE_ALL)
COMPATIBLE_IOCTL(DM_LIST_DEVICES)
@@ -155,6 +156,7 @@ COMPATIBLE_IOCTL(DM_TABLE_DEPS)
COMPATIBLE_IOCTL(DM_TABLE_STATUS)
COMPATIBLE_IOCTL(DM_LIST_VERSIONS)
COMPATIBLE_IOCTL(DM_TARGET_MSG)
+COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY)
/* Big K */
COMPATIBLE_IOCTL(PIO_FONT)
COMPATIBLE_IOCTL(GIO_FONT)
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index d612b89dce3..08d50c53aab 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -74,7 +74,6 @@ extern int lock_cpu_hotplug_interruptible(void);
register_cpu_notifier(&fn##_nb); \
}
int cpu_down(unsigned int cpu);
-extern int __attribute__((weak)) smp_prepare_cpu(int cpu);
#define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
#else
#define lock_cpu_hotplug() do { } while (0)
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 60e56c6e03d..9cbb781d6f8 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -67,7 +67,7 @@
*
* int any_online_cpu(mask) First online cpu in mask
*
- * for_each_cpu(cpu) for-loop cpu over cpu_possible_map
+ * for_each_possible_cpu(cpu) for-loop cpu over cpu_possible_map
* for_each_online_cpu(cpu) for-loop cpu over cpu_online_map
* for_each_present_cpu(cpu) for-loop cpu over cpu_present_map
*
@@ -212,17 +212,15 @@ static inline void __cpus_shift_left(cpumask_t *dstp,
bitmap_shift_left(dstp->bits, srcp->bits, n, nbits);
}
-#define first_cpu(src) __first_cpu(&(src), NR_CPUS)
-static inline int __first_cpu(const cpumask_t *srcp, int nbits)
-{
- return min_t(int, nbits, find_first_bit(srcp->bits, nbits));
-}
-
-#define next_cpu(n, src) __next_cpu((n), &(src), NR_CPUS)
-static inline int __next_cpu(int n, const cpumask_t *srcp, int nbits)
-{
- return min_t(int, nbits, find_next_bit(srcp->bits, nbits, n+1));
-}
+#ifdef CONFIG_SMP
+int __first_cpu(const cpumask_t *srcp);
+#define first_cpu(src) __first_cpu(&(src))
+int __next_cpu(int n, const cpumask_t *srcp);
+#define next_cpu(n, src) __next_cpu((n), &(src))
+#else
+#define first_cpu(src) 0
+#define next_cpu(n, src) 1
+#endif
#define cpumask_of_cpu(cpu) \
({ \
@@ -398,27 +396,18 @@ extern cpumask_t cpu_present_map;
#define cpu_present(cpu) ((cpu) == 0)
#endif
-#define any_online_cpu(mask) \
-({ \
- int cpu; \
- for_each_cpu_mask(cpu, (mask)) \
- if (cpu_online(cpu)) \
- break; \
- cpu; \
-})
+#ifdef CONFIG_SMP
+int highest_possible_processor_id(void);
+#define any_online_cpu(mask) __any_online_cpu(&(mask))
+int __any_online_cpu(const cpumask_t *mask);
+#else
+#define highest_possible_processor_id() 0
+#define any_online_cpu(mask) 0
+#endif
-#define for_each_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map)
+#define for_each_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map)
+#define for_each_possible_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map)
#define for_each_online_cpu(cpu) for_each_cpu_mask((cpu), cpu_online_map)
#define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map)
-/* Find the highest possible smp_processor_id() */
-#define highest_possible_processor_id() \
-({ \
- unsigned int cpu, highest = 0; \
- for_each_cpu_mask(cpu, cpu_possible_map) \
- highest = cpu; \
- highest; \
-})
-
-
#endif /* __LINUX_CPUMASK_H */
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
index 534d750d922..32503657f14 100644
--- a/include/linux/crash_dump.h
+++ b/include/linux/crash_dump.h
@@ -11,7 +11,7 @@
extern unsigned long long elfcorehdr_addr;
extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
unsigned long, int);
-extern struct file_operations proc_vmcore_operations;
+extern const struct file_operations proc_vmcore_operations;
extern struct proc_dir_entry *proc_vmcore;
#endif /* CONFIG_CRASH_DUMP */
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 4361f378997..d10bd30c337 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -162,6 +162,8 @@ d_iput: no no no yes
#define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
#define DCACHE_UNHASHED 0x0010
+#define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched */
+
extern spinlock_t dcache_lock;
/**
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 4b0428e335b..176e2d37157 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -29,7 +29,7 @@ struct debugfs_blob_wrapper {
#if defined(CONFIG_DEBUG_FS)
struct dentry *debugfs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data,
- struct file_operations *fops);
+ const struct file_operations *fops);
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 51e0e95a421..aee10b2ea4c 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -97,6 +97,7 @@ struct io_restrictions {
unsigned short hardsect_size;
unsigned int max_segment_size;
unsigned long seg_boundary_mask;
+ unsigned char no_cluster; /* inverted so that 0 is default */
};
struct dm_target {
diff --git a/include/linux/dio.h b/include/linux/dio.h
index fae9395fcf4..1e65ebc2a3d 100644
--- a/include/linux/dio.h
+++ b/include/linux/dio.h
@@ -276,37 +276,5 @@ static inline void dio_set_drvdata (struct dio_dev *d, void *data)
dev_set_drvdata(&d->dev, data);
}
-/*
- * A helper function which helps ensure correct dio_driver
- * setup and cleanup for commonly-encountered hotplug/modular cases
- *
- * This MUST stay in a header, as it checks for -DMODULE
- */
-static inline int dio_module_init(struct dio_driver *drv)
-{
- int rc = dio_register_driver(drv);
-
- if (rc > 0)
- return 0;
-
- /* iff CONFIG_HOTPLUG and built into kernel, we should
- * leave the driver around for future hotplug events.
- * For the module case, a hotplug daemon of some sort
- * should load a module in response to an insert event. */
-#if defined(CONFIG_HOTPLUG) && !defined(MODULE)
- if (rc == 0)
- return 0;
-#else
- if (rc == 0)
- rc = -ENODEV;
-#endif
-
- /* if we get here, we need to clean up DIO driver instance
- * and return some sort of error */
- dio_unregister_driver(drv);
-
- return rc;
-}
-
#endif /* __KERNEL__ */
#endif /* ndef _LINUX_DIO_H */
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
index fa75ba0d635..c67c6786612 100644
--- a/include/linux/dm-ioctl.h
+++ b/include/linux/dm-ioctl.h
@@ -80,6 +80,16 @@
*
* DM_TARGET_MSG:
* Pass a message string to the target at a specific offset of a device.
+ *
+ * DM_DEV_SET_GEOMETRY:
+ * Set the geometry of a device by passing in a string in this format:
+ *
+ * "cylinders heads sectors_per_track start_sector"
+ *
+ * Beware that CHS geometry is nearly obsolete and only provided
+ * for compatibility with dm devices that can be booted by a PC
+ * BIOS. See struct hd_geometry for range limits. Also note that
+ * the geometry is erased if the device size changes.
*/
/*
@@ -218,6 +228,7 @@ enum {
/* Added later */
DM_LIST_VERSIONS_CMD,
DM_TARGET_MSG_CMD,
+ DM_DEV_SET_GEOMETRY_CMD
};
/*
@@ -247,6 +258,7 @@ typedef char ioctl_struct[308];
#define DM_TABLE_STATUS_32 _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, ioctl_struct)
#define DM_LIST_VERSIONS_32 _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, ioctl_struct)
#define DM_TARGET_MSG_32 _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, ioctl_struct)
+#define DM_DEV_SET_GEOMETRY_32 _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, ioctl_struct)
#endif
#define DM_IOCTL 0xfd
@@ -270,11 +282,12 @@ typedef char ioctl_struct[308];
#define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl)
#define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl)
+#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 4
-#define DM_VERSION_MINOR 5
+#define DM_VERSION_MINOR 6
#define DM_VERSION_PATCHLEVEL 0
-#define DM_VERSION_EXTRA "-ioctl (2005-10-04)"
+#define DM_VERSION_EXTRA "-ioctl (2006-02-17)"
/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index a8731062a74..9b4751aecc2 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -21,6 +21,7 @@ enum dma_data_direction {
#define DMA_30BIT_MASK 0x000000003fffffffULL
#define DMA_29BIT_MASK 0x000000001fffffffULL
#define DMA_28BIT_MASK 0x000000000fffffffULL
+#define DMA_24BIT_MASK 0x0000000000ffffffULL
#include <asm/dma-mapping.h>
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index 2e6bbe01415..64fd6c36660 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -68,6 +68,7 @@ extern char * dmi_get_system_info(int field);
extern struct dmi_device * dmi_find_device(int type, const char *name,
struct dmi_device *from);
extern void dmi_scan_machine(void);
+extern int dmi_get_year(int field);
#else
@@ -75,6 +76,7 @@ static inline int dmi_check_system(struct dmi_system_id *list) { return 0; }
static inline char * dmi_get_system_info(int field) { return NULL; }
static inline struct dmi_device * dmi_find_device(int type, const char *name,
struct dmi_device *from) { return NULL; }
+static inline int dmi_get_year(int year) { return 0; }
#endif
diff --git a/include/linux/efi.h b/include/linux/efi.h
index c7c5dd31618..e203613d3ae 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -240,19 +240,21 @@ struct efi_memory_map {
unsigned long desc_size;
};
+#define EFI_INVALID_TABLE_ADDR (~0UL)
+
/*
* All runtime access to EFI goes through this structure:
*/
extern struct efi {
efi_system_table_t *systab; /* EFI system table */
- void *mps; /* MPS table */
- void *acpi; /* ACPI table (IA64 ext 0.71) */
- void *acpi20; /* ACPI table (ACPI 2.0) */
- void *smbios; /* SM BIOS table */
- void *sal_systab; /* SAL system table */
- void *boot_info; /* boot info table */
- void *hcdp; /* HCDP table */
- void *uga; /* UGA table */
+ unsigned long mps; /* MPS table */
+ unsigned long acpi; /* ACPI table (IA64 ext 0.71) */
+ unsigned long acpi20; /* ACPI table (ACPI 2.0) */
+ unsigned long smbios; /* SM BIOS table */
+ unsigned long sal_systab; /* SAL system table */
+ unsigned long boot_info; /* boot info table */
+ unsigned long hcdp; /* HCDP table */
+ unsigned long uga; /* UGA table */
efi_get_time_t *get_time;
efi_set_time_t *set_time;
efi_get_wakeup_time_t *get_wakeup_time;
@@ -292,6 +294,8 @@ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if pos
extern u64 efi_get_iobase (void);
extern u32 efi_mem_type (unsigned long phys_addr);
extern u64 efi_mem_attributes (unsigned long phys_addr);
+extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size,
+ u64 attr);
extern int __init efi_uart_console_only (void);
extern void efi_initialize_iomem_resources(struct resource *code_resource,
struct resource *data_resource);
diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h
index 28f368c526f..fbfa6b52e2f 100644
--- a/include/linux/efs_fs.h
+++ b/include/linux/efs_fs.h
@@ -37,7 +37,7 @@ static inline struct efs_sb_info *SUPER_INFO(struct super_block *sb)
struct statfs;
extern struct inode_operations efs_dir_inode_operations;
-extern struct file_operations efs_dir_operations;
+extern const struct file_operations efs_dir_operations;
extern struct address_space_operations efs_symlink_aops;
extern void efs_read_inode(struct inode *);
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index e7239f2f97a..3ade6a4e3bd 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -36,7 +36,8 @@ struct statfs;
* Define EXT3_RESERVATION to reserve data blocks for expanding files
*/
#define EXT3_DEFAULT_RESERVE_BLOCKS 8
-#define EXT3_MAX_RESERVE_BLOCKS 1024
+/*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */
+#define EXT3_MAX_RESERVE_BLOCKS 1027
#define EXT3_RESERVE_WINDOW_NOT_ALLOCATED 0
/*
* Always enable hashed directories
@@ -732,6 +733,8 @@ struct dir_private_info {
extern int ext3_bg_has_super(struct super_block *sb, int group);
extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group);
extern int ext3_new_block (handle_t *, struct inode *, unsigned long, int *);
+extern int ext3_new_blocks (handle_t *, struct inode *, unsigned long,
+ unsigned long *, int *);
extern void ext3_free_blocks (handle_t *, struct inode *, unsigned long,
unsigned long);
extern void ext3_free_blocks_sb (handle_t *, struct super_block *,
@@ -775,9 +778,9 @@ extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
-int ext3_get_block_handle(handle_t *handle, struct inode *inode,
- sector_t iblock, struct buffer_head *bh_result, int create,
- int extend_disksize);
+int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
+ sector_t iblock, unsigned long maxblocks, struct buffer_head *bh_result,
+ int create, int extend_disksize);
extern void ext3_read_inode (struct inode *);
extern int ext3_write_inode (struct inode *, int);
@@ -830,11 +833,11 @@ do { \
*/
/* dir.c */
-extern struct file_operations ext3_dir_operations;
+extern const struct file_operations ext3_dir_operations;
/* file.c */
extern struct inode_operations ext3_file_inode_operations;
-extern struct file_operations ext3_file_operations;
+extern const struct file_operations ext3_file_operations;
/* namei.c */
extern struct inode_operations ext3_dir_inode_operations;
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 2cb19e6503a..d03fadfcafe 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -734,7 +734,7 @@ struct fb_tile_ops {
/* A driver may set this flag to indicate that it does want a set_par to be
* called every time when fbcon_switch is executed. The advantage is that with
- * this flag set you can really be shure that set_par is always called before
+ * this flag set you can really be sure that set_par is always called before
* any of the functions dependant on the correct hardware state or altering
* that state, even if you are using some broken X releases. The disadvantage
* is that it introduces unwanted delays to every console switch if set_par
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 215696a0f16..408fe89498f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -65,6 +65,11 @@ extern int dir_notify_enable;
#define FMODE_PREAD 8
#define FMODE_PWRITE FMODE_PREAD /* These go hand in hand */
+/* File is being opened for execution. Primary users of this flag are
+ distributed filesystems that can use it to achieve correct ETXTBUSY
+ behavior for cross-node execution/opening_for_writing of files */
+#define FMODE_EXEC 16
+
#define RW_MASK 1
#define RWA_MASK 2
#define READ 0
@@ -247,9 +252,6 @@ extern void __init files_init(unsigned long);
struct buffer_head;
typedef int (get_block_t)(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create);
-typedef int (get_blocks_t)(struct inode *inode, sector_t iblock,
- unsigned long max_blocks,
- struct buffer_head *bh_result, int create);
typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
ssize_t bytes, void *private);
@@ -345,7 +347,7 @@ struct writeback_control;
struct address_space_operations {
int (*writepage)(struct page *page, struct writeback_control *wbc);
int (*readpage)(struct file *, struct page *);
- int (*sync_page)(struct page *);
+ void (*sync_page)(struct page *);
/* Write back some dirty pages from this mapping. */
int (*writepages)(struct address_space *, struct writeback_control *);
@@ -364,7 +366,7 @@ struct address_space_operations {
int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
/* Unfortunately this kludge is needed for FIBMAP. Don't use it */
sector_t (*bmap)(struct address_space *, sector_t);
- int (*invalidatepage) (struct page *, unsigned long);
+ void (*invalidatepage) (struct page *, unsigned long);
int (*releasepage) (struct page *, gfp_t);
ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
loff_t offset, unsigned long nr_segs);
@@ -408,6 +410,9 @@ struct block_device {
struct list_head bd_inodes;
void * bd_holder;
int bd_holders;
+#ifdef CONFIG_SYSFS
+ struct list_head bd_holder_list;
+#endif
struct block_device * bd_contains;
unsigned bd_block_size;
struct hd_struct * bd_part;
@@ -485,13 +490,13 @@ struct inode {
unsigned int i_blkbits;
unsigned long i_blksize;
unsigned long i_version;
- unsigned long i_blocks;
+ blkcnt_t i_blocks;
unsigned short i_bytes;
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
struct mutex i_mutex;
struct rw_semaphore i_alloc_sem;
struct inode_operations *i_op;
- struct file_operations *i_fop; /* former ->i_op->default_file_ops */
+ const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
struct super_block *i_sb;
struct file_lock *i_flock;
struct address_space *i_mapping;
@@ -631,7 +636,7 @@ struct file {
} f_u;
struct dentry *f_dentry;
struct vfsmount *f_vfsmnt;
- struct file_operations *f_op;
+ const struct file_operations *f_op;
atomic_t f_count;
unsigned int f_flags;
mode_t f_mode;
@@ -673,7 +678,6 @@ extern spinlock_t files_lock;
#define FL_POSIX 1
#define FL_FLOCK 2
#define FL_ACCESS 8 /* not trying to lock, just looking */
-#define FL_LOCKD 16 /* lock held by rpc.lockd */
#define FL_LEASE 32 /* lease held on this file */
#define FL_SLEEP 128 /* A blocking lock */
@@ -737,8 +741,6 @@ struct file_lock {
#define OFFT_OFFSET_MAX INT_LIMIT(off_t)
#endif
-extern struct list_head file_lock_list;
-
#include <linux/fcntl.h>
extern int fcntl_getlk(struct file *, struct flock __user *);
@@ -760,10 +762,10 @@ extern void locks_init_lock(struct file_lock *);
extern void locks_copy_lock(struct file_lock *, struct file_lock *);
extern void locks_remove_posix(struct file *, fl_owner_t);
extern void locks_remove_flock(struct file *);
-extern struct file_lock *posix_test_lock(struct file *, struct file_lock *);
+extern int posix_test_lock(struct file *, struct file_lock *, struct file_lock *);
+extern int posix_lock_file_conf(struct file *, struct file_lock *, struct file_lock *);
extern int posix_lock_file(struct file *, struct file_lock *);
extern int posix_lock_file_wait(struct file *, struct file_lock *);
-extern void posix_block_lock(struct file_lock *, struct file_lock *);
extern int posix_unblock_lock(struct file *, struct file_lock *);
extern int posix_locks_deadlock(struct file_lock *, struct file_lock *);
extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
@@ -1092,6 +1094,7 @@ struct super_operations {
void (*umount_begin) (struct super_block *);
int (*show_options)(struct seq_file *, struct vfsmount *);
+ int (*show_stats)(struct seq_file *, struct vfsmount *);
ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
@@ -1387,11 +1390,11 @@ extern void bd_set_size(struct block_device *, loff_t size);
extern void bd_forget(struct inode *inode);
extern void bdput(struct block_device *);
extern struct block_device *open_by_devnum(dev_t, unsigned);
-extern struct file_operations def_blk_fops;
+extern const struct file_operations def_blk_fops;
extern struct address_space_operations def_blk_aops;
-extern struct file_operations def_chr_fops;
-extern struct file_operations bad_sock_fops;
-extern struct file_operations def_fifo_fops;
+extern const struct file_operations def_chr_fops;
+extern const struct file_operations bad_sock_fops;
+extern const struct file_operations def_fifo_fops;
extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long);
extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long);
@@ -1399,12 +1402,19 @@ extern int blkdev_get(struct block_device *, mode_t, unsigned);
extern int blkdev_put(struct block_device *);
extern int bd_claim(struct block_device *, void *);
extern void bd_release(struct block_device *);
+#ifdef CONFIG_SYSFS
+extern int bd_claim_by_disk(struct block_device *, void *, struct gendisk *);
+extern void bd_release_from_disk(struct block_device *, struct gendisk *);
+#else
+#define bd_claim_by_disk(bdev, holder, disk) bd_claim(bdev, holder)
+#define bd_release_from_disk(bdev, disk) bd_release(bdev)
+#endif
/* fs/char_dev.c */
extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);
extern int register_chrdev_region(dev_t, unsigned, const char *);
extern int register_chrdev(unsigned int, const char *,
- struct file_operations *);
+ const struct file_operations *);
extern int unregister_chrdev(unsigned int, const char *);
extern void unregister_chrdev_region(dev_t, unsigned);
extern int chrdev_open(struct inode *, struct file *);
@@ -1434,9 +1444,9 @@ extern void init_special_inode(struct inode *, umode_t, dev_t);
extern void make_bad_inode(struct inode *);
extern int is_bad_inode(struct inode *);
-extern struct file_operations read_fifo_fops;
-extern struct file_operations write_fifo_fops;
-extern struct file_operations rdwr_fifo_fops;
+extern const struct file_operations read_fifo_fops;
+extern const struct file_operations write_fifo_fops;
+extern const struct file_operations rdwr_fifo_fops;
extern int fs_may_remount_ro(struct super_block *);
@@ -1558,7 +1568,6 @@ extern void destroy_inode(struct inode *);
extern struct inode *new_inode(struct super_block *);
extern int remove_suid(struct dentry *);
extern void remove_dquot_ref(struct super_block *, int, struct list_head *);
-extern struct mutex iprune_mutex;
extern void __insert_inode_hash(struct inode *, unsigned long hashval);
extern void remove_inode_hash(struct inode *);
@@ -1643,7 +1652,7 @@ static inline void do_generic_file_read(struct file * filp, loff_t *ppos,
ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
struct block_device *bdev, const struct iovec *iov, loff_t offset,
- unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io,
+ unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
int lock_type);
enum {
@@ -1654,32 +1663,32 @@ enum {
static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb,
struct inode *inode, struct block_device *bdev, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks,
+ loff_t offset, unsigned long nr_segs, get_block_t get_block,
dio_iodone_t end_io)
{
return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
- nr_segs, get_blocks, end_io, DIO_LOCKING);
+ nr_segs, get_block, end_io, DIO_LOCKING);
}
static inline ssize_t blockdev_direct_IO_no_locking(int rw, struct kiocb *iocb,
struct inode *inode, struct block_device *bdev, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks,
+ loff_t offset, unsigned long nr_segs, get_block_t get_block,
dio_iodone_t end_io)
{
return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
- nr_segs, get_blocks, end_io, DIO_NO_LOCKING);
+ nr_segs, get_block, end_io, DIO_NO_LOCKING);
}
static inline ssize_t blockdev_direct_IO_own_locking(int rw, struct kiocb *iocb,
struct inode *inode, struct block_device *bdev, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks,
+ loff_t offset, unsigned long nr_segs, get_block_t get_block,
dio_iodone_t end_io)
{
return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
- nr_segs, get_blocks, end_io, DIO_OWN_LOCKING);
+ nr_segs, get_block, end_io, DIO_OWN_LOCKING);
}
-extern struct file_operations generic_ro_fops;
+extern const struct file_operations generic_ro_fops;
#define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
@@ -1735,9 +1744,9 @@ extern int simple_commit_write(struct file *file, struct page *page,
extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *);
extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
-extern struct file_operations simple_dir_operations;
+extern const struct file_operations simple_dir_operations;
extern struct inode_operations simple_dir_inode_operations;
-struct tree_descr { char *name; struct file_operations *ops; int mode; };
+struct tree_descr { char *name; const struct file_operations *ops; int mode; };
struct dentry *d_alloc_name(struct dentry *, const char *);
extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count);
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 03b8e7932b8..11438eff4d4 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -15,6 +15,26 @@
#include <linux/dnotify.h>
#include <linux/inotify.h>
+#include <linux/audit.h>
+
+/*
+ * fsnotify_d_instantiate - instantiate a dentry for inode
+ * Called with dcache_lock held.
+ */
+static inline void fsnotify_d_instantiate(struct dentry *entry,
+ struct inode *inode)
+{
+ inotify_d_instantiate(entry, inode);
+}
+
+/*
+ * fsnotify_d_move - entry has been moved
+ * Called with dcache_lock and entry->d_lock held.
+ */
+static inline void fsnotify_d_move(struct dentry *entry)
+{
+ inotify_d_move(entry);
+}
/*
* fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
@@ -45,6 +65,8 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
if (source) {
inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL);
}
+ audit_inode_child(old_name, source, old_dir->i_ino);
+ audit_inode_child(new_name, target, new_dir->i_ino);
}
/*
@@ -70,19 +92,22 @@ static inline void fsnotify_inoderemove(struct inode *inode)
/*
* fsnotify_create - 'name' was linked in
*/
-static inline void fsnotify_create(struct inode *inode, const char *name)
+static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
{
inode_dir_notify(inode, DN_CREATE);
- inotify_inode_queue_event(inode, IN_CREATE, 0, name);
+ inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name);
+ audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino);
}
/*
* fsnotify_mkdir - directory 'name' was created
*/
-static inline void fsnotify_mkdir(struct inode *inode, const char *name)
+static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
{
inode_dir_notify(inode, DN_CREATE);
- inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, name);
+ inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0,
+ dentry->d_name.name);
+ audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino);
}
/*
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 10f96c31971..966a5b3da43 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -1,6 +1,8 @@
#ifndef _LINUX_FUTEX_H
#define _LINUX_FUTEX_H
+#include <linux/sched.h>
+
/* Second argument to futex syscall */
@@ -11,10 +13,97 @@
#define FUTEX_CMP_REQUEUE 4
#define FUTEX_WAKE_OP 5
+/*
+ * Support for robust futexes: the kernel cleans up held futexes at
+ * thread exit time.
+ */
+
+/*
+ * Per-lock list entry - embedded in user-space locks, somewhere close
+ * to the futex field. (Note: user-space uses a double-linked list to
+ * achieve O(1) list add and remove, but the kernel only needs to know
+ * about the forward link)
+ *
+ * NOTE: this structure is part of the syscall ABI, and must not be
+ * changed.
+ */
+struct robust_list {
+ struct robust_list __user *next;
+};
+
+/*
+ * Per-thread list head:
+ *
+ * NOTE: this structure is part of the syscall ABI, and must only be
+ * changed if the change is first communicated with the glibc folks.
+ * (When an incompatible change is done, we'll increase the structure
+ * size, which glibc will detect)
+ */
+struct robust_list_head {
+ /*
+ * The head of the list. Points back to itself if empty:
+ */
+ struct robust_list list;
+
+ /*
+ * This relative offset is set by user-space, it gives the kernel
+ * the relative position of the futex field to examine. This way
+ * we keep userspace flexible, to freely shape its data-structure,
+ * without hardcoding any particular offset into the kernel:
+ */
+ long futex_offset;
+
+ /*
+ * The death of the thread may race with userspace setting
+ * up a lock's links. So to handle this race, userspace first
+ * sets this field to the address of the to-be-taken lock,
+ * then does the lock acquire, and then adds itself to the
+ * list, and then clears this field. Hence the kernel will
+ * always have full knowledge of all locks that the thread
+ * _might_ have taken. We check the owner TID in any case,
+ * so only truly owned locks will be handled.
+ */
+ struct robust_list __user *list_op_pending;
+};
+
+/*
+ * Are there any waiters for this robust futex:
+ */
+#define FUTEX_WAITERS 0x80000000
+
+/*
+ * The kernel signals via this bit that a thread holding a futex
+ * has exited without unlocking the futex. The kernel also does
+ * a FUTEX_WAKE on such futexes, after setting the bit, to wake
+ * up any possible waiters:
+ */
+#define FUTEX_OWNER_DIED 0x40000000
+
+/*
+ * The rest of the robust-futex field is for the TID:
+ */
+#define FUTEX_TID_MASK 0x3fffffff
+
+/*
+ * This limit protects against a deliberately circular list.
+ * (Not worth introducing an rlimit for it)
+ */
+#define ROBUST_LIST_LIMIT 2048
+
long do_futex(unsigned long uaddr, int op, int val,
unsigned long timeout, unsigned long uaddr2, int val2,
int val3);
+extern int handle_futex_death(u32 __user *uaddr, struct task_struct *curr);
+
+#ifdef CONFIG_FUTEX
+extern void exit_robust_list(struct task_struct *curr);
+#else
+static inline void exit_robust_list(struct task_struct *curr)
+{
+}
+#endif
+
#define FUTEX_OP_SET 0 /* *(int *)UADDR2 = OPARG; */
#define FUTEX_OP_ADD 1 /* *(int *)UADDR2 += OPARG; */
#define FUTEX_OP_OR 2 /* *(int *)UADDR2 |= OPARG; */
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index 2401dea2b86..9c8e6da2393 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -119,7 +119,7 @@ static inline void gameport_set_name(struct gameport *gameport, const char *name
}
/*
- * Use the following fucntions to manipulate gameport's per-port
+ * Use the following functions to manipulate gameport's per-port
* driver-specific data.
*/
static inline void *gameport_get_drvdata(struct gameport *gameport)
@@ -133,7 +133,7 @@ static inline void gameport_set_drvdata(struct gameport *gameport, void *data)
}
/*
- * Use the following fucntions to pin gameport's driver in process context
+ * Use the following functions to pin gameport's driver in process context
*/
static inline int gameport_pin_driver(struct gameport *gameport)
{
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index fd647fde5ec..10a27f29d69 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -78,6 +78,7 @@ struct hd_struct {
sector_t start_sect;
sector_t nr_sects;
struct kobject kobj;
+ struct kobject *holder_dir;
unsigned ios[2], sectors[2]; /* READs and WRITEs */
int policy, partno;
};
@@ -89,12 +90,12 @@ struct hd_struct {
#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
struct disk_stats {
- unsigned sectors[2]; /* READs and WRITEs */
- unsigned ios[2];
- unsigned merges[2];
- unsigned ticks[2];
- unsigned io_ticks;
- unsigned time_in_queue;
+ unsigned long sectors[2]; /* READs and WRITEs */
+ unsigned long ios[2];
+ unsigned long merges[2];
+ unsigned long ticks[2];
+ unsigned long io_ticks;
+ unsigned long time_in_queue;
};
struct gendisk {
@@ -114,6 +115,8 @@ struct gendisk {
int number; /* more of the same */
struct device *driverfs_dev;
struct kobject kobj;
+ struct kobject *holder_dir;
+ struct kobject *slave_dir;
struct timer_rand_state *random;
int policy;
@@ -149,14 +152,14 @@ struct disk_attribute {
({ \
typeof(gendiskp->dkstats->field) res = 0; \
int i; \
- for_each_cpu(i) \
+ for_each_possible_cpu(i) \
res += per_cpu_ptr(gendiskp->dkstats, i)->field; \
res; \
})
static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) {
int i;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
memset(per_cpu_ptr(gendiskp->dkstats, i), value,
sizeof (struct disk_stats));
}
diff --git a/include/linux/gigaset_dev.h b/include/linux/gigaset_dev.h
new file mode 100644
index 00000000000..70ad09c8ad1
--- /dev/null
+++ b/include/linux/gigaset_dev.h
@@ -0,0 +1,32 @@
+/*
+ * interface to user space for the gigaset driver
+ *
+ * Copyright (c) 2004 by Hansjoerg Lipp <hjlipp@web.de>
+ *
+ * =====================================================================
+ * 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.
+ * =====================================================================
+ * Version: $Id: gigaset_dev.h,v 1.4.4.4 2005/11/21 22:28:09 hjlipp Exp $
+ * =====================================================================
+ */
+
+#ifndef GIGASET_INTERFACE_H
+#define GIGASET_INTERFACE_H
+
+#include <linux/ioctl.h>
+
+#define GIGASET_IOCTL 0x47
+
+#define GIGVER_DRIVER 0
+#define GIGVER_COMPAT 1
+#define GIGVER_FWBASE 2
+
+#define GIGASET_REDIR _IOWR (GIGASET_IOCTL, 0, int)
+#define GIGASET_CONFIG _IOWR (GIGASET_IOCTL, 1, int)
+#define GIGASET_BRKCHARS _IOW (GIGASET_IOCTL, 2, unsigned char[6]) //FIXME [6] okay?
+#define GIGASET_VERSION _IOWR (GIGASET_IOCTL, 3, unsigned[4])
+
+#endif
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 6bece9280eb..892c4ea1b42 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -7,6 +7,18 @@
#include <asm/cacheflush.h>
+#ifndef ARCH_HAS_FLUSH_ANON_PAGE
+static inline void flush_anon_page(struct page *page, unsigned long vmaddr)
+{
+}
+#endif
+
+#ifndef ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
+static inline void flush_kernel_dcache_page(struct page *page)
+{
+}
+#endif
+
#ifdef CONFIG_HIGHMEM
#include <asm/highmem.h>
diff --git a/include/linux/hpet.h b/include/linux/hpet.h
index 27238194b21..707f7cb9e79 100644
--- a/include/linux/hpet.h
+++ b/include/linux/hpet.h
@@ -3,6 +3,8 @@
#include <linux/compiler.h>
+#ifdef __KERNEL__
+
/*
* Offsets into HPET Registers
*/
@@ -85,22 +87,6 @@ struct hpet {
#define Tn_FSB_INT_ADDR_SHIFT (32UL)
#define Tn_FSB_INT_VAL_MASK (0x00000000ffffffffULL)
-struct hpet_info {
- unsigned long hi_ireqfreq; /* Hz */
- unsigned long hi_flags; /* information */
- unsigned short hi_hpet;
- unsigned short hi_timer;
-};
-
-#define HPET_INFO_PERIODIC 0x0001 /* timer is periodic */
-
-#define HPET_IE_ON _IO('h', 0x01) /* interrupt on */
-#define HPET_IE_OFF _IO('h', 0x02) /* interrupt off */
-#define HPET_INFO _IOR('h', 0x03, struct hpet_info)
-#define HPET_EPI _IO('h', 0x04) /* enable periodic */
-#define HPET_DPI _IO('h', 0x05) /* disable periodic */
-#define HPET_IRQFREQ _IOW('h', 0x6, unsigned long) /* IRQFREQ usec */
-
/*
* exported interfaces
*/
@@ -133,4 +119,22 @@ int hpet_register(struct hpet_task *, int);
int hpet_unregister(struct hpet_task *);
int hpet_control(struct hpet_task *, unsigned int, unsigned long);
+#endif /* __KERNEL__ */
+
+struct hpet_info {
+ unsigned long hi_ireqfreq; /* Hz */
+ unsigned long hi_flags; /* information */
+ unsigned short hi_hpet;
+ unsigned short hi_timer;
+};
+
+#define HPET_INFO_PERIODIC 0x0001 /* timer is periodic */
+
+#define HPET_IE_ON _IO('h', 0x01) /* interrupt on */
+#define HPET_IE_OFF _IO('h', 0x02) /* interrupt off */
+#define HPET_INFO _IOR('h', 0x03, struct hpet_info)
+#define HPET_EPI _IO('h', 0x04) /* enable periodic */
+#define HPET_DPI _IO('h', 0x05) /* disable periodic */
+#define HPET_IRQFREQ _IOW('h', 0x6, unsigned long) /* IRQFREQ usec */
+
#endif /* !__HPET__ */
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 6401c31d6ad..93830158348 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -34,15 +34,7 @@ enum hrtimer_restart {
HRTIMER_RESTART,
};
-/*
- * Timer states:
- */
-enum hrtimer_state {
- HRTIMER_INACTIVE, /* Timer is inactive */
- HRTIMER_EXPIRED, /* Timer is expired */
- HRTIMER_RUNNING, /* Timer is running the callback function */
- HRTIMER_PENDING, /* Timer is pending */
-};
+#define HRTIMER_INACTIVE ((void *)1UL)
struct hrtimer_base;
@@ -53,9 +45,7 @@ struct hrtimer_base;
* @expires: the absolute expiry time in the hrtimers internal
* representation. The time is related to the clock on
* which the timer is based.
- * @state: state of the timer
* @function: timer expiry callback function
- * @data: argument for the callback function
* @base: pointer to the timer base (per cpu and per clock)
*
* The hrtimer structure must be initialized by init_hrtimer_#CLOCKTYPE()
@@ -63,23 +53,23 @@ struct hrtimer_base;
struct hrtimer {
struct rb_node node;
ktime_t expires;
- enum hrtimer_state state;
- int (*function)(void *);
- void *data;
+ int (*function)(struct hrtimer *);
struct hrtimer_base *base;
};
/**
* struct hrtimer_base - the timer base for a specific clock
*
- * @index: clock type index for per_cpu support when moving a timer
- * to a base on another cpu.
- * @lock: lock protecting the base and associated timers
- * @active: red black tree root node for the active timers
- * @first: pointer to the timer node which expires first
- * @resolution: the resolution of the clock, in nanoseconds
- * @get_time: function to retrieve the current time of the clock
- * @curr_timer: the timer which is executing a callback right now
+ * @index: clock type index for per_cpu support when moving a timer
+ * to a base on another cpu.
+ * @lock: lock protecting the base and associated timers
+ * @active: red black tree root node for the active timers
+ * @first: pointer to the timer node which expires first
+ * @resolution: the resolution of the clock, in nanoseconds
+ * @get_time: function to retrieve the current time of the clock
+ * @get_sofirq_time: function to retrieve the current time from the softirq
+ * @curr_timer: the timer which is executing a callback right now
+ * @softirq_time: the time when running the hrtimer queue in the softirq
*/
struct hrtimer_base {
clockid_t index;
@@ -88,7 +78,9 @@ struct hrtimer_base {
struct rb_node *first;
ktime_t resolution;
ktime_t (*get_time)(void);
+ ktime_t (*get_softirq_time)(void);
struct hrtimer *curr_timer;
+ ktime_t softirq_time;
};
/*
@@ -122,11 +114,12 @@ extern ktime_t hrtimer_get_next_event(void);
static inline int hrtimer_active(const struct hrtimer *timer)
{
- return timer->state == HRTIMER_PENDING;
+ return timer->node.rb_parent != HRTIMER_INACTIVE;
}
/* Forward a hrtimer so it expires after now: */
-extern unsigned long hrtimer_forward(struct hrtimer *timer, ktime_t interval);
+extern unsigned long
+hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval);
/* Precise sleep: */
extern long hrtimer_nanosleep(struct timespec *rqtp,
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index d6f1019625a..4c5e610fe44 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -154,7 +154,7 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb)
return sb->s_fs_info;
}
-extern struct file_operations hugetlbfs_file_operations;
+extern const struct file_operations hugetlbfs_file_operations;
extern struct vm_operations_struct hugetlb_vm_ops;
struct file *hugetlb_zero_setup(size_t);
int hugetlb_extend_reservation(struct hugetlbfs_inode_info *info,
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index ec311bc8943..c8b81f419fd 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -108,6 +108,10 @@
#define I2C_DRIVERID_UPD64083 78 /* upd64083 video processor */
#define I2C_DRIVERID_UPD64031A 79 /* upd64031a video processor */
#define I2C_DRIVERID_SAA717X 80 /* saa717x video encoder */
+#define I2C_DRIVERID_DS1672 81 /* Dallas/Maxim DS1672 RTC */
+#define I2C_DRIVERID_X1205 82 /* Xicor/Intersil X1205 RTC */
+#define I2C_DRIVERID_PCF8563 83 /* Philips PCF8563 RTC */
+#define I2C_DRIVERID_RS5C372 84 /* Ricoh RS5C372 RTC */
#define I2C_DRIVERID_I2CDEV 900
#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */
@@ -184,6 +188,7 @@
#define I2C_HW_B_SAVAGE 0x01001d /* savage framebuffer driver */
#define I2C_HW_B_RADEON 0x01001e /* radeon framebuffer driver */
#define I2C_HW_B_EM28XX 0x01001f /* em28xx video capture cards */
+#define I2C_HW_B_CX2341X 0x010020 /* Conexant CX2341X MPEG encoder cards */
/* --- PCF 8584 based algorithms */
#define I2C_HW_P_LP 0x020000 /* Parallel port interface */
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
index 5a9d8c59917..dd7d627bf66 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
@@ -950,9 +950,7 @@ static inline int i2o_pool_alloc(struct i2o_pool *pool, const char *name,
if (!pool->slab)
goto free_name;
- pool->mempool =
- mempool_create(min_nr, mempool_alloc_slab, mempool_free_slab,
- pool->slab);
+ pool->mempool = mempool_create_slab_pool(min_nr, pool->slab);
if (!pool->mempool)
goto free_slab;
diff --git a/include/linux/init.h b/include/linux/init.h
index ff8d8b8632f..ed0ac7c39fd 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -69,6 +69,10 @@ extern initcall_t __security_initcall_start[], __security_initcall_end[];
/* Defined in init/main.c */
extern char saved_command_line[];
+
+/* used by init/main.c */
+extern void setup_arch(char **);
+
#endif
#ifndef MODULE
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 92146f3b742..41ecbb847f3 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -62,6 +62,8 @@
.posix_timers = LIST_HEAD_INIT(sig.posix_timers), \
.cpu_timers = INIT_CPU_TIMERS(sig.cpu_timers), \
.rlim = INIT_RLIMITS, \
+ .pgrp = 1, \
+ .session = 1, \
}
#define INIT_SIGHAND(sighand) { \
diff --git a/include/linux/inotify.h b/include/linux/inotify.h
index 267c88b5f74..09e00433c78 100644
--- a/include/linux/inotify.h
+++ b/include/linux/inotify.h
@@ -71,6 +71,8 @@ struct inotify_event {
#ifdef CONFIG_INOTIFY
+extern void inotify_d_instantiate(struct dentry *, struct inode *);
+extern void inotify_d_move(struct dentry *);
extern void inotify_inode_queue_event(struct inode *, __u32, __u32,
const char *);
extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32,
@@ -81,6 +83,15 @@ extern u32 inotify_get_cookie(void);
#else
+static inline void inotify_d_instantiate(struct dentry *dentry,
+ struct inode *inode)
+{
+}
+
+static inline void inotify_d_move(struct dentry *dentry)
+{
+}
+
static inline void inotify_inode_queue_event(struct inode *inode,
__u32 mask, __u32 cookie,
const char *filename)
diff --git a/include/linux/input.h b/include/linux/input.h
index 6d4cc3c110d..1d4e341b72e 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -957,7 +957,7 @@ struct input_handler {
struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id);
void (*disconnect)(struct input_handle *handle);
- struct file_operations *fops;
+ const struct file_operations *fops;
int minor;
char *name;
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
index d6276e60b3b..0a84b56935c 100644
--- a/include/linux/ipmi.h
+++ b/include/linux/ipmi.h
@@ -36,6 +36,7 @@
#include <linux/ipmi_msgdefs.h>
#include <linux/compiler.h>
+#include <linux/device.h>
/*
* This file describes an interface to an IPMI driver. You have to
@@ -397,7 +398,7 @@ struct ipmi_smi_watcher
the watcher list. So you can add and remove users from the
IPMI interface, send messages, etc., but you cannot add
or remove SMI watchers or SMI interfaces. */
- void (*new_smi)(int if_num);
+ void (*new_smi)(int if_num, struct device *dev);
void (*smi_gone)(int if_num);
};
diff --git a/include/linux/ipmi_msgdefs.h b/include/linux/ipmi_msgdefs.h
index 03bc64dc2ec..22f5e2afda4 100644
--- a/include/linux/ipmi_msgdefs.h
+++ b/include/linux/ipmi_msgdefs.h
@@ -47,6 +47,7 @@
#define IPMI_NETFN_APP_RESPONSE 0x07
#define IPMI_GET_DEVICE_ID_CMD 0x01
#define IPMI_CLEAR_MSG_FLAGS_CMD 0x30
+#define IPMI_GET_DEVICE_GUID_CMD 0x08
#define IPMI_GET_MSG_FLAGS_CMD 0x31
#define IPMI_SEND_MSG_CMD 0x34
#define IPMI_GET_MSG_CMD 0x33
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
index e36ee157ad6..53571288a9f 100644
--- a/include/linux/ipmi_smi.h
+++ b/include/linux/ipmi_smi.h
@@ -37,6 +37,9 @@
#include <linux/ipmi_msgdefs.h>
#include <linux/proc_fs.h>
#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/ipmi_smi.h>
/* This files describes the interface for IPMI system management interface
drivers to bind into the IPMI message handler. */
@@ -113,12 +116,52 @@ struct ipmi_smi_handlers
void (*dec_usecount)(void *send_info);
};
+struct ipmi_device_id {
+ unsigned char device_id;
+ unsigned char device_revision;
+ unsigned char firmware_revision_1;
+ unsigned char firmware_revision_2;
+ unsigned char ipmi_version;
+ unsigned char additional_device_support;
+ unsigned int manufacturer_id;
+ unsigned int product_id;
+ unsigned char aux_firmware_revision[4];
+ unsigned int aux_firmware_revision_set : 1;
+};
+
+#define ipmi_version_major(v) ((v)->ipmi_version & 0xf)
+#define ipmi_version_minor(v) ((v)->ipmi_version >> 4)
+
+/* Take a pointer to a raw data buffer and a length and extract device
+ id information from it. The first byte of data must point to the
+ byte from the get device id response after the completion code.
+ The caller is responsible for making sure the length is at least
+ 11 and the command completed without error. */
+static inline void ipmi_demangle_device_id(unsigned char *data,
+ unsigned int data_len,
+ struct ipmi_device_id *id)
+{
+ id->device_id = data[0];
+ id->device_revision = data[1];
+ id->firmware_revision_1 = data[2];
+ id->firmware_revision_2 = data[3];
+ id->ipmi_version = data[4];
+ id->additional_device_support = data[5];
+ id->manufacturer_id = data[6] | (data[7] << 8) | (data[8] << 16);
+ id->product_id = data[9] | (data[10] << 8);
+ if (data_len >= 15) {
+ memcpy(id->aux_firmware_revision, data+11, 4);
+ id->aux_firmware_revision_set = 1;
+ } else
+ id->aux_firmware_revision_set = 0;
+}
+
/* Add a low-level interface to the IPMI driver. Note that if the
interface doesn't know its slave address, it should pass in zero. */
int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
void *send_info,
- unsigned char version_major,
- unsigned char version_minor,
+ struct ipmi_device_id *device_id,
+ struct device *dev,
unsigned char slave_addr,
ipmi_smi_t *intf);
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 6c5d4c898cc..ee2a82a572f 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -114,53 +114,8 @@ static inline void set_native_irq_info(int irq, cpumask_t mask)
#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
extern cpumask_t pending_irq_cpumask[NR_IRQS];
-static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
-{
- irq_desc_t *desc = irq_desc + irq;
- unsigned long flags;
-
- spin_lock_irqsave(&desc->lock, flags);
- desc->move_irq = 1;
- pending_irq_cpumask[irq] = mask;
- spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-static inline void
-move_native_irq(int irq)
-{
- cpumask_t tmp;
- irq_desc_t *desc = irq_descp(irq);
-
- if (likely (!desc->move_irq))
- return;
-
- desc->move_irq = 0;
-
- if (likely(cpus_empty(pending_irq_cpumask[irq])))
- return;
-
- if (!desc->handler->set_affinity)
- return;
-
- /* note - we hold the desc->lock */
- cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
-
- /*
- * If there was a valid mask to work with, please
- * do the disable, re-program, enable sequence.
- * This is *not* particularly important for level triggered
- * but in a edge trigger case, we might be setting rte
- * when an active trigger is comming in. This could
- * cause some ioapics to mal-function.
- * Being paranoid i guess!
- */
- if (unlikely(!cpus_empty(tmp))) {
- desc->handler->disable(irq);
- desc->handler->set_affinity(irq,tmp);
- desc->handler->enable(irq);
- }
- cpus_clear(pending_irq_cpumask[irq]);
-}
+void set_pending_irq(unsigned int irq, cpumask_t mask);
+void move_native_irq(int irq);
#ifdef CONFIG_PCI_MSI
/*
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 2ccbfb6340b..6a425e370cb 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -29,6 +29,8 @@
#include <linux/stddef.h>
#include <linux/bit_spinlock.h>
#include <linux/mutex.h>
+#include <linux/timer.h>
+
#include <asm/semaphore.h>
#endif
@@ -787,7 +789,7 @@ struct journal_s
unsigned long j_commit_interval;
/* The timer used to wakeup the commit thread: */
- struct timer_list *j_commit_timer;
+ struct timer_list j_commit_timer;
/*
* The revoke table: maintains the list of revoked blocks in the
@@ -893,7 +895,7 @@ extern int journal_dirty_metadata (handle_t *, struct buffer_head *);
extern void journal_release_buffer (handle_t *, struct buffer_head *);
extern int journal_forget (handle_t *, struct buffer_head *);
extern void journal_sync_buffer (struct buffer_head *);
-extern int journal_invalidatepage(journal_t *,
+extern void journal_invalidatepage(journal_t *,
struct page *, unsigned long);
extern int journal_try_to_free_buffers(journal_t *, struct page *, gfp_t);
extern int journal_stop(handle_t *);
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index bb6e7ddee2f..a3720f973ea 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -87,7 +87,7 @@ extern int cond_resched(void);
(__x < 0) ? -__x : __x; \
})
-extern struct notifier_block *panic_notifier_list;
+extern struct atomic_notifier_head panic_notifier_list;
extern long (*panic_blink)(long time);
NORET_TYPE void panic(const char * fmt, ...)
__attribute__ ((NORET_AND format (printf, 1, 2)));
@@ -154,9 +154,10 @@ static inline int __attribute_pure__ long_log2(unsigned long x)
return r;
}
-static inline unsigned long __attribute_const__ roundup_pow_of_two(unsigned long x)
+static inline unsigned long
+__attribute_const__ roundup_pow_of_two(unsigned long x)
{
- return (1UL << fls(x - 1));
+ return 1UL << fls_long(x - 1);
}
extern int printk_ratelimit(void);
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index a484572c302..b46249082cc 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -46,7 +46,7 @@ static inline int kstat_irqs(int irq)
{
int cpu, sum = 0;
- for_each_cpu(cpu)
+ for_each_possible_cpu(cpu)
sum += kstat_cpu(cpu).irqs[irq];
return sum;
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index f3dec45ef87..62bc5758070 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -64,9 +64,6 @@ typedef union {
#if (BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)
-/* Define a ktime_t variable and initialize it to zero: */
-#define DEFINE_KTIME(kt) ktime_t kt = { .tv64 = 0 }
-
/**
* ktime_set - Set a ktime_t variable from a seconds/nanoseconds value
*
@@ -113,9 +110,6 @@ static inline ktime_t timeval_to_ktime(struct timeval tv)
/* Map the ktime_t to timeval conversion to ns_to_timeval function */
#define ktime_to_timeval(kt) ns_to_timeval((kt).tv64)
-/* Map the ktime_t to clock_t conversion to the inline in jiffies.h: */
-#define ktime_to_clock_t(kt) nsec_to_clock_t((kt).tv64)
-
/* Convert ktime_t to nanoseconds - NOP in the scalar storage format: */
#define ktime_to_ns(kt) ((kt).tv64)
@@ -136,9 +130,6 @@ static inline ktime_t timeval_to_ktime(struct timeval tv)
* tv.sec < 0 and 0 >= tv.nsec < NSEC_PER_SEC
*/
-/* Define a ktime_t variable and initialize it to zero: */
-#define DEFINE_KTIME(kt) ktime_t kt = { .tv64 = 0 }
-
/* Set a ktime_t variable to a value in sec/nsec representation: */
static inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
{
@@ -255,17 +246,6 @@ static inline struct timeval ktime_to_timeval(const ktime_t kt)
}
/**
- * ktime_to_clock_t - convert a ktime_t variable to clock_t format
- * @kt: the ktime_t variable to convert
- *
- * Returns a clock_t variable with the converted value
- */
-static inline clock_t ktime_to_clock_t(const ktime_t kt)
-{
- return nsec_to_clock_t( (u64) kt.tv.sec * NSEC_PER_SEC + kt.tv.nsec);
-}
-
-/**
* ktime_to_ns - convert a ktime_t variable to scalar nanoseconds
* @kt: the ktime_t variable to convert
*
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index ef21ed29603..995f89dc8c0 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -14,6 +14,7 @@
#include <linux/config.h>
#include <linux/in.h>
#include <linux/fs.h>
+#include <linux/kref.h>
#include <linux/utsname.h>
#include <linux/nfsd/nfsfh.h>
#include <linux/lockd/bind.h>
@@ -58,6 +59,8 @@ struct nlm_host {
unsigned long h_expires; /* eligible for GC */
struct list_head h_lockowners; /* Lockowners for the client */
spinlock_t h_lock;
+ struct list_head h_granted; /* Locks in GRANTED state */
+ struct list_head h_reclaim; /* Locks in RECLAIM state */
};
/*
@@ -83,9 +86,9 @@ struct nlm_rqst {
struct nlm_host * a_host; /* host handle */
struct nlm_args a_args; /* arguments */
struct nlm_res a_res; /* result */
- struct nlm_wait * a_block;
+ struct nlm_block * a_block;
unsigned int a_retries; /* Retry count */
- char a_owner[NLMCLNT_OHSIZE];
+ u8 a_owner[NLMCLNT_OHSIZE];
};
/*
@@ -110,16 +113,16 @@ struct nlm_file {
*/
#define NLM_NEVER (~(unsigned long) 0)
struct nlm_block {
+ struct kref b_count; /* Reference count */
struct nlm_block * b_next; /* linked list (all blocks) */
struct nlm_block * b_fnext; /* linked list (per file) */
- struct nlm_rqst b_call; /* RPC args & callback info */
+ struct nlm_rqst * b_call; /* RPC args & callback info */
struct svc_serv * b_daemon; /* NLM service */
struct nlm_host * b_host; /* host handle for RPC clnt */
unsigned long b_when; /* next re-xmit */
unsigned int b_id; /* block id */
unsigned char b_queued; /* re-queued */
unsigned char b_granted; /* VFS granted lock */
- unsigned char b_incall; /* doing callback */
unsigned char b_done; /* callback complete */
struct nlm_file * b_file; /* file in question */
};
@@ -145,15 +148,16 @@ extern unsigned long nlmsvc_timeout;
/*
* Lockd client functions
*/
-struct nlm_rqst * nlmclnt_alloc_call(void);
-int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl);
-void nlmclnt_finish_block(struct nlm_rqst *req);
-long nlmclnt_block(struct nlm_rqst *req, long timeout);
+struct nlm_rqst * nlm_alloc_call(struct nlm_host *host);
+void nlm_release_call(struct nlm_rqst *);
+int nlm_async_call(struct nlm_rqst *, u32, const struct rpc_call_ops *);
+int nlm_async_reply(struct nlm_rqst *, u32, const struct rpc_call_ops *);
+struct nlm_wait * nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl);
+void nlmclnt_finish_block(struct nlm_wait *block);
+int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout);
u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *);
void nlmclnt_recovery(struct nlm_host *, u32);
int nlmclnt_reclaim(struct nlm_host *, struct file_lock *);
-int nlmclnt_setgrantargs(struct nlm_rqst *, struct nlm_lock *);
-void nlmclnt_freegrantargs(struct nlm_rqst *);
/*
* Host cache
@@ -172,7 +176,6 @@ extern struct nlm_host *nlm_find_client(void);
/*
* Server-side lock handling
*/
-int nlmsvc_async_call(struct nlm_rqst *, u32, const struct rpc_call_ops *);
u32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *,
struct nlm_lock *, int, struct nlm_cookie *);
u32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *);
@@ -180,7 +183,7 @@ u32 nlmsvc_testlock(struct nlm_file *, struct nlm_lock *,
struct nlm_lock *);
u32 nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *);
unsigned long nlmsvc_retry_blocked(void);
-int nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
+void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
int action);
void nlmsvc_grant_reply(struct svc_rqst *, struct nlm_cookie *, u32);
diff --git a/include/linux/lockd/share.h b/include/linux/lockd/share.h
index 5d8aa325f14..c75a424ebe4 100644
--- a/include/linux/lockd/share.h
+++ b/include/linux/lockd/share.h
@@ -25,6 +25,6 @@ u32 nlmsvc_share_file(struct nlm_host *, struct nlm_file *,
struct nlm_args *);
u32 nlmsvc_unshare_file(struct nlm_host *, struct nlm_file *,
struct nlm_args *);
-int nlmsvc_traverse_shares(struct nlm_host *, struct nlm_file *, int);
+void nlmsvc_traverse_shares(struct nlm_host *, struct nlm_file *, int);
#endif /* LINUX_LOCKD_SHARE_H */
diff --git a/include/linux/lockd/xdr.h b/include/linux/lockd/xdr.h
index d7a5cc4cfa9..bb0a0f1caa9 100644
--- a/include/linux/lockd/xdr.h
+++ b/include/linux/lockd/xdr.h
@@ -28,6 +28,7 @@ struct nlm_lock {
int len; /* length of "caller" */
struct nfs_fh fh;
struct xdr_netobj oh;
+ u32 svid;
struct file_lock fl;
};
diff --git a/include/linux/m48t86.h b/include/linux/m48t86.h
new file mode 100644
index 00000000000..9065199319d
--- /dev/null
+++ b/include/linux/m48t86.h
@@ -0,0 +1,16 @@
+/*
+ * ST M48T86 / Dallas DS12887 RTC driver
+ * Copyright (c) 2006 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * 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.
+*/
+
+struct m48t86_ops
+{
+ void (*writeb)(unsigned char value, unsigned long addr);
+ unsigned char (*readb)(unsigned long addr);
+};
diff --git a/include/linux/major.h b/include/linux/major.h
index e36a46702d9..0a74c52924c 100644
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -113,6 +113,7 @@
#define UBD_MAJOR 98
+#define PP_MAJOR 99
#define JSFD_MAJOR 99
#define PHONE_MAJOR 100
diff --git a/include/linux/memory.h b/include/linux/memory.h
index e251dc43d0f..8f04143ca36 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -77,7 +77,6 @@ extern int remove_memory_block(unsigned long, struct mem_section *, int);
#define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT)
-struct notifier_block;
#endif /* CONFIG_MEMORY_HOTPLUG */
diff --git a/include/linux/mempool.h b/include/linux/mempool.h
index f2427d7394b..9be484d1128 100644
--- a/include/linux/mempool.h
+++ b/include/linux/mempool.h
@@ -6,6 +6,8 @@
#include <linux/wait.h>
+struct kmem_cache;
+
typedef void * (mempool_alloc_t)(gfp_t gfp_mask, void *pool_data);
typedef void (mempool_free_t)(void *element, void *pool_data);
@@ -37,5 +39,41 @@ extern void mempool_free(void *element, mempool_t *pool);
*/
void *mempool_alloc_slab(gfp_t gfp_mask, void *pool_data);
void mempool_free_slab(void *element, void *pool_data);
+static inline mempool_t *
+mempool_create_slab_pool(int min_nr, struct kmem_cache *kc)
+{
+ return mempool_create(min_nr, mempool_alloc_slab, mempool_free_slab,
+ (void *) kc);
+}
+
+/*
+ * 2 mempool_alloc_t's and a mempool_free_t to kmalloc/kzalloc and kfree
+ * the amount of memory specified by pool_data
+ */
+void *mempool_kmalloc(gfp_t gfp_mask, void *pool_data);
+void *mempool_kzalloc(gfp_t gfp_mask, void *pool_data);
+void mempool_kfree(void *element, void *pool_data);
+static inline mempool_t *mempool_create_kmalloc_pool(int min_nr, size_t size)
+{
+ return mempool_create(min_nr, mempool_kmalloc, mempool_kfree,
+ (void *) size);
+}
+static inline mempool_t *mempool_create_kzalloc_pool(int min_nr, size_t size)
+{
+ return mempool_create(min_nr, mempool_kzalloc, mempool_kfree,
+ (void *) size);
+}
+
+/*
+ * A mempool_alloc_t and mempool_free_t for a simple page allocator that
+ * allocates pages of the order specified by pool_data
+ */
+void *mempool_alloc_pages(gfp_t gfp_mask, void *pool_data);
+void mempool_free_pages(void *element, void *pool_data);
+static inline mempool_t *mempool_create_page_pool(int min_nr, int order)
+{
+ return mempool_create(min_nr, mempool_alloc_pages, mempool_free_pages,
+ (void *)(long)order);
+}
#endif /* _LINUX_MEMPOOL_H */
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index 14ceebfc1ef..5b584dafb5a 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -36,7 +36,7 @@ struct class_device;
struct miscdevice {
int minor;
const char *name;
- struct file_operations *fops;
+ const struct file_operations *fops;
struct list_head list;
struct device *dev;
struct class_device *class;
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index ebfc238cc24..b5c21122c29 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -13,6 +13,7 @@
#include <linux/numa.h>
#include <linux/init.h>
#include <linux/seqlock.h>
+#include <linux/nodemask.h>
#include <asm/atomic.h>
/* Free memory management - zoned buddy allocator. */
@@ -225,7 +226,6 @@ struct zone {
* Discontig memory support fields.
*/
struct pglist_data *zone_pgdat;
- struct page *zone_mem_map;
/* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */
unsigned long zone_start_pfn;
@@ -307,7 +307,6 @@ typedef struct pglist_data {
unsigned long node_spanned_pages; /* total size of physical page
range, including holes */
int node_id;
- struct pglist_data *pgdat_next;
wait_queue_head_t kswapd_wait;
struct task_struct *kswapd;
int kswapd_max_order;
@@ -324,8 +323,6 @@ typedef struct pglist_data {
#include <linux/memory_hotplug.h>
-extern struct pglist_data *pgdat_list;
-
void __get_zone_counts(unsigned long *active, unsigned long *inactive,
unsigned long *free, struct pglist_data *pgdat);
void get_zone_counts(unsigned long *active, unsigned long *inactive,
@@ -350,57 +347,6 @@ unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long);
*/
#define zone_idx(zone) ((zone) - (zone)->zone_pgdat->node_zones)
-/**
- * for_each_pgdat - helper macro to iterate over all nodes
- * @pgdat - pointer to a pg_data_t variable
- *
- * Meant to help with common loops of the form
- * pgdat = pgdat_list;
- * while(pgdat) {
- * ...
- * pgdat = pgdat->pgdat_next;
- * }
- */
-#define for_each_pgdat(pgdat) \
- for (pgdat = pgdat_list; pgdat; pgdat = pgdat->pgdat_next)
-
-/*
- * next_zone - helper magic for for_each_zone()
- * Thanks to William Lee Irwin III for this piece of ingenuity.
- */
-static inline struct zone *next_zone(struct zone *zone)
-{
- pg_data_t *pgdat = zone->zone_pgdat;
-
- if (zone < pgdat->node_zones + MAX_NR_ZONES - 1)
- zone++;
- else if (pgdat->pgdat_next) {
- pgdat = pgdat->pgdat_next;
- zone = pgdat->node_zones;
- } else
- zone = NULL;
-
- return zone;
-}
-
-/**
- * for_each_zone - helper macro to iterate over all memory zones
- * @zone - pointer to struct zone variable
- *
- * The user only needs to declare the zone variable, for_each_zone
- * fills it in. This basically means for_each_zone() is an
- * easier to read version of this piece of code:
- *
- * for (pgdat = pgdat_list; pgdat; pgdat = pgdat->node_next)
- * for (i = 0; i < MAX_NR_ZONES; ++i) {
- * struct zone * z = pgdat->node_zones + i;
- * ...
- * }
- * }
- */
-#define for_each_zone(zone) \
- for (zone = pgdat_list->node_zones; zone; zone = next_zone(zone))
-
static inline int populated_zone(struct zone *zone)
{
return (!!zone->present_pages);
@@ -472,6 +418,30 @@ extern struct pglist_data contig_page_data;
#endif /* !CONFIG_NEED_MULTIPLE_NODES */
+extern struct pglist_data *first_online_pgdat(void);
+extern struct pglist_data *next_online_pgdat(struct pglist_data *pgdat);
+extern struct zone *next_zone(struct zone *zone);
+
+/**
+ * for_each_pgdat - helper macro to iterate over all nodes
+ * @pgdat - pointer to a pg_data_t variable
+ */
+#define for_each_online_pgdat(pgdat) \
+ for (pgdat = first_online_pgdat(); \
+ pgdat; \
+ pgdat = next_online_pgdat(pgdat))
+/**
+ * for_each_zone - helper macro to iterate over all memory zones
+ * @zone - pointer to struct zone variable
+ *
+ * The user only needs to declare the zone variable, for_each_zone
+ * fills it in.
+ */
+#define for_each_zone(zone) \
+ for (zone = (first_online_pgdat())->node_zones; \
+ zone; \
+ zone = next_zone(zone))
+
#ifdef CONFIG_SPARSEMEM
#include <asm/sparsemem.h>
#endif
@@ -602,17 +572,6 @@ static inline struct mem_section *__pfn_to_section(unsigned long pfn)
return __nr_to_section(pfn_to_section_nr(pfn));
}
-#define pfn_to_page(pfn) \
-({ \
- unsigned long __pfn = (pfn); \
- __section_mem_map_addr(__pfn_to_section(__pfn)) + __pfn; \
-})
-#define page_to_pfn(page) \
-({ \
- page - __section_mem_map_addr(__nr_to_section( \
- page_to_section(page))); \
-})
-
static inline int pfn_valid(unsigned long pfn)
{
if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
diff --git a/include/linux/module.h b/include/linux/module.h
index 70bd843c71c..eaec13ddd66 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -183,6 +183,7 @@ void *__symbol_get_gpl(const char *symbol);
/* For every exported symbol, place a struct in the __ksymtab section */
#define __EXPORT_SYMBOL(sym, sec) \
+ extern typeof(sym) sym; \
__CRC_SYMBOL(sym, sec) \
static const char __kstrtab_##sym[] \
__attribute__((section("__ksymtab_strings"))) \
@@ -554,25 +555,6 @@ static inline void module_remove_driver(struct device_driver *driver)
/* BELOW HERE ALL THESE ARE OBSOLETE AND WILL VANISH */
-struct obsolete_modparm {
- char name[64];
- char type[64-sizeof(void *)];
- void *addr;
-};
-
-static inline void MODULE_PARM_(void) { }
-#ifdef MODULE
-/* DEPRECATED: Do not use. */
-#define MODULE_PARM(var,type) \
-extern struct obsolete_modparm __parm_##var \
-__attribute__((section("__obsparm"))); \
-struct obsolete_modparm __parm_##var = \
-{ __stringify(var), type, &MODULE_PARM_ }; \
-__MODULE_PARM_TYPE(var, type);
-#else
-#define MODULE_PARM(var,type) static void __attribute__((__unused__)) *__parm_##var = &MODULE_PARM_;
-#endif
-
#define __MODULE_STRING(x) __stringify(x)
/* Use symbol_get and symbol_put instead. You'll thank me. */
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index b5c98c43779..7c0c2c198f1 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -162,13 +162,6 @@ extern int param_array_get(char *buffer, struct kernel_param *kp);
extern int param_set_copystring(const char *val, struct kernel_param *kp);
extern int param_get_string(char *buffer, struct kernel_param *kp);
-int param_array(const char *name,
- const char *val,
- unsigned int min, unsigned int max,
- void *elem, int elemsize,
- int (*set)(const char *, struct kernel_param *kp),
- int *num);
-
/* for exporting parameters in /sys/parameters */
struct module;
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 779e6a5744c..d9035c73e5d 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -334,7 +334,7 @@ extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
unsigned long *mapped_blocks);
/* fat/dir.c */
-extern struct file_operations fat_dir_operations;
+extern const struct file_operations fat_dir_operations;
extern int fat_search_long(struct inode *inode, const unsigned char *name,
int name_len, struct fat_slot_info *sinfo);
extern int fat_dir_empty(struct inode *dir);
@@ -397,7 +397,7 @@ extern int fat_count_free_clusters(struct super_block *sb);
/* fat/file.c */
extern int fat_generic_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern struct file_operations fat_file_operations;
+extern const struct file_operations fat_file_operations;
extern struct inode_operations fat_file_inode_operations;
extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
extern void fat_truncate(struct inode *inode);
@@ -420,6 +420,9 @@ extern int date_dos2unix(unsigned short time, unsigned short date);
extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date);
extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
+int fat_cache_init(void);
+void fat_cache_destroy(void);
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index e0134256853..96dc237b8f0 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -209,7 +209,7 @@ void ncp_update_inode2(struct inode *, struct ncp_entry_info *);
/* linux/fs/ncpfs/dir.c */
extern struct inode_operations ncp_dir_inode_operations;
-extern struct file_operations ncp_dir_operations;
+extern const struct file_operations ncp_dir_operations;
int ncp_conn_logged_in(struct super_block *);
int ncp_date_dos2unix(__le16 time, __le16 date);
void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date);
@@ -230,7 +230,7 @@ void ncp_unlock_server(struct ncp_server *server);
/* linux/fs/ncpfs/file.c */
extern struct inode_operations ncp_file_inode_operations;
-extern struct file_operations ncp_file_operations;
+extern const struct file_operations ncp_file_operations;
int ncp_make_open(struct inode *, int);
/* linux/fs/ncpfs/mmap.c */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index f32d75c4f4c..d54d7b278e9 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -308,29 +308,30 @@ DECLARE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache);
#define CONNTRACK_ECACHE(x) (__get_cpu_var(ip_conntrack_ecache).x)
-extern struct notifier_block *ip_conntrack_chain;
-extern struct notifier_block *ip_conntrack_expect_chain;
+extern struct atomic_notifier_head ip_conntrack_chain;
+extern struct atomic_notifier_head ip_conntrack_expect_chain;
static inline int ip_conntrack_register_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&ip_conntrack_chain, nb);
+ return atomic_notifier_chain_register(&ip_conntrack_chain, nb);
}
static inline int ip_conntrack_unregister_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&ip_conntrack_chain, nb);
+ return atomic_notifier_chain_unregister(&ip_conntrack_chain, nb);
}
static inline int
ip_conntrack_expect_register_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&ip_conntrack_expect_chain, nb);
+ return atomic_notifier_chain_register(&ip_conntrack_expect_chain, nb);
}
static inline int
ip_conntrack_expect_unregister_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&ip_conntrack_expect_chain, nb);
+ return atomic_notifier_chain_unregister(&ip_conntrack_expect_chain,
+ nb);
}
extern void ip_ct_deliver_cached_events(const struct ip_conntrack *ct);
@@ -355,14 +356,14 @@ static inline void ip_conntrack_event(enum ip_conntrack_events event,
struct ip_conntrack *ct)
{
if (is_confirmed(ct) && !is_dying(ct))
- notifier_call_chain(&ip_conntrack_chain, event, ct);
+ atomic_notifier_call_chain(&ip_conntrack_chain, event, ct);
}
static inline void
ip_conntrack_expect_event(enum ip_conntrack_expect_events event,
struct ip_conntrack_expect *exp)
{
- notifier_call_chain(&ip_conntrack_expect_chain, event, exp);
+ atomic_notifier_call_chain(&ip_conntrack_expect_chain, event, exp);
}
#else /* CONFIG_IP_NF_CONNTRACK_EVENTS */
static inline void ip_conntrack_event_cache(enum ip_conntrack_events event,
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index b4dc6e2e10c..c71227dd438 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -56,9 +56,7 @@
* When flushing a cluster of dirty pages, there can be different
* strategies:
*/
-#define FLUSH_AGING 0 /* only flush old buffers */
#define FLUSH_SYNC 1 /* file being synced, or contention */
-#define FLUSH_WAIT 2 /* wait for completion */
#define FLUSH_STABLE 4 /* commit to stable storage */
#define FLUSH_LOWPRI 8 /* low priority background flush */
#define FLUSH_HIGHPRI 16 /* high priority memory reclaim flush */
@@ -78,6 +76,7 @@ struct nfs_access_entry {
struct nfs4_state;
struct nfs_open_context {
atomic_t count;
+ struct vfsmount *vfsmnt;
struct dentry *dentry;
struct rpc_cred *cred;
struct nfs4_state *state;
@@ -118,8 +117,7 @@ struct nfs_inode {
unsigned long cache_validity; /* bit mask */
/*
- * read_cache_jiffies is when we started read-caching this inode,
- * and read_cache_mtime is the mtime of the inode at that time.
+ * read_cache_jiffies is when we started read-caching this inode.
* attrtimeo is for how long the cached information is assumed
* to be valid. A successful attribute revalidation doubles
* attrtimeo (up to acregmax/acdirmax), a failure resets it to
@@ -128,11 +126,6 @@ struct nfs_inode {
* We need to revalidate the cached attrs for this inode if
*
* jiffies - read_cache_jiffies > attrtimeo
- *
- * and invalidate any cached data/flush out any dirty pages if
- * we find that
- *
- * mtime != read_cache_mtime
*/
unsigned long read_cache_jiffies;
unsigned long attrtimeo;
@@ -311,12 +304,9 @@ extern void nfs_begin_attr_update(struct inode *);
extern void nfs_end_attr_update(struct inode *);
extern void nfs_begin_data_update(struct inode *);
extern void nfs_end_data_update(struct inode *);
-extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred);
extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
extern void put_nfs_open_context(struct nfs_open_context *ctx);
-extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx);
extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode);
-extern void nfs_file_clear_open_context(struct file *filp);
/* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
extern u32 root_nfs_parse_addr(char *name); /*__init*/
@@ -334,7 +324,7 @@ extern struct inode_operations nfs_file_inode_operations;
#ifdef CONFIG_NFS_V3
extern struct inode_operations nfs3_file_inode_operations;
#endif /* CONFIG_NFS_V3 */
-extern struct file_operations nfs_file_operations;
+extern const struct file_operations nfs_file_operations;
extern struct address_space_operations nfs_file_aops;
static inline struct rpc_cred *nfs_file_cred(struct file *file)
@@ -381,7 +371,7 @@ extern struct inode_operations nfs_dir_inode_operations;
#ifdef CONFIG_NFS_V3
extern struct inode_operations nfs3_dir_inode_operations;
#endif /* CONFIG_NFS_V3 */
-extern struct file_operations nfs_dir_operations;
+extern const struct file_operations nfs_dir_operations;
extern struct dentry_operations nfs_dentry_operations;
extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr);
@@ -415,21 +405,22 @@ extern int nfs_writepage(struct page *page, struct writeback_control *wbc);
extern int nfs_writepages(struct address_space *, struct writeback_control *);
extern int nfs_flush_incompatible(struct file *file, struct page *page);
extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
-extern void nfs_writeback_done(struct rpc_task *task, void *data);
-extern void nfs_writedata_release(void *data);
+extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
+extern void nfs_writedata_release(void *);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-extern void nfs_commit_done(struct rpc_task *, void *data);
-extern void nfs_commit_release(void *data);
+struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount);
+void nfs_commit_free(struct nfs_write_data *p);
#endif
/*
* Try to write back everything synchronously (but check the
* return value!)
*/
-extern int nfs_sync_inode(struct inode *, unsigned long, unsigned int, int);
+extern int nfs_sync_inode_wait(struct inode *, unsigned long, unsigned int, int);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
extern int nfs_commit_inode(struct inode *, int);
+extern void nfs_commit_release(void *wdata);
#else
static inline int
nfs_commit_inode(struct inode *inode, int how)
@@ -447,7 +438,7 @@ nfs_have_writebacks(struct inode *inode)
static inline int
nfs_wb_all(struct inode *inode)
{
- int error = nfs_sync_inode(inode, 0, 0, FLUSH_WAIT);
+ int error = nfs_sync_inode_wait(inode, 0, 0, 0);
return (error < 0) ? error : 0;
}
@@ -456,8 +447,8 @@ nfs_wb_all(struct inode *inode)
*/
static inline int nfs_wb_page_priority(struct inode *inode, struct page* page, int how)
{
- int error = nfs_sync_inode(inode, page->index, 1,
- how | FLUSH_WAIT | FLUSH_STABLE);
+ int error = nfs_sync_inode_wait(inode, page->index, 1,
+ how | FLUSH_STABLE);
return (error < 0) ? error : 0;
}
@@ -469,37 +460,8 @@ static inline int nfs_wb_page(struct inode *inode, struct page* page)
/*
* Allocate and free nfs_write_data structures
*/
-extern mempool_t *nfs_wdata_mempool;
-
-static inline struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
-{
- struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, SLAB_NOFS);
-
- if (p) {
- memset(p, 0, sizeof(*p));
- INIT_LIST_HEAD(&p->pages);
- if (pagecount < NFS_PAGEVEC_SIZE)
- p->pagevec = &p->page_array[0];
- else {
- size_t size = ++pagecount * sizeof(struct page *);
- p->pagevec = kmalloc(size, GFP_NOFS);
- if (p->pagevec) {
- memset(p->pagevec, 0, size);
- } else {
- mempool_free(p, nfs_wdata_mempool);
- p = NULL;
- }
- }
- }
- return p;
-}
-
-static inline void nfs_writedata_free(struct nfs_write_data *p)
-{
- if (p && (p->pagevec != &p->page_array[0]))
- kfree(p->pagevec);
- mempool_free(p, nfs_wdata_mempool);
-}
+extern struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount);
+extern void nfs_writedata_free(struct nfs_write_data *p);
/*
* linux/fs/nfs/read.c
@@ -507,44 +469,14 @@ static inline void nfs_writedata_free(struct nfs_write_data *p)
extern int nfs_readpage(struct file *, struct page *);
extern int nfs_readpages(struct file *, struct address_space *,
struct list_head *, unsigned);
-extern void nfs_readpage_result(struct rpc_task *, void *);
-extern void nfs_readdata_release(void *data);
-
+extern int nfs_readpage_result(struct rpc_task *, struct nfs_read_data *);
+extern void nfs_readdata_release(void *data);
/*
* Allocate and free nfs_read_data structures
*/
-extern mempool_t *nfs_rdata_mempool;
-
-static inline struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
-{
- struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, SLAB_NOFS);
-
- if (p) {
- memset(p, 0, sizeof(*p));
- INIT_LIST_HEAD(&p->pages);
- if (pagecount < NFS_PAGEVEC_SIZE)
- p->pagevec = &p->page_array[0];
- else {
- size_t size = ++pagecount * sizeof(struct page *);
- p->pagevec = kmalloc(size, GFP_NOFS);
- if (p->pagevec) {
- memset(p->pagevec, 0, size);
- } else {
- mempool_free(p, nfs_rdata_mempool);
- p = NULL;
- }
- }
- }
- return p;
-}
-
-static inline void nfs_readdata_free(struct nfs_read_data *p)
-{
- if (p && (p->pagevec != &p->page_array[0]))
- kfree(p->pagevec);
- mempool_free(p, nfs_rdata_mempool);
-}
+extern struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount);
+extern void nfs_readdata_free(struct nfs_read_data *p);
/*
* linux/fs/nfs3proc.c
diff --git a/include/linux/nfs_fs_i.h b/include/linux/nfs_fs_i.h
index e2c18dabff8..861730275ba 100644
--- a/include/linux/nfs_fs_i.h
+++ b/include/linux/nfs_fs_i.h
@@ -12,8 +12,8 @@ struct nlm_lockowner;
*/
struct nfs_lock_info {
u32 state;
- u32 flags;
struct nlm_lockowner *owner;
+ struct list_head list;
};
struct nfs4_lock_state;
@@ -21,10 +21,4 @@ struct nfs4_lock_info {
struct nfs4_lock_state *owner;
};
-/*
- * Lock flag values
- */
-#define NFS_LCK_GRANTED 0x0001 /* lock has been granted */
-#define NFS_LCK_RECLAIM 0x0002 /* lock marked for reclaiming */
-
#endif
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 3d3a305488c..65dec21af77 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -4,6 +4,8 @@
#include <linux/list.h>
#include <linux/backing-dev.h>
+struct nfs_iostats;
+
/*
* NFS client parameters stored in the superblock.
*/
@@ -12,6 +14,7 @@ struct nfs_server {
struct rpc_clnt * client_sys; /* 2nd handle for FSINFO */
struct rpc_clnt * client_acl; /* ACL RPC client handle */
struct nfs_rpc_ops * rpc_ops; /* NFS protocol vector */
+ struct nfs_iostats * io_stats; /* I/O statistics */
struct backing_dev_info backing_dev_info;
int flags; /* various flags */
unsigned int caps; /* server capabilities */
@@ -26,10 +29,13 @@ struct nfs_server {
unsigned int acregmax;
unsigned int acdirmin;
unsigned int acdirmax;
+ unsigned long retrans_timeo; /* retransmit timeout */
+ unsigned int retrans_count; /* number of retransmit tries */
unsigned int namelen;
char * hostname; /* remote hostname */
struct nfs_fh fh;
struct sockaddr_in addr;
+ unsigned long mount_time; /* when this fs was mounted */
#ifdef CONFIG_NFS_V4
/* Our own IP address, as a null-terminated string.
* This is used to generate the clientid, and the callback address.
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 6d6f69ec567..7fafc4c546b 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -695,7 +695,6 @@ struct nfs_read_data {
#ifdef CONFIG_NFS_V4
unsigned long timestamp; /* For lease renewal */
#endif
- void (*complete) (struct nfs_read_data *, int);
struct page *page_array[NFS_PAGEVEC_SIZE + 1];
};
@@ -714,7 +713,6 @@ struct nfs_write_data {
#ifdef CONFIG_NFS_V4
unsigned long timestamp; /* For lease renewal */
#endif
- void (*complete) (struct nfs_write_data *, int);
struct page *page_array[NFS_PAGEVEC_SIZE + 1];
};
@@ -769,8 +767,11 @@ struct nfs_rpc_ops {
struct nfs_pathconf *);
u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus);
void (*read_setup) (struct nfs_read_data *);
+ int (*read_done) (struct rpc_task *, struct nfs_read_data *);
void (*write_setup) (struct nfs_write_data *, int how);
+ int (*write_done) (struct rpc_task *, struct nfs_write_data *);
void (*commit_setup) (struct nfs_write_data *, int how);
+ int (*commit_done) (struct rpc_task *, struct nfs_write_data *);
int (*file_open) (struct inode *, struct file *);
int (*file_release) (struct inode *, struct file *);
int (*lock)(struct file *, int, struct file_lock *);
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 6bad4766d3d..d2a8abb5011 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -67,7 +67,8 @@ struct svc_expkey {
int ek_fsidtype;
u32 ek_fsid[3];
- struct svc_export * ek_export;
+ struct vfsmount * ek_mnt;
+ struct dentry * ek_dentry;
};
#define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
@@ -85,9 +86,6 @@ void nfsd_export_shutdown(void);
void nfsd_export_flush(void);
void exp_readlock(void);
void exp_readunlock(void);
-struct svc_expkey * exp_find_key(struct auth_domain *clp,
- int fsid_type, u32 *fsidv,
- struct cache_req *reqp);
struct svc_export * exp_get_by_name(struct auth_domain *clp,
struct vfsmount *mnt,
struct dentry *dentry,
@@ -101,35 +99,20 @@ int exp_rootfh(struct auth_domain *,
int exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq);
int nfserrno(int errno);
-extern void expkey_put(struct cache_head *item, struct cache_detail *cd);
-extern void svc_export_put(struct cache_head *item, struct cache_detail *cd);
-extern struct cache_detail svc_export_cache, svc_expkey_cache;
+extern struct cache_detail svc_export_cache;
static inline void exp_put(struct svc_export *exp)
{
- svc_export_put(&exp->h, &svc_export_cache);
+ cache_put(&exp->h, &svc_export_cache);
}
static inline void exp_get(struct svc_export *exp)
{
cache_get(&exp->h);
}
-static inline struct svc_export *
+extern struct svc_export *
exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
- struct cache_req *reqp)
-{
- struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
- if (ek && !IS_ERR(ek)) {
- struct svc_export *exp = ek->ek_export;
- int err;
- exp_get(exp);
- expkey_put(&ek->h, &svc_expkey_cache);
- if ((err = cache_check(&svc_export_cache, &exp->h, reqp)))
- exp = ERR_PTR(err);
- return exp;
- } else
- return ERR_PTR(PTR_ERR(ek));
-}
+ struct cache_req *reqp);
#endif /* __KERNEL__ */
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index b959a4525cb..1a9ef3e627d 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -350,11 +350,15 @@ extern nodemask_t node_possible_map;
#define num_possible_nodes() nodes_weight(node_possible_map)
#define node_online(node) node_isset((node), node_online_map)
#define node_possible(node) node_isset((node), node_possible_map)
+#define first_online_node first_node(node_online_map)
+#define next_online_node(nid) next_node((nid), node_online_map)
#else
#define num_online_nodes() 1
#define num_possible_nodes() 1
#define node_online(node) ((node) == 0)
#define node_possible(node) ((node) == 0)
+#define first_online_node 0
+#define next_online_node(nid) (MAX_NUMNODES)
#endif
#define any_online_node(mask) \
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 5937dd6053c..51dbab9710c 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -10,25 +10,107 @@
#ifndef _LINUX_NOTIFIER_H
#define _LINUX_NOTIFIER_H
#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/rwsem.h>
-struct notifier_block
-{
- int (*notifier_call)(struct notifier_block *self, unsigned long, void *);
+/*
+ * Notifier chains are of three types:
+ *
+ * Atomic notifier chains: Chain callbacks run in interrupt/atomic
+ * context. Callouts are not allowed to block.
+ * Blocking notifier chains: Chain callbacks run in process context.
+ * Callouts are allowed to block.
+ * Raw notifier chains: There are no restrictions on callbacks,
+ * registration, or unregistration. All locking and protection
+ * must be provided by the caller.
+ *
+ * atomic_notifier_chain_register() may be called from an atomic context,
+ * but blocking_notifier_chain_register() must be called from a process
+ * context. Ditto for the corresponding _unregister() routines.
+ *
+ * atomic_notifier_chain_unregister() and blocking_notifier_chain_unregister()
+ * _must not_ be called from within the call chain.
+ */
+
+struct notifier_block {
+ int (*notifier_call)(struct notifier_block *, unsigned long, void *);
struct notifier_block *next;
int priority;
};
+struct atomic_notifier_head {
+ spinlock_t lock;
+ struct notifier_block *head;
+};
+
+struct blocking_notifier_head {
+ struct rw_semaphore rwsem;
+ struct notifier_block *head;
+};
+
+struct raw_notifier_head {
+ struct notifier_block *head;
+};
+
+#define ATOMIC_INIT_NOTIFIER_HEAD(name) do { \
+ spin_lock_init(&(name)->lock); \
+ (name)->head = NULL; \
+ } while (0)
+#define BLOCKING_INIT_NOTIFIER_HEAD(name) do { \
+ init_rwsem(&(name)->rwsem); \
+ (name)->head = NULL; \
+ } while (0)
+#define RAW_INIT_NOTIFIER_HEAD(name) do { \
+ (name)->head = NULL; \
+ } while (0)
+
+#define ATOMIC_NOTIFIER_INIT(name) { \
+ .lock = SPIN_LOCK_UNLOCKED, \
+ .head = NULL }
+#define BLOCKING_NOTIFIER_INIT(name) { \
+ .rwsem = __RWSEM_INITIALIZER((name).rwsem), \
+ .head = NULL }
+#define RAW_NOTIFIER_INIT(name) { \
+ .head = NULL }
+
+#define ATOMIC_NOTIFIER_HEAD(name) \
+ struct atomic_notifier_head name = \
+ ATOMIC_NOTIFIER_INIT(name)
+#define BLOCKING_NOTIFIER_HEAD(name) \
+ struct blocking_notifier_head name = \
+ BLOCKING_NOTIFIER_INIT(name)
+#define RAW_NOTIFIER_HEAD(name) \
+ struct raw_notifier_head name = \
+ RAW_NOTIFIER_INIT(name)
#ifdef __KERNEL__
-extern int notifier_chain_register(struct notifier_block **list, struct notifier_block *n);
-extern int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n);
-extern int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v);
+extern int atomic_notifier_chain_register(struct atomic_notifier_head *,
+ struct notifier_block *);
+extern int blocking_notifier_chain_register(struct blocking_notifier_head *,
+ struct notifier_block *);
+extern int raw_notifier_chain_register(struct raw_notifier_head *,
+ struct notifier_block *);
+
+extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *,
+ struct notifier_block *);
+extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *,
+ struct notifier_block *);
+extern int raw_notifier_chain_unregister(struct raw_notifier_head *,
+ struct notifier_block *);
+
+extern int atomic_notifier_call_chain(struct atomic_notifier_head *,
+ unsigned long val, void *v);
+extern int blocking_notifier_call_chain(struct blocking_notifier_head *,
+ unsigned long val, void *v);
+extern int raw_notifier_call_chain(struct raw_notifier_head *,
+ unsigned long val, void *v);
#define NOTIFY_DONE 0x0000 /* Don't care */
#define NOTIFY_OK 0x0001 /* Suits me */
#define NOTIFY_STOP_MASK 0x8000 /* Don't call further */
-#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002) /* Bad/Veto action */
+#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002)
+ /* Bad/Veto action */
/*
* Clean way to return from the notifier and stop further calls.
*/
diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h
index 559c4c38a9c..0d514b25245 100644
--- a/include/linux/oprofile.h
+++ b/include/linux/oprofile.h
@@ -61,6 +61,16 @@ void oprofile_arch_exit(void);
*/
void oprofile_add_sample(struct pt_regs * const regs, unsigned long event);
+/**
+ * Add an extended sample. Use this when the PC is not from the regs, and
+ * we cannot determine if we're in kernel mode from the regs.
+ *
+ * This function does perform a backtrace.
+ *
+ */
+void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
+ unsigned long event, int is_kernel);
+
/* Use this instead when the PC value is not from the regs. Doesn't
* backtrace. */
void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event);
@@ -74,10 +84,10 @@ void oprofile_add_trace(unsigned long eip);
* the specified file operations.
*/
int oprofilefs_create_file(struct super_block * sb, struct dentry * root,
- char const * name, struct file_operations * fops);
+ char const * name, const struct file_operations * fops);
int oprofilefs_create_file_perm(struct super_block * sb, struct dentry * root,
- char const * name, struct file_operations * fops, int perm);
+ char const * name, const struct file_operations * fops, int perm);
/** Create a file for read/write access to an unsigned long. */
int oprofilefs_create_ulong(struct super_block * sb, struct dentry * root,
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 6f080ae5928..870fe38378b 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -642,6 +642,7 @@
#define PCI_DEVICE_ID_SI_965 0x0965
#define PCI_DEVICE_ID_SI_5511 0x5511
#define PCI_DEVICE_ID_SI_5513 0x5513
+#define PCI_DEVICE_ID_SI_5517 0x5517
#define PCI_DEVICE_ID_SI_5518 0x5518
#define PCI_DEVICE_ID_SI_5571 0x5571
#define PCI_DEVICE_ID_SI_5581 0x5581
@@ -772,6 +773,7 @@
#define PCI_DEVICE_ID_MOTOROLA_HAWK 0x4803
#define PCI_DEVICE_ID_MOTOROLA_HARRIER 0x480b
#define PCI_DEVICE_ID_MOTOROLA_MPC5200 0x5803
+#define PCI_DEVICE_ID_MOTOROLA_MPC5200B 0x5809
#define PCI_VENDOR_ID_PROMISE 0x105a
#define PCI_DEVICE_ID_PROMISE_20265 0x0d30
@@ -1052,6 +1054,7 @@
#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2 0x00f2
#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1 0x00f3
#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT 0x00f9
+#define PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280 0x00fd
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101
#define PCI_DEVICE_ID_NVIDIA_QUADRO 0x0103
diff --git a/include/linux/pfn.h b/include/linux/pfn.h
new file mode 100644
index 00000000000..bb01f8b92b5
--- /dev/null
+++ b/include/linux/pfn.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_PFN_H_
+#define _LINUX_PFN_H_
+
+#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
+
+#endif
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 5b2fcb19d2d..5b9082cc600 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -4,7 +4,6 @@
enum pid_type
{
PIDTYPE_PID,
- PIDTYPE_TGID,
PIDTYPE_PGID,
PIDTYPE_SID,
PIDTYPE_MAX
@@ -38,7 +37,6 @@ extern struct pid *FASTCALL(find_pid(enum pid_type, int));
extern int alloc_pidmap(void);
extern void FASTCALL(free_pidmap(int));
-extern void switch_exec_pids(struct task_struct *leader, struct task_struct *thread);
#define do_each_task_pid(who, type, task) \
if ((task = find_task_by_pid_type(type, who))) { \
diff --git a/include/linux/poll.h b/include/linux/poll.h
index 8e8f6098508..51e1b56741f 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -11,6 +11,15 @@
#include <linux/mm.h>
#include <asm/uaccess.h>
+/* ~832 bytes of stack space used max in sys_select/sys_poll before allocating
+ additional memory. */
+#define MAX_STACK_ALLOC 832
+#define FRONTEND_STACK_ALLOC 256
+#define SELECT_STACK_ALLOC FRONTEND_STACK_ALLOC
+#define POLL_STACK_ALLOC FRONTEND_STACK_ALLOC
+#define WQUEUES_STACK_ALLOC (MAX_STACK_ALLOC - FRONTEND_STACK_ALLOC)
+#define N_INLINE_POLL_ENTRIES (WQUEUES_STACK_ALLOC / sizeof(struct poll_table_entry))
+
struct poll_table_struct;
/*
@@ -33,6 +42,12 @@ static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc)
pt->qproc = qproc;
}
+struct poll_table_entry {
+ struct file * filp;
+ wait_queue_t wait;
+ wait_queue_head_t * wait_address;
+};
+
/*
* Structures and helpers for sys_poll/sys_poll
*/
@@ -40,6 +55,8 @@ struct poll_wqueues {
poll_table pt;
struct poll_table_page * table;
int error;
+ int inline_index;
+ struct poll_table_entry inline_entries[N_INLINE_POLL_ENTRIES];
};
extern void poll_initwait(struct poll_wqueues *pwq);
diff --git a/include/linux/ppdev.h b/include/linux/ppdev.h
index 141c9658682..f376a7598a7 100644
--- a/include/linux/ppdev.h
+++ b/include/linux/ppdev.h
@@ -14,8 +14,6 @@
* Added PPGETMODES/PPGETMODE/PPGETPHASE, Fred Barnes <frmb2@ukc.ac.uk>, 03/01/2001
*/
-#define PP_MAJOR 99
-
#define PP_IOCTL 'p'
/* Set mode for read/write (e.g. IEEE1284_MODE_EPP) */
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index aa6322d4519..135871df991 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -4,6 +4,7 @@
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/fs.h>
+#include <linux/spinlock.h>
#include <asm/atomic.h>
/*
@@ -55,9 +56,9 @@ struct proc_dir_entry {
nlink_t nlink;
uid_t uid;
gid_t gid;
- unsigned long size;
+ loff_t size;
struct inode_operations * proc_iops;
- struct file_operations * proc_fops;
+ const struct file_operations * proc_fops;
get_info_t *get_info;
struct module *owner;
struct proc_dir_entry *next, *parent, *subdir;
@@ -92,6 +93,8 @@ extern struct proc_dir_entry *proc_bus;
extern struct proc_dir_entry *proc_root_driver;
extern struct proc_dir_entry *proc_root_kcore;
+extern spinlock_t proc_subdir_lock;
+
extern void proc_root_init(void);
extern void proc_misc_init(void);
@@ -125,9 +128,9 @@ extern int proc_match(int, const char *,struct proc_dir_entry *);
extern int proc_readdir(struct file *, void *, filldir_t);
extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
-extern struct file_operations proc_kcore_operations;
-extern struct file_operations proc_kmsg_operations;
-extern struct file_operations ppc_htab_operations;
+extern const struct file_operations proc_kcore_operations;
+extern const struct file_operations proc_kmsg_operations;
+extern const struct file_operations ppc_htab_operations;
/*
* proc_tty.c
@@ -186,7 +189,7 @@ static inline struct proc_dir_entry *proc_net_create(const char *name,
}
static inline struct proc_dir_entry *proc_net_fops_create(const char *name,
- mode_t mode, struct file_operations *fops)
+ mode_t mode, const struct file_operations *fops)
{
struct proc_dir_entry *res = create_proc_entry(name, mode, proc_net);
if (res)
diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h
index fc610bb0f73..27f49c85d5d 100644
--- a/include/linux/qnx4_fs.h
+++ b/include/linux/qnx4_fs.h
@@ -118,8 +118,8 @@ extern struct buffer_head *qnx4_bread(struct inode *, int, int);
extern struct inode_operations qnx4_file_inode_operations;
extern struct inode_operations qnx4_dir_inode_operations;
-extern struct file_operations qnx4_file_operations;
-extern struct file_operations qnx4_dir_operations;
+extern const struct file_operations qnx4_file_operations;
+extern const struct file_operations qnx4_dir_operations;
extern int qnx4_is_free(struct super_block *sb, long block);
extern int qnx4_set_bitmap(struct super_block *sb, long block, int busy);
extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode, struct nameidata *nd);
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 8dc2d04a103..2dab71e1c3d 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -209,7 +209,6 @@ extern struct dqstats dqstats;
#define DQ_FAKE_B 3 /* no limits only usage */
#define DQ_READ_B 4 /* dquot was read into memory */
#define DQ_ACTIVE_B 5 /* dquot is active (dquot_release not called) */
-#define DQ_WAITFREE_B 6 /* dquot being waited (by invalidate_dquots) */
struct dquot {
struct hlist_node dq_hash; /* Hash list in memory */
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index c57ff2fcb30..dd83cca2800 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -45,6 +45,8 @@ do { \
(root)->rnode = NULL; \
} while (0)
+#define RADIX_TREE_MAX_TAGS 2
+
int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long);
@@ -55,15 +57,16 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
int radix_tree_preload(gfp_t gfp_mask);
void radix_tree_init(void);
void *radix_tree_tag_set(struct radix_tree_root *root,
- unsigned long index, int tag);
+ unsigned long index, unsigned int tag);
void *radix_tree_tag_clear(struct radix_tree_root *root,
- unsigned long index, int tag);
+ unsigned long index, unsigned int tag);
int radix_tree_tag_get(struct radix_tree_root *root,
- unsigned long index, int tag);
+ unsigned long index, unsigned int tag);
unsigned int
radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
- unsigned long first_index, unsigned int max_items, int tag);
-int radix_tree_tagged(struct radix_tree_root *root, int tag);
+ unsigned long first_index, unsigned int max_items,
+ unsigned int tag);
+int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag);
static inline void radix_tree_preload_end(void)
{
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
index b6e0bcad84e..66b44e5e0d6 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -92,7 +92,10 @@ extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
extern void md_super_wait(mddev_t *mddev);
extern int sync_page_io(struct block_device *bdev, sector_t sector, int size,
struct page *page, int rw);
+extern void md_do_sync(mddev_t *mddev);
+extern void md_new_event(mddev_t *mddev);
+extern void md_update_sb(mddev_t * mddev);
#define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); }
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index 617b9506c76..e2df61f5b09 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -132,6 +132,14 @@ struct mddev_s
char uuid[16];
+ /* If the array is being reshaped, we need to record the
+ * new shape and an indication of where we are up to.
+ * This is written to the superblock.
+ * If reshape_position is MaxSector, then no reshape is happening (yet).
+ */
+ sector_t reshape_position;
+ int delta_disks, new_level, new_layout, new_chunk;
+
struct mdk_thread_s *thread; /* management thread */
struct mdk_thread_s *sync_thread; /* doing resync or reconstruct */
sector_t curr_resync; /* blocks scheduled */
@@ -143,6 +151,10 @@ struct mddev_s
sector_t resync_mismatches; /* count of sectors where
* parity/replica mismatch found
*/
+
+ /* allow user-space to request suspension of IO to regions of the array */
+ sector_t suspend_lo;
+ sector_t suspend_hi;
/* if zero, use the system-wide default */
int sync_speed_min;
int sync_speed_max;
@@ -157,6 +169,9 @@ struct mddev_s
* DONE: thread is done and is waiting to be reaped
* REQUEST: user-space has requested a sync (used with SYNC)
* CHECK: user-space request for for check-only, no repair
+ * RESHAPE: A reshape is happening
+ *
+ * If neither SYNC or RESHAPE are set, then it is a recovery.
*/
#define MD_RECOVERY_RUNNING 0
#define MD_RECOVERY_SYNC 1
@@ -166,10 +181,11 @@ struct mddev_s
#define MD_RECOVERY_NEEDED 5
#define MD_RECOVERY_REQUESTED 6
#define MD_RECOVERY_CHECK 7
+#define MD_RECOVERY_RESHAPE 8
unsigned long recovery;
int in_sync; /* know to not need resync */
- struct semaphore reconfig_sem;
+ struct mutex reconfig_mutex;
atomic_t active;
int changed; /* true if we might need to reread partition info */
@@ -249,7 +265,8 @@ struct mdk_personality
int (*spare_active) (mddev_t *mddev);
sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);
int (*resize) (mddev_t *mddev, sector_t sectors);
- int (*reshape) (mddev_t *mddev, int raid_disks);
+ int (*check_reshape) (mddev_t *mddev);
+ int (*start_reshape) (mddev_t *mddev);
int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);
/* quiesce moves between quiescence states
* 0 - fully active
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index c100fa5d4bf..774e1acfb8c 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -102,6 +102,18 @@ typedef struct mdp_device_descriptor_s {
#define MD_SB_ERRORS 1
#define MD_SB_BITMAP_PRESENT 8 /* bitmap may be present nearby */
+
+/*
+ * Notes:
+ * - if an array is being reshaped (restriped) in order to change the
+ * the number of active devices in the array, 'raid_disks' will be
+ * the larger of the old and new numbers. 'delta_disks' will
+ * be the "new - old". So if +ve, raid_disks is the new value, and
+ * "raid_disks-delta_disks" is the old. If -ve, raid_disks is the
+ * old value and "raid_disks+delta_disks" is the new (smaller) value.
+ */
+
+
typedef struct mdp_superblock_s {
/*
* Constant generic information
@@ -146,7 +158,13 @@ typedef struct mdp_superblock_s {
__u32 cp_events_hi; /* 10 high-order of checkpoint update count */
#endif
__u32 recovery_cp; /* 11 recovery checkpoint sector count */
- __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 12];
+ /* There are only valid for minor_version > 90 */
+ __u64 reshape_position; /* 12,13 next address in array-space for reshape */
+ __u32 new_level; /* 14 new level we are reshaping to */
+ __u32 delta_disks; /* 15 change in number of raid_disks */
+ __u32 new_layout; /* 16 new layout */
+ __u32 new_chunk; /* 17 new chunk size (bytes) */
+ __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18];
/*
* Personality information
@@ -207,7 +225,14 @@ struct mdp_superblock_1 {
* NOTE: signed, so bitmap can be before superblock
* only meaningful of feature_map[0] is set.
*/
- __u8 pad1[128-100]; /* set to 0 when written */
+
+ /* These are only valid with feature bit '4' */
+ __u64 reshape_position; /* next address in array-space for reshape */
+ __u32 new_level; /* new level we are reshaping to */
+ __u32 delta_disks; /* change in number of raid_disks */
+ __u32 new_layout; /* new layout */
+ __u32 new_chunk; /* new chunk size (bytes) */
+ __u8 pad1[128-124]; /* set to 0 when written */
/* constant this-device information - 64 bytes */
__u64 data_offset; /* sector start of data, often 0 */
@@ -240,8 +265,9 @@ struct mdp_superblock_1 {
/* feature_map bits */
#define MD_FEATURE_BITMAP_OFFSET 1
+#define MD_FEATURE_RESHAPE_ACTIVE 4
-#define MD_FEATURE_ALL 1
+#define MD_FEATURE_ALL 5
#endif
diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
index 394da8207b3..914af667044 100644
--- a/include/linux/raid/raid5.h
+++ b/include/linux/raid/raid5.h
@@ -135,6 +135,7 @@ struct stripe_head {
atomic_t count; /* nr of active thread/requests */
spinlock_t lock;
int bm_seq; /* sequence number for bitmap flushes */
+ int disks; /* disks in stripe */
struct r5dev {
struct bio req;
struct bio_vec vec;
@@ -156,6 +157,7 @@ struct stripe_head {
#define R5_ReadError 8 /* seen a read error here recently */
#define R5_ReWrite 9 /* have tried to over-write the readerror */
+#define R5_Expanded 10 /* This block now has post-expand data */
/*
* Write method
*/
@@ -174,7 +176,9 @@ struct stripe_head {
#define STRIPE_DELAYED 6
#define STRIPE_DEGRADED 7
#define STRIPE_BIT_DELAY 8
-
+#define STRIPE_EXPANDING 9
+#define STRIPE_EXPAND_SOURCE 10
+#define STRIPE_EXPAND_READY 11
/*
* Plugging:
*
@@ -211,12 +215,24 @@ struct raid5_private_data {
int raid_disks, working_disks, failed_disks;
int max_nr_stripes;
+ /* used during an expand */
+ sector_t expand_progress; /* MaxSector when no expand happening */
+ sector_t expand_lo; /* from here up to expand_progress it out-of-bounds
+ * as we haven't flushed the metadata yet
+ */
+ int previous_raid_disks;
+
struct list_head handle_list; /* stripes needing handling */
struct list_head delayed_list; /* stripes that have plugged requests */
struct list_head bitmap_list; /* stripes delaying awaiting bitmap update */
atomic_t preread_active_stripes; /* stripes with scheduled io */
- char cache_name[20];
+ atomic_t reshape_stripes; /* stripes with pending writes for reshape */
+ /* unfortunately we need two cache names as we temporarily have
+ * two caches.
+ */
+ int active_name;
+ char cache_name[2][20];
kmem_cache_t *slab_cache; /* for allocating stripes */
int seq_flush, seq_write;
@@ -238,9 +254,10 @@ struct raid5_private_data {
wait_queue_head_t wait_for_overlap;
int inactive_blocked; /* release of inactive stripes blocked,
* waiting for 25% to be free
- */
+ */
+ int pool_size; /* number of disks in stripeheads in pool */
spinlock_t device_lock;
- struct disk_info disks[0];
+ struct disk_info *disks;
};
typedef struct raid5_private_data raid5_conf_t;
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h
index 953b6df5d03..78ecfa28b1c 100644
--- a/include/linux/ramfs.h
+++ b/include/linux/ramfs.h
@@ -15,7 +15,7 @@ extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
extern int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma);
#endif
-extern struct file_operations ramfs_file_operations;
+extern const struct file_operations ramfs_file_operations;
extern struct vm_operations_struct generic_file_vm_ops;
#endif
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index dad78cecfd2..5676c4210e2 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1704,6 +1704,11 @@ static inline int reiserfs_transaction_running(struct super_block *s)
return 0;
}
+static inline int reiserfs_transaction_free_space(struct reiserfs_transaction_handle *th)
+{
+ return th->t_blocks_allocated - th->t_blocks_logged;
+}
+
int reiserfs_async_progress_wait(struct super_block *s);
struct reiserfs_transaction_handle *reiserfs_persistent_transaction(struct
@@ -1955,7 +1960,7 @@ int reiserfs_global_version_in_proc(char *buffer, char **start, off_t offset,
extern struct inode_operations reiserfs_dir_inode_operations;
extern struct inode_operations reiserfs_symlink_inode_operations;
extern struct inode_operations reiserfs_special_inode_operations;
-extern struct file_operations reiserfs_dir_operations;
+extern const struct file_operations reiserfs_dir_operations;
/* tail_conversion.c */
int direct2indirect(struct reiserfs_transaction_handle *, struct inode *,
@@ -1967,7 +1972,7 @@ void reiserfs_unmap_buffer(struct buffer_head *);
/* file.c */
extern struct inode_operations reiserfs_file_inode_operations;
-extern struct file_operations reiserfs_file_operations;
+extern const struct file_operations reiserfs_file_operations;
extern struct address_space_operations reiserfs_address_space_operations;
/* fix_nodes.c */
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index 87280eb6083..5353afb11db 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -101,13 +101,13 @@ static inline void reiserfs_mark_inode_private(struct inode *inode)
#else
#define is_reiserfs_priv_object(inode) 0
-#define reiserfs_mark_inode_private(inode)
+#define reiserfs_mark_inode_private(inode) do {;} while(0)
#define reiserfs_getxattr NULL
#define reiserfs_setxattr NULL
#define reiserfs_listxattr NULL
#define reiserfs_removexattr NULL
-#define reiserfs_write_lock_xattrs(sb)
-#define reiserfs_write_unlock_xattrs(sb)
+#define reiserfs_write_lock_xattrs(sb) do {;} while(0)
+#define reiserfs_write_unlock_xattrs(sb) do {;} while(0)
#define reiserfs_read_lock_xattrs(sb)
#define reiserfs_read_unlock_xattrs(sb)
diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h
deleted file mode 100644
index 7342e66247f..00000000000
--- a/include/linux/relayfs_fs.h
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * linux/include/linux/relayfs_fs.h
- *
- * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
- * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com)
- *
- * RelayFS definitions and declarations
- */
-
-#ifndef _LINUX_RELAYFS_FS_H
-#define _LINUX_RELAYFS_FS_H
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/list.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/kref.h>
-
-/*
- * Tracks changes to rchan/rchan_buf structs
- */
-#define RELAYFS_CHANNEL_VERSION 6
-
-/*
- * Per-cpu relay channel buffer
- */
-struct rchan_buf
-{
- void *start; /* start of channel buffer */
- void *data; /* start of current sub-buffer */
- size_t offset; /* current offset into sub-buffer */
- size_t subbufs_produced; /* count of sub-buffers produced */
- size_t subbufs_consumed; /* count of sub-buffers consumed */
- struct rchan *chan; /* associated channel */
- wait_queue_head_t read_wait; /* reader wait queue */
- struct work_struct wake_readers; /* reader wake-up work struct */
- struct dentry *dentry; /* channel file dentry */
- struct kref kref; /* channel buffer refcount */
- struct page **page_array; /* array of current buffer pages */
- unsigned int page_count; /* number of current buffer pages */
- unsigned int finalized; /* buffer has been finalized */
- size_t *padding; /* padding counts per sub-buffer */
- size_t prev_padding; /* temporary variable */
- size_t bytes_consumed; /* bytes consumed in cur read subbuf */
- unsigned int cpu; /* this buf's cpu */
-} ____cacheline_aligned;
-
-/*
- * Relay channel data structure
- */
-struct rchan
-{
- u32 version; /* the version of this struct */
- size_t subbuf_size; /* sub-buffer size */
- size_t n_subbufs; /* number of sub-buffers per buffer */
- size_t alloc_size; /* total buffer size allocated */
- struct rchan_callbacks *cb; /* client callbacks */
- struct kref kref; /* channel refcount */
- void *private_data; /* for user-defined data */
- size_t last_toobig; /* tried to log event > subbuf size */
- struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */
-};
-
-/*
- * Relay channel client callbacks
- */
-struct rchan_callbacks
-{
- /*
- * subbuf_start - called on buffer-switch to a new sub-buffer
- * @buf: the channel buffer containing the new sub-buffer
- * @subbuf: the start of the new sub-buffer
- * @prev_subbuf: the start of the previous sub-buffer
- * @prev_padding: unused space at the end of previous sub-buffer
- *
- * The client should return 1 to continue logging, 0 to stop
- * logging.
- *
- * NOTE: subbuf_start will also be invoked when the buffer is
- * created, so that the first sub-buffer can be initialized
- * if necessary. In this case, prev_subbuf will be NULL.
- *
- * NOTE: the client can reserve bytes at the beginning of the new
- * sub-buffer by calling subbuf_start_reserve() in this callback.
- */
- int (*subbuf_start) (struct rchan_buf *buf,
- void *subbuf,
- void *prev_subbuf,
- size_t prev_padding);
-
- /*
- * buf_mapped - relayfs buffer mmap notification
- * @buf: the channel buffer
- * @filp: relayfs file pointer
- *
- * Called when a relayfs file is successfully mmapped
- */
- void (*buf_mapped)(struct rchan_buf *buf,
- struct file *filp);
-
- /*
- * buf_unmapped - relayfs buffer unmap notification
- * @buf: the channel buffer
- * @filp: relayfs file pointer
- *
- * Called when a relayfs file is successfully unmapped
- */
- void (*buf_unmapped)(struct rchan_buf *buf,
- struct file *filp);
- /*
- * create_buf_file - create file to represent a relayfs channel buffer
- * @filename: the name of the file to create
- * @parent: the parent of the file to create
- * @mode: the mode of the file to create
- * @buf: the channel buffer
- * @is_global: outparam - set non-zero if the buffer should be global
- *
- * Called during relay_open(), once for each per-cpu buffer,
- * to allow the client to create a file to be used to
- * represent the corresponding channel buffer. If the file is
- * created outside of relayfs, the parent must also exist in
- * that filesystem.
- *
- * The callback should return the dentry of the file created
- * to represent the relay buffer.
- *
- * Setting the is_global outparam to a non-zero value will
- * cause relay_open() to create a single global buffer rather
- * than the default set of per-cpu buffers.
- *
- * See Documentation/filesystems/relayfs.txt for more info.
- */
- struct dentry *(*create_buf_file)(const char *filename,
- struct dentry *parent,
- int mode,
- struct rchan_buf *buf,
- int *is_global);
-
- /*
- * remove_buf_file - remove file representing a relayfs channel buffer
- * @dentry: the dentry of the file to remove
- *
- * Called during relay_close(), once for each per-cpu buffer,
- * to allow the client to remove a file used to represent a
- * channel buffer.
- *
- * The callback should return 0 if successful, negative if not.
- */
- int (*remove_buf_file)(struct dentry *dentry);
-};
-
-/*
- * relayfs kernel API, fs/relayfs/relay.c
- */
-
-struct rchan *relay_open(const char *base_filename,
- struct dentry *parent,
- size_t subbuf_size,
- size_t n_subbufs,
- struct rchan_callbacks *cb);
-extern void relay_close(struct rchan *chan);
-extern void relay_flush(struct rchan *chan);
-extern void relay_subbufs_consumed(struct rchan *chan,
- unsigned int cpu,
- size_t consumed);
-extern void relay_reset(struct rchan *chan);
-extern int relay_buf_full(struct rchan_buf *buf);
-
-extern size_t relay_switch_subbuf(struct rchan_buf *buf,
- size_t length);
-extern struct dentry *relayfs_create_dir(const char *name,
- struct dentry *parent);
-extern int relayfs_remove_dir(struct dentry *dentry);
-extern struct dentry *relayfs_create_file(const char *name,
- struct dentry *parent,
- int mode,
- struct file_operations *fops,
- void *data);
-extern int relayfs_remove_file(struct dentry *dentry);
-
-/**
- * relay_write - write data into the channel
- * @chan: relay channel
- * @data: data to be written
- * @length: number of bytes to write
- *
- * Writes data into the current cpu's channel buffer.
- *
- * Protects the buffer by disabling interrupts. Use this
- * if you might be logging from interrupt context. Try
- * __relay_write() if you know you won't be logging from
- * interrupt context.
- */
-static inline void relay_write(struct rchan *chan,
- const void *data,
- size_t length)
-{
- unsigned long flags;
- struct rchan_buf *buf;
-
- local_irq_save(flags);
- buf = chan->buf[smp_processor_id()];
- if (unlikely(buf->offset + length > chan->subbuf_size))
- length = relay_switch_subbuf(buf, length);
- memcpy(buf->data + buf->offset, data, length);
- buf->offset += length;
- local_irq_restore(flags);
-}
-
-/**
- * __relay_write - write data into the channel
- * @chan: relay channel
- * @data: data to be written
- * @length: number of bytes to write
- *
- * Writes data into the current cpu's channel buffer.
- *
- * Protects the buffer by disabling preemption. Use
- * relay_write() if you might be logging from interrupt
- * context.
- */
-static inline void __relay_write(struct rchan *chan,
- const void *data,
- size_t length)
-{
- struct rchan_buf *buf;
-
- buf = chan->buf[get_cpu()];
- if (unlikely(buf->offset + length > buf->chan->subbuf_size))
- length = relay_switch_subbuf(buf, length);
- memcpy(buf->data + buf->offset, data, length);
- buf->offset += length;
- put_cpu();
-}
-
-/**
- * relay_reserve - reserve slot in channel buffer
- * @chan: relay channel
- * @length: number of bytes to reserve
- *
- * Returns pointer to reserved slot, NULL if full.
- *
- * Reserves a slot in the current cpu's channel buffer.
- * Does not protect the buffer at all - caller must provide
- * appropriate synchronization.
- */
-static inline void *relay_reserve(struct rchan *chan, size_t length)
-{
- void *reserved;
- struct rchan_buf *buf = chan->buf[smp_processor_id()];
-
- if (unlikely(buf->offset + length > buf->chan->subbuf_size)) {
- length = relay_switch_subbuf(buf, length);
- if (!length)
- return NULL;
- }
- reserved = buf->data + buf->offset;
- buf->offset += length;
-
- return reserved;
-}
-
-/**
- * subbuf_start_reserve - reserve bytes at the start of a sub-buffer
- * @buf: relay channel buffer
- * @length: number of bytes to reserve
- *
- * Helper function used to reserve bytes at the beginning of
- * a sub-buffer in the subbuf_start() callback.
- */
-static inline void subbuf_start_reserve(struct rchan_buf *buf,
- size_t length)
-{
- BUG_ON(length >= buf->chan->subbuf_size - 1);
- buf->offset = length;
-}
-
-/*
- * exported relay file operations, fs/relayfs/inode.c
- */
-extern struct file_operations relay_file_operations;
-
-#endif /* _LINUX_RELAYFS_FS_H */
-
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index b739ac1f7ca..ab61cd1199f 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -91,10 +91,102 @@ struct rtc_pll_info {
#define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */
#define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */
+/* interrupt flags */
+#define RTC_IRQF 0x80 /* any of the following is active */
+#define RTC_PF 0x40
+#define RTC_AF 0x20
+#define RTC_UF 0x10
+
#ifdef __KERNEL__
#include <linux/interrupt.h>
+extern int rtc_month_days(unsigned int month, unsigned int year);
+extern int rtc_valid_tm(struct rtc_time *tm);
+extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time);
+extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
+
+#include <linux/device.h>
+#include <linux/seq_file.h>
+#include <linux/cdev.h>
+#include <linux/poll.h>
+#include <linux/mutex.h>
+
+extern struct class *rtc_class;
+
+struct rtc_class_ops {
+ int (*open)(struct device *);
+ void (*release)(struct device *);
+ int (*ioctl)(struct device *, unsigned int, unsigned long);
+ int (*read_time)(struct device *, struct rtc_time *);
+ int (*set_time)(struct device *, struct rtc_time *);
+ int (*read_alarm)(struct device *, struct rtc_wkalrm *);
+ int (*set_alarm)(struct device *, struct rtc_wkalrm *);
+ int (*proc)(struct device *, struct seq_file *);
+ int (*set_mmss)(struct device *, unsigned long secs);
+ int (*irq_set_state)(struct device *, int enabled);
+ int (*irq_set_freq)(struct device *, int freq);
+ int (*read_callback)(struct device *, int data);
+};
+
+#define RTC_DEVICE_NAME_SIZE 20
+struct rtc_task;
+
+struct rtc_device
+{
+ struct class_device class_dev;
+ struct module *owner;
+
+ int id;
+ char name[RTC_DEVICE_NAME_SIZE];
+
+ struct rtc_class_ops *ops;
+ struct mutex ops_lock;
+
+ struct class_device *rtc_dev;
+ struct cdev char_dev;
+ struct mutex char_lock;
+
+ unsigned long irq_data;
+ spinlock_t irq_lock;
+ wait_queue_head_t irq_queue;
+ struct fasync_struct *async_queue;
+
+ struct rtc_task *irq_task;
+ spinlock_t irq_task_lock;
+ int irq_freq;
+};
+#define to_rtc_device(d) container_of(d, struct rtc_device, class_dev)
+
+extern struct rtc_device *rtc_device_register(const char *name,
+ struct device *dev,
+ struct rtc_class_ops *ops,
+ struct module *owner);
+extern void rtc_device_unregister(struct rtc_device *rdev);
+extern int rtc_interface_register(struct class_interface *intf);
+
+extern int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm);
+extern int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm);
+extern int rtc_set_mmss(struct class_device *class_dev, unsigned long secs);
+extern int rtc_read_alarm(struct class_device *class_dev,
+ struct rtc_wkalrm *alrm);
+extern int rtc_set_alarm(struct class_device *class_dev,
+ struct rtc_wkalrm *alrm);
+extern void rtc_update_irq(struct class_device *class_dev,
+ unsigned long num, unsigned long events);
+
+extern struct class_device *rtc_class_open(char *name);
+extern void rtc_class_close(struct class_device *class_dev);
+
+extern int rtc_irq_register(struct class_device *class_dev,
+ struct rtc_task *task);
+extern void rtc_irq_unregister(struct class_device *class_dev,
+ struct rtc_task *task);
+extern int rtc_irq_set_state(struct class_device *class_dev,
+ struct rtc_task *task, int enabled);
+extern int rtc_irq_set_freq(struct class_device *class_dev,
+ struct rtc_task *task, int freq);
+
typedef struct rtc_task {
void (*func)(void *private_data);
void *private_data;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index e0054c1b9a0..d04186d8cc6 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -35,6 +35,7 @@
#include <linux/topology.h>
#include <linux/seccomp.h>
#include <linux/rcupdate.h>
+#include <linux/futex.h>
#include <linux/auxvec.h> /* For AT_VECTOR_SIZE */
@@ -354,16 +355,8 @@ struct sighand_struct {
atomic_t count;
struct k_sigaction action[_NSIG];
spinlock_t siglock;
- struct rcu_head rcu;
};
-extern void sighand_free_cb(struct rcu_head *rhp);
-
-static inline void sighand_free(struct sighand_struct *sp)
-{
- call_rcu(&sp->rcu, sighand_free_cb);
-}
-
/*
* NOTE! "signal_struct" does not have it's own
* locking, because a shared signal_struct always
@@ -402,6 +395,7 @@ struct signal_struct {
/* ITIMER_REAL timer for the process */
struct hrtimer real_timer;
+ struct task_struct *tsk;
ktime_t it_real_incr;
/* ITIMER_PROF and ITIMER_VIRTUAL timers for the process */
@@ -758,6 +752,7 @@ struct task_struct {
/* PID/PID hash table linkage. */
struct pid pids[PIDTYPE_MAX];
+ struct list_head thread_group;
struct completion *vfork_done; /* for vfork() */
int __user *set_child_tid; /* CLONE_CHILD_SETTID */
@@ -871,6 +866,11 @@ struct task_struct {
int cpuset_mems_generation;
int cpuset_mem_spread_rotor;
#endif
+ struct robust_list_head __user *robust_list;
+#ifdef CONFIG_COMPAT
+ struct compat_robust_list_head __user *compat_robust_list;
+#endif
+
atomic_t fs_excl; /* holding fs exclusive resources */
struct rcu_head rcu;
};
@@ -1094,7 +1094,6 @@ extern void force_sig_specific(int, struct task_struct *);
extern int send_sig(int, struct task_struct *, int);
extern void zap_other_threads(struct task_struct *p);
extern int kill_pg(pid_t, int, int);
-extern int kill_sl(pid_t, int, int);
extern int kill_proc(pid_t, int, int);
extern struct sigqueue *sigqueue_alloc(void);
extern void sigqueue_free(struct sigqueue *);
@@ -1151,10 +1150,8 @@ extern void flush_thread(void);
extern void exit_thread(void);
extern void exit_files(struct task_struct *);
-extern void exit_signal(struct task_struct *);
-extern void __exit_signal(struct task_struct *);
-extern void exit_sighand(struct task_struct *);
-extern void __exit_sighand(struct task_struct *);
+extern void __cleanup_signal(struct signal_struct *);
+extern void __cleanup_sighand(struct sighand_struct *);
extern void exit_itimers(struct signal_struct *);
extern NORET_TYPE void do_group_exit(int);
@@ -1178,19 +1175,7 @@ extern void wait_task_inactive(task_t * p);
#endif
#define remove_parent(p) list_del_init(&(p)->sibling)
-#define add_parent(p, parent) list_add_tail(&(p)->sibling,&(parent)->children)
-
-#define REMOVE_LINKS(p) do { \
- if (thread_group_leader(p)) \
- list_del_init(&(p)->tasks); \
- remove_parent(p); \
- } while (0)
-
-#define SET_LINKS(p) do { \
- if (thread_group_leader(p)) \
- list_add_tail(&(p)->tasks,&init_task.tasks); \
- add_parent(p, (p)->parent); \
- } while (0)
+#define add_parent(p) list_add_tail(&(p)->sibling,&(p)->parent->children)
#define next_task(p) list_entry((p)->tasks.next, struct task_struct, tasks)
#define prev_task(p) list_entry((p)->tasks.prev, struct task_struct, tasks)
@@ -1208,20 +1193,22 @@ extern void wait_task_inactive(task_t * p);
#define while_each_thread(g, t) \
while ((t = next_thread(t)) != g)
-extern task_t * FASTCALL(next_thread(const task_t *p));
-
#define thread_group_leader(p) (p->pid == p->tgid)
+static inline task_t *next_thread(task_t *p)
+{
+ return list_entry(rcu_dereference(p->thread_group.next),
+ task_t, thread_group);
+}
+
static inline int thread_group_empty(task_t *p)
{
- return list_empty(&p->pids[PIDTYPE_TGID].pid_list);
+ return list_empty(&p->thread_group);
}
#define delay_group_leader(p) \
(thread_group_leader(p) && !thread_group_empty(p))
-extern void unhash_process(struct task_struct *p);
-
/*
* Protects ->fs, ->files, ->mm, ->ptrace, ->group_info, ->comm, keyring
* subscriptions and synchronises with wait4(). Also used in procfs. Also
@@ -1241,6 +1228,15 @@ static inline void task_unlock(struct task_struct *p)
spin_unlock(&p->alloc_lock);
}
+extern struct sighand_struct *lock_task_sighand(struct task_struct *tsk,
+ unsigned long *flags);
+
+static inline void unlock_task_sighand(struct task_struct *tsk,
+ unsigned long *flags)
+{
+ spin_unlock_irqrestore(&tsk->sighand->siglock, *flags);
+}
+
#ifndef __HAVE_THREAD_FUNCTIONS
#define task_thread_info(task) (task)->thread_info
diff --git a/include/linux/security.h b/include/linux/security.h
index b18eb8cfa63..aaa0a5cdbf7 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -869,6 +869,11 @@ struct swap_info_struct;
* @ipcp contains the kernel IPC permission structure
* @flag contains the desired (requested) permission set
* Return 0 if permission is granted.
+ * @ipc_getsecurity:
+ * Copy the security label associated with the ipc object into
+ * @buffer. @buffer may be NULL to request the size of the buffer
+ * required. @size indicates the size of @buffer in bytes. Return
+ * number of bytes used/required on success.
*
* Security hooks for individual messages held in System V IPC message queues
* @msg_msg_alloc_security:
@@ -1040,6 +1045,11 @@ struct swap_info_struct;
* @effective contains the effective capability set.
* @inheritable contains the inheritable capability set.
* @permitted contains the permitted capability set.
+ * @capable:
+ * Check whether the @tsk process has the @cap capability.
+ * @tsk contains the task_struct for the process.
+ * @cap contains the capability <include/linux/capability.h>.
+ * Return 0 if the capability is granted for @tsk.
* @acct:
* Check permission before enabling or disabling process accounting. If
* accounting is being enabled, then @file refers to the open file used to
@@ -1053,11 +1063,6 @@ struct swap_info_struct;
* @table contains the ctl_table structure for the sysctl variable.
* @op contains the operation (001 = search, 002 = write, 004 = read).
* Return 0 if permission is granted.
- * @capable:
- * Check whether the @tsk process has the @cap capability.
- * @tsk contains the task_struct for the process.
- * @cap contains the capability <include/linux/capability.h>.
- * Return 0 if the capability is granted for @tsk.
* @syslog:
* Check permission before accessing the kernel message ring or changing
* logging to the console.
@@ -1099,9 +1104,9 @@ struct security_operations {
kernel_cap_t * effective,
kernel_cap_t * inheritable,
kernel_cap_t * permitted);
+ int (*capable) (struct task_struct * tsk, int cap);
int (*acct) (struct file * file);
int (*sysctl) (struct ctl_table * table, int op);
- int (*capable) (struct task_struct * tsk, int cap);
int (*quotactl) (int cmds, int type, int id, struct super_block * sb);
int (*quota_on) (struct dentry * dentry);
int (*syslog) (int type);
@@ -1168,7 +1173,8 @@ struct security_operations {
int (*inode_getxattr) (struct dentry *dentry, char *name);
int (*inode_listxattr) (struct dentry *dentry);
int (*inode_removexattr) (struct dentry *dentry, char *name);
- int (*inode_getsecurity)(struct inode *inode, const char *name, void *buffer, size_t size, int err);
+ const char *(*inode_xattr_getsuffix) (void);
+ int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size);
@@ -1217,6 +1223,7 @@ struct security_operations {
void (*task_to_inode)(struct task_struct *p, struct inode *inode);
int (*ipc_permission) (struct kern_ipc_perm * ipcp, short flag);
+ int (*ipc_getsecurity)(struct kern_ipc_perm *ipcp, void *buffer, size_t size);
int (*msg_msg_alloc_security) (struct msg_msg * msg);
void (*msg_msg_free_security) (struct msg_msg * msg);
@@ -1347,6 +1354,11 @@ static inline void security_capset_set (struct task_struct *target,
security_ops->capset_set (target, effective, inheritable, permitted);
}
+static inline int security_capable(struct task_struct *tsk, int cap)
+{
+ return security_ops->capable(tsk, cap);
+}
+
static inline int security_acct (struct file *file)
{
return security_ops->acct (file);
@@ -1675,7 +1687,12 @@ static inline int security_inode_removexattr (struct dentry *dentry, char *name)
return security_ops->inode_removexattr (dentry, name);
}
-static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
+static inline const char *security_inode_xattr_getsuffix(void)
+{
+ return security_ops->inode_xattr_getsuffix();
+}
+
+static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
{
if (unlikely (IS_PRIVATE (inode)))
return 0;
@@ -1870,6 +1887,11 @@ static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
return security_ops->ipc_permission (ipcp, flag);
}
+static inline int security_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
+{
+ return security_ops->ipc_getsecurity(ipcp, buffer, size);
+}
+
static inline int security_msg_msg_alloc (struct msg_msg * msg)
{
return security_ops->msg_msg_alloc_security (msg);
@@ -2050,6 +2072,11 @@ static inline void security_capset_set (struct task_struct *target,
cap_capset_set (target, effective, inheritable, permitted);
}
+static inline int security_capable(struct task_struct *tsk, int cap)
+{
+ return cap_capable(tsk, cap);
+}
+
static inline int security_acct (struct file *file)
{
return 0;
@@ -2317,7 +2344,12 @@ static inline int security_inode_removexattr (struct dentry *dentry, char *name)
return cap_inode_removexattr(dentry, name);
}
-static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
+static inline const char *security_inode_xattr_getsuffix (void)
+{
+ return NULL ;
+}
+
+static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
{
return -EOPNOTSUPP;
}
@@ -2500,6 +2532,11 @@ static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
return 0;
}
+static inline int security_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
+{
+ return -EOPNOTSUPP;
+}
+
static inline int security_msg_msg_alloc (struct msg_msg * msg)
{
return 0;
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 73b464f0926..8e968141372 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -37,6 +37,7 @@ enum {
PLAT8250_DEV_LEGACY = -1,
PLAT8250_DEV_PLATFORM,
PLAT8250_DEV_PLATFORM1,
+ PLAT8250_DEV_PLATFORM2,
PLAT8250_DEV_FOURPORT,
PLAT8250_DEV_ACCENT,
PLAT8250_DEV_BOCA,
diff --git a/include/linux/serio.h b/include/linux/serio.h
index aa4d6493a03..690aabca8ed 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -119,7 +119,7 @@ static inline void serio_cleanup(struct serio *serio)
}
/*
- * Use the following fucntions to manipulate serio's per-port
+ * Use the following functions to manipulate serio's per-port
* driver-specific data.
*/
static inline void *serio_get_drvdata(struct serio *serio)
@@ -133,7 +133,7 @@ static inline void serio_set_drvdata(struct serio *serio, void *data)
}
/*
- * Use the following fucntions to protect critical sections in
+ * Use the following functions to protect critical sections in
* driver code from port's interrupt handler
*/
static inline void serio_pause_rx(struct serio *serio)
@@ -147,7 +147,7 @@ static inline void serio_continue_rx(struct serio *serio)
}
/*
- * Use the following fucntions to pin serio's driver in process context
+ * Use the following functions to pin serio's driver in process context
*/
static inline int serio_pin_driver(struct serio *serio)
{
diff --git a/include/linux/signal.h b/include/linux/signal.h
index b7d093520bb..162a8fd10b2 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -249,6 +249,8 @@ static inline void init_sigpending(struct sigpending *sig)
INIT_LIST_HEAD(&sig->list);
}
+extern void flush_sigqueue(struct sigpending *queue);
+
/* Test if 'sig' is valid signal. Use this instead of testing _NSIG directly */
static inline int valid_signal(unsigned long sig)
{
diff --git a/include/linux/slab.h b/include/linux/slab.h
index e2ee5b26879..3af03b19c98 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -64,6 +64,7 @@ extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned lo
extern int kmem_cache_destroy(kmem_cache_t *);
extern int kmem_cache_shrink(kmem_cache_t *);
extern void *kmem_cache_alloc(kmem_cache_t *, gfp_t);
+extern void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
extern void kmem_cache_free(kmem_cache_t *, void *);
extern unsigned int kmem_cache_size(kmem_cache_t *);
extern const char *kmem_cache_name(kmem_cache_t *);
@@ -77,11 +78,12 @@ struct cache_sizes {
};
extern struct cache_sizes malloc_sizes[];
-#ifndef CONFIG_DEBUG_SLAB
extern void *__kmalloc(size_t, gfp_t);
+#ifndef CONFIG_DEBUG_SLAB
+#define ____kmalloc(size, flags) __kmalloc(size, flags)
#else
extern void *__kmalloc_track_caller(size_t, gfp_t, void*);
-#define __kmalloc(size, flags) \
+#define ____kmalloc(size, flags) \
__kmalloc_track_caller(size, flags, __builtin_return_address(0))
#endif
@@ -108,7 +110,30 @@ found:
return __kmalloc(size, flags);
}
-extern void *kzalloc(size_t, gfp_t);
+extern void *__kzalloc(size_t, gfp_t);
+
+static inline void *kzalloc(size_t size, gfp_t flags)
+{
+ if (__builtin_constant_p(size)) {
+ int i = 0;
+#define CACHE(x) \
+ if (size <= x) \
+ goto found; \
+ else \
+ i++;
+#include "kmalloc_sizes.h"
+#undef CACHE
+ {
+ extern void __you_cannot_kzalloc_that_much(void);
+ __you_cannot_kzalloc_that_much();
+ }
+found:
+ return kmem_cache_zalloc((flags & GFP_DMA) ?
+ malloc_sizes[i].cs_dmacachep :
+ malloc_sizes[i].cs_cachep, flags);
+ }
+ return __kzalloc(size, flags);
+}
/**
* kcalloc - allocate memory for an array. The memory is set to zero.
@@ -155,17 +180,18 @@ struct kmem_cache *kmem_cache_create(const char *c, size_t, size_t,
void (*)(void *, struct kmem_cache *, unsigned long));
int kmem_cache_destroy(struct kmem_cache *c);
void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags);
+void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
void kmem_cache_free(struct kmem_cache *c, void *b);
const char *kmem_cache_name(struct kmem_cache *);
void *kmalloc(size_t size, gfp_t flags);
-void *kzalloc(size_t size, gfp_t flags);
+void *__kzalloc(size_t size, gfp_t flags);
void kfree(const void *m);
unsigned int ksize(const void *m);
unsigned int kmem_cache_size(struct kmem_cache *c);
static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
{
- return kzalloc(n * size, flags);
+ return __kzalloc(n * size, flags);
}
#define kmem_cache_shrink(d) (0)
@@ -173,6 +199,8 @@ static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
#define kmem_ptr_validate(a, b) (0)
#define kmem_cache_alloc_node(c, f, n) kmem_cache_alloc(c, f)
#define kmalloc_node(s, f, n) kmalloc(s, f)
+#define kzalloc(s, f) __kzalloc(s, f)
+#define ____kmalloc kmalloc
#endif /* CONFIG_SLOB */
@@ -182,7 +210,6 @@ extern kmem_cache_t *names_cachep;
extern kmem_cache_t *files_cachep;
extern kmem_cache_t *filp_cachep;
extern kmem_cache_t *fs_cachep;
-extern kmem_cache_t *signal_cachep;
extern kmem_cache_t *sighand_cachep;
extern kmem_cache_t *bio_cachep;
diff --git a/include/linux/smp.h b/include/linux/smp.h
index d699a16b0cb..e2fa3ab4afc 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -82,7 +82,11 @@ void smp_prepare_boot_cpu(void);
*/
#define raw_smp_processor_id() 0
#define hard_smp_processor_id() 0
-#define smp_call_function(func,info,retry,wait) ({ 0; })
+static inline int up_smp_call_function(void)
+{
+ return 0;
+}
+#define smp_call_function(func,info,retry,wait) (up_smp_call_function())
#define on_each_cpu(func,info,retry,wait) \
({ \
local_irq_disable(); \
diff --git a/include/linux/sound.h b/include/linux/sound.h
index 72b9af4c3fd..f63d8342ffa 100644
--- a/include/linux/sound.h
+++ b/include/linux/sound.h
@@ -30,12 +30,12 @@
*/
struct device;
-extern int register_sound_special(struct file_operations *fops, int unit);
-extern int register_sound_special_device(struct file_operations *fops, int unit, struct device *dev);
-extern int register_sound_mixer(struct file_operations *fops, int dev);
-extern int register_sound_midi(struct file_operations *fops, int dev);
-extern int register_sound_dsp(struct file_operations *fops, int dev);
-extern int register_sound_synth(struct file_operations *fops, int dev);
+extern int register_sound_special(const struct file_operations *fops, int unit);
+extern int register_sound_special_device(const struct file_operations *fops, int unit, struct device *dev);
+extern int register_sound_mixer(const struct file_operations *fops, int dev);
+extern int register_sound_midi(const struct file_operations *fops, int dev);
+extern int register_sound_dsp(const struct file_operations *fops, int dev);
+extern int register_sound_synth(const struct file_operations *fops, int dev);
extern void unregister_sound_special(int unit);
extern void unregister_sound_mixer(int unit);
diff --git a/include/linux/stat.h b/include/linux/stat.h
index 8ff2a122dfe..8669291352d 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -69,7 +69,7 @@ struct kstat {
struct timespec mtime;
struct timespec ctime;
unsigned long blksize;
- unsigned long blocks;
+ unsigned long long blocks;
};
#endif
diff --git a/include/linux/statfs.h b/include/linux/statfs.h
index ad83a2bdb82..b34cc829f98 100644
--- a/include/linux/statfs.h
+++ b/include/linux/statfs.h
@@ -8,11 +8,11 @@
struct kstatfs {
long f_type;
long f_bsize;
- sector_t f_blocks;
- sector_t f_bfree;
- sector_t f_bavail;
- sector_t f_files;
- sector_t f_ffree;
+ u64 f_blocks;
+ u64 f_bfree;
+ u64 f_bavail;
+ u64 f_files;
+ u64 f_ffree;
__kernel_fsid_t f_fsid;
long f_namelen;
long f_frsize;
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index c4e3ea7cf15..b5612c958cc 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -50,7 +50,7 @@ struct cache_head {
time_t last_refresh; /* If CACHE_PENDING, this is when upcall
* was sent, else this is when update was received
*/
- atomic_t refcnt;
+ struct kref ref;
unsigned long flags;
};
#define CACHE_VALID 0 /* Entry contains valid data */
@@ -68,8 +68,7 @@ struct cache_detail {
atomic_t inuse; /* active user-space update or lookup */
char *name;
- void (*cache_put)(struct cache_head *,
- struct cache_detail*);
+ void (*cache_put)(struct kref *);
void (*cache_request)(struct cache_detail *cd,
struct cache_head *h,
@@ -81,6 +80,11 @@ struct cache_detail {
struct cache_detail *cd,
struct cache_head *h);
+ struct cache_head * (*alloc)(void);
+ int (*match)(struct cache_head *orig, struct cache_head *new);
+ void (*init)(struct cache_head *orig, struct cache_head *new);
+ void (*update)(struct cache_head *orig, struct cache_head *new);
+
/* fields below this comment are for internal use
* and should not be touched by cache owners
*/
@@ -123,126 +127,14 @@ struct cache_deferred_req {
int too_many);
};
-/*
- * just like a template in C++, this macro does cache lookup
- * for us.
- * The function is passed some sort of HANDLE from which a cache_detail
- * structure can be determined (via SETUP, DETAIL), a template
- * cache entry (type RTN*), and a "set" flag. Using the HASHFN and the
- * TEST, the function will try to find a matching cache entry in the cache.
- * If "set" == 0 :
- * If an entry is found, it is returned
- * If no entry is found, a new non-VALID entry is created.
- * If "set" == 1 and INPLACE == 0 :
- * If no entry is found a new one is inserted with data from "template"
- * If a non-CACHE_VALID entry is found, it is updated from template using UPDATE
- * If a CACHE_VALID entry is found, a new entry is swapped in with data
- * from "template"
- * If set == 1, and INPLACE == 1 :
- * As above, except that if a CACHE_VALID entry is found, we UPDATE in place
- * instead of swapping in a new entry.
- *
- * If the passed handle has the CACHE_NEGATIVE flag set, then UPDATE is not
- * run but insteead CACHE_NEGATIVE is set in any new item.
- * In any case, the new entry is returned with a reference count.
- *
- *
- * RTN is a struct type for a cache entry
- * MEMBER is the member of the cache which is cache_head, which must be first
- * FNAME is the name for the function
- * ARGS are arguments to function and must contain RTN *item, int set. May
- * also contain something to be usedby SETUP or DETAIL to find cache_detail.
- * SETUP locates the cache detail and makes it available as...
- * DETAIL identifies the cache detail, possibly set up by SETUP
- * HASHFN returns a hash value of the cache entry "item"
- * TEST tests if "tmp" matches "item"
- * INIT copies key information from "item" to "new"
- * UPDATE copies content information from "item" to "tmp"
- * INPLACE is true if updates can happen inplace rather than allocating a new structure
- *
- * WARNING: any substantial changes to this must be reflected in
- * net/sunrpc/svcauth.c(auth_domain_lookup)
- * which is a similar routine that is open-coded.
- */
-#define DefineCacheLookup(RTN,MEMBER,FNAME,ARGS,SETUP,DETAIL,HASHFN,TEST,INIT,UPDATE,INPLACE) \
-RTN *FNAME ARGS \
-{ \
- RTN *tmp, *new=NULL; \
- struct cache_head **hp, **head; \
- SETUP; \
- head = &(DETAIL)->hash_table[HASHFN]; \
- retry: \
- if (set||new) write_lock(&(DETAIL)->hash_lock); \
- else read_lock(&(DETAIL)->hash_lock); \
- for(hp=head; *hp != NULL; hp = &tmp->MEMBER.next) { \
- tmp = container_of(*hp, RTN, MEMBER); \
- if (TEST) { /* found a match */ \
- \
- if (set && !INPLACE && test_bit(CACHE_VALID, &tmp->MEMBER.flags) && !new) \
- break; \
- \
- if (new) \
- {INIT;} \
- if (set) { \
- if (!INPLACE && test_bit(CACHE_VALID, &tmp->MEMBER.flags))\
- { /* need to swap in new */ \
- RTN *t2; \
- \
- new->MEMBER.next = tmp->MEMBER.next; \
- *hp = &new->MEMBER; \
- tmp->MEMBER.next = NULL; \
- t2 = tmp; tmp = new; new = t2; \
- } \
- if (test_bit(CACHE_NEGATIVE, &item->MEMBER.flags)) \
- set_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags); \
- else { \
- UPDATE; \
- clear_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags); \
- } \
- } \
- cache_get(&tmp->MEMBER); \
- if (set||new) write_unlock(&(DETAIL)->hash_lock); \
- else read_unlock(&(DETAIL)->hash_lock); \
- if (set) \
- cache_fresh(DETAIL, &tmp->MEMBER, item->MEMBER.expiry_time); \
- if (set && !INPLACE && new) cache_fresh(DETAIL, &new->MEMBER, 0); \
- if (new) (DETAIL)->cache_put(&new->MEMBER, DETAIL); \
- return tmp; \
- } \
- } \
- /* Didn't find anything */ \
- if (new) { \
- INIT; \
- new->MEMBER.next = *head; \
- *head = &new->MEMBER; \
- (DETAIL)->entries ++; \
- cache_get(&new->MEMBER); \
- if (set) { \
- tmp = new; \
- if (test_bit(CACHE_NEGATIVE, &item->MEMBER.flags)) \
- set_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags); \
- else {UPDATE;} \
- } \
- } \
- if (set||new) write_unlock(&(DETAIL)->hash_lock); \
- else read_unlock(&(DETAIL)->hash_lock); \
- if (new && set) \
- cache_fresh(DETAIL, &new->MEMBER, item->MEMBER.expiry_time); \
- if (new) \
- return new; \
- new = kmalloc(sizeof(*new), GFP_KERNEL); \
- if (new) { \
- cache_init(&new->MEMBER); \
- goto retry; \
- } \
- return NULL; \
-}
+extern struct cache_head *
+sunrpc_cache_lookup(struct cache_detail *detail,
+ struct cache_head *key, int hash);
+extern struct cache_head *
+sunrpc_cache_update(struct cache_detail *detail,
+ struct cache_head *new, struct cache_head *old, int hash);
-#define DefineSimpleCacheLookup(STRUCT,INPLACE) \
- DefineCacheLookup(struct STRUCT, h, STRUCT##_lookup, (struct STRUCT *item, int set), /*no setup */, \
- & STRUCT##_cache, STRUCT##_hash(item), STRUCT##_match(item, tmp),\
- STRUCT##_init(new, item), STRUCT##_update(tmp, item),INPLACE)
#define cache_for_each(pos, detail, index, member) \
for (({read_lock(&(detail)->hash_lock); index = (detail)->hash_size;}) ; \
@@ -258,22 +150,19 @@ extern void cache_clean_deferred(void *owner);
static inline struct cache_head *cache_get(struct cache_head *h)
{
- atomic_inc(&h->refcnt);
+ kref_get(&h->ref);
return h;
}
-static inline int cache_put(struct cache_head *h, struct cache_detail *cd)
+static inline void cache_put(struct cache_head *h, struct cache_detail *cd)
{
- if (atomic_read(&h->refcnt) <= 2 &&
+ if (atomic_read(&h->ref.refcount) <= 2 &&
h->expiry_time < cd->nextcheck)
cd->nextcheck = h->expiry_time;
- return atomic_dec_and_test(&h->refcnt);
+ kref_put(&h->ref, cd->cache_put);
}
-extern void cache_init(struct cache_head *h);
-extern void cache_fresh(struct cache_detail *detail,
- struct cache_head *head, time_t expiry);
extern int cache_check(struct cache_detail *detail,
struct cache_head *h, struct cache_req *rqstp);
extern void cache_flush(void);
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index f147e6b8433..8fe9f35eba3 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -45,7 +45,8 @@ struct rpc_clnt {
char * cl_server; /* server machine name */
char * cl_protname; /* protocol name */
struct rpc_auth * cl_auth; /* authenticator */
- struct rpc_stat * cl_stats; /* statistics */
+ struct rpc_stat * cl_stats; /* per-program statistics */
+ struct rpc_iostats * cl_metrics; /* per-client statistics */
unsigned int cl_softrtry : 1,/* soft timeouts */
cl_intr : 1,/* interruptible */
@@ -59,6 +60,7 @@ struct rpc_clnt {
int cl_nodelen; /* nodename length */
char cl_nodename[UNX_MAXNODENAME];
char cl_pathname[30];/* Path in rpc_pipe_fs */
+ struct vfsmount * cl_vfsmnt;
struct dentry * cl_dentry; /* inode */
struct rpc_clnt * cl_parent; /* Points to parent of clones */
struct rpc_rtt cl_rtt_default;
@@ -100,6 +102,8 @@ struct rpc_procinfo {
unsigned int p_bufsiz; /* req. buffer size */
unsigned int p_count; /* call count */
unsigned int p_timer; /* Which RTT timer to use */
+ u32 p_statidx; /* Which procedure to account */
+ char * p_name; /* name of procedure */
};
#define RPC_CONGESTED(clnt) (RPCXPRT_CONGESTED((clnt)->cl_xprt))
@@ -137,20 +141,6 @@ size_t rpc_max_payload(struct rpc_clnt *);
void rpc_force_rebind(struct rpc_clnt *);
int rpc_ping(struct rpc_clnt *clnt, int flags);
-static __inline__
-int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
-{
- struct rpc_message msg = {
- .rpc_proc = &clnt->cl_procinfo[proc],
- .rpc_argp = argp,
- .rpc_resp = resp,
- .rpc_cred = NULL
- };
- return rpc_call_sync(clnt, &msg, flags);
-}
-
-extern void rpciod_wake_up(void);
-
/*
* Helper function for NFSroot support
*/
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index 2c3601d3104..1279280d719 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -53,6 +53,8 @@ struct krb5_ctx {
struct xdr_netobj mech_used;
};
+extern spinlock_t krb5_seq_lock;
+
#define KG_TOK_MIC_MSG 0x0101
#define KG_TOK_WRAP_MSG 0x0201
diff --git a/include/linux/sunrpc/metrics.h b/include/linux/sunrpc/metrics.h
new file mode 100644
index 00000000000..8f96e9dc369
--- /dev/null
+++ b/include/linux/sunrpc/metrics.h
@@ -0,0 +1,77 @@
+/*
+ * linux/include/linux/sunrpc/metrics.h
+ *
+ * Declarations for RPC client per-operation metrics
+ *
+ * Copyright (C) 2005 Chuck Lever <cel@netapp.com>
+ *
+ * RPC client per-operation statistics provide latency and retry
+ * information about each type of RPC procedure in a given RPC program.
+ * These statistics are not for detailed problem diagnosis, but simply
+ * to indicate whether the problem is local or remote.
+ *
+ * These counters are not meant to be human-readable, but are meant to be
+ * integrated into system monitoring tools such as "sar" and "iostat". As
+ * such, the counters are sampled by the tools over time, and are never
+ * zeroed after a file system is mounted. Moving averages can be computed
+ * by the tools by taking the difference between two instantaneous samples
+ * and dividing that by the time between the samples.
+ *
+ * The counters are maintained in a single array per RPC client, indexed
+ * by procedure number. There is no need to maintain separate counter
+ * arrays per-CPU because these counters are always modified behind locks.
+ */
+
+#ifndef _LINUX_SUNRPC_METRICS_H
+#define _LINUX_SUNRPC_METRICS_H
+
+#include <linux/seq_file.h>
+
+#define RPC_IOSTATS_VERS "1.0"
+
+struct rpc_iostats {
+ /*
+ * These counters give an idea about how many request
+ * transmissions are required, on average, to complete that
+ * particular procedure. Some procedures may require more
+ * than one transmission because the server is unresponsive,
+ * the client is retransmitting too aggressively, or the
+ * requests are large and the network is congested.
+ */
+ unsigned long om_ops, /* count of operations */
+ om_ntrans, /* count of RPC transmissions */
+ om_timeouts; /* count of major timeouts */
+
+ /*
+ * These count how many bytes are sent and received for a
+ * given RPC procedure type. This indicates how much load a
+ * particular procedure is putting on the network. These
+ * counts include the RPC and ULP headers, and the request
+ * payload.
+ */
+ unsigned long long om_bytes_sent, /* count of bytes out */
+ om_bytes_recv; /* count of bytes in */
+
+ /*
+ * The length of time an RPC request waits in queue before
+ * transmission, the network + server latency of the request,
+ * and the total time the request spent from init to release
+ * are measured.
+ */
+ unsigned long long om_queue, /* jiffies queued for xmit */
+ om_rtt, /* jiffies for RPC RTT */
+ om_execute; /* jiffies for RPC execution */
+} ____cacheline_aligned;
+
+struct rpc_task;
+struct rpc_clnt;
+
+/*
+ * EXPORTed functions for managing rpc_iostats structures
+ */
+struct rpc_iostats * rpc_alloc_iostats(struct rpc_clnt *);
+void rpc_count_iostats(struct rpc_task *);
+void rpc_print_iostats(struct seq_file *, struct rpc_clnt *);
+void rpc_free_iostats(struct rpc_iostats *);
+
+#endif /* _LINUX_SUNRPC_METRICS_H */
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index 63929349571..2c2189cb30a 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -45,6 +45,8 @@ extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *);
extern int rpc_rmdir(char *);
extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags);
extern int rpc_unlink(char *);
+extern struct vfsmount *rpc_get_mount(void);
+extern void rpc_put_mount(void);
#endif
#endif
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 8b25629accd..82a91bb2236 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -86,6 +86,12 @@ struct rpc_task {
struct work_struct tk_work; /* Async task work queue */
struct rpc_wait tk_wait; /* RPC wait */
} u;
+
+ unsigned short tk_timeouts; /* maj timeouts */
+ size_t tk_bytes_sent; /* total bytes sent */
+ unsigned long tk_start; /* RPC task init timestamp */
+ long tk_rtt; /* round-trip time (jiffies) */
+
#ifdef RPC_DEBUG
unsigned short tk_pid; /* debugging aid */
#endif
@@ -203,6 +209,7 @@ struct rpc_wait_queue {
unsigned char priority; /* current priority */
unsigned char count; /* # task groups remaining serviced so far */
unsigned char nr; /* # tasks remaining for cookie */
+ unsigned short qlen; /* total # tasks waiting in queue */
#ifdef RPC_DEBUG
const char * name;
#endif
@@ -269,13 +276,13 @@ void * rpc_malloc(struct rpc_task *, size_t);
void rpc_free(struct rpc_task *);
int rpciod_up(void);
void rpciod_down(void);
-void rpciod_wake_up(void);
int __rpc_wait_for_completion_task(struct rpc_task *task, int (*)(void *));
#ifdef RPC_DEBUG
void rpc_show_tasks(void);
#endif
int rpc_init_mempool(void);
void rpc_destroy_mempool(void);
+extern struct workqueue_struct *rpciod_workqueue;
static inline void rpc_exit(struct rpc_task *task, int status)
{
diff --git a/include/linux/sunrpc/stats.h b/include/linux/sunrpc/stats.h
index 0d6ed3c8bdc..d93c24b47f3 100644
--- a/include/linux/sunrpc/stats.h
+++ b/include/linux/sunrpc/stats.h
@@ -50,7 +50,7 @@ struct proc_dir_entry * rpc_proc_register(struct rpc_stat *);
void rpc_proc_unregister(const char *);
void rpc_proc_zero(struct rpc_program *);
struct proc_dir_entry * svc_proc_register(struct svc_stat *,
- struct file_operations *);
+ const struct file_operations *);
void svc_proc_unregister(const char *);
void svc_seq_show(struct seq_file *,
@@ -65,7 +65,7 @@ static inline void rpc_proc_unregister(const char *p) {}
static inline void rpc_proc_zero(struct rpc_program *p) {}
static inline struct proc_dir_entry *svc_proc_register(struct svc_stat *s,
- struct file_operations *f) { return NULL; }
+ const struct file_operations *f) { return NULL; }
static inline void svc_proc_unregister(const char *p) {}
static inline void svc_seq_show(struct seq_file *seq,
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index c119ce7cbd2..2fe2087edd6 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -45,9 +45,10 @@ struct svc_rqst; /* forward decl */
* of ip addresses to the given client.
*/
struct auth_domain {
- struct cache_head h;
+ struct kref ref;
+ struct hlist_node hash;
char *name;
- int flavour;
+ struct auth_ops *flavour;
};
/*
@@ -86,6 +87,9 @@ struct auth_domain {
*
* domain_release()
* This call releases a domain.
+ * set_client()
+ * Givens a pending request (struct svc_rqst), finds and assigns
+ * an appropriate 'auth_domain' as the client.
*/
struct auth_ops {
char * name;
@@ -117,7 +121,7 @@ extern void svc_auth_unregister(rpc_authflavor_t flavor);
extern struct auth_domain *unix_domain_find(char *name);
extern void auth_domain_put(struct auth_domain *item);
extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom);
-extern struct auth_domain *auth_domain_lookup(struct auth_domain *item, int set);
+extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
extern struct auth_domain *auth_domain_find(char *name);
extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
extern int auth_unix_forget_old(struct auth_domain *dom);
@@ -160,8 +164,6 @@ static inline unsigned long hash_mem(char *buf, int length, int bits)
return hash >> (BITS_PER_LONG - bits);
}
-extern struct cache_detail auth_domain_cache, ip_map_cache;
-
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_SVCAUTH_H_ */
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 6ef99b14ff0..7eebbab7160 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -114,6 +114,7 @@ struct rpc_xprt_ops {
void (*release_request)(struct rpc_task *task);
void (*close)(struct rpc_xprt *xprt);
void (*destroy)(struct rpc_xprt *xprt);
+ void (*print_stats)(struct rpc_xprt *xprt, struct seq_file *seq);
};
struct rpc_xprt {
@@ -187,6 +188,18 @@ struct rpc_xprt {
struct list_head recv;
+ struct {
+ unsigned long bind_count, /* total number of binds */
+ connect_count, /* total number of connects */
+ connect_start, /* connect start timestamp */
+ connect_time, /* jiffies waiting for connect */
+ sends, /* how many complete requests */
+ recvs, /* how many complete requests */
+ bad_xids; /* lookup_rqst didn't find XID */
+
+ unsigned long long req_u, /* average requests on the wire */
+ bklog_u; /* backlog queue utilization */
+ } stat;
void (*old_data_ready)(struct sock *, int);
void (*old_state_change)(struct sock *);
diff --git a/include/linux/synclink.h b/include/linux/synclink.h
index 1b7cd8d1a71..2993302f792 100644
--- a/include/linux/synclink.h
+++ b/include/linux/synclink.h
@@ -1,7 +1,7 @@
/*
* SyncLink Multiprotocol Serial Adapter Driver
*
- * $Id: synclink.h,v 3.10 2005/11/08 19:50:54 paulkf Exp $
+ * $Id: synclink.h,v 3.11 2006/02/06 21:20:29 paulkf Exp $
*
* Copyright (C) 1998-2000 by Microgate Corporation
*
@@ -221,6 +221,12 @@ struct mgsl_icount {
__u32 rxidle;
};
+struct gpio_desc {
+ __u32 state;
+ __u32 smask;
+ __u32 dir;
+ __u32 dmask;
+};
#define DEBUG_LEVEL_DATA 1
#define DEBUG_LEVEL_ERROR 2
@@ -276,5 +282,8 @@ struct mgsl_icount {
#define MGSL_IOCLOOPTXDONE _IO(MGSL_MAGIC_IOC,9)
#define MGSL_IOCSIF _IO(MGSL_MAGIC_IOC,10)
#define MGSL_IOCGIF _IO(MGSL_MAGIC_IOC,11)
+#define MGSL_IOCSGPIO _IOW(MGSL_MAGIC_IOC,16,struct gpio_desc)
+#define MGSL_IOCGGPIO _IOR(MGSL_MAGIC_IOC,17,struct gpio_desc)
+#define MGSL_IOCWAITGPIO _IOWR(MGSL_MAGIC_IOC,18,struct gpio_desc)
#endif /* _SYNCLINK_H_ */
diff --git a/include/linux/threads.h b/include/linux/threads.h
index b59738ac619..e646bcdf261 100644
--- a/include/linux/threads.h
+++ b/include/linux/threads.h
@@ -28,7 +28,8 @@
#define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000)
/*
- * A maximum of 4 million PIDs should be enough for a while:
+ * A maximum of 4 million PIDs should be enough for a while.
+ * [NOTE: PID/TIDs are limited to 2^29 ~= 500+ million, see futex.h.]
*/
#define PID_MAX_LIMIT (CONFIG_BASE_SMALL ? PAGE_SIZE * 8 : \
(sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT))
diff --git a/include/linux/time.h b/include/linux/time.h
index d9cdba54b78..0cd696cee99 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -73,12 +73,6 @@ extern void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec);
#define timespec_valid(ts) \
(((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC))
-/*
- * 64-bit nanosec type. Large enough to span 292+ years in nanosecond
- * resolution. Ought to be enough for a while.
- */
-typedef s64 nsec_t;
-
extern struct timespec xtime;
extern struct timespec wall_to_monotonic;
extern seqlock_t xtime_lock;
@@ -101,6 +95,7 @@ extern long do_utimes(int dfd, char __user *filename, struct timeval *times);
struct itimerval;
extern int do_setitimer(int which, struct itimerval *value,
struct itimerval *ovalue);
+extern unsigned int alarm_setitimer(unsigned int seconds);
extern int do_getitimer(int which, struct itimerval *value);
extern void getnstimeofday(struct timespec *tv);
@@ -113,9 +108,9 @@ extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
* Returns the scalar nanosecond representation of the timespec
* parameter.
*/
-static inline nsec_t timespec_to_ns(const struct timespec *ts)
+static inline s64 timespec_to_ns(const struct timespec *ts)
{
- return ((nsec_t) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
+ return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
}
/**
@@ -125,9 +120,9 @@ static inline nsec_t timespec_to_ns(const struct timespec *ts)
* Returns the scalar nanosecond representation of the timeval
* parameter.
*/
-static inline nsec_t timeval_to_ns(const struct timeval *tv)
+static inline s64 timeval_to_ns(const struct timeval *tv)
{
- return ((nsec_t) tv->tv_sec * NSEC_PER_SEC) +
+ return ((s64) tv->tv_sec * NSEC_PER_SEC) +
tv->tv_usec * NSEC_PER_USEC;
}
@@ -137,7 +132,7 @@ static inline nsec_t timeval_to_ns(const struct timeval *tv)
*
* Returns the timespec representation of the nsec parameter.
*/
-extern struct timespec ns_to_timespec(const nsec_t nsec);
+extern struct timespec ns_to_timespec(const s64 nsec);
/**
* ns_to_timeval - Convert nanoseconds to timeval
@@ -145,7 +140,7 @@ extern struct timespec ns_to_timespec(const nsec_t nsec);
*
* Returns the timeval representation of the nsec parameter.
*/
-extern struct timeval ns_to_timeval(const nsec_t nsec);
+extern struct timeval ns_to_timeval(const s64 nsec);
#endif /* __KERNEL__ */
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 9b9877fd250..b5caabca553 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -69,13 +69,13 @@ extern unsigned long next_timer_interrupt(void);
* @timer: the timer to be added
*
* The kernel will do a ->function(->data) callback from the
- * timer interrupt at the ->expired point in the future. The
+ * timer interrupt at the ->expires point in the future. The
* current time is 'jiffies'.
*
- * The timer's ->expired, ->function (and if the handler uses it, ->data)
+ * The timer's ->expires, ->function (and if the handler uses it, ->data)
* fields must be set prior calling this function.
*
- * Timers with an ->expired field in the past will be executed in the next
+ * Timers with an ->expires field in the past will be executed in the next
* timer tick.
*/
static inline void add_timer(struct timer_list *timer)
@@ -96,6 +96,7 @@ static inline void add_timer(struct timer_list *timer)
extern void init_timers(void);
extern void run_local_timers(void);
-extern int it_real_fn(void *);
+struct hrtimer;
+extern int it_real_fn(struct hrtimer *);
#endif
diff --git a/include/linux/timex.h b/include/linux/timex.h
index b7ca1204e42..03914b7e41b 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -97,38 +97,11 @@
#define MAXPHASE 512000L /* max phase error (us) */
#define MAXFREQ (512L << SHIFT_USEC) /* max frequency error (ppm) */
-#define MAXTIME (200L << PPS_AVG) /* max PPS error (jitter) (200 us) */
#define MINSEC 16L /* min interval between updates (s) */
#define MAXSEC 1200L /* max interval between updates (s) */
#define NTP_PHASE_LIMIT (MAXPHASE << 5) /* beyond max. dispersion */
/*
- * The following defines are used only if a pulse-per-second (PPS)
- * signal is available and connected via a modem control lead, such as
- * produced by the optional ppsclock feature incorporated in the Sun
- * asynch driver. They establish the design parameters of the frequency-
- * lock loop used to discipline the CPU clock oscillator to the PPS
- * signal.
- *
- * PPS_AVG is the averaging factor for the frequency loop, as well as
- * the time and frequency dispersion.
- *
- * PPS_SHIFT and PPS_SHIFTMAX specify the minimum and maximum
- * calibration intervals, respectively, in seconds as a power of two.
- *
- * PPS_VALID is the maximum interval before the PPS signal is considered
- * invalid and protocol updates used directly instead.
- *
- * MAXGLITCH is the maximum interval before a time offset of more than
- * MAXTIME is believed.
- */
-#define PPS_AVG 2 /* pps averaging constant (shift) */
-#define PPS_SHIFT 2 /* min interval duration (s) (shift) */
-#define PPS_SHIFTMAX 8 /* max interval duration (s) (shift) */
-#define PPS_VALID 120 /* pps signal watchdog max (s) */
-#define MAXGLITCH 30 /* pps signal glitch max (s) */
-
-/*
* syscall interface - used (mainly by NTP daemon)
* to discipline kernel clock oscillator
*/
@@ -246,20 +219,6 @@ extern long time_reftime; /* time at last adjustment (s) */
extern long time_adjust; /* The amount of adjtime left */
extern long time_next_adjust; /* Value for time_adjust at next tick */
-/* interface variables pps->timer interrupt */
-extern long pps_offset; /* pps time offset (us) */
-extern long pps_jitter; /* time dispersion (jitter) (us) */
-extern long pps_freq; /* frequency offset (scaled ppm) */
-extern long pps_stabil; /* frequency dispersion (scaled ppm) */
-extern long pps_valid; /* pps signal watchdog counter */
-
-/* interface variables pps->adjtimex */
-extern int pps_shift; /* interval duration (s) (shift) */
-extern long pps_jitcnt; /* jitter limit exceeded */
-extern long pps_calcnt; /* calibration intervals */
-extern long pps_errcnt; /* calibration errors */
-extern long pps_stbcnt; /* stability limit exceeded */
-
/**
* ntp_clear - Clears the NTP state variables
*
@@ -348,6 +307,8 @@ time_interpolator_reset(void)
/* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
extern u64 current_tick_length(void);
+extern int do_adjtimex(struct timex *);
+
#endif /* KERNEL */
#endif /* LINUX_TIMEX_H */
diff --git a/include/linux/topology.h b/include/linux/topology.h
index e8eb0040ce3..a305ae2e44b 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -164,6 +164,15 @@
.nr_balance_failed = 0, \
}
+#ifdef CONFIG_SCHED_MC
+#ifndef SD_MC_INIT
+/* for now its same as SD_CPU_INIT.
+ * TBD: Tune Domain parameters!
+ */
+#define SD_MC_INIT SD_CPU_INIT
+#endif
+#endif
+
#ifdef CONFIG_NUMA
#ifndef SD_NODE_INIT
#error Please define an appropriate SD_NODE_INIT in include/asm/topology.h!!!
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index 0c6169fff36..0976a163b45 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -2,8 +2,8 @@
#define _LINUX_TTY_FLIP_H
extern int tty_buffer_request_room(struct tty_struct *tty, size_t size);
-extern int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t size);
-extern int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *chars, char *flags, size_t size);
+extern int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size);
+extern int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size);
extern int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size);
extern int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size);
diff --git a/include/linux/types.h b/include/linux/types.h
index 54ae2d59e71..1046c7ad86d 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -137,6 +137,10 @@ typedef __s64 int64_t;
typedef unsigned long sector_t;
#endif
+#ifndef HAVE_BLKCNT_T
+typedef unsigned long blkcnt_t;
+#endif
+
/*
* The type of an index into the pagecache. Use a #define so asm/types.h
* can override it.
diff --git a/include/linux/udf_fs_i.h b/include/linux/udf_fs_i.h
index 1e7508420fc..ffaf05679ff 100644
--- a/include/linux/udf_fs_i.h
+++ b/include/linux/udf_fs_i.h
@@ -15,27 +15,6 @@
#ifdef __KERNEL__
-#ifndef _ECMA_167_H
-typedef struct
-{
- __u32 logicalBlockNum;
- __u16 partitionReferenceNum;
-} __attribute__ ((packed)) lb_addr;
-
-typedef struct
-{
- __u32 extLength;
- __u32 extPosition;
-} __attribute__ ((packed)) short_ad;
-
-typedef struct
-{
- __u32 extLength;
- lb_addr extLocation;
- __u8 impUse[6];
-} __attribute__ ((packed)) long_ad;
-#endif
-
struct udf_inode_info
{
struct timespec i_crtime;
diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h
index b0ffe4356e5..843aeaaa79d 100644
--- a/include/linux/ufs_fs.h
+++ b/include/linux/ufs_fs.h
@@ -895,7 +895,7 @@ extern void ufs_set_link(struct inode *, struct ufs_dir_entry *, struct buffer_h
/* file.c */
extern struct inode_operations ufs_file_inode_operations;
-extern struct file_operations ufs_file_operations;
+extern const struct file_operations ufs_file_operations;
extern struct address_space_operations ufs_aops;
@@ -915,7 +915,7 @@ extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create);
/* namei.c */
-extern struct file_operations ufs_dir_operations;
+extern const struct file_operations ufs_dir_operations;
/* super.c */
extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 130d125fda1..e34e5e3dce5 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -615,7 +615,7 @@ extern struct bus_type usb_bus_type;
*/
struct usb_class_driver {
char *name;
- struct file_operations *fops;
+ const struct file_operations *fops;
int minor_base;
};
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 724cfbf54b8..af2d6155d3f 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -75,7 +75,7 @@ struct video_device
int minor;
/* device ops + callbacks */
- struct file_operations *fops;
+ const struct file_operations *fops;
void (*release)(struct video_device *vfd);
@@ -883,6 +883,7 @@ struct v4l2_modulator
#define V4L2_TUNER_MODE_LANG2 0x0002
#define V4L2_TUNER_MODE_SAP 0x0002
#define V4L2_TUNER_MODE_LANG1 0x0003
+#define V4L2_TUNER_MODE_LANG1_LANG2 0x0004
struct v4l2_frequency
{
diff --git a/include/linux/x1205.h b/include/linux/x1205.h
deleted file mode 100644
index 64fd3af894a..00000000000
--- a/include/linux/x1205.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * x1205.h - defines for drivers/i2c/chips/x1205.c
- * Copyright 2004 Karen Spearel
- * Copyright 2005 Alessandro Zummo
- *
- * 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.
- */
-
-#ifndef __LINUX_X1205_H__
-#define __LINUX_X1205_H__
-
-/* commands */
-
-#define X1205_CMD_GETDATETIME 0
-#define X1205_CMD_SETTIME 1
-#define X1205_CMD_SETDATETIME 2
-#define X1205_CMD_GETALARM 3
-#define X1205_CMD_SETALARM 4
-#define X1205_CMD_GETDTRIM 5
-#define X1205_CMD_SETDTRIM 6
-#define X1205_CMD_GETATRIM 7
-#define X1205_CMD_SETATRIM 8
-
-extern int x1205_do_command(unsigned int cmd, void *arg);
-extern int x1205_direct_attach(int adapter_id,
- struct i2c_client_address_data *address_data);
-
-#endif /* __LINUX_X1205_H__ */
diff --git a/include/linux/zorro.h b/include/linux/zorro.h
index ba5b72768bb..2f135cf6eef 100644
--- a/include/linux/zorro.h
+++ b/include/linux/zorro.h
@@ -271,39 +271,6 @@ static inline void zorro_set_drvdata (struct zorro_dev *z, void *data)
}
-/*
- * A helper function which helps ensure correct zorro_driver
- * setup and cleanup for commonly-encountered hotplug/modular cases
- *
- * This MUST stay in a header, as it checks for -DMODULE
- */
-static inline int zorro_module_init(struct zorro_driver *drv)
-{
- int rc = zorro_register_driver(drv);
-
- if (rc > 0)
- return 0;
-
- /* iff CONFIG_HOTPLUG and built into kernel, we should
- * leave the driver around for future hotplug events.
- * For the module case, a hotplug daemon of some sort
- * should load a module in response to an insert event. */
-#if defined(CONFIG_HOTPLUG) && !defined(MODULE)
- if (rc == 0)
- return 0;
-#else
- if (rc == 0)
- rc = -ENODEV;
-#endif
-
- /* if we get here, we need to clean up Zorro driver instance
- * and return some sort of error */
- zorro_unregister_driver(drv);
-
- return rc;
-}
-
-
/*
* Bitmask indicating portions of available Zorro II RAM that are unused
* by the system. Every bit represents a 64K chunk, for a maximum of 8MB
diff --git a/include/media/audiochip.h b/include/media/audiochip.h
index 295d256ee81..1fd4a220757 100644
--- a/include/media/audiochip.h
+++ b/include/media/audiochip.h
@@ -21,18 +21,4 @@ enum audiochip {
AUDIO_CHIP_MSP34XX
};
-/* ---------------------------------------------------------------------- */
-
-/* audio inputs */
-#define AUDIO_TUNER 0x00
-#define AUDIO_RADIO 0x01
-#define AUDIO_EXTERN 0x02
-#define AUDIO_INTERN 0x03
-#define AUDIO_OFF 0x04
-#define AUDIO_ON 0x05
-#define AUDIO_EXTERN_1 AUDIO_EXTERN
-#define AUDIO_EXTERN_2 0x06
-#define AUDIO_MUTE 0x80
-#define AUDIO_UNMUTE 0x81
-
#endif /* AUDIOCHIP_H */
diff --git a/include/media/cs53l32a.h b/include/media/cs53l32a.h
new file mode 100644
index 00000000000..bf76197d379
--- /dev/null
+++ b/include/media/cs53l32a.h
@@ -0,0 +1,34 @@
+/*
+ cs53l32a.h - definition for cs53l32a inputs and outputs
+
+ Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+ 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 _CS53L32A_H_
+#define _CS53L32A_H_
+
+/* There are 2 physical inputs, but the second input can be
+ placed in two modes, the first mode bypasses the PGA (gain),
+ the second goes through the PGA. Hence there are three
+ possible inputs to choose from. */
+
+/* CS53L32A HW inputs */
+#define CS53L32A_IN0 0
+#define CS53L32A_IN1 1
+#define CS53L32A_IN2 2
+
+#endif
diff --git a/include/media/i2c-addr.h b/include/media/i2c-addr.h
new file mode 100644
index 00000000000..e7ff44a35ca
--- /dev/null
+++ b/include/media/i2c-addr.h
@@ -0,0 +1,44 @@
+/*
+ * V4L I2C address list
+ *
+ *
+ * Copyright (C) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ * Based on a previous mapping by
+ * Ralph Metzler (rjkm@thp.uni-koeln.de)
+ * Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ */
+
+/* bttv address list */
+#define I2C_ADDR_TSA5522 0xc2
+#define I2C_ADDR_TDA7432 0x8a
+#define I2C_ADDR_BT832_ALT1 0x88
+#define I2C_ADDR_BT832_ALT2 0x8a // alternate setting
+#define I2C_ADDR_TDA8425 0x82
+#define I2C_ADDR_TDA9840 0x84
+#define I2C_ADDR_TDA9850 0xb6 /* also used by 9855,9873 */
+#define I2C_ADDR_TDA9874 0xb0 /* also used by 9875 */
+#define I2C_ADDR_TDA9875 0xb0
+#define I2C_ADDR_HAUPEE 0xa0
+#define I2C_ADDR_STBEE 0xae
+#define I2C_ADDR_VHX 0xc0
+#define I2C_ADDR_MSP3400 0x80
+#define I2C_ADDR_MSP3400_ALT 0x88
+#define I2C_ADDR_TEA6300 0x80 /* also used by 6320 */
+#define I2C_ADDR_DPL3518 0x84
+#define I2C_ADDR_TDA9887 0x86
+
+/*
+ * i2c bus addresses for the chips supported by tvaudio.c
+ */
+
+#define I2C_ADDR_TDA8425 0x82
+#define I2C_ADDR_TDA9840 0x84 /* also used by TA8874Z */
+#define I2C_ADDR_TDA985x_L 0xb4 /* also used by 9873 */
+#define I2C_ADDR_TDA985x_H 0xb6
+#define I2C_ADDR_TDA9874 0xb0 /* also used by 9875 */
+
+#define I2C_ADDR_TEA6300 0x80 /* also used by 6320 */
+#define I2C_ADDR_TEA6420 0x98
+
+#define I2C_ADDR_PIC16C54 0x96 /* PV951 */
diff --git a/include/media/msp3400.h b/include/media/msp3400.h
new file mode 100644
index 00000000000..0be61a021d4
--- /dev/null
+++ b/include/media/msp3400.h
@@ -0,0 +1,226 @@
+/*
+ msp3400.h - definition for msp3400 inputs and outputs
+
+ Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+ 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 _MSP3400_H_
+#define _MSP3400_H_
+
+/* msp3400 routing
+ ===============
+
+ The msp3400 has a complicated routing scheme with many possible
+ combinations. The details are all in the datasheets but I will try
+ to give a short description here.
+
+ Inputs
+ ======
+
+ There are 1) tuner inputs, 2) I2S inputs, 3) SCART inputs. You will have
+ to select which tuner input to use and which SCART input to use. The
+ selected tuner input, the selected SCART input and all I2S inputs go to
+ the DSP (the tuner input first goes through the demodulator).
+
+ The DSP handles things like volume, bass/treble, balance, and some chips
+ have support for surround sound. It has several outputs: MAIN, AUX, I2S
+ and SCART1/2. Each output can select which DSP input to use. So the MAIN
+ output can select the tuner input while at the same time the SCART1 output
+ uses the I2S input.
+
+ Outputs
+ =======
+
+ Most DSP outputs are also the outputs of the msp3400. However, the SCART
+ outputs of the msp3400 can select which input to use: either the SCART1 or
+ SCART2 output from the DSP, or the msp3400 SCART inputs, thus completely
+ bypassing the DSP.
+
+ Summary
+ =======
+
+ So to specify a complete routing scheme for the msp3400 you will have to
+ specify in the 'input' field of the v4l2_routing struct:
+
+ 1) which tuner input to use
+ 2) which SCART input to use
+ 3) which DSP input to use for each DSP output
+
+ And in the 'output' field of the v4l2_routing struct you specify:
+
+ 1) which SCART input to use for each SCART output
+
+ Depending on how the msp is wired to the other components you can
+ ignore or mute certain inputs or outputs.
+
+ Also, depending on the msp version only a subset of the inputs or
+ outputs may be present. At the end of this header some tables are
+ added containing a list of what is available for each msp version.
+ */
+
+/* Inputs to the DSP unit: two independent selections have to be made:
+ 1) the tuner (SIF) input
+ 2) the SCART input
+ Bits 0-2 are used for the SCART input select, bit 3 is used for the tuner
+ input, bits 4-7 are reserved.
+ */
+
+/* SCART input to DSP selection */
+#define MSP_IN_SCART_1 0 /* Pin SC1_IN */
+#define MSP_IN_SCART_2 1 /* Pin SC2_IN */
+#define MSP_IN_SCART_3 2 /* Pin SC3_IN */
+#define MSP_IN_SCART_4 3 /* Pin SC4_IN */
+#define MSP_IN_MONO 6 /* Pin MONO_IN */
+#define MSP_IN_MUTE 7 /* Mute DSP input */
+#define MSP_SCART_TO_DSP(in) (in)
+/* Tuner input to demodulator and DSP selection */
+#define MSP_IN_TUNER_1 0 /* Analog Sound IF input pin ANA_IN1 */
+#define MSP_IN_TUNER_2 1 /* Analog Sound IF input pin ANA_IN2 */
+#define MSP_TUNER_TO_DSP(in) ((in) << 3)
+
+/* The msp has up to 5 DSP outputs, each output can independently select
+ a DSP input.
+
+ The DSP outputs are: loudspeaker output (aka MAIN), headphones output
+ (aka AUX), SCART1 DA output, SCART2 DA output and an I2S output.
+ There also is a quasi-peak detector output, but that is not used by
+ this driver and is set to the same input as the loudspeaker output.
+ Not all outputs are supported by all msp models. Setting the input
+ of an unsupported output will be ignored by the driver.
+
+ There are up to 16 DSP inputs to choose from, so each output is
+ assigned 4 bits.
+
+ Note: the 44x8G can mix two inputs and feed the result back to the
+ DSP. This is currently not implemented. Also not implemented is the
+ multi-channel capable I2S3 input of the 44x0G. If someone can demonstrate
+ a need for one of those features then additional support can be added. */
+#define MSP_DSP_OUT_TUNER 0 /* Tuner output */
+#define MSP_DSP_OUT_SCART 2 /* SCART output */
+#define MSP_DSP_OUT_I2S1 5 /* I2S1 output */
+#define MSP_DSP_OUT_I2S2 6 /* I2S2 output */
+#define MSP_DSP_OUT_I2S3 7 /* I2S3 output */
+#define MSP_DSP_OUT_MAIN_AVC 11 /* MAIN AVC processed output */
+#define MSP_DSP_OUT_MAIN 12 /* MAIN output */
+#define MSP_DSP_OUT_AUX 13 /* AUX output */
+#define MSP_DSP_TO_MAIN(in) ((in) << 4)
+#define MSP_DSP_TO_AUX(in) ((in) << 8)
+#define MSP_DSP_TO_SCART1(in) ((in) << 12)
+#define MSP_DSP_TO_SCART2(in) ((in) << 16)
+#define MSP_DSP_TO_I2S(in) ((in) << 20)
+
+/* Output SCART select: the SCART outputs can select which input
+ to use. */
+#define MSP_OUT_SCART1 0 /* SCART1 input, bypassing the DSP */
+#define MSP_OUT_SCART2 1 /* SCART2 input, bypassing the DSP */
+#define MSP_OUT_SCART3 2 /* SCART3 input, bypassing the DSP */
+#define MSP_OUT_SCART4 3 /* SCART4 input, bypassing the DSP */
+#define MSP_OUT_SCART1_DA 4 /* DSP SCART1 output */
+#define MSP_OUT_SCART2_DA 5 /* DSP SCART2 output */
+#define MSP_OUT_MONO 6 /* MONO input, bypassing the DSP */
+#define MSP_OUT_MUTE 7 /* MUTE output */
+#define MSP_OUT_TO_SCART1(in) (in)
+#define MSP_OUT_TO_SCART2(in) ((in) << 4)
+
+/* Shortcut macros */
+#define MSP_INPUT(sc, t, main_aux_src, sc_i2s_src) \
+ (MSP_SCART_TO_DSP(sc) | \
+ MSP_TUNER_TO_DSP(t) | \
+ MSP_DSP_TO_MAIN(main_aux_src) | \
+ MSP_DSP_TO_AUX(main_aux_src) | \
+ MSP_DSP_TO_SCART1(sc_i2s_src) | \
+ MSP_DSP_TO_SCART2(sc_i2s_src) | \
+ MSP_DSP_TO_I2S(sc_i2s_src))
+#define MSP_INPUT_DEFAULT MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1, \
+ MSP_DSP_OUT_TUNER, MSP_DSP_OUT_TUNER)
+#define MSP_OUTPUT(sc) \
+ (MSP_OUT_TO_SCART1(sc) | \
+ MSP_OUT_TO_SCART2(sc))
+/* This equals the RESET position of the msp3400 ACB register */
+#define MSP_OUTPUT_DEFAULT (MSP_OUT_TO_SCART1(MSP_OUT_SCART3) | \
+ MSP_OUT_TO_SCART2(MSP_OUT_SCART1_DA))
+
+/* Tuner inputs vs. msp version */
+/* Chip TUNER_1 TUNER_2
+ -------------------------
+ msp34x0b y y
+ msp34x0c y y
+ msp34x0d y y
+ msp34x5d y n
+ msp34x7d y n
+ msp34x0g y y
+ msp34x1g y y
+ msp34x2g y y
+ msp34x5g y n
+ msp34x7g y n
+ msp44x0g y y
+ msp44x8g y y
+ */
+
+/* SCART inputs vs. msp version */
+/* Chip SC1 SC2 SC3 SC4
+ -------------------------
+ msp34x0b y y y n
+ msp34x0c y y y n
+ msp34x0d y y y y
+ msp34x5d y y n n
+ msp34x7d y n n n
+ msp34x0g y y y y
+ msp34x1g y y y y
+ msp34x2g y y y y
+ msp34x5g y y n n
+ msp34x7g y n n n
+ msp44x0g y y y y
+ msp44x8g y y y y
+ */
+
+/* DSP inputs vs. msp version (tuner and SCART inputs are always available) */
+/* Chip I2S1 I2S2 I2S3 MAIN_AVC MAIN AUX
+ ------------------------------------------
+ msp34x0b y n n n n n
+ msp34x0c y y n n n n
+ msp34x0d y y n n n n
+ msp34x5d y y n n n n
+ msp34x7d n n n n n n
+ msp34x0g y y n n n n
+ msp34x1g y y n n n n
+ msp34x2g y y n y y y
+ msp34x5g y y n n n n
+ msp34x7g n n n n n n
+ msp44x0g y y y y y y
+ msp44x8g y y y n n n
+ */
+
+/* DSP outputs vs. msp version */
+/* Chip MAIN AUX SCART1 SCART2 I2S
+ ------------------------------------
+ msp34x0b y y y n y
+ msp34x0c y y y n y
+ msp34x0d y y y y y
+ msp34x5d y n y n y
+ msp34x7d y n y n n
+ msp34x0g y y y y y
+ msp34x1g y y y y y
+ msp34x2g y y y y y
+ msp34x5g y n y n y
+ msp34x7g y n y n n
+ msp44x0g y y y y y
+ msp44x8g y y y y y
+ */
+
+#endif /* MSP3400_H */
+
diff --git a/drivers/media/video/rds.h b/include/media/rds.h
index 0d30eb744e6..951c1ae0be7 100644
--- a/drivers/media/video/rds.h
+++ b/include/media/rds.h
@@ -42,7 +42,3 @@ struct rds_command {
#define RDS_CMD_POLL _IOR('R',4,int)
#endif
-
-
-
-
diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h
index e5e749e984e..4507cb61ae9 100644
--- a/include/media/saa7146_vv.h
+++ b/include/media/saa7146_vv.h
@@ -197,7 +197,8 @@ void saa7146_buffer_finish(struct saa7146_dev *dev, struct saa7146_dmaqueue *q,
void saa7146_buffer_next(struct saa7146_dev *dev, struct saa7146_dmaqueue *q,int vbi);
int saa7146_buffer_queue(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, struct saa7146_buf *buf);
void saa7146_buffer_timeout(unsigned long data);
-void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf);
+void saa7146_dma_free(struct saa7146_dev* dev,struct videobuf_queue *q,
+ struct saa7146_buf *buf);
int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv);
int saa7146_vv_release(struct saa7146_dev* dev);
diff --git a/include/media/tvaudio.h b/include/media/tvaudio.h
new file mode 100644
index 00000000000..6915aafc875
--- /dev/null
+++ b/include/media/tvaudio.h
@@ -0,0 +1,30 @@
+/*
+ tvaudio.h - definition for tvaudio inputs
+
+ Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+ 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 _TVAUDIO_H
+#define _TVAUDIO_H
+
+/* The tvaudio module accepts the following inputs: */
+#define TVAUDIO_INPUT_TUNER 0
+#define TVAUDIO_INPUT_RADIO 1
+#define TVAUDIO_INPUT_EXTERN 2
+#define TVAUDIO_INPUT_INTERN 3
+
+#endif
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 2360453e749..642520acdfa 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -123,17 +123,6 @@ enum v4l2_chip_ident {
/* v4l device was opened in Radio mode, to be replaced by VIDIOC_INT_S_TUNER_MODE */
#define AUDC_SET_RADIO _IO('d',88)
-/* select from TV,radio,extern,MUTE, to be replaced with VIDIOC_INT_S_AUDIO_ROUTING */
-#define AUDC_SET_INPUT _IOW('d',89,int)
-
-/* msp3400 ioctl: will be removed in the near future, to be replaced by
- VIDIOC_INT_S_AUDIO_ROUTING. */
-struct msp_matrix {
- int input;
- int output;
-};
-#define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix)
-
/* tuner ioctls */
/* Sets tuner type and its I2C addr */
@@ -209,10 +198,10 @@ struct v4l2_routing {
};
/* These internal commands should be used to define the inputs and outputs
- of an audio/video chip. They will replace AUDC_SET_INPUT.
- The v4l2 API commands VIDIOC_S/G_INPUT, VIDIOC_S/G_OUTPUT,
- VIDIOC_S/G_AUDIO and VIDIOC_S/G_AUDOUT are meant to be used by the
- user. Internally these commands should be used to switch inputs/outputs
+ of an audio/video chip. They will replace the v4l2 API commands
+ VIDIOC_S/G_INPUT, VIDIOC_S/G_OUTPUT, VIDIOC_S/G_AUDIO and VIDIOC_S/G_AUDOUT
+ that are meant to be used by the user.
+ The internal commands should be used to switch inputs/outputs
because only the driver knows how to map a 'Television' input to the precise
input/output routing of an A/D converter, or a DSP, or a video digitizer.
These four commands should only be sent directly to an i2c device, they
diff --git a/include/media/video-buf.h b/include/media/video-buf.h
index d90dec5484e..fff3fd0fbf9 100644
--- a/include/media/video-buf.h
+++ b/include/media/video-buf.h
@@ -1,15 +1,20 @@
/*
*
* generic helper functions for video4linux capture buffers, to handle
- * memory management and PCI DMA. Right now bttv + saa7134 use it.
+ * memory management and PCI DMA.
+ * Right now, bttv, saa7134, saa7146 and cx88 use it.
*
* The functions expect the hardware being able to scatter gatter
* (i.e. the buffers are not linear in physical memory, but fragmented
* into PAGE_SIZE chunks). They also assume the driver does not need
- * to touch the video data (thus it is probably not useful for USB as
- * data often must be uncompressed by the drivers).
+ * to touch the video data.
+ *
+ * device specific map/unmap/sync stuff now are mapped as file operations
+ * to allow its usage by USB and virtual devices.
*
* (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
+ * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org>
+ * (c) 2006 Ted Walther and John Sokol
*
* 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
@@ -38,6 +43,9 @@ struct scatterlist* videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages);
struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages,
int offset);
+struct videobuf_buffer;
+struct videobuf_queue;
+
/* --------------------------------------------------------------------- */
/*
@@ -49,7 +57,7 @@ struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages,
* pointer + length. The kernel version just wants the size and
* does memory allocation too using vmalloc_32().
*
- * videobuf_dma_pci_*()
+ * videobuf_dma_*()
* see Documentation/DMA-mapping.txt, these functions to
* basically the same. The map function does also build a
* scatterlist for the buffer (and unmap frees it ...)
@@ -86,12 +94,18 @@ int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
int nr_pages);
int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
dma_addr_t addr, int nr_pages);
-int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma);
-int videobuf_dma_pci_sync(struct pci_dev *dev,
- struct videobuf_dmabuf *dma);
-int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma);
int videobuf_dma_free(struct videobuf_dmabuf *dma);
+int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
+int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
+int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
+
+ /*FIXME: these variants are used only on *-alsa code, where videobuf is
+ * used without queue
+ */
+int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma);
+int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma);
+
/* --------------------------------------------------------------------- */
/*
@@ -115,9 +129,6 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma);
*
*/
-struct videobuf_buffer;
-struct videobuf_queue;
-
struct videobuf_mapping {
unsigned int count;
unsigned long start;
@@ -164,6 +175,10 @@ struct videobuf_buffer {
struct timeval ts;
};
+typedef int (vb_map_sg_t)(void *dev,struct scatterlist *sglist,int nr_pages,
+ int direction);
+
+
struct videobuf_queue_ops {
int (*buf_setup)(struct videobuf_queue *q,
unsigned int *count, unsigned int *size);
@@ -174,12 +189,20 @@ struct videobuf_queue_ops {
struct videobuf_buffer *vb);
void (*buf_release)(struct videobuf_queue *q,
struct videobuf_buffer *vb);
+
+ /* Helper operations - device dependent.
+ * If null, videobuf_init defaults all to PCI handling
+ */
+
+ vb_map_sg_t *vb_map_sg;
+ vb_map_sg_t *vb_dma_sync_sg;
+ vb_map_sg_t *vb_unmap_sg;
};
struct videobuf_queue {
struct mutex lock;
spinlock_t *irqlock;
- struct pci_dev *pci;
+ void *dev; /* on pci, points to struct pci_dev */
enum v4l2_buf_type type;
unsigned int inputs; /* for V4L2_BUF_FLAG_INPUT */
@@ -204,12 +227,15 @@ struct videobuf_queue {
void* videobuf_alloc(unsigned int size);
int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr);
-int videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb,
- struct v4l2_framebuffer *fbuf);
+int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
+ struct v4l2_framebuffer *fbuf);
+
+/* Maps fops to PCI stuff */
+void videobuf_queue_pci(struct videobuf_queue* q);
void videobuf_queue_init(struct videobuf_queue *q,
struct videobuf_queue_ops *ops,
- struct pci_dev *pci,
+ void *dev,
spinlock_t *irqlock,
enum v4l2_buf_type type,
enum v4l2_field field,
diff --git a/include/media/wm8775.h b/include/media/wm8775.h
new file mode 100644
index 00000000000..60739c5a23a
--- /dev/null
+++ b/include/media/wm8775.h
@@ -0,0 +1,35 @@
+/*
+ wm8775.h - definition for wm8775 inputs and outputs
+
+ Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+ 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 _WM8775_H_
+#define _WM8775_H_
+
+/* The WM8775 has 4 inputs and one output. Zero or more inputs
+ are multiplexed together to the output. Hence there are
+ 16 combinations.
+ If only one input is active (the normal case) then the
+ input values 1, 2, 4 or 8 should be used. */
+
+#define WM8775_AIN1 1
+#define WM8775_AIN2 2
+#define WM8775_AIN3 4
+#define WM8775_AIN4 8
+
+#endif
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index b6f0905a4ee..916013ca4a5 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -300,29 +300,30 @@ DECLARE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
#define CONNTRACK_ECACHE(x) (__get_cpu_var(nf_conntrack_ecache).x)
-extern struct notifier_block *nf_conntrack_chain;
-extern struct notifier_block *nf_conntrack_expect_chain;
+extern struct atomic_notifier_head nf_conntrack_chain;
+extern struct atomic_notifier_head nf_conntrack_expect_chain;
static inline int nf_conntrack_register_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&nf_conntrack_chain, nb);
+ return atomic_notifier_chain_register(&nf_conntrack_chain, nb);
}
static inline int nf_conntrack_unregister_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&nf_conntrack_chain, nb);
+ return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb);
}
static inline int
nf_conntrack_expect_register_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&nf_conntrack_expect_chain, nb);
+ return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb);
}
static inline int
nf_conntrack_expect_unregister_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&nf_conntrack_expect_chain, nb);
+ return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain,
+ nb);
}
extern void nf_ct_deliver_cached_events(const struct nf_conn *ct);
@@ -347,14 +348,14 @@ static inline void nf_conntrack_event(enum ip_conntrack_events event,
struct nf_conn *ct)
{
if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
- notifier_call_chain(&nf_conntrack_chain, event, ct);
+ atomic_notifier_call_chain(&nf_conntrack_chain, event, ct);
}
static inline void
nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
struct nf_conntrack_expect *exp)
{
- notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
+ atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
}
#else /* CONFIG_NF_CONNTRACK_EVENTS */
static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index 11641c9384f..c5d7f920c35 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -145,7 +145,7 @@ static inline struct request_sock *
{
struct request_sock *req = queue->rskq_accept_head;
- queue->rskq_accept_head = queue->rskq_accept_head = NULL;
+ queue->rskq_accept_head = NULL;
return req;
}
diff --git a/include/net/route.h b/include/net/route.h
index 9c04f15090d..98c915abdec 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -110,7 +110,7 @@ extern struct ip_rt_acct *ip_rt_acct;
struct in_device;
extern int ip_rt_init(void);
extern void ip_rt_redirect(u32 old_gw, u32 dst, u32 new_gw,
- u32 src, u8 tos, struct net_device *dev);
+ u32 src, struct net_device *dev);
extern void ip_rt_advice(struct rtable **rp, int advice);
extern void rt_cache_flush(int how);
extern int __ip_route_output_key(struct rtable **, const struct flowi *flp);
diff --git a/include/net/sock.h b/include/net/sock.h
index ec226f31dc2..af2b0544586 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -210,6 +210,7 @@ struct sock {
gfp_t sk_allocation;
int sk_sndbuf;
int sk_route_caps;
+ int sk_rcvlowat;
unsigned long sk_flags;
unsigned long sk_lingertime;
/*
@@ -230,7 +231,6 @@ struct sock {
unsigned short sk_max_ack_backlog;
__u32 sk_priority;
struct ucred sk_peercred;
- int sk_rcvlowat;
long sk_rcvtimeo;
long sk_sndtimeo;
struct sk_filter *sk_filter;
@@ -938,28 +938,7 @@ static inline void sock_put(struct sock *sk)
sk_free(sk);
}
-static inline int sk_receive_skb(struct sock *sk, struct sk_buff *skb)
-{
- int rc = NET_RX_SUCCESS;
-
- if (sk_filter(sk, skb, 0))
- goto discard_and_relse;
-
- skb->dev = NULL;
-
- bh_lock_sock(sk);
- if (!sock_owned_by_user(sk))
- rc = sk->sk_backlog_rcv(sk, skb);
- else
- sk_add_backlog(sk, skb);
- bh_unlock_sock(sk);
-out:
- sock_put(sk);
- return rc;
-discard_and_relse:
- kfree_skb(skb);
- goto out;
-}
+extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb);
/* Detach socket from process context.
* Announce socket dead, detach it from wait queue and inode.
@@ -1044,33 +1023,9 @@ sk_dst_reset(struct sock *sk)
write_unlock(&sk->sk_dst_lock);
}
-static inline struct dst_entry *
-__sk_dst_check(struct sock *sk, u32 cookie)
-{
- struct dst_entry *dst = sk->sk_dst_cache;
+extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie);
- if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
- sk->sk_dst_cache = NULL;
- dst_release(dst);
- return NULL;
- }
-
- return dst;
-}
-
-static inline struct dst_entry *
-sk_dst_check(struct sock *sk, u32 cookie)
-{
- struct dst_entry *dst = sk_dst_get(sk);
-
- if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
- sk_dst_reset(sk);
- dst_release(dst);
- return NULL;
- }
-
- return dst;
-}
+extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie);
static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
{
@@ -1140,45 +1095,7 @@ extern void sk_reset_timer(struct sock *sk, struct timer_list* timer,
extern void sk_stop_timer(struct sock *sk, struct timer_list* timer);
-static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
-{
- int err = 0;
- int skb_len;
-
- /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
- number of warnings when compiling with -W --ANK
- */
- if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
- (unsigned)sk->sk_rcvbuf) {
- err = -ENOMEM;
- goto out;
- }
-
- /* It would be deadlock, if sock_queue_rcv_skb is used
- with socket lock! We assume that users of this
- function are lock free.
- */
- err = sk_filter(sk, skb, 1);
- if (err)
- goto out;
-
- skb->dev = NULL;
- skb_set_owner_r(skb, sk);
-
- /* Cache the SKB length before we tack it onto the receive
- * queue. Once it is added it no longer belongs to us and
- * may be freed by other threads of control pulling packets
- * from the queue.
- */
- skb_len = skb->len;
-
- skb_queue_tail(&sk->sk_receive_queue, skb);
-
- if (!sock_flag(sk, SOCK_DEAD))
- sk->sk_data_ready(sk, skb_len);
-out:
- return err;
-}
+extern int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
static inline int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
{
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 61b7504fc2b..e100291e43f 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -864,13 +864,19 @@ struct xfrm_algo_desc {
/* XFRM tunnel handlers. */
struct xfrm_tunnel {
int (*handler)(struct sk_buff *skb);
- void (*err_handler)(struct sk_buff *skb, __u32 info);
+ int (*err_handler)(struct sk_buff *skb, __u32 info);
+
+ struct xfrm_tunnel *next;
+ int priority;
};
struct xfrm6_tunnel {
- int (*handler)(struct sk_buff **pskb);
- void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info);
+ int (*handler)(struct sk_buff *skb);
+ int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int type, int code, int offset, __u32 info);
+
+ struct xfrm6_tunnel *next;
+ int priority;
};
extern void xfrm_init(void);
@@ -906,7 +912,7 @@ extern int xfrm4_rcv(struct sk_buff *skb);
extern int xfrm4_output(struct sk_buff *skb);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
-extern int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi);
+extern int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi);
extern int xfrm6_rcv(struct sk_buff **pskb);
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
diff --git a/include/sound/core.h b/include/sound/core.h
index 144bdc2f217..7f32c12b4a0 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -186,7 +186,7 @@ struct snd_minor {
int type; /* SNDRV_DEVICE_TYPE_XXX */
int card; /* card number */
int device; /* device number */
- struct file_operations *f_ops; /* file operations */
+ const struct file_operations *f_ops; /* file operations */
void *private_data; /* private data for f_ops->open */
char name[0]; /* device name (keep at the end of
structure) */
@@ -200,14 +200,14 @@ extern int snd_ecards_limit;
void snd_request_card(int card);
int snd_register_device(int type, struct snd_card *card, int dev,
- struct file_operations *f_ops, void *private_data,
+ const struct file_operations *f_ops, void *private_data,
const char *name);
int snd_unregister_device(int type, struct snd_card *card, int dev);
void *snd_lookup_minor_data(unsigned int minor, int type);
#ifdef CONFIG_SND_OSSEMUL
int snd_register_oss_device(int type, struct snd_card *card, int dev,
- struct file_operations *f_ops, void *private_data,
+ const struct file_operations *f_ops, void *private_data,
const char *name);
int snd_unregister_oss_device(int type, struct snd_card *card, int dev);
void *snd_lookup_oss_minor_data(unsigned int minor, int type);
diff --git a/include/video/pm3fb.h b/include/video/pm3fb.h
index 6f4ea808cf7..ac021379ac4 100644
--- a/include/video/pm3fb.h
+++ b/include/video/pm3fb.h
@@ -1128,10 +1128,7 @@
#endif
/* max number of simultaneous board */
-/* warning : make sure module array def's are coherent with PM3_MAX_BOARD */
#define PM3_MAX_BOARD 4
-#define PM3_MAX_BOARD_MODULE_ARRAY_SHORT "1-4h"
-#define PM3_MAX_BOARD_MODULE_ARRAY_STRING "1-4s"
/* max size of options */
#define PM3_OPTIONS_SIZE 256
diff --git a/init/Kconfig b/init/Kconfig
index 1d19fd25204..3b36a1d5365 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -365,43 +365,6 @@ config SHMEM
option replaces shmem and tmpfs with the much simpler ramfs code,
which may be appropriate on small systems without swap.
-config CC_ALIGN_FUNCTIONS
- int "Function alignment" if EMBEDDED
- default 0
- help
- Align the start of functions to the next power-of-two greater than n,
- skipping up to n bytes. For instance, 32 aligns functions
- to the next 32-byte boundary, but 24 would align to the next
- 32-byte boundary only if this can be done by skipping 23 bytes or less.
- Zero means use compiler's default.
-
-config CC_ALIGN_LABELS
- int "Label alignment" if EMBEDDED
- default 0
- help
- Align all branch targets to a power-of-two boundary, skipping
- up to n bytes like ALIGN_FUNCTIONS. This option can easily
- make code slower, because it must insert dummy operations for
- when the branch target is reached in the usual flow of the code.
- Zero means use compiler's default.
-
-config CC_ALIGN_LOOPS
- int "Loop alignment" if EMBEDDED
- default 0
- help
- Align loops to a power-of-two boundary, skipping up to n bytes.
- Zero means use compiler's default.
-
-config CC_ALIGN_JUMPS
- int "Jump alignment" if EMBEDDED
- default 0
- help
- Align branch targets to a power-of-two boundary, for branch
- targets where the targets can only be reached by jumping,
- skipping up to n bytes like ALIGN_FUNCTIONS. In this case,
- no dummy operations need be executed.
- Zero means use compiler's default.
-
config SLAB
default y
bool "Use full SLAB allocator" if EMBEDDED
@@ -470,15 +433,6 @@ config MODULE_FORCE_UNLOAD
rmmod). This is mainly for kernel developers and desperate users.
If unsure, say N.
-config OBSOLETE_MODPARM
- bool
- default y
- depends on MODULES
- help
- You need this option to use module parameters on modules which
- have not been converted to the new module parameter system yet.
- If unsure, say Y.
-
config MODVERSIONS
bool "Module versioning support"
depends on MODULES
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 8b671fe68af..adb7cad3e6e 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -23,7 +23,6 @@ int root_mountflags = MS_RDONLY | MS_SILENT;
char * __initdata root_device_name;
static char __initdata saved_root_name[64];
-/* this is initialized in init/main.c */
dev_t ROOT_DEV;
static int __init load_ramdisk(char *str)
diff --git a/init/initramfs.c b/init/initramfs.c
index 637344b0598..679d870d991 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -506,6 +506,7 @@ void __init populate_rootfs(void)
panic(err);
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start) {
+#ifdef CONFIG_BLK_DEV_RAM
int fd;
printk(KERN_INFO "checking if image is initramfs...");
err = unpack_to_rootfs((char *)initrd_start,
@@ -518,13 +519,22 @@ void __init populate_rootfs(void)
return;
}
printk("it isn't (%s); looks like an initrd\n", err);
- fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 700);
+ fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700);
if (fd >= 0) {
sys_write(fd, (char *)initrd_start,
initrd_end - initrd_start);
sys_close(fd);
free_initrd();
}
+#else
+ printk(KERN_INFO "Unpacking initramfs...");
+ err = unpack_to_rootfs((char *)initrd_start,
+ initrd_end - initrd_start, 0);
+ if (err)
+ panic(err);
+ printk(" done\n");
+ free_initrd();
+#endif
}
#endif
}
diff --git a/init/main.c b/init/main.c
index 2714e0e7cfe..4a2f0898dda 100644
--- a/init/main.c
+++ b/init/main.c
@@ -306,8 +306,6 @@ static int __init rdinit_setup(char *str)
}
__setup("rdinit=", rdinit_setup);
-extern void setup_arch(char **);
-
#ifndef CONFIG_SMP
#ifdef CONFIG_X86_LOCAL_APIC
@@ -343,7 +341,7 @@ static void __init setup_per_cpu_areas(void)
#endif
ptr = alloc_bootmem(size * nr_possible_cpus);
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
__per_cpu_offset[i] = ptr - __per_cpu_start;
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
ptr += size;
@@ -571,17 +569,23 @@ static void __init do_initcalls(void)
int count = preempt_count();
for (call = __initcall_start; call < __initcall_end; call++) {
- char *msg;
+ char *msg = NULL;
+ char msgbuf[40];
+ int result;
if (initcall_debug) {
- printk(KERN_DEBUG "Calling initcall 0x%p", *call);
- print_fn_descriptor_symbol(": %s()", (unsigned long) *call);
+ printk("Calling initcall 0x%p", *call);
+ print_fn_descriptor_symbol(": %s()",
+ (unsigned long) *call);
printk("\n");
}
- (*call)();
+ result = (*call)();
- msg = NULL;
+ if (result && (result != -ENODEV || initcall_debug)) {
+ sprintf(msgbuf, "error code %d", result);
+ msg = msgbuf;
+ }
if (preempt_count() != count) {
msg = "preemption imbalance";
preempt_count() = count;
@@ -591,8 +595,10 @@ static void __init do_initcalls(void)
local_irq_enable();
}
if (msg) {
- printk(KERN_WARNING "error in initcall at 0x%p: "
- "returned with %s\n", *call, msg);
+ printk(KERN_WARNING "initcall at 0x%p", *call);
+ print_fn_descriptor_symbol(": %s()",
+ (unsigned long) *call);
+ printk(": returned with %s\n", msg);
}
}
@@ -639,24 +645,6 @@ static void run_init_process(char *init_filename)
execve(init_filename, argv_init, envp_init);
}
-static inline void fixup_cpu_present_map(void)
-{
-#ifdef CONFIG_SMP
- int i;
-
- /*
- * If arch is not hotplug ready and did not populate
- * cpu_present_map, just make cpu_present_map same as cpu_possible_map
- * for other cpu bringup code to function as normal. e.g smp_init() etc.
- */
- if (cpus_empty(cpu_present_map)) {
- for_each_cpu(i) {
- cpu_set(i, cpu_present_map);
- }
- }
-#endif
-}
-
static int init(void * unused)
{
lock_kernel();
@@ -678,7 +666,6 @@ static int init(void * unused)
do_pre_smp_initcalls();
- fixup_cpu_present_map();
smp_init();
sched_init_smp();
diff --git a/ipc/compat.c b/ipc/compat.c
index 1fe95f6659d..a544dfbb082 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -30,7 +30,7 @@
#include <linux/slab.h>
#include <linux/syscalls.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include "util.h"
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 85c52fd26bf..41ecbd440fe 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -25,6 +25,8 @@
#include <linux/netlink.h>
#include <linux/syscalls.h>
#include <linux/signal.h>
+#include <linux/mutex.h>
+
#include <net/sock.h>
#include "util.h"
@@ -760,7 +762,7 @@ out_unlock:
* The receiver accepts the message and returns without grabbing the queue
* spinlock. Therefore an intermediate STATE_PENDING state and memory barriers
* are necessary. The same algorithm is used for sysv semaphores, see
- * ipc/sem.c fore more details.
+ * ipc/sem.c for more details.
*
* The same algorithm is used for senders.
*/
diff --git a/ipc/msg.c b/ipc/msg.c
index fbf757064a3..48a7f17a723 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -28,6 +28,8 @@
#include <linux/syscalls.h>
#include <linux/audit.h>
#include <linux/seq_file.h>
+#include <linux/mutex.h>
+
#include <asm/current.h>
#include <asm/uaccess.h>
#include "util.h"
@@ -179,8 +181,8 @@ static void expunge_all(struct msg_queue* msq, int res)
* removes the message queue from message queue ID
* array, and cleans up all the messages associated with this queue.
*
- * msg_ids.sem and the spinlock for this message queue is hold
- * before freeque() is called. msg_ids.sem remains locked on exit.
+ * msg_ids.mutex and the spinlock for this message queue is hold
+ * before freeque() is called. msg_ids.mutex remains locked on exit.
*/
static void freeque (struct msg_queue *msq, int id)
{
@@ -208,7 +210,7 @@ asmlinkage long sys_msgget (key_t key, int msgflg)
int id, ret = -EPERM;
struct msg_queue *msq;
- down(&msg_ids.sem);
+ mutex_lock(&msg_ids.mutex);
if (key == IPC_PRIVATE)
ret = newque(key, msgflg);
else if ((id = ipc_findkey(&msg_ids, key)) == -1) { /* key not used */
@@ -220,8 +222,7 @@ asmlinkage long sys_msgget (key_t key, int msgflg)
ret = -EEXIST;
} else {
msq = msg_lock(id);
- if(msq==NULL)
- BUG();
+ BUG_ON(msq==NULL);
if (ipcperms(&msq->q_perm, msgflg))
ret = -EACCES;
else {
@@ -232,7 +233,7 @@ asmlinkage long sys_msgget (key_t key, int msgflg)
}
msg_unlock(msq);
}
- up(&msg_ids.sem);
+ mutex_unlock(&msg_ids.mutex);
return ret;
}
@@ -362,7 +363,7 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
msginfo.msgmnb = msg_ctlmnb;
msginfo.msgssz = MSGSSZ;
msginfo.msgseg = MSGSEG;
- down(&msg_ids.sem);
+ mutex_lock(&msg_ids.mutex);
if (cmd == MSG_INFO) {
msginfo.msgpool = msg_ids.in_use;
msginfo.msgmap = atomic_read(&msg_hdrs);
@@ -373,7 +374,7 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
msginfo.msgtql = MSGTQL;
}
max_id = msg_ids.max_id;
- up(&msg_ids.sem);
+ mutex_unlock(&msg_ids.mutex);
if (copy_to_user (buf, &msginfo, sizeof(struct msginfo)))
return -EFAULT;
return (max_id < 0) ? 0: max_id;
@@ -429,8 +430,6 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
return -EFAULT;
if (copy_msqid_from_user (&setbuf, buf, version))
return -EFAULT;
- if ((err = audit_ipc_perms(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode)))
- return err;
break;
case IPC_RMID:
break;
@@ -438,7 +437,7 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
return -EINVAL;
}
- down(&msg_ids.sem);
+ mutex_lock(&msg_ids.mutex);
msq = msg_lock(msqid);
err=-EINVAL;
if (msq == NULL)
@@ -461,6 +460,9 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
switch (cmd) {
case IPC_SET:
{
+ if ((err = audit_ipc_perms(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode, ipcp)))
+ goto out_unlock_up;
+
err = -EPERM;
if (setbuf.qbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
goto out_unlock_up;
@@ -489,7 +491,7 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
}
err = 0;
out_up:
- up(&msg_ids.sem);
+ mutex_unlock(&msg_ids.mutex);
return err;
out_unlock_up:
msg_unlock(msq);
diff --git a/ipc/sem.c b/ipc/sem.c
index 31fd4027d2b..642659cd596 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -75,6 +75,8 @@
#include <linux/audit.h>
#include <linux/capability.h>
#include <linux/seq_file.h>
+#include <linux/mutex.h>
+
#include <asm/uaccess.h>
#include "util.h"
@@ -139,7 +141,7 @@ void __init sem_init (void)
* * if it's IN_WAKEUP, then it must wait until the value changes
* * if it's not -EINTR, then the operation was completed by
* update_queue. semtimedop can return queue.status without
- * performing any operation on the semaphore array.
+ * performing any operation on the sem array.
* * otherwise it must acquire the spinlock and check what's up.
*
* The two-stage algorithm is necessary to protect against the following
@@ -214,7 +216,7 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
if (nsems < 0 || nsems > sc_semmsl)
return -EINVAL;
- down(&sem_ids.sem);
+ mutex_lock(&sem_ids.mutex);
if (key == IPC_PRIVATE) {
err = newary(key, nsems, semflg);
@@ -227,8 +229,7 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
err = -EEXIST;
} else {
sma = sem_lock(id);
- if(sma==NULL)
- BUG();
+ BUG_ON(sma==NULL);
if (nsems > sma->sem_nsems)
err = -EINVAL;
else if (ipcperms(&sma->sem_perm, semflg))
@@ -242,7 +243,7 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
sem_unlock(sma);
}
- up(&sem_ids.sem);
+ mutex_unlock(&sem_ids.mutex);
return err;
}
@@ -437,8 +438,8 @@ static int count_semzcnt (struct sem_array * sma, ushort semnum)
return semzcnt;
}
-/* Free a semaphore set. freeary() is called with sem_ids.sem down and
- * the spinlock for this semaphore set hold. sem_ids.sem remains locked
+/* Free a semaphore set. freeary() is called with sem_ids.mutex locked and
+ * the spinlock for this semaphore set hold. sem_ids.mutex remains locked
* on exit.
*/
static void freeary (struct sem_array *sma, int id)
@@ -525,7 +526,7 @@ static int semctl_nolock(int semid, int semnum, int cmd, int version, union semu
seminfo.semmnu = SEMMNU;
seminfo.semmap = SEMMAP;
seminfo.semume = SEMUME;
- down(&sem_ids.sem);
+ mutex_lock(&sem_ids.mutex);
if (cmd == SEM_INFO) {
seminfo.semusz = sem_ids.in_use;
seminfo.semaem = used_sems;
@@ -534,7 +535,7 @@ static int semctl_nolock(int semid, int semnum, int cmd, int version, union semu
seminfo.semaem = SEMAEM;
}
max_id = sem_ids.max_id;
- up(&sem_ids.sem);
+ mutex_unlock(&sem_ids.mutex);
if (copy_to_user (arg.__buf, &seminfo, sizeof(struct seminfo)))
return -EFAULT;
return (max_id < 0) ? 0: max_id;
@@ -809,8 +810,6 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
if(cmd == IPC_SET) {
if(copy_semid_from_user (&setbuf, arg.buf, version))
return -EFAULT;
- if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode)))
- return err;
}
sma = sem_lock(semid);
if(sma==NULL)
@@ -821,7 +820,6 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
goto out_unlock;
}
ipcp = &sma->sem_perm;
-
if (current->euid != ipcp->cuid &&
current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
err=-EPERM;
@@ -838,6 +836,8 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
err = 0;
break;
case IPC_SET:
+ if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode, ipcp)))
+ goto out_unlock;
ipcp->uid = setbuf.uid;
ipcp->gid = setbuf.gid;
ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
@@ -886,9 +886,9 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
return err;
case IPC_RMID:
case IPC_SET:
- down(&sem_ids.sem);
+ mutex_lock(&sem_ids.mutex);
err = semctl_down(semid,semnum,cmd,version,arg);
- up(&sem_ids.sem);
+ mutex_unlock(&sem_ids.mutex);
return err;
default:
return -EINVAL;
@@ -1182,8 +1182,7 @@ retry_undos:
sma = sem_lock(semid);
if(sma==NULL) {
- if(queue.prev != NULL)
- BUG();
+ BUG_ON(queue.prev != NULL);
error = -EIDRM;
goto out_free;
}
@@ -1300,9 +1299,9 @@ found:
/* perform adjustments registered in u */
nsems = sma->sem_nsems;
for (i = 0; i < nsems; i++) {
- struct sem * sem = &sma->sem_base[i];
+ struct sem * semaphore = &sma->sem_base[i];
if (u->semadj[i]) {
- sem->semval += u->semadj[i];
+ semaphore->semval += u->semadj[i];
/*
* Range checks of the new semaphore value,
* not defined by sus:
@@ -1316,11 +1315,11 @@ found:
*
* Manfred <manfred@colorfullife.com>
*/
- if (sem->semval < 0)
- sem->semval = 0;
- if (sem->semval > SEMVMX)
- sem->semval = SEMVMX;
- sem->sempid = current->tgid;
+ if (semaphore->semval < 0)
+ semaphore->semval = 0;
+ if (semaphore->semval > SEMVMX)
+ semaphore->semval = SEMVMX;
+ semaphore->sempid = current->tgid;
}
}
sma->sem_otime = get_seconds();
diff --git a/ipc/shm.c b/ipc/shm.c
index 16fe2786087..f806a2e314e 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -30,6 +30,7 @@
#include <linux/capability.h>
#include <linux/ptrace.h>
#include <linux/seq_file.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
@@ -109,7 +110,7 @@ static void shm_open (struct vm_area_struct *shmd)
*
* @shp: struct to free
*
- * It has to be called with shp and shm_ids.sem locked,
+ * It has to be called with shp and shm_ids.mutex locked,
* but returns with shp unlocked and freed.
*/
static void shm_destroy (struct shmid_kernel *shp)
@@ -139,7 +140,7 @@ static void shm_close (struct vm_area_struct *shmd)
int id = file->f_dentry->d_inode->i_ino;
struct shmid_kernel *shp;
- down (&shm_ids.sem);
+ mutex_lock(&shm_ids.mutex);
/* remove from the list of attaches of the shm segment */
if(!(shp = shm_lock(id)))
BUG();
@@ -151,7 +152,7 @@ static void shm_close (struct vm_area_struct *shmd)
shm_destroy (shp);
else
shm_unlock(shp);
- up (&shm_ids.sem);
+ mutex_unlock(&shm_ids.mutex);
}
static int shm_mmap(struct file * file, struct vm_area_struct * vma)
@@ -270,7 +271,7 @@ asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
struct shmid_kernel *shp;
int err, id = 0;
- down(&shm_ids.sem);
+ mutex_lock(&shm_ids.mutex);
if (key == IPC_PRIVATE) {
err = newseg(key, shmflg, size);
} else if ((id = ipc_findkey(&shm_ids, key)) == -1) {
@@ -296,7 +297,7 @@ asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
}
shm_unlock(shp);
}
- up(&shm_ids.sem);
+ mutex_unlock(&shm_ids.mutex);
return err;
}
@@ -467,14 +468,14 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
return err;
memset(&shm_info,0,sizeof(shm_info));
- down(&shm_ids.sem);
+ mutex_lock(&shm_ids.mutex);
shm_info.used_ids = shm_ids.in_use;
shm_get_stat (&shm_info.shm_rss, &shm_info.shm_swp);
shm_info.shm_tot = shm_tot;
shm_info.swap_attempts = 0;
shm_info.swap_successes = 0;
err = shm_ids.max_id;
- up(&shm_ids.sem);
+ mutex_unlock(&shm_ids.mutex);
if(copy_to_user (buf, &shm_info, sizeof(shm_info))) {
err = -EFAULT;
goto out;
@@ -583,7 +584,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
* Instead we set a destroyed flag, and then blow
* the name away when the usage hits zero.
*/
- down(&shm_ids.sem);
+ mutex_lock(&shm_ids.mutex);
shp = shm_lock(shmid);
err = -EINVAL;
if (shp == NULL)
@@ -610,7 +611,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
shm_unlock(shp);
} else
shm_destroy (shp);
- up(&shm_ids.sem);
+ mutex_unlock(&shm_ids.mutex);
goto out;
}
@@ -620,13 +621,14 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
err = -EFAULT;
goto out;
}
- if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode)))
- return err;
- down(&shm_ids.sem);
+ mutex_lock(&shm_ids.mutex);
shp = shm_lock(shmid);
err=-EINVAL;
if(shp==NULL)
goto out_up;
+ if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid,
+ setbuf.mode, &(shp->shm_perm))))
+ goto out_unlock_up;
err = shm_checkid(shp,shmid);
if(err)
goto out_unlock_up;
@@ -658,7 +660,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
out_unlock_up:
shm_unlock(shp);
out_up:
- up(&shm_ids.sem);
+ mutex_unlock(&shm_ids.mutex);
goto out;
out_unlock:
shm_unlock(shp);
@@ -771,7 +773,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
invalid:
up_write(&current->mm->mmap_sem);
- down (&shm_ids.sem);
+ mutex_lock(&shm_ids.mutex);
if(!(shp = shm_lock(shmid)))
BUG();
shp->shm_nattch--;
@@ -780,7 +782,7 @@ invalid:
shm_destroy (shp);
else
shm_unlock(shp);
- up (&shm_ids.sem);
+ mutex_unlock(&shm_ids.mutex);
*raddr = (unsigned long) user_addr;
err = 0;
diff --git a/ipc/util.c b/ipc/util.c
index 862621980b0..23151ef3259 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -68,7 +68,8 @@ __initcall(ipc_init);
void __init ipc_init_ids(struct ipc_ids* ids, int size)
{
int i;
- sema_init(&ids->sem,1);
+
+ mutex_init(&ids->mutex);
if(size > IPCMNI)
size = IPCMNI;
@@ -138,7 +139,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
* @ids: Identifier set
* @key: The key to find
*
- * Requires ipc_ids.sem locked.
+ * Requires ipc_ids.mutex locked.
* Returns the identifier if found or -1 if not.
*/
@@ -150,7 +151,7 @@ int ipc_findkey(struct ipc_ids* ids, key_t key)
/*
* rcu_dereference() is not needed here
- * since ipc_ids.sem is held
+ * since ipc_ids.mutex is held
*/
for (id = 0; id <= max_id; id++) {
p = ids->entries->p[id];
@@ -163,7 +164,7 @@ int ipc_findkey(struct ipc_ids* ids, key_t key)
}
/*
- * Requires ipc_ids.sem locked
+ * Requires ipc_ids.mutex locked
*/
static int grow_ary(struct ipc_ids* ids, int newsize)
{
@@ -210,7 +211,7 @@ static int grow_ary(struct ipc_ids* ids, int newsize)
* is returned. The list is returned in a locked state on success.
* On failure the list is not locked and -1 is returned.
*
- * Called with ipc_ids.sem held.
+ * Called with ipc_ids.mutex held.
*/
int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
@@ -221,7 +222,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
/*
* rcu_dereference()() is not needed here since
- * ipc_ids.sem is held
+ * ipc_ids.mutex is held
*/
for (id = 0; id < size; id++) {
if(ids->entries->p[id] == NULL)
@@ -257,7 +258,7 @@ found:
* fed an invalid identifier. The entry is removed and internal
* variables recomputed. The object associated with the identifier
* is returned.
- * ipc_ids.sem and the spinlock for this ID is hold before this function
+ * ipc_ids.mutex and the spinlock for this ID is hold before this function
* is called, and remain locked on the exit.
*/
@@ -270,7 +271,7 @@ struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id)
/*
* do not need a rcu_dereference()() here to force ordering
- * on Alpha, since the ipc_ids.sem is held.
+ * on Alpha, since the ipc_ids.mutex is held.
*/
p = ids->entries->p[lid];
ids->entries->p[lid] = NULL;
@@ -530,13 +531,13 @@ void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out)
/*
* So far only shm_get_stat() calls ipc_get() via shm_get(), so ipc_get()
- * is called with shm_ids.sem locked. Since grow_ary() is also called with
- * shm_ids.sem down(for Shared Memory), there is no need to add read
+ * is called with shm_ids.mutex locked. Since grow_ary() is also called with
+ * shm_ids.mutex down(for Shared Memory), there is no need to add read
* barriers here to gurantee the writes in grow_ary() are seen in order
* here (for Alpha).
*
- * However ipc_get() itself does not necessary require ipc_ids.sem down. So
- * if in the future ipc_get() is used by other places without ipc_ids.sem
+ * However ipc_get() itself does not necessary require ipc_ids.mutex down. So
+ * if in the future ipc_get() is used by other places without ipc_ids.mutex
* down, then ipc_get() needs read memery barriers as ipc_lock() does.
*/
struct kern_ipc_perm* ipc_get(struct ipc_ids* ids, int id)
@@ -667,7 +668,7 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
* Take the lock - this will be released by the corresponding
* call to stop().
*/
- down(&iface->ids->sem);
+ mutex_lock(&iface->ids->mutex);
/* pos < 0 is invalid */
if (*pos < 0)
@@ -697,7 +698,7 @@ static void sysvipc_proc_stop(struct seq_file *s, void *it)
ipc_unlock(ipc);
/* Release the lock we took in start() */
- up(&iface->ids->sem);
+ mutex_unlock(&iface->ids->mutex);
}
static int sysvipc_proc_show(struct seq_file *s, void *it)
diff --git a/ipc/util.h b/ipc/util.h
index efaff3ee7de..0181553d31d 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -25,7 +25,7 @@ struct ipc_ids {
int max_id;
unsigned short seq;
unsigned short seq_max;
- struct semaphore sem;
+ struct mutex mutex;
struct ipc_id_ary nullentry;
struct ipc_id_ary* entries;
};
@@ -40,7 +40,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
#define ipc_init_proc_interface(path, header, ids, show) do {} while (0)
#endif
-/* must be called with ids->sem acquired.*/
+/* must be called with ids->mutex acquired.*/
int ipc_findkey(struct ipc_ids* ids, key_t key);
int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size);
diff --git a/kernel/Makefile b/kernel/Makefile
index aebd7a78984..58908f9d156 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -12,6 +12,9 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o
obj-$(CONFIG_FUTEX) += futex.o
+ifeq ($(CONFIG_COMPAT),y)
+obj-$(CONFIG_FUTEX) += futex_compat.o
+endif
obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
obj-$(CONFIG_SMP) += cpu.o spinlock.o
obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
@@ -26,7 +29,7 @@ obj-$(CONFIG_COMPAT) += compat.o
obj-$(CONFIG_CPUSETS) += cpuset.o
obj-$(CONFIG_IKCONFIG) += configs.o
obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
-obj-$(CONFIG_AUDIT) += audit.o
+obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_SYSFS) += ksysfs.o
diff --git a/kernel/audit.c b/kernel/audit.c
index 0a813d2883e..04fe2e301b6 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -52,6 +52,7 @@
#include <linux/audit.h>
#include <net/sock.h>
+#include <net/netlink.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
@@ -72,7 +73,7 @@ static int audit_failure = AUDIT_FAIL_PRINTK;
* contains the (non-zero) pid. */
int audit_pid;
-/* If audit_limit is non-zero, limit the rate of sending audit records
+/* If audit_rate_limit is non-zero, limit the rate of sending audit records
* to that number per second. This prevents DoS attacks, but results in
* audit records being dropped. */
static int audit_rate_limit;
@@ -102,7 +103,7 @@ static struct sock *audit_sock;
* than AUDIT_MAXFREE are in use, the audit buffer is freed instead of
* being placed on the freelist). */
static DEFINE_SPINLOCK(audit_freelist_lock);
-static int audit_freelist_count = 0;
+static int audit_freelist_count;
static LIST_HEAD(audit_freelist);
static struct sk_buff_head audit_skb_queue;
@@ -113,7 +114,7 @@ static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
/* The netlink socket is only to be read by 1 CPU, which lets us assume
* that list additions and deletions never happen simultaneously in
* auditsc.c */
-DECLARE_MUTEX(audit_netlink_sem);
+DEFINE_MUTEX(audit_netlink_mutex);
/* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting
* audit records. Since printk uses a 1024 byte buffer, this buffer
@@ -142,7 +143,7 @@ static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
nlh->nlmsg_pid = pid;
}
-static void audit_panic(const char *message)
+void audit_panic(const char *message)
{
switch (audit_failure)
{
@@ -186,8 +187,14 @@ static inline int audit_rate_check(void)
return retval;
}
-/* Emit at least 1 message per second, even if audit_rate_check is
- * throttling. */
+/**
+ * audit_log_lost - conditionally log lost audit message event
+ * @message: the message stating reason for lost audit message
+ *
+ * Emit at least 1 message per second, even if audit_rate_check is
+ * throttling.
+ * Always increment the lost messages counter.
+*/
void audit_log_lost(const char *message)
{
static unsigned long last_msg = 0;
@@ -218,7 +225,6 @@ void audit_log_lost(const char *message)
audit_backlog_limit);
audit_panic(message);
}
-
}
static int audit_set_rate_limit(int limit, uid_t loginuid)
@@ -300,8 +306,22 @@ static int kauditd_thread(void *dummy)
remove_wait_queue(&kauditd_wait, &wait);
}
}
+ return 0;
}
+/**
+ * audit_send_reply - send an audit reply message via netlink
+ * @pid: process id to send reply to
+ * @seq: sequence number
+ * @type: audit message type
+ * @done: done (last) flag
+ * @multi: multi-part message flag
+ * @payload: payload data
+ * @size: payload size
+ *
+ * Allocates an skb, builds the netlink message, and sends it to the pid.
+ * No failure notifications.
+ */
void audit_send_reply(int pid, int seq, int type, int done, int multi,
void *payload, int size)
{
@@ -342,15 +362,19 @@ static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type)
switch (msg_type) {
case AUDIT_GET:
case AUDIT_LIST:
+ case AUDIT_LIST_RULES:
case AUDIT_SET:
case AUDIT_ADD:
+ case AUDIT_ADD_RULE:
case AUDIT_DEL:
+ case AUDIT_DEL_RULE:
case AUDIT_SIGNAL_INFO:
if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL))
err = -EPERM;
break;
case AUDIT_USER:
case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
+ case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2:
if (!cap_raised(eff_cap, CAP_AUDIT_WRITE))
err = -EPERM;
break;
@@ -376,7 +400,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (err)
return err;
- /* As soon as there's any sign of userspace auditd, start kauditd to talk to it */
+ /* As soon as there's any sign of userspace auditd,
+ * start kauditd to talk to it */
if (!kauditd_task)
kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd");
if (IS_ERR(kauditd_task)) {
@@ -430,6 +455,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
break;
case AUDIT_USER:
case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
+ case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2:
if (!audit_enabled && msg_type != AUDIT_USER_AVC)
return 0;
@@ -448,12 +474,23 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
break;
case AUDIT_ADD:
case AUDIT_DEL:
- if (nlh->nlmsg_len < sizeof(struct audit_rule))
+ if (nlmsg_len(nlh) < sizeof(struct audit_rule))
return -EINVAL;
/* fallthrough */
case AUDIT_LIST:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
- uid, seq, data, loginuid);
+ uid, seq, data, nlmsg_len(nlh),
+ loginuid);
+ break;
+ case AUDIT_ADD_RULE:
+ case AUDIT_DEL_RULE:
+ if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
+ return -EINVAL;
+ /* fallthrough */
+ case AUDIT_LIST_RULES:
+ err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
+ uid, seq, data, nlmsg_len(nlh),
+ loginuid);
break;
case AUDIT_SIGNAL_INFO:
sig_data.uid = audit_sig_uid;
@@ -469,9 +506,11 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
return err < 0 ? err : 0;
}
-/* Get message from skb (based on rtnetlink_rcv_skb). Each message is
+/*
+ * Get message from skb (based on rtnetlink_rcv_skb). Each message is
* processed by audit_receive_msg. Malformed skbs with wrong length are
- * discarded silently. */
+ * discarded silently.
+ */
static void audit_receive_skb(struct sk_buff *skb)
{
int err;
@@ -499,14 +538,14 @@ static void audit_receive(struct sock *sk, int length)
struct sk_buff *skb;
unsigned int qlen;
- down(&audit_netlink_sem);
+ mutex_lock(&audit_netlink_mutex);
for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
skb = skb_dequeue(&sk->sk_receive_queue);
audit_receive_skb(skb);
kfree_skb(skb);
}
- up(&audit_netlink_sem);
+ mutex_unlock(&audit_netlink_mutex);
}
@@ -519,8 +558,9 @@ static int __init audit_init(void)
THIS_MODULE);
if (!audit_sock)
audit_panic("cannot initialize netlink socket");
+ else
+ audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
- audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
skb_queue_head_init(&audit_skb_queue);
audit_initialized = 1;
audit_enabled = audit_default;
@@ -600,7 +640,10 @@ err:
return NULL;
}
-/* Compute a serial number for the audit record. Audit records are
+/**
+ * audit_serial - compute a serial number for the audit record
+ *
+ * Compute a serial number for the audit record. Audit records are
* written to user-space as soon as they are generated, so a complete
* audit record may be written in several pieces. The timestamp of the
* record and this serial number are used by the user-space tools to
@@ -612,8 +655,8 @@ err:
* audit context (for those records that have a context), and emit them
* all at syscall exit. However, this could delay the reporting of
* significant errors until syscall exit (or never, if the system
- * halts). */
-
+ * halts).
+ */
unsigned int audit_serial(void)
{
static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;
@@ -649,6 +692,21 @@ static inline void audit_get_stamp(struct audit_context *ctx,
* will be written at syscall exit. If there is no associated task, tsk
* should be NULL. */
+/**
+ * audit_log_start - obtain an audit buffer
+ * @ctx: audit_context (may be NULL)
+ * @gfp_mask: type of allocation
+ * @type: audit message type
+ *
+ * Returns audit_buffer pointer on success or NULL on error.
+ *
+ * Obtain an audit buffer. This routine does locking to obtain the
+ * audit buffer, but then no locking is required for calls to
+ * audit_log_*format. If the task (ctx) is a task that is currently in a
+ * syscall, then the syscall is marked as auditable and an audit record
+ * will be written at syscall exit. If there is no associated task, then
+ * task context (ctx) should be NULL.
+ */
struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
int type)
{
@@ -661,6 +719,9 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
if (!audit_initialized)
return NULL;
+ if (unlikely(audit_filter_type(type)))
+ return NULL;
+
if (gfp_mask & __GFP_WAIT)
reserve = 0;
else
@@ -713,6 +774,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
/**
* audit_expand - expand skb in the audit buffer
* @ab: audit_buffer
+ * @extra: space to add at tail of the skb
*
* Returns 0 (no space) on failed expansion, or available space if
* successful.
@@ -729,10 +791,12 @@ static inline int audit_expand(struct audit_buffer *ab, int extra)
return skb_tailroom(skb);
}
-/* Format an audit message into the audit buffer. If there isn't enough
+/*
+ * Format an audit message into the audit buffer. If there isn't enough
* room in the audit buffer, more room will be allocated and vsnprint
* will be called a second time. Currently, we assume that a printk
- * can't format message larger than 1024 bytes, so we don't either. */
+ * can't format message larger than 1024 bytes, so we don't either.
+ */
static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
va_list args)
{
@@ -757,7 +821,8 @@ static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
/* The printk buffer is 1024 bytes long, so if we get
* here and AUDIT_BUFSIZ is at least 1024, then we can
* log everything that printk could have logged. */
- avail = audit_expand(ab, max_t(unsigned, AUDIT_BUFSIZ, 1+len-avail));
+ avail = audit_expand(ab,
+ max_t(unsigned, AUDIT_BUFSIZ, 1+len-avail));
if (!avail)
goto out;
len = vsnprintf(skb->tail, avail, fmt, args2);
@@ -768,8 +833,14 @@ out:
return;
}
-/* Format a message into the audit buffer. All the work is done in
- * audit_log_vformat. */
+/**
+ * audit_log_format - format a message into the audit buffer.
+ * @ab: audit_buffer
+ * @fmt: format string
+ * @...: optional parameters matching @fmt string
+ *
+ * All the work is done in audit_log_vformat.
+ */
void audit_log_format(struct audit_buffer *ab, const char *fmt, ...)
{
va_list args;
@@ -781,9 +852,18 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...)
va_end(args);
}
-/* This function will take the passed buf and convert it into a string of
- * ascii hex digits. The new string is placed onto the skb. */
-void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf,
+/**
+ * audit_log_hex - convert a buffer to hex and append it to the audit skb
+ * @ab: the audit_buffer
+ * @buf: buffer to convert to hex
+ * @len: length of @buf to be converted
+ *
+ * No return value; failure to expand is silently ignored.
+ *
+ * This function will take the passed buf and convert it into a string of
+ * ascii hex digits. The new string is placed onto the skb.
+ */
+void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf,
size_t len)
{
int i, avail, new_len;
@@ -812,10 +892,16 @@ void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf,
skb_put(skb, len << 1); /* new string is twice the old string */
}
-/* This code will escape a string that is passed to it if the string
- * contains a control character, unprintable character, double quote mark,
+/**
+ * audit_log_unstrustedstring - log a string that may contain random characters
+ * @ab: audit_buffer
+ * @string: string to be logged
+ *
+ * This code will escape a string that is passed to it if the string
+ * contains a control character, unprintable character, double quote mark,
* or a space. Unescaped strings will start and end with a double quote mark.
- * Strings that are escaped are printed in hex (2 digits per char). */
+ * Strings that are escaped are printed in hex (2 digits per char).
+ */
void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
{
const unsigned char *p = string;
@@ -854,10 +940,15 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
kfree(path);
}
-/* The netlink_* functions cannot be called inside an irq context, so
- * the audit buffer is places on a queue and a tasklet is scheduled to
+/**
+ * audit_log_end - end one audit record
+ * @ab: the audit_buffer
+ *
+ * The netlink_* functions cannot be called inside an irq context, so
+ * the audit buffer is placed on a queue and a tasklet is scheduled to
* remove them from the queue outside the irq context. May be called in
- * any context. */
+ * any context.
+ */
void audit_log_end(struct audit_buffer *ab)
{
if (!ab)
@@ -878,9 +969,18 @@ void audit_log_end(struct audit_buffer *ab)
audit_buffer_free(ab);
}
-/* Log an audit record. This is a convenience function that calls
- * audit_log_start, audit_log_vformat, and audit_log_end. It may be
- * called in any context. */
+/**
+ * audit_log - Log an audit record
+ * @ctx: audit context
+ * @gfp_mask: type of allocation
+ * @type: audit message type
+ * @fmt: format string to use
+ * @...: variable parameters matching the format string
+ *
+ * This is a convenience function that calls audit_log_start,
+ * audit_log_vformat, and audit_log_end. It may be called
+ * in any context.
+ */
void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
const char *fmt, ...)
{
@@ -895,3 +995,8 @@ void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
audit_log_end(ab);
}
}
+
+EXPORT_SYMBOL(audit_log_start);
+EXPORT_SYMBOL(audit_log_end);
+EXPORT_SYMBOL(audit_log_format);
+EXPORT_SYMBOL(audit_log);
diff --git a/kernel/audit.h b/kernel/audit.h
new file mode 100644
index 00000000000..bc5392076e2
--- /dev/null
+++ b/kernel/audit.h
@@ -0,0 +1,88 @@
+/* audit -- definition of audit_context structure and supporting types
+ *
+ * Copyright 2003-2004 Red Hat, Inc.
+ * Copyright 2005 Hewlett-Packard Development Company, L.P.
+ * Copyright 2005 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/mutex.h>
+#include <linux/fs.h>
+#include <linux/audit.h>
+
+/* 0 = no checking
+ 1 = put_count checking
+ 2 = verbose put_count checking
+*/
+#define AUDIT_DEBUG 0
+
+/* At task start time, the audit_state is set in the audit_context using
+ a per-task filter. At syscall entry, the audit_state is augmented by
+ the syscall filter. */
+enum audit_state {
+ AUDIT_DISABLED, /* Do not create per-task audit_context.
+ * No syscall-specific audit records can
+ * be generated. */
+ AUDIT_SETUP_CONTEXT, /* Create the per-task audit_context,
+ * but don't necessarily fill it in at
+ * syscall entry time (i.e., filter
+ * instead). */
+ AUDIT_BUILD_CONTEXT, /* Create the per-task audit_context,
+ * and always fill it in at syscall
+ * entry time. This makes a full
+ * syscall record available if some
+ * other part of the kernel decides it
+ * should be recorded. */
+ AUDIT_RECORD_CONTEXT /* Create the per-task audit_context,
+ * always fill it in at syscall entry
+ * time, and always write out the audit
+ * record at syscall exit time. */
+};
+
+/* Rule lists */
+struct audit_field {
+ u32 type;
+ u32 val;
+ u32 op;
+};
+
+struct audit_krule {
+ int vers_ops;
+ u32 flags;
+ u32 listnr;
+ u32 action;
+ u32 mask[AUDIT_BITMASK_SIZE];
+ u32 buflen; /* for data alloc on list rules */
+ u32 field_count;
+ struct audit_field *fields;
+};
+
+struct audit_entry {
+ struct list_head list;
+ struct rcu_head rcu;
+ struct audit_krule rule;
+};
+
+
+extern int audit_pid;
+extern int audit_comparator(const u32 left, const u32 op, const u32 right);
+
+extern void audit_send_reply(int pid, int seq, int type,
+ int done, int multi,
+ void *payload, int size);
+extern void audit_log_lost(const char *message);
+extern void audit_panic(const char *message);
+extern struct mutex audit_netlink_mutex;
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
new file mode 100644
index 00000000000..d3a8539f3a8
--- /dev/null
+++ b/kernel/auditfilter.c
@@ -0,0 +1,630 @@
+/* auditfilter.c -- filtering of audit events
+ *
+ * Copyright 2003-2004 Red Hat, Inc.
+ * Copyright 2005 Hewlett-Packard Development Company, L.P.
+ * Copyright 2005 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/audit.h>
+#include <linux/kthread.h>
+#include <linux/netlink.h>
+#include "audit.h"
+
+/* There are three lists of rules -- one to search at task creation
+ * time, one to search at syscall entry time, and another to search at
+ * syscall exit time. */
+struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
+ LIST_HEAD_INIT(audit_filter_list[0]),
+ LIST_HEAD_INIT(audit_filter_list[1]),
+ LIST_HEAD_INIT(audit_filter_list[2]),
+ LIST_HEAD_INIT(audit_filter_list[3]),
+ LIST_HEAD_INIT(audit_filter_list[4]),
+ LIST_HEAD_INIT(audit_filter_list[5]),
+#if AUDIT_NR_FILTERS != 6
+#error Fix audit_filter_list initialiser
+#endif
+};
+
+static inline void audit_free_rule(struct audit_entry *e)
+{
+ kfree(e->rule.fields);
+ kfree(e);
+}
+
+static inline void audit_free_rule_rcu(struct rcu_head *head)
+{
+ struct audit_entry *e = container_of(head, struct audit_entry, rcu);
+ audit_free_rule(e);
+}
+
+/* Unpack a filter field's string representation from user-space
+ * buffer. */
+static __attribute__((unused)) char *audit_unpack_string(void **bufp, size_t *remain, size_t len)
+{
+ char *str;
+
+ if (!*bufp || (len == 0) || (len > *remain))
+ return ERR_PTR(-EINVAL);
+
+ /* Of the currently implemented string fields, PATH_MAX
+ * defines the longest valid length.
+ */
+ if (len > PATH_MAX)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ str = kmalloc(len + 1, GFP_KERNEL);
+ if (unlikely(!str))
+ return ERR_PTR(-ENOMEM);
+
+ memcpy(str, *bufp, len);
+ str[len] = 0;
+ *bufp += len;
+ *remain -= len;
+
+ return str;
+}
+
+/* Common user-space to kernel rule translation. */
+static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
+{
+ unsigned listnr;
+ struct audit_entry *entry;
+ struct audit_field *fields;
+ int i, err;
+
+ err = -EINVAL;
+ listnr = rule->flags & ~AUDIT_FILTER_PREPEND;
+ switch(listnr) {
+ default:
+ goto exit_err;
+ case AUDIT_FILTER_USER:
+ case AUDIT_FILTER_TYPE:
+#ifdef CONFIG_AUDITSYSCALL
+ case AUDIT_FILTER_ENTRY:
+ case AUDIT_FILTER_EXIT:
+ case AUDIT_FILTER_TASK:
+#endif
+ ;
+ }
+ if (rule->action != AUDIT_NEVER && rule->action != AUDIT_POSSIBLE &&
+ rule->action != AUDIT_ALWAYS)
+ goto exit_err;
+ if (rule->field_count > AUDIT_MAX_FIELDS)
+ goto exit_err;
+
+ err = -ENOMEM;
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (unlikely(!entry))
+ goto exit_err;
+ fields = kmalloc(sizeof(*fields) * rule->field_count, GFP_KERNEL);
+ if (unlikely(!fields)) {
+ kfree(entry);
+ goto exit_err;
+ }
+
+ memset(&entry->rule, 0, sizeof(struct audit_krule));
+ memset(fields, 0, sizeof(struct audit_field));
+
+ entry->rule.flags = rule->flags & AUDIT_FILTER_PREPEND;
+ entry->rule.listnr = listnr;
+ entry->rule.action = rule->action;
+ entry->rule.field_count = rule->field_count;
+ entry->rule.fields = fields;
+
+ for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
+ entry->rule.mask[i] = rule->mask[i];
+
+ return entry;
+
+exit_err:
+ return ERR_PTR(err);
+}
+
+/* Translate struct audit_rule to kernel's rule respresentation.
+ * Exists for backward compatibility with userspace. */
+static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
+{
+ struct audit_entry *entry;
+ int err = 0;
+ int i;
+
+ entry = audit_to_entry_common(rule);
+ if (IS_ERR(entry))
+ goto exit_nofree;
+
+ for (i = 0; i < rule->field_count; i++) {
+ struct audit_field *f = &entry->rule.fields[i];
+
+ if (rule->fields[i] & AUDIT_UNUSED_BITS) {
+ err = -EINVAL;
+ goto exit_free;
+ }
+
+ f->op = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
+ f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS);
+ f->val = rule->values[i];
+
+ entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1;
+
+ /* Support for legacy operators where
+ * AUDIT_NEGATE bit signifies != and otherwise assumes == */
+ if (f->op & AUDIT_NEGATE)
+ f->op = AUDIT_NOT_EQUAL;
+ else if (!f->op)
+ f->op = AUDIT_EQUAL;
+ else if (f->op == AUDIT_OPERATORS) {
+ err = -EINVAL;
+ goto exit_free;
+ }
+ }
+
+exit_nofree:
+ return entry;
+
+exit_free:
+ audit_free_rule(entry);
+ return ERR_PTR(err);
+}
+
+/* Translate struct audit_rule_data to kernel's rule respresentation. */
+static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
+ size_t datasz)
+{
+ int err = 0;
+ struct audit_entry *entry;
+ void *bufp;
+ /* size_t remain = datasz - sizeof(struct audit_rule_data); */
+ int i;
+
+ entry = audit_to_entry_common((struct audit_rule *)data);
+ if (IS_ERR(entry))
+ goto exit_nofree;
+
+ bufp = data->buf;
+ entry->rule.vers_ops = 2;
+ for (i = 0; i < data->field_count; i++) {
+ struct audit_field *f = &entry->rule.fields[i];
+
+ err = -EINVAL;
+ if (!(data->fieldflags[i] & AUDIT_OPERATORS) ||
+ data->fieldflags[i] & ~AUDIT_OPERATORS)
+ goto exit_free;
+
+ f->op = data->fieldflags[i] & AUDIT_OPERATORS;
+ f->type = data->fields[i];
+ switch(f->type) {
+ /* call type-specific conversion routines here */
+ default:
+ f->val = data->values[i];
+ }
+ }
+
+exit_nofree:
+ return entry;
+
+exit_free:
+ audit_free_rule(entry);
+ return ERR_PTR(err);
+}
+
+/* Pack a filter field's string representation into data block. */
+static inline size_t audit_pack_string(void **bufp, char *str)
+{
+ size_t len = strlen(str);
+
+ memcpy(*bufp, str, len);
+ *bufp += len;
+
+ return len;
+}
+
+/* Translate kernel rule respresentation to struct audit_rule.
+ * Exists for backward compatibility with userspace. */
+static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule)
+{
+ struct audit_rule *rule;
+ int i;
+
+ rule = kmalloc(sizeof(*rule), GFP_KERNEL);
+ if (unlikely(!rule))
+ return ERR_PTR(-ENOMEM);
+ memset(rule, 0, sizeof(*rule));
+
+ rule->flags = krule->flags | krule->listnr;
+ rule->action = krule->action;
+ rule->field_count = krule->field_count;
+ for (i = 0; i < rule->field_count; i++) {
+ rule->values[i] = krule->fields[i].val;
+ rule->fields[i] = krule->fields[i].type;
+
+ if (krule->vers_ops == 1) {
+ if (krule->fields[i].op & AUDIT_NOT_EQUAL)
+ rule->fields[i] |= AUDIT_NEGATE;
+ } else {
+ rule->fields[i] |= krule->fields[i].op;
+ }
+ }
+ for (i = 0; i < AUDIT_BITMASK_SIZE; i++) rule->mask[i] = krule->mask[i];
+
+ return rule;
+}
+
+/* Translate kernel rule respresentation to struct audit_rule_data. */
+static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
+{
+ struct audit_rule_data *data;
+ void *bufp;
+ int i;
+
+ data = kmalloc(sizeof(*data) + krule->buflen, GFP_KERNEL);
+ if (unlikely(!data))
+ return ERR_PTR(-ENOMEM);
+ memset(data, 0, sizeof(*data));
+
+ data->flags = krule->flags | krule->listnr;
+ data->action = krule->action;
+ data->field_count = krule->field_count;
+ bufp = data->buf;
+ for (i = 0; i < data->field_count; i++) {
+ struct audit_field *f = &krule->fields[i];
+
+ data->fields[i] = f->type;
+ data->fieldflags[i] = f->op;
+ switch(f->type) {
+ /* call type-specific conversion routines here */
+ default:
+ data->values[i] = f->val;
+ }
+ }
+ for (i = 0; i < AUDIT_BITMASK_SIZE; i++) data->mask[i] = krule->mask[i];
+
+ return data;
+}
+
+/* Compare two rules in kernel format. Considered success if rules
+ * don't match. */
+static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
+{
+ int i;
+
+ if (a->flags != b->flags ||
+ a->listnr != b->listnr ||
+ a->action != b->action ||
+ a->field_count != b->field_count)
+ return 1;
+
+ for (i = 0; i < a->field_count; i++) {
+ if (a->fields[i].type != b->fields[i].type ||
+ a->fields[i].op != b->fields[i].op)
+ return 1;
+
+ switch(a->fields[i].type) {
+ /* call type-specific comparison routines here */
+ default:
+ if (a->fields[i].val != b->fields[i].val)
+ return 1;
+ }
+ }
+
+ for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
+ if (a->mask[i] != b->mask[i])
+ return 1;
+
+ return 0;
+}
+
+/* Add rule to given filterlist if not a duplicate. Protected by
+ * audit_netlink_mutex. */
+static inline int audit_add_rule(struct audit_entry *entry,
+ struct list_head *list)
+{
+ struct audit_entry *e;
+
+ /* Do not use the _rcu iterator here, since this is the only
+ * addition routine. */
+ list_for_each_entry(e, list, list) {
+ if (!audit_compare_rule(&entry->rule, &e->rule))
+ return -EEXIST;
+ }
+
+ if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
+ list_add_rcu(&entry->list, list);
+ } else {
+ list_add_tail_rcu(&entry->list, list);
+ }
+
+ return 0;
+}
+
+/* Remove an existing rule from filterlist. Protected by
+ * audit_netlink_mutex. */
+static inline int audit_del_rule(struct audit_entry *entry,
+ struct list_head *list)
+{
+ struct audit_entry *e;
+
+ /* Do not use the _rcu iterator here, since this is the only
+ * deletion routine. */
+ list_for_each_entry(e, list, list) {
+ if (!audit_compare_rule(&entry->rule, &e->rule)) {
+ list_del_rcu(&e->list);
+ call_rcu(&e->rcu, audit_free_rule_rcu);
+ return 0;
+ }
+ }
+ return -ENOENT; /* No matching rule */
+}
+
+/* List rules using struct audit_rule. Exists for backward
+ * compatibility with userspace. */
+static int audit_list(void *_dest)
+{
+ int pid, seq;
+ int *dest = _dest;
+ struct audit_entry *entry;
+ int i;
+
+ pid = dest[0];
+ seq = dest[1];
+ kfree(dest);
+
+ mutex_lock(&audit_netlink_mutex);
+
+ /* The *_rcu iterators not needed here because we are
+ always called with audit_netlink_mutex held. */
+ for (i=0; i<AUDIT_NR_FILTERS; i++) {
+ list_for_each_entry(entry, &audit_filter_list[i], list) {
+ struct audit_rule *rule;
+
+ rule = audit_krule_to_rule(&entry->rule);
+ if (unlikely(!rule))
+ break;
+ audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
+ rule, sizeof(*rule));
+ kfree(rule);
+ }
+ }
+ audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
+
+ mutex_unlock(&audit_netlink_mutex);
+ return 0;
+}
+
+/* List rules using struct audit_rule_data. */
+static int audit_list_rules(void *_dest)
+{
+ int pid, seq;
+ int *dest = _dest;
+ struct audit_entry *e;
+ int i;
+
+ pid = dest[0];
+ seq = dest[1];
+ kfree(dest);
+
+ mutex_lock(&audit_netlink_mutex);
+
+ /* The *_rcu iterators not needed here because we are
+ always called with audit_netlink_mutex held. */
+ for (i=0; i<AUDIT_NR_FILTERS; i++) {
+ list_for_each_entry(e, &audit_filter_list[i], list) {
+ struct audit_rule_data *data;
+
+ data = audit_krule_to_data(&e->rule);
+ if (unlikely(!data))
+ break;
+ audit_send_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
+ data, sizeof(*data));
+ kfree(data);
+ }
+ }
+ audit_send_reply(pid, seq, AUDIT_LIST_RULES, 1, 1, NULL, 0);
+
+ mutex_unlock(&audit_netlink_mutex);
+ return 0;
+}
+
+/**
+ * audit_receive_filter - apply all rules to the specified message type
+ * @type: audit message type
+ * @pid: target pid for netlink audit messages
+ * @uid: target uid for netlink audit messages
+ * @seq: netlink audit message sequence (serial) number
+ * @data: payload data
+ * @datasz: size of payload data
+ * @loginuid: loginuid of sender
+ */
+int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
+ size_t datasz, uid_t loginuid)
+{
+ struct task_struct *tsk;
+ int *dest;
+ int err = 0;
+ struct audit_entry *entry;
+
+ switch (type) {
+ case AUDIT_LIST:
+ case AUDIT_LIST_RULES:
+ /* We can't just spew out the rules here because we might fill
+ * the available socket buffer space and deadlock waiting for
+ * auditctl to read from it... which isn't ever going to
+ * happen if we're actually running in the context of auditctl
+ * trying to _send_ the stuff */
+
+ dest = kmalloc(2 * sizeof(int), GFP_KERNEL);
+ if (!dest)
+ return -ENOMEM;
+ dest[0] = pid;
+ dest[1] = seq;
+
+ if (type == AUDIT_LIST)
+ tsk = kthread_run(audit_list, dest, "audit_list");
+ else
+ tsk = kthread_run(audit_list_rules, dest,
+ "audit_list_rules");
+ if (IS_ERR(tsk)) {
+ kfree(dest);
+ err = PTR_ERR(tsk);
+ }
+ break;
+ case AUDIT_ADD:
+ case AUDIT_ADD_RULE:
+ if (type == AUDIT_ADD)
+ entry = audit_rule_to_entry(data);
+ else
+ entry = audit_data_to_entry(data, datasz);
+ if (IS_ERR(entry))
+ return PTR_ERR(entry);
+
+ err = audit_add_rule(entry,
+ &audit_filter_list[entry->rule.listnr]);
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u add rule to list=%d res=%d\n",
+ loginuid, entry->rule.listnr, !err);
+
+ if (err)
+ audit_free_rule(entry);
+ break;
+ case AUDIT_DEL:
+ case AUDIT_DEL_RULE:
+ if (type == AUDIT_DEL)
+ entry = audit_rule_to_entry(data);
+ else
+ entry = audit_data_to_entry(data, datasz);
+ if (IS_ERR(entry))
+ return PTR_ERR(entry);
+
+ err = audit_del_rule(entry,
+ &audit_filter_list[entry->rule.listnr]);
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u remove rule from list=%d res=%d\n",
+ loginuid, entry->rule.listnr, !err);
+
+ audit_free_rule(entry);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return err;
+}
+
+int audit_comparator(const u32 left, const u32 op, const u32 right)
+{
+ switch (op) {
+ case AUDIT_EQUAL:
+ return (left == right);
+ case AUDIT_NOT_EQUAL:
+ return (left != right);
+ case AUDIT_LESS_THAN:
+ return (left < right);
+ case AUDIT_LESS_THAN_OR_EQUAL:
+ return (left <= right);
+ case AUDIT_GREATER_THAN:
+ return (left > right);
+ case AUDIT_GREATER_THAN_OR_EQUAL:
+ return (left >= right);
+ }
+ BUG();
+ return 0;
+}
+
+
+
+static int audit_filter_user_rules(struct netlink_skb_parms *cb,
+ struct audit_krule *rule,
+ enum audit_state *state)
+{
+ int i;
+
+ for (i = 0; i < rule->field_count; i++) {
+ struct audit_field *f = &rule->fields[i];
+ int result = 0;
+
+ switch (f->type) {
+ case AUDIT_PID:
+ result = audit_comparator(cb->creds.pid, f->op, f->val);
+ break;
+ case AUDIT_UID:
+ result = audit_comparator(cb->creds.uid, f->op, f->val);
+ break;
+ case AUDIT_GID:
+ result = audit_comparator(cb->creds.gid, f->op, f->val);
+ break;
+ case AUDIT_LOGINUID:
+ result = audit_comparator(cb->loginuid, f->op, f->val);
+ break;
+ }
+
+ if (!result)
+ return 0;
+ }
+ switch (rule->action) {
+ case AUDIT_NEVER: *state = AUDIT_DISABLED; break;
+ case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT; break;
+ case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break;
+ }
+ return 1;
+}
+
+int audit_filter_user(struct netlink_skb_parms *cb, int type)
+{
+ struct audit_entry *e;
+ enum audit_state state;
+ int ret = 1;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
+ if (audit_filter_user_rules(cb, &e->rule, &state)) {
+ if (state == AUDIT_DISABLED)
+ ret = 0;
+ break;
+ }
+ }
+ rcu_read_unlock();
+
+ return ret; /* Audit by default */
+}
+
+int audit_filter_type(int type)
+{
+ struct audit_entry *e;
+ int result = 0;
+
+ rcu_read_lock();
+ if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE]))
+ goto unlock_and_return;
+
+ list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE],
+ list) {
+ int i;
+ for (i = 0; i < e->rule.field_count; i++) {
+ struct audit_field *f = &e->rule.fields[i];
+ if (f->type == AUDIT_MSGTYPE) {
+ result = audit_comparator(type, f->op, f->val);
+ if (!result)
+ break;
+ }
+ }
+ if (result)
+ goto unlock_and_return;
+ }
+unlock_and_return:
+ rcu_read_unlock();
+ return result;
+}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index c4394abcd5e..7f160df21a2 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2,6 +2,8 @@
* Handles all system-call specific auditing features.
*
* Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ * Copyright 2005 Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2005 IBM Corporation
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -27,11 +29,22 @@
* this file -- see entry.S) is based on a GPL'd patch written by
* okir@suse.de and Copyright 2003 SuSE Linux AG.
*
+ * The support of additional filter rules compares (>, <, >=, <=) was
+ * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005.
+ *
+ * Modified by Amy Griffis <amy.griffis@hp.com> to collect additional
+ * filesystem information.
+ *
+ * Subject and object context labeling support added by <danjones@us.ibm.com>
+ * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance.
*/
#include <linux/init.h>
#include <asm/types.h>
#include <asm/atomic.h>
+#include <asm/types.h>
+#include <linux/fs.h>
+#include <linux/namei.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/mount.h>
@@ -39,16 +52,16 @@
#include <linux/audit.h>
#include <linux/personality.h>
#include <linux/time.h>
-#include <linux/kthread.h>
#include <linux/netlink.h>
#include <linux/compiler.h>
#include <asm/unistd.h>
+#include <linux/security.h>
+#include <linux/list.h>
+#include <linux/tty.h>
+
+#include "audit.h"
-/* 0 = no checking
- 1 = put_count checking
- 2 = verbose put_count checking
-*/
-#define AUDIT_DEBUG 0
+extern struct list_head audit_filter_list[];
/* No syscall auditing will take place unless audit_enabled != 0. */
extern int audit_enabled;
@@ -62,29 +75,6 @@ extern int audit_enabled;
* path_lookup. */
#define AUDIT_NAMES_RESERVED 7
-/* At task start time, the audit_state is set in the audit_context using
- a per-task filter. At syscall entry, the audit_state is augmented by
- the syscall filter. */
-enum audit_state {
- AUDIT_DISABLED, /* Do not create per-task audit_context.
- * No syscall-specific audit records can
- * be generated. */
- AUDIT_SETUP_CONTEXT, /* Create the per-task audit_context,
- * but don't necessarily fill it in at
- * syscall entry time (i.e., filter
- * instead). */
- AUDIT_BUILD_CONTEXT, /* Create the per-task audit_context,
- * and always fill it in at syscall
- * entry time. This makes a full
- * syscall record available if some
- * other part of the kernel decides it
- * should be recorded. */
- AUDIT_RECORD_CONTEXT /* Create the per-task audit_context,
- * always fill it in at syscall entry
- * time, and always write out the audit
- * record at syscall exit time. */
-};
-
/* When fs/namei.c:getname() is called, we store the pointer in name and
* we don't let putname() free it (instead we free all of the saved
* pointers at syscall exit time).
@@ -93,12 +83,13 @@ enum audit_state {
struct audit_names {
const char *name;
unsigned long ino;
+ unsigned long pino;
dev_t dev;
umode_t mode;
uid_t uid;
gid_t gid;
dev_t rdev;
- unsigned flags;
+ char *ctx;
};
struct audit_aux_data {
@@ -115,6 +106,7 @@ struct audit_aux_data_ipcctl {
uid_t uid;
gid_t gid;
mode_t mode;
+ char *ctx;
};
struct audit_aux_data_socketcall {
@@ -167,290 +159,72 @@ struct audit_context {
#endif
};
- /* Public API */
-/* There are three lists of rules -- one to search at task creation
- * time, one to search at syscall entry time, and another to search at
- * syscall exit time. */
-static struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
- LIST_HEAD_INIT(audit_filter_list[0]),
- LIST_HEAD_INIT(audit_filter_list[1]),
- LIST_HEAD_INIT(audit_filter_list[2]),
- LIST_HEAD_INIT(audit_filter_list[3]),
- LIST_HEAD_INIT(audit_filter_list[4]),
-#if AUDIT_NR_FILTERS != 5
-#error Fix audit_filter_list initialiser
-#endif
-};
-
-struct audit_entry {
- struct list_head list;
- struct rcu_head rcu;
- struct audit_rule rule;
-};
-
-extern int audit_pid;
-
-/* Copy rule from user-space to kernel-space. Called from
- * audit_add_rule during AUDIT_ADD. */
-static inline int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
-{
- int i;
-
- if (s->action != AUDIT_NEVER
- && s->action != AUDIT_POSSIBLE
- && s->action != AUDIT_ALWAYS)
- return -1;
- if (s->field_count < 0 || s->field_count > AUDIT_MAX_FIELDS)
- return -1;
- if ((s->flags & ~AUDIT_FILTER_PREPEND) >= AUDIT_NR_FILTERS)
- return -1;
-
- d->flags = s->flags;
- d->action = s->action;
- d->field_count = s->field_count;
- for (i = 0; i < d->field_count; i++) {
- d->fields[i] = s->fields[i];
- d->values[i] = s->values[i];
- }
- for (i = 0; i < AUDIT_BITMASK_SIZE; i++) d->mask[i] = s->mask[i];
- return 0;
-}
-
-/* Check to see if two rules are identical. It is called from
- * audit_add_rule during AUDIT_ADD and
- * audit_del_rule during AUDIT_DEL. */
-static inline int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
-{
- int i;
-
- if (a->flags != b->flags)
- return 1;
-
- if (a->action != b->action)
- return 1;
-
- if (a->field_count != b->field_count)
- return 1;
-
- for (i = 0; i < a->field_count; i++) {
- if (a->fields[i] != b->fields[i]
- || a->values[i] != b->values[i])
- return 1;
- }
-
- for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
- if (a->mask[i] != b->mask[i])
- return 1;
-
- return 0;
-}
-
-/* Note that audit_add_rule and audit_del_rule are called via
- * audit_receive() in audit.c, and are protected by
- * audit_netlink_sem. */
-static inline int audit_add_rule(struct audit_rule *rule,
- struct list_head *list)
-{
- struct audit_entry *entry;
-
- /* Do not use the _rcu iterator here, since this is the only
- * addition routine. */
- list_for_each_entry(entry, list, list) {
- if (!audit_compare_rule(rule, &entry->rule)) {
- return -EEXIST;
- }
- }
-
- if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
- return -ENOMEM;
- if (audit_copy_rule(&entry->rule, rule)) {
- kfree(entry);
- return -EINVAL;
- }
-
- if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
- entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
- list_add_rcu(&entry->list, list);
- } else {
- list_add_tail_rcu(&entry->list, list);
- }
-
- return 0;
-}
-
-static inline void audit_free_rule(struct rcu_head *head)
-{
- struct audit_entry *e = container_of(head, struct audit_entry, rcu);
- kfree(e);
-}
-
-/* Note that audit_add_rule and audit_del_rule are called via
- * audit_receive() in audit.c, and are protected by
- * audit_netlink_sem. */
-static inline int audit_del_rule(struct audit_rule *rule,
- struct list_head *list)
-{
- struct audit_entry *e;
-
- /* Do not use the _rcu iterator here, since this is the only
- * deletion routine. */
- list_for_each_entry(e, list, list) {
- if (!audit_compare_rule(rule, &e->rule)) {
- list_del_rcu(&e->list);
- call_rcu(&e->rcu, audit_free_rule);
- return 0;
- }
- }
- return -ENOENT; /* No matching rule */
-}
-
-static int audit_list_rules(void *_dest)
-{
- int pid, seq;
- int *dest = _dest;
- struct audit_entry *entry;
- int i;
-
- pid = dest[0];
- seq = dest[1];
- kfree(dest);
-
- down(&audit_netlink_sem);
-
- /* The *_rcu iterators not needed here because we are
- always called with audit_netlink_sem held. */
- for (i=0; i<AUDIT_NR_FILTERS; i++) {
- list_for_each_entry(entry, &audit_filter_list[i], list)
- audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
- &entry->rule, sizeof(entry->rule));
- }
- audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
-
- up(&audit_netlink_sem);
- return 0;
-}
-
-int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
- uid_t loginuid)
-{
- struct task_struct *tsk;
- int *dest;
- int err = 0;
- unsigned listnr;
-
- switch (type) {
- case AUDIT_LIST:
- /* We can't just spew out the rules here because we might fill
- * the available socket buffer space and deadlock waiting for
- * auditctl to read from it... which isn't ever going to
- * happen if we're actually running in the context of auditctl
- * trying to _send_ the stuff */
-
- dest = kmalloc(2 * sizeof(int), GFP_KERNEL);
- if (!dest)
- return -ENOMEM;
- dest[0] = pid;
- dest[1] = seq;
-
- tsk = kthread_run(audit_list_rules, dest, "audit_list_rules");
- if (IS_ERR(tsk)) {
- kfree(dest);
- err = PTR_ERR(tsk);
- }
- break;
- case AUDIT_ADD:
- listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
- if (listnr >= AUDIT_NR_FILTERS)
- return -EINVAL;
-
- err = audit_add_rule(data, &audit_filter_list[listnr]);
- if (!err)
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "auid=%u added an audit rule\n", loginuid);
- break;
- case AUDIT_DEL:
- listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
- if (listnr >= AUDIT_NR_FILTERS)
- return -EINVAL;
-
- err = audit_del_rule(data, &audit_filter_list[listnr]);
- if (!err)
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "auid=%u removed an audit rule\n", loginuid);
- break;
- default:
- return -EINVAL;
- }
-
- return err;
-}
/* Compare a task_struct with an audit_rule. Return 1 on match, 0
* otherwise. */
static int audit_filter_rules(struct task_struct *tsk,
- struct audit_rule *rule,
+ struct audit_krule *rule,
struct audit_context *ctx,
enum audit_state *state)
{
int i, j;
for (i = 0; i < rule->field_count; i++) {
- u32 field = rule->fields[i] & ~AUDIT_NEGATE;
- u32 value = rule->values[i];
+ struct audit_field *f = &rule->fields[i];
int result = 0;
- switch (field) {
+ switch (f->type) {
case AUDIT_PID:
- result = (tsk->pid == value);
+ result = audit_comparator(tsk->pid, f->op, f->val);
break;
case AUDIT_UID:
- result = (tsk->uid == value);
+ result = audit_comparator(tsk->uid, f->op, f->val);
break;
case AUDIT_EUID:
- result = (tsk->euid == value);
+ result = audit_comparator(tsk->euid, f->op, f->val);
break;
case AUDIT_SUID:
- result = (tsk->suid == value);
+ result = audit_comparator(tsk->suid, f->op, f->val);
break;
case AUDIT_FSUID:
- result = (tsk->fsuid == value);
+ result = audit_comparator(tsk->fsuid, f->op, f->val);
break;
case AUDIT_GID:
- result = (tsk->gid == value);
+ result = audit_comparator(tsk->gid, f->op, f->val);
break;
case AUDIT_EGID:
- result = (tsk->egid == value);
+ result = audit_comparator(tsk->egid, f->op, f->val);
break;
case AUDIT_SGID:
- result = (tsk->sgid == value);
+ result = audit_comparator(tsk->sgid, f->op, f->val);
break;
case AUDIT_FSGID:
- result = (tsk->fsgid == value);
+ result = audit_comparator(tsk->fsgid, f->op, f->val);
break;
case AUDIT_PERS:
- result = (tsk->personality == value);
+ result = audit_comparator(tsk->personality, f->op, f->val);
break;
case AUDIT_ARCH:
- if (ctx)
- result = (ctx->arch == value);
+ if (ctx)
+ result = audit_comparator(ctx->arch, f->op, f->val);
break;
case AUDIT_EXIT:
if (ctx && ctx->return_valid)
- result = (ctx->return_code == value);
+ result = audit_comparator(ctx->return_code, f->op, f->val);
break;
case AUDIT_SUCCESS:
if (ctx && ctx->return_valid) {
- if (value)
- result = (ctx->return_valid == AUDITSC_SUCCESS);
+ if (f->val)
+ result = audit_comparator(ctx->return_valid, f->op, AUDITSC_SUCCESS);
else
- result = (ctx->return_valid == AUDITSC_FAILURE);
+ result = audit_comparator(ctx->return_valid, f->op, AUDITSC_FAILURE);
}
break;
case AUDIT_DEVMAJOR:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (MAJOR(ctx->names[j].dev)==value) {
+ if (audit_comparator(MAJOR(ctx->names[j].dev), f->op, f->val)) {
++result;
break;
}
@@ -460,7 +234,7 @@ static int audit_filter_rules(struct task_struct *tsk,
case AUDIT_DEVMINOR:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (MINOR(ctx->names[j].dev)==value) {
+ if (audit_comparator(MINOR(ctx->names[j].dev), f->op, f->val)) {
++result;
break;
}
@@ -470,7 +244,8 @@ static int audit_filter_rules(struct task_struct *tsk,
case AUDIT_INODE:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (ctx->names[j].ino == value) {
+ if (audit_comparator(ctx->names[j].ino, f->op, f->val) ||
+ audit_comparator(ctx->names[j].pino, f->op, f->val)) {
++result;
break;
}
@@ -480,19 +255,17 @@ static int audit_filter_rules(struct task_struct *tsk,
case AUDIT_LOGINUID:
result = 0;
if (ctx)
- result = (ctx->loginuid == value);
+ result = audit_comparator(ctx->loginuid, f->op, f->val);
break;
case AUDIT_ARG0:
case AUDIT_ARG1:
case AUDIT_ARG2:
case AUDIT_ARG3:
if (ctx)
- result = (ctx->argv[field-AUDIT_ARG0]==value);
+ result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
break;
}
- if (rule->fields[i] & AUDIT_NEGATE)
- result = !result;
if (!result)
return 0;
}
@@ -527,7 +300,7 @@ static enum audit_state audit_filter_task(struct task_struct *tsk)
/* At syscall entry and exit time, this filter is called if the
* audit_state is not low enough that auditing cannot take place, but is
* also not high enough that we already know we have to write an audit
- * record (i.e., the state is AUDIT_SETUP_CONTEXT or AUDIT_BUILD_CONTEXT).
+ * record (i.e., the state is AUDIT_SETUP_CONTEXT or AUDIT_BUILD_CONTEXT).
*/
static enum audit_state audit_filter_syscall(struct task_struct *tsk,
struct audit_context *ctx,
@@ -541,77 +314,19 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
rcu_read_lock();
if (!list_empty(list)) {
- int word = AUDIT_WORD(ctx->major);
- int bit = AUDIT_BIT(ctx->major);
-
- list_for_each_entry_rcu(e, list, list) {
- if ((e->rule.mask[word] & bit) == bit
- && audit_filter_rules(tsk, &e->rule, ctx, &state)) {
- rcu_read_unlock();
- return state;
- }
- }
- }
- rcu_read_unlock();
- return AUDIT_BUILD_CONTEXT;
-}
-
-static int audit_filter_user_rules(struct netlink_skb_parms *cb,
- struct audit_rule *rule,
- enum audit_state *state)
-{
- int i;
-
- for (i = 0; i < rule->field_count; i++) {
- u32 field = rule->fields[i] & ~AUDIT_NEGATE;
- u32 value = rule->values[i];
- int result = 0;
-
- switch (field) {
- case AUDIT_PID:
- result = (cb->creds.pid == value);
- break;
- case AUDIT_UID:
- result = (cb->creds.uid == value);
- break;
- case AUDIT_GID:
- result = (cb->creds.gid == value);
- break;
- case AUDIT_LOGINUID:
- result = (cb->loginuid == value);
- break;
- }
-
- if (rule->fields[i] & AUDIT_NEGATE)
- result = !result;
- if (!result)
- return 0;
- }
- switch (rule->action) {
- case AUDIT_NEVER: *state = AUDIT_DISABLED; break;
- case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT; break;
- case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break;
- }
- return 1;
-}
-
-int audit_filter_user(struct netlink_skb_parms *cb, int type)
-{
- struct audit_entry *e;
- enum audit_state state;
- int ret = 1;
-
- rcu_read_lock();
- list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
- if (audit_filter_user_rules(cb, &e->rule, &state)) {
- if (state == AUDIT_DISABLED)
- ret = 0;
- break;
+ int word = AUDIT_WORD(ctx->major);
+ int bit = AUDIT_BIT(ctx->major);
+
+ list_for_each_entry_rcu(e, list, list) {
+ if ((e->rule.mask[word] & bit) == bit
+ && audit_filter_rules(tsk, &e->rule, ctx, &state)) {
+ rcu_read_unlock();
+ return state;
+ }
}
}
rcu_read_unlock();
-
- return ret; /* Audit by default */
+ return AUDIT_BUILD_CONTEXT;
}
/* This should be called with task_lock() held. */
@@ -654,17 +369,18 @@ static inline void audit_free_names(struct audit_context *context)
#if AUDIT_DEBUG == 2
if (context->auditable
||context->put_count + context->ino_count != context->name_count) {
- printk(KERN_ERR "audit.c:%d(:%d): major=%d in_syscall=%d"
+ printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d"
" name_count=%d put_count=%d"
" ino_count=%d [NOT freeing]\n",
- __LINE__,
+ __FILE__, __LINE__,
context->serial, context->major, context->in_syscall,
context->name_count, context->put_count,
context->ino_count);
- for (i = 0; i < context->name_count; i++)
+ for (i = 0; i < context->name_count; i++) {
printk(KERN_ERR "names[%d] = %p = %s\n", i,
context->names[i].name,
- context->names[i].name);
+ context->names[i].name ?: "(null)");
+ }
dump_stack();
return;
}
@@ -674,9 +390,13 @@ static inline void audit_free_names(struct audit_context *context)
context->ino_count = 0;
#endif
- for (i = 0; i < context->name_count; i++)
+ for (i = 0; i < context->name_count; i++) {
+ char *p = context->names[i].ctx;
+ context->names[i].ctx = NULL;
+ kfree(p);
if (context->names[i].name)
__putname(context->names[i].name);
+ }
context->name_count = 0;
if (context->pwd)
dput(context->pwd);
@@ -696,6 +416,12 @@ static inline void audit_free_aux(struct audit_context *context)
dput(axi->dentry);
mntput(axi->mnt);
}
+ if ( aux->type == AUDIT_IPC ) {
+ struct audit_aux_data_ipcctl *axi = (void *)aux;
+ if (axi->ctx)
+ kfree(axi->ctx);
+ }
+
context->aux = aux->next;
kfree(aux);
}
@@ -721,10 +447,15 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
return context;
}
-/* Filter on the task information and allocate a per-task audit context
+/**
+ * audit_alloc - allocate an audit context block for a task
+ * @tsk: task
+ *
+ * Filter on the task information and allocate a per-task audit context
* if necessary. Doing so turns on system call auditing for the
* specified task. This is called from copy_process, so no lock is
- * needed. */
+ * needed.
+ */
int audit_alloc(struct task_struct *tsk)
{
struct audit_context *context;
@@ -775,7 +506,37 @@ static inline void audit_free_context(struct audit_context *context)
printk(KERN_ERR "audit: freed %d contexts\n", count);
}
-static void audit_log_task_info(struct audit_buffer *ab)
+static void audit_log_task_context(struct audit_buffer *ab, gfp_t gfp_mask)
+{
+ char *ctx = NULL;
+ ssize_t len = 0;
+
+ len = security_getprocattr(current, "current", NULL, 0);
+ if (len < 0) {
+ if (len != -EINVAL)
+ goto error_path;
+ return;
+ }
+
+ ctx = kmalloc(len, gfp_mask);
+ if (!ctx)
+ goto error_path;
+
+ len = security_getprocattr(current, "current", ctx, len);
+ if (len < 0 )
+ goto error_path;
+
+ audit_log_format(ab, " subj=%s", ctx);
+ return;
+
+error_path:
+ if (ctx)
+ kfree(ctx);
+ audit_panic("error in audit_log_task_context");
+ return;
+}
+
+static void audit_log_task_info(struct audit_buffer *ab, gfp_t gfp_mask)
{
char name[sizeof(current->comm)];
struct mm_struct *mm = current->mm;
@@ -788,6 +549,10 @@ static void audit_log_task_info(struct audit_buffer *ab)
if (!mm)
return;
+ /*
+ * this is brittle; all callers that pass GFP_ATOMIC will have
+ * NULL current->mm and we won't get here.
+ */
down_read(&mm->mmap_sem);
vma = mm->mmap;
while (vma) {
@@ -801,6 +566,7 @@ static void audit_log_task_info(struct audit_buffer *ab)
vma = vma->vm_next;
}
up_read(&mm->mmap_sem);
+ audit_log_task_context(ab, gfp_mask);
}
static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
@@ -808,6 +574,7 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
int i;
struct audit_buffer *ab;
struct audit_aux_data *aux;
+ const char *tty;
ab = audit_log_start(context, gfp_mask, AUDIT_SYSCALL);
if (!ab)
@@ -820,11 +587,15 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
audit_log_format(ab, " success=%s exit=%ld",
(context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
context->return_code);
+ if (current->signal->tty && current->signal->tty->name)
+ tty = current->signal->tty->name;
+ else
+ tty = "(none)";
audit_log_format(ab,
" a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
" pid=%d auid=%u uid=%u gid=%u"
" euid=%u suid=%u fsuid=%u"
- " egid=%u sgid=%u fsgid=%u",
+ " egid=%u sgid=%u fsgid=%u tty=%s",
context->argv[0],
context->argv[1],
context->argv[2],
@@ -835,8 +606,8 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
context->uid,
context->gid,
context->euid, context->suid, context->fsuid,
- context->egid, context->sgid, context->fsgid);
- audit_log_task_info(ab);
+ context->egid, context->sgid, context->fsgid, tty);
+ audit_log_task_info(ab, gfp_mask);
audit_log_end(ab);
for (aux = context->aux; aux; aux = aux->next) {
@@ -849,8 +620,8 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
case AUDIT_IPC: {
struct audit_aux_data_ipcctl *axi = (void *)aux;
audit_log_format(ab,
- " qbytes=%lx iuid=%u igid=%u mode=%x",
- axi->qbytes, axi->uid, axi->gid, axi->mode);
+ " qbytes=%lx iuid=%u igid=%u mode=%x obj=%s",
+ axi->qbytes, axi->uid, axi->gid, axi->mode, axi->ctx);
break; }
case AUDIT_SOCKETCALL: {
@@ -885,42 +656,62 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
}
}
for (i = 0; i < context->name_count; i++) {
+ unsigned long ino = context->names[i].ino;
+ unsigned long pino = context->names[i].pino;
+
ab = audit_log_start(context, gfp_mask, AUDIT_PATH);
if (!ab)
continue; /* audit_panic has been called */
audit_log_format(ab, "item=%d", i);
- if (context->names[i].name) {
- audit_log_format(ab, " name=");
+
+ audit_log_format(ab, " name=");
+ if (context->names[i].name)
audit_log_untrustedstring(ab, context->names[i].name);
- }
- audit_log_format(ab, " flags=%x\n", context->names[i].flags);
-
- if (context->names[i].ino != (unsigned long)-1)
- audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
- " ouid=%u ogid=%u rdev=%02x:%02x",
- context->names[i].ino,
- MAJOR(context->names[i].dev),
- MINOR(context->names[i].dev),
- context->names[i].mode,
- context->names[i].uid,
- context->names[i].gid,
- MAJOR(context->names[i].rdev),
+ else
+ audit_log_format(ab, "(null)");
+
+ if (pino != (unsigned long)-1)
+ audit_log_format(ab, " parent=%lu", pino);
+ if (ino != (unsigned long)-1)
+ audit_log_format(ab, " inode=%lu", ino);
+ if ((pino != (unsigned long)-1) || (ino != (unsigned long)-1))
+ audit_log_format(ab, " dev=%02x:%02x mode=%#o"
+ " ouid=%u ogid=%u rdev=%02x:%02x",
+ MAJOR(context->names[i].dev),
+ MINOR(context->names[i].dev),
+ context->names[i].mode,
+ context->names[i].uid,
+ context->names[i].gid,
+ MAJOR(context->names[i].rdev),
MINOR(context->names[i].rdev));
+ if (context->names[i].ctx) {
+ audit_log_format(ab, " obj=%s",
+ context->names[i].ctx);
+ }
+
audit_log_end(ab);
}
}
-/* Free a per-task audit context. Called from copy_process and
- * __put_task_struct. */
+/**
+ * audit_free - free a per-task audit context
+ * @tsk: task whose audit context block to free
+ *
+ * Called from copy_process and __put_task_struct.
+ */
void audit_free(struct task_struct *tsk)
{
struct audit_context *context;
- task_lock(tsk);
+ /*
+ * No need to lock the task - when we execute audit_free()
+ * then the task has no external references anymore, and
+ * we are tearing it down. (The locking also confuses
+ * DEBUG_LOCKDEP - this freeing may occur in softirq
+ * contexts as well, via RCU.)
+ */
context = audit_get_context(tsk, 0, 0);
- task_unlock(tsk);
-
if (likely(!context))
return;
@@ -934,13 +725,24 @@ void audit_free(struct task_struct *tsk)
audit_free_context(context);
}
-/* Fill in audit context at syscall entry. This only happens if the
+/**
+ * audit_syscall_entry - fill in an audit record at syscall entry
+ * @tsk: task being audited
+ * @arch: architecture type
+ * @major: major syscall type (function)
+ * @a1: additional syscall register 1
+ * @a2: additional syscall register 2
+ * @a3: additional syscall register 3
+ * @a4: additional syscall register 4
+ *
+ * Fill in audit context at syscall entry. This only happens if the
* audit context was created when the task was created and the state or
* filters demand the audit context be built. If the state from the
* per-task filter or from the per-syscall filter is AUDIT_RECORD_CONTEXT,
* then the record will be written at syscall exit time (otherwise, it
* will only be written if another part of the kernel requests that it
- * be written). */
+ * be written).
+ */
void audit_syscall_entry(struct task_struct *tsk, int arch, int major,
unsigned long a1, unsigned long a2,
unsigned long a3, unsigned long a4)
@@ -950,7 +752,8 @@ void audit_syscall_entry(struct task_struct *tsk, int arch, int major,
BUG_ON(!context);
- /* This happens only on certain architectures that make system
+ /*
+ * This happens only on certain architectures that make system
* calls in kernel_thread via the entry.S interface, instead of
* with direct calls. (If you are porting to a new
* architecture, hitting this condition can indicate that you
@@ -966,11 +769,6 @@ void audit_syscall_entry(struct task_struct *tsk, int arch, int major,
if (context->in_syscall) {
struct audit_context *newctx;
-#if defined(__NR_vm86) && defined(__NR_vm86old)
- /* vm86 mode should only be entered once */
- if (major == __NR_vm86 || major == __NR_vm86old)
- return;
-#endif
#if AUDIT_DEBUG
printk(KERN_ERR
"audit(:%d) pid=%d in syscall=%d;"
@@ -1014,11 +812,18 @@ void audit_syscall_entry(struct task_struct *tsk, int arch, int major,
context->auditable = !!(state == AUDIT_RECORD_CONTEXT);
}
-/* Tear down after system call. If the audit context has been marked as
+/**
+ * audit_syscall_exit - deallocate audit context after a system call
+ * @tsk: task being audited
+ * @valid: success/failure flag
+ * @return_code: syscall return value
+ *
+ * Tear down after system call. If the audit context has been marked as
* auditable (either because of the AUDIT_RECORD_CONTEXT state from
* filtering, or because some other part of the kernel write an audit
* message), then write out the syscall information. In call cases,
- * free the names stored from getname(). */
+ * free the names stored from getname().
+ */
void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code)
{
struct audit_context *context;
@@ -1053,7 +858,13 @@ void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code)
put_task_struct(tsk);
}
-/* Add a name to the list. Called from fs/namei.c:getname(). */
+/**
+ * audit_getname - add a name to the list
+ * @name: name to add
+ *
+ * Add a name to the list of audit names for this context.
+ * Called from fs/namei.c:getname().
+ */
void audit_getname(const char *name)
{
struct audit_context *context = current->audit_context;
@@ -1082,10 +893,13 @@ void audit_getname(const char *name)
}
-/* Intercept a putname request. Called from
- * include/linux/fs.h:putname(). If we have stored the name from
- * getname in the audit context, then we delay the putname until syscall
- * exit. */
+/* audit_putname - intercept a putname request
+ * @name: name to intercept and delay for putname
+ *
+ * If we have stored the name from getname in the audit context,
+ * then we delay the putname until syscall exit.
+ * Called from include/linux/fs.h:putname().
+ */
void audit_putname(const char *name)
{
struct audit_context *context = current->audit_context;
@@ -1100,7 +914,7 @@ void audit_putname(const char *name)
for (i = 0; i < context->name_count; i++)
printk(KERN_ERR "name[%d] = %p = %s\n", i,
context->names[i].name,
- context->names[i].name);
+ context->names[i].name ?: "(null)");
}
#endif
__putname(name);
@@ -1122,9 +936,52 @@ void audit_putname(const char *name)
#endif
}
-/* Store the inode and device from a lookup. Called from
- * fs/namei.c:path_lookup(). */
-void audit_inode(const char *name, const struct inode *inode, unsigned flags)
+void audit_inode_context(int idx, const struct inode *inode)
+{
+ struct audit_context *context = current->audit_context;
+ const char *suffix = security_inode_xattr_getsuffix();
+ char *ctx = NULL;
+ int len = 0;
+
+ if (!suffix)
+ goto ret;
+
+ len = security_inode_getsecurity(inode, suffix, NULL, 0, 0);
+ if (len == -EOPNOTSUPP)
+ goto ret;
+ if (len < 0)
+ goto error_path;
+
+ ctx = kmalloc(len, GFP_KERNEL);
+ if (!ctx)
+ goto error_path;
+
+ len = security_inode_getsecurity(inode, suffix, ctx, len, 0);
+ if (len < 0)
+ goto error_path;
+
+ kfree(context->names[idx].ctx);
+ context->names[idx].ctx = ctx;
+ goto ret;
+
+error_path:
+ if (ctx)
+ kfree(ctx);
+ audit_panic("error in audit_inode_context");
+ret:
+ return;
+}
+
+
+/**
+ * audit_inode - store the inode and device from a lookup
+ * @name: name being audited
+ * @inode: inode being audited
+ * @flags: lookup flags (as used in path_lookup())
+ *
+ * Called from fs/namei.c:path_lookup().
+ */
+void __audit_inode(const char *name, const struct inode *inode, unsigned flags)
{
int idx;
struct audit_context *context = current->audit_context;
@@ -1150,15 +1007,105 @@ void audit_inode(const char *name, const struct inode *inode, unsigned flags)
++context->ino_count;
#endif
}
- context->names[idx].flags = flags;
- context->names[idx].ino = inode->i_ino;
context->names[idx].dev = inode->i_sb->s_dev;
context->names[idx].mode = inode->i_mode;
context->names[idx].uid = inode->i_uid;
context->names[idx].gid = inode->i_gid;
context->names[idx].rdev = inode->i_rdev;
+ audit_inode_context(idx, inode);
+ if ((flags & LOOKUP_PARENT) && (strcmp(name, "/") != 0) &&
+ (strcmp(name, ".") != 0)) {
+ context->names[idx].ino = (unsigned long)-1;
+ context->names[idx].pino = inode->i_ino;
+ } else {
+ context->names[idx].ino = inode->i_ino;
+ context->names[idx].pino = (unsigned long)-1;
+ }
+}
+
+/**
+ * audit_inode_child - collect inode info for created/removed objects
+ * @dname: inode's dentry name
+ * @inode: inode being audited
+ * @pino: inode number of dentry parent
+ *
+ * For syscalls that create or remove filesystem objects, audit_inode
+ * can only collect information for the filesystem object's parent.
+ * This call updates the audit context with the child's information.
+ * Syscalls that create a new filesystem object must be hooked after
+ * the object is created. Syscalls that remove a filesystem object
+ * must be hooked prior, in order to capture the target inode during
+ * unsuccessful attempts.
+ */
+void __audit_inode_child(const char *dname, const struct inode *inode,
+ unsigned long pino)
+{
+ int idx;
+ struct audit_context *context = current->audit_context;
+
+ if (!context->in_syscall)
+ return;
+
+ /* determine matching parent */
+ if (dname)
+ for (idx = 0; idx < context->name_count; idx++)
+ if (context->names[idx].pino == pino) {
+ const char *n;
+ const char *name = context->names[idx].name;
+ int dlen = strlen(dname);
+ int nlen = name ? strlen(name) : 0;
+
+ if (nlen < dlen)
+ continue;
+
+ /* disregard trailing slashes */
+ n = name + nlen - 1;
+ while ((*n == '/') && (n > name))
+ n--;
+
+ /* find last path component */
+ n = n - dlen + 1;
+ if (n < name)
+ continue;
+ else if (n > name) {
+ if (*--n != '/')
+ continue;
+ else
+ n++;
+ }
+
+ if (strncmp(n, dname, dlen) == 0)
+ goto update_context;
+ }
+
+ /* catch-all in case match not found */
+ idx = context->name_count++;
+ context->names[idx].name = NULL;
+ context->names[idx].pino = pino;
+#if AUDIT_DEBUG
+ context->ino_count++;
+#endif
+
+update_context:
+ if (inode) {
+ context->names[idx].ino = inode->i_ino;
+ context->names[idx].dev = inode->i_sb->s_dev;
+ context->names[idx].mode = inode->i_mode;
+ context->names[idx].uid = inode->i_uid;
+ context->names[idx].gid = inode->i_gid;
+ context->names[idx].rdev = inode->i_rdev;
+ audit_inode_context(idx, inode);
+ }
}
+/**
+ * auditsc_get_stamp - get local copies of audit_context values
+ * @ctx: audit_context for the task
+ * @t: timespec to store time recorded in the audit_context
+ * @serial: serial value that is recorded in the audit_context
+ *
+ * Also sets the context as auditable.
+ */
void auditsc_get_stamp(struct audit_context *ctx,
struct timespec *t, unsigned int *serial)
{
@@ -1170,6 +1117,15 @@ void auditsc_get_stamp(struct audit_context *ctx,
ctx->auditable = 1;
}
+/**
+ * audit_set_loginuid - set a task's audit_context loginuid
+ * @task: task whose audit context is being modified
+ * @loginuid: loginuid value
+ *
+ * Returns 0.
+ *
+ * Called (set) from fs/proc/base.c::proc_loginuid_write().
+ */
int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
{
if (task->audit_context) {
@@ -1188,12 +1144,59 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
return 0;
}
+/**
+ * audit_get_loginuid - get the loginuid for an audit_context
+ * @ctx: the audit_context
+ *
+ * Returns the context's loginuid or -1 if @ctx is NULL.
+ */
uid_t audit_get_loginuid(struct audit_context *ctx)
{
return ctx ? ctx->loginuid : -1;
}
-int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
+static char *audit_ipc_context(struct kern_ipc_perm *ipcp)
+{
+ struct audit_context *context = current->audit_context;
+ char *ctx = NULL;
+ int len = 0;
+
+ if (likely(!context))
+ return NULL;
+
+ len = security_ipc_getsecurity(ipcp, NULL, 0);
+ if (len == -EOPNOTSUPP)
+ goto ret;
+ if (len < 0)
+ goto error_path;
+
+ ctx = kmalloc(len, GFP_ATOMIC);
+ if (!ctx)
+ goto error_path;
+
+ len = security_ipc_getsecurity(ipcp, ctx, len);
+ if (len < 0)
+ goto error_path;
+
+ return ctx;
+
+error_path:
+ kfree(ctx);
+ audit_panic("error in audit_ipc_context");
+ret:
+ return NULL;
+}
+
+/**
+ * audit_ipc_perms - record audit data for ipc
+ * @qbytes: msgq bytes
+ * @uid: msgq user id
+ * @gid: msgq group id
+ * @mode: msgq mode (permissions)
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp)
{
struct audit_aux_data_ipcctl *ax;
struct audit_context *context = current->audit_context;
@@ -1201,7 +1204,7 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
if (likely(!context))
return 0;
- ax = kmalloc(sizeof(*ax), GFP_KERNEL);
+ ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
if (!ax)
return -ENOMEM;
@@ -1209,6 +1212,7 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
ax->uid = uid;
ax->gid = gid;
ax->mode = mode;
+ ax->ctx = audit_ipc_context(ipcp);
ax->d.type = AUDIT_IPC;
ax->d.next = context->aux;
@@ -1216,6 +1220,13 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
return 0;
}
+/**
+ * audit_socketcall - record audit data for sys_socketcall
+ * @nargs: number of args
+ * @args: args array
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
int audit_socketcall(int nargs, unsigned long *args)
{
struct audit_aux_data_socketcall *ax;
@@ -1237,6 +1248,13 @@ int audit_socketcall(int nargs, unsigned long *args)
return 0;
}
+/**
+ * audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto
+ * @len: data length in user space
+ * @a: data address in kernel space
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
int audit_sockaddr(int len, void *a)
{
struct audit_aux_data_sockaddr *ax;
@@ -1258,6 +1276,15 @@ int audit_sockaddr(int len, void *a)
return 0;
}
+/**
+ * audit_avc_path - record the granting or denial of permissions
+ * @dentry: dentry to record
+ * @mnt: mnt to record
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ *
+ * Called from security/selinux/avc.c::avc_audit()
+ */
int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt)
{
struct audit_aux_data_path *ax;
@@ -1279,6 +1306,14 @@ int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt)
return 0;
}
+/**
+ * audit_signal_info - record signal info for shutting down audit subsystem
+ * @sig: signal value
+ * @t: task being signaled
+ *
+ * If the audit subsystem is being terminated, record the task (pid)
+ * and uid that is doing that.
+ */
void audit_signal_info(int sig, struct task_struct *t)
{
extern pid_t audit_sig_pid;
@@ -1295,4 +1330,3 @@ void audit_signal_info(int sig, struct task_struct *t)
}
}
}
-
diff --git a/kernel/capability.c b/kernel/capability.c
index bfa3c92e16f..1a4d8a40d3f 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -233,3 +233,19 @@ out:
return ret;
}
+
+int __capable(struct task_struct *t, int cap)
+{
+ if (security_capable(t, cap) == 0) {
+ t->flags |= PF_SUPERPRIV;
+ return 1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(__capable);
+
+int capable(int cap)
+{
+ return __capable(current, cap);
+}
+EXPORT_SYMBOL(capable);
diff --git a/kernel/compat.c b/kernel/compat.c
index 8c9cd88b678..c1601a84f8d 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -17,10 +17,10 @@
#include <linux/time.h>
#include <linux/signal.h>
#include <linux/sched.h> /* for MAX_SCHEDULE_TIMEOUT */
-#include <linux/futex.h> /* for FUTEX_WAIT */
#include <linux/syscalls.h>
#include <linux/unistd.h>
#include <linux/security.h>
+#include <linux/timex.h>
#include <asm/uaccess.h>
@@ -238,28 +238,6 @@ asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set,
return ret;
}
-#ifdef CONFIG_FUTEX
-asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, int val,
- struct compat_timespec __user *utime, u32 __user *uaddr2,
- int val3)
-{
- struct timespec t;
- unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
- int val2 = 0;
-
- if ((op == FUTEX_WAIT) && utime) {
- if (get_compat_timespec(&t, utime))
- return -EFAULT;
- timeout = timespec_to_jiffies(&t) + 1;
- }
- if (op >= FUTEX_REQUEUE)
- val2 = (int) (unsigned long) utime;
-
- return do_futex((unsigned long)uaddr, op, val, timeout,
- (unsigned long)uaddr2, val2, val3);
-}
-#endif
-
asmlinkage long compat_sys_setrlimit(unsigned int resource,
struct compat_rlimit __user *rlim)
{
@@ -898,3 +876,61 @@ asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat
return -ERESTARTNOHAND;
}
#endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
+
+asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp)
+{
+ struct timex txc;
+ int ret;
+
+ memset(&txc, 0, sizeof(struct timex));
+
+ if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) ||
+ __get_user(txc.modes, &utp->modes) ||
+ __get_user(txc.offset, &utp->offset) ||
+ __get_user(txc.freq, &utp->freq) ||
+ __get_user(txc.maxerror, &utp->maxerror) ||
+ __get_user(txc.esterror, &utp->esterror) ||
+ __get_user(txc.status, &utp->status) ||
+ __get_user(txc.constant, &utp->constant) ||
+ __get_user(txc.precision, &utp->precision) ||
+ __get_user(txc.tolerance, &utp->tolerance) ||
+ __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+ __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+ __get_user(txc.tick, &utp->tick) ||
+ __get_user(txc.ppsfreq, &utp->ppsfreq) ||
+ __get_user(txc.jitter, &utp->jitter) ||
+ __get_user(txc.shift, &utp->shift) ||
+ __get_user(txc.stabil, &utp->stabil) ||
+ __get_user(txc.jitcnt, &utp->jitcnt) ||
+ __get_user(txc.calcnt, &utp->calcnt) ||
+ __get_user(txc.errcnt, &utp->errcnt) ||
+ __get_user(txc.stbcnt, &utp->stbcnt))
+ return -EFAULT;
+
+ ret = do_adjtimex(&txc);
+
+ if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) ||
+ __put_user(txc.modes, &utp->modes) ||
+ __put_user(txc.offset, &utp->offset) ||
+ __put_user(txc.freq, &utp->freq) ||
+ __put_user(txc.maxerror, &utp->maxerror) ||
+ __put_user(txc.esterror, &utp->esterror) ||
+ __put_user(txc.status, &utp->status) ||
+ __put_user(txc.constant, &utp->constant) ||
+ __put_user(txc.precision, &utp->precision) ||
+ __put_user(txc.tolerance, &utp->tolerance) ||
+ __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+ __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+ __put_user(txc.tick, &utp->tick) ||
+ __put_user(txc.ppsfreq, &utp->ppsfreq) ||
+ __put_user(txc.jitter, &utp->jitter) ||
+ __put_user(txc.shift, &utp->shift) ||
+ __put_user(txc.stabil, &utp->stabil) ||
+ __put_user(txc.jitcnt, &utp->jitcnt) ||
+ __put_user(txc.calcnt, &utp->calcnt) ||
+ __put_user(txc.errcnt, &utp->errcnt) ||
+ __put_user(txc.stbcnt, &utp->stbcnt))
+ ret = -EFAULT;
+
+ return ret;
+}
diff --git a/kernel/cpu.c b/kernel/cpu.c
index e882c6babf4..fe2b8d0bfe4 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -18,7 +18,7 @@
/* This protects CPUs going up and down... */
static DECLARE_MUTEX(cpucontrol);
-static struct notifier_block *cpu_chain;
+static BLOCKING_NOTIFIER_HEAD(cpu_chain);
#ifdef CONFIG_HOTPLUG_CPU
static struct task_struct *lock_cpu_hotplug_owner;
@@ -71,21 +71,13 @@ EXPORT_SYMBOL_GPL(lock_cpu_hotplug_interruptible);
/* Need to know about CPUs going up/down? */
int register_cpu_notifier(struct notifier_block *nb)
{
- int ret;
-
- if ((ret = lock_cpu_hotplug_interruptible()) != 0)
- return ret;
- ret = notifier_chain_register(&cpu_chain, nb);
- unlock_cpu_hotplug();
- return ret;
+ return blocking_notifier_chain_register(&cpu_chain, nb);
}
EXPORT_SYMBOL(register_cpu_notifier);
void unregister_cpu_notifier(struct notifier_block *nb)
{
- lock_cpu_hotplug();
- notifier_chain_unregister(&cpu_chain, nb);
- unlock_cpu_hotplug();
+ blocking_notifier_chain_unregister(&cpu_chain, nb);
}
EXPORT_SYMBOL(unregister_cpu_notifier);
@@ -141,7 +133,7 @@ int cpu_down(unsigned int cpu)
goto out;
}
- err = notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE,
+ err = blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE,
(void *)(long)cpu);
if (err == NOTIFY_BAD) {
printk("%s: attempt to take down CPU %u failed\n",
@@ -159,7 +151,7 @@ int cpu_down(unsigned int cpu)
p = __stop_machine_run(take_cpu_down, NULL, cpu);
if (IS_ERR(p)) {
/* CPU didn't die: tell everyone. Can't complain. */
- if (notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED,
+ if (blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED,
(void *)(long)cpu) == NOTIFY_BAD)
BUG();
@@ -182,8 +174,8 @@ int cpu_down(unsigned int cpu)
put_cpu();
/* CPU is completely dead: tell everyone. Too late to complain. */
- if (notifier_call_chain(&cpu_chain, CPU_DEAD, (void *)(long)cpu)
- == NOTIFY_BAD)
+ if (blocking_notifier_call_chain(&cpu_chain, CPU_DEAD,
+ (void *)(long)cpu) == NOTIFY_BAD)
BUG();
check_for_tasks(cpu);
@@ -211,7 +203,7 @@ int __devinit cpu_up(unsigned int cpu)
goto out;
}
- ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
+ ret = blocking_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
if (ret == NOTIFY_BAD) {
printk("%s: attempt to bring up CPU %u failed\n",
__FUNCTION__, cpu);
@@ -223,15 +215,15 @@ int __devinit cpu_up(unsigned int cpu)
ret = __cpu_up(cpu);
if (ret != 0)
goto out_notify;
- if (!cpu_online(cpu))
- BUG();
+ BUG_ON(!cpu_online(cpu));
/* Now call notifier in preparation. */
- notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);
+ blocking_notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);
out_notify:
if (ret != 0)
- notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu);
+ blocking_notifier_call_chain(&cpu_chain,
+ CPU_UP_CANCELED, hcpu);
out:
unlock_cpu_hotplug();
return ret;
diff --git a/kernel/exit.c b/kernel/exit.c
index 8037405e136..bc0ec674d3f 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -29,8 +29,11 @@
#include <linux/cpuset.h>
#include <linux/syscalls.h>
#include <linux/signal.h>
+#include <linux/posix-timers.h>
#include <linux/cn_proc.h>
#include <linux/mutex.h>
+#include <linux/futex.h>
+#include <linux/compat.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -48,15 +51,80 @@ static void __unhash_process(struct task_struct *p)
{
nr_threads--;
detach_pid(p, PIDTYPE_PID);
- detach_pid(p, PIDTYPE_TGID);
if (thread_group_leader(p)) {
detach_pid(p, PIDTYPE_PGID);
detach_pid(p, PIDTYPE_SID);
- if (p->pid)
- __get_cpu_var(process_counts)--;
+
+ list_del_init(&p->tasks);
+ __get_cpu_var(process_counts)--;
}
+ list_del_rcu(&p->thread_group);
+ remove_parent(p);
+}
- REMOVE_LINKS(p);
+/*
+ * This function expects the tasklist_lock write-locked.
+ */
+static void __exit_signal(struct task_struct *tsk)
+{
+ struct signal_struct *sig = tsk->signal;
+ struct sighand_struct *sighand;
+
+ BUG_ON(!sig);
+ BUG_ON(!atomic_read(&sig->count));
+
+ rcu_read_lock();
+ sighand = rcu_dereference(tsk->sighand);
+ spin_lock(&sighand->siglock);
+
+ posix_cpu_timers_exit(tsk);
+ if (atomic_dec_and_test(&sig->count))
+ posix_cpu_timers_exit_group(tsk);
+ else {
+ /*
+ * If there is any task waiting for the group exit
+ * then notify it:
+ */
+ if (sig->group_exit_task && atomic_read(&sig->count) == sig->notify_count) {
+ wake_up_process(sig->group_exit_task);
+ sig->group_exit_task = NULL;
+ }
+ if (tsk == sig->curr_target)
+ sig->curr_target = next_thread(tsk);
+ /*
+ * Accumulate here the counters for all threads but the
+ * group leader as they die, so they can be added into
+ * the process-wide totals when those are taken.
+ * The group leader stays around as a zombie as long
+ * as there are other threads. When it gets reaped,
+ * the exit.c code will add its counts into these totals.
+ * We won't ever get here for the group leader, since it
+ * will have been the last reference on the signal_struct.
+ */
+ 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;
+ sig->nivcsw += tsk->nivcsw;
+ sig->sched_time += tsk->sched_time;
+ sig = NULL; /* Marker for below. */
+ }
+
+ __unhash_process(tsk);
+
+ tsk->signal = NULL;
+ tsk->sighand = NULL;
+ spin_unlock(&sighand->siglock);
+ rcu_read_unlock();
+
+ __cleanup_sighand(sighand);
+ clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
+ flush_sigqueue(&tsk->pending);
+ if (sig) {
+ flush_sigqueue(&sig->shared_pending);
+ __cleanup_signal(sig);
+ }
}
void release_task(struct task_struct * p)
@@ -65,21 +133,14 @@ void release_task(struct task_struct * p)
task_t *leader;
struct dentry *proc_dentry;
-repeat:
+repeat:
atomic_dec(&p->user->processes);
spin_lock(&p->proc_lock);
proc_dentry = proc_pid_unhash(p);
write_lock_irq(&tasklist_lock);
- if (unlikely(p->ptrace))
- __ptrace_unlink(p);
+ ptrace_unlink(p);
BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
__exit_signal(p);
- /*
- * Note that the fastpath in sys_times depends on __exit_signal having
- * updated the counters before a task is removed from the tasklist of
- * the process by __unhash_process.
- */
- __unhash_process(p);
/*
* If we are the last non-leader member of the thread
@@ -114,21 +175,6 @@ repeat:
goto repeat;
}
-/* we are using it only for SMP init */
-
-void unhash_process(struct task_struct *p)
-{
- struct dentry *proc_dentry;
-
- spin_lock(&p->proc_lock);
- proc_dentry = proc_pid_unhash(p);
- write_lock_irq(&tasklist_lock);
- __unhash_process(p);
- write_unlock_irq(&tasklist_lock);
- spin_unlock(&p->proc_lock);
- proc_pid_flush(proc_dentry);
-}
-
/*
* This checks not only the pgrp, but falls back on the pid if no
* satisfactory pgrp is found. I dunno - gdb doesn't work correctly
@@ -236,10 +282,10 @@ static void reparent_to_init(void)
ptrace_unlink(current);
/* Reparent to init */
- REMOVE_LINKS(current);
+ remove_parent(current);
current->parent = child_reaper;
current->real_parent = child_reaper;
- SET_LINKS(current);
+ add_parent(current);
/* Set the exit signal to SIGCHLD so we signal init on exit */
current->exit_signal = SIGCHLD;
@@ -536,13 +582,13 @@ static void exit_mm(struct task_struct * tsk)
mmput(mm);
}
-static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_reaper)
+static inline void choose_new_parent(task_t *p, task_t *reaper)
{
/*
* Make sure we're not reparenting to ourselves and that
* the parent is not a zombie.
*/
- BUG_ON(p == reaper || reaper->exit_state >= EXIT_ZOMBIE);
+ BUG_ON(p == reaper || reaper->exit_state);
p->real_parent = reaper;
}
@@ -567,9 +613,9 @@ static void reparent_thread(task_t *p, task_t *father, int traced)
* anyway, so let go of it.
*/
p->ptrace = 0;
- list_del_init(&p->sibling);
+ remove_parent(p);
p->parent = p->real_parent;
- list_add_tail(&p->sibling, &p->parent->children);
+ add_parent(p);
/* If we'd notified the old parent about this child's death,
* also notify the new parent.
@@ -643,7 +689,7 @@ static void forget_original_parent(struct task_struct * father,
if (father == p->real_parent) {
/* reparent with a reaper, real father it's us */
- choose_new_parent(p, reaper, child_reaper);
+ choose_new_parent(p, reaper);
reparent_thread(p, father, 0);
} else {
/* reparent ptraced task to its real parent */
@@ -664,7 +710,7 @@ static void forget_original_parent(struct task_struct * father,
}
list_for_each_safe(_p, _n, &father->ptrace_children) {
p = list_entry(_p,struct task_struct,ptrace_list);
- choose_new_parent(p, reaper, child_reaper);
+ choose_new_parent(p, reaper);
reparent_thread(p, father, 1);
}
}
@@ -805,7 +851,7 @@ fastcall NORET_TYPE void do_exit(long code)
panic("Aiee, killing interrupt handler!");
if (unlikely(!tsk->pid))
panic("Attempted to kill the idle task!");
- if (unlikely(tsk->pid == 1))
+ if (unlikely(tsk == child_reaper))
panic("Attempted to kill init!");
if (unlikely(current->ptrace & PT_TRACE_EXIT)) {
@@ -852,6 +898,12 @@ fastcall NORET_TYPE void do_exit(long code)
exit_itimers(tsk->signal);
acct_process(code);
}
+ if (unlikely(tsk->robust_list))
+ exit_robust_list(tsk);
+#ifdef CONFIG_COMPAT
+ if (unlikely(tsk->compat_robust_list))
+ compat_exit_robust_list(tsk);
+#endif
exit_mm(tsk);
exit_sem(tsk);
@@ -912,13 +964,6 @@ asmlinkage long sys_exit(int error_code)
do_exit((error_code&0xff)<<8);
}
-task_t fastcall *next_thread(const task_t *p)
-{
- return pid_task(p->pids[PIDTYPE_TGID].pid_list.next, PIDTYPE_TGID);
-}
-
-EXPORT_SYMBOL(next_thread);
-
/*
* Take down every thread in the group. This is called by fatal signals
* as well as by sys_exit_group (below).
@@ -933,7 +978,6 @@ do_group_exit(int exit_code)
else if (!thread_group_empty(current)) {
struct signal_struct *const sig = current->signal;
struct sighand_struct *const sighand = current->sighand;
- read_lock(&tasklist_lock);
spin_lock_irq(&sighand->siglock);
if (sig->flags & SIGNAL_GROUP_EXIT)
/* Another thread got here before we took the lock. */
@@ -943,7 +987,6 @@ do_group_exit(int exit_code)
zap_other_threads(current);
}
spin_unlock_irq(&sighand->siglock);
- read_unlock(&tasklist_lock);
}
do_exit(exit_code);
@@ -1273,7 +1316,7 @@ bail_ref:
/* move to end of parent's list to avoid starvation */
remove_parent(p);
- add_parent(p, p->parent);
+ add_parent(p);
write_unlock_irq(&tasklist_lock);
diff --git a/kernel/fork.c b/kernel/fork.c
index a02063903aa..b3f7a1bb5e5 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -84,7 +84,7 @@ static kmem_cache_t *task_struct_cachep;
#endif
/* SLAB cache for signal_struct structures (tsk->signal) */
-kmem_cache_t *signal_cachep;
+static kmem_cache_t *signal_cachep;
/* SLAB cache for sighand_struct structures (tsk->sighand) */
kmem_cache_t *sighand_cachep;
@@ -769,8 +769,7 @@ int unshare_files(void)
struct files_struct *files = current->files;
int rc;
- if(!files)
- BUG();
+ BUG_ON(!files);
/* This can race but the race causes us to copy when we don't
need to and drop the copy */
@@ -787,14 +786,6 @@ int unshare_files(void)
EXPORT_SYMBOL(unshare_files);
-void sighand_free_cb(struct rcu_head *rhp)
-{
- struct sighand_struct *sp;
-
- sp = container_of(rhp, struct sighand_struct, rcu);
- kmem_cache_free(sighand_cachep, sp);
-}
-
static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk)
{
struct sighand_struct *sig;
@@ -807,12 +798,17 @@ static inline int copy_sighand(unsigned long clone_flags, struct task_struct * t
rcu_assign_pointer(tsk->sighand, sig);
if (!sig)
return -ENOMEM;
- spin_lock_init(&sig->siglock);
atomic_set(&sig->count, 1);
memcpy(sig->action, current->sighand->action, sizeof(sig->action));
return 0;
}
+void __cleanup_sighand(struct sighand_struct *sighand)
+{
+ if (atomic_dec_and_test(&sighand->count))
+ kmem_cache_free(sighand_cachep, sighand);
+}
+
static inline int copy_signal(unsigned long clone_flags, struct task_struct * tsk)
{
struct signal_struct *sig;
@@ -848,7 +844,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_REL);
sig->it_real_incr.tv64 = 0;
sig->real_timer.function = it_real_fn;
- sig->real_timer.data = tsk;
+ sig->tsk = tsk;
sig->it_virt_expires = cputime_zero;
sig->it_virt_incr = cputime_zero;
@@ -882,6 +878,22 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
return 0;
}
+void __cleanup_signal(struct signal_struct *sig)
+{
+ exit_thread_group_keys(sig);
+ kmem_cache_free(signal_cachep, sig);
+}
+
+static inline void cleanup_signal(struct task_struct *tsk)
+{
+ struct signal_struct *sig = tsk->signal;
+
+ atomic_dec(&sig->live);
+
+ if (atomic_dec_and_test(&sig->count))
+ __cleanup_signal(sig);
+}
+
static inline void copy_flags(unsigned long clone_flags, struct task_struct *p)
{
unsigned long new_flags = p->flags;
@@ -1062,7 +1074,10 @@ static task_t *copy_process(unsigned long clone_flags,
* Clear TID on mm_release()?
*/
p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL;
-
+ p->robust_list = NULL;
+#ifdef CONFIG_COMPAT
+ p->compat_robust_list = NULL;
+#endif
/*
* sigaltstack should be cleared when sharing the same VM
*/
@@ -1093,6 +1108,7 @@ static task_t *copy_process(unsigned long clone_flags,
* We dont wake it up yet.
*/
p->group_leader = p;
+ INIT_LIST_HEAD(&p->thread_group);
INIT_LIST_HEAD(&p->ptrace_children);
INIT_LIST_HEAD(&p->ptrace_list);
@@ -1116,16 +1132,6 @@ static task_t *copy_process(unsigned long clone_flags,
!cpu_online(task_cpu(p))))
set_task_cpu(p, smp_processor_id());
- /*
- * Check for pending SIGKILL! The new thread should not be allowed
- * to slip out of an OOM kill. (or normal SIGKILL.)
- */
- if (sigismember(&current->pending.signal, SIGKILL)) {
- write_unlock_irq(&tasklist_lock);
- retval = -EINTR;
- goto bad_fork_cleanup_namespace;
- }
-
/* CLONE_PARENT re-uses the old parent */
if (clone_flags & (CLONE_PARENT|CLONE_THREAD))
p->real_parent = current->real_parent;
@@ -1134,6 +1140,23 @@ static task_t *copy_process(unsigned long clone_flags,
p->parent = p->real_parent;
spin_lock(&current->sighand->siglock);
+
+ /*
+ * Process group and session signals need to be delivered to just the
+ * parent before the fork or both the parent and the child after the
+ * fork. Restart if a signal comes in before we add the new process to
+ * it's process group.
+ * A fatal signal pending means that current will exit, so the new
+ * thread can't slip out of an OOM kill (or normal SIGKILL).
+ */
+ recalc_sigpending();
+ if (signal_pending(current)) {
+ spin_unlock(&current->sighand->siglock);
+ write_unlock_irq(&tasklist_lock);
+ retval = -ERESTARTNOINTR;
+ goto bad_fork_cleanup_namespace;
+ }
+
if (clone_flags & CLONE_THREAD) {
/*
* Important: if an exit-all has been started then
@@ -1146,17 +1169,9 @@ static task_t *copy_process(unsigned long clone_flags,
retval = -EAGAIN;
goto bad_fork_cleanup_namespace;
}
- p->group_leader = current->group_leader;
- if (current->signal->group_stop_count > 0) {
- /*
- * There is an all-stop in progress for the group.
- * We ourselves will stop as soon as we check signals.
- * Make the new thread part of that group stop too.
- */
- current->signal->group_stop_count++;
- set_tsk_thread_flag(p, TIF_SIGPENDING);
- }
+ p->group_leader = current->group_leader;
+ list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
if (!cputime_eq(current->signal->it_virt_expires,
cputime_zero) ||
@@ -1179,23 +1194,25 @@ static task_t *copy_process(unsigned long clone_flags,
*/
p->ioprio = current->ioprio;
- SET_LINKS(p);
- if (unlikely(p->ptrace & PT_PTRACED))
- __ptrace_link(p, current->parent);
-
- if (thread_group_leader(p)) {
- p->signal->tty = current->signal->tty;
- p->signal->pgrp = process_group(current);
- p->signal->session = current->signal->session;
- attach_pid(p, PIDTYPE_PGID, process_group(p));
- attach_pid(p, PIDTYPE_SID, p->signal->session);
- if (p->pid)
+ if (likely(p->pid)) {
+ add_parent(p);
+ if (unlikely(p->ptrace & PT_PTRACED))
+ __ptrace_link(p, current->parent);
+
+ if (thread_group_leader(p)) {
+ p->signal->tty = current->signal->tty;
+ p->signal->pgrp = process_group(current);
+ p->signal->session = current->signal->session;
+ attach_pid(p, PIDTYPE_PGID, process_group(p));
+ attach_pid(p, PIDTYPE_SID, p->signal->session);
+
+ list_add_tail(&p->tasks, &init_task.tasks);
__get_cpu_var(process_counts)++;
+ }
+ attach_pid(p, PIDTYPE_PID, p->pid);
+ nr_threads++;
}
- attach_pid(p, PIDTYPE_TGID, p->tgid);
- attach_pid(p, PIDTYPE_PID, p->pid);
- nr_threads++;
total_forks++;
spin_unlock(&current->sighand->siglock);
write_unlock_irq(&tasklist_lock);
@@ -1210,9 +1227,9 @@ bad_fork_cleanup_mm:
if (p->mm)
mmput(p->mm);
bad_fork_cleanup_signal:
- exit_signal(p);
+ cleanup_signal(p);
bad_fork_cleanup_sighand:
- exit_sighand(p);
+ __cleanup_sighand(p->sighand);
bad_fork_cleanup_fs:
exit_fs(p); /* blocking */
bad_fork_cleanup_files:
@@ -1259,7 +1276,7 @@ task_t * __devinit fork_idle(int cpu)
if (!task)
return ERR_PTR(-ENOMEM);
init_idle(task, cpu);
- unhash_process(task);
+
return task;
}
@@ -1351,11 +1368,21 @@ long do_fork(unsigned long clone_flags,
#define ARCH_MIN_MMSTRUCT_ALIGN 0
#endif
+static void sighand_ctor(void *data, kmem_cache_t *cachep, unsigned long flags)
+{
+ struct sighand_struct *sighand = data;
+
+ if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR)
+ spin_lock_init(&sighand->siglock);
+}
+
void __init proc_caches_init(void)
{
sighand_cachep = kmem_cache_create("sighand_cache",
sizeof(struct sighand_struct), 0,
- SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+ SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_DESTROY_BY_RCU,
+ sighand_ctor, NULL);
signal_cachep = kmem_cache_create("signal_cache",
sizeof(struct signal_struct), 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
diff --git a/kernel/futex.c b/kernel/futex.c
index 5efa2f97803..9c9b2b6b22d 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -8,6 +8,10 @@
* Removed page pinning, fix privately mapped COW pages and other cleanups
* (C) Copyright 2003, 2004 Jamie Lokier
*
+ * Robust futex support started by Ingo Molnar
+ * (C) Copyright 2006 Red Hat Inc, All Rights Reserved
+ * Thanks to Thomas Gleixner for suggestions, analysis and fixes.
+ *
* Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly
* enough at me, Linus for the original (flawed) idea, Matthew
* Kirkwood for proof-of-concept implementation.
@@ -829,6 +833,172 @@ error:
goto out;
}
+/*
+ * Support for robust futexes: the kernel cleans up held futexes at
+ * thread exit time.
+ *
+ * Implementation: user-space maintains a per-thread list of locks it
+ * is holding. Upon do_exit(), the kernel carefully walks this list,
+ * and marks all locks that are owned by this thread with the
+ * FUTEX_OWNER_DEAD bit, and wakes up a waiter (if any). The list is
+ * always manipulated with the lock held, so the list is private and
+ * per-thread. Userspace also maintains a per-thread 'list_op_pending'
+ * field, to allow the kernel to clean up if the thread dies after
+ * acquiring the lock, but just before it could have added itself to
+ * the list. There can only be one such pending lock.
+ */
+
+/**
+ * sys_set_robust_list - set the robust-futex list head of a task
+ * @head: pointer to the list-head
+ * @len: length of the list-head, as userspace expects
+ */
+asmlinkage long
+sys_set_robust_list(struct robust_list_head __user *head,
+ size_t len)
+{
+ /*
+ * The kernel knows only one size for now:
+ */
+ if (unlikely(len != sizeof(*head)))
+ return -EINVAL;
+
+ current->robust_list = head;
+
+ return 0;
+}
+
+/**
+ * sys_get_robust_list - get the robust-futex list head of a task
+ * @pid: pid of the process [zero for current task]
+ * @head_ptr: pointer to a list-head pointer, the kernel fills it in
+ * @len_ptr: pointer to a length field, the kernel fills in the header size
+ */
+asmlinkage long
+sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr,
+ size_t __user *len_ptr)
+{
+ struct robust_list_head *head;
+ unsigned long ret;
+
+ if (!pid)
+ head = current->robust_list;
+ else {
+ struct task_struct *p;
+
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (!p)
+ goto err_unlock;
+ ret = -EPERM;
+ if ((current->euid != p->euid) && (current->euid != p->uid) &&
+ !capable(CAP_SYS_PTRACE))
+ goto err_unlock;
+ head = p->robust_list;
+ read_unlock(&tasklist_lock);
+ }
+
+ if (put_user(sizeof(*head), len_ptr))
+ return -EFAULT;
+ return put_user(head, head_ptr);
+
+err_unlock:
+ read_unlock(&tasklist_lock);
+
+ return ret;
+}
+
+/*
+ * Process a futex-list entry, check whether it's owned by the
+ * dying task, and do notification if so:
+ */
+int handle_futex_death(u32 __user *uaddr, struct task_struct *curr)
+{
+ u32 uval;
+
+retry:
+ if (get_user(uval, uaddr))
+ return -1;
+
+ if ((uval & FUTEX_TID_MASK) == curr->pid) {
+ /*
+ * Ok, this dying thread is truly holding a futex
+ * of interest. Set the OWNER_DIED bit atomically
+ * via cmpxchg, and if the value had FUTEX_WAITERS
+ * set, wake up a waiter (if any). (We have to do a
+ * futex_wake() even if OWNER_DIED is already set -
+ * to handle the rare but possible case of recursive
+ * thread-death.) The rest of the cleanup is done in
+ * userspace.
+ */
+ if (futex_atomic_cmpxchg_inatomic(uaddr, uval,
+ uval | FUTEX_OWNER_DIED) != uval)
+ goto retry;
+
+ if (uval & FUTEX_WAITERS)
+ futex_wake((unsigned long)uaddr, 1);
+ }
+ return 0;
+}
+
+/*
+ * Walk curr->robust_list (very carefully, it's a userspace list!)
+ * and mark any locks found there dead, and notify any waiters.
+ *
+ * We silently return on any sign of list-walking problem.
+ */
+void exit_robust_list(struct task_struct *curr)
+{
+ struct robust_list_head __user *head = curr->robust_list;
+ struct robust_list __user *entry, *pending;
+ unsigned int limit = ROBUST_LIST_LIMIT;
+ unsigned long futex_offset;
+
+ /*
+ * Fetch the list head (which was registered earlier, via
+ * sys_set_robust_list()):
+ */
+ if (get_user(entry, &head->list.next))
+ return;
+ /*
+ * Fetch the relative futex offset:
+ */
+ if (get_user(futex_offset, &head->futex_offset))
+ return;
+ /*
+ * Fetch any possibly pending lock-add first, and handle it
+ * if it exists:
+ */
+ if (get_user(pending, &head->list_op_pending))
+ return;
+ if (pending)
+ handle_futex_death((void *)pending + futex_offset, curr);
+
+ while (entry != &head->list) {
+ /*
+ * A pending lock might already be on the list, so
+ * dont process it twice:
+ */
+ if (entry != pending)
+ if (handle_futex_death((void *)entry + futex_offset,
+ curr))
+ return;
+ /*
+ * Fetch the next entry in the list:
+ */
+ if (get_user(entry, &entry->next))
+ return;
+ /*
+ * Avoid excessively long or circular lists:
+ */
+ if (!--limit)
+ break;
+
+ cond_resched();
+ }
+}
+
long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout,
unsigned long uaddr2, int val2, int val3)
{
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
new file mode 100644
index 00000000000..54274fc8532
--- /dev/null
+++ b/kernel/futex_compat.c
@@ -0,0 +1,142 @@
+/*
+ * linux/kernel/futex_compat.c
+ *
+ * Futex compatibililty routines.
+ *
+ * Copyright 2006, Red Hat, Inc., Ingo Molnar
+ */
+
+#include <linux/linkage.h>
+#include <linux/compat.h>
+#include <linux/futex.h>
+
+#include <asm/uaccess.h>
+
+/*
+ * Walk curr->robust_list (very carefully, it's a userspace list!)
+ * and mark any locks found there dead, and notify any waiters.
+ *
+ * We silently return on any sign of list-walking problem.
+ */
+void compat_exit_robust_list(struct task_struct *curr)
+{
+ struct compat_robust_list_head __user *head = curr->compat_robust_list;
+ struct robust_list __user *entry, *pending;
+ compat_uptr_t uentry, upending;
+ unsigned int limit = ROBUST_LIST_LIMIT;
+ compat_long_t futex_offset;
+
+ /*
+ * Fetch the list head (which was registered earlier, via
+ * sys_set_robust_list()):
+ */
+ if (get_user(uentry, &head->list.next))
+ return;
+ entry = compat_ptr(uentry);
+ /*
+ * Fetch the relative futex offset:
+ */
+ if (get_user(futex_offset, &head->futex_offset))
+ return;
+ /*
+ * Fetch any possibly pending lock-add first, and handle it
+ * if it exists:
+ */
+ if (get_user(upending, &head->list_op_pending))
+ return;
+ pending = compat_ptr(upending);
+ if (upending)
+ handle_futex_death((void *)pending + futex_offset, curr);
+
+ while (compat_ptr(uentry) != &head->list) {
+ /*
+ * A pending lock might already be on the list, so
+ * dont process it twice:
+ */
+ if (entry != pending)
+ if (handle_futex_death((void *)entry + futex_offset,
+ curr))
+ return;
+
+ /*
+ * Fetch the next entry in the list:
+ */
+ if (get_user(uentry, (compat_uptr_t *)&entry->next))
+ return;
+ entry = compat_ptr(uentry);
+ /*
+ * Avoid excessively long or circular lists:
+ */
+ if (!--limit)
+ break;
+
+ cond_resched();
+ }
+}
+
+asmlinkage long
+compat_sys_set_robust_list(struct compat_robust_list_head __user *head,
+ compat_size_t len)
+{
+ if (unlikely(len != sizeof(*head)))
+ return -EINVAL;
+
+ current->compat_robust_list = head;
+
+ return 0;
+}
+
+asmlinkage long
+compat_sys_get_robust_list(int pid, compat_uptr_t *head_ptr,
+ compat_size_t __user *len_ptr)
+{
+ struct compat_robust_list_head *head;
+ unsigned long ret;
+
+ if (!pid)
+ head = current->compat_robust_list;
+ else {
+ struct task_struct *p;
+
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (!p)
+ goto err_unlock;
+ ret = -EPERM;
+ if ((current->euid != p->euid) && (current->euid != p->uid) &&
+ !capable(CAP_SYS_PTRACE))
+ goto err_unlock;
+ head = p->compat_robust_list;
+ read_unlock(&tasklist_lock);
+ }
+
+ if (put_user(sizeof(*head), len_ptr))
+ return -EFAULT;
+ return put_user(ptr_to_compat(head), head_ptr);
+
+err_unlock:
+ read_unlock(&tasklist_lock);
+
+ return ret;
+}
+
+asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
+ struct compat_timespec __user *utime, u32 __user *uaddr2,
+ u32 val3)
+{
+ struct timespec t;
+ unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
+ int val2 = 0;
+
+ if ((op == FUTEX_WAIT) && utime) {
+ if (get_compat_timespec(&t, utime))
+ return -EFAULT;
+ timeout = timespec_to_jiffies(&t) + 1;
+ }
+ if (op >= FUTEX_REQUEUE)
+ val2 = (int) (unsigned long) utime;
+
+ return do_futex((unsigned long)uaddr, op, val, timeout,
+ (unsigned long)uaddr2, val2, val3);
+}
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 14bc9cfa639..0237a556eb1 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -123,6 +123,26 @@ void ktime_get_ts(struct timespec *ts)
EXPORT_SYMBOL_GPL(ktime_get_ts);
/*
+ * Get the coarse grained time at the softirq based on xtime and
+ * wall_to_monotonic.
+ */
+static void hrtimer_get_softirq_time(struct hrtimer_base *base)
+{
+ ktime_t xtim, tomono;
+ unsigned long seq;
+
+ do {
+ seq = read_seqbegin(&xtime_lock);
+ xtim = timespec_to_ktime(xtime);
+ tomono = timespec_to_ktime(wall_to_monotonic);
+
+ } while (read_seqretry(&xtime_lock, seq));
+
+ base[CLOCK_REALTIME].softirq_time = xtim;
+ base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono);
+}
+
+/*
* Functions and macros which are different for UP/SMP systems are kept in a
* single place
*/
@@ -246,7 +266,7 @@ ktime_t ktime_add_ns(const ktime_t kt, u64 nsec)
/*
* Divide a ktime value by a nanosecond value
*/
-static unsigned long ktime_divns(const ktime_t kt, nsec_t div)
+static unsigned long ktime_divns(const ktime_t kt, s64 div)
{
u64 dclc, inc, dns;
int sft = 0;
@@ -281,18 +301,17 @@ void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
* hrtimer_forward - forward the timer expiry
*
* @timer: hrtimer to forward
+ * @now: forward past this time
* @interval: the interval to forward
*
* Forward the timer expiry so it will expire in the future.
* Returns the number of overruns.
*/
unsigned long
-hrtimer_forward(struct hrtimer *timer, ktime_t interval)
+hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval)
{
unsigned long orun = 1;
- ktime_t delta, now;
-
- now = timer->base->get_time();
+ ktime_t delta;
delta = ktime_sub(now, timer->expires);
@@ -303,7 +322,7 @@ hrtimer_forward(struct hrtimer *timer, ktime_t interval)
interval.tv64 = timer->base->resolution.tv64;
if (unlikely(delta.tv64 >= interval.tv64)) {
- nsec_t incr = ktime_to_ns(interval);
+ s64 incr = ktime_to_ns(interval);
orun = ktime_divns(delta, incr);
timer->expires = ktime_add_ns(timer->expires, incr * orun);
@@ -355,8 +374,6 @@ static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
rb_link_node(&timer->node, parent, link);
rb_insert_color(&timer->node, &base->active);
- timer->state = HRTIMER_PENDING;
-
if (!base->first || timer->expires.tv64 <
rb_entry(base->first, struct hrtimer, node)->expires.tv64)
base->first = &timer->node;
@@ -376,6 +393,7 @@ static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
if (base->first == &timer->node)
base->first = rb_next(&timer->node);
rb_erase(&timer->node, &base->active);
+ timer->node.rb_parent = HRTIMER_INACTIVE;
}
/*
@@ -386,7 +404,6 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
{
if (hrtimer_active(timer)) {
__remove_hrtimer(timer, base);
- timer->state = HRTIMER_INACTIVE;
return 1;
}
return 0;
@@ -560,6 +577,7 @@ void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
clock_id = CLOCK_MONOTONIC;
timer->base = &bases[clock_id];
+ timer->node.rb_parent = HRTIMER_INACTIVE;
}
/**
@@ -586,48 +604,35 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
*/
static inline void run_hrtimer_queue(struct hrtimer_base *base)
{
- ktime_t now = base->get_time();
struct rb_node *node;
+ if (base->get_softirq_time)
+ base->softirq_time = base->get_softirq_time();
+
spin_lock_irq(&base->lock);
while ((node = base->first)) {
struct hrtimer *timer;
- int (*fn)(void *);
+ int (*fn)(struct hrtimer *);
int restart;
- void *data;
timer = rb_entry(node, struct hrtimer, node);
- if (now.tv64 <= timer->expires.tv64)
+ if (base->softirq_time.tv64 <= timer->expires.tv64)
break;
fn = timer->function;
- data = timer->data;
set_curr_timer(base, timer);
- timer->state = HRTIMER_RUNNING;
__remove_hrtimer(timer, base);
spin_unlock_irq(&base->lock);
- /*
- * fn == NULL is special case for the simplest timer
- * variant - wake up process and do not restart:
- */
- if (!fn) {
- wake_up_process(data);
- restart = HRTIMER_NORESTART;
- } else
- restart = fn(data);
+ restart = fn(timer);
spin_lock_irq(&base->lock);
- /* Another CPU has added back the timer */
- if (timer->state != HRTIMER_RUNNING)
- continue;
-
- if (restart == HRTIMER_RESTART)
+ if (restart != HRTIMER_NORESTART) {
+ BUG_ON(hrtimer_active(timer));
enqueue_hrtimer(timer, base);
- else
- timer->state = HRTIMER_EXPIRED;
+ }
}
set_curr_timer(base, NULL);
spin_unlock_irq(&base->lock);
@@ -641,6 +646,8 @@ void hrtimer_run_queues(void)
struct hrtimer_base *base = __get_cpu_var(hrtimer_bases);
int i;
+ hrtimer_get_softirq_time(base);
+
for (i = 0; i < MAX_HRTIMER_BASES; i++)
run_hrtimer_queue(&base[i]);
}
@@ -649,79 +656,70 @@ void hrtimer_run_queues(void)
* Sleep related functions:
*/
-/**
- * schedule_hrtimer - sleep until timeout
- *
- * @timer: hrtimer variable initialized with the correct clock base
- * @mode: timeout value is abs/rel
- *
- * Make the current task sleep until @timeout is
- * elapsed.
- *
- * You can set the task state as follows -
- *
- * %TASK_UNINTERRUPTIBLE - at least @timeout is guaranteed to
- * pass before the routine returns. The routine will return 0
- *
- * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
- * delivered to the current task. In this case the remaining time
- * will be returned
- *
- * The current task state is guaranteed to be TASK_RUNNING when this
- * routine returns.
- */
-static ktime_t __sched
-schedule_hrtimer(struct hrtimer *timer, const enum hrtimer_mode mode)
-{
- /* fn stays NULL, meaning single-shot wakeup: */
- timer->data = current;
+struct sleep_hrtimer {
+ struct hrtimer timer;
+ struct task_struct *task;
+ int expired;
+};
- hrtimer_start(timer, timer->expires, mode);
+static int nanosleep_wakeup(struct hrtimer *timer)
+{
+ struct sleep_hrtimer *t =
+ container_of(timer, struct sleep_hrtimer, timer);
- schedule();
- hrtimer_cancel(timer);
+ t->expired = 1;
+ wake_up_process(t->task);
- /* Return the remaining time: */
- if (timer->state != HRTIMER_EXPIRED)
- return ktime_sub(timer->expires, timer->base->get_time());
- else
- return (ktime_t) {.tv64 = 0 };
+ return HRTIMER_NORESTART;
}
-static inline ktime_t __sched
-schedule_hrtimer_interruptible(struct hrtimer *timer,
- const enum hrtimer_mode mode)
+static int __sched do_nanosleep(struct sleep_hrtimer *t, enum hrtimer_mode mode)
{
- set_current_state(TASK_INTERRUPTIBLE);
+ t->timer.function = nanosleep_wakeup;
+ t->task = current;
+ t->expired = 0;
+
+ do {
+ set_current_state(TASK_INTERRUPTIBLE);
+ hrtimer_start(&t->timer, t->timer.expires, mode);
+
+ schedule();
+
+ if (unlikely(!t->expired)) {
+ hrtimer_cancel(&t->timer);
+ mode = HRTIMER_ABS;
+ }
+ } while (!t->expired && !signal_pending(current));
- return schedule_hrtimer(timer, mode);
+ return t->expired;
}
static long __sched nanosleep_restart(struct restart_block *restart)
{
+ struct sleep_hrtimer t;
struct timespec __user *rmtp;
struct timespec tu;
- void *rfn_save = restart->fn;
- struct hrtimer timer;
- ktime_t rem;
+ ktime_t time;
restart->fn = do_no_restart_syscall;
- hrtimer_init(&timer, (clockid_t) restart->arg3, HRTIMER_ABS);
-
- timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0;
-
- rem = schedule_hrtimer_interruptible(&timer, HRTIMER_ABS);
+ hrtimer_init(&t.timer, restart->arg3, HRTIMER_ABS);
+ t.timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0;
- if (rem.tv64 <= 0)
+ if (do_nanosleep(&t, HRTIMER_ABS))
return 0;
rmtp = (struct timespec __user *) restart->arg2;
- tu = ktime_to_timespec(rem);
- if (rmtp && copy_to_user(rmtp, &tu, sizeof(tu)))
- return -EFAULT;
+ if (rmtp) {
+ time = ktime_sub(t.timer.expires, t.timer.base->get_time());
+ if (time.tv64 <= 0)
+ return 0;
+ tu = ktime_to_timespec(time);
+ if (copy_to_user(rmtp, &tu, sizeof(tu)))
+ return -EFAULT;
+ }
- restart->fn = rfn_save;
+ restart->fn = nanosleep_restart;
/* The other values in restart are already filled in */
return -ERESTART_RESTARTBLOCK;
@@ -731,33 +729,34 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
const enum hrtimer_mode mode, const clockid_t clockid)
{
struct restart_block *restart;
- struct hrtimer timer;
+ struct sleep_hrtimer t;
struct timespec tu;
ktime_t rem;
- hrtimer_init(&timer, clockid, mode);
-
- timer.expires = timespec_to_ktime(*rqtp);
-
- rem = schedule_hrtimer_interruptible(&timer, mode);
- if (rem.tv64 <= 0)
+ hrtimer_init(&t.timer, clockid, mode);
+ t.timer.expires = timespec_to_ktime(*rqtp);
+ if (do_nanosleep(&t, mode))
return 0;
/* Absolute timers do not update the rmtp value and restart: */
if (mode == HRTIMER_ABS)
return -ERESTARTNOHAND;
- tu = ktime_to_timespec(rem);
-
- if (rmtp && copy_to_user(rmtp, &tu, sizeof(tu)))
- return -EFAULT;
+ if (rmtp) {
+ rem = ktime_sub(t.timer.expires, t.timer.base->get_time());
+ if (rem.tv64 <= 0)
+ return 0;
+ tu = ktime_to_timespec(rem);
+ if (copy_to_user(rmtp, &tu, sizeof(tu)))
+ return -EFAULT;
+ }
restart = &current_thread_info()->restart_block;
restart->fn = nanosleep_restart;
- restart->arg0 = timer.expires.tv64 & 0xFFFFFFFF;
- restart->arg1 = timer.expires.tv64 >> 32;
+ restart->arg0 = t.timer.expires.tv64 & 0xFFFFFFFF;
+ restart->arg1 = t.timer.expires.tv64 >> 32;
restart->arg2 = (unsigned long) rmtp;
- restart->arg3 = (unsigned long) timer.base->index;
+ restart->arg3 = (unsigned long) t.timer.base->index;
return -ERESTART_RESTARTBLOCK;
}
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 49378738ff5..2b33f852be3 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -1,5 +1,4 @@
-obj-y := handle.o manage.o spurious.o
+obj-y := handle.o manage.o spurious.o migration.o
obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
obj-$(CONFIG_PROC_FS) += proc.o
-
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 97d5559997d..ac766ad573e 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -204,10 +204,14 @@ int setup_irq(unsigned int irq, struct irqaction * new)
p = &desc->action;
if ((old = *p) != NULL) {
/* Can't share interrupts unless both agree to */
- if (!(old->flags & new->flags & SA_SHIRQ)) {
- spin_unlock_irqrestore(&desc->lock,flags);
- return -EBUSY;
- }
+ if (!(old->flags & new->flags & SA_SHIRQ))
+ goto mismatch;
+
+#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ)
+ /* All handlers must agree on per-cpuness */
+ if ((old->flags & IRQ_PER_CPU) != (new->flags & IRQ_PER_CPU))
+ goto mismatch;
+#endif
/* add new interrupt at end of irq queue */
do {
@@ -218,7 +222,10 @@ int setup_irq(unsigned int irq, struct irqaction * new)
}
*p = new;
-
+#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ)
+ if (new->flags & SA_PERCPU_IRQ)
+ desc->status |= IRQ_PER_CPU;
+#endif
if (!shared) {
desc->depth = 0;
desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT |
@@ -236,6 +243,12 @@ int setup_irq(unsigned int irq, struct irqaction * new)
register_handler_proc(irq, new);
return 0;
+
+mismatch:
+ spin_unlock_irqrestore(&desc->lock, flags);
+ printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__);
+ dump_stack();
+ return -EBUSY;
}
/**
@@ -258,6 +271,7 @@ void free_irq(unsigned int irq, void *dev_id)
struct irqaction **p;
unsigned long flags;
+ WARN_ON(in_interrupt());
if (irq >= NR_IRQS)
return;
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
new file mode 100644
index 00000000000..52a8655fa08
--- /dev/null
+++ b/kernel/irq/migration.c
@@ -0,0 +1,65 @@
+#include <linux/irq.h>
+
+#if defined(CONFIG_GENERIC_PENDING_IRQ)
+
+void set_pending_irq(unsigned int irq, cpumask_t mask)
+{
+ irq_desc_t *desc = irq_desc + irq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ desc->move_irq = 1;
+ pending_irq_cpumask[irq] = mask;
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+void move_native_irq(int irq)
+{
+ cpumask_t tmp;
+ irq_desc_t *desc = irq_descp(irq);
+
+ if (likely(!desc->move_irq))
+ return;
+
+ /*
+ * Paranoia: cpu-local interrupts shouldn't be calling in here anyway.
+ */
+ if (CHECK_IRQ_PER_CPU(desc->status)) {
+ WARN_ON(1);
+ return;
+ }
+
+ desc->move_irq = 0;
+
+ if (likely(cpus_empty(pending_irq_cpumask[irq])))
+ return;
+
+ if (!desc->handler->set_affinity)
+ return;
+
+ assert_spin_locked(&desc->lock);
+
+ cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
+
+ /*
+ * If there was a valid mask to work with, please
+ * do the disable, re-program, enable sequence.
+ * This is *not* particularly important for level triggered
+ * but in a edge trigger case, we might be setting rte
+ * when an active trigger is comming in. This could
+ * cause some ioapics to mal-function.
+ * Being paranoid i guess!
+ */
+ if (unlikely(!cpus_empty(tmp))) {
+ if (likely(!(desc->status & IRQ_DISABLED)))
+ desc->handler->disable(irq);
+
+ desc->handler->set_affinity(irq,tmp);
+
+ if (likely(!(desc->status & IRQ_DISABLED)))
+ desc->handler->enable(irq);
+ }
+ cpus_clear(pending_irq_cpumask[irq]);
+}
+
+#endif
diff --git a/kernel/itimer.c b/kernel/itimer.c
index 379be2f8c84..204ed7939e7 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -128,21 +128,75 @@ asmlinkage long sys_getitimer(int which, struct itimerval __user *value)
/*
* The timer is automagically restarted, when interval != 0
*/
-int it_real_fn(void *data)
+int it_real_fn(struct hrtimer *timer)
{
- struct task_struct *tsk = (struct task_struct *) data;
+ struct signal_struct *sig =
+ container_of(timer, struct signal_struct, real_timer);
- send_group_sig_info(SIGALRM, SEND_SIG_PRIV, tsk);
-
- if (tsk->signal->it_real_incr.tv64 != 0) {
- hrtimer_forward(&tsk->signal->real_timer,
- tsk->signal->it_real_incr);
+ send_group_sig_info(SIGALRM, SEND_SIG_PRIV, sig->tsk);
+ if (sig->it_real_incr.tv64 != 0) {
+ hrtimer_forward(timer, timer->base->softirq_time,
+ sig->it_real_incr);
return HRTIMER_RESTART;
}
return HRTIMER_NORESTART;
}
+/*
+ * We do not care about correctness. We just sanitize the values so
+ * the ktime_t operations which expect normalized values do not
+ * break. This converts negative values to long timeouts similar to
+ * the code in kernel versions < 2.6.16
+ *
+ * Print a limited number of warning messages when an invalid timeval
+ * is detected.
+ */
+static void fixup_timeval(struct timeval *tv, int interval)
+{
+ static int warnlimit = 10;
+ unsigned long tmp;
+
+ if (warnlimit > 0) {
+ warnlimit--;
+ printk(KERN_WARNING
+ "setitimer: %s (pid = %d) provided "
+ "invalid timeval %s: tv_sec = %ld tv_usec = %ld\n",
+ current->comm, current->pid,
+ interval ? "it_interval" : "it_value",
+ tv->tv_sec, (long) tv->tv_usec);
+ }
+
+ tmp = tv->tv_usec;
+ if (tmp >= USEC_PER_SEC) {
+ tv->tv_usec = tmp % USEC_PER_SEC;
+ tv->tv_sec += tmp / USEC_PER_SEC;
+ }
+
+ tmp = tv->tv_sec;
+ if (tmp > LONG_MAX)
+ tv->tv_sec = LONG_MAX;
+}
+
+/*
+ * Returns true if the timeval is in canonical form
+ */
+#define timeval_valid(t) \
+ (((t)->tv_sec >= 0) && (((unsigned long) (t)->tv_usec) < USEC_PER_SEC))
+
+/*
+ * Check for invalid timevals, sanitize them and print a limited
+ * number of warnings.
+ */
+static void check_itimerval(struct itimerval *value) {
+
+ if (unlikely(!timeval_valid(&value->it_value)))
+ fixup_timeval(&value->it_value, 0);
+
+ if (unlikely(!timeval_valid(&value->it_interval)))
+ fixup_timeval(&value->it_interval, 1);
+}
+
int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
{
struct task_struct *tsk = current;
@@ -150,6 +204,18 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
ktime_t expires;
cputime_t cval, cinterval, nval, ninterval;
+ /*
+ * Validate the timevals in value.
+ *
+ * Note: Although the spec requires that invalid values shall
+ * return -EINVAL, we just fixup the value and print a limited
+ * number of warnings in order not to break users of this
+ * historical misfeature.
+ *
+ * Scheduled for replacement in March 2007
+ */
+ check_itimerval(value);
+
switch (which) {
case ITIMER_REAL:
again:
@@ -226,6 +292,43 @@ again:
return 0;
}
+/**
+ * alarm_setitimer - set alarm in seconds
+ *
+ * @seconds: number of seconds until alarm
+ * 0 disables the alarm
+ *
+ * Returns the remaining time in seconds of a pending timer or 0 when
+ * the timer is not active.
+ *
+ * On 32 bit machines the seconds value is limited to (INT_MAX/2) to avoid
+ * negative timeval settings which would cause immediate expiry.
+ */
+unsigned int alarm_setitimer(unsigned int seconds)
+{
+ struct itimerval it_new, it_old;
+
+#if BITS_PER_LONG < 64
+ if (seconds > INT_MAX)
+ seconds = INT_MAX;
+#endif
+ it_new.it_value.tv_sec = seconds;
+ it_new.it_value.tv_usec = 0;
+ it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
+
+ do_setitimer(ITIMER_REAL, &it_new, &it_old);
+
+ /*
+ * We can't return 0 if we have an alarm pending ... And we'd
+ * better return too much than too little anyway
+ */
+ if ((!it_old.it_value.tv_sec && it_old.it_value.tv_usec) ||
+ it_old.it_value.tv_usec >= 500000)
+ it_old.it_value.tv_sec++;
+
+ return it_old.it_value.tv_sec;
+}
+
asmlinkage long sys_setitimer(int which,
struct itimerval __user *value,
struct itimerval __user *ovalue)
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 51a892063aa..20a997c73c3 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -170,7 +170,7 @@ static int wait_for_helper(void *data)
sa.sa.sa_handler = SIG_IGN;
sa.sa.sa_flags = 0;
siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD));
- do_sigaction(SIGCHLD, &sa, (struct k_sigaction *)0);
+ do_sigaction(SIGCHLD, &sa, NULL);
allow_signal(SIGCHLD);
pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD);
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 1fb9f753ef6..1156eb0977d 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -323,10 +323,10 @@ struct hlist_head __kprobes *kretprobe_inst_table_head(struct task_struct *tsk)
}
/*
- * This function is called from exit_thread or flush_thread when task tk's
- * stack is being recycled so that we can recycle any function-return probe
- * instances associated with this task. These left over instances represent
- * probed functions that have been called but will never return.
+ * This function is called from finish_task_switch when task tk becomes dead,
+ * so that we can recycle any function-return probe instances associated
+ * with this task. These left over instances represent probed functions
+ * that have been called but will never return.
*/
void __kprobes kprobe_flush_task(struct task_struct *tk)
{
@@ -336,7 +336,7 @@ void __kprobes kprobe_flush_task(struct task_struct *tk)
unsigned long flags = 0;
spin_lock_irqsave(&kretprobe_lock, flags);
- head = kretprobe_inst_table_head(current);
+ head = kretprobe_inst_table_head(tk);
hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
if (ri->task == tk)
recycle_rp_inst(ri);
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 6a5373868a9..c5f3c6613b6 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -115,7 +115,9 @@ static void keventd_create_kthread(void *_create)
create->result = ERR_PTR(pid);
} else {
wait_for_completion(&create->started);
+ read_lock(&tasklist_lock);
create->result = find_task_by_pid(pid);
+ read_unlock(&tasklist_lock);
}
complete(&create->done);
}
diff --git a/kernel/module.c b/kernel/module.c
index 54623c714bb..bd088a7c149 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -64,26 +64,17 @@ static DEFINE_SPINLOCK(modlist_lock);
static DEFINE_MUTEX(module_mutex);
static LIST_HEAD(modules);
-static DEFINE_MUTEX(notify_mutex);
-static struct notifier_block * module_notify_list;
+static BLOCKING_NOTIFIER_HEAD(module_notify_list);
int register_module_notifier(struct notifier_block * nb)
{
- int err;
- mutex_lock(&notify_mutex);
- err = notifier_chain_register(&module_notify_list, nb);
- mutex_unlock(&notify_mutex);
- return err;
+ return blocking_notifier_chain_register(&module_notify_list, nb);
}
EXPORT_SYMBOL(register_module_notifier);
int unregister_module_notifier(struct notifier_block * nb)
{
- int err;
- mutex_lock(&notify_mutex);
- err = notifier_chain_unregister(&module_notify_list, nb);
- mutex_unlock(&notify_mutex);
- return err;
+ return blocking_notifier_chain_unregister(&module_notify_list, nb);
}
EXPORT_SYMBOL(unregister_module_notifier);
@@ -136,7 +127,7 @@ extern const unsigned long __start___kcrctab_gpl_future[];
#ifndef CONFIG_MODVERSIONS
#define symversion(base, idx) NULL
#else
-#define symversion(base, idx) ((base) ? ((base) + (idx)) : NULL)
+#define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL)
#endif
/* lookup symbol in given range of kernel_symbols */
@@ -233,24 +224,6 @@ static unsigned long __find_symbol(const char *name,
return 0;
}
-/* Find a symbol in this elf symbol table */
-static unsigned long find_local_symbol(Elf_Shdr *sechdrs,
- unsigned int symindex,
- const char *strtab,
- const char *name)
-{
- unsigned int i;
- Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
-
- /* Search (defined) internal symbols first. */
- for (i = 1; i < sechdrs[symindex].sh_size/sizeof(*sym); i++) {
- if (sym[i].st_shndx != SHN_UNDEF
- && strcmp(name, strtab + sym[i].st_name) == 0)
- return sym[i].st_value;
- }
- return 0;
-}
-
/* Search for module by name: must hold module_mutex. */
static struct module *find_module(const char *name)
{
@@ -785,139 +758,6 @@ static struct module_attribute *modinfo_attrs[] = {
NULL,
};
-#ifdef CONFIG_OBSOLETE_MODPARM
-/* Bounds checking done below */
-static int obsparm_copy_string(const char *val, struct kernel_param *kp)
-{
- strcpy(kp->arg, val);
- return 0;
-}
-
-static int set_obsolete(const char *val, struct kernel_param *kp)
-{
- unsigned int min, max;
- unsigned int size, maxsize;
- int dummy;
- char *endp;
- const char *p;
- struct obsolete_modparm *obsparm = kp->arg;
-
- if (!val) {
- printk(KERN_ERR "Parameter %s needs an argument\n", kp->name);
- return -EINVAL;
- }
-
- /* type is: [min[-max]]{b,h,i,l,s} */
- p = obsparm->type;
- min = simple_strtol(p, &endp, 10);
- if (endp == obsparm->type)
- min = max = 1;
- else if (*endp == '-') {
- p = endp+1;
- max = simple_strtol(p, &endp, 10);
- } else
- max = min;
- switch (*endp) {
- case 'b':
- return param_array(kp->name, val, min, max, obsparm->addr,
- 1, param_set_byte, &dummy);
- case 'h':
- return param_array(kp->name, val, min, max, obsparm->addr,
- sizeof(short), param_set_short, &dummy);
- case 'i':
- return param_array(kp->name, val, min, max, obsparm->addr,
- sizeof(int), param_set_int, &dummy);
- case 'l':
- return param_array(kp->name, val, min, max, obsparm->addr,
- sizeof(long), param_set_long, &dummy);
- case 's':
- return param_array(kp->name, val, min, max, obsparm->addr,
- sizeof(char *), param_set_charp, &dummy);
-
- case 'c':
- /* Undocumented: 1-5c50 means 1-5 strings of up to 49 chars,
- and the decl is "char xxx[5][50];" */
- p = endp+1;
- maxsize = simple_strtol(p, &endp, 10);
- /* We check lengths here (yes, this is a hack). */
- p = val;
- while (p[size = strcspn(p, ",")]) {
- if (size >= maxsize)
- goto oversize;
- p += size+1;
- }
- if (size >= maxsize)
- goto oversize;
- return param_array(kp->name, val, min, max, obsparm->addr,
- maxsize, obsparm_copy_string, &dummy);
- }
- printk(KERN_ERR "Unknown obsolete parameter type %s\n", obsparm->type);
- return -EINVAL;
- oversize:
- printk(KERN_ERR
- "Parameter %s doesn't fit in %u chars.\n", kp->name, maxsize);
- return -EINVAL;
-}
-
-static int obsolete_params(const char *name,
- char *args,
- struct obsolete_modparm obsparm[],
- unsigned int num,
- Elf_Shdr *sechdrs,
- unsigned int symindex,
- const char *strtab)
-{
- struct kernel_param *kp;
- unsigned int i;
- int ret;
-
- kp = kmalloc(sizeof(kp[0]) * num, GFP_KERNEL);
- if (!kp)
- return -ENOMEM;
-
- for (i = 0; i < num; i++) {
- char sym_name[128 + sizeof(MODULE_SYMBOL_PREFIX)];
-
- snprintf(sym_name, sizeof(sym_name), "%s%s",
- MODULE_SYMBOL_PREFIX, obsparm[i].name);
-
- kp[i].name = obsparm[i].name;
- kp[i].perm = 000;
- kp[i].set = set_obsolete;
- kp[i].get = NULL;
- obsparm[i].addr
- = (void *)find_local_symbol(sechdrs, symindex, strtab,
- sym_name);
- if (!obsparm[i].addr) {
- printk("%s: falsely claims to have parameter %s\n",
- name, obsparm[i].name);
- ret = -EINVAL;
- goto out;
- }
- kp[i].arg = &obsparm[i];
- }
-
- ret = parse_args(name, args, kp, num, NULL);
- out:
- kfree(kp);
- return ret;
-}
-#else
-static int obsolete_params(const char *name,
- char *args,
- struct obsolete_modparm obsparm[],
- unsigned int num,
- Elf_Shdr *sechdrs,
- unsigned int symindex,
- const char *strtab)
-{
- if (num != 0)
- printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",
- name);
- return 0;
-}
-#endif /* CONFIG_OBSOLETE_MODPARM */
-
static const char vermagic[] = VERMAGIC_STRING;
#ifdef CONFIG_MODVERSIONS
@@ -1874,27 +1714,17 @@ static struct module *load_module(void __user *umod,
set_fs(old_fs);
mod->args = args;
- if (obsparmindex) {
- err = obsolete_params(mod->name, mod->args,
- (struct obsolete_modparm *)
- sechdrs[obsparmindex].sh_addr,
- sechdrs[obsparmindex].sh_size
- / sizeof(struct obsolete_modparm),
- sechdrs, symindex,
- (char *)sechdrs[strindex].sh_addr);
- if (setupindex)
- printk(KERN_WARNING "%s: Ignoring new-style "
- "parameters in presence of obsolete ones\n",
- mod->name);
- } else {
- /* Size of section 0 is 0, so this works well if no params */
- err = parse_args(mod->name, mod->args,
- (struct kernel_param *)
- sechdrs[setupindex].sh_addr,
- sechdrs[setupindex].sh_size
- / sizeof(struct kernel_param),
- NULL);
- }
+ if (obsparmindex)
+ printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",
+ mod->name);
+
+ /* Size of section 0 is 0, so this works well if no params */
+ err = parse_args(mod->name, mod->args,
+ (struct kernel_param *)
+ sechdrs[setupindex].sh_addr,
+ sechdrs[setupindex].sh_size
+ / sizeof(struct kernel_param),
+ NULL);
if (err < 0)
goto arch_cleanup;
@@ -1977,9 +1807,8 @@ sys_init_module(void __user *umod,
/* Drop lock so they can recurse */
mutex_unlock(&module_mutex);
- mutex_lock(&notify_mutex);
- notifier_call_chain(&module_notify_list, MODULE_STATE_COMING, mod);
- mutex_unlock(&notify_mutex);
+ blocking_notifier_call_chain(&module_notify_list,
+ MODULE_STATE_COMING, mod);
/* Start the module */
if (mod->init != NULL)
diff --git a/kernel/panic.c b/kernel/panic.c
index acd95adddb9..f895c7c01d5 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -29,7 +29,7 @@ static DEFINE_SPINLOCK(pause_on_oops_lock);
int panic_timeout;
EXPORT_SYMBOL(panic_timeout);
-struct notifier_block *panic_notifier_list;
+ATOMIC_NOTIFIER_HEAD(panic_notifier_list);
EXPORT_SYMBOL(panic_notifier_list);
@@ -97,7 +97,7 @@ NORET_TYPE void panic(const char * fmt, ...)
smp_send_stop();
#endif
- notifier_call_chain(&panic_notifier_list, 0, buf);
+ atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
if (!panic_blink)
panic_blink = no_blink;
diff --git a/kernel/params.c b/kernel/params.c
index a2915058231..af43ecdc8d9 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -31,7 +31,7 @@
#define DEBUGP(fmt, a...)
#endif
-static inline int dash2underscore(char c)
+static inline char dash2underscore(char c)
{
if (c == '-')
return '_';
@@ -265,12 +265,12 @@ int param_get_invbool(char *buffer, struct kernel_param *kp)
}
/* We cheat here and temporarily mangle the string. */
-int param_array(const char *name,
- const char *val,
- unsigned int min, unsigned int max,
- void *elem, int elemsize,
- int (*set)(const char *, struct kernel_param *kp),
- int *num)
+static int param_array(const char *name,
+ const char *val,
+ unsigned int min, unsigned int max,
+ void *elem, int elemsize,
+ int (*set)(const char *, struct kernel_param *kp),
+ int *num)
{
int ret;
struct kernel_param kp;
diff --git a/kernel/pid.c b/kernel/pid.c
index 1acc0724699..a9f2dfd006d 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -218,36 +218,6 @@ task_t *find_task_by_pid_type(int type, int nr)
EXPORT_SYMBOL(find_task_by_pid_type);
/*
- * This function switches the PIDs if a non-leader thread calls
- * sys_execve() - this must be done without releasing the PID.
- * (which a detach_pid() would eventually do.)
- */
-void switch_exec_pids(task_t *leader, task_t *thread)
-{
- __detach_pid(leader, PIDTYPE_PID);
- __detach_pid(leader, PIDTYPE_TGID);
- __detach_pid(leader, PIDTYPE_PGID);
- __detach_pid(leader, PIDTYPE_SID);
-
- __detach_pid(thread, PIDTYPE_PID);
- __detach_pid(thread, PIDTYPE_TGID);
-
- leader->pid = leader->tgid = thread->pid;
- thread->pid = thread->tgid;
-
- attach_pid(thread, PIDTYPE_PID, thread->pid);
- attach_pid(thread, PIDTYPE_TGID, thread->tgid);
- attach_pid(thread, PIDTYPE_PGID, thread->signal->pgrp);
- attach_pid(thread, PIDTYPE_SID, thread->signal->session);
- list_add_tail(&thread->tasks, &init_task.tasks);
-
- attach_pid(leader, PIDTYPE_PID, leader->pid);
- attach_pid(leader, PIDTYPE_TGID, leader->tgid);
- attach_pid(leader, PIDTYPE_PGID, leader->signal->pgrp);
- attach_pid(leader, PIDTYPE_SID, leader->signal->session);
-}
-
-/*
* The pid hash table is scaled according to the amount of memory in the
* machine. From a minimum of 16 slots up to 4096 slots at one gigabyte or
* more.
@@ -277,16 +247,8 @@ void __init pidhash_init(void)
void __init pidmap_init(void)
{
- int i;
-
pidmap_array->page = (void *)get_zeroed_page(GFP_KERNEL);
+ /* Reserve PID 0. We never call free_pidmap(0) */
set_bit(0, pidmap_array->page);
atomic_dec(&pidmap_array->nr_free);
-
- /*
- * Allocate PID 0, and hash it via all PID types:
- */
-
- for (i = 0; i < PIDTYPE_MAX; i++)
- attach_pid(current, i, 0);
}
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 9944379360b..ac6dc874442 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -145,7 +145,7 @@ static int common_timer_set(struct k_itimer *, int,
struct itimerspec *, struct itimerspec *);
static int common_timer_del(struct k_itimer *timer);
-static int posix_timer_fn(void *data);
+static int posix_timer_fn(struct hrtimer *data);
static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);
@@ -251,15 +251,18 @@ __initcall(init_posix_timers);
static void schedule_next_timer(struct k_itimer *timr)
{
+ struct hrtimer *timer = &timr->it.real.timer;
+
if (timr->it.real.interval.tv64 == 0)
return;
- timr->it_overrun += hrtimer_forward(&timr->it.real.timer,
+ timr->it_overrun += hrtimer_forward(timer, timer->base->get_time(),
timr->it.real.interval);
+
timr->it_overrun_last = timr->it_overrun;
timr->it_overrun = -1;
++timr->it_requeue_pending;
- hrtimer_restart(&timr->it.real.timer);
+ hrtimer_restart(timer);
}
/*
@@ -331,13 +334,14 @@ EXPORT_SYMBOL_GPL(posix_timer_event);
* This code is for CLOCK_REALTIME* and CLOCK_MONOTONIC* timers.
*/
-static int posix_timer_fn(void *data)
+static int posix_timer_fn(struct hrtimer *timer)
{
- struct k_itimer *timr = data;
+ struct k_itimer *timr;
unsigned long flags;
int si_private = 0;
int ret = HRTIMER_NORESTART;
+ timr = container_of(timer, struct k_itimer, it.real.timer);
spin_lock_irqsave(&timr->it_lock, flags);
if (timr->it.real.interval.tv64 != 0)
@@ -351,7 +355,8 @@ static int posix_timer_fn(void *data)
*/
if (timr->it.real.interval.tv64 != 0) {
timr->it_overrun +=
- hrtimer_forward(&timr->it.real.timer,
+ hrtimer_forward(timer,
+ timer->base->softirq_time,
timr->it.real.interval);
ret = HRTIMER_RESTART;
++timr->it_requeue_pending;
@@ -603,38 +608,41 @@ static struct k_itimer * lock_timer(timer_t timer_id, unsigned long *flags)
static void
common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
{
- ktime_t remaining;
+ ktime_t now, remaining, iv;
struct hrtimer *timer = &timr->it.real.timer;
memset(cur_setting, 0, sizeof(struct itimerspec));
- remaining = hrtimer_get_remaining(timer);
- /* Time left ? or timer pending */
- if (remaining.tv64 > 0 || hrtimer_active(timer))
- goto calci;
+ iv = timr->it.real.interval;
+
/* interval timer ? */
- if (timr->it.real.interval.tv64 == 0)
+ if (iv.tv64)
+ cur_setting->it_interval = ktime_to_timespec(iv);
+ else if (!hrtimer_active(timer) &&
+ (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
return;
+
+ now = timer->base->get_time();
+
/*
- * When a requeue is pending or this is a SIGEV_NONE timer
- * move the expiry time forward by intervals, so expiry is >
- * now.
+ * When a requeue is pending or this is a SIGEV_NONE
+ * timer move the expiry time forward by intervals, so
+ * expiry is > now.
*/
- if (timr->it_requeue_pending & REQUEUE_PENDING ||
- (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) {
- timr->it_overrun +=
- hrtimer_forward(timer, timr->it.real.interval);
- remaining = hrtimer_get_remaining(timer);
- }
- calci:
- /* interval timer ? */
- if (timr->it.real.interval.tv64 != 0)
- cur_setting->it_interval =
- ktime_to_timespec(timr->it.real.interval);
+ if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING ||
+ (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
+ timr->it_overrun += hrtimer_forward(timer, now, iv);
+
+ remaining = ktime_sub(timer->expires, now);
/* Return 0 only, when the timer is expired and not pending */
- if (remaining.tv64 <= 0)
- cur_setting->it_value.tv_nsec = 1;
- else
+ if (remaining.tv64 <= 0) {
+ /*
+ * A single shot SIGEV_NONE timer must return 0, when
+ * it is expired !
+ */
+ if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
+ cur_setting->it_value.tv_nsec = 1;
+ } else
cur_setting->it_value = ktime_to_timespec(remaining);
}
@@ -717,7 +725,6 @@ common_timer_set(struct k_itimer *timr, int flags,
mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL;
hrtimer_init(&timr->it.real.timer, timr->it_clock, mode);
- timr->it.real.timer.data = timr;
timr->it.real.timer.function = posix_timer_fn;
timer->expires = timespec_to_ktime(new_setting->it_value);
diff --git a/kernel/power/smp.c b/kernel/power/smp.c
index 911fc62b822..5957312b2d6 100644
--- a/kernel/power/smp.c
+++ b/kernel/power/smp.c
@@ -49,9 +49,7 @@ void enable_nonboot_cpus(void)
printk("Thawing cpus ...\n");
for_each_cpu_mask(cpu, frozen_cpus) {
- error = smp_prepare_cpu(cpu);
- if (!error)
- error = cpu_up(cpu);
+ error = cpu_up(cpu);
if (!error) {
printk("CPU%d is up\n", cpu);
continue;
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 9177f3f73a6..044b8e0c102 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -454,10 +454,11 @@ static int load_image(struct swap_map_handle *handle,
nr_pages++;
}
} while (ret > 0);
- if (!error)
+ if (!error) {
printk("\b\b\b\bdone\n");
- if (!snapshot_image_loaded(snapshot))
- error = -ENODATA;
+ if (!snapshot_image_loaded(snapshot))
+ error = -ENODATA;
+ }
return error;
}
diff --git a/kernel/profile.c b/kernel/profile.c
index ad81f799a9b..5a730fdb1a2 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -87,72 +87,52 @@ void __init profile_init(void)
#ifdef CONFIG_PROFILING
-static DECLARE_RWSEM(profile_rwsem);
-static DEFINE_RWLOCK(handoff_lock);
-static struct notifier_block * task_exit_notifier;
-static struct notifier_block * task_free_notifier;
-static struct notifier_block * munmap_notifier;
+static BLOCKING_NOTIFIER_HEAD(task_exit_notifier);
+static ATOMIC_NOTIFIER_HEAD(task_free_notifier);
+static BLOCKING_NOTIFIER_HEAD(munmap_notifier);
void profile_task_exit(struct task_struct * task)
{
- down_read(&profile_rwsem);
- notifier_call_chain(&task_exit_notifier, 0, task);
- up_read(&profile_rwsem);
+ blocking_notifier_call_chain(&task_exit_notifier, 0, task);
}
int profile_handoff_task(struct task_struct * task)
{
int ret;
- read_lock(&handoff_lock);
- ret = notifier_call_chain(&task_free_notifier, 0, task);
- read_unlock(&handoff_lock);
+ ret = atomic_notifier_call_chain(&task_free_notifier, 0, task);
return (ret == NOTIFY_OK) ? 1 : 0;
}
void profile_munmap(unsigned long addr)
{
- down_read(&profile_rwsem);
- notifier_call_chain(&munmap_notifier, 0, (void *)addr);
- up_read(&profile_rwsem);
+ blocking_notifier_call_chain(&munmap_notifier, 0, (void *)addr);
}
int task_handoff_register(struct notifier_block * n)
{
- int err = -EINVAL;
-
- write_lock(&handoff_lock);
- err = notifier_chain_register(&task_free_notifier, n);
- write_unlock(&handoff_lock);
- return err;
+ return atomic_notifier_chain_register(&task_free_notifier, n);
}
int task_handoff_unregister(struct notifier_block * n)
{
- int err = -EINVAL;
-
- write_lock(&handoff_lock);
- err = notifier_chain_unregister(&task_free_notifier, n);
- write_unlock(&handoff_lock);
- return err;
+ return atomic_notifier_chain_unregister(&task_free_notifier, n);
}
int profile_event_register(enum profile_type type, struct notifier_block * n)
{
int err = -EINVAL;
- down_write(&profile_rwsem);
-
switch (type) {
case PROFILE_TASK_EXIT:
- err = notifier_chain_register(&task_exit_notifier, n);
+ err = blocking_notifier_chain_register(
+ &task_exit_notifier, n);
break;
case PROFILE_MUNMAP:
- err = notifier_chain_register(&munmap_notifier, n);
+ err = blocking_notifier_chain_register(
+ &munmap_notifier, n);
break;
}
- up_write(&profile_rwsem);
-
return err;
}
@@ -161,18 +141,17 @@ int profile_event_unregister(enum profile_type type, struct notifier_block * n)
{
int err = -EINVAL;
- down_write(&profile_rwsem);
-
switch (type) {
case PROFILE_TASK_EXIT:
- err = notifier_chain_unregister(&task_exit_notifier, n);
+ err = blocking_notifier_chain_unregister(
+ &task_exit_notifier, n);
break;
case PROFILE_MUNMAP:
- err = notifier_chain_unregister(&munmap_notifier, n);
+ err = blocking_notifier_chain_unregister(
+ &munmap_notifier, n);
break;
}
- up_write(&profile_rwsem);
return err;
}
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index d95a72c9279..86a7f6c60cb 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -35,9 +35,9 @@ void __ptrace_link(task_t *child, task_t *new_parent)
if (child->parent == new_parent)
return;
list_add(&child->ptrace_list, &child->parent->ptrace_children);
- REMOVE_LINKS(child);
+ remove_parent(child);
child->parent = new_parent;
- SET_LINKS(child);
+ add_parent(child);
}
/*
@@ -77,9 +77,9 @@ void __ptrace_unlink(task_t *child)
child->ptrace = 0;
if (!list_empty(&child->ptrace_list)) {
list_del_init(&child->ptrace_list);
- REMOVE_LINKS(child);
+ remove_parent(child);
child->parent = child->real_parent;
- SET_LINKS(child);
+ add_parent(child);
}
ptrace_untrace(child);
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 9a1fa8894b9..8154e7589d1 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -54,15 +54,15 @@ static int verbose; /* Print more debug info. */
static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */
static int shuffle_interval = 5; /* Interval between shuffles (in sec)*/
-MODULE_PARM(nreaders, "i");
+module_param(nreaders, int, 0);
MODULE_PARM_DESC(nreaders, "Number of RCU reader threads");
-MODULE_PARM(stat_interval, "i");
+module_param(stat_interval, int, 0);
MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s");
-MODULE_PARM(verbose, "i");
+module_param(verbose, bool, 0);
MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
-MODULE_PARM(test_no_idle_hz, "i");
+module_param(test_no_idle_hz, bool, 0);
MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs");
-MODULE_PARM(shuffle_interval, "i");
+module_param(shuffle_interval, int, 0);
MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles");
#define TORTURE_FLAG "rcutorture: "
#define PRINTK_STRING(s) \
@@ -301,7 +301,7 @@ rcu_torture_printk(char *page)
long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
long batchsummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
pipesummary[i] += per_cpu(rcu_torture_count, cpu)[i];
batchsummary[i] += per_cpu(rcu_torture_batch, cpu)[i];
@@ -535,7 +535,7 @@ rcu_torture_init(void)
atomic_set(&n_rcu_torture_error, 0);
for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
atomic_set(&rcu_torture_wcount[i], 0);
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
per_cpu(rcu_torture_count, cpu)[i] = 0;
per_cpu(rcu_torture_batch, cpu)[i] = 0;
diff --git a/kernel/sched.c b/kernel/sched.c
index 7ffaabd64f8..a9ecac398bb 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -49,6 +49,7 @@
#include <linux/syscalls.h>
#include <linux/times.h>
#include <linux/acct.h>
+#include <linux/kprobes.h>
#include <asm/tlb.h>
#include <asm/unistd.h>
@@ -144,7 +145,8 @@
(v1) * (v2_max) / (v1_max)
#define DELTA(p) \
- (SCALE(TASK_NICE(p), 40, MAX_BONUS) + INTERACTIVE_DELTA)
+ (SCALE(TASK_NICE(p) + 20, 40, MAX_BONUS) - 20 * MAX_BONUS / 40 + \
+ INTERACTIVE_DELTA)
#define TASK_INTERACTIVE(p) \
((p)->prio <= (p)->static_prio - DELTA(p))
@@ -1546,8 +1548,14 @@ static inline void finish_task_switch(runqueue_t *rq, task_t *prev)
finish_lock_switch(rq, prev);
if (mm)
mmdrop(mm);
- if (unlikely(prev_task_flags & PF_DEAD))
+ if (unlikely(prev_task_flags & PF_DEAD)) {
+ /*
+ * Remove function-return probe instances associated with this
+ * task and put them back on the free list.
+ */
+ kprobe_flush_task(prev);
put_task_struct(prev);
+ }
}
/**
@@ -1617,7 +1625,7 @@ unsigned long nr_uninterruptible(void)
{
unsigned long i, sum = 0;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
sum += cpu_rq(i)->nr_uninterruptible;
/*
@@ -1634,7 +1642,7 @@ unsigned long long nr_context_switches(void)
{
unsigned long long i, sum = 0;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
sum += cpu_rq(i)->nr_switches;
return sum;
@@ -1644,7 +1652,7 @@ unsigned long nr_iowait(void)
{
unsigned long i, sum = 0;
- for_each_cpu(i)
+ for_each_possible_cpu(i)
sum += atomic_read(&cpu_rq(i)->nr_iowait);
return sum;
@@ -2871,13 +2879,11 @@ asmlinkage void __sched schedule(void)
* schedule() atomically, we ignore that path for now.
* Otherwise, whine if we are scheduling when we should not be.
*/
- if (likely(!current->exit_state)) {
- if (unlikely(in_atomic())) {
- printk(KERN_ERR "BUG: scheduling while atomic: "
- "%s/0x%08x/%d\n",
- current->comm, preempt_count(), current->pid);
- dump_stack();
- }
+ if (unlikely(in_atomic() && !current->exit_state)) {
+ printk(KERN_ERR "BUG: scheduling while atomic: "
+ "%s/0x%08x/%d\n",
+ current->comm, preempt_count(), current->pid);
+ dump_stack();
}
profile_hit(SCHED_PROFILING, __builtin_return_address(0));
@@ -5568,11 +5574,31 @@ static int cpu_to_cpu_group(int cpu)
}
#endif
+#ifdef CONFIG_SCHED_MC
+static DEFINE_PER_CPU(struct sched_domain, core_domains);
+static struct sched_group sched_group_core[NR_CPUS];
+#endif
+
+#if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT)
+static int cpu_to_core_group(int cpu)
+{
+ return first_cpu(cpu_sibling_map[cpu]);
+}
+#elif defined(CONFIG_SCHED_MC)
+static int cpu_to_core_group(int cpu)
+{
+ return cpu;
+}
+#endif
+
static DEFINE_PER_CPU(struct sched_domain, phys_domains);
static struct sched_group sched_group_phys[NR_CPUS];
static int cpu_to_phys_group(int cpu)
{
-#ifdef CONFIG_SCHED_SMT
+#if defined(CONFIG_SCHED_MC)
+ cpumask_t mask = cpu_coregroup_map(cpu);
+ return first_cpu(mask);
+#elif defined(CONFIG_SCHED_SMT)
return first_cpu(cpu_sibling_map[cpu]);
#else
return cpu;
@@ -5595,6 +5621,32 @@ static int cpu_to_allnodes_group(int cpu)
{
return cpu_to_node(cpu);
}
+static void init_numa_sched_groups_power(struct sched_group *group_head)
+{
+ struct sched_group *sg = group_head;
+ int j;
+
+ if (!sg)
+ return;
+next_sg:
+ for_each_cpu_mask(j, sg->cpumask) {
+ struct sched_domain *sd;
+
+ sd = &per_cpu(phys_domains, j);
+ if (j != first_cpu(sd->groups->cpumask)) {
+ /*
+ * Only add "power" once for each
+ * physical package.
+ */
+ continue;
+ }
+
+ sg->cpu_power += sd->groups->cpu_power;
+ }
+ sg = sg->next;
+ if (sg != group_head)
+ goto next_sg;
+}
#endif
/*
@@ -5670,6 +5722,17 @@ void build_sched_domains(const cpumask_t *cpu_map)
sd->parent = p;
sd->groups = &sched_group_phys[group];
+#ifdef CONFIG_SCHED_MC
+ p = sd;
+ sd = &per_cpu(core_domains, i);
+ group = cpu_to_core_group(i);
+ *sd = SD_MC_INIT;
+ sd->span = cpu_coregroup_map(i);
+ cpus_and(sd->span, sd->span, *cpu_map);
+ sd->parent = p;
+ sd->groups = &sched_group_core[group];
+#endif
+
#ifdef CONFIG_SCHED_SMT
p = sd;
sd = &per_cpu(cpu_domains, i);
@@ -5695,6 +5758,19 @@ void build_sched_domains(const cpumask_t *cpu_map)
}
#endif
+#ifdef CONFIG_SCHED_MC
+ /* Set up multi-core groups */
+ for_each_cpu_mask(i, *cpu_map) {
+ cpumask_t this_core_map = cpu_coregroup_map(i);
+ cpus_and(this_core_map, this_core_map, *cpu_map);
+ if (i != first_cpu(this_core_map))
+ continue;
+ init_sched_build_groups(sched_group_core, this_core_map,
+ &cpu_to_core_group);
+ }
+#endif
+
+
/* Set up physical groups */
for (i = 0; i < MAX_NUMNODES; i++) {
cpumask_t nodemask = node_to_cpumask(i);
@@ -5791,51 +5867,38 @@ void build_sched_domains(const cpumask_t *cpu_map)
power = SCHED_LOAD_SCALE;
sd->groups->cpu_power = power;
#endif
+#ifdef CONFIG_SCHED_MC
+ sd = &per_cpu(core_domains, i);
+ power = SCHED_LOAD_SCALE + (cpus_weight(sd->groups->cpumask)-1)
+ * SCHED_LOAD_SCALE / 10;
+ sd->groups->cpu_power = power;
+
+ sd = &per_cpu(phys_domains, i);
+ /*
+ * This has to be < 2 * SCHED_LOAD_SCALE
+ * Lets keep it SCHED_LOAD_SCALE, so that
+ * while calculating NUMA group's cpu_power
+ * we can simply do
+ * numa_group->cpu_power += phys_group->cpu_power;
+ *
+ * See "only add power once for each physical pkg"
+ * comment below
+ */
+ sd->groups->cpu_power = SCHED_LOAD_SCALE;
+#else
sd = &per_cpu(phys_domains, i);
power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
(cpus_weight(sd->groups->cpumask)-1) / 10;
sd->groups->cpu_power = power;
-
-#ifdef CONFIG_NUMA
- sd = &per_cpu(allnodes_domains, i);
- if (sd->groups) {
- power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
- (cpus_weight(sd->groups->cpumask)-1) / 10;
- sd->groups->cpu_power = power;
- }
#endif
}
#ifdef CONFIG_NUMA
- for (i = 0; i < MAX_NUMNODES; i++) {
- struct sched_group *sg = sched_group_nodes[i];
- int j;
-
- if (sg == NULL)
- continue;
-next_sg:
- for_each_cpu_mask(j, sg->cpumask) {
- struct sched_domain *sd;
- int power;
+ for (i = 0; i < MAX_NUMNODES; i++)
+ init_numa_sched_groups_power(sched_group_nodes[i]);
- sd = &per_cpu(phys_domains, j);
- if (j != first_cpu(sd->groups->cpumask)) {
- /*
- * Only add "power" once for each
- * physical package.
- */
- continue;
- }
- power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
- (cpus_weight(sd->groups->cpumask)-1) / 10;
-
- sg->cpu_power += power;
- }
- sg = sg->next;
- if (sg != sched_group_nodes[i])
- goto next_sg;
- }
+ init_numa_sched_groups_power(sched_group_allnodes);
#endif
/* Attach the domains */
@@ -5843,6 +5906,8 @@ next_sg:
struct sched_domain *sd;
#ifdef CONFIG_SCHED_SMT
sd = &per_cpu(cpu_domains, i);
+#elif defined(CONFIG_SCHED_MC)
+ sd = &per_cpu(core_domains, i);
#else
sd = &per_cpu(phys_domains, i);
#endif
@@ -6015,7 +6080,7 @@ void __init sched_init(void)
runqueue_t *rq;
int i, j, k;
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
prio_array_t *array;
rq = cpu_rq(i);
diff --git a/kernel/signal.c b/kernel/signal.c
index 75f7341b0c3..4922928d91f 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -22,7 +22,6 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/ptrace.h>
-#include <linux/posix-timers.h>
#include <linux/signal.h>
#include <linux/audit.h>
#include <linux/capability.h>
@@ -147,6 +146,8 @@ static kmem_cache_t *sigqueue_cachep;
#define sig_kernel_stop(sig) \
(((sig) < SIGRTMIN) && T(sig, SIG_KERNEL_STOP_MASK))
+#define sig_needs_tasklist(sig) ((sig) == SIGCONT)
+
#define sig_user_defined(t, signr) \
(((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_DFL) && \
((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_IGN))
@@ -292,7 +293,7 @@ static void __sigqueue_free(struct sigqueue *q)
kmem_cache_free(sigqueue_cachep, q);
}
-static void flush_sigqueue(struct sigpending *queue)
+void flush_sigqueue(struct sigpending *queue)
{
struct sigqueue *q;
@@ -307,9 +308,7 @@ static void flush_sigqueue(struct sigpending *queue)
/*
* Flush all pending signals for a task.
*/
-
-void
-flush_signals(struct task_struct *t)
+void flush_signals(struct task_struct *t)
{
unsigned long flags;
@@ -321,109 +320,6 @@ flush_signals(struct task_struct *t)
}
/*
- * This function expects the tasklist_lock write-locked.
- */
-void __exit_sighand(struct task_struct *tsk)
-{
- struct sighand_struct * sighand = tsk->sighand;
-
- /* Ok, we're done with the signal handlers */
- tsk->sighand = NULL;
- if (atomic_dec_and_test(&sighand->count))
- sighand_free(sighand);
-}
-
-void exit_sighand(struct task_struct *tsk)
-{
- write_lock_irq(&tasklist_lock);
- rcu_read_lock();
- if (tsk->sighand != NULL) {
- struct sighand_struct *sighand = rcu_dereference(tsk->sighand);
- spin_lock(&sighand->siglock);
- __exit_sighand(tsk);
- spin_unlock(&sighand->siglock);
- }
- rcu_read_unlock();
- write_unlock_irq(&tasklist_lock);
-}
-
-/*
- * This function expects the tasklist_lock write-locked.
- */
-void __exit_signal(struct task_struct *tsk)
-{
- struct signal_struct * sig = tsk->signal;
- struct sighand_struct * sighand;
-
- if (!sig)
- BUG();
- if (!atomic_read(&sig->count))
- BUG();
- rcu_read_lock();
- sighand = rcu_dereference(tsk->sighand);
- spin_lock(&sighand->siglock);
- posix_cpu_timers_exit(tsk);
- if (atomic_dec_and_test(&sig->count)) {
- posix_cpu_timers_exit_group(tsk);
- tsk->signal = NULL;
- __exit_sighand(tsk);
- spin_unlock(&sighand->siglock);
- flush_sigqueue(&sig->shared_pending);
- } else {
- /*
- * If there is any task waiting for the group exit
- * then notify it:
- */
- if (sig->group_exit_task && atomic_read(&sig->count) == sig->notify_count) {
- wake_up_process(sig->group_exit_task);
- sig->group_exit_task = NULL;
- }
- if (tsk == sig->curr_target)
- sig->curr_target = next_thread(tsk);
- tsk->signal = NULL;
- /*
- * Accumulate here the counters for all threads but the
- * group leader as they die, so they can be added into
- * the process-wide totals when those are taken.
- * The group leader stays around as a zombie as long
- * as there are other threads. When it gets reaped,
- * the exit.c code will add its counts into these totals.
- * We won't ever get here for the group leader, since it
- * will have been the last reference on the signal_struct.
- */
- 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;
- sig->nivcsw += tsk->nivcsw;
- sig->sched_time += tsk->sched_time;
- __exit_sighand(tsk);
- spin_unlock(&sighand->siglock);
- sig = NULL; /* Marker for below. */
- }
- rcu_read_unlock();
- clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
- flush_sigqueue(&tsk->pending);
- if (sig) {
- /*
- * We are cleaning up the signal_struct here.
- */
- exit_thread_group_keys(sig);
- kmem_cache_free(signal_cachep, sig);
- }
-}
-
-void exit_signal(struct task_struct *tsk)
-{
- atomic_dec(&tsk->signal->live);
-
- write_lock_irq(&tasklist_lock);
- __exit_signal(tsk);
- write_unlock_irq(&tasklist_lock);
-}
-
-/*
* Flush all handlers for a task.
*/
@@ -695,9 +591,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
}
/* forward decl */
-static void do_notify_parent_cldstop(struct task_struct *tsk,
- int to_self,
- int why);
+static void do_notify_parent_cldstop(struct task_struct *tsk, int why);
/*
* Handle magic process-wide effects of stop/continue signals.
@@ -747,7 +641,7 @@ static void handle_stop_signal(int sig, struct task_struct *p)
p->signal->group_stop_count = 0;
p->signal->flags = SIGNAL_STOP_CONTINUED;
spin_unlock(&p->sighand->siglock);
- do_notify_parent_cldstop(p, (p->ptrace & PT_PTRACED), CLD_STOPPED);
+ do_notify_parent_cldstop(p, CLD_STOPPED);
spin_lock(&p->sighand->siglock);
}
rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
@@ -788,7 +682,7 @@ static void handle_stop_signal(int sig, struct task_struct *p)
p->signal->flags = SIGNAL_STOP_CONTINUED;
p->signal->group_exit_code = 0;
spin_unlock(&p->sighand->siglock);
- do_notify_parent_cldstop(p, (p->ptrace & PT_PTRACED), CLD_CONTINUED);
+ do_notify_parent_cldstop(p, CLD_CONTINUED);
spin_lock(&p->sighand->siglock);
} else {
/*
@@ -1120,27 +1014,37 @@ void zap_other_threads(struct task_struct *p)
/*
* Must be called under rcu_read_lock() or with tasklist_lock read-held.
*/
+struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long *flags)
+{
+ struct sighand_struct *sighand;
+
+ for (;;) {
+ sighand = rcu_dereference(tsk->sighand);
+ if (unlikely(sighand == NULL))
+ break;
+
+ spin_lock_irqsave(&sighand->siglock, *flags);
+ if (likely(sighand == tsk->sighand))
+ break;
+ spin_unlock_irqrestore(&sighand->siglock, *flags);
+ }
+
+ return sighand;
+}
+
int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
{
unsigned long flags;
- struct sighand_struct *sp;
int ret;
-retry:
ret = check_kill_permission(sig, info, p);
- if (!ret && sig && (sp = rcu_dereference(p->sighand))) {
- spin_lock_irqsave(&sp->siglock, flags);
- if (p->sighand != sp) {
- spin_unlock_irqrestore(&sp->siglock, flags);
- goto retry;
- }
- if ((atomic_read(&sp->count) == 0) ||
- (atomic_read(&p->usage) == 0)) {
- spin_unlock_irqrestore(&sp->siglock, flags);
- return -ESRCH;
+
+ if (!ret && sig) {
+ ret = -ESRCH;
+ if (lock_task_sighand(p, &flags)) {
+ ret = __group_send_sig_info(sig, info, p);
+ unlock_task_sighand(p, &flags);
}
- ret = __group_send_sig_info(sig, info, p);
- spin_unlock_irqrestore(&sp->siglock, flags);
}
return ret;
@@ -1189,7 +1093,7 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid)
struct task_struct *p;
rcu_read_lock();
- if (unlikely(sig_kernel_stop(sig) || sig == SIGCONT)) {
+ if (unlikely(sig_needs_tasklist(sig))) {
read_lock(&tasklist_lock);
acquired_tasklist_lock = 1;
}
@@ -1405,12 +1309,10 @@ void sigqueue_free(struct sigqueue *q)
__sigqueue_free(q);
}
-int
-send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
+int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
{
unsigned long flags;
int ret = 0;
- struct sighand_struct *sh;
BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
@@ -1424,48 +1326,17 @@ send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
*/
rcu_read_lock();
- if (unlikely(p->flags & PF_EXITING)) {
+ if (!likely(lock_task_sighand(p, &flags))) {
ret = -1;
goto out_err;
}
-retry:
- sh = rcu_dereference(p->sighand);
-
- spin_lock_irqsave(&sh->siglock, flags);
- if (p->sighand != sh) {
- /* We raced with exec() in a multithreaded process... */
- spin_unlock_irqrestore(&sh->siglock, flags);
- goto retry;
- }
-
- /*
- * We do the check here again to handle the following scenario:
- *
- * CPU 0 CPU 1
- * send_sigqueue
- * check PF_EXITING
- * interrupt exit code running
- * __exit_signal
- * lock sighand->siglock
- * unlock sighand->siglock
- * lock sh->siglock
- * add(tsk->pending) flush_sigqueue(tsk->pending)
- *
- */
-
- if (unlikely(p->flags & PF_EXITING)) {
- ret = -1;
- goto out;
- }
-
if (unlikely(!list_empty(&q->list))) {
/*
* If an SI_TIMER entry is already queue just increment
* the overrun count.
*/
- if (q->info.si_code != SI_TIMER)
- BUG();
+ BUG_ON(q->info.si_code != SI_TIMER);
q->info.si_overrun++;
goto out;
}
@@ -1481,7 +1352,7 @@ retry:
signal_wake_up(p, sig == SIGKILL);
out:
- spin_unlock_irqrestore(&sh->siglock, flags);
+ unlock_task_sighand(p, &flags);
out_err:
rcu_read_unlock();
@@ -1613,14 +1484,14 @@ void do_notify_parent(struct task_struct *tsk, int sig)
spin_unlock_irqrestore(&psig->siglock, flags);
}
-static void do_notify_parent_cldstop(struct task_struct *tsk, int to_self, int why)
+static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
{
struct siginfo info;
unsigned long flags;
struct task_struct *parent;
struct sighand_struct *sighand;
- if (to_self)
+ if (tsk->ptrace & PT_PTRACED)
parent = tsk->parent;
else {
tsk = tsk->group_leader;
@@ -1695,7 +1566,7 @@ static void ptrace_stop(int exit_code, int nostop_code, siginfo_t *info)
!(current->ptrace & PT_ATTACHED)) &&
(likely(current->parent->signal != current->signal) ||
!unlikely(current->signal->flags & SIGNAL_GROUP_EXIT))) {
- do_notify_parent_cldstop(current, 1, CLD_TRAPPED);
+ do_notify_parent_cldstop(current, CLD_TRAPPED);
read_unlock(&tasklist_lock);
schedule();
} else {
@@ -1744,25 +1615,17 @@ void ptrace_notify(int exit_code)
static void
finish_stop(int stop_count)
{
- int to_self;
-
/*
* If there are no other threads in the group, or if there is
* a group stop in progress and we are the last to stop,
* report to the parent. When ptraced, every thread reports itself.
*/
- if (stop_count < 0 || (current->ptrace & PT_PTRACED))
- to_self = 1;
- else if (stop_count == 0)
- to_self = 0;
- else
- goto out;
-
- read_lock(&tasklist_lock);
- do_notify_parent_cldstop(current, to_self, CLD_STOPPED);
- read_unlock(&tasklist_lock);
+ if (stop_count == 0 || (current->ptrace & PT_PTRACED)) {
+ read_lock(&tasklist_lock);
+ do_notify_parent_cldstop(current, CLD_STOPPED);
+ read_unlock(&tasklist_lock);
+ }
-out:
schedule();
/*
* Now we don't run again until continued.
@@ -1776,12 +1639,10 @@ out:
* Returns nonzero if we've actually stopped and released the siglock.
* Returns zero if we didn't stop and still hold the siglock.
*/
-static int
-do_signal_stop(int signr)
+static int do_signal_stop(int signr)
{
struct signal_struct *sig = current->signal;
- struct sighand_struct *sighand = current->sighand;
- int stop_count = -1;
+ int stop_count;
if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED))
return 0;
@@ -1791,86 +1652,37 @@ do_signal_stop(int signr)
* There is a group stop in progress. We don't need to
* start another one.
*/
- signr = sig->group_exit_code;
stop_count = --sig->group_stop_count;
- current->exit_code = signr;
- set_current_state(TASK_STOPPED);
- if (stop_count == 0)
- sig->flags = SIGNAL_STOP_STOPPED;
- spin_unlock_irq(&sighand->siglock);
- }
- else if (thread_group_empty(current)) {
- /*
- * Lock must be held through transition to stopped state.
- */
- current->exit_code = current->signal->group_exit_code = signr;
- set_current_state(TASK_STOPPED);
- sig->flags = SIGNAL_STOP_STOPPED;
- spin_unlock_irq(&sighand->siglock);
- }
- else {
+ } else {
/*
* There is no group stop already in progress.
- * We must initiate one now, but that requires
- * dropping siglock to get both the tasklist lock
- * and siglock again in the proper order. Note that
- * this allows an intervening SIGCONT to be posted.
- * We need to check for that and bail out if necessary.
+ * We must initiate one now.
*/
struct task_struct *t;
- spin_unlock_irq(&sighand->siglock);
-
- /* signals can be posted during this window */
+ sig->group_exit_code = signr;
- read_lock(&tasklist_lock);
- spin_lock_irq(&sighand->siglock);
-
- if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED)) {
+ stop_count = 0;
+ for (t = next_thread(current); t != current; t = next_thread(t))
/*
- * Another stop or continue happened while we
- * didn't have the lock. We can just swallow this
- * signal now. If we raced with a SIGCONT, that
- * should have just cleared it now. If we raced
- * with another processor delivering a stop signal,
- * then the SIGCONT that wakes us up should clear it.
+ * Setting state to TASK_STOPPED for a group
+ * stop is always done with the siglock held,
+ * so this check has no races.
*/
- read_unlock(&tasklist_lock);
- return 0;
- }
-
- if (sig->group_stop_count == 0) {
- sig->group_exit_code = signr;
- stop_count = 0;
- for (t = next_thread(current); t != current;
- t = next_thread(t))
- /*
- * Setting state to TASK_STOPPED for a group
- * stop is always done with the siglock held,
- * so this check has no races.
- */
- if (!t->exit_state &&
- !(t->state & (TASK_STOPPED|TASK_TRACED))) {
- stop_count++;
- signal_wake_up(t, 0);
- }
- sig->group_stop_count = stop_count;
- }
- else {
- /* A race with another thread while unlocked. */
- signr = sig->group_exit_code;
- stop_count = --sig->group_stop_count;
- }
-
- current->exit_code = signr;
- set_current_state(TASK_STOPPED);
- if (stop_count == 0)
- sig->flags = SIGNAL_STOP_STOPPED;
-
- spin_unlock_irq(&sighand->siglock);
- read_unlock(&tasklist_lock);
+ if (!t->exit_state &&
+ !(t->state & (TASK_STOPPED|TASK_TRACED))) {
+ stop_count++;
+ signal_wake_up(t, 0);
+ }
+ sig->group_stop_count = stop_count;
}
+ if (stop_count == 0)
+ sig->flags = SIGNAL_STOP_STOPPED;
+ current->exit_code = sig->group_exit_code;
+ __set_current_state(TASK_STOPPED);
+
+ spin_unlock_irq(&current->sighand->siglock);
finish_stop(stop_count);
return 1;
}
@@ -1990,7 +1802,7 @@ relock:
continue;
/* Init gets no signals it doesn't want. */
- if (current->pid == 1)
+ if (current == child_reaper)
continue;
if (sig_kernel_stop(signr)) {
@@ -2430,8 +2242,7 @@ sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo)
return kill_proc_info(sig, &info, pid);
}
-int
-do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
+int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
{
struct k_sigaction *k;
sigset_t mask;
@@ -2457,6 +2268,7 @@ do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
if (act) {
sigdelsetmask(&act->sa.sa_mask,
sigmask(SIGKILL) | sigmask(SIGSTOP));
+ *k = *act;
/*
* POSIX 3.3.1.3:
* "Setting a signal action to SIG_IGN for a signal that is
@@ -2469,19 +2281,8 @@ do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
* be discarded, whether or not it is blocked"
*/
if (act->sa.sa_handler == SIG_IGN ||
- (act->sa.sa_handler == SIG_DFL &&
- sig_kernel_ignore(sig))) {
- /*
- * This is a fairly rare case, so we only take the
- * tasklist_lock once we're sure we'll need it.
- * Now we must do this little unlock and relock
- * dance to maintain the lock hierarchy.
- */
+ (act->sa.sa_handler == SIG_DFL && sig_kernel_ignore(sig))) {
struct task_struct *t = current;
- spin_unlock_irq(&t->sighand->siglock);
- read_lock(&tasklist_lock);
- spin_lock_irq(&t->sighand->siglock);
- *k = *act;
sigemptyset(&mask);
sigaddset(&mask, sig);
rm_from_queue_full(&mask, &t->signal->shared_pending);
@@ -2490,12 +2291,7 @@ do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
recalc_sigpending_tsk(t);
t = next_thread(t);
} while (t != current);
- spin_unlock_irq(&current->sighand->siglock);
- read_unlock(&tasklist_lock);
- return 0;
}
-
- *k = *act;
}
spin_unlock_irq(&current->sighand->siglock);
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index dd9524fa649..ced91e1ff56 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -118,6 +118,7 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
printk("watchdog for %i failed\n", hotcpu);
return NOTIFY_BAD;
}
+ per_cpu(touch_timestamp, hotcpu) = jiffies;
per_cpu(watchdog_task, hotcpu) = p;
kthread_bind(p, hotcpu);
break;
@@ -151,5 +152,5 @@ __init void spawn_softlockup_task(void)
cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
register_cpu_notifier(&cpu_nfb);
- notifier_chain_register(&panic_notifier_list, &panic_block);
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
}
diff --git a/kernel/sys.c b/kernel/sys.c
index 19d058be49d..7ef7f6054c2 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -95,99 +95,304 @@ int cad_pid = 1;
* and the like.
*/
-static struct notifier_block *reboot_notifier_list;
-static DEFINE_RWLOCK(notifier_lock);
+static BLOCKING_NOTIFIER_HEAD(reboot_notifier_list);
+
+/*
+ * Notifier chain core routines. The exported routines below
+ * are layered on top of these, with appropriate locking added.
+ */
+
+static int notifier_chain_register(struct notifier_block **nl,
+ struct notifier_block *n)
+{
+ while ((*nl) != NULL) {
+ if (n->priority > (*nl)->priority)
+ break;
+ nl = &((*nl)->next);
+ }
+ n->next = *nl;
+ rcu_assign_pointer(*nl, n);
+ return 0;
+}
+
+static int notifier_chain_unregister(struct notifier_block **nl,
+ struct notifier_block *n)
+{
+ while ((*nl) != NULL) {
+ if ((*nl) == n) {
+ rcu_assign_pointer(*nl, n->next);
+ return 0;
+ }
+ nl = &((*nl)->next);
+ }
+ return -ENOENT;
+}
+
+static int __kprobes notifier_call_chain(struct notifier_block **nl,
+ unsigned long val, void *v)
+{
+ int ret = NOTIFY_DONE;
+ struct notifier_block *nb;
+
+ nb = rcu_dereference(*nl);
+ while (nb) {
+ ret = nb->notifier_call(nb, val, v);
+ if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
+ break;
+ nb = rcu_dereference(nb->next);
+ }
+ return ret;
+}
+
+/*
+ * Atomic notifier chain routines. Registration and unregistration
+ * use a mutex, and call_chain is synchronized by RCU (no locks).
+ */
/**
- * notifier_chain_register - Add notifier to a notifier chain
- * @list: Pointer to root list pointer
+ * atomic_notifier_chain_register - Add notifier to an atomic notifier chain
+ * @nh: Pointer to head of the atomic notifier chain
* @n: New entry in notifier chain
*
- * Adds a notifier to a notifier chain.
+ * Adds a notifier to an atomic notifier chain.
*
* Currently always returns zero.
*/
+
+int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
+ struct notifier_block *n)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&nh->lock, flags);
+ ret = notifier_chain_register(&nh->head, n);
+ spin_unlock_irqrestore(&nh->lock, flags);
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(atomic_notifier_chain_register);
+
+/**
+ * atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain
+ * @nh: Pointer to head of the atomic notifier chain
+ * @n: Entry to remove from notifier chain
+ *
+ * Removes a notifier from an atomic notifier chain.
+ *
+ * Returns zero on success or %-ENOENT on failure.
+ */
+int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
+ struct notifier_block *n)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&nh->lock, flags);
+ ret = notifier_chain_unregister(&nh->head, n);
+ spin_unlock_irqrestore(&nh->lock, flags);
+ synchronize_rcu();
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
+
+/**
+ * atomic_notifier_call_chain - Call functions in an atomic notifier chain
+ * @nh: Pointer to head of the atomic notifier chain
+ * @val: Value passed unmodified to notifier function
+ * @v: Pointer passed unmodified to notifier function
+ *
+ * Calls each function in a notifier chain in turn. The functions
+ * run in an atomic context, so they must not block.
+ * This routine uses RCU to synchronize with changes to the chain.
+ *
+ * If the return value of the notifier can be and'ed
+ * with %NOTIFY_STOP_MASK then atomic_notifier_call_chain
+ * will return immediately, with the return value of
+ * the notifier function which halted execution.
+ * Otherwise the return value is the return value
+ * of the last notifier function called.
+ */
-int notifier_chain_register(struct notifier_block **list, struct notifier_block *n)
+int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
+ unsigned long val, void *v)
{
- write_lock(&notifier_lock);
- while(*list)
- {
- if(n->priority > (*list)->priority)
- break;
- list= &((*list)->next);
- }
- n->next = *list;
- *list=n;
- write_unlock(&notifier_lock);
- return 0;
+ int ret;
+
+ rcu_read_lock();
+ ret = notifier_call_chain(&nh->head, val, v);
+ rcu_read_unlock();
+ return ret;
}
-EXPORT_SYMBOL(notifier_chain_register);
+EXPORT_SYMBOL_GPL(atomic_notifier_call_chain);
+
+/*
+ * Blocking notifier chain routines. All access to the chain is
+ * synchronized by an rwsem.
+ */
/**
- * notifier_chain_unregister - Remove notifier from a notifier chain
- * @nl: Pointer to root list pointer
+ * blocking_notifier_chain_register - Add notifier to a blocking notifier chain
+ * @nh: Pointer to head of the blocking notifier chain
* @n: New entry in notifier chain
*
- * Removes a notifier from a notifier chain.
+ * Adds a notifier to a blocking notifier chain.
+ * Must be called in process context.
*
- * Returns zero on success, or %-ENOENT on failure.
+ * Currently always returns zero.
*/
-int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n)
+int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
+ struct notifier_block *n)
{
- write_lock(&notifier_lock);
- while((*nl)!=NULL)
- {
- if((*nl)==n)
- {
- *nl=n->next;
- write_unlock(&notifier_lock);
- return 0;
- }
- nl=&((*nl)->next);
- }
- write_unlock(&notifier_lock);
- return -ENOENT;
+ int ret;
+
+ /*
+ * This code gets used during boot-up, when task switching is
+ * not yet working and interrupts must remain disabled. At
+ * such times we must not call down_write().
+ */
+ if (unlikely(system_state == SYSTEM_BOOTING))
+ return notifier_chain_register(&nh->head, n);
+
+ down_write(&nh->rwsem);
+ ret = notifier_chain_register(&nh->head, n);
+ up_write(&nh->rwsem);
+ return ret;
}
-EXPORT_SYMBOL(notifier_chain_unregister);
+EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
/**
- * notifier_call_chain - Call functions in a notifier chain
- * @n: Pointer to root pointer of notifier chain
+ * blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain
+ * @nh: Pointer to head of the blocking notifier chain
+ * @n: Entry to remove from notifier chain
+ *
+ * Removes a notifier from a blocking notifier chain.
+ * Must be called from process context.
+ *
+ * Returns zero on success or %-ENOENT on failure.
+ */
+int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
+ struct notifier_block *n)
+{
+ int ret;
+
+ /*
+ * This code gets used during boot-up, when task switching is
+ * not yet working and interrupts must remain disabled. At
+ * such times we must not call down_write().
+ */
+ if (unlikely(system_state == SYSTEM_BOOTING))
+ return notifier_chain_unregister(&nh->head, n);
+
+ down_write(&nh->rwsem);
+ ret = notifier_chain_unregister(&nh->head, n);
+ up_write(&nh->rwsem);
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
+
+/**
+ * blocking_notifier_call_chain - Call functions in a blocking notifier chain
+ * @nh: Pointer to head of the blocking notifier chain
* @val: Value passed unmodified to notifier function
* @v: Pointer passed unmodified to notifier function
*
- * Calls each function in a notifier chain in turn.
+ * Calls each function in a notifier chain in turn. The functions
+ * run in a process context, so they are allowed to block.
*
- * If the return value of the notifier can be and'd
- * with %NOTIFY_STOP_MASK, then notifier_call_chain
+ * If the return value of the notifier can be and'ed
+ * with %NOTIFY_STOP_MASK then blocking_notifier_call_chain
* will return immediately, with the return value of
* the notifier function which halted execution.
- * Otherwise, the return value is the return value
+ * Otherwise the return value is the return value
* of the last notifier function called.
*/
-int __kprobes notifier_call_chain(struct notifier_block **n, unsigned long val, void *v)
+int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
+ unsigned long val, void *v)
{
- int ret=NOTIFY_DONE;
- struct notifier_block *nb = *n;
+ int ret;
- while(nb)
- {
- ret=nb->notifier_call(nb,val,v);
- if(ret&NOTIFY_STOP_MASK)
- {
- return ret;
- }
- nb=nb->next;
- }
+ down_read(&nh->rwsem);
+ ret = notifier_call_chain(&nh->head, val, v);
+ up_read(&nh->rwsem);
return ret;
}
-EXPORT_SYMBOL(notifier_call_chain);
+EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
+
+/*
+ * Raw notifier chain routines. There is no protection;
+ * the caller must provide it. Use at your own risk!
+ */
+
+/**
+ * raw_notifier_chain_register - Add notifier to a raw notifier chain
+ * @nh: Pointer to head of the raw notifier chain
+ * @n: New entry in notifier chain
+ *
+ * Adds a notifier to a raw notifier chain.
+ * All locking must be provided by the caller.
+ *
+ * Currently always returns zero.
+ */
+
+int raw_notifier_chain_register(struct raw_notifier_head *nh,
+ struct notifier_block *n)
+{
+ return notifier_chain_register(&nh->head, n);
+}
+
+EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
+
+/**
+ * raw_notifier_chain_unregister - Remove notifier from a raw notifier chain
+ * @nh: Pointer to head of the raw notifier chain
+ * @n: Entry to remove from notifier chain
+ *
+ * Removes a notifier from a raw notifier chain.
+ * All locking must be provided by the caller.
+ *
+ * Returns zero on success or %-ENOENT on failure.
+ */
+int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
+ struct notifier_block *n)
+{
+ return notifier_chain_unregister(&nh->head, n);
+}
+
+EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
+
+/**
+ * raw_notifier_call_chain - Call functions in a raw notifier chain
+ * @nh: Pointer to head of the raw notifier chain
+ * @val: Value passed unmodified to notifier function
+ * @v: Pointer passed unmodified to notifier function
+ *
+ * Calls each function in a notifier chain in turn. The functions
+ * run in an undefined context.
+ * All locking must be provided by the caller.
+ *
+ * If the return value of the notifier can be and'ed
+ * with %NOTIFY_STOP_MASK then raw_notifier_call_chain
+ * will return immediately, with the return value of
+ * the notifier function which halted execution.
+ * Otherwise the return value is the return value
+ * of the last notifier function called.
+ */
+
+int raw_notifier_call_chain(struct raw_notifier_head *nh,
+ unsigned long val, void *v)
+{
+ return notifier_call_chain(&nh->head, val, v);
+}
+
+EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
/**
* register_reboot_notifier - Register function to be called at reboot time
@@ -196,13 +401,13 @@ EXPORT_SYMBOL(notifier_call_chain);
* Registers a function with the list of functions
* to be called at reboot time.
*
- * Currently always returns zero, as notifier_chain_register
+ * Currently always returns zero, as blocking_notifier_chain_register
* always returns zero.
*/
int register_reboot_notifier(struct notifier_block * nb)
{
- return notifier_chain_register(&reboot_notifier_list, nb);
+ return blocking_notifier_chain_register(&reboot_notifier_list, nb);
}
EXPORT_SYMBOL(register_reboot_notifier);
@@ -219,23 +424,11 @@ EXPORT_SYMBOL(register_reboot_notifier);
int unregister_reboot_notifier(struct notifier_block * nb)
{
- return notifier_chain_unregister(&reboot_notifier_list, nb);
+ return blocking_notifier_chain_unregister(&reboot_notifier_list, nb);
}
EXPORT_SYMBOL(unregister_reboot_notifier);
-#ifndef CONFIG_SECURITY
-int capable(int cap)
-{
- if (cap_raised(current->cap_effective, cap)) {
- current->flags |= PF_SUPERPRIV;
- return 1;
- }
- return 0;
-}
-EXPORT_SYMBOL(capable);
-#endif
-
static int set_one_prio(struct task_struct *p, int niceval, int error)
{
int no_nice;
@@ -392,7 +585,7 @@ EXPORT_SYMBOL_GPL(emergency_restart);
void kernel_restart_prepare(char *cmd)
{
- notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
+ blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
system_state = SYSTEM_RESTART;
device_shutdown();
}
@@ -442,7 +635,7 @@ EXPORT_SYMBOL_GPL(kernel_kexec);
void kernel_shutdown_prepare(enum system_states state)
{
- notifier_call_chain(&reboot_notifier_list,
+ blocking_notifier_call_chain(&reboot_notifier_list,
(state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL);
system_state = state;
device_shutdown();
@@ -1009,69 +1202,24 @@ asmlinkage long sys_times(struct tms __user * tbuf)
*/
if (tbuf) {
struct tms tmp;
+ struct task_struct *tsk = current;
+ struct task_struct *t;
cputime_t utime, stime, cutime, cstime;
-#ifdef CONFIG_SMP
- if (thread_group_empty(current)) {
- /*
- * Single thread case without the use of any locks.
- *
- * We may race with release_task if two threads are
- * executing. However, release task first adds up the
- * counters (__exit_signal) before removing the task
- * from the process tasklist (__unhash_process).
- * __exit_signal also acquires and releases the
- * siglock which results in the proper memory ordering
- * so that the list modifications are always visible
- * after the counters have been updated.
- *
- * If the counters have been updated by the second thread
- * but the thread has not yet been removed from the list
- * then the other branch will be executing which will
- * block on tasklist_lock until the exit handling of the
- * other task is finished.
- *
- * This also implies that the sighand->siglock cannot
- * be held by another processor. So we can also
- * skip acquiring that lock.
- */
- utime = cputime_add(current->signal->utime, current->utime);
- stime = cputime_add(current->signal->utime, current->stime);
- cutime = current->signal->cutime;
- cstime = current->signal->cstime;
- } else
-#endif
- {
-
- /* Process with multiple threads */
- struct task_struct *tsk = current;
- struct task_struct *t;
+ spin_lock_irq(&tsk->sighand->siglock);
+ utime = tsk->signal->utime;
+ stime = tsk->signal->stime;
+ t = tsk;
+ do {
+ utime = cputime_add(utime, t->utime);
+ stime = cputime_add(stime, t->stime);
+ t = next_thread(t);
+ } while (t != tsk);
- read_lock(&tasklist_lock);
- utime = tsk->signal->utime;
- stime = tsk->signal->stime;
- t = tsk;
- do {
- utime = cputime_add(utime, t->utime);
- stime = cputime_add(stime, t->stime);
- t = next_thread(t);
- } while (t != tsk);
+ cutime = tsk->signal->cutime;
+ cstime = tsk->signal->cstime;
+ spin_unlock_irq(&tsk->sighand->siglock);
- /*
- * While we have tasklist_lock read-locked, no dying thread
- * can be updating current->signal->[us]time. Instead,
- * we got their counts included in the live thread loop.
- * However, another thread can come in right now and
- * do a wait call that updates current->signal->c[us]time.
- * To make sure we always see that pair updated atomically,
- * we take the siglock around fetching them.
- */
- spin_lock_irq(&tsk->sighand->siglock);
- cutime = tsk->signal->cutime;
- cstime = tsk->signal->cstime;
- spin_unlock_irq(&tsk->sighand->siglock);
- read_unlock(&tasklist_lock);
- }
tmp.tms_utime = cputime_to_clock_t(utime);
tmp.tms_stime = cputime_to_clock_t(stime);
tmp.tms_cutime = cputime_to_clock_t(cutime);
@@ -1375,7 +1523,7 @@ static void groups_sort(struct group_info *group_info)
/* a simple bsearch */
int groups_search(struct group_info *group_info, gid_t grp)
{
- int left, right;
+ unsigned int left, right;
if (!group_info)
return 0;
@@ -1383,7 +1531,7 @@ int groups_search(struct group_info *group_info, gid_t grp)
left = 0;
right = group_info->ngroups;
while (left < right) {
- int mid = (left+right)/2;
+ unsigned int mid = (left+right)/2;
int cmp = grp - GROUP_AT(group_info, mid);
if (cmp > 0)
left = mid + 1;
@@ -1433,7 +1581,6 @@ asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
return -EINVAL;
/* no need to grab task_lock here; it cannot change */
- get_group_info(current->group_info);
i = current->group_info->ngroups;
if (gidsetsize) {
if (i > gidsetsize) {
@@ -1446,7 +1593,6 @@ asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
}
}
out:
- put_group_info(current->group_info);
return i;
}
@@ -1487,9 +1633,7 @@ int in_group_p(gid_t grp)
{
int retval = 1;
if (grp != current->fsgid) {
- get_group_info(current->group_info);
retval = groups_search(current->group_info, grp);
- put_group_info(current->group_info);
}
return retval;
}
@@ -1500,9 +1644,7 @@ int in_egroup_p(gid_t grp)
{
int retval = 1;
if (grp != current->egid) {
- get_group_info(current->group_info);
retval = groups_search(current->group_info, grp);
- put_group_info(current->group_info);
}
return retval;
}
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 1067090db6b..d82864c4a61 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -42,6 +42,10 @@ cond_syscall(sys_recvmsg);
cond_syscall(sys_socketcall);
cond_syscall(sys_futex);
cond_syscall(compat_sys_futex);
+cond_syscall(sys_set_robust_list);
+cond_syscall(compat_sys_set_robust_list);
+cond_syscall(sys_get_robust_list);
+cond_syscall(compat_sys_get_robust_list);
cond_syscall(sys_epoll_create);
cond_syscall(sys_epoll_ctl);
cond_syscall(sys_epoll_wait);
diff --git a/kernel/time.c b/kernel/time.c
index 804539165d8..ff8e7019c4c 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -202,24 +202,6 @@ asmlinkage long sys_settimeofday(struct timeval __user *tv,
return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
}
-long pps_offset; /* pps time offset (us) */
-long pps_jitter = MAXTIME; /* time dispersion (jitter) (us) */
-
-long pps_freq; /* frequency offset (scaled ppm) */
-long pps_stabil = MAXFREQ; /* frequency dispersion (scaled ppm) */
-
-long pps_valid = PPS_VALID; /* pps signal watchdog counter */
-
-int pps_shift = PPS_SHIFT; /* interval duration (s) (shift) */
-
-long pps_jitcnt; /* jitter limit exceeded */
-long pps_calcnt; /* calibration intervals */
-long pps_errcnt; /* calibration errors */
-long pps_stbcnt; /* stability limit exceeded */
-
-/* hook for a loadable hardpps kernel module */
-void (*hardpps_ptr)(struct timeval *);
-
/* we call this to notify the arch when the clock is being
* controlled. If no such arch routine, do nothing.
*/
@@ -279,7 +261,7 @@ int do_adjtimex(struct timex *txc)
result = -EINVAL;
goto leave;
}
- time_freq = txc->freq - pps_freq;
+ time_freq = txc->freq;
}
if (txc->modes & ADJ_MAXERROR) {
@@ -312,10 +294,8 @@ int do_adjtimex(struct timex *txc)
if ((time_next_adjust = txc->offset) == 0)
time_adjust = 0;
}
- else if ( time_status & (STA_PLL | STA_PPSTIME) ) {
- ltemp = (time_status & (STA_PPSTIME | STA_PPSSIGNAL)) ==
- (STA_PPSTIME | STA_PPSSIGNAL) ?
- pps_offset : txc->offset;
+ else if (time_status & STA_PLL) {
+ ltemp = txc->offset;
/*
* Scale the phase adjustment and
@@ -356,23 +336,14 @@ int do_adjtimex(struct timex *txc)
}
time_freq = min(time_freq, time_tolerance);
time_freq = max(time_freq, -time_tolerance);
- } /* STA_PLL || STA_PPSTIME */
+ } /* STA_PLL */
} /* txc->modes & ADJ_OFFSET */
if (txc->modes & ADJ_TICK) {
tick_usec = txc->tick;
tick_nsec = TICK_USEC_TO_NSEC(tick_usec);
}
} /* txc->modes */
-leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
- || ((time_status & (STA_PPSFREQ|STA_PPSTIME)) != 0
- && (time_status & STA_PPSSIGNAL) == 0)
- /* p. 24, (b) */
- || ((time_status & (STA_PPSTIME|STA_PPSJITTER))
- == (STA_PPSTIME|STA_PPSJITTER))
- /* p. 24, (c) */
- || ((time_status & STA_PPSFREQ) != 0
- && (time_status & (STA_PPSWANDER|STA_PPSERROR)) != 0))
- /* p. 24, (d) */
+leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
result = TIME_ERROR;
if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
@@ -380,7 +351,7 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
else {
txc->offset = shift_right(time_offset, SHIFT_UPDATE);
}
- txc->freq = time_freq + pps_freq;
+ txc->freq = time_freq;
txc->maxerror = time_maxerror;
txc->esterror = time_esterror;
txc->status = time_status;
@@ -388,14 +359,16 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
txc->precision = time_precision;
txc->tolerance = time_tolerance;
txc->tick = tick_usec;
- txc->ppsfreq = pps_freq;
- txc->jitter = pps_jitter >> PPS_AVG;
- txc->shift = pps_shift;
- txc->stabil = pps_stabil;
- txc->jitcnt = pps_jitcnt;
- txc->calcnt = pps_calcnt;
- txc->errcnt = pps_errcnt;
- txc->stbcnt = pps_stbcnt;
+
+ /* PPS is not implemented, so these are zero */
+ txc->ppsfreq = 0;
+ txc->jitter = 0;
+ txc->shift = 0;
+ txc->stabil = 0;
+ txc->jitcnt = 0;
+ txc->calcnt = 0;
+ txc->errcnt = 0;
+ txc->stbcnt = 0;
write_sequnlock_irq(&xtime_lock);
do_gettimeofday(&txc->time);
notify_arch_cmos_timer();
@@ -637,7 +610,7 @@ void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec)
*
* Returns the timespec representation of the nsec parameter.
*/
-struct timespec ns_to_timespec(const nsec_t nsec)
+struct timespec ns_to_timespec(const s64 nsec)
{
struct timespec ts;
@@ -657,7 +630,7 @@ struct timespec ns_to_timespec(const nsec_t nsec)
*
* Returns the timeval representation of the nsec parameter.
*/
-struct timeval ns_to_timeval(const nsec_t nsec)
+struct timeval ns_to_timeval(const s64 nsec)
{
struct timespec ts = ns_to_timespec(nsec);
struct timeval tv;
diff --git a/kernel/timer.c b/kernel/timer.c
index 17d956cebcb..ab189dd187c 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -697,18 +697,9 @@ static void second_overflow(void)
/*
* Compute the frequency estimate and additional phase adjustment due
- * to frequency error for the next second. When the PPS signal is
- * engaged, gnaw on the watchdog counter and update the frequency
- * computed by the pll and the PPS signal.
+ * to frequency error for the next second.
*/
- pps_valid++;
- if (pps_valid == PPS_VALID) { /* PPS signal lost */
- pps_jitter = MAXTIME;
- pps_stabil = MAXFREQ;
- time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
- STA_PPSWANDER | STA_PPSERROR);
- }
- ltemp = time_freq + pps_freq;
+ ltemp = time_freq;
time_adj += shift_right(ltemp,(SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE));
#if HZ == 100
@@ -956,19 +947,7 @@ void do_timer(struct pt_regs *regs)
*/
asmlinkage unsigned long sys_alarm(unsigned int seconds)
{
- struct itimerval it_new, it_old;
- unsigned int oldalarm;
-
- it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
- it_new.it_value.tv_sec = seconds;
- it_new.it_value.tv_usec = 0;
- do_setitimer(ITIMER_REAL, &it_new, &it_old);
- oldalarm = it_old.it_value.tv_sec;
- /* ehhh.. We can't return 0 if we have an alarm pending.. */
- /* And we'd better return too much than too little anyway */
- if ((!oldalarm && it_old.it_value.tv_usec) || it_old.it_value.tv_usec >= 500000)
- oldalarm++;
- return oldalarm;
+ return alarm_setitimer(seconds);
}
#endif
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index f2618e1c2b9..6e8a60f67c7 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -78,13 +78,17 @@ config SCHEDSTATS
this adds.
config DEBUG_SLAB
- bool "Debug memory allocations"
+ bool "Debug slab memory allocations"
depends on DEBUG_KERNEL && SLAB
help
Say Y here to have the kernel do limited verification on memory
allocation as well as poisoning memory on free to catch use of freed
memory. This can make kmalloc/kfree-intensive workloads much slower.
+config DEBUG_SLAB_LEAK
+ bool "Memory leak debugging"
+ depends on DEBUG_SLAB
+
config DEBUG_PREEMPT
bool "Debug preemptible kernel"
depends on DEBUG_KERNEL && PREEMPT
@@ -168,7 +172,7 @@ config DEBUG_IOREMAP
config DEBUG_FS
bool "Debug Filesystem"
- depends on DEBUG_KERNEL && SYSFS
+ depends on SYSFS
help
debugfs is a virtual file system that kernel developers use to put
debugging files into. Enable this option to be able to read and
@@ -199,7 +203,6 @@ config UNWIND_INFO
bool "Compile the kernel with frame unwind information"
depends on !IA64
depends on !MODULES || !(MIPS || PARISC || PPC || SUPERH || SPARC64 || V850)
- default DEBUG_KERNEL
help
If you say Y here the resulting kernel image will be slightly larger
but not slower, and it will give very useful debugging information.
diff --git a/lib/Makefile b/lib/Makefile
index 648b2c1242f..b830c9a1554 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -7,6 +7,8 @@ lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \
sha1.o
+lib-$(CONFIG_SMP) += cpumask.o
+
lib-y += kobject.o kref.o kobject_uevent.o klist.o
obj-y += sort.o parser.o halfmd4.o iomap_copy.o
@@ -21,6 +23,7 @@ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o
lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
+lib-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 8acab0e176e..ed2ae3b0cd0 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -253,33 +253,18 @@ int __bitmap_subset(const unsigned long *bitmap1,
}
EXPORT_SYMBOL(__bitmap_subset);
-#if BITS_PER_LONG == 32
int __bitmap_weight(const unsigned long *bitmap, int bits)
{
int k, w = 0, lim = bits/BITS_PER_LONG;
for (k = 0; k < lim; k++)
- w += hweight32(bitmap[k]);
+ w += hweight_long(bitmap[k]);
if (bits % BITS_PER_LONG)
- w += hweight32(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
+ w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
return w;
}
-#else
-int __bitmap_weight(const unsigned long *bitmap, int bits)
-{
- int k, w = 0, lim = bits/BITS_PER_LONG;
-
- for (k = 0; k < lim; k++)
- w += hweight64(bitmap[k]);
-
- if (bits % BITS_PER_LONG)
- w += hweight64(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
-
- return w;
-}
-#endif
EXPORT_SYMBOL(__bitmap_weight);
/*
diff --git a/lib/cpumask.c b/lib/cpumask.c
new file mode 100644
index 00000000000..3a67dc5ada7
--- /dev/null
+++ b/lib/cpumask.c
@@ -0,0 +1,45 @@
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/cpumask.h>
+#include <linux/module.h>
+
+int __first_cpu(const cpumask_t *srcp)
+{
+ return min_t(int, NR_CPUS, find_first_bit(srcp->bits, NR_CPUS));
+}
+EXPORT_SYMBOL(__first_cpu);
+
+int __next_cpu(int n, const cpumask_t *srcp)
+{
+ return min_t(int, NR_CPUS, find_next_bit(srcp->bits, NR_CPUS, n+1));
+}
+EXPORT_SYMBOL(__next_cpu);
+
+/*
+ * Find the highest possible smp_processor_id()
+ *
+ * Note: if we're prepared to assume that cpu_possible_map never changes
+ * (reasonable) then this function should cache its return value.
+ */
+int highest_possible_processor_id(void)
+{
+ unsigned int cpu;
+ unsigned highest = 0;
+
+ for_each_cpu_mask(cpu, cpu_possible_map)
+ highest = cpu;
+ return highest;
+}
+EXPORT_SYMBOL(highest_possible_processor_id);
+
+int __any_online_cpu(const cpumask_t *mask)
+{
+ int cpu;
+
+ for_each_cpu_mask(cpu, *mask) {
+ if (cpu_online(cpu))
+ break;
+ }
+ return cpu;
+}
+EXPORT_SYMBOL(__any_online_cpu);
diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c
index c05b4b19cf6..bda0d71a251 100644
--- a/lib/find_next_bit.c
+++ b/lib/find_next_bit.c
@@ -11,48 +11,171 @@
#include <linux/bitops.h>
#include <linux/module.h>
+#include <asm/types.h>
+#include <asm/byteorder.h>
-int find_next_bit(const unsigned long *addr, int size, int offset)
+#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
+
+/**
+ * find_next_bit - find the next set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
+ unsigned long offset)
{
- const unsigned long *base;
- const int NBITS = sizeof(*addr) * 8;
+ const unsigned long *p = addr + BITOP_WORD(offset);
+ unsigned long result = offset & ~(BITS_PER_LONG-1);
unsigned long tmp;
- base = addr;
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset %= BITS_PER_LONG;
if (offset) {
- int suboffset;
+ tmp = *(p++);
+ tmp &= (~0UL << offset);
+ if (size < BITS_PER_LONG)
+ goto found_first;
+ if (tmp)
+ goto found_middle;
+ size -= BITS_PER_LONG;
+ result += BITS_PER_LONG;
+ }
+ while (size & ~(BITS_PER_LONG-1)) {
+ if ((tmp = *(p++)))
+ goto found_middle;
+ result += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
+ }
+ if (!size)
+ return result;
+ tmp = *p;
- addr += offset / NBITS;
+found_first:
+ tmp &= (~0UL >> (BITS_PER_LONG - size));
+ if (tmp == 0UL) /* Are any bits set? */
+ return result + size; /* Nope. */
+found_middle:
+ return result + __ffs(tmp);
+}
- suboffset = offset % NBITS;
- if (suboffset) {
- tmp = *addr;
- tmp >>= suboffset;
- if (tmp)
- goto finish;
- }
+EXPORT_SYMBOL(find_next_bit);
- addr++;
+/*
+ * This implementation of find_{first,next}_zero_bit was stolen from
+ * Linus' asm-alpha/bitops.h.
+ */
+unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
+ unsigned long offset)
+{
+ const unsigned long *p = addr + BITOP_WORD(offset);
+ unsigned long result = offset & ~(BITS_PER_LONG-1);
+ unsigned long tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset %= BITS_PER_LONG;
+ if (offset) {
+ tmp = *(p++);
+ tmp |= ~0UL >> (BITS_PER_LONG - offset);
+ if (size < BITS_PER_LONG)
+ goto found_first;
+ if (~tmp)
+ goto found_middle;
+ size -= BITS_PER_LONG;
+ result += BITS_PER_LONG;
+ }
+ while (size & ~(BITS_PER_LONG-1)) {
+ if (~(tmp = *(p++)))
+ goto found_middle;
+ result += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
}
+ if (!size)
+ return result;
+ tmp = *p;
+
+found_first:
+ tmp |= ~0UL << size;
+ if (tmp == ~0UL) /* Are any bits zero? */
+ return result + size; /* Nope. */
+found_middle:
+ return result + ffz(tmp);
+}
+
+EXPORT_SYMBOL(find_next_zero_bit);
- while ((tmp = *addr) == 0)
- addr++;
+#ifdef __BIG_ENDIAN
- offset = (addr - base) * NBITS;
+/* include/linux/byteorder does not support "unsigned long" type */
+static inline unsigned long ext2_swabp(const unsigned long * x)
+{
+#if BITS_PER_LONG == 64
+ return (unsigned long) __swab64p((u64 *) x);
+#elif BITS_PER_LONG == 32
+ return (unsigned long) __swab32p((u32 *) x);
+#else
+#error BITS_PER_LONG not defined
+#endif
+}
+
+/* include/linux/byteorder doesn't support "unsigned long" type */
+static inline unsigned long ext2_swab(const unsigned long y)
+{
+#if BITS_PER_LONG == 64
+ return (unsigned long) __swab64((u64) y);
+#elif BITS_PER_LONG == 32
+ return (unsigned long) __swab32((u32) y);
+#else
+#error BITS_PER_LONG not defined
+#endif
+}
- finish:
- /* count the remaining bits without using __ffs() since that takes a 32-bit arg */
- while (!(tmp & 0xff)) {
- offset += 8;
- tmp >>= 8;
+unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, unsigned
+ long size, unsigned long offset)
+{
+ const unsigned long *p = addr + BITOP_WORD(offset);
+ unsigned long result = offset & ~(BITS_PER_LONG - 1);
+ unsigned long tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset &= (BITS_PER_LONG - 1UL);
+ if (offset) {
+ tmp = ext2_swabp(p++);
+ tmp |= (~0UL >> (BITS_PER_LONG - offset));
+ if (size < BITS_PER_LONG)
+ goto found_first;
+ if (~tmp)
+ goto found_middle;
+ size -= BITS_PER_LONG;
+ result += BITS_PER_LONG;
}
- while (!(tmp & 1)) {
- offset++;
- tmp >>= 1;
+ while (size & ~(BITS_PER_LONG - 1)) {
+ if (~(tmp = *(p++)))
+ goto found_middle_swap;
+ result += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
}
+ if (!size)
+ return result;
+ tmp = ext2_swabp(p);
+found_first:
+ tmp |= ~0UL << size;
+ if (tmp == ~0UL) /* Are any bits zero? */
+ return result + size; /* Nope. Skip ffz */
+found_middle:
+ return result + ffz(tmp);
- return offset;
+found_middle_swap:
+ return result + ffz(ext2_swab(tmp));
}
-EXPORT_SYMBOL(find_next_bit);
+EXPORT_SYMBOL(generic_find_next_zero_le_bit);
+
+#endif /* __BIG_ENDIAN */
diff --git a/lib/hweight.c b/lib/hweight.c
new file mode 100644
index 00000000000..43825767170
--- /dev/null
+++ b/lib/hweight.c
@@ -0,0 +1,53 @@
+#include <linux/module.h>
+#include <asm/types.h>
+
+/**
+ * hweightN - returns the hamming weight of a N-bit word
+ * @x: the word to weigh
+ *
+ * The Hamming Weight of a number is the total number of bits set in it.
+ */
+
+unsigned int hweight32(unsigned int w)
+{
+ unsigned int res = w - ((w >> 1) & 0x55555555);
+ res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+ res = (res + (res >> 4)) & 0x0F0F0F0F;
+ res = res + (res >> 8);
+ return (res + (res >> 16)) & 0x000000FF;
+}
+EXPORT_SYMBOL(hweight32);
+
+unsigned int hweight16(unsigned int w)
+{
+ unsigned int res = w - ((w >> 1) & 0x5555);
+ res = (res & 0x3333) + ((res >> 2) & 0x3333);
+ res = (res + (res >> 4)) & 0x0F0F;
+ return (res + (res >> 8)) & 0x00FF;
+}
+EXPORT_SYMBOL(hweight16);
+
+unsigned int hweight8(unsigned int w)
+{
+ unsigned int res = w - ((w >> 1) & 0x55);
+ res = (res & 0x33) + ((res >> 2) & 0x33);
+ return (res + (res >> 4)) & 0x0F;
+}
+EXPORT_SYMBOL(hweight8);
+
+unsigned long hweight64(__u64 w)
+{
+#if BITS_PER_LONG == 32
+ return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w);
+#elif BITS_PER_LONG == 64
+ __u64 res = w - ((w >> 1) & 0x5555555555555555ul);
+ res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
+ res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful;
+ res = res + (res >> 8);
+ res = res + (res >> 16);
+ return (res + (res >> 32)) & 0x00000000000000FFul;
+#else
+#error BITS_PER_LONG not defined
+#endif
+}
+EXPORT_SYMBOL(hweight64);
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 1e5b17dc7e3..7097bb239e4 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -37,7 +37,6 @@
#else
#define RADIX_TREE_MAP_SHIFT 3 /* For more stressful testing */
#endif
-#define RADIX_TREE_TAGS 2
#define RADIX_TREE_MAP_SIZE (1UL << RADIX_TREE_MAP_SHIFT)
#define RADIX_TREE_MAP_MASK (RADIX_TREE_MAP_SIZE-1)
@@ -48,7 +47,7 @@
struct radix_tree_node {
unsigned int count;
void *slots[RADIX_TREE_MAP_SIZE];
- unsigned long tags[RADIX_TREE_TAGS][RADIX_TREE_TAG_LONGS];
+ unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];
};
struct radix_tree_path {
@@ -135,17 +134,20 @@ out:
return ret;
}
-static inline void tag_set(struct radix_tree_node *node, int tag, int offset)
+static inline void tag_set(struct radix_tree_node *node, unsigned int tag,
+ int offset)
{
__set_bit(offset, node->tags[tag]);
}
-static inline void tag_clear(struct radix_tree_node *node, int tag, int offset)
+static inline void tag_clear(struct radix_tree_node *node, unsigned int tag,
+ int offset)
{
__clear_bit(offset, node->tags[tag]);
}
-static inline int tag_get(struct radix_tree_node *node, int tag, int offset)
+static inline int tag_get(struct radix_tree_node *node, unsigned int tag,
+ int offset)
{
return test_bit(offset, node->tags[tag]);
}
@@ -154,7 +156,7 @@ static inline int tag_get(struct radix_tree_node *node, int tag, int offset)
* Returns 1 if any slot in the node has this tag set.
* Otherwise returns 0.
*/
-static inline int any_tag_set(struct radix_tree_node *node, int tag)
+static inline int any_tag_set(struct radix_tree_node *node, unsigned int tag)
{
int idx;
for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) {
@@ -180,7 +182,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
{
struct radix_tree_node *node;
unsigned int height;
- char tags[RADIX_TREE_TAGS];
+ char tags[RADIX_TREE_MAX_TAGS];
int tag;
/* Figure out what the height should be. */
@@ -197,7 +199,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
* Prepare the tag status of the top-level node for propagation
* into the newly-pushed top-level node(s)
*/
- for (tag = 0; tag < RADIX_TREE_TAGS; tag++) {
+ for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
tags[tag] = 0;
if (any_tag_set(root->rnode, tag))
tags[tag] = 1;
@@ -211,7 +213,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
node->slots[0] = root->rnode;
/* Propagate the aggregated tag info into the new root */
- for (tag = 0; tag < RADIX_TREE_TAGS; tag++) {
+ for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
if (tags[tag])
tag_set(node, tag, 0);
}
@@ -349,14 +351,15 @@ EXPORT_SYMBOL(radix_tree_lookup);
* @index: index key
* @tag: tag index
*
- * Set the search tag corresponging to @index in the radix tree. From
+ * Set the search tag (which must be < RADIX_TREE_MAX_TAGS)
+ * corresponding to @index in the radix tree. From
* the root all the way down to the leaf node.
*
* Returns the address of the tagged item. Setting a tag on a not-present
* item is a bug.
*/
void *radix_tree_tag_set(struct radix_tree_root *root,
- unsigned long index, int tag)
+ unsigned long index, unsigned int tag)
{
unsigned int height, shift;
struct radix_tree_node *slot;
@@ -390,7 +393,8 @@ EXPORT_SYMBOL(radix_tree_tag_set);
* @index: index key
* @tag: tag index
*
- * Clear the search tag corresponging to @index in the radix tree. If
+ * Clear the search tag (which must be < RADIX_TREE_MAX_TAGS)
+ * corresponding to @index in the radix tree. If
* this causes the leaf node to have no tags set then clear the tag in the
* next-to-leaf node, etc.
*
@@ -398,7 +402,7 @@ EXPORT_SYMBOL(radix_tree_tag_set);
* has the same return value and semantics as radix_tree_lookup().
*/
void *radix_tree_tag_clear(struct radix_tree_root *root,
- unsigned long index, int tag)
+ unsigned long index, unsigned int tag)
{
struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path;
struct radix_tree_node *slot;
@@ -450,7 +454,7 @@ EXPORT_SYMBOL(radix_tree_tag_clear);
* radix_tree_tag_get - get a tag on a radix tree node
* @root: radix tree root
* @index: index key
- * @tag: tag index
+ * @tag: tag index (< RADIX_TREE_MAX_TAGS)
*
* Return values:
*
@@ -459,7 +463,7 @@ EXPORT_SYMBOL(radix_tree_tag_clear);
* -1: tag present, unset
*/
int radix_tree_tag_get(struct radix_tree_root *root,
- unsigned long index, int tag)
+ unsigned long index, unsigned int tag)
{
unsigned int height, shift;
struct radix_tree_node *slot;
@@ -592,7 +596,7 @@ EXPORT_SYMBOL(radix_tree_gang_lookup);
*/
static unsigned int
__lookup_tag(struct radix_tree_root *root, void **results, unsigned long index,
- unsigned int max_items, unsigned long *next_index, int tag)
+ unsigned int max_items, unsigned long *next_index, unsigned int tag)
{
unsigned int nr_found = 0;
unsigned int shift;
@@ -646,7 +650,7 @@ out:
* @results: where the results of the lookup are placed
* @first_index: start the lookup from this key
* @max_items: place up to this many items at *results
- * @tag: the tag index
+ * @tag: the tag index (< RADIX_TREE_MAX_TAGS)
*
* Performs an index-ascending scan of the tree for present items which
* have the tag indexed by @tag set. Places the items at *@results and
@@ -654,7 +658,8 @@ out:
*/
unsigned int
radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
- unsigned long first_index, unsigned int max_items, int tag)
+ unsigned long first_index, unsigned int max_items,
+ unsigned int tag)
{
const unsigned long max_index = radix_tree_maxindex(root->height);
unsigned long cur_index = first_index;
@@ -716,7 +721,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
struct radix_tree_node *slot;
unsigned int height, shift;
void *ret = NULL;
- char tags[RADIX_TREE_TAGS];
+ char tags[RADIX_TREE_MAX_TAGS];
int nr_cleared_tags;
int tag;
int offset;
@@ -751,7 +756,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
* Clear all tags associated with the just-deleted item
*/
nr_cleared_tags = 0;
- for (tag = 0; tag < RADIX_TREE_TAGS; tag++) {
+ for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
tags[tag] = 1;
if (tag_get(pathp->node, tag, pathp->offset)) {
tag_clear(pathp->node, tag, pathp->offset);
@@ -763,7 +768,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
}
for (pathp--; nr_cleared_tags && pathp->node; pathp--) {
- for (tag = 0; tag < RADIX_TREE_TAGS; tag++) {
+ for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
if (tags[tag])
continue;
@@ -801,7 +806,7 @@ EXPORT_SYMBOL(radix_tree_delete);
* @root: radix tree root
* @tag: tag to test
*/
-int radix_tree_tagged(struct radix_tree_root *root, int tag)
+int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag)
{
struct radix_tree_node *rnode;
rnode = root->rnode;
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 0af497b6b9a..10625785eef 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -296,8 +296,7 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
else
stride = 1;
- if (!nslots)
- BUG();
+ BUG_ON(!nslots);
/*
* Find suitable number of IO TLB entries size that will fit this
@@ -416,14 +415,14 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size,
case SYNC_FOR_CPU:
if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
memcpy(buffer, dma_addr, size);
- else if (dir != DMA_TO_DEVICE)
- BUG();
+ else
+ BUG_ON(dir != DMA_TO_DEVICE);
break;
case SYNC_FOR_DEVICE:
if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
memcpy(dma_addr, buffer, size);
- else if (dir != DMA_FROM_DEVICE)
- BUG();
+ else
+ BUG_ON(dir != DMA_FROM_DEVICE);
break;
default:
BUG();
@@ -529,8 +528,7 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
unsigned long dev_addr = virt_to_phys(ptr);
void *map;
- if (dir == DMA_NONE)
- BUG();
+ BUG_ON(dir == DMA_NONE);
/*
* If the pointer passed in happens to be in the device's DMA window,
* we can safely return the device addr and not worry about bounce
@@ -592,8 +590,7 @@ swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
{
char *dma_addr = phys_to_virt(dev_addr);
- if (dir == DMA_NONE)
- BUG();
+ BUG_ON(dir == DMA_NONE);
if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
unmap_single(hwdev, dma_addr, size, dir);
else if (dir == DMA_FROM_DEVICE)
@@ -616,8 +613,7 @@ swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
{
char *dma_addr = phys_to_virt(dev_addr);
- if (dir == DMA_NONE)
- BUG();
+ BUG_ON(dir == DMA_NONE);
if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
sync_single(hwdev, dma_addr, size, dir, target);
else if (dir == DMA_FROM_DEVICE)
@@ -648,8 +644,7 @@ swiotlb_sync_single_range(struct device *hwdev, dma_addr_t dev_addr,
{
char *dma_addr = phys_to_virt(dev_addr) + offset;
- if (dir == DMA_NONE)
- BUG();
+ BUG_ON(dir == DMA_NONE);
if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
sync_single(hwdev, dma_addr, size, dir, target);
else if (dir == DMA_FROM_DEVICE)
@@ -696,8 +691,7 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
unsigned long dev_addr;
int i;
- if (dir == DMA_NONE)
- BUG();
+ BUG_ON(dir == DMA_NONE);
for (i = 0; i < nelems; i++, sg++) {
addr = SG_ENT_VIRT_ADDRESS(sg);
@@ -730,8 +724,7 @@ swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
{
int i;
- if (dir == DMA_NONE)
- BUG();
+ BUG_ON(dir == DMA_NONE);
for (i = 0; i < nelems; i++, sg++)
if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
@@ -753,8 +746,7 @@ swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sg,
{
int i;
- if (dir == DMA_NONE)
- BUG();
+ BUG_ON(dir == DMA_NONE);
for (i = 0; i < nelems; i++, sg++)
if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
diff --git a/mm/Kconfig b/mm/Kconfig
index bd80460360d..332f5c29b53 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -138,8 +138,8 @@ config SPLIT_PTLOCK_CPUS
#
config MIGRATION
bool "Page migration"
- def_bool y if NUMA || SPARSEMEM || DISCONTIGMEM
- depends on SWAP
+ def_bool y if NUMA
+ depends on SWAP && NUMA
help
Allows the migration of the physical location of pages of processes
while the virtual addresses are not changed. This is useful for
diff --git a/mm/Makefile b/mm/Makefile
index f10c753dce6..0b8f73f2ed1 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -10,7 +10,7 @@ mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \
obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
page_alloc.o page-writeback.o pdflush.o \
readahead.o swap.o truncate.o vmscan.o \
- prio_tree.o util.o $(mmu-y)
+ prio_tree.o util.o mmzone.o $(mmu-y)
obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o
obj-$(CONFIG_HUGETLBFS) += hugetlb.o
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 35c32290f71..d3e3bd2ffce 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -33,6 +33,7 @@ EXPORT_SYMBOL(max_pfn); /* This is exported so
* dma_get_required_mask(), which uses
* it, can be an inline function */
+static LIST_HEAD(bdata_list);
#ifdef CONFIG_CRASH_DUMP
/*
* If we have booted due to a crash, max_pfn will be a very low value. We need
@@ -52,6 +53,27 @@ unsigned long __init bootmem_bootmap_pages (unsigned long pages)
return mapsize;
}
+/*
+ * link bdata in order
+ */
+static void link_bootmem(bootmem_data_t *bdata)
+{
+ bootmem_data_t *ent;
+ if (list_empty(&bdata_list)) {
+ list_add(&bdata->list, &bdata_list);
+ return;
+ }
+ /* insert in order */
+ list_for_each_entry(ent, &bdata_list, list) {
+ if (bdata->node_boot_start < ent->node_boot_start) {
+ list_add_tail(&bdata->list, &ent->list);
+ return;
+ }
+ }
+ list_add_tail(&bdata->list, &bdata_list);
+ return;
+}
+
/*
* Called once to set up the allocator itself.
@@ -62,13 +84,11 @@ static unsigned long __init init_bootmem_core (pg_data_t *pgdat,
bootmem_data_t *bdata = pgdat->bdata;
unsigned long mapsize = ((end - start)+7)/8;
- pgdat->pgdat_next = pgdat_list;
- pgdat_list = pgdat;
-
mapsize = ALIGN(mapsize, sizeof(long));
bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
bdata->node_boot_start = (start << PAGE_SHIFT);
bdata->node_low_pfn = end;
+ link_bootmem(bdata);
/*
* Initially all pages are reserved - setup_arch() has to
@@ -152,7 +172,7 @@ static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr,
*
* NOTE: This function is _not_ reentrant.
*/
-static void * __init
+void * __init
__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
unsigned long align, unsigned long goal, unsigned long limit)
{
@@ -383,12 +403,11 @@ unsigned long __init free_all_bootmem (void)
void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal)
{
- pg_data_t *pgdat = pgdat_list;
+ bootmem_data_t *bdata;
void *ptr;
- for_each_pgdat(pgdat)
- if ((ptr = __alloc_bootmem_core(pgdat->bdata, size,
- align, goal, 0)))
+ list_for_each_entry(bdata, &bdata_list, list)
+ if ((ptr = __alloc_bootmem_core(bdata, size, align, goal, 0)))
return(ptr);
/*
@@ -416,11 +435,11 @@ void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size, unsigne
void * __init __alloc_bootmem_low(unsigned long size, unsigned long align, unsigned long goal)
{
- pg_data_t *pgdat = pgdat_list;
+ bootmem_data_t *bdata;
void *ptr;
- for_each_pgdat(pgdat)
- if ((ptr = __alloc_bootmem_core(pgdat->bdata, size,
+ list_for_each_entry(bdata, &bdata_list, list)
+ if ((ptr = __alloc_bootmem_core(bdata, size,
align, goal, LOW32LIMIT)))
return(ptr);
diff --git a/mm/highmem.c b/mm/highmem.c
index d0ea1eec6a9..55885f64af4 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -31,14 +31,9 @@
static mempool_t *page_pool, *isa_page_pool;
-static void *page_pool_alloc_isa(gfp_t gfp_mask, void *data)
+static void *mempool_alloc_pages_isa(gfp_t gfp_mask, void *data)
{
- return alloc_page(gfp_mask | GFP_DMA);
-}
-
-static void page_pool_free(void *page, void *data)
-{
- __free_page(page);
+ return mempool_alloc_pages(gfp_mask | GFP_DMA, data);
}
/*
@@ -51,11 +46,6 @@ static void page_pool_free(void *page, void *data)
*/
#ifdef CONFIG_HIGHMEM
-static void *page_pool_alloc(gfp_t gfp_mask, void *data)
-{
- return alloc_page(gfp_mask);
-}
-
static int pkmap_count[LAST_PKMAP];
static unsigned int last_pkmap_nr;
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(kmap_lock);
@@ -229,7 +219,7 @@ static __init int init_emergency_pool(void)
if (!i.totalhigh)
return 0;
- page_pool = mempool_create(POOL_SIZE, page_pool_alloc, page_pool_free, NULL);
+ page_pool = mempool_create_page_pool(POOL_SIZE, 0);
if (!page_pool)
BUG();
printk("highmem bounce pool size: %d pages\n", POOL_SIZE);
@@ -272,7 +262,8 @@ int init_emergency_isa_pool(void)
if (isa_page_pool)
return 0;
- isa_page_pool = mempool_create(ISA_POOL_SIZE, page_pool_alloc_isa, page_pool_free, NULL);
+ isa_page_pool = mempool_create(ISA_POOL_SIZE, mempool_alloc_pages_isa,
+ mempool_free_pages, (void *) 0);
if (!isa_page_pool)
BUG();
@@ -337,7 +328,7 @@ static void bounce_end_io(struct bio *bio, mempool_t *pool, int err)
bio_put(bio);
}
-static int bounce_end_io_write(struct bio *bio, unsigned int bytes_done,int err)
+static int bounce_end_io_write(struct bio *bio, unsigned int bytes_done, int err)
{
if (bio->bi_size)
return 1;
@@ -384,7 +375,7 @@ static int bounce_end_io_read_isa(struct bio *bio, unsigned int bytes_done, int
}
static void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig,
- mempool_t *pool)
+ mempool_t *pool)
{
struct page *page;
struct bio *bio = NULL;
diff --git a/mm/memory.c b/mm/memory.c
index 80c3fb370f9..8d8f52569f3 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -395,12 +395,16 @@ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, pte_
return NULL;
}
-#ifdef CONFIG_DEBUG_VM
+ /*
+ * Add some anal sanity checks for now. Eventually,
+ * we should just do "return pfn_to_page(pfn)", but
+ * in the meantime we check that we get a valid pfn,
+ * and that the resulting page looks ok.
+ */
if (unlikely(!pfn_valid(pfn))) {
print_bad_pte(vma, pte, addr);
return NULL;
}
-#endif
/*
* NOTE! We still have PageReserved() pages in the page
@@ -1067,6 +1071,8 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
}
if (pages) {
pages[i] = page;
+
+ flush_anon_page(page, start);
flush_dcache_page(page);
}
if (vmas)
@@ -2348,10 +2354,8 @@ int make_pages_present(unsigned long addr, unsigned long end)
if (!vma)
return -1;
write = (vma->vm_flags & VM_WRITE) != 0;
- if (addr >= end)
- BUG();
- if (end > vma->vm_end)
- BUG();
+ BUG_ON(addr >= end);
+ BUG_ON(end > vma->vm_end);
len = (end+PAGE_SIZE-1)/PAGE_SIZE-addr/PAGE_SIZE;
ret = get_user_pages(current, current->mm, addr,
len, write, 0, NULL, NULL);
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 4f71cfd29c6..dec8249e972 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -912,7 +912,7 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
/*
* Check if this process has the right to modify the specified
* process. The right exists if the process has administrative
- * capabilities, superuser priviledges or the same
+ * capabilities, superuser privileges or the same
* userid as the target process.
*/
if ((current->euid != task->suid) && (current->euid != task->uid) &&
diff --git a/mm/mempool.c b/mm/mempool.c
index f71893ed354..fe6e05289cc 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -183,8 +183,8 @@ EXPORT_SYMBOL(mempool_resize);
*/
void mempool_destroy(mempool_t *pool)
{
- if (pool->curr_nr != pool->min_nr)
- BUG(); /* There were outstanding elements */
+ /* Check for outstanding elements */
+ BUG_ON(pool->curr_nr != pool->min_nr);
free_pool(pool);
}
EXPORT_SYMBOL(mempool_destroy);
@@ -289,3 +289,45 @@ void mempool_free_slab(void *element, void *pool_data)
kmem_cache_free(mem, element);
}
EXPORT_SYMBOL(mempool_free_slab);
+
+/*
+ * A commonly used alloc and free fn that kmalloc/kfrees the amount of memory
+ * specfied by pool_data
+ */
+void *mempool_kmalloc(gfp_t gfp_mask, void *pool_data)
+{
+ size_t size = (size_t)(long)pool_data;
+ return kmalloc(size, gfp_mask);
+}
+EXPORT_SYMBOL(mempool_kmalloc);
+
+void *mempool_kzalloc(gfp_t gfp_mask, void *pool_data)
+{
+ size_t size = (size_t) pool_data;
+ return kzalloc(size, gfp_mask);
+}
+EXPORT_SYMBOL(mempool_kzalloc);
+
+void mempool_kfree(void *element, void *pool_data)
+{
+ kfree(element);
+}
+EXPORT_SYMBOL(mempool_kfree);
+
+/*
+ * A simple mempool-backed page allocator that allocates pages
+ * of the order specified by pool_data.
+ */
+void *mempool_alloc_pages(gfp_t gfp_mask, void *pool_data)
+{
+ int order = (int)(long)pool_data;
+ return alloc_pages(gfp_mask, order);
+}
+EXPORT_SYMBOL(mempool_alloc_pages);
+
+void mempool_free_pages(void *element, void *pool_data)
+{
+ int order = (int)(long)pool_data;
+ __free_pages(element, order);
+}
+EXPORT_SYMBOL(mempool_free_pages);
diff --git a/mm/mmap.c b/mm/mmap.c
index 0eb9894db6d..4f5b5709136 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1040,12 +1040,11 @@ munmap_back:
* specific mapper. the address has already been validated, but
* not unmapped, but the maps are removed from the list.
*/
- vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
if (!vma) {
error = -ENOMEM;
goto unacct_error;
}
- memset(vma, 0, sizeof(*vma));
vma->vm_mm = mm;
vma->vm_start = addr;
@@ -1896,12 +1895,11 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
/*
* create a vma struct for an anonymous mapping
*/
- vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
if (!vma) {
vm_unacct_memory(len >> PAGE_SHIFT);
return -ENOMEM;
}
- memset(vma, 0, sizeof(*vma));
vma->vm_mm = mm;
vma->vm_start = addr;
diff --git a/mm/mmzone.c b/mm/mmzone.c
new file mode 100644
index 00000000000..b022370e612
--- /dev/null
+++ b/mm/mmzone.c
@@ -0,0 +1,50 @@
+/*
+ * linux/mm/mmzone.c
+ *
+ * management codes for pgdats and zones.
+ */
+
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/mmzone.h>
+#include <linux/module.h>
+
+struct pglist_data *first_online_pgdat(void)
+{
+ return NODE_DATA(first_online_node);
+}
+
+EXPORT_SYMBOL(first_online_pgdat);
+
+struct pglist_data *next_online_pgdat(struct pglist_data *pgdat)
+{
+ int nid = next_online_node(pgdat->node_id);
+
+ if (nid == MAX_NUMNODES)
+ return NULL;
+ return NODE_DATA(nid);
+}
+EXPORT_SYMBOL(next_online_pgdat);
+
+
+/*
+ * next_zone - helper magic for for_each_zone()
+ */
+struct zone *next_zone(struct zone *zone)
+{
+ pg_data_t *pgdat = zone->zone_pgdat;
+
+ if (zone < pgdat->node_zones + MAX_NR_ZONES - 1)
+ zone++;
+ else {
+ pgdat = next_online_pgdat(pgdat);
+ if (pgdat)
+ zone = pgdat->node_zones;
+ else
+ zone = NULL;
+ }
+ return zone;
+}
+EXPORT_SYMBOL(next_zone);
+
diff --git a/mm/msync.c b/mm/msync.c
index 2672b8dc3d8..bc6c9537636 100644
--- a/mm/msync.c
+++ b/mm/msync.c
@@ -126,7 +126,7 @@ static unsigned long msync_page_range(struct vm_area_struct *vma,
* write out the dirty pages and wait on the writeout and check the result.
* Or the application may run fadvise(FADV_DONTNEED) against the fd to start
* async writeout immediately.
- * So my _not_ starting I/O in MS_ASYNC we provide complete flexibility to
+ * So by _not_ starting I/O in MS_ASYNC we provide complete flexibility to
* applications.
*/
static int msync_interval(struct vm_area_struct *vma, unsigned long addr,
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index a5c3f8bd98a..dc523a1f270 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -49,7 +49,6 @@ nodemask_t node_online_map __read_mostly = { { [0] = 1UL } };
EXPORT_SYMBOL(node_online_map);
nodemask_t node_possible_map __read_mostly = NODE_MASK_ALL;
EXPORT_SYMBOL(node_possible_map);
-struct pglist_data *pgdat_list __read_mostly;
unsigned long totalram_pages __read_mostly;
unsigned long totalhigh_pages __read_mostly;
long nr_swap_pages;
@@ -1201,7 +1200,7 @@ unsigned int nr_free_highpages (void)
pg_data_t *pgdat;
unsigned int pages = 0;
- for_each_pgdat(pgdat)
+ for_each_online_pgdat(pgdat)
pages += pgdat->node_zones[ZONE_HIGHMEM].free_pages;
return pages;
@@ -1343,7 +1342,7 @@ void get_zone_counts(unsigned long *active,
*active = 0;
*inactive = 0;
*free = 0;
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
unsigned long l, m, n;
__get_zone_counts(&l, &m, &n, pgdat);
*active += l;
@@ -2029,8 +2028,9 @@ static __meminit void zone_pcp_init(struct zone *zone)
setup_pageset(zone_pcp(zone,cpu), batch);
#endif
}
- printk(KERN_DEBUG " %s zone: %lu pages, LIFO batch:%lu\n",
- zone->name, zone->present_pages, batch);
+ if (zone->present_pages)
+ printk(KERN_DEBUG " %s zone: %lu pages, LIFO batch:%lu\n",
+ zone->name, zone->present_pages, batch);
}
static __meminit void init_currently_empty_zone(struct zone *zone,
@@ -2041,7 +2041,6 @@ static __meminit void init_currently_empty_zone(struct zone *zone,
zone_wait_table_init(zone, size);
pgdat->nr_zones = zone_idx(zone) + 1;
- zone->zone_mem_map = pfn_to_page(zone_start_pfn);
zone->zone_start_pfn = zone_start_pfn;
memmap_init(size, pgdat->node_id, zone_idx(zone), zone_start_pfn);
@@ -2169,8 +2168,9 @@ static void *frag_start(struct seq_file *m, loff_t *pos)
{
pg_data_t *pgdat;
loff_t node = *pos;
-
- for (pgdat = pgdat_list; pgdat && node; pgdat = pgdat->pgdat_next)
+ for (pgdat = first_online_pgdat();
+ pgdat && node;
+ pgdat = next_online_pgdat(pgdat))
--node;
return pgdat;
@@ -2181,7 +2181,7 @@ static void *frag_next(struct seq_file *m, void *arg, loff_t *pos)
pg_data_t *pgdat = (pg_data_t *)arg;
(*pos)++;
- return pgdat->pgdat_next;
+ return next_online_pgdat(pgdat);
}
static void frag_stop(struct seq_file *m, void *arg)
@@ -2482,7 +2482,7 @@ static void setup_per_zone_lowmem_reserve(void)
struct pglist_data *pgdat;
int j, idx;
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
for (j = 0; j < MAX_NR_ZONES; j++) {
struct zone *zone = pgdat->node_zones + j;
unsigned long present_pages = zone->present_pages;
@@ -2701,8 +2701,7 @@ void *__init alloc_large_system_hash(const char *tablename,
else
numentries <<= (PAGE_SHIFT - scale);
}
- /* rounded up to nearest power of 2 in size */
- numentries = 1UL << (long_log2(numentries) + 1);
+ numentries = roundup_pow_of_two(numentries);
/* limit allocation size to 1/16 total memory by default */
if (max == 0) {
@@ -2745,3 +2744,44 @@ void *__init alloc_large_system_hash(const char *tablename,
return table;
}
+
+#ifdef CONFIG_OUT_OF_LINE_PFN_TO_PAGE
+/*
+ * pfn <-> page translation. out-of-line version.
+ * (see asm-generic/memory_model.h)
+ */
+#if defined(CONFIG_FLATMEM)
+struct page *pfn_to_page(unsigned long pfn)
+{
+ return mem_map + (pfn - ARCH_PFN_OFFSET);
+}
+unsigned long page_to_pfn(struct page *page)
+{
+ return (page - mem_map) + ARCH_PFN_OFFSET;
+}
+#elif defined(CONFIG_DISCONTIGMEM)
+struct page *pfn_to_page(unsigned long pfn)
+{
+ int nid = arch_pfn_to_nid(pfn);
+ return NODE_DATA(nid)->node_mem_map + arch_local_page_offset(pfn,nid);
+}
+unsigned long page_to_pfn(struct page *page)
+{
+ struct pglist_data *pgdat = NODE_DATA(page_to_nid(page));
+ return (page - pgdat->node_mem_map) + pgdat->node_start_pfn;
+}
+#elif defined(CONFIG_SPARSEMEM)
+struct page *pfn_to_page(unsigned long pfn)
+{
+ return __section_mem_map_addr(__pfn_to_section(pfn)) + pfn;
+}
+
+unsigned long page_to_pfn(struct page *page)
+{
+ long section_id = page_to_section(page);
+ return page - __section_mem_map_addr(__nr_to_section(section_id));
+}
+#endif /* CONFIG_FLATMEM/DISCONTIGMME/SPARSEMEM */
+EXPORT_SYMBOL(pfn_to_page);
+EXPORT_SYMBOL(page_to_pfn);
+#endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
diff --git a/mm/slab.c b/mm/slab.c
index 26138c9f8f0..4cbf8bb1355 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -204,7 +204,8 @@
typedef unsigned int kmem_bufctl_t;
#define BUFCTL_END (((kmem_bufctl_t)(~0U))-0)
#define BUFCTL_FREE (((kmem_bufctl_t)(~0U))-1)
-#define SLAB_LIMIT (((kmem_bufctl_t)(~0U))-2)
+#define BUFCTL_ACTIVE (((kmem_bufctl_t)(~0U))-2)
+#define SLAB_LIMIT (((kmem_bufctl_t)(~0U))-3)
/* Max number of objs-per-slab for caches which use off-slab slabs.
* Needed to avoid a possible looping condition in cache_grow().
@@ -897,6 +898,30 @@ static struct array_cache *alloc_arraycache(int node, int entries,
return nc;
}
+/*
+ * Transfer objects in one arraycache to another.
+ * Locking must be handled by the caller.
+ *
+ * Return the number of entries transferred.
+ */
+static int transfer_objects(struct array_cache *to,
+ struct array_cache *from, unsigned int max)
+{
+ /* Figure out how many entries to transfer */
+ int nr = min(min(from->avail, max), to->limit - to->avail);
+
+ if (!nr)
+ return 0;
+
+ memcpy(to->entry + to->avail, from->entry + from->avail -nr,
+ sizeof(void *) *nr);
+
+ from->avail -= nr;
+ to->avail += nr;
+ to->touched = 1;
+ return nr;
+}
+
#ifdef CONFIG_NUMA
static void *__cache_alloc_node(struct kmem_cache *, gfp_t, int);
static void *alternate_node_alloc(struct kmem_cache *, gfp_t);
@@ -946,6 +971,13 @@ static void __drain_alien_cache(struct kmem_cache *cachep,
if (ac->avail) {
spin_lock(&rl3->list_lock);
+ /*
+ * Stuff objects into the remote nodes shared array first.
+ * That way we could avoid the overhead of putting the objects
+ * into the free lists and getting them back later.
+ */
+ transfer_objects(rl3->shared, ac, ac->limit);
+
free_block(cachep, ac->entry, ac->avail, node);
ac->avail = 0;
spin_unlock(&rl3->list_lock);
@@ -961,8 +993,8 @@ static void reap_alien(struct kmem_cache *cachep, struct kmem_list3 *l3)
if (l3->alien) {
struct array_cache *ac = l3->alien[node];
- if (ac && ac->avail) {
- spin_lock_irq(&ac->lock);
+
+ if (ac && ac->avail && spin_trylock_irq(&ac->lock)) {
__drain_alien_cache(cachep, ac, node);
spin_unlock_irq(&ac->lock);
}
@@ -1989,10 +2021,9 @@ kmem_cache_create (const char *name, size_t size, size_t align,
align = ralign;
/* Get cache's description obj. */
- cachep = kmem_cache_alloc(&cache_cache, SLAB_KERNEL);
+ cachep = kmem_cache_zalloc(&cache_cache, SLAB_KERNEL);
if (!cachep)
goto oops;
- memset(cachep, 0, sizeof(struct kmem_cache));
#if DEBUG
cachep->obj_size = size;
@@ -2399,7 +2430,7 @@ static void slab_put_obj(struct kmem_cache *cachep, struct slab *slabp,
/* Verify that the slab belongs to the intended node */
WARN_ON(slabp->nodeid != nodeid);
- if (slab_bufctl(slabp)[objnr] != BUFCTL_FREE) {
+ if (slab_bufctl(slabp)[objnr] + 1 <= SLAB_LIMIT + 1) {
printk(KERN_ERR "slab: double free detected in cache "
"'%s', objp %p\n", cachep->name, objp);
BUG();
@@ -2605,6 +2636,9 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
*/
cachep->dtor(objp + obj_offset(cachep), cachep, 0);
}
+#ifdef CONFIG_DEBUG_SLAB_LEAK
+ slab_bufctl(slabp)[objnr] = BUFCTL_FREE;
+#endif
if (cachep->flags & SLAB_POISON) {
#ifdef CONFIG_DEBUG_PAGEALLOC
if ((cachep->buffer_size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) {
@@ -2677,20 +2711,10 @@ retry:
BUG_ON(ac->avail > 0 || !l3);
spin_lock(&l3->list_lock);
- if (l3->shared) {
- struct array_cache *shared_array = l3->shared;
- if (shared_array->avail) {
- if (batchcount > shared_array->avail)
- batchcount = shared_array->avail;
- shared_array->avail -= batchcount;
- ac->avail = batchcount;
- memcpy(ac->entry,
- &(shared_array->entry[shared_array->avail]),
- sizeof(void *) * batchcount);
- shared_array->touched = 1;
- goto alloc_done;
- }
- }
+ /* See if we can refill from the shared array */
+ if (l3->shared && transfer_objects(ac, l3->shared, batchcount))
+ goto alloc_done;
+
while (batchcount > 0) {
struct list_head *entry;
struct slab *slabp;
@@ -2788,6 +2812,16 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
*dbg_redzone1(cachep, objp) = RED_ACTIVE;
*dbg_redzone2(cachep, objp) = RED_ACTIVE;
}
+#ifdef CONFIG_DEBUG_SLAB_LEAK
+ {
+ struct slab *slabp;
+ unsigned objnr;
+
+ slabp = page_get_slab(virt_to_page(objp));
+ objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size;
+ slab_bufctl(slabp)[objnr] = BUFCTL_ACTIVE;
+ }
+#endif
objp += obj_offset(cachep);
if (cachep->ctor && cachep->flags & SLAB_POISON) {
unsigned long ctor_flags = SLAB_CTOR_CONSTRUCTOR;
@@ -3094,6 +3128,23 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
EXPORT_SYMBOL(kmem_cache_alloc);
/**
+ * kmem_cache_alloc - Allocate an object. The memory is set to zero.
+ * @cache: The cache to allocate from.
+ * @flags: See kmalloc().
+ *
+ * Allocate an object from this cache and set the allocated memory to zero.
+ * The flags are only relevant if the cache has no available objects.
+ */
+void *kmem_cache_zalloc(struct kmem_cache *cache, gfp_t flags)
+{
+ void *ret = __cache_alloc(cache, flags, __builtin_return_address(0));
+ if (ret)
+ memset(ret, 0, obj_size(cache));
+ return ret;
+}
+EXPORT_SYMBOL(kmem_cache_zalloc);
+
+/**
* kmem_ptr_validate - check if an untrusted pointer might
* be a slab entry.
* @cachep: the cache we're checking against
@@ -3220,22 +3271,23 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,
return __cache_alloc(cachep, flags, caller);
}
-#ifndef CONFIG_DEBUG_SLAB
void *__kmalloc(size_t size, gfp_t flags)
{
+#ifndef CONFIG_DEBUG_SLAB
return __do_kmalloc(size, flags, NULL);
+#else
+ return __do_kmalloc(size, flags, __builtin_return_address(0));
+#endif
}
EXPORT_SYMBOL(__kmalloc);
-#else
-
+#ifdef CONFIG_DEBUG_SLAB
void *__kmalloc_track_caller(size_t size, gfp_t flags, void *caller)
{
return __do_kmalloc(size, flags, caller);
}
EXPORT_SYMBOL(__kmalloc_track_caller);
-
#endif
#ifdef CONFIG_SMP
@@ -3259,7 +3311,7 @@ void *__alloc_percpu(size_t size)
* and we have no way of figuring out how to fix the array
* that we have allocated then....
*/
- for_each_cpu(i) {
+ for_each_possible_cpu(i) {
int node = cpu_to_node(i);
if (node_online(node))
@@ -3346,7 +3398,7 @@ void free_percpu(const void *objp)
/*
* We allocate for all cpus so we cannot use for online cpu here.
*/
- for_each_cpu(i)
+ for_each_possible_cpu(i)
kfree(p->ptrs[i]);
kfree(p);
}
@@ -3366,63 +3418,86 @@ const char *kmem_cache_name(struct kmem_cache *cachep)
EXPORT_SYMBOL_GPL(kmem_cache_name);
/*
- * This initializes kmem_list3 for all nodes.
+ * This initializes kmem_list3 or resizes varioius caches for all nodes.
*/
static int alloc_kmemlist(struct kmem_cache *cachep)
{
int node;
struct kmem_list3 *l3;
- int err = 0;
+ struct array_cache *new_shared;
+ struct array_cache **new_alien;
for_each_online_node(node) {
- struct array_cache *nc = NULL, *new;
- struct array_cache **new_alien = NULL;
-#ifdef CONFIG_NUMA
+
new_alien = alloc_alien_cache(node, cachep->limit);
if (!new_alien)
goto fail;
-#endif
- new = alloc_arraycache(node, cachep->shared*cachep->batchcount,
+
+ new_shared = alloc_arraycache(node,
+ cachep->shared*cachep->batchcount,
0xbaadf00d);
- if (!new)
+ if (!new_shared) {
+ free_alien_cache(new_alien);
goto fail;
+ }
+
l3 = cachep->nodelists[node];
if (l3) {
+ struct array_cache *shared = l3->shared;
+
spin_lock_irq(&l3->list_lock);
- nc = cachep->nodelists[node]->shared;
- if (nc)
- free_block(cachep, nc->entry, nc->avail, node);
+ if (shared)
+ free_block(cachep, shared->entry,
+ shared->avail, node);
- l3->shared = new;
- if (!cachep->nodelists[node]->alien) {
+ l3->shared = new_shared;
+ if (!l3->alien) {
l3->alien = new_alien;
new_alien = NULL;
}
l3->free_limit = (1 + nr_cpus_node(node)) *
cachep->batchcount + cachep->num;
spin_unlock_irq(&l3->list_lock);
- kfree(nc);
+ kfree(shared);
free_alien_cache(new_alien);
continue;
}
l3 = kmalloc_node(sizeof(struct kmem_list3), GFP_KERNEL, node);
- if (!l3)
+ if (!l3) {
+ free_alien_cache(new_alien);
+ kfree(new_shared);
goto fail;
+ }
kmem_list3_init(l3);
l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
((unsigned long)cachep) % REAPTIMEOUT_LIST3;
- l3->shared = new;
+ l3->shared = new_shared;
l3->alien = new_alien;
l3->free_limit = (1 + nr_cpus_node(node)) *
cachep->batchcount + cachep->num;
cachep->nodelists[node] = l3;
}
- return err;
+ return 0;
+
fail:
- err = -ENOMEM;
- return err;
+ if (!cachep->next.next) {
+ /* Cache is not active yet. Roll back what we did */
+ node--;
+ while (node >= 0) {
+ if (cachep->nodelists[node]) {
+ l3 = cachep->nodelists[node];
+
+ kfree(l3->shared);
+ free_alien_cache(l3->alien);
+ kfree(l3);
+ cachep->nodelists[node] = NULL;
+ }
+ node--;
+ }
+ }
+ return -ENOMEM;
}
struct ccupdate_struct {
@@ -3899,6 +3974,159 @@ ssize_t slabinfo_write(struct file *file, const char __user * buffer,
res = count;
return res;
}
+
+#ifdef CONFIG_DEBUG_SLAB_LEAK
+
+static void *leaks_start(struct seq_file *m, loff_t *pos)
+{
+ loff_t n = *pos;
+ struct list_head *p;
+
+ mutex_lock(&cache_chain_mutex);
+ p = cache_chain.next;
+ while (n--) {
+ p = p->next;
+ if (p == &cache_chain)
+ return NULL;
+ }
+ return list_entry(p, struct kmem_cache, next);
+}
+
+static inline int add_caller(unsigned long *n, unsigned long v)
+{
+ unsigned long *p;
+ int l;
+ if (!v)
+ return 1;
+ l = n[1];
+ p = n + 2;
+ while (l) {
+ int i = l/2;
+ unsigned long *q = p + 2 * i;
+ if (*q == v) {
+ q[1]++;
+ return 1;
+ }
+ if (*q > v) {
+ l = i;
+ } else {
+ p = q + 2;
+ l -= i + 1;
+ }
+ }
+ if (++n[1] == n[0])
+ return 0;
+ memmove(p + 2, p, n[1] * 2 * sizeof(unsigned long) - ((void *)p - (void *)n));
+ p[0] = v;
+ p[1] = 1;
+ return 1;
+}
+
+static void handle_slab(unsigned long *n, struct kmem_cache *c, struct slab *s)
+{
+ void *p;
+ int i;
+ if (n[0] == n[1])
+ return;
+ for (i = 0, p = s->s_mem; i < c->num; i++, p += c->buffer_size) {
+ if (slab_bufctl(s)[i] != BUFCTL_ACTIVE)
+ continue;
+ if (!add_caller(n, (unsigned long)*dbg_userword(c, p)))
+ return;
+ }
+}
+
+static void show_symbol(struct seq_file *m, unsigned long address)
+{
+#ifdef CONFIG_KALLSYMS
+ char *modname;
+ const char *name;
+ unsigned long offset, size;
+ char namebuf[KSYM_NAME_LEN+1];
+
+ name = kallsyms_lookup(address, &size, &offset, &modname, namebuf);
+
+ if (name) {
+ seq_printf(m, "%s+%#lx/%#lx", name, offset, size);
+ if (modname)
+ seq_printf(m, " [%s]", modname);
+ return;
+ }
+#endif
+ seq_printf(m, "%p", (void *)address);
+}
+
+static int leaks_show(struct seq_file *m, void *p)
+{
+ struct kmem_cache *cachep = p;
+ struct list_head *q;
+ struct slab *slabp;
+ struct kmem_list3 *l3;
+ const char *name;
+ unsigned long *n = m->private;
+ int node;
+ int i;
+
+ if (!(cachep->flags & SLAB_STORE_USER))
+ return 0;
+ if (!(cachep->flags & SLAB_RED_ZONE))
+ return 0;
+
+ /* OK, we can do it */
+
+ n[1] = 0;
+
+ for_each_online_node(node) {
+ l3 = cachep->nodelists[node];
+ if (!l3)
+ continue;
+
+ check_irq_on();
+ spin_lock_irq(&l3->list_lock);
+
+ list_for_each(q, &l3->slabs_full) {
+ slabp = list_entry(q, struct slab, list);
+ handle_slab(n, cachep, slabp);
+ }
+ list_for_each(q, &l3->slabs_partial) {
+ slabp = list_entry(q, struct slab, list);
+ handle_slab(n, cachep, slabp);
+ }
+ spin_unlock_irq(&l3->list_lock);
+ }
+ name = cachep->name;
+ if (n[0] == n[1]) {
+ /* Increase the buffer size */
+ mutex_unlock(&cache_chain_mutex);
+ m->private = kzalloc(n[0] * 4 * sizeof(unsigned long), GFP_KERNEL);
+ if (!m->private) {
+ /* Too bad, we are really out */
+ m->private = n;
+ mutex_lock(&cache_chain_mutex);
+ return -ENOMEM;
+ }
+ *(unsigned long *)m->private = n[0] * 2;
+ kfree(n);
+ mutex_lock(&cache_chain_mutex);
+ /* Now make sure this entry will be retried */
+ m->count = m->size;
+ return 0;
+ }
+ for (i = 0; i < n[1]; i++) {
+ seq_printf(m, "%s: %lu ", name, n[2*i+3]);
+ show_symbol(m, n[2*i+2]);
+ seq_putc(m, '\n');
+ }
+ return 0;
+}
+
+struct seq_operations slabstats_op = {
+ .start = leaks_start,
+ .next = s_next,
+ .stop = s_stop,
+ .show = leaks_show,
+};
+#endif
#endif
/**
diff --git a/mm/slob.c b/mm/slob.c
index a1f42bdc024..9bcc7e2cabf 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -294,6 +294,16 @@ void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags)
}
EXPORT_SYMBOL(kmem_cache_alloc);
+void *kmem_cache_zalloc(struct kmem_cache *c, gfp_t flags)
+{
+ void *ret = kmem_cache_alloc(c, flags);
+ if (ret)
+ memset(ret, 0, c->size);
+
+ return ret;
+}
+EXPORT_SYMBOL(kmem_cache_zalloc);
+
void kmem_cache_free(struct kmem_cache *c, void *b)
{
if (c->dtor)
diff --git a/mm/swap.c b/mm/swap.c
index 91b7e2026f6..88895c249bc 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -512,7 +512,7 @@ long percpu_counter_sum(struct percpu_counter *fbc)
spin_lock(&fbc->lock);
ret = fbc->count;
- for_each_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
long *pcount = per_cpu_ptr(fbc->counters, cpu);
ret += *pcount;
}
diff --git a/mm/util.c b/mm/util.c
index 49e29f751b5..7368479220b 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -5,18 +5,18 @@
#include <asm/uaccess.h>
/**
- * kzalloc - allocate memory. The memory is set to zero.
+ * __kzalloc - allocate memory. The memory is set to zero.
* @size: how many bytes of memory are required.
* @flags: the type of memory to allocate.
*/
-void *kzalloc(size_t size, gfp_t flags)
+void *__kzalloc(size_t size, gfp_t flags)
{
- void *ret = kmalloc(size, flags);
+ void *ret = ____kmalloc(size, flags);
if (ret)
memset(ret, 0, size);
return ret;
}
-EXPORT_SYMBOL(kzalloc);
+EXPORT_SYMBOL(__kzalloc);
/*
* kstrdup - allocate space for and copy an existing string
@@ -33,7 +33,7 @@ char *kstrdup(const char *s, gfp_t gfp)
return NULL;
len = strlen(s) + 1;
- buf = kmalloc(len, gfp);
+ buf = ____kmalloc(len, gfp);
if (buf)
memcpy(buf, s, len);
return buf;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index fd572bbdc9f..acdf001d694 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1305,7 +1305,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
current->reclaim_state = &reclaim_state;
repeat:
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
unsigned long freed;
freed = balance_pgdat(pgdat, nr_to_free, 0);
@@ -1335,7 +1335,7 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
cpumask_t mask;
if (action == CPU_ONLINE) {
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
mask = node_to_cpumask(pgdat->node_id);
if (any_online_cpu(mask) != NR_CPUS)
/* One of our CPUs online: restore mask */
@@ -1351,12 +1351,14 @@ static int __init kswapd_init(void)
pg_data_t *pgdat;
swap_setup();
- for_each_pgdat(pgdat) {
+ for_each_online_pgdat(pgdat) {
pid_t pid;
pid = kernel_thread(kswapd, pgdat, CLONE_KERNEL);
BUG_ON(pid < 0);
+ read_lock(&tasklist_lock);
pgdat->kswapd = find_task_by_pid(pid);
+ read_unlock(&tasklist_lock);
}
total_memory = nr_free_pagecache_pages();
hotcpu_notifier(cpu_callback, 0);
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 697ac55e29d..7b1eb9a4fc9 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1819,6 +1819,22 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return rc;
}
+
+#ifdef CONFIG_COMPAT
+static int atalk_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ /*
+ * All Appletalk ioctls except SIOCATALKDIFADDR are standard. And
+ * SIOCATALKDIFADDR is handled by upper layer as well, so there is
+ * nothing to do. Eventually SIOCATALKDIFADDR should be moved
+ * here so there is no generic SIOCPROTOPRIVATE translation in the
+ * system.
+ */
+ return -ENOIOCTLCMD;
+}
+#endif
+
+
static struct net_proto_family atalk_family_ops = {
.family = PF_APPLETALK,
.create = atalk_create,
@@ -1836,6 +1852,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
.getname = atalk_getname,
.poll = datagram_poll,
.ioctl = atalk_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = atalk_compat_ioctl,
+#endif
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt,
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index fb031fe9be9..469eda0f0df 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -238,6 +238,9 @@ unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *w
if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
mask |= POLLERR;
+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ mask |= POLLRDHUP;
+
if (sk->sk_shutdown == SHUTDOWN_MASK)
mask |= POLLHUP;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 9106354c781..a49a6975092 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -73,23 +73,23 @@ DEFINE_RWLOCK(hci_cb_list_lock);
struct hci_proto *hci_proto[HCI_MAX_PROTO];
/* HCI notifiers list */
-static struct notifier_block *hci_notifier;
+static ATOMIC_NOTIFIER_HEAD(hci_notifier);
/* ---- HCI notifications ---- */
int hci_register_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&hci_notifier, nb);
+ return atomic_notifier_chain_register(&hci_notifier, nb);
}
int hci_unregister_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&hci_notifier, nb);
+ return atomic_notifier_chain_unregister(&hci_notifier, nb);
}
static void hci_notify(struct hci_dev *hdev, int event)
{
- notifier_call_chain(&hci_notifier, event, hdev);
+ atomic_notifier_call_chain(&hci_notifier, event, hdev);
}
/* ---- HCI requests ---- */
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
index 8934a54792b..a7ba0cce0b4 100644
--- a/net/bridge/br_stp_bpdu.c
+++ b/net/bridge/br_stp_bpdu.c
@@ -19,6 +19,7 @@
#include <linux/llc.h>
#include <net/llc.h>
#include <net/llc_pdu.h>
+#include <asm/unaligned.h>
#include "br_private.h"
#include "br_private_stp.h"
@@ -59,12 +60,12 @@ static inline void br_set_ticks(unsigned char *dest, int j)
{
unsigned long ticks = (STP_HZ * j)/ HZ;
- *((__be16 *) dest) = htons(ticks);
+ put_unaligned(htons(ticks), (__be16 *)dest);
}
static inline int br_get_ticks(const unsigned char *src)
{
- unsigned long ticks = ntohs(*(__be16 *)src);
+ unsigned long ticks = ntohs(get_unaligned((__be16 *)src));
return (ticks * HZ + STP_HZ - 1) / STP_HZ;
}
diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c
index 468ebdf4bc1..d42f63f5e9f 100644
--- a/net/bridge/netfilter/ebt_802_3.c
+++ b/net/bridge/netfilter/ebt_802_3.c
@@ -58,16 +58,16 @@ static struct ebt_match filter_802_3 =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_802_3_init(void)
{
return ebt_register_match(&filter_802_3);
}
-static void __exit fini(void)
+static void __exit ebt_802_3_fini(void)
{
ebt_unregister_match(&filter_802_3);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_802_3_init);
+module_exit(ebt_802_3_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c
index 5a1f5e3bff1..a614485828a 100644
--- a/net/bridge/netfilter/ebt_among.c
+++ b/net/bridge/netfilter/ebt_among.c
@@ -213,16 +213,16 @@ static struct ebt_match filter_among = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_among_init(void)
{
return ebt_register_match(&filter_among);
}
-static void __exit fini(void)
+static void __exit ebt_among_fini(void)
{
ebt_unregister_match(&filter_among);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_among_init);
+module_exit(ebt_among_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
index b94c48cb6e4..a6c81d9f73b 100644
--- a/net/bridge/netfilter/ebt_arp.c
+++ b/net/bridge/netfilter/ebt_arp.c
@@ -125,16 +125,16 @@ static struct ebt_match filter_arp =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_arp_init(void)
{
return ebt_register_match(&filter_arp);
}
-static void __exit fini(void)
+static void __exit ebt_arp_fini(void)
{
ebt_unregister_match(&filter_arp);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_arp_init);
+module_exit(ebt_arp_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
index b934de90f7c..d19fc4b328d 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -82,16 +82,16 @@ static struct ebt_target reply_target =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_arpreply_init(void)
{
return ebt_register_target(&reply_target);
}
-static void __exit fini(void)
+static void __exit ebt_arpreply_fini(void)
{
ebt_unregister_target(&reply_target);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_arpreply_init);
+module_exit(ebt_arpreply_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
index f5463086c7b..4582659dff0 100644
--- a/net/bridge/netfilter/ebt_dnat.c
+++ b/net/bridge/netfilter/ebt_dnat.c
@@ -61,16 +61,16 @@ static struct ebt_target dnat =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_dnat_init(void)
{
return ebt_register_target(&dnat);
}
-static void __exit fini(void)
+static void __exit ebt_dnat_fini(void)
{
ebt_unregister_target(&dnat);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_dnat_init);
+module_exit(ebt_dnat_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
index dc5d0b2427c..65b665ce57b 100644
--- a/net/bridge/netfilter/ebt_ip.c
+++ b/net/bridge/netfilter/ebt_ip.c
@@ -112,16 +112,16 @@ static struct ebt_match filter_ip =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_ip_init(void)
{
return ebt_register_match(&filter_ip);
}
-static void __exit fini(void)
+static void __exit ebt_ip_fini(void)
{
ebt_unregister_match(&filter_ip);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_ip_init);
+module_exit(ebt_ip_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_limit.c b/net/bridge/netfilter/ebt_limit.c
index 637c8844cd5..d48fa5cb26c 100644
--- a/net/bridge/netfilter/ebt_limit.c
+++ b/net/bridge/netfilter/ebt_limit.c
@@ -98,16 +98,16 @@ static struct ebt_match ebt_limit_reg =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_limit_init(void)
{
return ebt_register_match(&ebt_limit_reg);
}
-static void __exit fini(void)
+static void __exit ebt_limit_fini(void)
{
ebt_unregister_match(&ebt_limit_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_limit_init);
+module_exit(ebt_limit_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 288ff1d4ccc..d159c92cca8 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -188,7 +188,7 @@ static struct nf_logger ebt_log_logger = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_log_init(void)
{
int ret;
@@ -205,12 +205,12 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ebt_log_fini(void)
{
nf_log_unregister_logger(&ebt_log_logger);
ebt_unregister_watcher(&log);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_log_init);
+module_exit(ebt_log_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index c93d35ab95c..770c0df972a 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -52,16 +52,16 @@ static struct ebt_target mark_target =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_mark_init(void)
{
return ebt_register_target(&mark_target);
}
-static void __exit fini(void)
+static void __exit ebt_mark_fini(void)
{
ebt_unregister_target(&mark_target);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_mark_init);
+module_exit(ebt_mark_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c
index 625102de149..a6413e4b498 100644
--- a/net/bridge/netfilter/ebt_mark_m.c
+++ b/net/bridge/netfilter/ebt_mark_m.c
@@ -47,16 +47,16 @@ static struct ebt_match filter_mark =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_mark_m_init(void)
{
return ebt_register_match(&filter_mark);
}
-static void __exit fini(void)
+static void __exit ebt_mark_m_fini(void)
{
ebt_unregister_match(&filter_mark);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_mark_m_init);
+module_exit(ebt_mark_m_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_pkttype.c b/net/bridge/netfilter/ebt_pkttype.c
index ecd3b42b19b..4fffd70e4da 100644
--- a/net/bridge/netfilter/ebt_pkttype.c
+++ b/net/bridge/netfilter/ebt_pkttype.c
@@ -44,16 +44,16 @@ static struct ebt_match filter_pkttype =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_pkttype_init(void)
{
return ebt_register_match(&filter_pkttype);
}
-static void __exit fini(void)
+static void __exit ebt_pkttype_fini(void)
{
ebt_unregister_match(&filter_pkttype);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_pkttype_init);
+module_exit(ebt_pkttype_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index 1538b438666..9f378eab72d 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -66,16 +66,16 @@ static struct ebt_target redirect_target =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_redirect_init(void)
{
return ebt_register_target(&redirect_target);
}
-static void __exit fini(void)
+static void __exit ebt_redirect_fini(void)
{
ebt_unregister_target(&redirect_target);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_redirect_init);
+module_exit(ebt_redirect_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index 1529bdcb9a4..cbb33e24ca8 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -61,16 +61,16 @@ static struct ebt_target snat =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_snat_init(void)
{
return ebt_register_target(&snat);
}
-static void __exit fini(void)
+static void __exit ebt_snat_fini(void)
{
ebt_unregister_target(&snat);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_snat_init);
+module_exit(ebt_snat_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c
index 0248c67277e..a0bed82145e 100644
--- a/net/bridge/netfilter/ebt_stp.c
+++ b/net/bridge/netfilter/ebt_stp.c
@@ -180,16 +180,16 @@ static struct ebt_match filter_stp =
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_stp_init(void)
{
return ebt_register_match(&filter_stp);
}
-static void __exit fini(void)
+static void __exit ebt_stp_fini(void)
{
ebt_unregister_match(&filter_stp);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_stp_init);
+module_exit(ebt_stp_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 802baf755ef..ee5a5176126 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -281,7 +281,7 @@ static struct nf_logger ebt_ulog_logger = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_ulog_init(void)
{
int i, ret = 0;
@@ -316,7 +316,7 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit ebt_ulog_fini(void)
{
ebt_ulog_buff_t *ub;
int i;
@@ -337,8 +337,8 @@ static void __exit fini(void)
sock_release(ebtulognl->sk_socket);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_ulog_init);
+module_exit(ebt_ulog_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
MODULE_DESCRIPTION("ebtables userspace logging module for bridged Ethernet"
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
index db60d734908..a2b452862b7 100644
--- a/net/bridge/netfilter/ebt_vlan.c
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -178,7 +178,7 @@ static struct ebt_match filter_vlan = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ebt_vlan_init(void)
{
DEBUG_MSG("ebtables 802.1Q extension module v"
MODULE_VERS "\n");
@@ -186,10 +186,10 @@ static int __init init(void)
return ebt_register_match(&filter_vlan);
}
-static void __exit fini(void)
+static void __exit ebt_vlan_fini(void)
{
ebt_unregister_match(&filter_vlan);
}
-module_init(init);
-module_exit(fini);
+module_init(ebt_vlan_init);
+module_exit(ebt_vlan_fini);
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index 1767c94cd3d..9a6e548e148 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -62,7 +62,7 @@ static int ebt_broute(struct sk_buff **pskb)
return 0; /* bridge it */
}
-static int __init init(void)
+static int __init ebtable_broute_init(void)
{
int ret;
@@ -74,13 +74,13 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit ebtable_broute_fini(void)
{
br_should_route_hook = NULL;
synchronize_net();
ebt_unregister_table(&broute_table);
}
-module_init(init);
-module_exit(fini);
+module_init(ebtable_broute_init);
+module_exit(ebtable_broute_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index c18666e0392..3d5bd44f239 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -91,7 +91,7 @@ static struct nf_hook_ops ebt_ops_filter[] = {
},
};
-static int __init init(void)
+static int __init ebtable_filter_init(void)
{
int i, j, ret;
@@ -109,7 +109,7 @@ cleanup:
return ret;
}
-static void __exit fini(void)
+static void __exit ebtable_filter_fini(void)
{
int i;
@@ -118,6 +118,6 @@ static void __exit fini(void)
ebt_unregister_table(&frame_filter);
}
-module_init(init);
-module_exit(fini);
+module_init(ebtable_filter_init);
+module_exit(ebtable_filter_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 828cac2cc4a..04dd42efda1 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -98,7 +98,7 @@ static struct nf_hook_ops ebt_ops_nat[] = {
},
};
-static int __init init(void)
+static int __init ebtable_nat_init(void)
{
int i, ret, j;
@@ -116,7 +116,7 @@ cleanup:
return ret;
}
-static void __exit fini(void)
+static void __exit ebtable_nat_fini(void)
{
int i;
@@ -125,6 +125,6 @@ static void __exit fini(void)
ebt_unregister_table(&frame_nat);
}
-module_init(init);
-module_exit(fini);
+module_init(ebtable_nat_init);
+module_exit(ebtable_nat_fini);
MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 99795336720..01eae97c53d 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1487,7 +1487,7 @@ static struct nf_sockopt_ops ebt_sockopts =
.get = do_ebt_get_ctl,
};
-static int __init init(void)
+static int __init ebtables_init(void)
{
int ret;
@@ -1501,7 +1501,7 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ebtables_fini(void)
{
nf_unregister_sockopt(&ebt_sockopts);
printk(KERN_NOTICE "Ebtables v2.0 unregistered\n");
@@ -1516,6 +1516,6 @@ EXPORT_SYMBOL(ebt_unregister_watcher);
EXPORT_SYMBOL(ebt_register_target);
EXPORT_SYMBOL(ebt_unregister_target);
EXPORT_SYMBOL(ebt_do_table);
-module_init(init);
-module_exit(fini);
+module_init(ebtables_init);
+module_exit(ebtables_fini);
MODULE_LICENSE("GPL");
diff --git a/net/core/datagram.c b/net/core/datagram.c
index b8ce6bf8118..aecddcc3040 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -500,6 +500,8 @@ unsigned int datagram_poll(struct file *file, struct socket *sock,
/* exceptional events? */
if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
mask |= POLLERR;
+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ mask |= POLLRDHUP;
if (sk->sk_shutdown == SHUTDOWN_MASK)
mask |= POLLHUP;
diff --git a/net/core/dev.c b/net/core/dev.c
index 08dec6eb922..a3ab11f3415 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -114,6 +114,7 @@
#include <linux/wireless.h>
#include <net/iw_handler.h>
#include <asm/current.h>
+#include <linux/audit.h>
/*
* The list of packet types we will receive (as opposed to discard)
@@ -192,7 +193,7 @@ static inline struct hlist_head *dev_index_hash(int ifindex)
* Our notifier list
*/
-static struct notifier_block *netdev_chain;
+static BLOCKING_NOTIFIER_HEAD(netdev_chain);
/*
* Device drivers call our routines to queue packets here. We empty the
@@ -735,7 +736,8 @@ int dev_change_name(struct net_device *dev, char *newname)
if (!err) {
hlist_del(&dev->name_hlist);
hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
- notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
+ blocking_notifier_call_chain(&netdev_chain,
+ NETDEV_CHANGENAME, dev);
}
return err;
@@ -749,7 +751,7 @@ int dev_change_name(struct net_device *dev, char *newname)
*/
void netdev_features_change(struct net_device *dev)
{
- notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev);
+ blocking_notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev);
}
EXPORT_SYMBOL(netdev_features_change);
@@ -764,7 +766,8 @@ EXPORT_SYMBOL(netdev_features_change);
void netdev_state_change(struct net_device *dev)
{
if (dev->flags & IFF_UP) {
- notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
+ blocking_notifier_call_chain(&netdev_chain,
+ NETDEV_CHANGE, dev);
rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
}
}
@@ -861,7 +864,7 @@ int dev_open(struct net_device *dev)
/*
* ... and announce new interface.
*/
- notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
+ blocking_notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
}
return ret;
}
@@ -884,7 +887,7 @@ int dev_close(struct net_device *dev)
* Tell people we are going down, so that they can
* prepare to death, when device is still operating.
*/
- notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);
+ blocking_notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);
dev_deactivate(dev);
@@ -921,7 +924,7 @@ int dev_close(struct net_device *dev)
/*
* Tell people we are down
*/
- notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
+ blocking_notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
return 0;
}
@@ -952,7 +955,7 @@ int register_netdevice_notifier(struct notifier_block *nb)
int err;
rtnl_lock();
- err = notifier_chain_register(&netdev_chain, nb);
+ err = blocking_notifier_chain_register(&netdev_chain, nb);
if (!err) {
for (dev = dev_base; dev; dev = dev->next) {
nb->notifier_call(nb, NETDEV_REGISTER, dev);
@@ -977,7 +980,12 @@ int register_netdevice_notifier(struct notifier_block *nb)
int unregister_netdevice_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&netdev_chain, nb);
+ int err;
+
+ rtnl_lock();
+ err = blocking_notifier_chain_unregister(&netdev_chain, nb);
+ rtnl_unlock();
+ return err;
}
/**
@@ -986,12 +994,12 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
* @v: pointer passed unmodified to notifier function
*
* Call all network notifier blocks. Parameters and return value
- * are as for notifier_call_chain().
+ * are as for blocking_notifier_call_chain().
*/
int call_netdevice_notifiers(unsigned long val, void *v)
{
- return notifier_call_chain(&netdev_chain, val, v);
+ return blocking_notifier_call_chain(&netdev_chain, val, v);
}
/* When > 0 there are consumers of rx skb time stamps */
@@ -2142,6 +2150,12 @@ void dev_set_promiscuity(struct net_device *dev, int inc)
printk(KERN_INFO "device %s %s promiscuous mode\n",
dev->name, (dev->flags & IFF_PROMISC) ? "entered" :
"left");
+ audit_log(current->audit_context, GFP_ATOMIC,
+ AUDIT_ANOM_PROMISCUOUS,
+ "dev=%s prom=%d old_prom=%d auid=%u",
+ dev->name, (dev->flags & IFF_PROMISC),
+ (old_flags & IFF_PROMISC),
+ audit_get_loginuid(current->audit_context));
}
}
@@ -2230,7 +2244,8 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
if (dev->flags & IFF_UP &&
((old_flags ^ dev->flags) &~ (IFF_UP | IFF_PROMISC | IFF_ALLMULTI |
IFF_VOLATILE)))
- notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
+ blocking_notifier_call_chain(&netdev_chain,
+ NETDEV_CHANGE, dev);
if ((flags ^ dev->gflags) & IFF_PROMISC) {
int inc = (flags & IFF_PROMISC) ? +1 : -1;
@@ -2274,8 +2289,8 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
else
dev->mtu = new_mtu;
if (!err && dev->flags & IFF_UP)
- notifier_call_chain(&netdev_chain,
- NETDEV_CHANGEMTU, dev);
+ blocking_notifier_call_chain(&netdev_chain,
+ NETDEV_CHANGEMTU, dev);
return err;
}
@@ -2291,7 +2306,8 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
return -ENODEV;
err = dev->set_mac_address(dev, sa);
if (!err)
- notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
+ blocking_notifier_call_chain(&netdev_chain,
+ NETDEV_CHANGEADDR, dev);
return err;
}
@@ -2347,7 +2363,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
return -EINVAL;
memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
- notifier_call_chain(&netdev_chain,
+ blocking_notifier_call_chain(&netdev_chain,
NETDEV_CHANGEADDR, dev);
return 0;
@@ -2801,7 +2817,7 @@ int register_netdevice(struct net_device *dev)
write_unlock_bh(&dev_base_lock);
/* Notify protocols, that a new device appeared. */
- notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
+ blocking_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
/* Finish registration after unlock */
net_set_todo(dev);
@@ -2880,7 +2896,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
rtnl_lock();
/* Rebroadcast unregister notification */
- notifier_call_chain(&netdev_chain,
+ blocking_notifier_call_chain(&netdev_chain,
NETDEV_UNREGISTER, dev);
if (test_bit(__LINK_STATE_LINKWATCH_PENDING,
@@ -3136,7 +3152,7 @@ int unregister_netdevice(struct net_device *dev)
/* Notify protocols, that we are about to destroy
this device. They should clean all the things.
*/
- notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
+ blocking_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
/*
* Flush the multicast chain
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index 98f0fc923f9..1e44eda1fda 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -51,7 +51,7 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd));
rwlock_init(&queue->syn_wait_lock);
- queue->rskq_accept_head = queue->rskq_accept_head = NULL;
+ queue->rskq_accept_head = NULL;
lopt->nr_table_entries = nr_table_entries;
write_lock_bh(&queue->syn_wait_lock);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index c9f87845453..09464fa8d72 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -149,7 +149,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
/* Get the DATA. Size must match skb_add_mtu(). */
size = SKB_DATA_ALIGN(size);
- data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
+ data = ____kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
if (!data)
goto nodata;
diff --git a/net/core/sock.c b/net/core/sock.c
index 1a7e6eac90b..a96ea7dd0fc 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -187,6 +187,99 @@ static void sock_disable_timestamp(struct sock *sk)
}
+int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+ int err = 0;
+ int skb_len;
+
+ /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
+ number of warnings when compiling with -W --ANK
+ */
+ if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
+ (unsigned)sk->sk_rcvbuf) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /* It would be deadlock, if sock_queue_rcv_skb is used
+ with socket lock! We assume that users of this
+ function are lock free.
+ */
+ err = sk_filter(sk, skb, 1);
+ if (err)
+ goto out;
+
+ skb->dev = NULL;
+ skb_set_owner_r(skb, sk);
+
+ /* Cache the SKB length before we tack it onto the receive
+ * queue. Once it is added it no longer belongs to us and
+ * may be freed by other threads of control pulling packets
+ * from the queue.
+ */
+ skb_len = skb->len;
+
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk->sk_data_ready(sk, skb_len);
+out:
+ return err;
+}
+EXPORT_SYMBOL(sock_queue_rcv_skb);
+
+int sk_receive_skb(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = NET_RX_SUCCESS;
+
+ if (sk_filter(sk, skb, 0))
+ goto discard_and_relse;
+
+ skb->dev = NULL;
+
+ bh_lock_sock(sk);
+ if (!sock_owned_by_user(sk))
+ rc = sk->sk_backlog_rcv(sk, skb);
+ else
+ sk_add_backlog(sk, skb);
+ bh_unlock_sock(sk);
+out:
+ sock_put(sk);
+ return rc;
+discard_and_relse:
+ kfree_skb(skb);
+ goto out;
+}
+EXPORT_SYMBOL(sk_receive_skb);
+
+struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie)
+{
+ struct dst_entry *dst = sk->sk_dst_cache;
+
+ if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
+ sk->sk_dst_cache = NULL;
+ dst_release(dst);
+ return NULL;
+ }
+
+ return dst;
+}
+EXPORT_SYMBOL(__sk_dst_check);
+
+struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie)
+{
+ struct dst_entry *dst = sk_dst_get(sk);
+
+ if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
+ sk_dst_reset(sk);
+ dst_release(dst);
+ return NULL;
+ }
+
+ return dst;
+}
+EXPORT_SYMBOL(sk_dst_check);
+
/*
* This is meant for all protocols to use and covers goings on
* at the socket level. Everything here is generic.
@@ -404,8 +497,9 @@ set_rcvbuf:
if (!valbool) {
sk->sk_bound_dev_if = 0;
} else {
- if (optlen > IFNAMSIZ)
- optlen = IFNAMSIZ;
+ if (optlen > IFNAMSIZ - 1)
+ optlen = IFNAMSIZ - 1;
+ memset(devname, 0, sizeof(devname));
if (copy_from_user(devname, optval, optlen)) {
ret = -EFAULT;
break;
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index d4b293e1628..1ff7328b0e1 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -350,7 +350,7 @@ unsigned int dccp_poll(struct file *file, struct socket *sock,
if (sk->sk_shutdown == SHUTDOWN_MASK || sk->sk_state == DCCP_CLOSED)
mask |= POLLHUP;
if (sk->sk_shutdown & RCV_SHUTDOWN)
- mask |= POLLIN | POLLRDNORM;
+ mask |= POLLIN | POLLRDNORM | POLLRDHUP;
/* Connected? */
if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_RESPOND)) {
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index cc7b9d9255e..d2ae9893ca1 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -68,7 +68,7 @@ __le16 decnet_address = 0;
static DEFINE_RWLOCK(dndev_lock);
static struct net_device *decnet_default_device;
-static struct notifier_block *dnaddr_chain;
+static BLOCKING_NOTIFIER_HEAD(dnaddr_chain);
static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
static void dn_dev_delete(struct net_device *dev);
@@ -446,7 +446,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de
}
rtmsg_ifa(RTM_DELADDR, ifa1);
- notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
+ blocking_notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
if (destroy) {
dn_dev_free_ifa(ifa1);
@@ -481,7 +481,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
dn_db->ifa_list = ifa;
rtmsg_ifa(RTM_NEWADDR, ifa);
- notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
+ blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
return 0;
}
@@ -1285,12 +1285,12 @@ void dn_dev_devices_on(void)
int register_dnaddr_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&dnaddr_chain, nb);
+ return blocking_notifier_chain_register(&dnaddr_chain, nb);
}
int unregister_dnaddr_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&dnaddr_chain, nb);
+ return blocking_notifier_chain_unregister(&dnaddr_chain, nb);
}
#ifdef CONFIG_PROC_FS
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 16a5a31e212..74133ecd770 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -133,7 +133,7 @@ static struct nf_hook_ops dnrmg_ops = {
.priority = NF_DN_PRI_DNRTMSG,
};
-static int __init init(void)
+static int __init dn_rtmsg_init(void)
{
int rv = 0;
@@ -152,7 +152,7 @@ static int __init init(void)
return rv;
}
-static void __exit fini(void)
+static void __exit dn_rtmsg_fini(void)
{
nf_unregister_hook(&dnrmg_ops);
sock_release(dnrmg->sk_socket);
@@ -164,6 +164,6 @@ MODULE_AUTHOR("Steven Whitehouse <steve@chygwyn.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_DNRTMSG);
-module_init(init);
-module_exit(fini);
+module_init(dn_rtmsg_init);
+module_exit(dn_rtmsg_fini);
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index c792994d795..868265619db 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -42,6 +42,7 @@
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <linux/bitops.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -49,6 +50,7 @@
static const struct proto_ops econet_ops;
static struct hlist_head econet_sklist;
static DEFINE_RWLOCK(econet_lock);
+static DEFINE_MUTEX(econet_mutex);
/* Since there are only 256 possible network numbers (or fewer, depends
how you count) it makes sense to use a simple lookup table. */
@@ -124,6 +126,8 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
msg->msg_namelen = sizeof(struct sockaddr_ec);
+ mutex_lock(&econet_mutex);
+
/*
* Call the generic datagram receiver. This handles all sorts
* of horrible races and re-entrancy so we can forget about it
@@ -174,6 +178,7 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
out_free:
skb_free_datagram(sk, skb);
out:
+ mutex_unlock(&econet_mutex);
return err;
}
@@ -184,8 +189,8 @@ out:
static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
- struct sock *sk=sock->sk;
- struct econet_sock *eo = ec_sk(sk);
+ struct sock *sk;
+ struct econet_sock *eo;
/*
* Check legality
@@ -195,11 +200,18 @@ static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len
sec->sec_family != AF_ECONET)
return -EINVAL;
+ mutex_lock(&econet_mutex);
+
+ sk = sock->sk;
+ eo = ec_sk(sk);
+
eo->cb = sec->cb;
eo->port = sec->port;
eo->station = sec->addr.station;
eo->net = sec->addr.net;
+ mutex_unlock(&econet_mutex);
+
return 0;
}
@@ -284,6 +296,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
* Get and verify the address.
*/
+ mutex_lock(&econet_mutex);
+
if (saddr == NULL) {
struct econet_sock *eo = ec_sk(sk);
@@ -292,8 +306,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
port = eo->port;
cb = eo->cb;
} else {
- if (msg->msg_namelen < sizeof(struct sockaddr_ec))
+ if (msg->msg_namelen < sizeof(struct sockaddr_ec)) {
+ mutex_unlock(&econet_mutex);
return -EINVAL;
+ }
addr.station = saddr->addr.station;
addr.net = saddr->addr.net;
port = saddr->port;
@@ -304,19 +320,21 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
dev = net2dev_map[addr.net];
/* If not directly reachable, use some default */
- if (dev == NULL)
- {
+ if (dev == NULL) {
dev = net2dev_map[0];
/* No interfaces at all? */
- if (dev == NULL)
+ if (dev == NULL) {
+ mutex_unlock(&econet_mutex);
return -ENETDOWN;
+ }
}
- if (len + 15 > dev->mtu)
+ if (len + 15 > dev->mtu) {
+ mutex_unlock(&econet_mutex);
return -EMSGSIZE;
+ }
- if (dev->type == ARPHRD_ECONET)
- {
+ if (dev->type == ARPHRD_ECONET) {
/* Real hardware Econet. We're not worthy etc. */
#ifdef CONFIG_ECONET_NATIVE
unsigned short proto = 0;
@@ -374,6 +392,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
dev_queue_xmit(skb);
dev_put(dev);
+ mutex_unlock(&econet_mutex);
return(len);
out_free:
@@ -384,14 +403,18 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
#else
err = -EPROTOTYPE;
#endif
+ mutex_unlock(&econet_mutex);
+
return err;
}
#ifdef CONFIG_ECONET_AUNUDP
/* AUN virtual Econet. */
- if (udpsock == NULL)
+ if (udpsock == NULL) {
+ mutex_unlock(&econet_mutex);
return -ENETDOWN; /* No socket - can't send */
+ }
/* Make up a UDP datagram and hand it off to some higher intellect. */
@@ -438,8 +461,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
void __user *base = msg->msg_iov[i].iov_base;
size_t len = msg->msg_iov[i].iov_len;
/* Check it now since we switch to KERNEL_DS later. */
- if (!access_ok(VERIFY_READ, base, len))
+ if (!access_ok(VERIFY_READ, base, len)) {
+ mutex_unlock(&econet_mutex);
return -EFAULT;
+ }
iov[i+1].iov_base = base;
iov[i+1].iov_len = len;
size += len;
@@ -447,8 +472,11 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
/* Get a skbuff (no data, just holds our cb information) */
if ((skb = sock_alloc_send_skb(sk, 0,
- msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)
+ msg->msg_flags & MSG_DONTWAIT,
+ &err)) == NULL) {
+ mutex_unlock(&econet_mutex);
return err;
+ }
eb = (struct ec_cb *)&skb->cb;
@@ -475,6 +503,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
#else
err = -EPROTOTYPE;
#endif
+ mutex_unlock(&econet_mutex);
+
return err;
}
@@ -485,18 +515,25 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
static int econet_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
- struct sock *sk = sock->sk;
- struct econet_sock *eo = ec_sk(sk);
+ struct sock *sk;
+ struct econet_sock *eo;
struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
if (peer)
return -EOPNOTSUPP;
+ mutex_lock(&econet_mutex);
+
+ sk = sock->sk;
+ eo = ec_sk(sk);
+
sec->sec_family = AF_ECONET;
sec->port = eo->port;
sec->addr.station = eo->station;
sec->addr.net = eo->net;
+ mutex_unlock(&econet_mutex);
+
*uaddr_len = sizeof(*sec);
return 0;
}
@@ -522,10 +559,13 @@ static void econet_destroy_timer(unsigned long data)
static int econet_release(struct socket *sock)
{
- struct sock *sk = sock->sk;
+ struct sock *sk;
+ mutex_lock(&econet_mutex);
+
+ sk = sock->sk;
if (!sk)
- return 0;
+ goto out_unlock;
econet_remove_socket(&econet_sklist, sk);
@@ -549,10 +589,14 @@ static int econet_release(struct socket *sock)
sk->sk_timer.expires = jiffies + HZ;
sk->sk_timer.function = econet_destroy_timer;
add_timer(&sk->sk_timer);
- return 0;
+
+ goto out_unlock;
}
sk_free(sk);
+
+out_unlock:
+ mutex_unlock(&econet_mutex);
return 0;
}
@@ -608,6 +652,7 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
struct ec_device *edev;
struct net_device *dev;
struct sockaddr_ec *sec;
+ int err;
/*
* Fetch the caller's info block into kernel space
@@ -621,38 +666,35 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
sec = (struct sockaddr_ec *)&ifr.ifr_addr;
- switch (cmd)
- {
+ mutex_lock(&econet_mutex);
+
+ err = 0;
+ switch (cmd) {
case SIOCSIFADDR:
edev = dev->ec_ptr;
- if (edev == NULL)
- {
+ if (edev == NULL) {
/* Magic up a new one. */
edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL);
if (edev == NULL) {
- printk("af_ec: memory squeeze.\n");
- dev_put(dev);
- return -ENOMEM;
+ err = -ENOMEM;
+ break;
}
memset(edev, 0, sizeof(struct ec_device));
dev->ec_ptr = edev;
- }
- else
+ } else
net2dev_map[edev->net] = NULL;
edev->station = sec->addr.station;
edev->net = sec->addr.net;
net2dev_map[sec->addr.net] = dev;
if (!net2dev_map[0])
net2dev_map[0] = dev;
- dev_put(dev);
- return 0;
+ break;
case SIOCGIFADDR:
edev = dev->ec_ptr;
- if (edev == NULL)
- {
- dev_put(dev);
- return -ENODEV;
+ if (edev == NULL) {
+ err = -ENODEV;
+ break;
}
memset(sec, 0, sizeof(struct sockaddr_ec));
sec->addr.station = edev->station;
@@ -660,12 +702,19 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
sec->sec_family = AF_ECONET;
dev_put(dev);
if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
- return -EFAULT;
- return 0;
+ err = -EFAULT;
+ break;
+
+ default:
+ err = -EINVAL;
+ break;
}
+ mutex_unlock(&econet_mutex);
+
dev_put(dev);
- return -EINVAL;
+
+ return err;
}
/*
@@ -699,7 +748,7 @@ static struct net_proto_family econet_family_ops = {
.owner = THIS_MODULE,
};
-static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
+static const struct proto_ops econet_ops = {
.family = PF_ECONET,
.owner = THIS_MODULE,
.release = econet_release,
@@ -720,9 +769,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
.sendpage = sock_no_sendpage,
};
-#include <linux/smp_lock.h>
-SOCKOPS_WRAP(econet, PF_ECONET);
-
#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)
/*
* Find the listening socket, if any, for the given data.
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 011cca7ae02..e40f7532237 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -235,6 +235,7 @@ config IP_PNP_RARP
# bool ' IP: ARP support' CONFIG_IP_PNP_ARP
config NET_IPIP
tristate "IP: tunneling"
+ select INET_TUNNEL
---help---
Tunneling means encapsulating data of one protocol type within
another protocol and sending it over a channel that understands the
@@ -395,7 +396,7 @@ config INET_ESP
config INET_IPCOMP
tristate "IP: IPComp transformation"
select XFRM
- select INET_TUNNEL
+ select INET_XFRM_TUNNEL
select CRYPTO
select CRYPTO_DEFLATE
---help---
@@ -404,14 +405,14 @@ config INET_IPCOMP
If unsure, say Y.
+config INET_XFRM_TUNNEL
+ tristate
+ select INET_TUNNEL
+ default n
+
config INET_TUNNEL
- tristate "IP: tunnel transformation"
- select XFRM
- ---help---
- Support for generic IP tunnel transformation, which is required by
- the IP tunneling module as well as tunnel mode IPComp.
-
- If unsure, say Y.
+ tristate
+ default n
config INET_DIAG
tristate "INET: socket monitoring interface"
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 35e5f599909..9ef50a0b9d2 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -22,7 +22,8 @@ obj-$(CONFIG_SYN_COOKIES) += syncookies.o
obj-$(CONFIG_INET_AH) += ah4.o
obj-$(CONFIG_INET_ESP) += esp4.o
obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
-obj-$(CONFIG_INET_TUNNEL) += xfrm4_tunnel.o
+obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o
+obj-$(CONFIG_INET_TUNNEL) += tunnel4.o
obj-$(CONFIG_IP_PNP) += ipconfig.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 44fdf1413e2..81c2f788529 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -81,7 +81,7 @@ static struct ipv4_devconf ipv4_devconf_dflt = {
static void rtmsg_ifa(int event, struct in_ifaddr *);
-static struct notifier_block *inetaddr_chain;
+static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
int destroy);
#ifdef CONFIG_SYSCTL
@@ -267,7 +267,8 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
*ifap1 = ifa->ifa_next;
rtmsg_ifa(RTM_DELADDR, ifa);
- notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
+ blocking_notifier_call_chain(&inetaddr_chain,
+ NETDEV_DOWN, ifa);
inet_free_ifa(ifa);
} else {
promote = ifa;
@@ -291,7 +292,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
So that, this order is correct.
*/
rtmsg_ifa(RTM_DELADDR, ifa1);
- notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
+ blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
if (promote) {
@@ -303,7 +304,8 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
promote->ifa_flags &= ~IFA_F_SECONDARY;
rtmsg_ifa(RTM_NEWADDR, promote);
- notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote);
+ blocking_notifier_call_chain(&inetaddr_chain,
+ NETDEV_UP, promote);
for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) {
if (ifa1->ifa_mask != ifa->ifa_mask ||
!inet_ifa_match(ifa1->ifa_address, ifa))
@@ -366,7 +368,7 @@ static int inet_insert_ifa(struct in_ifaddr *ifa)
Notifier will trigger FIB update, so that
listeners of netlink will know about new ifaddr */
rtmsg_ifa(RTM_NEWADDR, ifa);
- notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
+ blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
return 0;
}
@@ -938,12 +940,12 @@ u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scop
int register_inetaddr_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&inetaddr_chain, nb);
+ return blocking_notifier_chain_register(&inetaddr_chain, nb);
}
int unregister_inetaddr_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&inetaddr_chain, nb);
+ return blocking_notifier_chain_unregister(&inetaddr_chain, nb);
}
/* Rename ifa_labels for a device name change. Make some effort to preserve existing
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index e7bbff4340b..9831fd2c73a 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -753,7 +753,7 @@ static void icmp_redirect(struct sk_buff *skb)
case ICMP_REDIR_HOST:
case ICMP_REDIR_HOSTTOS:
ip_rt_redirect(skb->nh.iph->saddr, ip, skb->h.icmph->un.gateway,
- iph->saddr, iph->tos, skb->dev);
+ iph->saddr, skb->dev);
break;
}
out:
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 03d13742a4b..eef07b0916a 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -114,7 +114,6 @@
#include <net/sock.h>
#include <net/ip.h>
#include <net/icmp.h>
-#include <net/protocol.h>
#include <net/ipip.h>
#include <net/inet_ecn.h>
#include <net/xfrm.h>
@@ -274,7 +273,7 @@ static void ipip_tunnel_uninit(struct net_device *dev)
dev_put(dev);
}
-static void ipip_err(struct sk_buff *skb, u32 info)
+static int ipip_err(struct sk_buff *skb, u32 info)
{
#ifndef I_WISH_WORLD_WERE_PERFECT
@@ -286,21 +285,22 @@ static void ipip_err(struct sk_buff *skb, u32 info)
int type = skb->h.icmph->type;
int code = skb->h.icmph->code;
struct ip_tunnel *t;
+ int err;
switch (type) {
default:
case ICMP_PARAMETERPROB:
- return;
+ return 0;
case ICMP_DEST_UNREACH:
switch (code) {
case ICMP_SR_FAILED:
case ICMP_PORT_UNREACH:
/* Impossible event. */
- return;
+ return 0;
case ICMP_FRAG_NEEDED:
/* Soft state for pmtu is maintained by IP core. */
- return;
+ return 0;
default:
/* All others are translated to HOST_UNREACH.
rfc2003 contains "deep thoughts" about NET_UNREACH,
@@ -311,14 +311,18 @@ static void ipip_err(struct sk_buff *skb, u32 info)
break;
case ICMP_TIME_EXCEEDED:
if (code != ICMP_EXC_TTL)
- return;
+ return 0;
break;
}
+ err = -ENOENT;
+
read_lock(&ipip_lock);
t = ipip_tunnel_lookup(iph->daddr, iph->saddr);
if (t == NULL || t->parms.iph.daddr == 0)
goto out;
+
+ err = 0;
if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
goto out;
@@ -329,7 +333,7 @@ static void ipip_err(struct sk_buff *skb, u32 info)
t->err_time = jiffies;
out:
read_unlock(&ipip_lock);
- return;
+ return err;
#else
struct iphdr *iph = (struct iphdr*)dp;
int hlen = iph->ihl<<2;
@@ -344,15 +348,15 @@ out:
struct rtable *rt;
if (len < hlen + sizeof(struct iphdr))
- return;
+ return 0;
eiph = (struct iphdr*)(dp + hlen);
switch (type) {
default:
- return;
+ return 0;
case ICMP_PARAMETERPROB:
if (skb->h.icmph->un.gateway < hlen)
- return;
+ return 0;
/* So... This guy found something strange INSIDE encapsulated
packet. Well, he is fool, but what can we do ?
@@ -366,16 +370,16 @@ out:
case ICMP_SR_FAILED:
case ICMP_PORT_UNREACH:
/* Impossible event. */
- return;
+ return 0;
case ICMP_FRAG_NEEDED:
/* And it is the only really necessary thing :-) */
rel_info = ntohs(skb->h.icmph->un.frag.mtu);
if (rel_info < hlen+68)
- return;
+ return 0;
rel_info -= hlen;
/* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
if (rel_info > ntohs(eiph->tot_len))
- return;
+ return 0;
break;
default:
/* All others are translated to HOST_UNREACH.
@@ -389,14 +393,14 @@ out:
break;
case ICMP_TIME_EXCEEDED:
if (code != ICMP_EXC_TTL)
- return;
+ return 0;
break;
}
/* Prepare fake skb to feed it to icmp_send */
skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2 == NULL)
- return;
+ return 0;
dst_release(skb2->dst);
skb2->dst = NULL;
skb_pull(skb2, skb->data - (u8*)eiph);
@@ -409,7 +413,7 @@ out:
fl.proto = IPPROTO_IPIP;
if (ip_route_output_key(&rt, &key)) {
kfree_skb(skb2);
- return;
+ return 0;
}
skb2->dev = rt->u.dst.dev;
@@ -424,14 +428,14 @@ out:
rt->u.dst.dev->type != ARPHRD_TUNNEL) {
ip_rt_put(rt);
kfree_skb(skb2);
- return;
+ return 0;
}
} else {
ip_rt_put(rt);
if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) ||
skb2->dst->dev->type != ARPHRD_TUNNEL) {
kfree_skb(skb2);
- return;
+ return 0;
}
}
@@ -439,7 +443,7 @@ out:
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
if (rel_info > dst_mtu(skb2->dst)) {
kfree_skb(skb2);
- return;
+ return 0;
}
skb2->dst->ops->update_pmtu(skb2->dst, rel_info);
rel_info = htonl(rel_info);
@@ -453,7 +457,7 @@ out:
icmp_send(skb2, rel_type, rel_code, rel_info);
kfree_skb(skb2);
- return;
+ return 0;
#endif
}
@@ -855,39 +859,12 @@ static int __init ipip_fb_tunnel_init(struct net_device *dev)
return 0;
}
-#ifdef CONFIG_INET_TUNNEL
static struct xfrm_tunnel ipip_handler = {
.handler = ipip_rcv,
.err_handler = ipip_err,
+ .priority = 1,
};
-static inline int ipip_register(void)
-{
- return xfrm4_tunnel_register(&ipip_handler);
-}
-
-static inline int ipip_unregister(void)
-{
- return xfrm4_tunnel_deregister(&ipip_handler);
-}
-#else
-static struct net_protocol ipip_protocol = {
- .handler = ipip_rcv,
- .err_handler = ipip_err,
- .no_policy = 1,
-};
-
-static inline int ipip_register(void)
-{
- return inet_add_protocol(&ipip_protocol, IPPROTO_IPIP);
-}
-
-static inline int ipip_unregister(void)
-{
- return inet_del_protocol(&ipip_protocol, IPPROTO_IPIP);
-}
-#endif
-
static char banner[] __initdata =
KERN_INFO "IPv4 over IPv4 tunneling driver\n";
@@ -897,7 +874,7 @@ static int __init ipip_init(void)
printk(banner);
- if (ipip_register() < 0) {
+ if (xfrm4_tunnel_register(&ipip_handler)) {
printk(KERN_INFO "ipip init: can't register tunnel\n");
return -EAGAIN;
}
@@ -919,7 +896,7 @@ static int __init ipip_init(void)
err2:
free_netdev(ipip_fb_tunnel_dev);
err1:
- ipip_unregister();
+ xfrm4_tunnel_deregister(&ipip_handler);
goto out;
}
@@ -939,7 +916,7 @@ static void __exit ipip_destroy_tunnels(void)
static void __exit ipip_fini(void)
{
- if (ipip_unregister() < 0)
+ if (xfrm4_tunnel_deregister(&ipip_handler))
printk(KERN_INFO "ipip close: can't deregister tunnel\n");
rtnl_lock();
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 7f0288b25fa..f28ec688216 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -34,6 +34,7 @@
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
+#include <linux/mutex.h>
#include <net/ip.h>
#include <net/route.h>
@@ -44,7 +45,7 @@
#include <net/ip_vs.h>
/* semaphore for IPVS sockopts. And, [gs]etsockopt may sleep. */
-static DECLARE_MUTEX(__ip_vs_mutex);
+static DEFINE_MUTEX(__ip_vs_mutex);
/* lock for service table */
static DEFINE_RWLOCK(__ip_vs_svc_lock);
@@ -1950,7 +1951,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
/* increase the module use count */
ip_vs_use_count_inc();
- if (down_interruptible(&__ip_vs_mutex)) {
+ if (mutex_lock_interruptible(&__ip_vs_mutex)) {
ret = -ERESTARTSYS;
goto out_dec;
}
@@ -2041,7 +2042,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
ip_vs_service_put(svc);
out_unlock:
- up(&__ip_vs_mutex);
+ mutex_unlock(&__ip_vs_mutex);
out_dec:
/* decrease the module use count */
ip_vs_use_count_dec();
@@ -2211,7 +2212,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
if (copy_from_user(arg, user, get_arglen[GET_CMDID(cmd)]) != 0)
return -EFAULT;
- if (down_interruptible(&__ip_vs_mutex))
+ if (mutex_lock_interruptible(&__ip_vs_mutex))
return -ERESTARTSYS;
switch (cmd) {
@@ -2330,7 +2331,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
}
out:
- up(&__ip_vs_mutex);
+ mutex_unlock(&__ip_vs_mutex);
return ret;
}
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index ed42cdc57cd..b5ad9ac2fbc 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -167,15 +167,15 @@ static struct nf_queue_rerouter ip_reroute = {
.reroute = queue_reroute,
};
-static int init(void)
+static int ipv4_netfilter_init(void)
{
return nf_register_queue_rerouter(PF_INET, &ip_reroute);
}
-static void fini(void)
+static void ipv4_netfilter_fini(void)
{
nf_unregister_queue_rerouter(PF_INET);
}
-module_init(init);
-module_exit(fini);
+module_init(ipv4_netfilter_init);
+module_exit(ipv4_netfilter_fini);
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index ff0c594a419..a44a5d73457 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1166,7 +1166,7 @@ static struct nf_sockopt_ops arpt_sockopts = {
.get = do_arpt_get_ctl,
};
-static int __init init(void)
+static int __init arp_tables_init(void)
{
int ret;
@@ -1187,7 +1187,7 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit arp_tables_fini(void)
{
nf_unregister_sockopt(&arpt_sockopts);
xt_proto_fini(NF_ARP);
@@ -1197,5 +1197,5 @@ EXPORT_SYMBOL(arpt_register_table);
EXPORT_SYMBOL(arpt_unregister_table);
EXPORT_SYMBOL(arpt_do_table);
-module_init(init);
-module_exit(fini);
+module_init(arp_tables_init);
+module_exit(arp_tables_fini);
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index 0f2a95350e2..a58325c1ceb 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -89,7 +89,7 @@ static struct arpt_target arpt_mangle_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init arpt_mangle_init(void)
{
if (arpt_register_target(&arpt_mangle_reg))
return -EINVAL;
@@ -97,10 +97,10 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit arpt_mangle_fini(void)
{
arpt_unregister_target(&arpt_mangle_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(arpt_mangle_init);
+module_exit(arpt_mangle_fini);
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index f6ab45f4868..d0d379c7df9 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -179,7 +179,7 @@ static struct nf_hook_ops arpt_ops[] = {
},
};
-static int __init init(void)
+static int __init arptable_filter_init(void)
{
int ret, i;
@@ -201,7 +201,7 @@ cleanup_hooks:
return ret;
}
-static void __exit fini(void)
+static void __exit arptable_filter_fini(void)
{
unsigned int i;
@@ -211,5 +211,5 @@ static void __exit fini(void)
arpt_unregister_table(&packet_filter);
}
-module_init(init);
-module_exit(fini);
+module_init(arptable_filter_init);
+module_exit(arptable_filter_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index 84e4f79b7ff..a604b1ccfda 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -153,13 +153,13 @@ static struct ip_conntrack_helper amanda_helper = {
},
};
-static void __exit fini(void)
+static void __exit ip_conntrack_amanda_fini(void)
{
ip_conntrack_helper_unregister(&amanda_helper);
kfree(amanda_buffer);
}
-static int __init init(void)
+static int __init ip_conntrack_amanda_init(void)
{
int ret;
@@ -177,5 +177,5 @@ static int __init init(void)
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_amanda_init);
+module_exit(ip_conntrack_amanda_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 9e34034729a..ceaabc18202 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -80,8 +80,8 @@ static int ip_conntrack_vmalloc;
static unsigned int ip_conntrack_next_id;
static unsigned int ip_conntrack_expect_next_id;
#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
-struct notifier_block *ip_conntrack_chain;
-struct notifier_block *ip_conntrack_expect_chain;
+ATOMIC_NOTIFIER_HEAD(ip_conntrack_chain);
+ATOMIC_NOTIFIER_HEAD(ip_conntrack_expect_chain);
DEFINE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache);
@@ -92,7 +92,7 @@ __ip_ct_deliver_cached_events(struct ip_conntrack_ecache *ecache)
{
DEBUGP("ecache: delivering events for %p\n", ecache->ct);
if (is_confirmed(ecache->ct) && !is_dying(ecache->ct) && ecache->events)
- notifier_call_chain(&ip_conntrack_chain, ecache->events,
+ atomic_notifier_call_chain(&ip_conntrack_chain, ecache->events,
ecache->ct);
ecache->events = 0;
ip_conntrack_put(ecache->ct);
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index e627e585617..3e542bf28a9 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -453,7 +453,7 @@ static struct ip_conntrack_helper ftp[MAX_PORTS];
static char ftp_names[MAX_PORTS][sizeof("ftp-65535")];
/* Not __exit: called from init() */
-static void fini(void)
+static void ip_conntrack_ftp_fini(void)
{
int i;
for (i = 0; i < ports_c; i++) {
@@ -465,7 +465,7 @@ static void fini(void)
kfree(ftp_buffer);
}
-static int __init init(void)
+static int __init ip_conntrack_ftp_init(void)
{
int i, ret;
char *tmpname;
@@ -499,12 +499,12 @@ static int __init init(void)
ret = ip_conntrack_helper_register(&ftp[i]);
if (ret) {
- fini();
+ ip_conntrack_ftp_fini();
return ret;
}
}
return 0;
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_ftp_init);
+module_exit(ip_conntrack_ftp_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
index d716bba798f..7d3ba4302e9 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -766,7 +766,7 @@ extern void ip_ct_proto_gre_fini(void);
extern int __init ip_ct_proto_gre_init(void);
/* ip_conntrack_pptp initialization */
-static int __init init(void)
+static int __init ip_conntrack_helper_pptp_init(void)
{
int retcode;
@@ -786,15 +786,15 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ip_conntrack_helper_pptp_fini(void)
{
ip_conntrack_helper_unregister(&pptp);
ip_ct_proto_gre_fini();
printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_helper_pptp_init);
+module_exit(ip_conntrack_helper_pptp_fini);
EXPORT_SYMBOL(ip_nat_pptp_hook_outbound);
EXPORT_SYMBOL(ip_nat_pptp_hook_inbound);
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index c51a2cf71b4..a2ac5ce544b 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -242,9 +242,9 @@ static int help(struct sk_buff **pskb,
static struct ip_conntrack_helper irc_helpers[MAX_PORTS];
static char irc_names[MAX_PORTS][sizeof("irc-65535")];
-static void fini(void);
+static void ip_conntrack_irc_fini(void);
-static int __init init(void)
+static int __init ip_conntrack_irc_init(void)
{
int i, ret;
struct ip_conntrack_helper *hlpr;
@@ -288,7 +288,7 @@ static int __init init(void)
if (ret) {
printk("ip_conntrack_irc: ERROR registering port %d\n",
ports[i]);
- fini();
+ ip_conntrack_irc_fini();
return -EBUSY;
}
}
@@ -297,7 +297,7 @@ static int __init init(void)
/* This function is intentionally _NOT_ defined as __exit, because
* it is needed by the init function */
-static void fini(void)
+static void ip_conntrack_irc_fini(void)
{
int i;
for (i = 0; i < ports_c; i++) {
@@ -308,5 +308,5 @@ static void fini(void)
kfree(irc_buffer);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_irc_init);
+module_exit(ip_conntrack_irc_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
index 4e68e16a261..a566a81325b 100644
--- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
+++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
@@ -127,16 +127,16 @@ static struct ip_conntrack_helper helper = {
.help = help,
};
-static int __init init(void)
+static int __init ip_conntrack_netbios_ns_init(void)
{
helper.timeout = timeout;
return ip_conntrack_helper_register(&helper);
}
-static void __exit fini(void)
+static void __exit ip_conntrack_netbios_ns_fini(void)
{
ip_conntrack_helper_unregister(&helper);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_netbios_ns_init);
+module_exit(ip_conntrack_netbios_ns_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
index be602e8aeab..5259abd0fb4 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
@@ -609,7 +609,7 @@ static ctl_table ip_ct_net_table[] = {
static struct ctl_table_header *ip_ct_sysctl_header;
#endif
-static int __init init(void)
+static int __init ip_conntrack_proto_sctp_init(void)
{
int ret;
@@ -640,7 +640,7 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit ip_conntrack_proto_sctp_fini(void)
{
ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
#ifdef CONFIG_SYSCTL
@@ -649,8 +649,8 @@ static void __exit fini(void)
DEBUGP("SCTP conntrack module unloaded\n");
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_proto_sctp_init);
+module_exit(ip_conntrack_proto_sctp_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kiran Kumar Immidi");
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 833fcb4be5e..52076026db3 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -929,18 +929,18 @@ void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
ip_ct_iterate_cleanup(kill_proto, &proto->proto);
}
-static int __init init(void)
+static int __init ip_conntrack_standalone_init(void)
{
return init_or_cleanup(1);
}
-static void __exit fini(void)
+static void __exit ip_conntrack_standalone_fini(void)
{
init_or_cleanup(0);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_standalone_init);
+module_exit(ip_conntrack_standalone_fini);
/* Some modules need us, but don't depend directly on any symbol.
They should call this. */
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index 4ba4463cec2..7e33d3bed5e 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -103,7 +103,7 @@ static int tftp_help(struct sk_buff **pskb,
static struct ip_conntrack_helper tftp[MAX_PORTS];
static char tftp_names[MAX_PORTS][sizeof("tftp-65535")];
-static void fini(void)
+static void ip_conntrack_tftp_fini(void)
{
int i;
@@ -114,7 +114,7 @@ static void fini(void)
}
}
-static int __init init(void)
+static int __init ip_conntrack_tftp_init(void)
{
int i, ret;
char *tmpname;
@@ -148,12 +148,12 @@ static int __init init(void)
if (ret) {
printk("ERROR registering helper for port %d\n",
ports[i]);
- fini();
+ ip_conntrack_tftp_fini();
return(ret);
}
}
return(0);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_tftp_init);
+module_exit(ip_conntrack_tftp_fini);
diff --git a/net/ipv4/netfilter/ip_nat_amanda.c b/net/ipv4/netfilter/ip_nat_amanda.c
index 706c8074f42..3a888715bbf 100644
--- a/net/ipv4/netfilter/ip_nat_amanda.c
+++ b/net/ipv4/netfilter/ip_nat_amanda.c
@@ -68,19 +68,19 @@ static unsigned int help(struct sk_buff **pskb,
return ret;
}
-static void __exit fini(void)
+static void __exit ip_nat_amanda_fini(void)
{
ip_nat_amanda_hook = NULL;
/* Make sure noone calls it, meanwhile. */
synchronize_net();
}
-static int __init init(void)
+static int __init ip_nat_amanda_init(void)
{
BUG_ON(ip_nat_amanda_hook);
ip_nat_amanda_hook = help;
return 0;
}
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_amanda_init);
+module_exit(ip_nat_amanda_fini);
diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
index b8daab3c64a..3328fc5c5f5 100644
--- a/net/ipv4/netfilter/ip_nat_ftp.c
+++ b/net/ipv4/netfilter/ip_nat_ftp.c
@@ -154,14 +154,14 @@ static unsigned int ip_nat_ftp(struct sk_buff **pskb,
return NF_ACCEPT;
}
-static void __exit fini(void)
+static void __exit ip_nat_ftp_fini(void)
{
ip_nat_ftp_hook = NULL;
/* Make sure noone calls it, meanwhile. */
synchronize_net();
}
-static int __init init(void)
+static int __init ip_nat_ftp_init(void)
{
BUG_ON(ip_nat_ftp_hook);
ip_nat_ftp_hook = ip_nat_ftp;
@@ -177,5 +177,5 @@ static int warn_set(const char *val, struct kernel_param *kp)
}
module_param_call(ports, warn_set, NULL, NULL, 0);
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_ftp_init);
+module_exit(ip_nat_ftp_fini);
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
index b9c016c063b..f3977726ff0 100644
--- a/net/ipv4/netfilter/ip_nat_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -370,7 +370,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
extern int __init ip_nat_proto_gre_init(void);
extern void __exit ip_nat_proto_gre_fini(void);
-static int __init init(void)
+static int __init ip_nat_helper_pptp_init(void)
{
int ret;
@@ -396,7 +396,7 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ip_nat_helper_pptp_fini(void)
{
DEBUGP("cleanup_module\n" );
@@ -412,5 +412,5 @@ static void __exit fini(void)
printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_helper_pptp_init);
+module_exit(ip_nat_helper_pptp_fini);
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
index 461c833eaca..a767123e082 100644
--- a/net/ipv4/netfilter/ip_nat_irc.c
+++ b/net/ipv4/netfilter/ip_nat_irc.c
@@ -96,14 +96,14 @@ static unsigned int help(struct sk_buff **pskb,
return ret;
}
-static void __exit fini(void)
+static void __exit ip_nat_irc_fini(void)
{
ip_nat_irc_hook = NULL;
/* Make sure noone calls it, meanwhile. */
synchronize_net();
}
-static int __init init(void)
+static int __init ip_nat_irc_init(void)
{
BUG_ON(ip_nat_irc_hook);
ip_nat_irc_hook = help;
@@ -119,5 +119,5 @@ static int warn_set(const char *val, struct kernel_param *kp)
}
module_param_call(ports, warn_set, NULL, NULL, 0);
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_irc_init);
+module_exit(ip_nat_irc_fini);
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index f029da2a60e..c6225384553 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -1324,7 +1324,7 @@ static struct ip_conntrack_helper snmp_trap_helper = {
*
*****************************************************************************/
-static int __init init(void)
+static int __init ip_nat_snmp_basic_init(void)
{
int ret = 0;
@@ -1339,13 +1339,13 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit ip_nat_snmp_basic_fini(void)
{
ip_conntrack_helper_unregister(&snmp_helper);
ip_conntrack_helper_unregister(&snmp_trap_helper);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_snmp_basic_init);
+module_exit(ip_nat_snmp_basic_fini);
module_param(debug, bool, 0600);
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 380aef3d786..3505b0de2e0 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -425,17 +425,17 @@ static int init_or_cleanup(int init)
return ret;
}
-static int __init init(void)
+static int __init ip_nat_standalone_init(void)
{
return init_or_cleanup(1);
}
-static void __exit fini(void)
+static void __exit ip_nat_standalone_fini(void)
{
init_or_cleanup(0);
}
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_standalone_init);
+module_exit(ip_nat_standalone_fini);
MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c
index 43c3bd7c118..94a78015451 100644
--- a/net/ipv4/netfilter/ip_nat_tftp.c
+++ b/net/ipv4/netfilter/ip_nat_tftp.c
@@ -53,19 +53,19 @@ static unsigned int help(struct sk_buff **pskb,
return NF_ACCEPT;
}
-static void __exit fini(void)
+static void __exit ip_nat_tftp_fini(void)
{
ip_nat_tftp_hook = NULL;
/* Make sure noone calls it, meanwhile. */
synchronize_net();
}
-static int __init init(void)
+static int __init ip_nat_tftp_init(void)
{
BUG_ON(ip_nat_tftp_hook);
ip_nat_tftp_hook = help;
return 0;
}
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_tftp_init);
+module_exit(ip_nat_tftp_fini);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 1655866c55b..896a244f8f9 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -717,13 +717,13 @@ cleanup_netlink_notifier:
return status;
}
-static int __init init(void)
+static int __init ip_queue_init(void)
{
return init_or_cleanup(1);
}
-static void __exit fini(void)
+static void __exit ip_queue_fini(void)
{
init_or_cleanup(0);
}
@@ -732,5 +732,5 @@ MODULE_DESCRIPTION("IPv4 packet queue handler");
MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
MODULE_LICENSE("GPL");
-module_init(init);
-module_exit(fini);
+module_init(ip_queue_init);
+module_exit(ip_queue_fini);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index a7b194c4d79..460fd905fad 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1364,7 +1364,7 @@ static struct ipt_match icmp_matchstruct = {
.checkentry = icmp_checkentry,
};
-static int __init init(void)
+static int __init ip_tables_init(void)
{
int ret;
@@ -1386,7 +1386,7 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ip_tables_fini(void)
{
nf_unregister_sockopt(&ipt_sockopts);
@@ -1400,5 +1400,5 @@ static void __exit fini(void)
EXPORT_SYMBOL(ipt_register_table);
EXPORT_SYMBOL(ipt_unregister_table);
EXPORT_SYMBOL(ipt_do_table);
-module_init(init);
-module_exit(fini);
+module_init(ip_tables_init);
+module_exit(ip_tables_fini);
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 61e11edcd6a..e4768a31718 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -770,15 +770,15 @@ cleanup_none:
return -EINVAL;
}
-static int __init init(void)
+static int __init ipt_clusterip_init(void)
{
return init_or_cleanup(0);
}
-static void __exit fini(void)
+static void __exit ipt_clusterip_fini(void)
{
init_or_cleanup(1);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_clusterip_init);
+module_exit(ipt_clusterip_fini);
diff --git a/net/ipv4/netfilter/ipt_DSCP.c b/net/ipv4/netfilter/ipt_DSCP.c
index cfb0b90e598..c8e971288df 100644
--- a/net/ipv4/netfilter/ipt_DSCP.c
+++ b/net/ipv4/netfilter/ipt_DSCP.c
@@ -82,15 +82,15 @@ static struct ipt_target ipt_dscp_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_dscp_init(void)
{
return ipt_register_target(&ipt_dscp_reg);
}
-static void __exit fini(void)
+static void __exit ipt_dscp_fini(void)
{
ipt_unregister_target(&ipt_dscp_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_dscp_init);
+module_exit(ipt_dscp_fini);
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index b9b80f90c84..4adf5c9d34f 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -151,15 +151,15 @@ static struct ipt_target ipt_ecn_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_ecn_init(void)
{
return ipt_register_target(&ipt_ecn_reg);
}
-static void __exit fini(void)
+static void __exit ipt_ecn_fini(void)
{
ipt_unregister_target(&ipt_ecn_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_ecn_init);
+module_exit(ipt_ecn_fini);
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 750d3221b28..39fd4c2a238 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -471,7 +471,7 @@ static struct nf_logger ipt_log_logger ={
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_log_init(void)
{
if (ipt_register_target(&ipt_log_reg))
return -EINVAL;
@@ -485,11 +485,11 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ipt_log_fini(void)
{
nf_log_unregister_logger(&ipt_log_logger);
ipt_unregister_target(&ipt_log_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_log_init);
+module_exit(ipt_log_fini);
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index e0c321c3bae..8b3e7f99b86 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -175,7 +175,7 @@ static struct ipt_target masquerade = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_masquerade_init(void)
{
int ret;
@@ -191,12 +191,12 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit ipt_masquerade_fini(void)
{
ipt_unregister_target(&masquerade);
unregister_netdevice_notifier(&masq_dev_notifier);
unregister_inetaddr_notifier(&masq_inet_notifier);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_masquerade_init);
+module_exit(ipt_masquerade_fini);
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index fba181c2a42..2fcf1075b02 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -98,15 +98,15 @@ static struct ipt_target target_module = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init ipt_netmap_init(void)
{
return ipt_register_target(&target_module);
}
-static void __exit fini(void)
+static void __exit ipt_netmap_fini(void)
{
ipt_unregister_target(&target_module);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_netmap_init);
+module_exit(ipt_netmap_fini);
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index be3da7c4b87..f290463232d 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -112,15 +112,15 @@ static struct ipt_target redirect_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_redirect_init(void)
{
return ipt_register_target(&redirect_reg);
}
-static void __exit fini(void)
+static void __exit ipt_redirect_fini(void)
{
ipt_unregister_target(&redirect_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_redirect_init);
+module_exit(ipt_redirect_fini);
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 9d3b3579f27..4269a5440d4 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -313,15 +313,15 @@ static struct ipt_target ipt_reject_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_reject_init(void)
{
return ipt_register_target(&ipt_reject_reg);
}
-static void __exit fini(void)
+static void __exit ipt_reject_fini(void)
{
ipt_unregister_target(&ipt_reject_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_reject_init);
+module_exit(ipt_reject_fini);
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index 7e2ebc9d945..7169b09b5a6 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -189,16 +189,16 @@ static struct ipt_target same_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_same_init(void)
{
return ipt_register_target(&same_reg);
}
-static void __exit fini(void)
+static void __exit ipt_same_fini(void)
{
ipt_unregister_target(&same_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_same_init);
+module_exit(ipt_same_fini);
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index c4fc50ec2dd..ef2fe5b3f0d 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -243,15 +243,15 @@ static struct ipt_target ipt_tcpmss_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_tcpmss_init(void)
{
return ipt_register_target(&ipt_tcpmss_reg);
}
-static void __exit fini(void)
+static void __exit ipt_tcpmss_fini(void)
{
ipt_unregister_target(&ipt_tcpmss_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_tcpmss_init);
+module_exit(ipt_tcpmss_fini);
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 9aa7817657f..1c7a5ca399b 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -81,15 +81,15 @@ static struct ipt_target ipt_tos_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_tos_init(void)
{
return ipt_register_target(&ipt_tos_reg);
}
-static void __exit fini(void)
+static void __exit ipt_tos_fini(void)
{
ipt_unregister_target(&ipt_tos_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_tos_init);
+module_exit(ipt_tos_fini);
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index 5009a003d57..f48892ae0be 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -94,15 +94,15 @@ static struct ipt_target ipt_TTL = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_ttl_init(void)
{
return ipt_register_target(&ipt_TTL);
}
-static void __exit fini(void)
+static void __exit ipt_ttl_fini(void)
{
ipt_unregister_target(&ipt_TTL);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_ttl_init);
+module_exit(ipt_ttl_fini);
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index a82a32ed0e2..c84cc03389d 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -374,7 +374,7 @@ static struct nf_logger ipt_ulog_logger = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_ulog_init(void)
{
int i;
@@ -407,7 +407,7 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ipt_ulog_fini(void)
{
ulog_buff_t *ub;
int i;
@@ -435,5 +435,5 @@ static void __exit fini(void)
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_ulog_init);
+module_exit(ipt_ulog_fini);
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index 5fdf85d0efc..893dae210b0 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -51,15 +51,15 @@ static struct ipt_match addrtype_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init ipt_addrtype_init(void)
{
return ipt_register_match(&addrtype_match);
}
-static void __exit fini(void)
+static void __exit ipt_addrtype_fini(void)
{
ipt_unregister_match(&addrtype_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_addrtype_init);
+module_exit(ipt_addrtype_fini);
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index 35a21fb1f8e..2927135873d 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -96,15 +96,15 @@ static struct ipt_match ah_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_ah_init(void)
{
return ipt_register_match(&ah_match);
}
-static void __exit cleanup(void)
+static void __exit ipt_ah_fini(void)
{
ipt_unregister_match(&ah_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ipt_ah_init);
+module_exit(ipt_ah_fini);
diff --git a/net/ipv4/netfilter/ipt_dscp.c b/net/ipv4/netfilter/ipt_dscp.c
index 11963c385de..47177591aeb 100644
--- a/net/ipv4/netfilter/ipt_dscp.c
+++ b/net/ipv4/netfilter/ipt_dscp.c
@@ -39,16 +39,16 @@ static struct ipt_match dscp_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_dscp_init(void)
{
return ipt_register_match(&dscp_match);
}
-static void __exit fini(void)
+static void __exit ipt_dscp_fini(void)
{
ipt_unregister_match(&dscp_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_dscp_init);
+module_exit(ipt_dscp_fini);
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index d7e29f6a38d..b2825041493 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -118,15 +118,15 @@ static struct ipt_match ecn_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_ecn_init(void)
{
return ipt_register_match(&ecn_match);
}
-static void __exit fini(void)
+static void __exit ipt_ecn_fini(void)
{
ipt_unregister_match(&ecn_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_ecn_init);
+module_exit(ipt_ecn_fini);
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c
index af0d5ec79cb..3840b417a3c 100644
--- a/net/ipv4/netfilter/ipt_esp.c
+++ b/net/ipv4/netfilter/ipt_esp.c
@@ -97,15 +97,15 @@ static struct ipt_match esp_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_esp_init(void)
{
return ipt_register_match(&esp_match);
}
-static void __exit cleanup(void)
+static void __exit ipt_esp_fini(void)
{
ipt_unregister_match(&esp_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ipt_esp_init);
+module_exit(ipt_esp_fini);
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index dc1521c5aa8..7c6836c4646 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -40,6 +40,7 @@
/* FIXME: this is just for IP_NF_ASSERRT */
#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/mutex.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
@@ -92,7 +93,7 @@ struct ipt_hashlimit_htable {
};
static DEFINE_SPINLOCK(hashlimit_lock); /* protects htables list */
-static DECLARE_MUTEX(hlimit_mutex); /* additional checkentry protection */
+static DEFINE_MUTEX(hlimit_mutex); /* additional checkentry protection */
static HLIST_HEAD(hashlimit_htables);
static kmem_cache_t *hashlimit_cachep __read_mostly;
@@ -542,13 +543,13 @@ hashlimit_checkentry(const char *tablename,
* call vmalloc, and that can sleep. And we cannot just re-search
* the list of htable's in htable_create(), since then we would
* create duplicate proc files. -HW */
- down(&hlimit_mutex);
+ mutex_lock(&hlimit_mutex);
r->hinfo = htable_find_get(r->name);
if (!r->hinfo && (htable_create(r) != 0)) {
- up(&hlimit_mutex);
+ mutex_unlock(&hlimit_mutex);
return 0;
}
- up(&hlimit_mutex);
+ mutex_unlock(&hlimit_mutex);
/* Ugly hack: For SMP, we only want to use one set */
r->u.master = r;
@@ -718,15 +719,15 @@ cleanup_nothing:
}
-static int __init init(void)
+static int __init ipt_hashlimit_init(void)
{
return init_or_fini(0);
}
-static void __exit fini(void)
+static void __exit ipt_hashlimit_fini(void)
{
init_or_fini(1);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_hashlimit_init);
+module_exit(ipt_hashlimit_fini);
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c
index ae70112f5e0..5202edd8d33 100644
--- a/net/ipv4/netfilter/ipt_iprange.c
+++ b/net/ipv4/netfilter/ipt_iprange.c
@@ -71,15 +71,15 @@ static struct ipt_match iprange_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init ipt_iprange_init(void)
{
return ipt_register_match(&iprange_match);
}
-static void __exit fini(void)
+static void __exit ipt_iprange_fini(void)
{
ipt_unregister_match(&iprange_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_iprange_init);
+module_exit(ipt_iprange_fini);
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c
index bd07f7c5387..ac95d8390bc 100644
--- a/net/ipv4/netfilter/ipt_multiport.c
+++ b/net/ipv4/netfilter/ipt_multiport.c
@@ -171,7 +171,7 @@ static struct ipt_match multiport_match_v1 = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_multiport_init(void)
{
int err;
@@ -185,11 +185,11 @@ static int __init init(void)
return err;
}
-static void __exit fini(void)
+static void __exit ipt_multiport_fini(void)
{
ipt_unregister_match(&multiport_match);
ipt_unregister_match(&multiport_match_v1);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_multiport_init);
+module_exit(ipt_multiport_fini);
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 3900428771f..5ac6ac023b5 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -78,15 +78,15 @@ static struct ipt_match owner_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_owner_init(void)
{
return ipt_register_match(&owner_match);
}
-static void __exit fini(void)
+static void __exit ipt_owner_fini(void)
{
ipt_unregister_match(&owner_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_owner_init);
+module_exit(ipt_owner_fini);
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 06792ead1da..14384328570 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -962,7 +962,7 @@ static struct ipt_match recent_match = {
};
/* Kernel module initialization. */
-static int __init init(void)
+static int __init ipt_recent_init(void)
{
int err, count;
@@ -995,7 +995,7 @@ static int __init init(void)
}
/* Kernel module destruction. */
-static void __exit fini(void)
+static void __exit ipt_recent_fini(void)
{
ipt_unregister_match(&recent_match);
@@ -1003,5 +1003,5 @@ static void __exit fini(void)
}
/* Register our module with the kernel. */
-module_init(init);
-module_exit(fini);
+module_init(ipt_recent_init);
+module_exit(ipt_recent_fini);
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c
index e404e92ddd0..5549c39c785 100644
--- a/net/ipv4/netfilter/ipt_tos.c
+++ b/net/ipv4/netfilter/ipt_tos.c
@@ -39,15 +39,15 @@ static struct ipt_match tos_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_multiport_init(void)
{
return ipt_register_match(&tos_match);
}
-static void __exit fini(void)
+static void __exit ipt_multiport_fini(void)
{
ipt_unregister_match(&tos_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_multiport_init);
+module_exit(ipt_multiport_fini);
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index ae7ce4d8d90..a5243bdb87d 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -55,16 +55,16 @@ static struct ipt_match ttl_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ipt_ttl_init(void)
{
return ipt_register_match(&ttl_match);
}
-static void __exit fini(void)
+static void __exit ipt_ttl_fini(void)
{
ipt_unregister_match(&ttl_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ipt_ttl_init);
+module_exit(ipt_ttl_fini);
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 212a3079085..3d80aefe9cf 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -139,7 +139,7 @@ static struct nf_hook_ops ipt_ops[] = {
static int forward = NF_ACCEPT;
module_param(forward, bool, 0000);
-static int __init init(void)
+static int __init iptable_filter_init(void)
{
int ret;
@@ -181,7 +181,7 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit iptable_filter_fini(void)
{
unsigned int i;
@@ -191,5 +191,5 @@ static void __exit fini(void)
ipt_unregister_table(&packet_filter);
}
-module_init(init);
-module_exit(fini);
+module_init(iptable_filter_init);
+module_exit(iptable_filter_fini);
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 3212a5cc4b6..412fc96cc89 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -201,7 +201,7 @@ static struct nf_hook_ops ipt_ops[] = {
},
};
-static int __init init(void)
+static int __init iptable_mangle_init(void)
{
int ret;
@@ -247,7 +247,7 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit iptable_mangle_fini(void)
{
unsigned int i;
@@ -257,5 +257,5 @@ static void __exit fini(void)
ipt_unregister_table(&packet_mangler);
}
-module_init(init);
-module_exit(fini);
+module_init(iptable_mangle_init);
+module_exit(iptable_mangle_fini);
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index fdb9e9c81e8..03cc79a6160 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -116,7 +116,7 @@ static struct nf_hook_ops ipt_ops[] = {
},
};
-static int __init init(void)
+static int __init iptable_raw_init(void)
{
int ret;
@@ -144,7 +144,7 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit iptable_raw_fini(void)
{
unsigned int i;
@@ -154,6 +154,6 @@ static void __exit fini(void)
ipt_unregister_table(&packet_raw);
}
-module_init(init);
-module_exit(fini);
+module_init(iptable_raw_init);
+module_exit(iptable_raw_fini);
MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index c8abc9d859b..4afbc699d3b 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -571,18 +571,18 @@ static int init_or_cleanup(int init)
MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
MODULE_LICENSE("GPL");
-static int __init init(void)
+static int __init nf_conntrack_l3proto_ipv4_init(void)
{
need_conntrack();
return init_or_cleanup(1);
}
-static void __exit fini(void)
+static void __exit nf_conntrack_l3proto_ipv4_fini(void)
{
init_or_cleanup(0);
}
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_l3proto_ipv4_init);
+module_exit(nf_conntrack_l3proto_ipv4_fini);
EXPORT_SYMBOL(nf_ct_ipv4_gather_frags);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index fca5fe0cf94..94fcbc5e5a1 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -55,6 +55,8 @@
* Robert Olsson : Added rt_cache statistics
* Arnaldo C. Melo : Convert proc stuff to seq_file
* Eric Dumazet : hashed spinlocks and rt_check_expire() fixes.
+ * Ilia Sotnikov : Ignore TOS on PMTUD and Redirect
+ * Ilia Sotnikov : Removed TOS from hash calculations
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -247,9 +249,9 @@ static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
static int rt_intern_hash(unsigned hash, struct rtable *rth,
struct rtable **res);
-static unsigned int rt_hash_code(u32 daddr, u32 saddr, u8 tos)
+static unsigned int rt_hash_code(u32 daddr, u32 saddr)
{
- return (jhash_3words(daddr, saddr, (u32) tos, rt_hash_rnd)
+ return (jhash_2words(daddr, saddr, rt_hash_rnd)
& rt_hash_mask);
}
@@ -1111,7 +1113,7 @@ static void rt_del(unsigned hash, struct rtable *rt)
}
void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
- u32 saddr, u8 tos, struct net_device *dev)
+ u32 saddr, struct net_device *dev)
{
int i, k;
struct in_device *in_dev = in_dev_get(dev);
@@ -1119,8 +1121,6 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
u32 skeys[2] = { saddr, 0 };
int ikeys[2] = { dev->ifindex, 0 };
- tos &= IPTOS_RT_MASK;
-
if (!in_dev)
return;
@@ -1141,8 +1141,7 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
for (i = 0; i < 2; i++) {
for (k = 0; k < 2; k++) {
unsigned hash = rt_hash_code(daddr,
- skeys[i] ^ (ikeys[k] << 5),
- tos);
+ skeys[i] ^ (ikeys[k] << 5));
rthp=&rt_hash_table[hash].chain;
@@ -1152,7 +1151,6 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
if (rth->fl.fl4_dst != daddr ||
rth->fl.fl4_src != skeys[i] ||
- rth->fl.fl4_tos != tos ||
rth->fl.oif != ikeys[k] ||
rth->fl.iif != 0) {
rthp = &rth->u.rt_next;
@@ -1232,10 +1230,9 @@ reject_redirect:
if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
printk(KERN_INFO "Redirect from %u.%u.%u.%u on %s about "
"%u.%u.%u.%u ignored.\n"
- " Advised path = %u.%u.%u.%u -> %u.%u.%u.%u, "
- "tos %02x\n",
+ " Advised path = %u.%u.%u.%u -> %u.%u.%u.%u\n",
NIPQUAD(old_gw), dev->name, NIPQUAD(new_gw),
- NIPQUAD(saddr), NIPQUAD(daddr), tos);
+ NIPQUAD(saddr), NIPQUAD(daddr));
#endif
in_dev_put(in_dev);
}
@@ -1253,8 +1250,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
rt->u.dst.expires) {
unsigned hash = rt_hash_code(rt->fl.fl4_dst,
rt->fl.fl4_src ^
- (rt->fl.oif << 5),
- rt->fl.fl4_tos);
+ (rt->fl.oif << 5));
#if RT_CACHE_DEBUG >= 1
printk(KERN_DEBUG "ip_rt_advice: redirect to "
"%u.%u.%u.%u/%02x dropped\n",
@@ -1391,14 +1387,13 @@ unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu)
struct rtable *rth;
u32 skeys[2] = { iph->saddr, 0, };
u32 daddr = iph->daddr;
- u8 tos = iph->tos & IPTOS_RT_MASK;
unsigned short est_mtu = 0;
if (ipv4_config.no_pmtu_disc)
return 0;
for (i = 0; i < 2; i++) {
- unsigned hash = rt_hash_code(daddr, skeys[i], tos);
+ unsigned hash = rt_hash_code(daddr, skeys[i]);
rcu_read_lock();
for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
@@ -1407,7 +1402,6 @@ unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu)
rth->fl.fl4_src == skeys[i] &&
rth->rt_dst == daddr &&
rth->rt_src == iph->saddr &&
- rth->fl.fl4_tos == tos &&
rth->fl.iif == 0 &&
!(dst_metric_locked(&rth->u.dst, RTAX_MTU))) {
unsigned short mtu = new_mtu;
@@ -1658,7 +1652,7 @@ static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
RT_CACHE_STAT_INC(in_slow_mc);
in_dev_put(in_dev);
- hash = rt_hash_code(daddr, saddr ^ (dev->ifindex << 5), tos);
+ hash = rt_hash_code(daddr, saddr ^ (dev->ifindex << 5));
return rt_intern_hash(hash, rth, (struct rtable**) &skb->dst);
e_nobufs:
@@ -1823,7 +1817,7 @@ static inline int ip_mkroute_input_def(struct sk_buff *skb,
return err;
/* put it into the cache */
- hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5), tos);
+ hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5));
return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
}
@@ -1864,7 +1858,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
return err;
/* put it into the cache */
- hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5), tos);
+ hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5));
err = rt_intern_hash(hash, rth, &rtres);
if (err)
return err;
@@ -2041,7 +2035,7 @@ local_input:
rth->rt_flags &= ~RTCF_LOCAL;
}
rth->rt_type = res.type;
- hash = rt_hash_code(daddr, saddr ^ (fl.iif << 5), tos);
+ hash = rt_hash_code(daddr, saddr ^ (fl.iif << 5));
err = rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
goto done;
@@ -2088,7 +2082,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
int iif = dev->ifindex;
tos &= IPTOS_RT_MASK;
- hash = rt_hash_code(daddr, saddr ^ (iif << 5), tos);
+ hash = rt_hash_code(daddr, saddr ^ (iif << 5));
rcu_read_lock();
for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
@@ -2286,10 +2280,8 @@ static inline int ip_mkroute_output_def(struct rtable **rp,
int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
unsigned hash;
if (err == 0) {
- u32 tos = RT_FL_TOS(oldflp);
-
hash = rt_hash_code(oldflp->fl4_dst,
- oldflp->fl4_src ^ (oldflp->oif << 5), tos);
+ oldflp->fl4_src ^ (oldflp->oif << 5));
err = rt_intern_hash(hash, rth, rp);
}
@@ -2304,7 +2296,6 @@ static inline int ip_mkroute_output(struct rtable** rp,
unsigned flags)
{
#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- u32 tos = RT_FL_TOS(oldflp);
unsigned char hop;
unsigned hash;
int err = -EINVAL;
@@ -2334,7 +2325,7 @@ static inline int ip_mkroute_output(struct rtable** rp,
hash = rt_hash_code(oldflp->fl4_dst,
oldflp->fl4_src ^
- (oldflp->oif << 5), tos);
+ (oldflp->oif << 5));
err = rt_intern_hash(hash, rth, rp);
/* forward hop information to multipath impl. */
@@ -2563,7 +2554,7 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
unsigned hash;
struct rtable *rth;
- hash = rt_hash_code(flp->fl4_dst, flp->fl4_src ^ (flp->oif << 5), flp->fl4_tos);
+ hash = rt_hash_code(flp->fl4_dst, flp->fl4_src ^ (flp->oif << 5));
rcu_read_lock_bh();
for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 4b0272c92d6..87f68e787d0 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -257,6 +257,7 @@
#include <linux/fs.h>
#include <linux/random.h>
#include <linux/bootmem.h>
+#include <linux/cache.h>
#include <net/icmp.h>
#include <net/tcp.h>
@@ -275,9 +276,9 @@ atomic_t tcp_orphan_count = ATOMIC_INIT(0);
EXPORT_SYMBOL_GPL(tcp_orphan_count);
-int sysctl_tcp_mem[3];
-int sysctl_tcp_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
-int sysctl_tcp_rmem[3] = { 4 * 1024, 87380, 87380 * 2 };
+int sysctl_tcp_mem[3] __read_mostly;
+int sysctl_tcp_wmem[3] __read_mostly;
+int sysctl_tcp_rmem[3] __read_mostly;
EXPORT_SYMBOL(sysctl_tcp_mem);
EXPORT_SYMBOL(sysctl_tcp_rmem);
@@ -365,7 +366,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
if (sk->sk_shutdown == SHUTDOWN_MASK || sk->sk_state == TCP_CLOSE)
mask |= POLLHUP;
if (sk->sk_shutdown & RCV_SHUTDOWN)
- mask |= POLLIN | POLLRDNORM;
+ mask |= POLLIN | POLLRDNORM | POLLRDHUP;
/* Connected? */
if ((1 << sk->sk_state) & ~(TCPF_SYN_SENT | TCPF_SYN_RECV)) {
@@ -2081,7 +2082,8 @@ __setup("thash_entries=", set_thash_entries);
void __init tcp_init(void)
{
struct sk_buff *skb = NULL;
- int order, i;
+ unsigned long limit;
+ int order, i, max_share;
if (sizeof(struct tcp_skb_cb) > sizeof(skb->cb))
__skb_cb_too_small_for_tcp(sizeof(struct tcp_skb_cb),
@@ -2155,12 +2157,16 @@ void __init tcp_init(void)
sysctl_tcp_mem[1] = 1024 << order;
sysctl_tcp_mem[2] = 1536 << order;
- if (order < 3) {
- sysctl_tcp_wmem[2] = 64 * 1024;
- sysctl_tcp_rmem[0] = PAGE_SIZE;
- sysctl_tcp_rmem[1] = 43689;
- sysctl_tcp_rmem[2] = 2 * 43689;
- }
+ limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7);
+ max_share = min(4UL*1024*1024, limit);
+
+ sysctl_tcp_wmem[0] = SK_STREAM_MEM_QUANTUM;
+ sysctl_tcp_wmem[1] = 16*1024;
+ sysctl_tcp_wmem[2] = max(64*1024, max_share);
+
+ sysctl_tcp_rmem[0] = SK_STREAM_MEM_QUANTUM;
+ sysctl_tcp_rmem[1] = 87380;
+ sysctl_tcp_rmem[2] = max(87380, max_share);
printk(KERN_INFO "TCP: Hash tables configured "
"(established %d bind %d)\n",
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index e688c687d62..91c2f41c7f5 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -223,7 +223,7 @@ void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 rtt, u32 in_flight,
/* In dangerous area, increase slowly. */
else if (sysctl_tcp_abc) {
- /* RFC3465: Apppriate Byte Count
+ /* RFC3465: Appropriate Byte Count
* increase once for each full cwnd acked
*/
if (tp->bytes_acked >= tp->snd_cwnd*tp->mss_cache) {
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
new file mode 100644
index 00000000000..0d7d386dac2
--- /dev/null
+++ b/net/ipv4/tunnel4.c
@@ -0,0 +1,113 @@
+/* tunnel4.c: Generic IP tunnel transformer.
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <net/protocol.h>
+#include <net/xfrm.h>
+
+static struct xfrm_tunnel *tunnel4_handlers;
+static DEFINE_MUTEX(tunnel4_mutex);
+
+int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
+{
+ struct xfrm_tunnel **pprev;
+ int ret = -EEXIST;
+ int priority = handler->priority;
+
+ mutex_lock(&tunnel4_mutex);
+
+ for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
+ if ((*pprev)->priority > priority)
+ break;
+ if ((*pprev)->priority == priority)
+ goto err;
+ }
+
+ handler->next = *pprev;
+ *pprev = handler;
+
+ ret = 0;
+
+err:
+ mutex_unlock(&tunnel4_mutex);
+
+ return ret;
+}
+
+EXPORT_SYMBOL(xfrm4_tunnel_register);
+
+int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
+{
+ struct xfrm_tunnel **pprev;
+ int ret = -ENOENT;
+
+ mutex_lock(&tunnel4_mutex);
+
+ for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
+ if (*pprev == handler) {
+ *pprev = handler->next;
+ ret = 0;
+ break;
+ }
+ }
+
+ mutex_unlock(&tunnel4_mutex);
+
+ synchronize_net();
+
+ return ret;
+}
+
+EXPORT_SYMBOL(xfrm4_tunnel_deregister);
+
+static int tunnel4_rcv(struct sk_buff *skb)
+{
+ struct xfrm_tunnel *handler;
+
+ for (handler = tunnel4_handlers; handler; handler = handler->next)
+ if (!handler->handler(skb))
+ return 0;
+
+ kfree_skb(skb);
+ return 0;
+}
+
+static void tunnel4_err(struct sk_buff *skb, u32 info)
+{
+ struct xfrm_tunnel *handler;
+
+ for (handler = tunnel4_handlers; handler; handler = handler->next)
+ if (!handler->err_handler(skb, info))
+ break;
+}
+
+static struct net_protocol tunnel4_protocol = {
+ .handler = tunnel4_rcv,
+ .err_handler = tunnel4_err,
+ .no_policy = 1,
+};
+
+static int __init tunnel4_init(void)
+{
+ if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) {
+ printk(KERN_ERR "tunnel4 init: can't add protocol\n");
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+static void __exit tunnel4_fini(void)
+{
+ if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP))
+ printk(KERN_ERR "tunnel4 close: can't remove protocol\n");
+}
+
+module_init(tunnel4_init);
+module_exit(tunnel4_fini);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index b08d56b117f..2d670935c2b 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -26,64 +26,6 @@ static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, s
return 0;
}
-static struct xfrm_tunnel *ipip_handler;
-static DEFINE_MUTEX(xfrm4_tunnel_mutex);
-
-int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
-{
- int ret;
-
- mutex_lock(&xfrm4_tunnel_mutex);
- ret = 0;
- if (ipip_handler != NULL)
- ret = -EINVAL;
- if (!ret)
- ipip_handler = handler;
- mutex_unlock(&xfrm4_tunnel_mutex);
-
- return ret;
-}
-
-EXPORT_SYMBOL(xfrm4_tunnel_register);
-
-int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
-{
- int ret;
-
- mutex_lock(&xfrm4_tunnel_mutex);
- ret = 0;
- if (ipip_handler != handler)
- ret = -EINVAL;
- if (!ret)
- ipip_handler = NULL;
- mutex_unlock(&xfrm4_tunnel_mutex);
-
- synchronize_net();
-
- return ret;
-}
-
-EXPORT_SYMBOL(xfrm4_tunnel_deregister);
-
-static int ipip_rcv(struct sk_buff *skb)
-{
- struct xfrm_tunnel *handler = ipip_handler;
-
- /* Tunnel devices take precedence. */
- if (handler && handler->handler(skb) == 0)
- return 0;
-
- return xfrm4_rcv(skb);
-}
-
-static void ipip_err(struct sk_buff *skb, u32 info)
-{
- struct xfrm_tunnel *handler = ipip_handler;
-
- if (handler)
- handler->err_handler(skb, info);
-}
-
static int ipip_init_state(struct xfrm_state *x)
{
if (!x->props.mode)
@@ -111,10 +53,15 @@ static struct xfrm_type ipip_type = {
.output = ipip_output
};
-static struct net_protocol ipip_protocol = {
- .handler = ipip_rcv,
- .err_handler = ipip_err,
- .no_policy = 1,
+static int xfrm_tunnel_err(struct sk_buff *skb, u32 info)
+{
+ return -ENOENT;
+}
+
+static struct xfrm_tunnel xfrm_tunnel_handler = {
+ .handler = xfrm4_rcv,
+ .err_handler = xfrm_tunnel_err,
+ .priority = 2,
};
static int __init ipip_init(void)
@@ -123,8 +70,8 @@ static int __init ipip_init(void)
printk(KERN_INFO "ipip init: can't add xfrm type\n");
return -EAGAIN;
}
- if (inet_add_protocol(&ipip_protocol, IPPROTO_IPIP) < 0) {
- printk(KERN_INFO "ipip init: can't add protocol\n");
+ if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) {
+ printk(KERN_INFO "ipip init: can't add xfrm handler\n");
xfrm_unregister_type(&ipip_type, AF_INET);
return -EAGAIN;
}
@@ -133,8 +80,8 @@ static int __init ipip_init(void)
static void __exit ipip_fini(void)
{
- if (inet_del_protocol(&ipip_protocol, IPPROTO_IPIP) < 0)
- printk(KERN_INFO "ipip close: can't remove protocol\n");
+ if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler))
+ printk(KERN_INFO "ipip close: can't remove xfrm handler\n");
if (xfrm_unregister_type(&ipip_type, AF_INET) < 0)
printk(KERN_INFO "ipip close: can't remove xfrm type\n");
}
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index e6f83b6a2b7..f8a107ab559 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -88,7 +88,7 @@ config INET6_IPCOMP
tristate "IPv6: IPComp transformation"
depends on IPV6
select XFRM
- select INET6_TUNNEL
+ select INET6_XFRM_TUNNEL
select CRYPTO
select CRYPTO_DEFLATE
---help---
@@ -97,19 +97,18 @@ config INET6_IPCOMP
If unsure, say Y.
+config INET6_XFRM_TUNNEL
+ tristate
+ select INET6_TUNNEL
+ default n
+
config INET6_TUNNEL
- tristate "IPv6: tunnel transformation"
- depends on IPV6
- select XFRM
- ---help---
- Support for generic IPv6-in-IPv6 tunnel transformation, which is
- required by the IPv6-in-IPv6 tunneling module as well as tunnel mode
- IPComp.
-
- If unsure, say Y.
+ tristate
+ default n
config IPV6_TUNNEL
tristate "IPv6: IPv6-in-IPv6 tunnel"
+ select INET6_TUNNEL
depends on IPV6
---help---
Support for IPv6-in-IPv6 tunnels described in RFC 2473.
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 41877abd22e..a760b0988fb 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -18,7 +18,8 @@ ipv6-objs += $(ipv6-y)
obj-$(CONFIG_INET6_AH) += ah6.o
obj-$(CONFIG_INET6_ESP) += esp6.o
obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o
-obj-$(CONFIG_INET6_TUNNEL) += xfrm6_tunnel.o
+obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o
+obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o
obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 01c62a0d374..445006ee452 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -143,7 +143,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
struct prefix_info *pinfo);
static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev);
-static struct notifier_block *inet6addr_chain;
+static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
struct ipv6_devconf ipv6_devconf = {
.forwarding = 0,
@@ -593,7 +593,7 @@ out2:
read_unlock_bh(&addrconf_lock);
if (likely(err == 0))
- notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
+ atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
else {
kfree(ifa);
ifa = ERR_PTR(err);
@@ -688,7 +688,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
ipv6_ifa_notify(RTM_DELADDR, ifp);
- notifier_call_chain(&inet6addr_chain,NETDEV_DOWN,ifp);
+ atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp);
addrconf_del_timer(ifp);
@@ -3767,12 +3767,12 @@ static void addrconf_sysctl_unregister(struct ipv6_devconf *p)
int register_inet6addr_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&inet6addr_chain, nb);
+ return atomic_notifier_chain_register(&inet6addr_chain, nb);
}
int unregister_inet6addr_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&inet6addr_chain,nb);
+ return atomic_notifier_chain_unregister(&inet6addr_chain,nb);
}
/*
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 48597538db3..ff9040c9255 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -44,7 +44,6 @@
#include <net/ip.h>
#include <net/ipv6.h>
-#include <net/protocol.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
#include <net/ip6_tunnel.h>
@@ -391,7 +390,7 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw)
* to the specifications in RFC 2473.
**/
-static void
+static int
ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
int type, int code, int offset, __u32 info)
{
@@ -402,6 +401,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
int rel_code = ICMPV6_ADDR_UNREACH;
__u32 rel_info = 0;
__u16 len;
+ int err = -ENOENT;
/* If the packet doesn't contain the original IPv6 header we are
in trouble since we might need the source address for further
@@ -411,6 +411,8 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
if ((t = ip6ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL)
goto out;
+ err = 0;
+
switch (type) {
__u32 teli;
struct ipv6_tlv_tnl_enc_lim *tel;
@@ -492,6 +494,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
}
out:
read_unlock(&ip6ip6_lock);
+ return err;
}
static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
@@ -511,9 +514,8 @@ static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
**/
static int
-ip6ip6_rcv(struct sk_buff **pskb)
+ip6ip6_rcv(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
struct ipv6hdr *ipv6h;
struct ip6_tnl *t;
@@ -1112,39 +1114,12 @@ ip6ip6_fb_tnl_dev_init(struct net_device *dev)
return 0;
}
-#ifdef CONFIG_INET6_TUNNEL
static struct xfrm6_tunnel ip6ip6_handler = {
.handler = ip6ip6_rcv,
.err_handler = ip6ip6_err,
+ .priority = 1,
};
-static inline int ip6ip6_register(void)
-{
- return xfrm6_tunnel_register(&ip6ip6_handler);
-}
-
-static inline int ip6ip6_unregister(void)
-{
- return xfrm6_tunnel_deregister(&ip6ip6_handler);
-}
-#else
-static struct inet6_protocol xfrm6_tunnel_protocol = {
- .handler = ip6ip6_rcv,
- .err_handler = ip6ip6_err,
- .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
-};
-
-static inline int ip6ip6_register(void)
-{
- return inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
-}
-
-static inline int ip6ip6_unregister(void)
-{
- return inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
-}
-#endif
-
/**
* ip6_tunnel_init - register protocol and reserve needed resources
*
@@ -1155,7 +1130,7 @@ static int __init ip6_tunnel_init(void)
{
int err;
- if (ip6ip6_register() < 0) {
+ if (xfrm6_tunnel_register(&ip6ip6_handler)) {
printk(KERN_ERR "ip6ip6 init: can't register tunnel\n");
return -EAGAIN;
}
@@ -1174,7 +1149,7 @@ static int __init ip6_tunnel_init(void)
}
return 0;
fail:
- ip6ip6_unregister();
+ xfrm6_tunnel_deregister(&ip6ip6_handler);
return err;
}
@@ -1184,7 +1159,7 @@ fail:
static void __exit ip6_tunnel_cleanup(void)
{
- if (ip6ip6_unregister() < 0)
+ if (xfrm6_tunnel_deregister(&ip6ip6_handler))
printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");
unregister_netdev(ip6ip6_fb_tnl_dev);
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 028b636687e..d4cfec3f414 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -228,6 +228,9 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
t->id.proto = IPPROTO_IPV6;
t->id.spi = xfrm6_tunnel_alloc_spi((xfrm_address_t *)&x->props.saddr);
+ if (!t->id.spi)
+ goto error;
+
memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr));
memcpy(&t->sel, &x->sel, sizeof(t->sel));
t->props.family = AF_INET6;
@@ -243,7 +246,9 @@ out:
return t;
error:
+ t->km.state = XFRM_STATE_DEAD;
xfrm_state_put(t);
+ t = NULL;
goto out;
}
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 344eab3b5da..e81c6a9dab8 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -713,13 +713,13 @@ cleanup_netlink_notifier:
return status;
}
-static int __init init(void)
+static int __init ip6_queue_init(void)
{
return init_or_cleanup(1);
}
-static void __exit fini(void)
+static void __exit ip6_queue_fini(void)
{
init_or_cleanup(0);
}
@@ -727,5 +727,5 @@ static void __exit fini(void)
MODULE_DESCRIPTION("IPv6 packet queue handler");
MODULE_LICENSE("GPL");
-module_init(init);
-module_exit(fini);
+module_init(ip6_queue_init);
+module_exit(ip6_queue_fini);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index db3c9ae98e9..3ecf2db841f 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1406,7 +1406,7 @@ static struct ip6t_match icmp6_matchstruct = {
.family = AF_INET6,
};
-static int __init init(void)
+static int __init ip6_tables_init(void)
{
int ret;
@@ -1429,7 +1429,7 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ip6_tables_fini(void)
{
nf_unregister_sockopt(&ip6t_sockopts);
xt_unregister_match(&icmp6_matchstruct);
@@ -1517,5 +1517,5 @@ EXPORT_SYMBOL(ip6t_do_table);
EXPORT_SYMBOL(ip6t_ext_hdr);
EXPORT_SYMBOL(ipv6_find_hdr);
-module_init(init);
-module_exit(fini);
+module_init(ip6_tables_init);
+module_exit(ip6_tables_fini);
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index da14c6d86bc..b8eff8ee69b 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -93,15 +93,15 @@ static struct ip6t_target ip6t_HL = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init ip6t_hl_init(void)
{
return ip6t_register_target(&ip6t_HL);
}
-static void __exit fini(void)
+static void __exit ip6t_hl_fini(void)
{
ip6t_unregister_target(&ip6t_HL);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6t_hl_init);
+module_exit(ip6t_hl_fini);
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 07c6bcbe4c5..a96c0de14b0 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -483,7 +483,7 @@ static struct nf_logger ip6t_logger = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_log_init(void)
{
if (ip6t_register_target(&ip6t_log_reg))
return -EINVAL;
@@ -497,11 +497,11 @@ static int __init init(void)
return 0;
}
-static void __exit fini(void)
+static void __exit ip6t_log_fini(void)
{
nf_log_unregister_logger(&ip6t_logger);
ip6t_unregister_target(&ip6t_log_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6t_log_init);
+module_exit(ip6t_log_fini);
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index ddfa38575fe..de1175c27f6 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -255,17 +255,17 @@ static struct ip6t_target ip6t_reject_reg = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init ip6t_reject_init(void)
{
if (ip6t_register_target(&ip6t_reject_reg))
return -EINVAL;
return 0;
}
-static void __exit fini(void)
+static void __exit ip6t_reject_fini(void)
{
ip6t_unregister_target(&ip6t_reject_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6t_reject_init);
+module_exit(ip6t_reject_fini);
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index 178f6fb1e53..2f7bb20c758 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -122,15 +122,15 @@ static struct ip6t_match ah_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_ah_init(void)
{
return ip6t_register_match(&ah_match);
}
-static void __exit cleanup(void)
+static void __exit ip6t_ah_fini(void)
{
ip6t_unregister_match(&ah_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_ah_init);
+module_exit(ip6t_ah_fini);
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
index e97a7022698..9422413d057 100644
--- a/net/ipv6/netfilter/ip6t_dst.c
+++ b/net/ipv6/netfilter/ip6t_dst.c
@@ -206,15 +206,15 @@ static struct ip6t_match opts_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_dst_init(void)
{
return ip6t_register_match(&opts_match);
}
-static void __exit cleanup(void)
+static void __exit ip6t_dst_fini(void)
{
ip6t_unregister_match(&opts_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_dst_init);
+module_exit(ip6t_dst_fini);
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
index 540b8bfd505..36bedad2c6f 100644
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ b/net/ipv6/netfilter/ip6t_esp.c
@@ -101,15 +101,15 @@ static struct ip6t_match esp_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_esp_init(void)
{
return ip6t_register_match(&esp_match);
}
-static void __exit cleanup(void)
+static void __exit ip6t_esp_fini(void)
{
ip6t_unregister_match(&esp_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_esp_init);
+module_exit(ip6t_esp_fini);
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index d4b0bad5283..94dbdb8b458 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -70,15 +70,15 @@ static struct ip6t_match eui64_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_eui64_init(void)
{
return ip6t_register_match(&eui64_match);
}
-static void __exit fini(void)
+static void __exit ip6t_eui64_fini(void)
{
ip6t_unregister_match(&eui64_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6t_eui64_init);
+module_exit(ip6t_eui64_fini);
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 4c41e14823d..06768c84bd3 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -139,15 +139,15 @@ static struct ip6t_match frag_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_frag_init(void)
{
return ip6t_register_match(&frag_match);
}
-static void __exit cleanup(void)
+static void __exit ip6t_frag_fini(void)
{
ip6t_unregister_match(&frag_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_frag_init);
+module_exit(ip6t_frag_fini);
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index b4a1fdfe6ab..374f1be85c0 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -206,15 +206,15 @@ static struct ip6t_match opts_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_hbh_init(void)
{
return ip6t_register_match(&opts_match);
}
-static void __exit cleanup(void)
+static void __exit ip6t_hbh_fini(void)
{
ip6t_unregister_match(&opts_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_hbh_init);
+module_exit(ip6t_hbh_fini);
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index 374055733b2..44a729e17c4 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -55,16 +55,16 @@ static struct ip6t_match hl_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_hl_init(void)
{
return ip6t_register_match(&hl_match);
}
-static void __exit fini(void)
+static void __exit ip6t_hl_fini(void)
{
ip6t_unregister_match(&hl_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6t_hl_init);
+module_exit(ip6t_hl_fini);
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
index 752b65d21c7..10c48ba596d 100644
--- a/net/ipv6/netfilter/ip6t_multiport.c
+++ b/net/ipv6/netfilter/ip6t_multiport.c
@@ -111,15 +111,15 @@ static struct ip6t_match multiport_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_multiport_init(void)
{
return ip6t_register_match(&multiport_match);
}
-static void __exit fini(void)
+static void __exit ip6t_multiport_fini(void)
{
ip6t_unregister_match(&multiport_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6t_multiport_init);
+module_exit(ip6t_multiport_fini);
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index e2cee3bcdef..5d047990cd4 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -79,15 +79,15 @@ static struct ip6t_match owner_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_owner_init(void)
{
return ip6t_register_match(&owner_match);
}
-static void __exit fini(void)
+static void __exit ip6t_owner_fini(void)
{
ip6t_unregister_match(&owner_match);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6t_owner_init);
+module_exit(ip6t_owner_fini);
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 4c6b55bb225..fbb0184a41d 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -225,15 +225,15 @@ static struct ip6t_match rt_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init ip6t_rt_init(void)
{
return ip6t_register_match(&rt_match);
}
-static void __exit cleanup(void)
+static void __exit ip6t_rt_fini(void)
{
ip6t_unregister_match(&rt_match);
}
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_rt_init);
+module_exit(ip6t_rt_fini);
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index ce4a968e1f7..e5e724d9ee6 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -159,7 +159,7 @@ static struct nf_hook_ops ip6t_ops[] = {
static int forward = NF_ACCEPT;
module_param(forward, bool, 0000);
-static int __init init(void)
+static int __init ip6table_filter_init(void)
{
int ret;
@@ -201,7 +201,7 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit ip6table_filter_fini(void)
{
unsigned int i;
@@ -211,5 +211,5 @@ static void __exit fini(void)
ip6t_unregister_table(&packet_filter);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6table_filter_init);
+module_exit(ip6table_filter_fini);
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 30a4627e000..e1f0f6ae984 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -228,7 +228,7 @@ static struct nf_hook_ops ip6t_ops[] = {
},
};
-static int __init init(void)
+static int __init ip6table_mangle_init(void)
{
int ret;
@@ -274,7 +274,7 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit ip6table_mangle_fini(void)
{
unsigned int i;
@@ -284,5 +284,5 @@ static void __exit fini(void)
ip6t_unregister_table(&packet_mangler);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6table_mangle_init);
+module_exit(ip6table_mangle_fini);
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index db28ba3855e..54d1fffd62b 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -142,7 +142,7 @@ static struct nf_hook_ops ip6t_ops[] = {
},
};
-static int __init init(void)
+static int __init ip6table_raw_init(void)
{
int ret;
@@ -170,7 +170,7 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit ip6table_raw_fini(void)
{
unsigned int i;
@@ -180,6 +180,6 @@ static void __exit fini(void)
ip6t_unregister_table(&packet_raw);
}
-module_init(init);
-module_exit(fini);
+module_init(ip6table_raw_init);
+module_exit(ip6table_raw_fini);
MODULE_LICENSE("GPL");
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index c16f62934bd..c8b5a96cbb0 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -588,16 +588,16 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
-static int __init init(void)
+static int __init nf_conntrack_l3proto_ipv6_init(void)
{
need_conntrack();
return init_or_cleanup(1);
}
-static void __exit fini(void)
+static void __exit nf_conntrack_l3proto_ipv6_fini(void)
{
init_or_cleanup(0);
}
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_l3proto_ipv6_init);
+module_exit(nf_conntrack_l3proto_ipv6_fini);
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
new file mode 100644
index 00000000000..5659b52284b
--- /dev/null
+++ b/net/ipv6/tunnel6.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C)2003,2004 USAGI/WIDE Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors Mitsuru KANDA <mk@linux-ipv6.org>
+ * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <net/protocol.h>
+#include <net/xfrm.h>
+
+static struct xfrm6_tunnel *tunnel6_handlers;
+static DEFINE_MUTEX(tunnel6_mutex);
+
+int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
+{
+ struct xfrm6_tunnel **pprev;
+ int ret = -EEXIST;
+ int priority = handler->priority;
+
+ mutex_lock(&tunnel6_mutex);
+
+ for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
+ if ((*pprev)->priority > priority)
+ break;
+ if ((*pprev)->priority == priority)
+ goto err;
+ }
+
+ handler->next = *pprev;
+ *pprev = handler;
+
+ ret = 0;
+
+err:
+ mutex_unlock(&tunnel6_mutex);
+
+ return ret;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_register);
+
+int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
+{
+ struct xfrm6_tunnel **pprev;
+ int ret = -ENOENT;
+
+ mutex_lock(&tunnel6_mutex);
+
+ for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
+ if (*pprev == handler) {
+ *pprev = handler->next;
+ ret = 0;
+ break;
+ }
+ }
+
+ mutex_unlock(&tunnel6_mutex);
+
+ synchronize_net();
+
+ return ret;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_deregister);
+
+static int tunnel6_rcv(struct sk_buff **pskb)
+{
+ struct sk_buff *skb = *pskb;
+ struct xfrm6_tunnel *handler;
+
+ for (handler = tunnel6_handlers; handler; handler = handler->next)
+ if (!handler->handler(skb))
+ return 0;
+
+ kfree_skb(skb);
+ return 0;
+}
+
+static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int type, int code, int offset, __u32 info)
+{
+ struct xfrm6_tunnel *handler;
+
+ for (handler = tunnel6_handlers; handler; handler = handler->next)
+ if (!handler->err_handler(skb, opt, type, code, offset, info))
+ break;
+}
+
+static struct inet6_protocol tunnel6_protocol = {
+ .handler = tunnel6_rcv,
+ .err_handler = tunnel6_err,
+ .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+};
+
+static int __init tunnel6_init(void)
+{
+ if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) {
+ printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+static void __exit tunnel6_fini(void)
+{
+ if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6))
+ printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
+}
+
+module_init(tunnel6_init);
+module_exit(tunnel6_fini);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 1ca2da68ef6..cccf8b76f04 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -28,9 +28,8 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
IP6_ECN_set_ce(inner_iph);
}
-int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi)
+int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
{
- struct sk_buff *skb = *pskb;
int err;
u32 seq;
struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
@@ -159,5 +158,5 @@ EXPORT_SYMBOL(xfrm6_rcv_spi);
int xfrm6_rcv(struct sk_buff **pskb)
{
- return xfrm6_rcv_spi(pskb, 0);
+ return xfrm6_rcv_spi(*pskb, 0);
}
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 08f9abbdf1d..a8f6776c518 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -28,7 +28,6 @@
#include <net/ip.h>
#include <net/xfrm.h>
#include <net/ipv6.h>
-#include <net/protocol.h>
#include <linux/ipv6.h>
#include <linux/icmpv6.h>
#include <linux/mutex.h>
@@ -357,71 +356,18 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *dec
return 0;
}
-static struct xfrm6_tunnel *xfrm6_tunnel_handler;
-static DEFINE_MUTEX(xfrm6_tunnel_mutex);
-
-int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
+static int xfrm6_tunnel_rcv(struct sk_buff *skb)
{
- int ret;
-
- mutex_lock(&xfrm6_tunnel_mutex);
- ret = 0;
- if (xfrm6_tunnel_handler != NULL)
- ret = -EINVAL;
- if (!ret)
- xfrm6_tunnel_handler = handler;
- mutex_unlock(&xfrm6_tunnel_mutex);
-
- return ret;
-}
-
-EXPORT_SYMBOL(xfrm6_tunnel_register);
-
-int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
-{
- int ret;
-
- mutex_lock(&xfrm6_tunnel_mutex);
- ret = 0;
- if (xfrm6_tunnel_handler != handler)
- ret = -EINVAL;
- if (!ret)
- xfrm6_tunnel_handler = NULL;
- mutex_unlock(&xfrm6_tunnel_mutex);
-
- synchronize_net();
-
- return ret;
-}
-
-EXPORT_SYMBOL(xfrm6_tunnel_deregister);
-
-static int xfrm6_tunnel_rcv(struct sk_buff **pskb)
-{
- struct sk_buff *skb = *pskb;
- struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
struct ipv6hdr *iph = skb->nh.ipv6h;
u32 spi;
- /* device-like_ip6ip6_handler() */
- if (handler && handler->handler(pskb) == 0)
- return 0;
-
spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
- return xfrm6_rcv_spi(pskb, spi);
+ return xfrm6_rcv_spi(skb, spi);
}
-static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info)
+static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int type, int code, int offset, __u32 info)
{
- struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
-
- /* call here first for device-like ip6ip6 err handling */
- if (handler) {
- handler->err_handler(skb, opt, type, code, offset, info);
- return;
- }
-
/* xfrm6_tunnel native err handling */
switch (type) {
case ICMPV6_DEST_UNREACH:
@@ -462,7 +408,8 @@ static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
default:
break;
}
- return;
+
+ return 0;
}
static int xfrm6_tunnel_init_state(struct xfrm_state *x)
@@ -493,10 +440,10 @@ static struct xfrm_type xfrm6_tunnel_type = {
.output = xfrm6_tunnel_output,
};
-static struct inet6_protocol xfrm6_tunnel_protocol = {
+static struct xfrm6_tunnel xfrm6_tunnel_handler = {
.handler = xfrm6_tunnel_rcv,
- .err_handler = xfrm6_tunnel_err,
- .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+ .err_handler = xfrm6_tunnel_err,
+ .priority = 2,
};
static int __init xfrm6_tunnel_init(void)
@@ -508,16 +455,16 @@ static int __init xfrm6_tunnel_init(void)
"xfrm6_tunnel init: can't add xfrm type\n");
return -EAGAIN;
}
- if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) {
+ if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) {
X6TPRINTK1(KERN_ERR
- "xfrm6_tunnel init(): can't add protocol\n");
+ "xfrm6_tunnel init(): can't add handler\n");
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
return -EAGAIN;
}
if (xfrm6_tunnel_spi_init() < 0) {
X6TPRINTK1(KERN_ERR
"xfrm6_tunnel init: failed to initialize spi\n");
- inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
+ xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
return -EAGAIN;
}
@@ -529,9 +476,9 @@ static void __exit xfrm6_tunnel_fini(void)
X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
xfrm6_tunnel_spi_fini();
- if (inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0)
+ if (xfrm6_tunnel_deregister(&xfrm6_tunnel_handler))
X6TPRINTK1(KERN_ERR
- "xfrm6_tunnel close: can't remove protocol\n");
+ "xfrm6_tunnel close: can't remove handler\n");
if (xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6) < 0)
X6TPRINTK1(KERN_ERR
"xfrm6_tunnel close: can't remove xfrm type\n");
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 0fb513a34d1..2dbf134d526 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -1892,6 +1892,29 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return rc;
}
+
+#ifdef CONFIG_COMPAT
+static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ /*
+ * These 4 commands use same structure on 32bit and 64bit. Rest of IPX
+ * commands is handled by generic ioctl code. As these commands are
+ * SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic
+ * code.
+ */
+ switch (cmd) {
+ case SIOCAIPXITFCRT:
+ case SIOCAIPXPRISLT:
+ case SIOCIPXCFGDATA:
+ case SIOCIPXNCPCONN:
+ return ipx_ioctl(sock, cmd, arg);
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+#endif
+
+
/*
* Socket family declarations
*/
@@ -1913,6 +1936,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
.getname = ipx_getname,
.poll = datagram_poll,
.ioctl = ipx_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = ipx_compat_ioctl,
+#endif
.listen = sock_no_listen,
.shutdown = sock_no_shutdown, /* FIXME: support shutdown */
.setsockopt = ipx_setsockopt,
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 75944564866..2f37c9f35e2 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -1302,7 +1302,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
if (sk->sk_state != TCP_ESTABLISHED)
return -ENOTCONN;
- /* Check that we don't send out to big frames */
+ /* Check that we don't send out too big frames */
if (len > self->max_data_size) {
IRDA_DEBUG(2, "%s(), Chopping frame from %zd to %d bytes!\n",
__FUNCTION__, len, self->max_data_size);
@@ -1546,7 +1546,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
IRDA_ASSERT(self != NULL, return -1;);
/*
- * Check that we don't send out to big frames. This is an unreliable
+ * Check that we don't send out too big frames. This is an unreliable
* service, so we have no fragmentation and no coalescence
*/
if (len > self->max_data_size) {
@@ -1642,7 +1642,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
}
/*
- * Check that we don't send out to big frames. This is an unreliable
+ * Check that we don't send out too big frames. This is an unreliable
* service, so we have no fragmentation and no coalescence
*/
if (len > self->max_data_size) {
@@ -1830,6 +1830,19 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return 0;
}
+#ifdef CONFIG_COMPAT
+/*
+ * Function irda_ioctl (sock, cmd, arg)
+ */
+static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ /*
+ * All IRDA's ioctl are standard ones.
+ */
+ return -ENOIOCTLCMD;
+}
+#endif
+
/*
* Function irda_setsockopt (sock, level, optname, optval, optlen)
*
@@ -2476,6 +2489,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
.getname = irda_getname,
.poll = irda_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = irda_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
@@ -2497,6 +2513,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.getname = irda_getname,
.poll = datagram_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = irda_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
@@ -2518,6 +2537,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
.getname = irda_getname,
.poll = datagram_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = irda_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
@@ -2540,6 +2562,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
.getname = irda_getname,
.poll = datagram_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = sock_no_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 0ae281d9bfc..56389c83557 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -90,8 +90,8 @@ static int nf_conntrack_vmalloc;
static unsigned int nf_conntrack_next_id;
static unsigned int nf_conntrack_expect_next_id;
#ifdef CONFIG_NF_CONNTRACK_EVENTS
-struct notifier_block *nf_conntrack_chain;
-struct notifier_block *nf_conntrack_expect_chain;
+ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
+ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain);
DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
@@ -103,7 +103,7 @@ __nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache)
DEBUGP("ecache: delivering events for %p\n", ecache->ct);
if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct)
&& ecache->events)
- notifier_call_chain(&nf_conntrack_chain, ecache->events,
+ atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events,
ecache->ct);
ecache->events = 0;
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index cd191b0d4ac..e38a4b5a308 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -624,7 +624,7 @@ static struct nf_conntrack_helper ftp[MAX_PORTS][2];
static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")];
/* don't make this __exit, since it's called from __init ! */
-static void fini(void)
+static void nf_conntrack_ftp_fini(void)
{
int i, j;
for (i = 0; i < ports_c; i++) {
@@ -642,7 +642,7 @@ static void fini(void)
kfree(ftp_buffer);
}
-static int __init init(void)
+static int __init nf_conntrack_ftp_init(void)
{
int i, j = -1, ret = 0;
char *tmpname;
@@ -683,7 +683,7 @@ static int __init init(void)
printk("nf_ct_ftp: failed to register helper "
" for pf: %d port: %d\n",
ftp[i][j].tuple.src.l3num, ports[i]);
- fini();
+ nf_conntrack_ftp_fini();
return ret;
}
}
@@ -692,5 +692,5 @@ static int __init init(void)
return 0;
}
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_ftp_init);
+module_exit(nf_conntrack_ftp_fini);
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index cf798e61e37..9cccc325b68 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -615,7 +615,7 @@ static ctl_table nf_ct_net_table[] = {
static struct ctl_table_header *nf_ct_sysctl_header;
#endif
-int __init init(void)
+int __init nf_conntrack_proto_sctp_init(void)
{
int ret;
@@ -652,7 +652,7 @@ int __init init(void)
return ret;
}
-void __exit fini(void)
+void __exit nf_conntrack_proto_sctp_fini(void)
{
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp6);
nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp4);
@@ -662,8 +662,8 @@ void __exit fini(void)
DEBUGP("SCTP conntrack module unloaded\n");
}
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_proto_sctp_init);
+module_exit(nf_conntrack_proto_sctp_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kiran Kumar Immidi");
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 75577e175b3..c72aa3cd22e 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -806,18 +806,18 @@ void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto)
nf_ct_iterate_cleanup(kill_proto, proto);
}
-static int __init init(void)
+static int __init nf_conntrack_standalone_init(void)
{
return init_or_cleanup(1);
}
-static void __exit fini(void)
+static void __exit nf_conntrack_standalone_fini(void)
{
init_or_cleanup(0);
}
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_standalone_init);
+module_exit(nf_conntrack_standalone_fini);
/* Some modules need us, but don't depend directly on any symbol.
They should call this. */
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 54cbbaa712d..3e3f5448bac 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -1081,13 +1081,13 @@ cleanup_netlink_notifier:
return status;
}
-static int __init init(void)
+static int __init nfnetlink_log_init(void)
{
return init_or_cleanup(1);
}
-static void __exit fini(void)
+static void __exit nfnetlink_log_fini(void)
{
init_or_cleanup(0);
}
@@ -1097,5 +1097,5 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_LICENSE("GPL");
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ULOG);
-module_init(init);
-module_exit(fini);
+module_init(nfnetlink_log_init);
+module_exit(nfnetlink_log_fini);
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index b5701662182..d0e62f68139 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1117,13 +1117,13 @@ cleanup_netlink_notifier:
return status;
}
-static int __init init(void)
+static int __init nfnetlink_queue_init(void)
{
return init_or_cleanup(1);
}
-static void __exit fini(void)
+static void __exit nfnetlink_queue_fini(void)
{
init_or_cleanup(0);
}
@@ -1133,5 +1133,5 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_LICENSE("GPL");
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_QUEUE);
-module_init(init);
-module_exit(fini);
+module_init(nfnetlink_queue_init);
+module_exit(nfnetlink_queue_fini);
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 0a29a24d9a7..a657ab5394c 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -21,10 +21,12 @@
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
+#include <linux/mutex.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_arp.h>
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
@@ -32,7 +34,7 @@ MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
struct xt_af {
- struct semaphore mutex;
+ struct mutex mutex;
struct list_head match;
struct list_head target;
struct list_head tables;
@@ -64,11 +66,11 @@ xt_register_target(struct xt_target *target)
{
int ret, af = target->family;
- ret = down_interruptible(&xt[af].mutex);
+ ret = mutex_lock_interruptible(&xt[af].mutex);
if (ret != 0)
return ret;
list_add(&target->list, &xt[af].target);
- up(&xt[af].mutex);
+ mutex_unlock(&xt[af].mutex);
return ret;
}
EXPORT_SYMBOL(xt_register_target);
@@ -78,9 +80,9 @@ xt_unregister_target(struct xt_target *target)
{
int af = target->family;
- down(&xt[af].mutex);
+ mutex_lock(&xt[af].mutex);
LIST_DELETE(&xt[af].target, target);
- up(&xt[af].mutex);
+ mutex_unlock(&xt[af].mutex);
}
EXPORT_SYMBOL(xt_unregister_target);
@@ -89,12 +91,12 @@ xt_register_match(struct xt_match *match)
{
int ret, af = match->family;
- ret = down_interruptible(&xt[af].mutex);
+ ret = mutex_lock_interruptible(&xt[af].mutex);
if (ret != 0)
return ret;
list_add(&match->list, &xt[af].match);
- up(&xt[af].mutex);
+ mutex_unlock(&xt[af].mutex);
return ret;
}
@@ -105,9 +107,9 @@ xt_unregister_match(struct xt_match *match)
{
int af = match->family;
- down(&xt[af].mutex);
+ mutex_lock(&xt[af].mutex);
LIST_DELETE(&xt[af].match, match);
- up(&xt[af].mutex);
+ mutex_unlock(&xt[af].mutex);
}
EXPORT_SYMBOL(xt_unregister_match);
@@ -124,21 +126,21 @@ struct xt_match *xt_find_match(int af, const char *name, u8 revision)
struct xt_match *m;
int err = 0;
- if (down_interruptible(&xt[af].mutex) != 0)
+ if (mutex_lock_interruptible(&xt[af].mutex) != 0)
return ERR_PTR(-EINTR);
list_for_each_entry(m, &xt[af].match, list) {
if (strcmp(m->name, name) == 0) {
if (m->revision == revision) {
if (try_module_get(m->me)) {
- up(&xt[af].mutex);
+ mutex_unlock(&xt[af].mutex);
return m;
}
} else
err = -EPROTOTYPE; /* Found something. */
}
}
- up(&xt[af].mutex);
+ mutex_unlock(&xt[af].mutex);
return ERR_PTR(err);
}
EXPORT_SYMBOL(xt_find_match);
@@ -149,21 +151,21 @@ struct xt_target *xt_find_target(int af, const char *name, u8 revision)
struct xt_target *t;
int err = 0;
- if (down_interruptible(&xt[af].mutex) != 0)
+ if (mutex_lock_interruptible(&xt[af].mutex) != 0)
return ERR_PTR(-EINTR);
list_for_each_entry(t, &xt[af].target, list) {
if (strcmp(t->name, name) == 0) {
if (t->revision == revision) {
if (try_module_get(t->me)) {
- up(&xt[af].mutex);
+ mutex_unlock(&xt[af].mutex);
return t;
}
} else
err = -EPROTOTYPE; /* Found something. */
}
}
- up(&xt[af].mutex);
+ mutex_unlock(&xt[af].mutex);
return ERR_PTR(err);
}
EXPORT_SYMBOL(xt_find_target);
@@ -218,7 +220,7 @@ int xt_find_revision(int af, const char *name, u8 revision, int target,
{
int have_rev, best = -1;
- if (down_interruptible(&xt[af].mutex) != 0) {
+ if (mutex_lock_interruptible(&xt[af].mutex) != 0) {
*err = -EINTR;
return 1;
}
@@ -226,7 +228,7 @@ int xt_find_revision(int af, const char *name, u8 revision, int target,
have_rev = target_revfn(af, name, revision, &best);
else
have_rev = match_revfn(af, name, revision, &best);
- up(&xt[af].mutex);
+ mutex_unlock(&xt[af].mutex);
/* Nothing at all? Return 0 to try loading module. */
if (best == -1) {
@@ -352,20 +354,20 @@ struct xt_table *xt_find_table_lock(int af, const char *name)
{
struct xt_table *t;
- if (down_interruptible(&xt[af].mutex) != 0)
+ if (mutex_lock_interruptible(&xt[af].mutex) != 0)
return ERR_PTR(-EINTR);
list_for_each_entry(t, &xt[af].tables, list)
if (strcmp(t->name, name) == 0 && try_module_get(t->me))
return t;
- up(&xt[af].mutex);
+ mutex_unlock(&xt[af].mutex);
return NULL;
}
EXPORT_SYMBOL_GPL(xt_find_table_lock);
void xt_table_unlock(struct xt_table *table)
{
- up(&xt[table->af].mutex);
+ mutex_unlock(&xt[table->af].mutex);
}
EXPORT_SYMBOL_GPL(xt_table_unlock);
@@ -405,7 +407,7 @@ int xt_register_table(struct xt_table *table,
int ret;
struct xt_table_info *private;
- ret = down_interruptible(&xt[table->af].mutex);
+ ret = mutex_lock_interruptible(&xt[table->af].mutex);
if (ret != 0)
return ret;
@@ -431,7 +433,7 @@ int xt_register_table(struct xt_table *table,
ret = 0;
unlock:
- up(&xt[table->af].mutex);
+ mutex_unlock(&xt[table->af].mutex);
return ret;
}
EXPORT_SYMBOL_GPL(xt_register_table);
@@ -440,10 +442,10 @@ void *xt_unregister_table(struct xt_table *table)
{
struct xt_table_info *private;
- down(&xt[table->af].mutex);
+ mutex_lock(&xt[table->af].mutex);
private = table->private;
LIST_DELETE(&xt[table->af].tables, table);
- up(&xt[table->af].mutex);
+ mutex_unlock(&xt[table->af].mutex);
return private;
}
@@ -507,7 +509,7 @@ static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos)
if (!list)
return NULL;
- if (down_interruptible(&xt[af].mutex) != 0)
+ if (mutex_lock_interruptible(&xt[af].mutex) != 0)
return NULL;
return xt_get_idx(list, seq, *pos);
@@ -536,7 +538,7 @@ static void xt_tgt_seq_stop(struct seq_file *seq, void *v)
struct proc_dir_entry *pde = seq->private;
u_int16_t af = (unsigned long)pde->data & 0xffff;
- up(&xt[af].mutex);
+ mutex_unlock(&xt[af].mutex);
}
static int xt_name_seq_show(struct seq_file *seq, void *v)
@@ -668,7 +670,7 @@ static int __init xt_init(void)
return -ENOMEM;
for (i = 0; i < NPROTO; i++) {
- init_MUTEX(&xt[i].mutex);
+ mutex_init(&xt[i].mutex);
INIT_LIST_HEAD(&xt[i].target);
INIT_LIST_HEAD(&xt[i].match);
INIT_LIST_HEAD(&xt[i].tables);
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 3cd2ac90a25..e54e5773001 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -62,7 +62,7 @@ static struct xt_target classify6_reg = {
};
-static int __init init(void)
+static int __init xt_classify_init(void)
{
int ret;
@@ -77,11 +77,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_classify_fini(void)
{
xt_unregister_target(&classify_reg);
xt_unregister_target(&classify6_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_classify_init);
+module_exit(xt_classify_fini);
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 35448b8e688..60c375d36f0 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -115,7 +115,7 @@ static struct xt_target connmark6_reg = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_connmark_init(void)
{
int ret;
@@ -132,11 +132,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_connmark_fini(void)
{
xt_unregister_target(&connmark_reg);
xt_unregister_target(&connmark6_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_connmark_init);
+module_exit(xt_connmark_fini);
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index 73bdd5c80e1..ee9c34edc76 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -145,7 +145,7 @@ static struct xt_target ip6t_mark_reg_v0 = {
.revision = 0,
};
-static int __init init(void)
+static int __init xt_mark_init(void)
{
int err;
@@ -166,12 +166,12 @@ static int __init init(void)
return err;
}
-static void __exit fini(void)
+static void __exit xt_mark_fini(void)
{
xt_unregister_target(&ipt_mark_reg_v0);
xt_unregister_target(&ipt_mark_reg_v1);
xt_unregister_target(&ip6t_mark_reg_v0);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_mark_init);
+module_exit(xt_mark_fini);
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 2873e1c60f6..86ccceb61fd 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -61,7 +61,7 @@ static struct xt_target arpt_NFQ_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_nfqueue_init(void)
{
int ret;
ret = xt_register_target(&ipt_NFQ_reg);
@@ -83,12 +83,12 @@ out_ip:
return ret;
}
-static void __exit fini(void)
+static void __exit xt_nfqueue_fini(void)
{
xt_unregister_target(&arpt_NFQ_reg);
xt_unregister_target(&ip6t_NFQ_reg);
xt_unregister_target(&ipt_NFQ_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_nfqueue_init);
+module_exit(xt_nfqueue_fini);
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index cf2ebd76fd6..98f4b5363ce 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -52,7 +52,7 @@ static struct xt_target notrack6_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_notrack_init(void)
{
int ret;
@@ -67,11 +67,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_notrack_fini(void)
{
xt_unregister_target(&notrack6_reg);
xt_unregister_target(&notrack_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_notrack_init);
+module_exit(xt_notrack_fini);
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c
index 2637724b498..197609cb06d 100644
--- a/net/netfilter/xt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -45,7 +45,7 @@ static struct xt_match comment6_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_comment_init(void)
{
int ret;
@@ -60,11 +60,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_comment_fini(void)
{
xt_unregister_match(&comment_match);
xt_unregister_match(&comment6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_comment_init);
+module_exit(xt_comment_fini);
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 4985f5ec58c..1396fe2d07c 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -160,7 +160,7 @@ static struct xt_match connbytes6_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_connbytes_init(void)
{
int ret;
ret = xt_register_match(&connbytes_match);
@@ -173,11 +173,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_connbytes_fini(void)
{
xt_unregister_match(&connbytes_match);
xt_unregister_match(&connbytes6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_connbytes_init);
+module_exit(xt_connbytes_fini);
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index 7b16f1ee16b..dc26a27cbca 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -102,7 +102,7 @@ static struct xt_match connmark6_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_connmark_init(void)
{
int ret;
@@ -118,11 +118,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_connmark_fini(void)
{
xt_unregister_match(&connmark6_match);
xt_unregister_match(&connmark_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_connmark_init);
+module_exit(xt_connmark_fini);
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 65a84809fd3..145489a4c3f 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -239,7 +239,7 @@ static struct xt_match conntrack_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_conntrack_init(void)
{
int ret;
need_conntrack();
@@ -248,10 +248,10 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_conntrack_fini(void)
{
xt_unregister_match(&conntrack_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_conntrack_init);
+module_exit(xt_conntrack_fini);
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 2f331decd15..dfb10b648e5 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -164,7 +164,7 @@ static struct xt_match dccp6_match =
};
-static int __init init(void)
+static int __init xt_dccp_init(void)
{
int ret;
@@ -191,12 +191,12 @@ out_kfree:
return ret;
}
-static void __exit fini(void)
+static void __exit xt_dccp_fini(void)
{
xt_unregister_match(&dccp6_match);
xt_unregister_match(&dccp_match);
kfree(dccp_optbuf);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_dccp_init);
+module_exit(xt_dccp_fini);
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index 101f0005e98..799c2a43e3b 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -182,7 +182,7 @@ static struct xt_match helper6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_helper_init(void)
{
int ret;
need_conntrack();
@@ -198,12 +198,12 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_helper_fini(void)
{
xt_unregister_match(&helper_match);
xt_unregister_match(&helper6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_helper_init);
+module_exit(xt_helper_fini);
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
index 38560caef75..109132c9a14 100644
--- a/net/netfilter/xt_length.c
+++ b/net/netfilter/xt_length.c
@@ -68,7 +68,7 @@ static struct xt_match length6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_length_init(void)
{
int ret;
ret = xt_register_match(&length_match);
@@ -81,11 +81,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_length_fini(void)
{
xt_unregister_match(&length_match);
xt_unregister_match(&length6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_length_init);
+module_exit(xt_length_fini);
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index e91c1a444e7..ce7fdb7e4e0 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -153,7 +153,7 @@ static struct xt_match limit6_reg = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_limit_init(void)
{
int ret;
@@ -168,11 +168,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_limit_fini(void)
{
xt_unregister_match(&ipt_limit_reg);
xt_unregister_match(&limit6_reg);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_limit_init);
+module_exit(xt_limit_fini);
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index f4defa28a6e..356290ffe38 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -62,7 +62,7 @@ static struct xt_match mac6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_mac_init(void)
{
int ret;
ret = xt_register_match(&mac_match);
@@ -76,11 +76,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_mac_fini(void)
{
xt_unregister_match(&mac_match);
xt_unregister_match(&mac6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_mac_init);
+module_exit(xt_mac_fini);
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index ce0badfeef9..8b385a34886 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -69,7 +69,7 @@ static struct xt_match mark6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_mark_init(void)
{
int ret;
ret = xt_register_match(&mark_match);
@@ -83,11 +83,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_mark_fini(void)
{
xt_unregister_match(&mark_match);
xt_unregister_match(&mark6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_mark_init);
+module_exit(xt_mark_fini);
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 089f4f7e863..5fe4c9df17f 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -134,7 +134,7 @@ static struct xt_match physdev6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_physdev_init(void)
{
int ret;
@@ -149,11 +149,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_physdev_fini(void)
{
xt_unregister_match(&physdev_match);
xt_unregister_match(&physdev6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_physdev_init);
+module_exit(xt_physdev_fini);
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index 8b8bca988ac..3ac703b5cb8 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -49,7 +49,7 @@ static struct xt_match pkttype6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_pkttype_init(void)
{
int ret;
ret = xt_register_match(&pkttype_match);
@@ -63,11 +63,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_pkttype_fini(void)
{
xt_unregister_match(&pkttype_match);
xt_unregister_match(&pkttype6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_pkttype_init);
+module_exit(xt_pkttype_fini);
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
index 5e31a4a835b..a80b7d132b6 100644
--- a/net/netfilter/xt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -49,15 +49,15 @@ static struct xt_match realm_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_realm_init(void)
{
return xt_register_match(&realm_match);
}
-static void __exit fini(void)
+static void __exit xt_realm_fini(void)
{
xt_unregister_match(&realm_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_realm_init);
+module_exit(xt_realm_fini);
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index c6eb24a2fe1..34bd87259a0 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -200,7 +200,7 @@ static struct xt_match sctp6_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_sctp_init(void)
{
int ret;
ret = xt_register_match(&sctp_match);
@@ -214,11 +214,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_sctp_fini(void)
{
xt_unregister_match(&sctp6_match);
xt_unregister_match(&sctp_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_sctp_init);
+module_exit(xt_sctp_fini);
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index e6c0be9d94d..f9e304dc450 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -89,7 +89,7 @@ static struct xt_match state6_match = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_state_init(void)
{
int ret;
@@ -106,11 +106,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_state_fini(void)
{
xt_unregister_match(&state_match);
xt_unregister_match(&state6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_state_init);
+module_exit(xt_state_fini);
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 703d80fccac..79d9ea6964b 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -91,7 +91,7 @@ static struct xt_match string6_match = {
.me = THIS_MODULE
};
-static int __init init(void)
+static int __init xt_string_init(void)
{
int ret;
@@ -105,11 +105,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_string_fini(void)
{
xt_unregister_match(&string_match);
xt_unregister_match(&string6_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_string_init);
+module_exit(xt_string_fini);
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 70a8858ae3f..cf7d335cadc 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -112,7 +112,7 @@ static struct xt_match tcpmss6_match = {
};
-static int __init init(void)
+static int __init xt_tcpmss_init(void)
{
int ret;
ret = xt_register_match(&tcpmss_match);
@@ -126,11 +126,11 @@ static int __init init(void)
return ret;
}
-static void __exit fini(void)
+static void __exit xt_tcpmss_fini(void)
{
xt_unregister_match(&tcpmss6_match);
xt_unregister_match(&tcpmss_match);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_tcpmss_init);
+module_exit(xt_tcpmss_fini);
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index 14a990eb666..1b61dac9c87 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -238,7 +238,7 @@ static struct xt_match udp6_matchstruct = {
.me = THIS_MODULE,
};
-static int __init init(void)
+static int __init xt_tcpudp_init(void)
{
int ret;
ret = xt_register_match(&tcp_matchstruct);
@@ -268,7 +268,7 @@ out_unreg_tcp:
return ret;
}
-static void __exit fini(void)
+static void __exit xt_tcpudp_fini(void)
{
xt_unregister_match(&udp6_matchstruct);
xt_unregister_match(&udp_matchstruct);
@@ -276,5 +276,5 @@ static void __exit fini(void)
xt_unregister_match(&tcp_matchstruct);
}
-module_init(init);
-module_exit(fini);
+module_init(xt_tcpudp_init);
+module_exit(xt_tcpudp_fini);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index d00a9034cb5..2a233ffcf61 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -123,7 +123,7 @@ static void netlink_destroy_callback(struct netlink_callback *cb);
static DEFINE_RWLOCK(nl_table_lock);
static atomic_t nl_table_users = ATOMIC_INIT(0);
-static struct notifier_block *netlink_chain;
+static ATOMIC_NOTIFIER_HEAD(netlink_chain);
static u32 netlink_group_mask(u32 group)
{
@@ -469,7 +469,8 @@ static int netlink_release(struct socket *sock)
.protocol = sk->sk_protocol,
.pid = nlk->pid,
};
- notifier_call_chain(&netlink_chain, NETLINK_URELEASE, &n);
+ atomic_notifier_call_chain(&netlink_chain,
+ NETLINK_URELEASE, &n);
}
if (nlk->module)
@@ -1695,12 +1696,12 @@ static struct file_operations netlink_seq_fops = {
int netlink_register_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&netlink_chain, nb);
+ return atomic_notifier_chain_register(&netlink_chain, nb);
}
int netlink_unregister_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&netlink_chain, nb);
+ return atomic_notifier_chain_unregister(&netlink_chain, nb);
}
static const struct proto_ops netlink_ops = {
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 43e72419c86..f329b72578f 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -13,26 +13,27 @@
#include <linux/socket.h>
#include <linux/string.h>
#include <linux/skbuff.h>
+#include <linux/mutex.h>
#include <net/sock.h>
#include <net/genetlink.h>
struct sock *genl_sock = NULL;
-static DECLARE_MUTEX(genl_sem); /* serialization of message processing */
+static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */
static void genl_lock(void)
{
- down(&genl_sem);
+ mutex_lock(&genl_mutex);
}
static int genl_trylock(void)
{
- return down_trylock(&genl_sem);
+ return !mutex_trylock(&genl_mutex);
}
static void genl_unlock(void)
{
- up(&genl_sem);
+ mutex_unlock(&genl_mutex);
if (genl_sock && genl_sock->sk_receive_queue.qlen)
genl_sock->sk_data_ready(genl_sock, 0);
diff --git a/net/nonet.c b/net/nonet.c
index 1230f0ae832..92e76640c7c 100644
--- a/net/nonet.c
+++ b/net/nonet.c
@@ -19,7 +19,7 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
return -ENXIO;
}
-struct file_operations bad_sock_fops = {
+const struct file_operations bad_sock_fops = {
.owner = THIS_MODULE,
.open = sock_no_open,
};
diff --git a/net/rxrpc/main.c b/net/rxrpc/main.c
index 36fdcbcd80d..48cbd065bb4 100644
--- a/net/rxrpc/main.c
+++ b/net/rxrpc/main.c
@@ -79,8 +79,8 @@ static int __init rxrpc_initialise(void)
error_sysctl:
#ifdef CONFIG_SYSCTL
rxrpc_sysctl_cleanup();
-#endif
error_proc:
+#endif
#ifdef CONFIG_PROC_FS
rxrpc_proc_cleanup();
#endif
diff --git a/net/sctp/input.c b/net/sctp/input.c
index cb78b50868e..d117ebc75cf 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -127,7 +127,6 @@ int sctp_rcv(struct sk_buff *skb)
union sctp_addr dest;
int family;
struct sctp_af *af;
- int ret = 0;
if (skb->pkt_type!=PACKET_HOST)
goto discard_it;
@@ -227,16 +226,13 @@ int sctp_rcv(struct sk_buff *skb)
goto discard_release;
nf_reset(skb);
- ret = sk_filter(sk, skb, 1);
- if (ret)
+ if (sk_filter(sk, skb, 1))
goto discard_release;
/* Create an SCTP packet structure. */
chunk = sctp_chunkify(skb, asoc, sk);
- if (!chunk) {
- ret = -ENOMEM;
+ if (!chunk)
goto discard_release;
- }
SCTP_INPUT_CB(skb)->chunk = chunk;
/* Remember what endpoint is to handle this packet. */
@@ -277,11 +273,11 @@ int sctp_rcv(struct sk_buff *skb)
sctp_bh_unlock_sock(sk);
sock_put(sk);
- return ret;
+ return 0;
discard_it:
kfree_skb(skb);
- return ret;
+ return 0;
discard_release:
/* Release any structures we may be holding. */
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 0ea947eb681..b6e4b89539b 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4894,6 +4894,8 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
/* Is there any exceptional events? */
if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
mask |= POLLERR;
+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ mask |= POLLRDHUP;
if (sk->sk_shutdown == SHUTDOWN_MASK)
mask |= POLLHUP;
diff --git a/net/socket.c b/net/socket.c
index 5211ba27037..fcd77eac0cc 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -539,7 +539,7 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
return -ENXIO;
}
-struct file_operations bad_sock_fops = {
+const struct file_operations bad_sock_fops = {
.owner = THIS_MODULE,
.open = sock_no_open,
};
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 8d6f1a176b1..55163af3dca 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -64,14 +64,26 @@ rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
struct rpc_authops *ops;
u32 flavor = pseudoflavor_to_flavor(pseudoflavor);
- if (flavor >= RPC_AUTH_MAXFLAVOR || !(ops = auth_flavors[flavor]))
- return ERR_PTR(-EINVAL);
+ auth = ERR_PTR(-EINVAL);
+ if (flavor >= RPC_AUTH_MAXFLAVOR)
+ goto out;
+
+ /* FIXME - auth_flavors[] really needs an rw lock,
+ * and module refcounting. */
+#ifdef CONFIG_KMOD
+ if ((ops = auth_flavors[flavor]) == NULL)
+ request_module("rpc-auth-%u", flavor);
+#endif
+ if ((ops = auth_flavors[flavor]) == NULL)
+ goto out;
auth = ops->create(clnt, pseudoflavor);
if (IS_ERR(auth))
return auth;
if (clnt->cl_auth)
rpcauth_destroy(clnt->cl_auth);
clnt->cl_auth = auth;
+
+out:
return auth;
}
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index bb46efd92e5..900ef31f5a0 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -721,6 +721,8 @@ gss_destroy(struct rpc_auth *auth)
gss_auth = container_of(auth, struct gss_auth, rpc_auth);
rpc_unlink(gss_auth->path);
+ dput(gss_auth->dentry);
+ gss_auth->dentry = NULL;
gss_mech_put(gss_auth->mech);
rpcauth_free_credcache(auth);
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index d0dfdfd5e79..f43311221a7 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -70,15 +70,19 @@
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
+spinlock_t krb5_seq_lock = SPIN_LOCK_UNLOCKED;
+
u32
gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
struct xdr_netobj *token)
{
struct krb5_ctx *ctx = gss_ctx->internal_ctx_id;
s32 checksum_type;
- struct xdr_netobj md5cksum = {.len = 0, .data = NULL};
+ char cksumdata[16];
+ struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata};
unsigned char *ptr, *krb5_hdr, *msg_start;
s32 now;
+ u32 seq_send;
dprintk("RPC: gss_krb5_seal\n");
@@ -133,16 +137,15 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
BUG();
}
- kfree(md5cksum.data);
+ spin_lock(&krb5_seq_lock);
+ seq_send = ctx->seq_send++;
+ spin_unlock(&krb5_seq_lock);
if ((krb5_make_seq_num(ctx->seq, ctx->initiate ? 0 : 0xff,
- ctx->seq_send, krb5_hdr + 16, krb5_hdr + 8)))
+ seq_send, krb5_hdr + 16, krb5_hdr + 8)))
goto out_err;
- ctx->seq_send++;
-
return ((ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE);
out_err:
- kfree(md5cksum.data);
return GSS_S_FAILURE;
}
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index db055fd7d77..0828cf64100 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -79,7 +79,8 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
int signalg;
int sealalg;
s32 checksum_type;
- struct xdr_netobj md5cksum = {.len = 0, .data = NULL};
+ char cksumdata[16];
+ struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata};
s32 now;
int direction;
s32 seqnum;
@@ -176,6 +177,5 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
ret = GSS_S_COMPLETE;
out:
- kfree(md5cksum.data);
return ret;
}
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index af777cf9f25..89d1f3e1412 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -121,12 +121,14 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
{
struct krb5_ctx *kctx = ctx->internal_ctx_id;
s32 checksum_type;
- struct xdr_netobj md5cksum = {.len = 0, .data = NULL};
+ char cksumdata[16];
+ struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata};
int blocksize = 0, plainlen;
unsigned char *ptr, *krb5_hdr, *msg_start;
s32 now;
int headlen;
struct page **tmp_pages;
+ u32 seq_send;
dprintk("RPC: gss_wrap_kerberos\n");
@@ -205,23 +207,22 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
BUG();
}
- kfree(md5cksum.data);
+ spin_lock(&krb5_seq_lock);
+ seq_send = kctx->seq_send++;
+ spin_unlock(&krb5_seq_lock);
/* XXX would probably be more efficient to compute checksum
* and encrypt at the same time: */
if ((krb5_make_seq_num(kctx->seq, kctx->initiate ? 0 : 0xff,
- kctx->seq_send, krb5_hdr + 16, krb5_hdr + 8)))
+ seq_send, krb5_hdr + 16, krb5_hdr + 8)))
goto out_err;
if (gss_encrypt_xdr_buf(kctx->enc, buf, offset + headlen - blocksize,
pages))
goto out_err;
- kctx->seq_send++;
-
return ((kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE);
out_err:
- if (md5cksum.data) kfree(md5cksum.data);
return GSS_S_FAILURE;
}
@@ -232,7 +233,8 @@ gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
int signalg;
int sealalg;
s32 checksum_type;
- struct xdr_netobj md5cksum = {.len = 0, .data = NULL};
+ char cksumdata[16];
+ struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata};
s32 now;
int direction;
s32 seqnum;
@@ -358,6 +360,5 @@ gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
ret = GSS_S_COMPLETE;
out:
- if (md5cksum.data) kfree(md5cksum.data);
return ret;
}
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index 58400807d4d..5bf11ccba7c 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -102,6 +102,12 @@ get_key(const void *p, const void *end, struct crypto_tfm **res, int *resalg)
alg_mode = CRYPTO_TFM_MODE_CBC;
setkey = 1;
break;
+ case NID_cast5_cbc:
+ /* XXXX here in name only, not used */
+ alg_name = "cast5";
+ alg_mode = CRYPTO_TFM_MODE_CBC;
+ setkey = 0; /* XXX will need to set to 1 */
+ break;
case NID_md5:
if (key.len == 0) {
dprintk("RPC: SPKM3 get_key: NID_md5 zero Key length\n");
diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
index 86fbf7c3e39..18c7862bc23 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
@@ -57,7 +57,8 @@ spkm3_make_token(struct spkm3_ctx *ctx,
{
s32 checksum_type;
char tokhdrbuf[25];
- struct xdr_netobj md5cksum = {.len = 0, .data = NULL};
+ char cksumdata[16];
+ struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata};
struct xdr_netobj mic_hdr = {.len = 0, .data = tokhdrbuf};
int tokenlen = 0;
unsigned char *ptr;
@@ -115,13 +116,11 @@ spkm3_make_token(struct spkm3_ctx *ctx,
dprintk("RPC: gss_spkm3_seal: SPKM_WRAP_TOK not supported\n");
goto out_err;
}
- kfree(md5cksum.data);
/* XXX need to implement sequence numbers, and ctx->expired */
return GSS_S_COMPLETE;
out_err:
- kfree(md5cksum.data);
token->data = NULL;
token->len = 0;
return GSS_S_FAILURE;
diff --git a/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
index 96851b0ba1b..8537f581ef9 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_unseal.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
@@ -56,7 +56,8 @@ spkm3_read_token(struct spkm3_ctx *ctx,
{
s32 code;
struct xdr_netobj wire_cksum = {.len =0, .data = NULL};
- struct xdr_netobj md5cksum = {.len = 0, .data = NULL};
+ char cksumdata[16];
+ struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata};
unsigned char *ptr = (unsigned char *)read_token->data;
unsigned char *cksum;
int bodysize, md5elen;
@@ -120,7 +121,6 @@ spkm3_read_token(struct spkm3_ctx *ctx,
/* XXX: need to add expiration and sequencing */
ret = GSS_S_COMPLETE;
out:
- kfree(md5cksum.data);
kfree(wire_cksum.data);
return ret;
}
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 23632d84d8d..4d7eb9e704d 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -78,7 +78,8 @@ struct rsi {
static struct cache_head *rsi_table[RSI_HASHMAX];
static struct cache_detail rsi_cache;
-static struct rsi *rsi_lookup(struct rsi *item, int set);
+static struct rsi *rsi_update(struct rsi *new, struct rsi *old);
+static struct rsi *rsi_lookup(struct rsi *item);
static void rsi_free(struct rsi *rsii)
{
@@ -88,13 +89,11 @@ static void rsi_free(struct rsi *rsii)
kfree(rsii->out_token.data);
}
-static void rsi_put(struct cache_head *item, struct cache_detail *cd)
+static void rsi_put(struct kref *ref)
{
- struct rsi *rsii = container_of(item, struct rsi, h);
- if (cache_put(item, cd)) {
- rsi_free(rsii);
- kfree(rsii);
- }
+ struct rsi *rsii = container_of(ref, struct rsi, h.ref);
+ rsi_free(rsii);
+ kfree(rsii);
}
static inline int rsi_hash(struct rsi *item)
@@ -103,8 +102,10 @@ static inline int rsi_hash(struct rsi *item)
^ hash_mem(item->in_token.data, item->in_token.len, RSI_HASHBITS);
}
-static inline int rsi_match(struct rsi *item, struct rsi *tmp)
+static int rsi_match(struct cache_head *a, struct cache_head *b)
{
+ struct rsi *item = container_of(a, struct rsi, h);
+ struct rsi *tmp = container_of(b, struct rsi, h);
return netobj_equal(&item->in_handle, &tmp->in_handle)
&& netobj_equal(&item->in_token, &tmp->in_token);
}
@@ -125,8 +126,11 @@ static inline int dup_netobj(struct xdr_netobj *dst, struct xdr_netobj *src)
return dup_to_netobj(dst, src->data, src->len);
}
-static inline void rsi_init(struct rsi *new, struct rsi *item)
+static void rsi_init(struct cache_head *cnew, struct cache_head *citem)
{
+ struct rsi *new = container_of(cnew, struct rsi, h);
+ struct rsi *item = container_of(citem, struct rsi, h);
+
new->out_handle.data = NULL;
new->out_handle.len = 0;
new->out_token.data = NULL;
@@ -141,8 +145,11 @@ static inline void rsi_init(struct rsi *new, struct rsi *item)
item->in_token.data = NULL;
}
-static inline void rsi_update(struct rsi *new, struct rsi *item)
+static void update_rsi(struct cache_head *cnew, struct cache_head *citem)
{
+ struct rsi *new = container_of(cnew, struct rsi, h);
+ struct rsi *item = container_of(citem, struct rsi, h);
+
BUG_ON(new->out_handle.data || new->out_token.data);
new->out_handle.len = item->out_handle.len;
item->out_handle.len = 0;
@@ -157,6 +164,15 @@ static inline void rsi_update(struct rsi *new, struct rsi *item)
new->minor_status = item->minor_status;
}
+static struct cache_head *rsi_alloc(void)
+{
+ struct rsi *rsii = kmalloc(sizeof(*rsii), GFP_KERNEL);
+ if (rsii)
+ return &rsii->h;
+ else
+ return NULL;
+}
+
static void rsi_request(struct cache_detail *cd,
struct cache_head *h,
char **bpp, int *blen)
@@ -198,6 +214,10 @@ static int rsi_parse(struct cache_detail *cd,
if (dup_to_netobj(&rsii.in_token, buf, len))
goto out;
+ rsip = rsi_lookup(&rsii);
+ if (!rsip)
+ goto out;
+
rsii.h.flags = 0;
/* expiry */
expiry = get_expiry(&mesg);
@@ -240,12 +260,14 @@ static int rsi_parse(struct cache_detail *cd,
goto out;
}
rsii.h.expiry_time = expiry;
- rsip = rsi_lookup(&rsii, 1);
+ rsip = rsi_update(&rsii, rsip);
status = 0;
out:
rsi_free(&rsii);
if (rsip)
- rsi_put(&rsip->h, &rsi_cache);
+ cache_put(&rsip->h, &rsi_cache);
+ else
+ status = -ENOMEM;
return status;
}
@@ -257,9 +279,37 @@ static struct cache_detail rsi_cache = {
.cache_put = rsi_put,
.cache_request = rsi_request,
.cache_parse = rsi_parse,
+ .match = rsi_match,
+ .init = rsi_init,
+ .update = update_rsi,
+ .alloc = rsi_alloc,
};
-static DefineSimpleCacheLookup(rsi, 0)
+static struct rsi *rsi_lookup(struct rsi *item)
+{
+ struct cache_head *ch;
+ int hash = rsi_hash(item);
+
+ ch = sunrpc_cache_lookup(&rsi_cache, &item->h, hash);
+ if (ch)
+ return container_of(ch, struct rsi, h);
+ else
+ return NULL;
+}
+
+static struct rsi *rsi_update(struct rsi *new, struct rsi *old)
+{
+ struct cache_head *ch;
+ int hash = rsi_hash(new);
+
+ ch = sunrpc_cache_update(&rsi_cache, &new->h,
+ &old->h, hash);
+ if (ch)
+ return container_of(ch, struct rsi, h);
+ else
+ return NULL;
+}
+
/*
* The rpcsec_context cache is used to store a context that is
@@ -293,7 +343,8 @@ struct rsc {
static struct cache_head *rsc_table[RSC_HASHMAX];
static struct cache_detail rsc_cache;
-static struct rsc *rsc_lookup(struct rsc *item, int set);
+static struct rsc *rsc_update(struct rsc *new, struct rsc *old);
+static struct rsc *rsc_lookup(struct rsc *item);
static void rsc_free(struct rsc *rsci)
{
@@ -304,14 +355,12 @@ static void rsc_free(struct rsc *rsci)
put_group_info(rsci->cred.cr_group_info);
}
-static void rsc_put(struct cache_head *item, struct cache_detail *cd)
+static void rsc_put(struct kref *ref)
{
- struct rsc *rsci = container_of(item, struct rsc, h);
+ struct rsc *rsci = container_of(ref, struct rsc, h.ref);
- if (cache_put(item, cd)) {
- rsc_free(rsci);
- kfree(rsci);
- }
+ rsc_free(rsci);
+ kfree(rsci);
}
static inline int
@@ -320,15 +369,21 @@ rsc_hash(struct rsc *rsci)
return hash_mem(rsci->handle.data, rsci->handle.len, RSC_HASHBITS);
}
-static inline int
-rsc_match(struct rsc *new, struct rsc *tmp)
+static int
+rsc_match(struct cache_head *a, struct cache_head *b)
{
+ struct rsc *new = container_of(a, struct rsc, h);
+ struct rsc *tmp = container_of(b, struct rsc, h);
+
return netobj_equal(&new->handle, &tmp->handle);
}
-static inline void
-rsc_init(struct rsc *new, struct rsc *tmp)
+static void
+rsc_init(struct cache_head *cnew, struct cache_head *ctmp)
{
+ struct rsc *new = container_of(cnew, struct rsc, h);
+ struct rsc *tmp = container_of(ctmp, struct rsc, h);
+
new->handle.len = tmp->handle.len;
tmp->handle.len = 0;
new->handle.data = tmp->handle.data;
@@ -337,9 +392,12 @@ rsc_init(struct rsc *new, struct rsc *tmp)
new->cred.cr_group_info = NULL;
}
-static inline void
-rsc_update(struct rsc *new, struct rsc *tmp)
+static void
+update_rsc(struct cache_head *cnew, struct cache_head *ctmp)
{
+ struct rsc *new = container_of(cnew, struct rsc, h);
+ struct rsc *tmp = container_of(ctmp, struct rsc, h);
+
new->mechctx = tmp->mechctx;
tmp->mechctx = NULL;
memset(&new->seqdata, 0, sizeof(new->seqdata));
@@ -348,6 +406,16 @@ rsc_update(struct rsc *new, struct rsc *tmp)
tmp->cred.cr_group_info = NULL;
}
+static struct cache_head *
+rsc_alloc(void)
+{
+ struct rsc *rsci = kmalloc(sizeof(*rsci), GFP_KERNEL);
+ if (rsci)
+ return &rsci->h;
+ else
+ return NULL;
+}
+
static int rsc_parse(struct cache_detail *cd,
char *mesg, int mlen)
{
@@ -373,6 +441,10 @@ static int rsc_parse(struct cache_detail *cd,
if (expiry == 0)
goto out;
+ rscp = rsc_lookup(&rsci);
+ if (!rscp)
+ goto out;
+
/* uid, or NEGATIVE */
rv = get_int(&mesg, &rsci.cred.cr_uid);
if (rv == -EINVAL)
@@ -428,12 +500,14 @@ static int rsc_parse(struct cache_detail *cd,
gss_mech_put(gm);
}
rsci.h.expiry_time = expiry;
- rscp = rsc_lookup(&rsci, 1);
+ rscp = rsc_update(&rsci, rscp);
status = 0;
out:
rsc_free(&rsci);
if (rscp)
- rsc_put(&rscp->h, &rsc_cache);
+ cache_put(&rscp->h, &rsc_cache);
+ else
+ status = -ENOMEM;
return status;
}
@@ -444,9 +518,37 @@ static struct cache_detail rsc_cache = {
.name = "auth.rpcsec.context",
.cache_put = rsc_put,
.cache_parse = rsc_parse,
+ .match = rsc_match,
+ .init = rsc_init,
+ .update = update_rsc,
+ .alloc = rsc_alloc,
};
-static DefineSimpleCacheLookup(rsc, 0);
+static struct rsc *rsc_lookup(struct rsc *item)
+{
+ struct cache_head *ch;
+ int hash = rsc_hash(item);
+
+ ch = sunrpc_cache_lookup(&rsc_cache, &item->h, hash);
+ if (ch)
+ return container_of(ch, struct rsc, h);
+ else
+ return NULL;
+}
+
+static struct rsc *rsc_update(struct rsc *new, struct rsc *old)
+{
+ struct cache_head *ch;
+ int hash = rsc_hash(new);
+
+ ch = sunrpc_cache_update(&rsc_cache, &new->h,
+ &old->h, hash);
+ if (ch)
+ return container_of(ch, struct rsc, h);
+ else
+ return NULL;
+}
+
static struct rsc *
gss_svc_searchbyctx(struct xdr_netobj *handle)
@@ -457,7 +559,7 @@ gss_svc_searchbyctx(struct xdr_netobj *handle)
memset(&rsci, 0, sizeof(rsci));
if (dup_to_netobj(&rsci.handle, handle->data, handle->len))
return NULL;
- found = rsc_lookup(&rsci, 0);
+ found = rsc_lookup(&rsci);
rsc_free(&rsci);
if (!found)
return NULL;
@@ -645,6 +747,8 @@ find_gss_auth_domain(struct gss_ctx *ctx, u32 svc)
return auth_domain_find(name);
}
+static struct auth_ops svcauthops_gss;
+
int
svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
{
@@ -655,20 +759,18 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
new = kmalloc(sizeof(*new), GFP_KERNEL);
if (!new)
goto out;
- cache_init(&new->h.h);
+ kref_init(&new->h.ref);
new->h.name = kmalloc(strlen(name) + 1, GFP_KERNEL);
if (!new->h.name)
goto out_free_dom;
strcpy(new->h.name, name);
- new->h.flavour = RPC_AUTH_GSS;
+ new->h.flavour = &svcauthops_gss;
new->pseudoflavor = pseudoflavor;
- new->h.h.expiry_time = NEVER;
- test = auth_domain_lookup(&new->h, 1);
- if (test == &new->h) {
- BUG_ON(atomic_dec_and_test(&new->h.h.refcnt));
- } else { /* XXX Duplicate registration? */
+ test = auth_domain_lookup(name, &new->h);
+ if (test != &new->h) { /* XXX Duplicate registration? */
auth_domain_put(&new->h);
+ /* dangling ref-count... */
goto out;
}
return 0;
@@ -895,7 +997,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
goto drop;
}
- rsip = rsi_lookup(&rsikey, 0);
+ rsip = rsi_lookup(&rsikey);
rsi_free(&rsikey);
if (!rsip) {
goto drop;
@@ -970,7 +1072,7 @@ drop:
ret = SVC_DROP;
out:
if (rsci)
- rsc_put(&rsci->h, &rsc_cache);
+ cache_put(&rsci->h, &rsc_cache);
return ret;
}
@@ -1062,7 +1164,7 @@ out_err:
put_group_info(rqstp->rq_cred.cr_group_info);
rqstp->rq_cred.cr_group_info = NULL;
if (gsd->rsci)
- rsc_put(&gsd->rsci->h, &rsc_cache);
+ cache_put(&gsd->rsci->h, &rsc_cache);
gsd->rsci = NULL;
return stat;
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 0acccfeeb28..3ac4193a78e 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -37,16 +37,138 @@
static void cache_defer_req(struct cache_req *req, struct cache_head *item);
static void cache_revisit_request(struct cache_head *item);
-void cache_init(struct cache_head *h)
+static void cache_init(struct cache_head *h)
{
time_t now = get_seconds();
h->next = NULL;
h->flags = 0;
- atomic_set(&h->refcnt, 1);
+ kref_init(&h->ref);
h->expiry_time = now + CACHE_NEW_EXPIRY;
h->last_refresh = now;
}
+struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
+ struct cache_head *key, int hash)
+{
+ struct cache_head **head, **hp;
+ struct cache_head *new = NULL;
+
+ head = &detail->hash_table[hash];
+
+ read_lock(&detail->hash_lock);
+
+ for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
+ struct cache_head *tmp = *hp;
+ if (detail->match(tmp, key)) {
+ cache_get(tmp);
+ read_unlock(&detail->hash_lock);
+ return tmp;
+ }
+ }
+ read_unlock(&detail->hash_lock);
+ /* Didn't find anything, insert an empty entry */
+
+ new = detail->alloc();
+ if (!new)
+ return NULL;
+ cache_init(new);
+
+ write_lock(&detail->hash_lock);
+
+ /* check if entry appeared while we slept */
+ for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
+ struct cache_head *tmp = *hp;
+ if (detail->match(tmp, key)) {
+ cache_get(tmp);
+ write_unlock(&detail->hash_lock);
+ cache_put(new, detail);
+ return tmp;
+ }
+ }
+ detail->init(new, key);
+ new->next = *head;
+ *head = new;
+ detail->entries++;
+ cache_get(new);
+ write_unlock(&detail->hash_lock);
+
+ return new;
+}
+EXPORT_SYMBOL(sunrpc_cache_lookup);
+
+
+static void queue_loose(struct cache_detail *detail, struct cache_head *ch);
+
+static int cache_fresh_locked(struct cache_head *head, time_t expiry)
+{
+ head->expiry_time = expiry;
+ head->last_refresh = get_seconds();
+ return !test_and_set_bit(CACHE_VALID, &head->flags);
+}
+
+static void cache_fresh_unlocked(struct cache_head *head,
+ struct cache_detail *detail, int new)
+{
+ if (new)
+ cache_revisit_request(head);
+ if (test_and_clear_bit(CACHE_PENDING, &head->flags)) {
+ cache_revisit_request(head);
+ queue_loose(detail, head);
+ }
+}
+
+struct cache_head *sunrpc_cache_update(struct cache_detail *detail,
+ struct cache_head *new, struct cache_head *old, int hash)
+{
+ /* The 'old' entry is to be replaced by 'new'.
+ * If 'old' is not VALID, we update it directly,
+ * otherwise we need to replace it
+ */
+ struct cache_head **head;
+ struct cache_head *tmp;
+ int is_new;
+
+ if (!test_bit(CACHE_VALID, &old->flags)) {
+ write_lock(&detail->hash_lock);
+ if (!test_bit(CACHE_VALID, &old->flags)) {
+ if (test_bit(CACHE_NEGATIVE, &new->flags))
+ set_bit(CACHE_NEGATIVE, &old->flags);
+ else
+ detail->update(old, new);
+ is_new = cache_fresh_locked(old, new->expiry_time);
+ write_unlock(&detail->hash_lock);
+ cache_fresh_unlocked(old, detail, is_new);
+ return old;
+ }
+ write_unlock(&detail->hash_lock);
+ }
+ /* We need to insert a new entry */
+ tmp = detail->alloc();
+ if (!tmp) {
+ cache_put(old, detail);
+ return NULL;
+ }
+ cache_init(tmp);
+ detail->init(tmp, old);
+ head = &detail->hash_table[hash];
+
+ write_lock(&detail->hash_lock);
+ if (test_bit(CACHE_NEGATIVE, &new->flags))
+ set_bit(CACHE_NEGATIVE, &tmp->flags);
+ else
+ detail->update(tmp, new);
+ tmp->next = *head;
+ *head = tmp;
+ cache_get(tmp);
+ is_new = cache_fresh_locked(tmp, new->expiry_time);
+ cache_fresh_locked(old, 0);
+ write_unlock(&detail->hash_lock);
+ cache_fresh_unlocked(tmp, detail, is_new);
+ cache_fresh_unlocked(old, detail, 0);
+ cache_put(old, detail);
+ return tmp;
+}
+EXPORT_SYMBOL(sunrpc_cache_update);
static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h);
/*
@@ -94,7 +216,8 @@ int cache_check(struct cache_detail *detail,
clear_bit(CACHE_PENDING, &h->flags);
if (rv == -EAGAIN) {
set_bit(CACHE_NEGATIVE, &h->flags);
- cache_fresh(detail, h, get_seconds()+CACHE_NEW_EXPIRY);
+ cache_fresh_unlocked(h, detail,
+ cache_fresh_locked(h, get_seconds()+CACHE_NEW_EXPIRY));
rv = -ENOENT;
}
break;
@@ -110,25 +233,11 @@ int cache_check(struct cache_detail *detail,
if (rv == -EAGAIN)
cache_defer_req(rqstp, h);
- if (rv && h)
- detail->cache_put(h, detail);
+ if (rv)
+ cache_put(h, detail);
return rv;
}
-static void queue_loose(struct cache_detail *detail, struct cache_head *ch);
-
-void cache_fresh(struct cache_detail *detail,
- struct cache_head *head, time_t expiry)
-{
-
- head->expiry_time = expiry;
- head->last_refresh = get_seconds();
- if (!test_and_set_bit(CACHE_VALID, &head->flags))
- cache_revisit_request(head);
- if (test_and_clear_bit(CACHE_PENDING, &head->flags))
- queue_loose(detail, head);
-}
-
/*
* caches need to be periodically cleaned.
* For this we maintain a list of cache_detail and
@@ -322,7 +431,7 @@ static int cache_clean(void)
if (test_and_clear_bit(CACHE_PENDING, &ch->flags))
queue_loose(current_detail, ch);
- if (atomic_read(&ch->refcnt) == 1)
+ if (atomic_read(&ch->ref.refcount) == 1)
break;
}
if (ch) {
@@ -337,7 +446,7 @@ static int cache_clean(void)
current_index ++;
spin_unlock(&cache_list_lock);
if (ch)
- d->cache_put(ch, d);
+ cache_put(ch, d);
} else
spin_unlock(&cache_list_lock);
@@ -453,7 +562,7 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item)
/* there was one too many */
dreq->revisit(dreq, 1);
}
- if (test_bit(CACHE_VALID, &item->flags)) {
+ if (!test_bit(CACHE_PENDING, &item->flags)) {
/* must have just been validated... */
cache_revisit_request(item);
}
@@ -614,7 +723,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
!test_bit(CACHE_PENDING, &rq->item->flags)) {
list_del(&rq->q.list);
spin_unlock(&queue_lock);
- cd->cache_put(rq->item, cd);
+ cache_put(rq->item, cd);
kfree(rq->buf);
kfree(rq);
} else
@@ -794,10 +903,10 @@ static void queue_loose(struct cache_detail *detail, struct cache_head *ch)
if (cr->item != ch)
continue;
if (cr->readers != 0)
- break;
+ continue;
list_del(&cr->q.list);
spin_unlock(&queue_lock);
- detail->cache_put(cr->item, detail);
+ cache_put(cr->item, detail);
kfree(cr->buf);
kfree(cr);
return;
@@ -1082,8 +1191,8 @@ static int c_show(struct seq_file *m, void *p)
return cd->cache_show(m, cd, NULL);
ifdebug(CACHE)
- seq_printf(m, "# expiry=%ld refcnt=%d\n",
- cp->expiry_time, atomic_read(&cp->refcnt));
+ seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n",
+ cp->expiry_time, atomic_read(&cp->ref.refcount), cp->flags);
cache_get(cp);
if (cache_check(cd, cp, NULL))
/* cache_check does a cache_put on failure */
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index d7847978204..aa8965e9d30 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -28,12 +28,11 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/utsname.h>
+#include <linux/workqueue.h>
#include <linux/sunrpc/clnt.h>
-#include <linux/workqueue.h>
#include <linux/sunrpc/rpc_pipe_fs.h>
-
-#include <linux/nfs.h>
+#include <linux/sunrpc/metrics.h>
#define RPC_SLACK_SPACE (1024) /* total overkill */
@@ -71,8 +70,15 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
static uint32_t clntid;
int error;
+ clnt->cl_vfsmnt = ERR_PTR(-ENOENT);
+ clnt->cl_dentry = ERR_PTR(-ENOENT);
if (dir_name == NULL)
return 0;
+
+ clnt->cl_vfsmnt = rpc_get_mount();
+ if (IS_ERR(clnt->cl_vfsmnt))
+ return PTR_ERR(clnt->cl_vfsmnt);
+
for (;;) {
snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname),
"%s/clnt%x", dir_name,
@@ -85,6 +91,7 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
if (error != -EEXIST) {
printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n",
clnt->cl_pathname, error);
+ rpc_put_mount();
return error;
}
}
@@ -147,6 +154,7 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
clnt->cl_vers = version->number;
clnt->cl_prot = xprt->prot;
clnt->cl_stats = program->stats;
+ clnt->cl_metrics = rpc_alloc_iostats(clnt);
rpc_init_wait_queue(&clnt->cl_pmap_default.pm_bindwait, "bindwait");
if (!clnt->cl_port)
@@ -175,7 +183,11 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
return clnt;
out_no_auth:
- rpc_rmdir(clnt->cl_pathname);
+ if (!IS_ERR(clnt->cl_dentry)) {
+ rpc_rmdir(clnt->cl_pathname);
+ dput(clnt->cl_dentry);
+ rpc_put_mount();
+ }
out_no_path:
if (clnt->cl_server != clnt->cl_inline_name)
kfree(clnt->cl_server);
@@ -240,11 +252,15 @@ rpc_clone_client(struct rpc_clnt *clnt)
new->cl_autobind = 0;
new->cl_oneshot = 0;
new->cl_dead = 0;
+ if (!IS_ERR(new->cl_dentry)) {
+ dget(new->cl_dentry);
+ rpc_get_mount();
+ }
rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
if (new->cl_auth)
atomic_inc(&new->cl_auth->au_count);
new->cl_pmap = &new->cl_pmap_default;
- rpc_init_wait_queue(&new->cl_pmap_default.pm_bindwait, "bindwait");
+ new->cl_metrics = rpc_alloc_iostats(clnt);
return new;
out_no_clnt:
printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__);
@@ -314,6 +330,12 @@ rpc_destroy_client(struct rpc_clnt *clnt)
if (clnt->cl_server != clnt->cl_inline_name)
kfree(clnt->cl_server);
out_free:
+ rpc_free_iostats(clnt->cl_metrics);
+ clnt->cl_metrics = NULL;
+ if (!IS_ERR(clnt->cl_dentry)) {
+ dput(clnt->cl_dentry);
+ rpc_put_mount();
+ }
kfree(clnt);
return 0;
}
@@ -473,15 +495,16 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
int status;
/* If this client is slain all further I/O fails */
+ status = -EIO;
if (clnt->cl_dead)
- return -EIO;
+ goto out_release;
flags |= RPC_TASK_ASYNC;
/* Create/initialize a new RPC task */
status = -ENOMEM;
if (!(task = rpc_new_task(clnt, flags, tk_ops, data)))
- goto out;
+ goto out_release;
/* Mask signals on GSS_AUTH upcalls */
rpc_task_sigmask(task, &oldset);
@@ -496,7 +519,10 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
rpc_release_task(task);
rpc_restore_sigmask(&oldset);
-out:
+ return status;
+out_release:
+ if (tk_ops->rpc_release != NULL)
+ tk_ops->rpc_release(data);
return status;
}
@@ -993,6 +1019,8 @@ call_timeout(struct rpc_task *task)
}
dprintk("RPC: %4d call_timeout (major)\n", task->tk_pid);
+ task->tk_timeouts++;
+
if (RPC_IS_SOFT(task)) {
printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
clnt->cl_protname, clnt->cl_server);
@@ -1045,6 +1073,11 @@ call_decode(struct rpc_task *task)
return;
}
+ /*
+ * Ensure that we see all writes made by xprt_complete_rqst()
+ * before it changed req->rq_received.
+ */
+ smp_rmb();
req->rq_rcv_buf.len = req->rq_private_buf.len;
/* Check that the softirq receive buffer is valid */
@@ -1194,8 +1227,8 @@ call_verify(struct rpc_task *task)
task->tk_action = call_bind;
goto out_retry;
case RPC_AUTH_TOOWEAK:
- printk(KERN_NOTICE "call_verify: server requires stronger "
- "authentication.\n");
+ printk(KERN_NOTICE "call_verify: server %s requires stronger "
+ "authentication.\n", task->tk_client->cl_server);
break;
default:
printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n);
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index 8139ce68e91..d25b054ec92 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -82,6 +82,7 @@ rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
rpc_call_setup(child, &msg, 0);
/* ... and run the child task */
+ task->tk_xprt->stat.bind_count++;
rpc_run_child(task, child, pmap_getport_done);
return;
@@ -103,6 +104,11 @@ rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
.pm_prot = prot,
.pm_port = 0
};
+ struct rpc_message msg = {
+ .rpc_proc = &pmap_procedures[PMAP_GETPORT],
+ .rpc_argp = &map,
+ .rpc_resp = &map.pm_port,
+ };
struct rpc_clnt *pmap_clnt;
char hostname[32];
int status;
@@ -116,7 +122,7 @@ rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
return PTR_ERR(pmap_clnt);
/* Setup the call info struct */
- status = rpc_call(pmap_clnt, PMAP_GETPORT, &map, &map.pm_port, 0);
+ status = rpc_call_sync(pmap_clnt, &msg, 0);
if (status >= 0) {
if (map.pm_port != 0)
@@ -161,16 +167,27 @@ pmap_getport_done(struct rpc_task *task)
int
rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
{
- struct sockaddr_in sin;
- struct rpc_portmap map;
+ struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
+ };
+ struct rpc_portmap map = {
+ .pm_prog = prog,
+ .pm_vers = vers,
+ .pm_prot = prot,
+ .pm_port = port,
+ };
+ struct rpc_message msg = {
+ .rpc_proc = &pmap_procedures[port ? PMAP_SET : PMAP_UNSET],
+ .rpc_argp = &map,
+ .rpc_resp = okay,
+ };
struct rpc_clnt *pmap_clnt;
int error = 0;
dprintk("RPC: registering (%d, %d, %d, %d) with portmapper.\n",
prog, vers, prot, port);
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP, 1);
if (IS_ERR(pmap_clnt)) {
error = PTR_ERR(pmap_clnt);
@@ -178,13 +195,7 @@ rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
return error;
}
- map.pm_prog = prog;
- map.pm_vers = vers;
- map.pm_prot = prot;
- map.pm_port = port;
-
- error = rpc_call(pmap_clnt, port? PMAP_SET : PMAP_UNSET,
- &map, okay, 0);
+ error = rpc_call_sync(pmap_clnt, &msg, 0);
if (error < 0) {
printk(KERN_WARNING
@@ -260,6 +271,8 @@ static struct rpc_procinfo pmap_procedures[] = {
.p_decode = (kxdrproc_t) xdr_decode_bool,
.p_bufsiz = 4,
.p_count = 1,
+ .p_statidx = PMAP_SET,
+ .p_name = "SET",
},
[PMAP_UNSET] = {
.p_proc = PMAP_UNSET,
@@ -267,6 +280,8 @@ static struct rpc_procinfo pmap_procedures[] = {
.p_decode = (kxdrproc_t) xdr_decode_bool,
.p_bufsiz = 4,
.p_count = 1,
+ .p_statidx = PMAP_UNSET,
+ .p_name = "UNSET",
},
[PMAP_GETPORT] = {
.p_proc = PMAP_GETPORT,
@@ -274,6 +289,8 @@ static struct rpc_procinfo pmap_procedures[] = {
.p_decode = (kxdrproc_t) xdr_decode_port,
.p_bufsiz = 4,
.p_count = 1,
+ .p_statidx = PMAP_GETPORT,
+ .p_name = "GETPORT",
},
};
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index ad9d9fc4e73..cc673dd8433 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -91,7 +91,8 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
res = 0;
} else if (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN) {
if (list_empty(&rpci->pipe))
- schedule_delayed_work(&rpci->queue_timeout,
+ queue_delayed_work(rpciod_workqueue,
+ &rpci->queue_timeout,
RPC_UPCALL_TIMEOUT);
list_add_tail(&msg->list, &rpci->pipe);
rpci->pipelen += msg->len;
@@ -132,7 +133,7 @@ rpc_close_pipes(struct inode *inode)
if (ops->release_pipe)
ops->release_pipe(inode);
cancel_delayed_work(&rpci->queue_timeout);
- flush_scheduled_work();
+ flush_workqueue(rpciod_workqueue);
}
rpc_inode_setowner(inode, NULL);
mutex_unlock(&inode->i_mutex);
@@ -394,7 +395,7 @@ enum {
*/
struct rpc_filelist {
char *name;
- struct file_operations *i_fop;
+ const struct file_operations *i_fop;
int mode;
};
@@ -434,14 +435,17 @@ static struct rpc_filelist authfiles[] = {
},
};
-static int
-rpc_get_mount(void)
+struct vfsmount *rpc_get_mount(void)
{
- return simple_pin_fs("rpc_pipefs", &rpc_mount, &rpc_mount_count);
+ int err;
+
+ err = simple_pin_fs("rpc_pipefs", &rpc_mount, &rpc_mount_count);
+ if (err != 0)
+ return ERR_PTR(err);
+ return rpc_mount;
}
-static void
-rpc_put_mount(void)
+void rpc_put_mount(void)
{
simple_release_fs(&rpc_mount, &rpc_mount_count);
}
@@ -451,12 +455,13 @@ rpc_lookup_parent(char *path, struct nameidata *nd)
{
if (path[0] == '\0')
return -ENOENT;
- if (rpc_get_mount()) {
+ nd->mnt = rpc_get_mount();
+ if (IS_ERR(nd->mnt)) {
printk(KERN_WARNING "%s: %s failed to mount "
"pseudofilesystem \n", __FILE__, __FUNCTION__);
- return -ENODEV;
+ return PTR_ERR(nd->mnt);
}
- nd->mnt = mntget(rpc_mount);
+ mntget(nd->mnt);
nd->dentry = dget(rpc_mount->mnt_root);
nd->last_type = LAST_ROOT;
nd->flags = LOOKUP_PARENT;
@@ -593,7 +598,6 @@ __rpc_mkdir(struct inode *dir, struct dentry *dentry)
d_instantiate(dentry, inode);
dir->i_nlink++;
inode_dir_notify(dir, DN_CREATE);
- rpc_get_mount();
return 0;
out_err:
printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n",
@@ -614,7 +618,6 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry)
if (!error) {
inode_dir_notify(dir, DN_DELETE);
d_drop(dentry);
- rpc_put_mount();
}
return 0;
}
@@ -668,7 +671,7 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client)
out:
mutex_unlock(&dir->i_mutex);
rpc_release_path(&nd);
- return dentry;
+ return dget(dentry);
err_depopulate:
rpc_depopulate(dentry);
__rpc_rmdir(dir, dentry);
@@ -732,7 +735,7 @@ rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags)
out:
mutex_unlock(&dir->i_mutex);
rpc_release_path(&nd);
- return dentry;
+ return dget(dentry);
err_dput:
dput(dentry);
dentry = ERR_PTR(-ENOMEM);
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index dff07795bd1..5c3eee76850 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -65,7 +65,7 @@ static LIST_HEAD(all_tasks);
*/
static DEFINE_MUTEX(rpciod_mutex);
static unsigned int rpciod_users;
-static struct workqueue_struct *rpciod_workqueue;
+struct workqueue_struct *rpciod_workqueue;
/*
* Spinlock for other critical sections of code.
@@ -182,6 +182,7 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *
else
list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]);
task->u.tk_wait.rpc_waitq = queue;
+ queue->qlen++;
rpc_set_queued(task);
dprintk("RPC: %4d added to queue %p \"%s\"\n",
@@ -216,6 +217,7 @@ static void __rpc_remove_wait_queue(struct rpc_task *task)
__rpc_remove_wait_queue_priority(task);
else
list_del(&task->u.tk_wait.list);
+ queue->qlen--;
dprintk("RPC: %4d removed from queue %p \"%s\"\n",
task->tk_pid, queue, rpc_qname(queue));
}
@@ -816,6 +818,9 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons
BUG_ON(task->tk_ops == NULL);
+ /* starting timestamp */
+ task->tk_start = jiffies;
+
dprintk("RPC: %4d new task procpid %d\n", task->tk_pid,
current->pid);
}
@@ -917,8 +922,11 @@ struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
{
struct rpc_task *task;
task = rpc_new_task(clnt, flags, ops, data);
- if (task == NULL)
+ if (task == NULL) {
+ if (ops->rpc_release != NULL)
+ ops->rpc_release(data);
return ERR_PTR(-ENOMEM);
+ }
atomic_inc(&task->tk_count);
rpc_execute(task);
return task;
@@ -1159,16 +1167,12 @@ rpc_init_mempool(void)
NULL, NULL);
if (!rpc_buffer_slabp)
goto err_nomem;
- rpc_task_mempool = mempool_create(RPC_TASK_POOLSIZE,
- mempool_alloc_slab,
- mempool_free_slab,
- rpc_task_slabp);
+ rpc_task_mempool = mempool_create_slab_pool(RPC_TASK_POOLSIZE,
+ rpc_task_slabp);
if (!rpc_task_mempool)
goto err_nomem;
- rpc_buffer_mempool = mempool_create(RPC_BUFFER_POOLSIZE,
- mempool_alloc_slab,
- mempool_free_slab,
- rpc_buffer_slabp);
+ rpc_buffer_mempool = mempool_create_slab_pool(RPC_BUFFER_POOLSIZE,
+ rpc_buffer_slabp);
if (!rpc_buffer_mempool)
goto err_nomem;
return 0;
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index 4979f226e28..dea529666d6 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -21,6 +21,7 @@
#include <linux/seq_file.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svcsock.h>
+#include <linux/sunrpc/metrics.h>
#define RPCDBG_FACILITY RPCDBG_MISC
@@ -106,11 +107,125 @@ void svc_seq_show(struct seq_file *seq, const struct svc_stat *statp) {
}
}
+/**
+ * rpc_alloc_iostats - allocate an rpc_iostats structure
+ * @clnt: RPC program, version, and xprt
+ *
+ */
+struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt)
+{
+ unsigned int ops = clnt->cl_maxproc;
+ size_t size = ops * sizeof(struct rpc_iostats);
+ struct rpc_iostats *new;
+
+ new = kmalloc(size, GFP_KERNEL);
+ if (new)
+ memset(new, 0 , size);
+ return new;
+}
+EXPORT_SYMBOL(rpc_alloc_iostats);
+
+/**
+ * rpc_free_iostats - release an rpc_iostats structure
+ * @stats: doomed rpc_iostats structure
+ *
+ */
+void rpc_free_iostats(struct rpc_iostats *stats)
+{
+ kfree(stats);
+}
+EXPORT_SYMBOL(rpc_free_iostats);
+
+/**
+ * rpc_count_iostats - tally up per-task stats
+ * @task: completed rpc_task
+ *
+ * Relies on the caller for serialization.
+ */
+void rpc_count_iostats(struct rpc_task *task)
+{
+ struct rpc_rqst *req = task->tk_rqstp;
+ struct rpc_iostats *stats = task->tk_client->cl_metrics;
+ struct rpc_iostats *op_metrics;
+ long rtt, execute, queue;
+
+ if (!stats || !req)
+ return;
+ op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx];
+
+ op_metrics->om_ops++;
+ op_metrics->om_ntrans += req->rq_ntrans;
+ op_metrics->om_timeouts += task->tk_timeouts;
+
+ op_metrics->om_bytes_sent += task->tk_bytes_sent;
+ op_metrics->om_bytes_recv += req->rq_received;
+
+ queue = (long)req->rq_xtime - task->tk_start;
+ if (queue < 0)
+ queue = -queue;
+ op_metrics->om_queue += queue;
+
+ rtt = task->tk_rtt;
+ if (rtt < 0)
+ rtt = -rtt;
+ op_metrics->om_rtt += rtt;
+
+ execute = (long)jiffies - task->tk_start;
+ if (execute < 0)
+ execute = -execute;
+ op_metrics->om_execute += execute;
+}
+
+void _print_name(struct seq_file *seq, unsigned int op, struct rpc_procinfo *procs)
+{
+ if (procs[op].p_name)
+ seq_printf(seq, "\t%12s: ", procs[op].p_name);
+ else if (op == 0)
+ seq_printf(seq, "\t NULL: ");
+ else
+ seq_printf(seq, "\t%12u: ", op);
+}
+
+#define MILLISECS_PER_JIFFY (1000 / HZ)
+
+void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt)
+{
+ struct rpc_iostats *stats = clnt->cl_metrics;
+ struct rpc_xprt *xprt = clnt->cl_xprt;
+ unsigned int op, maxproc = clnt->cl_maxproc;
+
+ if (!stats)
+ return;
+
+ seq_printf(seq, "\tRPC iostats version: %s ", RPC_IOSTATS_VERS);
+ seq_printf(seq, "p/v: %u/%u (%s)\n",
+ clnt->cl_prog, clnt->cl_vers, clnt->cl_protname);
+
+ if (xprt)
+ xprt->ops->print_stats(xprt, seq);
+
+ seq_printf(seq, "\tper-op statistics\n");
+ for (op = 0; op < maxproc; op++) {
+ struct rpc_iostats *metrics = &stats[op];
+ _print_name(seq, op, clnt->cl_procinfo);
+ seq_printf(seq, "%lu %lu %lu %Lu %Lu %Lu %Lu %Lu\n",
+ metrics->om_ops,
+ metrics->om_ntrans,
+ metrics->om_timeouts,
+ metrics->om_bytes_sent,
+ metrics->om_bytes_recv,
+ metrics->om_queue * MILLISECS_PER_JIFFY,
+ metrics->om_rtt * MILLISECS_PER_JIFFY,
+ metrics->om_execute * MILLISECS_PER_JIFFY);
+ }
+}
+EXPORT_SYMBOL(rpc_print_iostats);
+
/*
* Register/unregister RPC proc files
*/
static inline struct proc_dir_entry *
-do_register(const char *name, void *data, struct file_operations *fops)
+do_register(const char *name, void *data, const struct file_operations *fops)
{
struct proc_dir_entry *ent;
@@ -138,7 +253,7 @@ rpc_proc_unregister(const char *name)
}
struct proc_dir_entry *
-svc_proc_register(struct svc_stat *statp, struct file_operations *fops)
+svc_proc_register(struct svc_stat *statp, const struct file_operations *fops)
{
return do_register(statp->program->pg_name, statp, fops);
}
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index 9f737320359..769114f0f88 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -105,8 +105,6 @@ EXPORT_SYMBOL(auth_unix_lookup);
EXPORT_SYMBOL(cache_check);
EXPORT_SYMBOL(cache_flush);
EXPORT_SYMBOL(cache_purge);
-EXPORT_SYMBOL(cache_fresh);
-EXPORT_SYMBOL(cache_init);
EXPORT_SYMBOL(cache_register);
EXPORT_SYMBOL(cache_unregister);
EXPORT_SYMBOL(qword_add);
@@ -142,6 +140,7 @@ EXPORT_SYMBOL(nlm_debug);
extern int register_rpc_pipefs(void);
extern void unregister_rpc_pipefs(void);
+extern struct cache_detail ip_map_cache;
static int __init
init_sunrpc(void)
@@ -158,7 +157,6 @@ init_sunrpc(void)
#ifdef CONFIG_PROC_FS
rpc_proc_init();
#endif
- cache_register(&auth_domain_cache);
cache_register(&ip_map_cache);
out:
return err;
@@ -169,8 +167,6 @@ cleanup_sunrpc(void)
{
unregister_rpc_pipefs();
rpc_destroy_mempool();
- if (cache_unregister(&auth_domain_cache))
- printk(KERN_ERR "sunrpc: failed to unregister auth_domain cache\n");
if (cache_unregister(&ip_map_cache))
printk(KERN_ERR "sunrpc: failed to unregister ip_map cache\n");
#ifdef RPC_DEBUG
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index dda4f0c6351..5b28c617680 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -106,112 +106,56 @@ svc_auth_unregister(rpc_authflavor_t flavor)
EXPORT_SYMBOL(svc_auth_unregister);
/**************************************************
- * cache for domain name to auth_domain
- * Entries are only added by flavours which will normally
- * have a structure that 'inherits' from auth_domain.
- * e.g. when an IP -> domainname is given to auth_unix,
- * and the domain name doesn't exist, it will create a
- * auth_unix_domain and add it to this hash table.
- * If it finds the name does exist, but isn't AUTH_UNIX,
- * it will complain.
+ * 'auth_domains' are stored in a hash table indexed by name.
+ * When the last reference to an 'auth_domain' is dropped,
+ * the object is unhashed and freed.
+ * If auth_domain_lookup fails to find an entry, it will return
+ * it's second argument 'new'. If this is non-null, it will
+ * have been atomically linked into the table.
*/
-/*
- * Auth auth_domain cache is somewhat different to other caches,
- * largely because the entries are possibly of different types:
- * each auth flavour has it's own type.
- * One consequence of this that DefineCacheLookup cannot
- * allocate a new structure as it cannot know the size.
- * Notice that the "INIT" code fragment is quite different
- * from other caches. When auth_domain_lookup might be
- * creating a new domain, the new domain is passed in
- * complete and it is used as-is rather than being copied into
- * another structure.
- */
#define DN_HASHBITS 6
#define DN_HASHMAX (1<<DN_HASHBITS)
#define DN_HASHMASK (DN_HASHMAX-1)
-static struct cache_head *auth_domain_table[DN_HASHMAX];
-
-static void auth_domain_drop(struct cache_head *item, struct cache_detail *cd)
-{
- struct auth_domain *dom = container_of(item, struct auth_domain, h);
- if (cache_put(item,cd))
- authtab[dom->flavour]->domain_release(dom);
-}
-
-
-struct cache_detail auth_domain_cache = {
- .owner = THIS_MODULE,
- .hash_size = DN_HASHMAX,
- .hash_table = auth_domain_table,
- .name = "auth.domain",
- .cache_put = auth_domain_drop,
-};
+static struct hlist_head auth_domain_table[DN_HASHMAX];
+static spinlock_t auth_domain_lock = SPIN_LOCK_UNLOCKED;
void auth_domain_put(struct auth_domain *dom)
{
- auth_domain_drop(&dom->h, &auth_domain_cache);
-}
-
-static inline int auth_domain_hash(struct auth_domain *item)
-{
- return hash_str(item->name, DN_HASHBITS);
-}
-static inline int auth_domain_match(struct auth_domain *tmp, struct auth_domain *item)
-{
- return strcmp(tmp->name, item->name) == 0;
+ if (atomic_dec_and_lock(&dom->ref.refcount, &auth_domain_lock)) {
+ hlist_del(&dom->hash);
+ dom->flavour->domain_release(dom);
+ }
}
struct auth_domain *
-auth_domain_lookup(struct auth_domain *item, int set)
+auth_domain_lookup(char *name, struct auth_domain *new)
{
- struct auth_domain *tmp = NULL;
- struct cache_head **hp, **head;
- head = &auth_domain_cache.hash_table[auth_domain_hash(item)];
-
- if (set)
- write_lock(&auth_domain_cache.hash_lock);
- else
- read_lock(&auth_domain_cache.hash_lock);
- for (hp=head; *hp != NULL; hp = &tmp->h.next) {
- tmp = container_of(*hp, struct auth_domain, h);
- if (!auth_domain_match(tmp, item))
- continue;
- if (!set) {
- cache_get(&tmp->h);
- goto out_noset;
+ struct auth_domain *hp;
+ struct hlist_head *head;
+ struct hlist_node *np;
+
+ head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
+
+ spin_lock(&auth_domain_lock);
+
+ hlist_for_each_entry(hp, np, head, hash) {
+ if (strcmp(hp->name, name)==0) {
+ kref_get(&hp->ref);
+ spin_unlock(&auth_domain_lock);
+ return hp;
}
- *hp = tmp->h.next;
- tmp->h.next = NULL;
- auth_domain_drop(&tmp->h, &auth_domain_cache);
- goto out_set;
}
- /* Didn't find anything */
- if (!set)
- goto out_nada;
- auth_domain_cache.entries++;
-out_set:
- item->h.next = *head;
- *head = &item->h;
- cache_get(&item->h);
- write_unlock(&auth_domain_cache.hash_lock);
- cache_fresh(&auth_domain_cache, &item->h, item->h.expiry_time);
- cache_get(&item->h);
- return item;
-out_nada:
- tmp = NULL;
-out_noset:
- read_unlock(&auth_domain_cache.hash_lock);
- return tmp;
+ if (new) {
+ hlist_add_head(&new->hash, head);
+ kref_get(&new->ref);
+ }
+ spin_unlock(&auth_domain_lock);
+ return new;
}
struct auth_domain *auth_domain_find(char *name)
{
- struct auth_domain *rv, ad;
-
- ad.name = name;
- rv = auth_domain_lookup(&ad, 0);
- return rv;
+ return auth_domain_lookup(name, NULL);
}
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 3e6c694bbad..7e5707e2d6b 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -27,41 +27,35 @@ struct unix_domain {
/* other stuff later */
};
+extern struct auth_ops svcauth_unix;
+
struct auth_domain *unix_domain_find(char *name)
{
- struct auth_domain *rv, ud;
- struct unix_domain *new;
-
- ud.name = name;
-
- rv = auth_domain_lookup(&ud, 0);
-
- foundit:
- if (rv && rv->flavour != RPC_AUTH_UNIX) {
- auth_domain_put(rv);
- return NULL;
- }
- if (rv)
- return rv;
-
- new = kmalloc(sizeof(*new), GFP_KERNEL);
- if (new == NULL)
- return NULL;
- cache_init(&new->h.h);
- new->h.name = kstrdup(name, GFP_KERNEL);
- new->h.flavour = RPC_AUTH_UNIX;
- new->addr_changes = 0;
- new->h.h.expiry_time = NEVER;
-
- rv = auth_domain_lookup(&new->h, 2);
- if (rv == &new->h) {
- if (atomic_dec_and_test(&new->h.h.refcnt)) BUG();
- } else {
- auth_domain_put(&new->h);
- goto foundit;
+ struct auth_domain *rv;
+ struct unix_domain *new = NULL;
+
+ rv = auth_domain_lookup(name, NULL);
+ while(1) {
+ if (rv) {
+ if (new && rv != &new->h)
+ auth_domain_put(&new->h);
+
+ if (rv->flavour != &svcauth_unix) {
+ auth_domain_put(rv);
+ return NULL;
+ }
+ return rv;
+ }
+
+ new = kmalloc(sizeof(*new), GFP_KERNEL);
+ if (new == NULL)
+ return NULL;
+ kref_init(&new->h.ref);
+ new->h.name = kstrdup(name, GFP_KERNEL);
+ new->h.flavour = &svcauth_unix;
+ new->addr_changes = 0;
+ rv = auth_domain_lookup(name, &new->h);
}
-
- return rv;
}
static void svcauth_unix_domain_release(struct auth_domain *dom)
@@ -90,15 +84,15 @@ struct ip_map {
};
static struct cache_head *ip_table[IP_HASHMAX];
-static void ip_map_put(struct cache_head *item, struct cache_detail *cd)
+static void ip_map_put(struct kref *kref)
{
+ struct cache_head *item = container_of(kref, struct cache_head, ref);
struct ip_map *im = container_of(item, struct ip_map,h);
- if (cache_put(item, cd)) {
- if (test_bit(CACHE_VALID, &item->flags) &&
- !test_bit(CACHE_NEGATIVE, &item->flags))
- auth_domain_put(&im->m_client->h);
- kfree(im);
- }
+
+ if (test_bit(CACHE_VALID, &item->flags) &&
+ !test_bit(CACHE_NEGATIVE, &item->flags))
+ auth_domain_put(&im->m_client->h);
+ kfree(im);
}
#if IP_HASHBITS == 8
@@ -112,28 +106,38 @@ static inline int hash_ip(unsigned long ip)
return (hash ^ (hash>>8)) & 0xff;
}
#endif
-
-static inline int ip_map_hash(struct ip_map *item)
-{
- return hash_str(item->m_class, IP_HASHBITS) ^
- hash_ip((unsigned long)item->m_addr.s_addr);
-}
-static inline int ip_map_match(struct ip_map *item, struct ip_map *tmp)
+static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
{
- return strcmp(tmp->m_class, item->m_class) == 0
- && tmp->m_addr.s_addr == item->m_addr.s_addr;
+ struct ip_map *orig = container_of(corig, struct ip_map, h);
+ struct ip_map *new = container_of(cnew, struct ip_map, h);
+ return strcmp(orig->m_class, new->m_class) == 0
+ && orig->m_addr.s_addr == new->m_addr.s_addr;
}
-static inline void ip_map_init(struct ip_map *new, struct ip_map *item)
+static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
{
+ struct ip_map *new = container_of(cnew, struct ip_map, h);
+ struct ip_map *item = container_of(citem, struct ip_map, h);
+
strcpy(new->m_class, item->m_class);
new->m_addr.s_addr = item->m_addr.s_addr;
}
-static inline void ip_map_update(struct ip_map *new, struct ip_map *item)
+static void update(struct cache_head *cnew, struct cache_head *citem)
{
- cache_get(&item->m_client->h.h);
+ struct ip_map *new = container_of(cnew, struct ip_map, h);
+ struct ip_map *item = container_of(citem, struct ip_map, h);
+
+ kref_get(&item->m_client->h.ref);
new->m_client = item->m_client;
new->m_add_change = item->m_add_change;
}
+static struct cache_head *ip_map_alloc(void)
+{
+ struct ip_map *i = kmalloc(sizeof(*i), GFP_KERNEL);
+ if (i)
+ return &i->h;
+ else
+ return NULL;
+}
static void ip_map_request(struct cache_detail *cd,
struct cache_head *h,
@@ -154,7 +158,8 @@ static void ip_map_request(struct cache_detail *cd,
(*bpp)[-1] = '\n';
}
-static struct ip_map *ip_map_lookup(struct ip_map *, int);
+static struct ip_map *ip_map_lookup(char *class, struct in_addr addr);
+static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
static int ip_map_parse(struct cache_detail *cd,
char *mesg, int mlen)
@@ -166,7 +171,11 @@ static int ip_map_parse(struct cache_detail *cd,
int len;
int b1,b2,b3,b4;
char c;
- struct ip_map ipm, *ipmp;
+ char class[8];
+ struct in_addr addr;
+ int err;
+
+ struct ip_map *ipmp;
struct auth_domain *dom;
time_t expiry;
@@ -175,7 +184,7 @@ static int ip_map_parse(struct cache_detail *cd,
mesg[mlen-1] = 0;
/* class */
- len = qword_get(&mesg, ipm.m_class, sizeof(ipm.m_class));
+ len = qword_get(&mesg, class, sizeof(class));
if (len <= 0) return -EINVAL;
/* ip address */
@@ -200,25 +209,22 @@ static int ip_map_parse(struct cache_detail *cd,
} else
dom = NULL;
- ipm.m_addr.s_addr =
+ addr.s_addr =
htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
- ipm.h.flags = 0;
- if (dom) {
- ipm.m_client = container_of(dom, struct unix_domain, h);
- ipm.m_add_change = ipm.m_client->addr_changes;
+
+ ipmp = ip_map_lookup(class,addr);
+ if (ipmp) {
+ err = ip_map_update(ipmp,
+ container_of(dom, struct unix_domain, h),
+ expiry);
} else
- set_bit(CACHE_NEGATIVE, &ipm.h.flags);
- ipm.h.expiry_time = expiry;
+ err = -ENOMEM;
- ipmp = ip_map_lookup(&ipm, 1);
- if (ipmp)
- ip_map_put(&ipmp->h, &ip_map_cache);
if (dom)
auth_domain_put(dom);
- if (!ipmp)
- return -ENOMEM;
+
cache_flush();
- return 0;
+ return err;
}
static int ip_map_show(struct seq_file *m,
@@ -262,32 +268,70 @@ struct cache_detail ip_map_cache = {
.cache_request = ip_map_request,
.cache_parse = ip_map_parse,
.cache_show = ip_map_show,
+ .match = ip_map_match,
+ .init = ip_map_init,
+ .update = update,
+ .alloc = ip_map_alloc,
};
-static DefineSimpleCacheLookup(ip_map, 0)
+static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
+{
+ struct ip_map ip;
+ struct cache_head *ch;
+
+ strcpy(ip.m_class, class);
+ ip.m_addr = addr;
+ ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
+ hash_str(class, IP_HASHBITS) ^
+ hash_ip((unsigned long)addr.s_addr));
+
+ if (ch)
+ return container_of(ch, struct ip_map, h);
+ else
+ return NULL;
+}
+static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry)
+{
+ struct ip_map ip;
+ struct cache_head *ch;
+
+ ip.m_client = udom;
+ ip.h.flags = 0;
+ if (!udom)
+ set_bit(CACHE_NEGATIVE, &ip.h.flags);
+ else {
+ ip.m_add_change = udom->addr_changes;
+ /* if this is from the legacy set_client system call,
+ * we need m_add_change to be one higher
+ */
+ if (expiry == NEVER)
+ ip.m_add_change++;
+ }
+ ip.h.expiry_time = expiry;
+ ch = sunrpc_cache_update(&ip_map_cache,
+ &ip.h, &ipm->h,
+ hash_str(ipm->m_class, IP_HASHBITS) ^
+ hash_ip((unsigned long)ipm->m_addr.s_addr));
+ if (!ch)
+ return -ENOMEM;
+ cache_put(ch, &ip_map_cache);
+ return 0;
+}
int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
{
struct unix_domain *udom;
- struct ip_map ip, *ipmp;
+ struct ip_map *ipmp;
- if (dom->flavour != RPC_AUTH_UNIX)
+ if (dom->flavour != &svcauth_unix)
return -EINVAL;
udom = container_of(dom, struct unix_domain, h);
- strcpy(ip.m_class, "nfsd");
- ip.m_addr = addr;
- ip.m_client = udom;
- ip.m_add_change = udom->addr_changes+1;
- ip.h.flags = 0;
- ip.h.expiry_time = NEVER;
-
- ipmp = ip_map_lookup(&ip, 1);
+ ipmp = ip_map_lookup("nfsd", addr);
- if (ipmp) {
- ip_map_put(&ipmp->h, &ip_map_cache);
- return 0;
- } else
+ if (ipmp)
+ return ip_map_update(ipmp, udom, NEVER);
+ else
return -ENOMEM;
}
@@ -295,7 +339,7 @@ int auth_unix_forget_old(struct auth_domain *dom)
{
struct unix_domain *udom;
- if (dom->flavour != RPC_AUTH_UNIX)
+ if (dom->flavour != &svcauth_unix)
return -EINVAL;
udom = container_of(dom, struct unix_domain, h);
udom->addr_changes++;
@@ -310,7 +354,7 @@ struct auth_domain *auth_unix_lookup(struct in_addr addr)
strcpy(key.m_class, "nfsd");
key.m_addr = addr;
- ipm = ip_map_lookup(&key, 0);
+ ipm = ip_map_lookup("nfsd", addr);
if (!ipm)
return NULL;
@@ -323,31 +367,28 @@ struct auth_domain *auth_unix_lookup(struct in_addr addr)
rv = NULL;
} else {
rv = &ipm->m_client->h;
- cache_get(&rv->h);
+ kref_get(&rv->ref);
}
- ip_map_put(&ipm->h, &ip_map_cache);
+ cache_put(&ipm->h, &ip_map_cache);
return rv;
}
void svcauth_unix_purge(void)
{
cache_purge(&ip_map_cache);
- cache_purge(&auth_domain_cache);
}
static int
svcauth_unix_set_client(struct svc_rqst *rqstp)
{
- struct ip_map key, *ipm;
+ struct ip_map *ipm;
rqstp->rq_client = NULL;
if (rqstp->rq_proc == 0)
return SVC_OK;
- strcpy(key.m_class, rqstp->rq_server->sv_program->pg_class);
- key.m_addr = rqstp->rq_addr.sin_addr;
-
- ipm = ip_map_lookup(&key, 0);
+ ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
+ rqstp->rq_addr.sin_addr);
if (ipm == NULL)
return SVC_DENIED;
@@ -361,8 +402,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
return SVC_DENIED;
case 0:
rqstp->rq_client = &ipm->m_client->h;
- cache_get(&rqstp->rq_client->h);
- ip_map_put(&ipm->h, &ip_map_cache);
+ kref_get(&rqstp->rq_client->ref);
+ cache_put(&ipm->h, &ip_map_cache);
break;
}
return SVC_OK;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 8ff2c8acb22..4dd5b3cfe75 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -44,13 +44,13 @@
#include <linux/random.h>
#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/metrics.h>
/*
* Local variables
*/
#ifdef RPC_DEBUG
-# undef RPC_DEBUG_DATA
# define RPCDBG_FACILITY RPCDBG_XPRT
#endif
@@ -548,6 +548,7 @@ void xprt_connect(struct rpc_task *task)
task->tk_timeout = xprt->connect_timeout;
rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
+ xprt->stat.connect_start = jiffies;
xprt->ops->connect(task);
}
return;
@@ -558,6 +559,8 @@ static void xprt_connect_status(struct rpc_task *task)
struct rpc_xprt *xprt = task->tk_xprt;
if (task->tk_status >= 0) {
+ xprt->stat.connect_count++;
+ xprt->stat.connect_time += (long)jiffies - xprt->stat.connect_start;
dprintk("RPC: %4d xprt_connect_status: connection established\n",
task->tk_pid);
return;
@@ -601,16 +604,14 @@ static void xprt_connect_status(struct rpc_task *task)
struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
{
struct list_head *pos;
- struct rpc_rqst *req = NULL;
list_for_each(pos, &xprt->recv) {
struct rpc_rqst *entry = list_entry(pos, struct rpc_rqst, rq_list);
- if (entry->rq_xid == xid) {
- req = entry;
- break;
- }
+ if (entry->rq_xid == xid)
+ return entry;
}
- return req;
+ xprt->stat.bad_xids++;
+ return NULL;
}
/**
@@ -646,7 +647,12 @@ void xprt_complete_rqst(struct rpc_task *task, int copied)
dprintk("RPC: %5u xid %08x complete (%d bytes received)\n",
task->tk_pid, ntohl(req->rq_xid), copied);
+ task->tk_xprt->stat.recvs++;
+ task->tk_rtt = (long)jiffies - req->rq_xtime;
+
list_del_init(&req->rq_list);
+ /* Ensure all writes are done before we update req->rq_received */
+ smp_wmb();
req->rq_received = req->rq_private_buf.len = copied;
rpc_wake_up_task(task);
}
@@ -723,7 +729,6 @@ void xprt_transmit(struct rpc_task *task)
dprintk("RPC: %4d xprt_transmit(%u)\n", task->tk_pid, req->rq_slen);
- smp_rmb();
if (!req->rq_received) {
if (list_empty(&req->rq_list)) {
spin_lock_bh(&xprt->transport_lock);
@@ -744,12 +749,19 @@ void xprt_transmit(struct rpc_task *task)
if (status == 0) {
dprintk("RPC: %4d xmit complete\n", task->tk_pid);
spin_lock_bh(&xprt->transport_lock);
+
xprt->ops->set_retrans_timeout(task);
+
+ xprt->stat.sends++;
+ xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs;
+ xprt->stat.bklog_u += xprt->backlog.qlen;
+
/* Don't race with disconnect */
if (!xprt_connected(xprt))
task->tk_status = -ENOTCONN;
else if (!req->rq_received)
rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
+
xprt->ops->release_xprt(xprt, task);
spin_unlock_bh(&xprt->transport_lock);
return;
@@ -848,6 +860,7 @@ void xprt_release(struct rpc_task *task)
if (!(req = task->tk_rqstp))
return;
+ rpc_count_iostats(task);
spin_lock_bh(&xprt->transport_lock);
xprt->ops->release_xprt(xprt, task);
if (xprt->ops->release_request)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index c458f8d1d6d..4b4e7dfdff1 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -382,6 +382,7 @@ static int xs_tcp_send_request(struct rpc_task *task)
/* If we've sent the entire packet, immediately
* reset the count of bytes sent. */
req->rq_bytes_sent += status;
+ task->tk_bytes_sent += status;
if (likely(req->rq_bytes_sent >= req->rq_slen)) {
req->rq_bytes_sent = 0;
return 0;
@@ -1114,6 +1115,8 @@ static void xs_tcp_connect_worker(void *args)
}
/* Tell the socket layer to start connecting... */
+ xprt->stat.connect_count++;
+ xprt->stat.connect_start = jiffies;
status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
sizeof(xprt->addr), O_NONBLOCK);
dprintk("RPC: %p connect status %d connected %d sock state %d\n",
@@ -1177,6 +1180,50 @@ static void xs_connect(struct rpc_task *task)
}
}
+/**
+ * xs_udp_print_stats - display UDP socket-specifc stats
+ * @xprt: rpc_xprt struct containing statistics
+ * @seq: output file
+ *
+ */
+static void xs_udp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
+{
+ seq_printf(seq, "\txprt:\tudp %u %lu %lu %lu %lu %Lu %Lu\n",
+ xprt->port,
+ xprt->stat.bind_count,
+ xprt->stat.sends,
+ xprt->stat.recvs,
+ xprt->stat.bad_xids,
+ xprt->stat.req_u,
+ xprt->stat.bklog_u);
+}
+
+/**
+ * xs_tcp_print_stats - display TCP socket-specifc stats
+ * @xprt: rpc_xprt struct containing statistics
+ * @seq: output file
+ *
+ */
+static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
+{
+ long idle_time = 0;
+
+ if (xprt_connected(xprt))
+ idle_time = (long)(jiffies - xprt->last_used) / HZ;
+
+ seq_printf(seq, "\txprt:\ttcp %u %lu %lu %lu %ld %lu %lu %lu %Lu %Lu\n",
+ xprt->port,
+ xprt->stat.bind_count,
+ xprt->stat.connect_count,
+ xprt->stat.connect_time,
+ idle_time,
+ xprt->stat.sends,
+ xprt->stat.recvs,
+ xprt->stat.bad_xids,
+ xprt->stat.req_u,
+ xprt->stat.bklog_u);
+}
+
static struct rpc_xprt_ops xs_udp_ops = {
.set_buffer_size = xs_udp_set_buffer_size,
.reserve_xprt = xprt_reserve_xprt_cong,
@@ -1191,6 +1238,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
.release_request = xprt_release_rqst_cong,
.close = xs_close,
.destroy = xs_destroy,
+ .print_stats = xs_udp_print_stats,
};
static struct rpc_xprt_ops xs_tcp_ops = {
@@ -1204,6 +1252,7 @@ static struct rpc_xprt_ops xs_tcp_ops = {
.set_retrans_timeout = xprt_set_retrans_timeout_def,
.close = xs_close,
.destroy = xs_destroy,
+ .print_stats = xs_tcp_print_stats,
};
/**
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 2b4cc2eea5b..d901465ce01 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1878,6 +1878,8 @@ static unsigned int unix_poll(struct file * file, struct socket *sock, poll_tabl
mask |= POLLERR;
if (sk->sk_shutdown == SHUTDOWN_MASK)
mask |= POLLHUP;
+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ mask |= POLLRDHUP;
/* readable? */
if (!skb_queue_empty(&sk->sk_receive_queue) ||
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 0168d6c3707..59620b1554e 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -44,6 +44,43 @@ define filechk
fi
endef
+######
+# gcc support functions
+# See documentation in Documentation/kbuild/makefiles.txt
+
+# as-option
+# Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,)
+
+as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
+ -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \
+ else echo "$(2)"; fi ;)
+
+# cc-option
+# Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
+
+cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
+ > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
+
+# cc-option-yn
+# Usage: flag := $(call cc-option-yn, -march=winchip-c6)
+cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
+ > /dev/null 2>&1; then echo "y"; else echo "n"; fi;)
+
+# cc-option-align
+# Prefix align with either -falign or -malign
+cc-option-align = $(subst -functions=0,,\
+ $(call cc-option,-falign-functions=0,-malign-functions=0))
+
+# cc-version
+# Usage gcc-ver := $(call cc-version, $(CC))
+cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
+ $(if $(1), $(1), $(CC)))
+
+# cc-ifversion
+# Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
+cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \
+ echo $(3); fi;)
+
###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
# Usage:
@@ -51,8 +88,7 @@ endef
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
# If quiet is set, only print short version of command
-cmd = @$(if $($(quiet)cmd_$(1)),\
- echo ' $(call escsq,$($(quiet)cmd_$(1)))' &&) $(cmd_$(1))
+cmd = @$(echo-cmd) $(cmd_$(1))
# Add $(obj)/ for paths that is not absolute
objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
@@ -75,30 +111,33 @@ endif
echo-cmd = $(if $($(quiet)cmd_$(1)), \
echo ' $(call escsq,$($(quiet)cmd_$(1)))';)
+make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
+
# function to only execute the passed command if necessary
# >'< substitution is for echo to work, >$< substitution to preserve $ when reloading .cmd file
# note: when using inline perl scripts [perl -e '...$$t=1;...'] in $(cmd_xxx) double $$ your perl vars
-#
-if_changed = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
+#
+if_changed = $(if $(strip $(filter-out $(PHONY),$?) \
+ $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
@set -e; \
- $(echo-cmd) \
- $(cmd_$(1)); \
- echo 'cmd_$@ := $(subst $$,$$$$,$(call escsq,$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
+ $(echo-cmd) $(cmd_$(1)); \
+ echo 'cmd_$@ := $(make-cmd)' > $(@D)/.$(@F).cmd)
# execute the command and also postprocess generated .d dependencies
# file
-if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
- $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
+if_changed_dep = $(if $(strip $(filter-out $(PHONY),$?) \
+ $(filter-out FORCE $(wildcard $^),$^) \
+ $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
@set -e; \
- $(echo-cmd) \
- $(cmd_$(1)); \
- scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
+ $(echo-cmd) $(cmd_$(1)); \
+ scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(@D)/.$(@F).tmp; \
rm -f $(depfile); \
mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
# Usage: $(call if_changed_rule,foo)
# will check if $(cmd_foo) changed, or any of the prequisites changed,
# and if so will execute $(rule_foo)
-if_changed_rule = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
+if_changed_rule = $(if $(strip $(filter-out $(PHONY),$?) \
+ $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
@set -e; \
$(rule_$(1)))
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index c33e62bde6b..e48e60da304 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -4,17 +4,18 @@
src := $(obj)
-.PHONY: __build
+PHONY := __build
__build:
# Read .config if it exist, otherwise ignore
-include .config
+include scripts/Kbuild.include
+
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
-include scripts/Kbuild.include
include scripts/Makefile.lib
ifdef host-progs
@@ -128,7 +129,7 @@ $(multi-objs-y:.o=.s) : modname = $(modname-multi)
$(multi-objs-y:.o=.lst) : modname = $(modname-multi)
quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
-cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $<
+cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
%.s: %.c FORCE
$(call if_changed_dep,cc_s_c)
@@ -165,7 +166,7 @@ cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
cmd_modversions = \
if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
$(CPP) -D__GENKSYMS__ $(c_flags) $< \
- | $(GENKSYMS) \
+ | $(GENKSYMS) -a $(ARCH) \
> $(@D)/.tmp_$(@F:.o=.ver); \
\
$(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
@@ -177,12 +178,10 @@ cmd_modversions = \
endif
define rule_cc_o_c
- $(if $($(quiet)cmd_checksrc),echo ' $($(quiet)cmd_checksrc)';) \
- $(cmd_checksrc) \
- $(if $($(quiet)cmd_cc_o_c),echo ' $(call escsq,$($(quiet)cmd_cc_o_c))';) \
- $(cmd_cc_o_c); \
+ $(call echo-cmd,checksrc) $(cmd_checksrc) \
+ $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \
$(cmd_modversions) \
- scripts/basic/fixdep $(depfile) $@ '$(call escsq,$(cmd_cc_o_c))' > $(@D)/.$(@F).tmp; \
+ scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > $(@D)/.$(@F).tmp; \
rm -f $(depfile); \
mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd
endef
@@ -309,14 +308,14 @@ targets += $(multi-used-y) $(multi-used-m)
# Descending
# ---------------------------------------------------------------------------
-.PHONY: $(subdir-ym)
+PHONY += $(subdir-ym)
$(subdir-ym):
$(Q)$(MAKE) $(build)=$@
# Add FORCE to the prequisites of a target to force it to be always rebuilt.
# ---------------------------------------------------------------------------
-.PHONY: FORCE
+PHONY += FORCE
FORCE:
@@ -331,3 +330,9 @@ cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
ifneq ($(cmd_files),)
include $(cmd_files)
endif
+
+
+# Declare the contents of the .PHONY variable as phony. We keep that
+# information in a variable se we can use it in if_changed and friends.
+
+.PHONY: $(PHONY)
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index 8974ea5fc87..cff33498fa1 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -4,7 +4,7 @@
src := $(obj)
-.PHONY: __clean
+PHONY := __clean
__clean:
# Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir
@@ -87,10 +87,16 @@ endif
# Descending
# ---------------------------------------------------------------------------
-.PHONY: $(subdir-ymn)
+PHONY += $(subdir-ymn)
$(subdir-ymn):
$(Q)$(MAKE) $(clean)=$@
# If quiet is set, only print short version of command
cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1))
+
+
+# Declare the contents of the .PHONY variable as phony. We keep that
+# information in a variable se we can use it in if_changed and friends.
+
+.PHONY: $(PHONY)
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index 23fd1bdc25c..2686dd5dce8 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -2,7 +2,7 @@
# Installing modules
# ==========================================================================
-.PHONY: __modinst
+PHONY := __modinst
__modinst:
include scripts/Kbuild.include
@@ -12,7 +12,7 @@ include scripts/Kbuild.include
__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
-.PHONY: $(modules)
+PHONY += $(modules)
__modinst: $(modules)
@:
@@ -27,3 +27,9 @@ modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D))
$(modules):
$(call cmd,modules_install,$(MODLIB)/$(modinst_dir))
+
+
+# Declare the contents of the .PHONY variable as phony. We keep that
+# information in a variable se we can use it in if_changed and friends.
+
+.PHONY: $(PHONY)
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index bf96a61d4b8..0e056cffffd 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -4,7 +4,7 @@
#
# Stage one of module building created the following:
# a) The individual .o files used for the module
-# b) A <module>.o file wich is the .o files above linked together
+# b) A <module>.o file which is the .o files above linked together
# c) A <module>.mod file in $(MODVERDIR)/, listing the name of the
# the preliminary <module>.o file, plus all .o files
@@ -32,14 +32,15 @@
# Step 4 is solely used to allow module versioning in external modules,
# where the CRC of each module is retrieved from the Module.symers file.
-.PHONY: _modpost
+PHONY := _modpost
_modpost: __modpost
include .config
include scripts/Kbuild.include
include scripts/Makefile.lib
-symverfile := $(objtree)/Module.symvers
+kernelsymfile := $(objtree)/Module.symvers
+modulesymfile := $(KBUILD_EXTMOD)/Modules.symvers
# Step 1), find all modules listed in $(MODVERDIR)/
__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
@@ -54,10 +55,12 @@ quiet_cmd_modpost = MODPOST
cmd_modpost = scripts/mod/modpost \
$(if $(CONFIG_MODVERSIONS),-m) \
$(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \
- $(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \
+ $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
+ $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
+ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
$(filter-out FORCE,$^)
-.PHONY: __modpost
+PHONY += __modpost
__modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE
$(call cmd,modpost)
@@ -94,7 +97,7 @@ targets += $(modules)
# Add FORCE to the prequisites of a target to force it to be always rebuilt.
# ---------------------------------------------------------------------------
-.PHONY: FORCE
+PHONY += FORCE
FORCE:
@@ -109,3 +112,9 @@ cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
ifneq ($(cmd_files),)
include $(cmd_files)
endif
+
+
+# Declare the contents of the .PHONY variable as phony. We keep that
+# information in a variable se we can use it in if_changed and friends.
+
+.PHONY: $(PHONY)
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index 679124b11e1..668a11a8b38 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -132,20 +132,10 @@ void usage(void)
/*
* Print out the commandline prefixed with cmd_<target filename> :=
- * If commandline contains '#' escape with '\' so make to not see
- * the '#' as a start-of-comment symbol
- **/
+ */
void print_cmdline(void)
{
- char *p = cmdline;
-
- printf("cmd_%s := ", target);
- for (; *p; p++) {
- if (*p == '#')
- printf("\\");
- printf("%c", *p);
- }
- printf("\n\n");
+ printf("cmd_%s := %s\n\n", target, cmdline);
}
char * str_config = NULL;
diff --git a/scripts/checkconfig.pl b/scripts/checkconfig.pl
deleted file mode 100755
index ca1f231b15a..00000000000
--- a/scripts/checkconfig.pl
+++ /dev/null
@@ -1,65 +0,0 @@
-#! /usr/bin/perl
-#
-# checkconfig: find uses of CONFIG_* names without matching definitions.
-# Copyright abandoned, 1998, Michael Elizabeth Chastain <mailto:mec@shout.net>.
-
-use integer;
-
-$| = 1;
-
-foreach $file (@ARGV)
-{
- # Open this file.
- open(FILE, $file) || die "Can't open $file: $!\n";
-
- # Initialize variables.
- my $fInComment = 0;
- my $fInString = 0;
- my $fUseConfig = 0;
- my $iLinuxConfig = 0;
- my %configList = ();
-
- LINE: while ( <FILE> )
- {
- # Strip comments.
- $fInComment && (s+^.*?\*/+ +o ? ($fInComment = 0) : next);
- m+/\*+o && (s+/\*.*?\*/+ +go, (s+/\*.*$+ +o && ($fInComment = 1)));
-
- # Pick up definitions.
- if ( m/^\s*#/o )
- {
- $iLinuxConfig = $. if m/^\s*#\s*include\s*"linux\/config\.h"/o;
- $configList{uc $1} = 1 if m/^\s*#\s*include\s*"config\/(\S*)\.h"/o;
- }
-
- # Strip strings.
- $fInString && (s+^.*?"+ +o ? ($fInString = 0) : next);
- m+"+o && (s+".*?"+ +go, (s+".*$+ +o && ($fInString = 1)));
-
- # Pick up definitions.
- if ( m/^\s*#/o )
- {
- $iLinuxConfig = $. if m/^\s*#\s*include\s*<linux\/config\.h>/o;
- $configList{uc $1} = 1 if m/^\s*#\s*include\s*<config\/(\S*)\.h>/o;
- $configList{$1} = 1 if m/^\s*#\s*define\s+CONFIG_(\w*)/o;
- $configList{$1} = 1 if m/^\s*#\s*undef\s+CONFIG_(\w*)/o;
- }
-
- # Look for usages.
- next unless m/CONFIG_/o;
- WORD: while ( m/\bCONFIG_(\w+)/og )
- {
- $fUseConfig = 1;
- last LINE if $iLinuxConfig;
- next WORD if exists $configList{$1};
- print "$file: $.: need CONFIG_$1.\n";
- $configList{$1} = 0;
- }
- }
-
- # Report superfluous includes.
- if ( $iLinuxConfig && ! $fUseConfig )
- { print "$file: $iLinuxConfig: linux/config.h not needed.\n"; }
-
- close(FILE);
-}
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index 416a694b099..5b0344e20d6 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -29,481 +29,421 @@
#include <stdarg.h>
#ifdef __GNU_LIBRARY__
#include <getopt.h>
-#endif /* __GNU_LIBRARY__ */
+#endif /* __GNU_LIBRARY__ */
#include "genksyms.h"
-
/*----------------------------------------------------------------------*/
#define HASH_BUCKETS 4096
static struct symbol *symtab[HASH_BUCKETS];
-FILE *debugfile;
+static FILE *debugfile;
int cur_line = 1;
-char *cur_filename, *output_directory;
+char *cur_filename;
-int flag_debug, flag_dump_defs, flag_warnings;
+static int flag_debug, flag_dump_defs, flag_warnings;
+static const char *arch = "";
+static const char *mod_prefix = "";
static int errors;
static int nsyms;
static struct symbol *expansion_trail;
-static const char * const symbol_type_name[] = {
- "normal", "typedef", "enum", "struct", "union"
+static const char *const symbol_type_name[] = {
+ "normal", "typedef", "enum", "struct", "union"
};
+static int equal_list(struct string_list *a, struct string_list *b);
+static void print_list(FILE * f, struct string_list *list);
+
/*----------------------------------------------------------------------*/
-static const unsigned int crctab32[] =
-{
- 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
- 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
- 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
- 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
- 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
- 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
- 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
- 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
- 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
- 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
- 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
- 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
- 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
- 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
- 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
- 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
- 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
- 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
- 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
- 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
- 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
- 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
- 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
- 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
- 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
- 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
- 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
- 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
- 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
- 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
- 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
- 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
- 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
- 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
- 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
- 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
- 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
- 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
- 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
- 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
- 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
- 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
- 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
- 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
- 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
- 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
- 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
- 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
- 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
- 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
- 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
- 0x2d02ef8dU
+static const unsigned int crctab32[] = {
+ 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
+ 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
+ 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
+ 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
+ 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
+ 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
+ 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
+ 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
+ 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
+ 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
+ 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
+ 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
+ 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
+ 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
+ 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
+ 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
+ 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
+ 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
+ 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
+ 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
+ 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
+ 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
+ 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
+ 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
+ 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
+ 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
+ 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
+ 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
+ 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
+ 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
+ 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
+ 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
+ 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
+ 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
+ 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
+ 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
+ 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
+ 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
+ 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
+ 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
+ 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
+ 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
+ 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
+ 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
+ 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
+ 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
+ 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
+ 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
+ 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
+ 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
+ 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
+ 0x2d02ef8dU
};
-static inline unsigned long
-partial_crc32_one(unsigned char c, unsigned long crc)
+static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
{
- return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
+ return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
}
-static inline unsigned long
-partial_crc32(const char *s, unsigned long crc)
+static unsigned long partial_crc32(const char *s, unsigned long crc)
{
- while (*s)
- crc = partial_crc32_one(*s++, crc);
- return crc;
+ while (*s)
+ crc = partial_crc32_one(*s++, crc);
+ return crc;
}
-static inline unsigned long
-crc32(const char *s)
+static unsigned long crc32(const char *s)
{
- return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
+ return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
}
-
/*----------------------------------------------------------------------*/
-static inline enum symbol_type
-map_to_ns(enum symbol_type t)
+static enum symbol_type map_to_ns(enum symbol_type t)
{
- if (t == SYM_TYPEDEF)
- t = SYM_NORMAL;
- else if (t == SYM_UNION)
- t = SYM_STRUCT;
- return t;
+ if (t == SYM_TYPEDEF)
+ t = SYM_NORMAL;
+ else if (t == SYM_UNION)
+ t = SYM_STRUCT;
+ return t;
}
-struct symbol *
-find_symbol(const char *name, enum symbol_type ns)
+struct symbol *find_symbol(const char *name, enum symbol_type ns)
{
- unsigned long h = crc32(name) % HASH_BUCKETS;
- struct symbol *sym;
+ unsigned long h = crc32(name) % HASH_BUCKETS;
+ struct symbol *sym;
- for (sym = symtab[h]; sym ; sym = sym->hash_next)
- if (map_to_ns(sym->type) == map_to_ns(ns) && strcmp(name, sym->name) == 0)
- break;
+ for (sym = symtab[h]; sym; sym = sym->hash_next)
+ if (map_to_ns(sym->type) == map_to_ns(ns) &&
+ strcmp(name, sym->name) == 0)
+ break;
- return sym;
+ return sym;
}
-struct symbol *
-add_symbol(const char *name, enum symbol_type type, struct string_list *defn, int is_extern)
+struct symbol *add_symbol(const char *name, enum symbol_type type,
+ struct string_list *defn, int is_extern)
{
- unsigned long h = crc32(name) % HASH_BUCKETS;
- struct symbol *sym;
-
- for (sym = symtab[h]; sym ; sym = sym->hash_next)
- if (map_to_ns(sym->type) == map_to_ns(type)
- && strcmp(name, sym->name) == 0)
- {
- if (!equal_list(sym->defn, defn))
- error_with_pos("redefinition of %s", name);
+ unsigned long h = crc32(name) % HASH_BUCKETS;
+ struct symbol *sym;
+
+ for (sym = symtab[h]; sym; sym = sym->hash_next) {
+ if (map_to_ns(sym->type) == map_to_ns(type)
+ && strcmp(name, sym->name) == 0) {
+ if (!equal_list(sym->defn, defn))
+ error_with_pos("redefinition of %s", name);
+ return sym;
+ }
+ }
+
+ sym = xmalloc(sizeof(*sym));
+ sym->name = name;
+ sym->type = type;
+ sym->defn = defn;
+ sym->expansion_trail = NULL;
+ sym->is_extern = is_extern;
+
+ sym->hash_next = symtab[h];
+ symtab[h] = sym;
+
+ if (flag_debug) {
+ fprintf(debugfile, "Defn for %s %s == <",
+ symbol_type_name[type], name);
+ if (is_extern)
+ fputs("extern ", debugfile);
+ print_list(debugfile, defn);
+ fputs(">\n", debugfile);
+ }
+
+ ++nsyms;
return sym;
- }
-
- sym = xmalloc(sizeof(*sym));
- sym->name = name;
- sym->type = type;
- sym->defn = defn;
- sym->expansion_trail = NULL;
- sym->is_extern = is_extern;
-
- sym->hash_next = symtab[h];
- symtab[h] = sym;
-
- if (flag_debug)
- {
- fprintf(debugfile, "Defn for %s %s == <", symbol_type_name[type], name);
- if (is_extern)
- fputs("extern ", debugfile);
- print_list(debugfile, defn);
- fputs(">\n", debugfile);
- }
-
- ++nsyms;
- return sym;
}
-
/*----------------------------------------------------------------------*/
-inline void
-free_node(struct string_list *node)
+void free_node(struct string_list *node)
{
- free(node->string);
- free(node);
+ free(node->string);
+ free(node);
}
-void
-free_list(struct string_list *s, struct string_list *e)
+void free_list(struct string_list *s, struct string_list *e)
{
- while (s != e)
- {
- struct string_list *next = s->next;
- free_node(s);
- s = next;
- }
+ while (s != e) {
+ struct string_list *next = s->next;
+ free_node(s);
+ s = next;
+ }
}
-inline struct string_list *
-copy_node(struct string_list *node)
+struct string_list *copy_node(struct string_list *node)
{
- struct string_list *newnode;
+ struct string_list *newnode;
- newnode = xmalloc(sizeof(*newnode));
- newnode->string = xstrdup(node->string);
- newnode->tag = node->tag;
+ newnode = xmalloc(sizeof(*newnode));
+ newnode->string = xstrdup(node->string);
+ newnode->tag = node->tag;
- return newnode;
+ return newnode;
}
-struct string_list *
-copy_list(struct string_list *s, struct string_list *e)
+static int equal_list(struct string_list *a, struct string_list *b)
{
- struct string_list *h, *p;
-
- if (s == e)
- return NULL;
-
- p = h = copy_node(s);
- while ((s = s->next) != e)
- p = p->next = copy_node(s);
- p->next = NULL;
-
- return h;
-}
+ while (a && b) {
+ if (a->tag != b->tag || strcmp(a->string, b->string))
+ return 0;
+ a = a->next;
+ b = b->next;
+ }
-int
-equal_list(struct string_list *a, struct string_list *b)
-{
- while (a && b)
- {
- if (a->tag != b->tag || strcmp(a->string, b->string))
- return 0;
- a = a->next;
- b = b->next;
- }
-
- return !a && !b;
+ return !a && !b;
}
-static inline void
-print_node(FILE *f, struct string_list *list)
+static void print_node(FILE * f, struct string_list *list)
{
- switch (list->tag)
- {
- case SYM_STRUCT:
- putc('s', f);
- goto printit;
- case SYM_UNION:
- putc('u', f);
- goto printit;
- case SYM_ENUM:
- putc('e', f);
- goto printit;
- case SYM_TYPEDEF:
- putc('t', f);
- goto printit;
-
- printit:
- putc('#', f);
- case SYM_NORMAL:
- fputs(list->string, f);
- break;
- }
-}
+ switch (list->tag) {
+ case SYM_STRUCT:
+ putc('s', f);
+ goto printit;
+ case SYM_UNION:
+ putc('u', f);
+ goto printit;
+ case SYM_ENUM:
+ putc('e', f);
+ goto printit;
+ case SYM_TYPEDEF:
+ putc('t', f);
+ goto printit;
-void
-print_list(FILE *f, struct string_list *list)
-{
- struct string_list **e, **b;
- struct string_list *tmp, **tmp2;
- int elem = 1;
-
- if (list == NULL)
- {
- fputs("(nil)", f);
- return;
- }
-
- tmp = list;
- while((tmp = tmp->next) != NULL)
- elem++;
-
- b = alloca(elem * sizeof(*e));
- e = b + elem;
- tmp2 = e - 1;
-
- (*tmp2--) = list;
- while((list = list->next) != NULL)
- *(tmp2--) = list;
-
- while (b != e)
- {
- print_node(f, *b++);
- putc(' ', f);
- }
+ printit:
+ putc('#', f);
+ case SYM_NORMAL:
+ fputs(list->string, f);
+ break;
+ }
}
-static unsigned long
-expand_and_crc_list(struct string_list *list, unsigned long crc)
+static void print_list(FILE * f, struct string_list *list)
{
- struct string_list **e, **b;
- struct string_list *tmp, **tmp2;
- int elem = 1;
-
- if (!list)
- return crc;
+ struct string_list **e, **b;
+ struct string_list *tmp, **tmp2;
+ int elem = 1;
- tmp = list;
- while((tmp = tmp->next) != NULL)
- elem++;
-
- b = alloca(elem * sizeof(*e));
- e = b + elem;
- tmp2 = e - 1;
+ if (list == NULL) {
+ fputs("(nil)", f);
+ return;
+ }
- *(tmp2--) = list;
- while ((list = list->next) != NULL)
- *(tmp2--) = list;
+ tmp = list;
+ while ((tmp = tmp->next) != NULL)
+ elem++;
- while (b != e)
- {
- struct string_list *cur;
- struct symbol *subsym;
+ b = alloca(elem * sizeof(*e));
+ e = b + elem;
+ tmp2 = e - 1;
- cur = *(b++);
- switch (cur->tag)
- {
- case SYM_NORMAL:
- if (flag_dump_defs)
- fprintf(debugfile, "%s ", cur->string);
- crc = partial_crc32(cur->string, crc);
- crc = partial_crc32_one(' ', crc);
- break;
+ (*tmp2--) = list;
+ while ((list = list->next) != NULL)
+ *(tmp2--) = list;
- case SYM_TYPEDEF:
- subsym = find_symbol(cur->string, cur->tag);
- if (subsym->expansion_trail)
- {
- if (flag_dump_defs)
- fprintf(debugfile, "%s ", cur->string);
- crc = partial_crc32(cur->string, crc);
- crc = partial_crc32_one(' ', crc);
- }
- else
- {
- subsym->expansion_trail = expansion_trail;
- expansion_trail = subsym;
- crc = expand_and_crc_list(subsym->defn, crc);
- }
- break;
+ while (b != e) {
+ print_node(f, *b++);
+ putc(' ', f);
+ }
+}
- case SYM_STRUCT:
- case SYM_UNION:
- case SYM_ENUM:
- subsym = find_symbol(cur->string, cur->tag);
- if (!subsym)
- {
- struct string_list *n, *t = NULL;
-
- error_with_pos("expand undefined %s %s",
- symbol_type_name[cur->tag], cur->string);
-
- n = xmalloc(sizeof(*n));
- n->string = xstrdup(symbol_type_name[cur->tag]);
- n->tag = SYM_NORMAL;
- n->next = t;
- t = n;
-
- n = xmalloc(sizeof(*n));
- n->string = xstrdup(cur->string);
- n->tag = SYM_NORMAL;
- n->next = t;
- t = n;
-
- n = xmalloc(sizeof(*n));
- n->string = xstrdup("{ UNKNOWN }");
- n->tag = SYM_NORMAL;
- n->next = t;
-
- subsym = add_symbol(cur->string, cur->tag, n, 0);
- }
- if (subsym->expansion_trail)
- {
- if (flag_dump_defs)
- {
- fprintf(debugfile, "%s %s ", symbol_type_name[cur->tag],
- cur->string);
+static unsigned long expand_and_crc_list(struct string_list *list,
+ unsigned long crc)
+{
+ struct string_list **e, **b;
+ struct string_list *tmp, **tmp2;
+ int elem = 1;
+
+ if (!list)
+ return crc;
+
+ tmp = list;
+ while ((tmp = tmp->next) != NULL)
+ elem++;
+
+ b = alloca(elem * sizeof(*e));
+ e = b + elem;
+ tmp2 = e - 1;
+
+ *(tmp2--) = list;
+ while ((list = list->next) != NULL)
+ *(tmp2--) = list;
+
+ while (b != e) {
+ struct string_list *cur;
+ struct symbol *subsym;
+
+ cur = *(b++);
+ switch (cur->tag) {
+ case SYM_NORMAL:
+ if (flag_dump_defs)
+ fprintf(debugfile, "%s ", cur->string);
+ crc = partial_crc32(cur->string, crc);
+ crc = partial_crc32_one(' ', crc);
+ break;
+
+ case SYM_TYPEDEF:
+ subsym = find_symbol(cur->string, cur->tag);
+ if (subsym->expansion_trail) {
+ if (flag_dump_defs)
+ fprintf(debugfile, "%s ", cur->string);
+ crc = partial_crc32(cur->string, crc);
+ crc = partial_crc32_one(' ', crc);
+ } else {
+ subsym->expansion_trail = expansion_trail;
+ expansion_trail = subsym;
+ crc = expand_and_crc_list(subsym->defn, crc);
+ }
+ break;
+
+ case SYM_STRUCT:
+ case SYM_UNION:
+ case SYM_ENUM:
+ subsym = find_symbol(cur->string, cur->tag);
+ if (!subsym) {
+ struct string_list *n, *t = NULL;
+
+ error_with_pos("expand undefined %s %s",
+ symbol_type_name[cur->tag],
+ cur->string);
+
+ n = xmalloc(sizeof(*n));
+ n->string = xstrdup(symbol_type_name[cur->tag]);
+ n->tag = SYM_NORMAL;
+ n->next = t;
+ t = n;
+
+ n = xmalloc(sizeof(*n));
+ n->string = xstrdup(cur->string);
+ n->tag = SYM_NORMAL;
+ n->next = t;
+ t = n;
+
+ n = xmalloc(sizeof(*n));
+ n->string = xstrdup("{ UNKNOWN }");
+ n->tag = SYM_NORMAL;
+ n->next = t;
+
+ subsym =
+ add_symbol(cur->string, cur->tag, n, 0);
+ }
+ if (subsym->expansion_trail) {
+ if (flag_dump_defs) {
+ fprintf(debugfile, "%s %s ",
+ symbol_type_name[cur->tag],
+ cur->string);
+ }
+
+ crc = partial_crc32(symbol_type_name[cur->tag],
+ crc);
+ crc = partial_crc32_one(' ', crc);
+ crc = partial_crc32(cur->string, crc);
+ crc = partial_crc32_one(' ', crc);
+ } else {
+ subsym->expansion_trail = expansion_trail;
+ expansion_trail = subsym;
+ crc = expand_and_crc_list(subsym->defn, crc);
+ }
+ break;
}
-
- crc = partial_crc32(symbol_type_name[cur->tag], crc);
- crc = partial_crc32_one(' ', crc);
- crc = partial_crc32(cur->string, crc);
- crc = partial_crc32_one(' ', crc);
- }
- else
- {
- subsym->expansion_trail = expansion_trail;
- expansion_trail = subsym;
- crc = expand_and_crc_list(subsym->defn, crc);
- }
- break;
}
- }
- return crc;
+ return crc;
}
-void
-export_symbol(const char *name)
+void export_symbol(const char *name)
{
- struct symbol *sym;
+ struct symbol *sym;
- sym = find_symbol(name, SYM_NORMAL);
- if (!sym)
- error_with_pos("export undefined symbol %s", name);
- else
- {
- unsigned long crc;
+ sym = find_symbol(name, SYM_NORMAL);
+ if (!sym)
+ error_with_pos("export undefined symbol %s", name);
+ else {
+ unsigned long crc;
- if (flag_dump_defs)
- fprintf(debugfile, "Export %s == <", name);
+ if (flag_dump_defs)
+ fprintf(debugfile, "Export %s == <", name);
- expansion_trail = (struct symbol *)-1L;
+ expansion_trail = (struct symbol *)-1L;
- crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff;
+ crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff;
- sym = expansion_trail;
- while (sym != (struct symbol *)-1L)
- {
- struct symbol *n = sym->expansion_trail;
- sym->expansion_trail = 0;
- sym = n;
- }
+ sym = expansion_trail;
+ while (sym != (struct symbol *)-1L) {
+ struct symbol *n = sym->expansion_trail;
+ sym->expansion_trail = 0;
+ sym = n;
+ }
- if (flag_dump_defs)
- fputs(">\n", debugfile);
+ if (flag_dump_defs)
+ fputs(">\n", debugfile);
- /* Used as a linker script. */
- printf("__crc_%s = 0x%08lx ;\n", name, crc);
- }
+ /* Used as a linker script. */
+ printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
+ }
}
/*----------------------------------------------------------------------*/
-
-void
-error(const char *fmt, ...)
-{
- va_list args;
-
- if (flag_warnings)
- {
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- putc('\n', stderr);
-
- errors++;
- }
-}
-
-void
-error_with_pos(const char *fmt, ...)
+void error_with_pos(const char *fmt, ...)
{
- va_list args;
+ va_list args;
- if (flag_warnings)
- {
- fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
+ if (flag_warnings) {
+ fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>",
+ cur_line);
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- putc('\n', stderr);
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ putc('\n', stderr);
- errors++;
- }
+ errors++;
+ }
}
-
-void genksyms_usage(void)
+static void genksyms_usage(void)
{
- fputs("Usage:\n"
- "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n"
- "\n"
+ fputs("Usage:\n" "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n" "\n"
#ifdef __GNU_LIBRARY__
" -d, --debug Increment the debug level (repeatable)\n"
" -D, --dump Dump expanded symbol defs (for debugging only)\n"
@@ -511,81 +451,84 @@ void genksyms_usage(void)
" -q, --quiet Disable warnings (default)\n"
" -h, --help Print this message\n"
" -V, --version Print the release version\n"
-#else /* __GNU_LIBRARY__ */
- " -d Increment the debug level (repeatable)\n"
- " -D Dump expanded symbol defs (for debugging only)\n"
- " -w Enable warnings\n"
- " -q Disable warnings (default)\n"
- " -h Print this message\n"
- " -V Print the release version\n"
-#endif /* __GNU_LIBRARY__ */
+#else /* __GNU_LIBRARY__ */
+ " -d Increment the debug level (repeatable)\n"
+ " -D Dump expanded symbol defs (for debugging only)\n"
+ " -w Enable warnings\n"
+ " -q Disable warnings (default)\n"
+ " -h Print this message\n"
+ " -V Print the release version\n"
+#endif /* __GNU_LIBRARY__ */
, stderr);
}
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
{
- int o;
+ int o;
#ifdef __GNU_LIBRARY__
- struct option long_opts[] = {
- {"debug", 0, 0, 'd'},
- {"warnings", 0, 0, 'w'},
- {"quiet", 0, 0, 'q'},
- {"dump", 0, 0, 'D'},
- {"version", 0, 0, 'V'},
- {"help", 0, 0, 'h'},
- {0, 0, 0, 0}
- };
-
- while ((o = getopt_long(argc, argv, "dwqVDk:p:",
- &long_opts[0], NULL)) != EOF)
-#else /* __GNU_LIBRARY__ */
- while ((o = getopt(argc, argv, "dwqVDk:p:")) != EOF)
-#endif /* __GNU_LIBRARY__ */
- switch (o)
- {
- case 'd':
- flag_debug++;
- break;
- case 'w':
- flag_warnings = 1;
- break;
- case 'q':
- flag_warnings = 0;
- break;
- case 'V':
- fputs("genksyms version 2.5.60\n", stderr);
- break;
- case 'D':
- flag_dump_defs = 1;
- break;
- case 'h':
- genksyms_usage();
- return 0;
- default:
- genksyms_usage();
- return 1;
- }
-
- {
- extern int yydebug;
- extern int yy_flex_debug;
-
- yydebug = (flag_debug > 1);
- yy_flex_debug = (flag_debug > 2);
-
- debugfile = stderr;
- /* setlinebuf(debugfile); */
- }
-
- yyparse();
-
- if (flag_debug)
- {
- fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
- nsyms, HASH_BUCKETS, (double)nsyms / (double)HASH_BUCKETS);
- }
-
- return errors != 0;
+ struct option long_opts[] = {
+ {"arch", 1, 0, 'a'},
+ {"debug", 0, 0, 'd'},
+ {"warnings", 0, 0, 'w'},
+ {"quiet", 0, 0, 'q'},
+ {"dump", 0, 0, 'D'},
+ {"version", 0, 0, 'V'},
+ {"help", 0, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+
+ while ((o = getopt_long(argc, argv, "a:dwqVDk:p:",
+ &long_opts[0], NULL)) != EOF)
+#else /* __GNU_LIBRARY__ */
+ while ((o = getopt(argc, argv, "a:dwqVDk:p:")) != EOF)
+#endif /* __GNU_LIBRARY__ */
+ switch (o) {
+ case 'a':
+ arch = optarg;
+ break;
+ case 'd':
+ flag_debug++;
+ break;
+ case 'w':
+ flag_warnings = 1;
+ break;
+ case 'q':
+ flag_warnings = 0;
+ break;
+ case 'V':
+ fputs("genksyms version 2.5.60\n", stderr);
+ break;
+ case 'D':
+ flag_dump_defs = 1;
+ break;
+ case 'h':
+ genksyms_usage();
+ return 0;
+ default:
+ genksyms_usage();
+ return 1;
+ }
+ if ((strcmp(arch, "v850") == 0) || (strcmp(arch, "h8300") == 0))
+ mod_prefix = "_";
+ {
+ extern int yydebug;
+ extern int yy_flex_debug;
+
+ yydebug = (flag_debug > 1);
+ yy_flex_debug = (flag_debug > 2);
+
+ debugfile = stderr;
+ /* setlinebuf(debugfile); */
+ }
+
+ yyparse();
+
+ if (flag_debug) {
+ fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
+ nsyms, HASH_BUCKETS,
+ (double)nsyms / (double)HASH_BUCKETS);
+ }
+
+ return errors != 0;
}
diff --git a/scripts/genksyms/genksyms.h b/scripts/genksyms/genksyms.h
index f09af47ab28..ab6f34f3873 100644
--- a/scripts/genksyms/genksyms.h
+++ b/scripts/genksyms/genksyms.h
@@ -20,74 +20,51 @@
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
#ifndef MODUTILS_GENKSYMS_H
#define MODUTILS_GENKSYMS_H 1
#include <stdio.h>
-
-enum symbol_type
-{
- SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION
+enum symbol_type {
+ SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION
};
-struct string_list
-{
- struct string_list *next;
- enum symbol_type tag;
- char *string;
+struct string_list {
+ struct string_list *next;
+ enum symbol_type tag;
+ char *string;
};
-struct symbol
-{
- struct symbol *hash_next;
- const char *name;
- enum symbol_type type;
- struct string_list *defn;
- struct symbol *expansion_trail;
- int is_extern;
+struct symbol {
+ struct symbol *hash_next;
+ const char *name;
+ enum symbol_type type;
+ struct string_list *defn;
+ struct symbol *expansion_trail;
+ int is_extern;
};
typedef struct string_list **yystype;
#define YYSTYPE yystype
-extern FILE *outfile, *debugfile;
-
extern int cur_line;
-extern char *cur_filename, *output_directory;
-
-extern int flag_debug, flag_dump_defs, flag_warnings;
-extern int checksum_version, kernel_version;
-
-extern int want_brace_phrase, want_exp_phrase, discard_phrase_contents;
-extern struct string_list *current_list, *next_list;
-
+extern char *cur_filename;
struct symbol *find_symbol(const char *name, enum symbol_type ns);
struct symbol *add_symbol(const char *name, enum symbol_type type,
- struct string_list *defn, int is_extern);
+ struct string_list *defn, int is_extern);
void export_symbol(const char *);
-struct string_list *reset_list(void);
-void free_list(struct string_list *s, struct string_list *e);
void free_node(struct string_list *list);
+void free_list(struct string_list *s, struct string_list *e);
struct string_list *copy_node(struct string_list *);
-struct string_list *copy_list(struct string_list *s, struct string_list *e);
-int equal_list(struct string_list *a, struct string_list *b);
-void print_list(FILE *, struct string_list *list);
int yylex(void);
int yyparse(void);
void error_with_pos(const char *, ...);
-#define version(a,b,c) ((a << 16) | (b << 8) | (c))
-
/*----------------------------------------------------------------------*/
-
-#define MODUTILS_VERSION "<in-kernel>"
-
#define xmalloc(size) ({ void *__ptr = malloc(size); \
if(!__ptr && size != 0) { \
fprintf(stderr, "out of memory\n"); \
@@ -101,4 +78,4 @@ void error_with_pos(const char *, ...);
} \
__str; })
-#endif /* genksyms.h */
+#endif /* genksyms.h */
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index d591578bd3b..22d281c6ec2 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -124,6 +124,11 @@ static int read_symbol(FILE *in, struct sym_entry *s)
* compressed together */
s->len = strlen(str) + 1;
s->sym = malloc(s->len + 1);
+ if (!s->sym) {
+ fprintf(stderr, "kallsyms failure: "
+ "unable to allocate required amount of memory\n");
+ exit(EXIT_FAILURE);
+ }
strcpy((char *)s->sym + 1, str);
s->sym[0] = stype;
@@ -272,7 +277,12 @@ static void write_src(void)
/* table of offset markers, that give the offset in the compressed stream
* every 256 symbols */
- markers = (unsigned int *) malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256));
+ markers = malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256));
+ if (!markers) {
+ fprintf(stderr, "kallsyms failure: "
+ "unable to allocate required memory\n");
+ exit(EXIT_FAILURE);
+ }
output_label("kallsyms_names");
off = 0;
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 5760e057ecb..e6499db4c8c 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -2,7 +2,7 @@
# Kernel configuration targets
# These targets are used from top-level makefile
-.PHONY: oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config
+PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config
xconfig: $(obj)/qconf
$< arch/$(ARCH)/Kconfig
@@ -42,7 +42,7 @@ update-po-config: $(obj)/kxgettext
$(Q)rm -f arch/um/Kconfig_arch
$(Q)rm -f scripts/kconfig/linux_*.pot scripts/kconfig/config.pot
-.PHONY: randconfig allyesconfig allnoconfig allmodconfig defconfig
+PHONY += randconfig allyesconfig allnoconfig allmodconfig defconfig
randconfig: $(obj)/conf
$< -r arch/$(ARCH)/Kconfig
@@ -78,7 +78,7 @@ help:
@echo ' defconfig - New config with default answer to all options'
@echo ' allmodconfig - New config selecting modules when possible'
@echo ' allyesconfig - New config where all options are accepted with yes'
- @echo ' allnoconfig - New minimal config'
+ @echo ' allnoconfig - New config where all options are answered with no'
# ===========================================================================
# Shared Makefile for the various kconfig executables:
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index b0cbbe2e41b..1b8882ddbc7 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -374,6 +374,7 @@ int conf_write(const char *name)
out_h = fopen(".tmpconfig.h", "w");
if (!out_h)
return 1;
+ file_write_dep(NULL);
}
sym = sym_lookup("KERNELVERSION", 0);
sym_calc_value(sym);
@@ -512,7 +513,6 @@ int conf_write(const char *name)
if (out_h) {
fclose(out_h);
rename(".tmpconfig.h", "include/linux/autoconf.h");
- file_write_dep(NULL);
}
if (!name || basename != conf_def_filename) {
if (!name)
diff --git a/scripts/kconfig/lxdialog/Makefile b/scripts/kconfig/lxdialog/Makefile
index bbf4887cff7..a8b02632624 100644
--- a/scripts/kconfig/lxdialog/Makefile
+++ b/scripts/kconfig/lxdialog/Makefile
@@ -7,10 +7,10 @@ check-lxdialog := $(srctree)/$(src)/check-lxdialog.sh
# we really need to do so. (Do not call gcc as part of make mrproper)
HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
-
-HOST_EXTRACFLAGS += -DLOCALE
-.PHONY: dochecklxdialog
+HOST_EXTRACFLAGS += -DLOCALE
+
+PHONY += dochecklxdialog
$(obj)/dochecklxdialog:
$(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_LOADLIBES)
diff --git a/scripts/mkmakefile b/scripts/mkmakefile
index c4d621b30d0..a22cbedd3b3 100644
--- a/scripts/mkmakefile
+++ b/scripts/mkmakefile
@@ -21,11 +21,13 @@ KERNELOUTPUT := $2
MAKEFLAGS += --no-print-directory
+.PHONY: all \$(MAKECMDGOALS)
+
all:
\$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT)
-%::
- \$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) \$@
+Makefile:;
+\$(filter-out all Makefile,\$(MAKECMDGOALS)) %/:
+ \$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) \$@
EOF
-
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index c164b230ad6..84e21201f3c 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -34,7 +34,7 @@ typedef uint16_t __u16;
typedef unsigned char __u8;
/* Big exception to the "don't include kernel headers into userspace, which
- * even potentially has different endianness and word sizes, since
+ * even potentially has different endianness and word sizes, since
* we handle those differences explicitly below */
#include "../../include/linux/mod_devicetable.h"
#include "../../include/linux/input.h"
@@ -153,8 +153,8 @@ static void do_usb_table(void *symval, unsigned long size,
const unsigned long id_size = sizeof(struct usb_device_id);
if (size % id_size || size < id_size) {
- fprintf(stderr, "*** Warning: %s ids %lu bad size "
- "(each on %lu)\n", mod->name, size, id_size);
+ warn("%s ids %lu bad size "
+ "(each on %lu)\n", mod->name, size, id_size);
}
/* Leave last one: it's the terminator. */
size -= id_size;
@@ -217,9 +217,8 @@ static int do_pci_entry(const char *filename,
if ((baseclass_mask != 0 && baseclass_mask != 0xFF)
|| (subclass_mask != 0 && subclass_mask != 0xFF)
|| (interface_mask != 0 && interface_mask != 0xFF)) {
- fprintf(stderr,
- "*** Warning: Can't handle masks in %s:%04X\n",
- filename, id->class_mask);
+ warn("Can't handle masks in %s:%04X\n",
+ filename, id->class_mask);
return 0;
}
@@ -229,7 +228,7 @@ static int do_pci_entry(const char *filename,
return 1;
}
-/* looks like: "ccw:tNmNdtNdmN" */
+/* looks like: "ccw:tNmNdtNdmN" */
static int do_ccw_entry(const char *filename,
struct ccw_device_id *id, char *alias)
{
@@ -445,8 +444,8 @@ static void do_table(void *symval, unsigned long size,
int (*do_entry)(const char *, void *entry, char *alias) = function;
if (size % id_size || size < id_size) {
- fprintf(stderr, "*** Warning: %s ids %lu bad size "
- "(each on %lu)\n", mod->name, size, id_size);
+ warn("%s ids %lu bad size "
+ "(each on %lu)\n", mod->name, size, id_size);
}
/* Leave last one: it's the terminator. */
size -= id_size;
diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c
index de2aabf89fb..3c92c83733f 100644
--- a/scripts/mod/mk_elfconfig.c
+++ b/scripts/mod/mk_elfconfig.c
@@ -6,7 +6,7 @@
int
main(int argc, char **argv)
{
- unsigned char ei[EI_NIDENT];
+ unsigned char ei[EI_NIDENT];
union { short s; char c[2]; } endian_test;
if (argc != 2) {
@@ -57,7 +57,7 @@ main(int argc, char **argv)
if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0))
printf("#define MODULE_SYMBOL_PREFIX \"_\"\n");
- else
+ else
printf("#define MODULE_SYMBOL_PREFIX \"\"\n");
return 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index b8b2a560b26..0b92ddff26f 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -2,7 +2,7 @@
*
* Copyright 2003 Kai Germaschewski
* Copyright 2002-2004 Rusty Russell, IBM Corporation
- *
+ * Copyright 2006 Sam Ravnborg
* Based in part on module-init-tools/depmod.c,file2alias
*
* This software may be used and distributed according to the terms
@@ -20,9 +20,10 @@ int modversions = 0;
int have_vmlinux = 0;
/* Is CONFIG_MODULE_SRCVERSION_ALL set? */
static int all_versions = 0;
+/* If we are modposting external module set to 1 */
+static int external_module = 0;
-void
-fatal(const char *fmt, ...)
+void fatal(const char *fmt, ...)
{
va_list arglist;
@@ -35,8 +36,7 @@ fatal(const char *fmt, ...)
exit(1);
}
-void
-warn(const char *fmt, ...)
+void warn(const char *fmt, ...)
{
va_list arglist;
@@ -47,6 +47,18 @@ warn(const char *fmt, ...)
va_end(arglist);
}
+static int is_vmlinux(const char *modname)
+{
+ const char *myname;
+
+ if ((myname = strrchr(modname, '/')))
+ myname++;
+ else
+ myname = modname;
+
+ return strcmp(myname, "vmlinux") == 0;
+}
+
void *do_nofail(void *ptr, const char *expr)
{
if (!ptr) {
@@ -59,8 +71,7 @@ void *do_nofail(void *ptr, const char *expr)
static struct module *modules;
-struct module *
-find_module(char *modname)
+static struct module *find_module(char *modname)
{
struct module *mod;
@@ -70,12 +81,11 @@ find_module(char *modname)
return mod;
}
-struct module *
-new_module(char *modname)
+static struct module *new_module(char *modname)
{
struct module *mod;
char *p, *s;
-
+
mod = NOFAIL(malloc(sizeof(*mod)));
memset(mod, 0, sizeof(*mod));
p = NOFAIL(strdup(modname));
@@ -104,6 +114,10 @@ struct symbol {
unsigned int crc;
int crc_valid;
unsigned int weak:1;
+ unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */
+ unsigned int kernel:1; /* 1 if symbol is from kernel
+ * (only for external modules) **/
+ unsigned int preloaded:1; /* 1 if symbol from Module.symvers */
char name[0];
};
@@ -122,11 +136,12 @@ static inline unsigned int tdb_hash(const char *name)
return (1103515243 * value + 12345);
}
-/* Allocate a new symbols for use in the hash of exported symbols or
- * the list of unresolved symbols per module */
-
-struct symbol *
-alloc_symbol(const char *name, unsigned int weak, struct symbol *next)
+/**
+ * Allocate a new symbols for use in the hash of exported symbols or
+ * the list of unresolved symbols per module
+ **/
+static struct symbol *alloc_symbol(const char *name, unsigned int weak,
+ struct symbol *next)
{
struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1));
@@ -138,9 +153,7 @@ alloc_symbol(const char *name, unsigned int weak, struct symbol *next)
}
/* For the hash of exported symbols */
-
-void
-new_symbol(const char *name, struct module *module, unsigned int *crc)
+static struct symbol *new_symbol(const char *name, struct module *module)
{
unsigned int hash;
struct symbol *new;
@@ -148,14 +161,10 @@ new_symbol(const char *name, struct module *module, unsigned int *crc)
hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]);
new->module = module;
- if (crc) {
- new->crc = *crc;
- new->crc_valid = 1;
- }
+ return new;
}
-struct symbol *
-find_symbol(const char *name)
+static struct symbol *find_symbol(const char *name)
{
struct symbol *s;
@@ -170,25 +179,42 @@ find_symbol(const char *name)
return NULL;
}
-/* Add an exported symbol - it may have already been added without a
- * CRC, in this case just update the CRC */
-void
-add_exported_symbol(const char *name, struct module *module, unsigned int *crc)
+/**
+ * Add an exported symbol - it may have already been added without a
+ * CRC, in this case just update the CRC
+ **/
+static struct symbol *sym_add_exported(const char *name, struct module *mod)
{
struct symbol *s = find_symbol(name);
if (!s) {
- new_symbol(name, module, crc);
- return;
- }
- if (crc) {
- s->crc = *crc;
- s->crc_valid = 1;
+ s = new_symbol(name, mod);
+ } else {
+ if (!s->preloaded) {
+ warn("%s: '%s' exported twice. Previous export "
+ "was in %s%s\n", mod->name, name,
+ s->module->name,
+ is_vmlinux(s->module->name) ?"":".ko");
+ }
}
+ s->preloaded = 0;
+ s->vmlinux = is_vmlinux(mod->name);
+ s->kernel = 0;
+ return s;
+}
+
+static void sym_update_crc(const char *name, struct module *mod,
+ unsigned int crc)
+{
+ struct symbol *s = find_symbol(name);
+
+ if (!s)
+ s = new_symbol(name, mod);
+ s->crc = crc;
+ s->crc_valid = 1;
}
-void *
-grab_file(const char *filename, unsigned long *size)
+void *grab_file(const char *filename, unsigned long *size)
{
struct stat st;
void *map;
@@ -207,13 +233,12 @@ grab_file(const char *filename, unsigned long *size)
return map;
}
-/*
- Return a copy of the next line in a mmap'ed file.
- spaces in the beginning of the line is trimmed away.
- Return a pointer to a static buffer.
-*/
-char*
-get_next_line(unsigned long *pos, void *file, unsigned long size)
+/**
+ * Return a copy of the next line in a mmap'ed file.
+ * spaces in the beginning of the line is trimmed away.
+ * Return a pointer to a static buffer.
+ **/
+char* get_next_line(unsigned long *pos, void *file, unsigned long size)
{
static char line[4096];
int skip = 1;
@@ -243,14 +268,12 @@ get_next_line(unsigned long *pos, void *file, unsigned long size)
return NULL;
}
-void
-release_file(void *file, unsigned long size)
+void release_file(void *file, unsigned long size)
{
munmap(file, size);
}
-void
-parse_elf(struct elf_info *info, const char *filename)
+static void parse_elf(struct elf_info *info, const char *filename)
{
unsigned int i;
Elf_Ehdr *hdr = info->hdr;
@@ -297,14 +320,13 @@ parse_elf(struct elf_info *info, const char *filename)
continue;
info->symtab_start = (void *)hdr + sechdrs[i].sh_offset;
- info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset
+ info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset
+ sechdrs[i].sh_size;
- info->strtab = (void *)hdr +
+ info->strtab = (void *)hdr +
sechdrs[sechdrs[i].sh_link].sh_offset;
}
if (!info->symtab_start) {
- fprintf(stderr, "modpost: %s no symtab?\n", filename);
- abort();
+ fatal("%s has no symtab?\n", filename);
}
/* Fix endianness in symbols */
for (sym = info->symtab_start; sym < info->symtab_stop; sym++) {
@@ -316,36 +338,31 @@ parse_elf(struct elf_info *info, const char *filename)
return;
truncated:
- fprintf(stderr, "modpost: %s is truncated.\n", filename);
- abort();
+ fatal("%s is truncated.\n", filename);
}
-void
-parse_elf_finish(struct elf_info *info)
+static void parse_elf_finish(struct elf_info *info)
{
release_file(info->hdr, info->size);
}
-#define CRC_PFX "__crc_"
-#define KSYMTAB_PFX "__ksymtab_"
+#define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_"
+#define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_"
-void
-handle_modversions(struct module *mod, struct elf_info *info,
- Elf_Sym *sym, const char *symname)
+static void handle_modversions(struct module *mod, struct elf_info *info,
+ Elf_Sym *sym, const char *symname)
{
unsigned int crc;
switch (sym->st_shndx) {
case SHN_COMMON:
- fprintf(stderr, "*** Warning: \"%s\" [%s] is COMMON symbol\n",
- symname, mod->name);
+ warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);
break;
case SHN_ABS:
/* CRC'd symbol */
if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
crc = (unsigned int) sym->st_value;
- add_exported_symbol(symname + strlen(CRC_PFX),
- mod, &crc);
+ sym_update_crc(symname + strlen(CRC_PFX), mod, crc);
}
break;
case SHN_UNDEF:
@@ -370,15 +387,15 @@ handle_modversions(struct module *mod, struct elf_info *info,
/* Ignore register directives. */
if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER)
break;
- if (symname[0] == '.') {
- char *munged = strdup(symname);
- munged[0] = '_';
- munged[1] = toupper(munged[1]);
- symname = munged;
- }
+ if (symname[0] == '.') {
+ char *munged = strdup(symname);
+ munged[0] = '_';
+ munged[1] = toupper(munged[1]);
+ symname = munged;
+ }
}
#endif
-
+
if (memcmp(symname, MODULE_SYMBOL_PREFIX,
strlen(MODULE_SYMBOL_PREFIX)) == 0)
mod->unres = alloc_symbol(symname +
@@ -389,8 +406,7 @@ handle_modversions(struct module *mod, struct elf_info *info,
default:
/* All exported symbols */
if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
- add_exported_symbol(symname + strlen(KSYMTAB_PFX),
- mod, NULL);
+ sym_add_exported(symname + strlen(KSYMTAB_PFX), mod);
}
if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
mod->has_init = 1;
@@ -400,20 +416,9 @@ handle_modversions(struct module *mod, struct elf_info *info,
}
}
-int
-is_vmlinux(const char *modname)
-{
- const char *myname;
-
- if ((myname = strrchr(modname, '/')))
- myname++;
- else
- myname = modname;
-
- return strcmp(myname, "vmlinux") == 0;
-}
-
-/* Parse tag=value strings from .modinfo section */
+/**
+ * Parse tag=value strings from .modinfo section
+ **/
static char *next_string(char *string, unsigned long *secsize)
{
/* Skip non-zero chars */
@@ -446,8 +451,418 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
return NULL;
}
-void
-read_symbols(char *modname)
+/**
+ * Test if string s ends in string sub
+ * return 0 if match
+ **/
+static int strrcmp(const char *s, const char *sub)
+{
+ int slen, sublen;
+
+ if (!s || !sub)
+ return 1;
+
+ slen = strlen(s);
+ sublen = strlen(sub);
+
+ if ((slen == 0) || (sublen == 0))
+ return 1;
+
+ if (sublen > slen)
+ return 1;
+
+ return memcmp(s + slen - sublen, sub, sublen);
+}
+
+/**
+ * Whitelist to allow certain references to pass with no warning.
+ * Pattern 1:
+ * If a module parameter is declared __initdata and permissions=0
+ * then this is legal despite the warning generated.
+ * We cannot see value of permissions here, so just ignore
+ * this pattern.
+ * The pattern is identified by:
+ * tosec = .init.data
+ * fromsec = .data*
+ * atsym =__param*
+ *
+ * Pattern 2:
+ * Many drivers utilise a *_driver container with references to
+ * add, remove, probe functions etc.
+ * These functions may often be marked __init and we do not want to
+ * warn here.
+ * the pattern is identified by:
+ * tosec = .init.text | .exit.text
+ * fromsec = .data
+ * atsym = *_driver, *_ops, *_probe, *probe_one
+ **/
+static int secref_whitelist(const char *tosec, const char *fromsec,
+ const char *atsym)
+{
+ int f1 = 1, f2 = 1;
+ const char **s;
+ const char *pat2sym[] = {
+ "_driver",
+ "_ops",
+ "_probe",
+ "_probe_one",
+ NULL
+ };
+
+ /* Check for pattern 1 */
+ if (strcmp(tosec, ".init.data") != 0)
+ f1 = 0;
+ if (strncmp(fromsec, ".data", strlen(".data")) != 0)
+ f1 = 0;
+ if (strncmp(atsym, "__param", strlen("__param")) != 0)
+ f1 = 0;
+
+ if (f1)
+ return f1;
+
+ /* Check for pattern 2 */
+ if ((strcmp(tosec, ".init.text") != 0) &&
+ (strcmp(tosec, ".exit.text") != 0))
+ f2 = 0;
+ if (strcmp(fromsec, ".data") != 0)
+ f2 = 0;
+
+ for (s = pat2sym; *s; s++)
+ if (strrcmp(atsym, *s) == 0)
+ f1 = 1;
+
+ return f1 && f2;
+}
+
+/**
+ * Find symbol based on relocation record info.
+ * In some cases the symbol supplied is a valid symbol so
+ * return refsym. If st_name != 0 we assume this is a valid symbol.
+ * In other cases the symbol needs to be looked up in the symbol table
+ * based on section and address.
+ * **/
+static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr,
+ Elf_Sym *relsym)
+{
+ Elf_Sym *sym;
+
+ if (relsym->st_name != 0)
+ return relsym;
+ for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
+ if (sym->st_shndx != relsym->st_shndx)
+ continue;
+ if (sym->st_value == addr)
+ return sym;
+ }
+ return NULL;
+}
+
+/*
+ * Find symbols before or equal addr and after addr - in the section sec.
+ * If we find two symbols with equal offset prefer one with a valid name.
+ * The ELF format may have a better way to detect what type of symbol
+ * it is, but this works for now.
+ **/
+static void find_symbols_between(struct elf_info *elf, Elf_Addr addr,
+ const char *sec,
+ Elf_Sym **before, Elf_Sym **after)
+{
+ Elf_Sym *sym;
+ Elf_Ehdr *hdr = elf->hdr;
+ Elf_Addr beforediff = ~0;
+ Elf_Addr afterdiff = ~0;
+ const char *secstrings = (void *)hdr +
+ elf->sechdrs[hdr->e_shstrndx].sh_offset;
+
+ *before = NULL;
+ *after = NULL;
+
+ for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
+ const char *symsec;
+
+ if (sym->st_shndx >= SHN_LORESERVE)
+ continue;
+ symsec = secstrings + elf->sechdrs[sym->st_shndx].sh_name;
+ if (strcmp(symsec, sec) != 0)
+ continue;
+ if (sym->st_value <= addr) {
+ if ((addr - sym->st_value) < beforediff) {
+ beforediff = addr - sym->st_value;
+ *before = sym;
+ }
+ else if ((addr - sym->st_value) == beforediff) {
+ /* equal offset, valid name? */
+ const char *name = elf->strtab + sym->st_name;
+ if (name && strlen(name))
+ *before = sym;
+ }
+ }
+ else
+ {
+ if ((sym->st_value - addr) < afterdiff) {
+ afterdiff = sym->st_value - addr;
+ *after = sym;
+ }
+ else if ((sym->st_value - addr) == afterdiff) {
+ /* equal offset, valid name? */
+ const char *name = elf->strtab + sym->st_name;
+ if (name && strlen(name))
+ *after = sym;
+ }
+ }
+ }
+}
+
+/**
+ * Print a warning about a section mismatch.
+ * Try to find symbols near it so user can find it.
+ * Check whitelist before warning - it may be a false positive.
+ **/
+static void warn_sec_mismatch(const char *modname, const char *fromsec,
+ struct elf_info *elf, Elf_Sym *sym, Elf_Rela r)
+{
+ const char *refsymname = "";
+ Elf_Sym *before, *after;
+ Elf_Sym *refsym;
+ Elf_Ehdr *hdr = elf->hdr;
+ Elf_Shdr *sechdrs = elf->sechdrs;
+ const char *secstrings = (void *)hdr +
+ sechdrs[hdr->e_shstrndx].sh_offset;
+ const char *secname = secstrings + sechdrs[sym->st_shndx].sh_name;
+
+ find_symbols_between(elf, r.r_offset, fromsec, &before, &after);
+
+ refsym = find_elf_symbol(elf, r.r_addend, sym);
+ if (refsym && strlen(elf->strtab + refsym->st_name))
+ refsymname = elf->strtab + refsym->st_name;
+
+ /* check whitelist - we may ignore it */
+ if (before &&
+ secref_whitelist(secname, fromsec, elf->strtab + before->st_name))
+ return;
+
+ if (before && after) {
+ warn("%s - Section mismatch: reference to %s:%s from %s "
+ "between '%s' (at offset 0x%llx) and '%s'\n",
+ modname, secname, refsymname, fromsec,
+ elf->strtab + before->st_name,
+ (long long)r.r_offset,
+ elf->strtab + after->st_name);
+ } else if (before) {
+ warn("%s - Section mismatch: reference to %s:%s from %s "
+ "after '%s' (at offset 0x%llx)\n",
+ modname, secname, refsymname, fromsec,
+ elf->strtab + before->st_name,
+ (long long)r.r_offset);
+ } else if (after) {
+ warn("%s - Section mismatch: reference to %s:%s from %s "
+ "before '%s' (at offset -0x%llx)\n",
+ modname, secname, refsymname, fromsec,
+ elf->strtab + before->st_name,
+ (long long)r.r_offset);
+ } else {
+ warn("%s - Section mismatch: reference to %s:%s from %s "
+ "(offset 0x%llx)\n",
+ modname, secname, fromsec, refsymname,
+ (long long)r.r_offset);
+ }
+}
+
+/**
+ * A module includes a number of sections that are discarded
+ * either when loaded or when used as built-in.
+ * For loaded modules all functions marked __init and all data
+ * marked __initdata will be discarded when the module has been intialized.
+ * Likewise for modules used built-in the sections marked __exit
+ * are discarded because __exit marked function are supposed to be called
+ * only when a moduel is unloaded which never happes for built-in modules.
+ * The check_sec_ref() function traverses all relocation records
+ * to find all references to a section that reference a section that will
+ * be discarded and warns about it.
+ **/
+static void check_sec_ref(struct module *mod, const char *modname,
+ struct elf_info *elf,
+ int section(const char*),
+ int section_ref_ok(const char *))
+{
+ int i;
+ Elf_Sym *sym;
+ Elf_Ehdr *hdr = elf->hdr;
+ Elf_Shdr *sechdrs = elf->sechdrs;
+ const char *secstrings = (void *)hdr +
+ sechdrs[hdr->e_shstrndx].sh_offset;
+
+ /* Walk through all sections */
+ for (i = 0; i < hdr->e_shnum; i++) {
+ Elf_Rela *rela;
+ Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset;
+ Elf_Rela *stop = (void*)start + sechdrs[i].sh_size;
+ const char *name = secstrings + sechdrs[i].sh_name +
+ strlen(".rela");
+ /* We want to process only relocation sections and not .init */
+ if (section_ref_ok(name) || (sechdrs[i].sh_type != SHT_RELA))
+ continue;
+
+ for (rela = start; rela < stop; rela++) {
+ Elf_Rela r;
+ const char *secname;
+ r.r_offset = TO_NATIVE(rela->r_offset);
+ r.r_info = TO_NATIVE(rela->r_info);
+ r.r_addend = TO_NATIVE(rela->r_addend);
+ sym = elf->symtab_start + ELF_R_SYM(r.r_info);
+ /* Skip special sections */
+ if (sym->st_shndx >= SHN_LORESERVE)
+ continue;
+
+ secname = secstrings + sechdrs[sym->st_shndx].sh_name;
+ if (section(secname))
+ warn_sec_mismatch(modname, name, elf, sym, r);
+ }
+ }
+}
+
+/**
+ * Functions used only during module init is marked __init and is stored in
+ * a .init.text section. Likewise data is marked __initdata and stored in
+ * a .init.data section.
+ * If this section is one of these sections return 1
+ * See include/linux/init.h for the details
+ **/
+static int init_section(const char *name)
+{
+ if (strcmp(name, ".init") == 0)
+ return 1;
+ if (strncmp(name, ".init.", strlen(".init.")) == 0)
+ return 1;
+ return 0;
+}
+
+/**
+ * Identify sections from which references to a .init section is OK.
+ *
+ * Unfortunately references to read only data that referenced .init
+ * sections had to be excluded. Almost all of these are false
+ * positives, they are created by gcc. The downside of excluding rodata
+ * is that there really are some user references from rodata to
+ * init code, e.g. drivers/video/vgacon.c:
+ *
+ * const struct consw vga_con = {
+ * con_startup: vgacon_startup,
+ *
+ * where vgacon_startup is __init. If you want to wade through the false
+ * positives, take out the check for rodata.
+ **/
+static int init_section_ref_ok(const char *name)
+{
+ const char **s;
+ /* Absolute section names */
+ const char *namelist1[] = {
+ ".init",
+ ".opd", /* see comment [OPD] at exit_section_ref_ok() */
+ ".toc1", /* used by ppc64 */
+ ".stab",
+ ".rodata",
+ ".text.lock",
+ "__bug_table", /* used by powerpc for BUG() */
+ ".pci_fixup_header",
+ ".pci_fixup_final",
+ ".pdr",
+ "__param",
+ NULL
+ };
+ /* Start of section names */
+ const char *namelist2[] = {
+ ".init.",
+ ".altinstructions",
+ ".eh_frame",
+ ".debug",
+ NULL
+ };
+ /* part of section name */
+ const char *namelist3 [] = {
+ ".unwind", /* sample: IA_64.unwind.init.text */
+ NULL
+ };
+
+ for (s = namelist1; *s; s++)
+ if (strcmp(*s, name) == 0)
+ return 1;
+ for (s = namelist2; *s; s++)
+ if (strncmp(*s, name, strlen(*s)) == 0)
+ return 1;
+ for (s = namelist3; *s; s++)
+ if (strstr(name, *s) != NULL)
+ return 1;
+ return 0;
+}
+
+/*
+ * Functions used only during module exit is marked __exit and is stored in
+ * a .exit.text section. Likewise data is marked __exitdata and stored in
+ * a .exit.data section.
+ * If this section is one of these sections return 1
+ * See include/linux/init.h for the details
+ **/
+static int exit_section(const char *name)
+{
+ if (strcmp(name, ".exit.text") == 0)
+ return 1;
+ if (strcmp(name, ".exit.data") == 0)
+ return 1;
+ return 0;
+
+}
+
+/*
+ * Identify sections from which references to a .exit section is OK.
+ *
+ * [OPD] Keith Ownes <kaos@sgi.com> commented:
+ * For our future {in}sanity, add a comment that this is the ppc .opd
+ * section, not the ia64 .opd section.
+ * ia64 .opd should not point to discarded sections.
+ **/
+static int exit_section_ref_ok(const char *name)
+{
+ const char **s;
+ /* Absolute section names */
+ const char *namelist1[] = {
+ ".exit.text",
+ ".exit.data",
+ ".init.text",
+ ".opd", /* See comment [OPD] */
+ ".toc1", /* used by ppc64 */
+ ".altinstructions",
+ ".pdr",
+ "__bug_table", /* used by powerpc for BUG() */
+ ".exitcall.exit",
+ ".eh_frame",
+ ".stab",
+ NULL
+ };
+ /* Start of section names */
+ const char *namelist2[] = {
+ ".debug",
+ NULL
+ };
+ /* part of section name */
+ const char *namelist3 [] = {
+ ".unwind", /* Sample: IA_64.unwind.exit.text */
+ NULL
+ };
+
+ for (s = namelist1; *s; s++)
+ if (strcmp(*s, name) == 0)
+ return 1;
+ for (s = namelist2; *s; s++)
+ if (strncmp(*s, name, strlen(*s)) == 0)
+ return 1;
+ for (s = namelist3; *s; s++)
+ if (strstr(name, *s) != NULL)
+ return 1;
+ return 0;
+}
+
+static void read_symbols(char *modname)
{
const char *symname;
char *version;
@@ -462,9 +877,7 @@ read_symbols(char *modname)
/* When there's no vmlinux, don't print warnings about
* unresolved symbols (since there'll be too many ;) */
if (is_vmlinux(modname)) {
- unsigned int fake_crc = 0;
have_vmlinux = 1;
- add_exported_symbol("struct_module", mod, &fake_crc);
mod->skip = 1;
}
@@ -474,6 +887,8 @@ read_symbols(char *modname)
handle_modversions(mod, &info, sym, symname);
handle_moddevtable(mod, &info, sym, symname);
}
+ check_sec_ref(mod, modname, &info, init_section, init_section_ref_ok);
+ check_sec_ref(mod, modname, &info, exit_section, exit_section_ref_ok);
version = get_modinfo(info.modinfo, info.modinfo_len, "version");
if (version)
@@ -499,21 +914,20 @@ read_symbols(char *modname)
* following helper, then compare to the file on disk and
* only update the later if anything changed */
-void __attribute__((format(printf, 2, 3)))
-buf_printf(struct buffer *buf, const char *fmt, ...)
+void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf,
+ const char *fmt, ...)
{
char tmp[SZ];
int len;
va_list ap;
-
+
va_start(ap, fmt);
len = vsnprintf(tmp, SZ, fmt, ap);
buf_write(buf, tmp, len);
va_end(ap);
}
-void
-buf_write(struct buffer *buf, const char *s, int len)
+void buf_write(struct buffer *buf, const char *s, int len)
{
if (buf->size - buf->pos < len) {
buf->size += len + SZ;
@@ -523,10 +937,10 @@ buf_write(struct buffer *buf, const char *s, int len)
buf->pos += len;
}
-/* Header for the generated file */
-
-void
-add_header(struct buffer *b, struct module *mod)
+/**
+ * Header for the generated file
+ **/
+static void add_header(struct buffer *b, struct module *mod)
{
buf_printf(b, "#include <linux/module.h>\n");
buf_printf(b, "#include <linux/vermagic.h>\n");
@@ -546,10 +960,10 @@ add_header(struct buffer *b, struct module *mod)
buf_printf(b, "};\n");
}
-/* Record CRCs for unresolved symbols */
-
-void
-add_versions(struct buffer *b, struct module *mod)
+/**
+ * Record CRCs for unresolved symbols
+ **/
+static void add_versions(struct buffer *b, struct module *mod)
{
struct symbol *s, *exp;
@@ -557,8 +971,8 @@ add_versions(struct buffer *b, struct module *mod)
exp = find_symbol(s->name);
if (!exp || exp->module == mod) {
if (have_vmlinux && !s->weak)
- fprintf(stderr, "*** Warning: \"%s\" [%s.ko] "
- "undefined!\n", s->name, mod->name);
+ warn("\"%s\" [%s.ko] undefined!\n",
+ s->name, mod->name);
continue;
}
s->module = exp->module;
@@ -579,8 +993,7 @@ add_versions(struct buffer *b, struct module *mod)
continue;
}
if (!s->crc_valid) {
- fprintf(stderr, "*** Warning: \"%s\" [%s.ko] "
- "has no CRC!\n",
+ warn("\"%s\" [%s.ko] has no CRC!\n",
s->name, mod->name);
continue;
}
@@ -590,8 +1003,8 @@ add_versions(struct buffer *b, struct module *mod)
buf_printf(b, "};\n");
}
-void
-add_depends(struct buffer *b, struct module *mod, struct module *modules)
+static void add_depends(struct buffer *b, struct module *mod,
+ struct module *modules)
{
struct symbol *s;
struct module *m;
@@ -621,8 +1034,7 @@ add_depends(struct buffer *b, struct module *mod, struct module *modules)
buf_printf(b, "\";\n");
}
-void
-add_srcversion(struct buffer *b, struct module *mod)
+static void add_srcversion(struct buffer *b, struct module *mod)
{
if (mod->srcversion[0]) {
buf_printf(b, "\n");
@@ -631,8 +1043,7 @@ add_srcversion(struct buffer *b, struct module *mod)
}
}
-void
-write_if_changed(struct buffer *b, const char *fname)
+static void write_if_changed(struct buffer *b, const char *fname)
{
char *tmp;
FILE *file;
@@ -676,8 +1087,7 @@ write_if_changed(struct buffer *b, const char *fname)
fclose(file);
}
-void
-read_dump(const char *fname)
+static void read_dump(const char *fname, unsigned int kernel)
{
unsigned long size, pos = 0;
void *file = grab_file(fname, &size);
@@ -691,6 +1101,7 @@ read_dump(const char *fname)
char *symname, *modname, *d;
unsigned int crc;
struct module *mod;
+ struct symbol *s;
if (!(symname = strchr(line, '\t')))
goto fail;
@@ -711,15 +1122,30 @@ read_dump(const char *fname)
mod = new_module(NOFAIL(strdup(modname)));
mod->skip = 1;
}
- add_exported_symbol(symname, mod, &crc);
+ s = sym_add_exported(symname, mod);
+ s->kernel = kernel;
+ s->preloaded = 1;
+ sym_update_crc(symname, mod, crc);
}
return;
fail:
fatal("parse error in symbol dump file\n");
}
-void
-write_dump(const char *fname)
+/* For normal builds always dump all symbols.
+ * For external modules only dump symbols
+ * that are not read from kernel Module.symvers.
+ **/
+static int dump_sym(struct symbol *sym)
+{
+ if (!external_module)
+ return 1;
+ if (sym->vmlinux || sym->kernel)
+ return 0;
+ return 1;
+}
+
+static void write_dump(const char *fname)
{
struct buffer buf = { };
struct symbol *symbol;
@@ -728,34 +1154,33 @@ write_dump(const char *fname)
for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
symbol = symbolhash[n];
while (symbol) {
- symbol = symbol->next;
- }
- }
-
- for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
- symbol = symbolhash[n];
- while (symbol) {
- buf_printf(&buf, "0x%08x\t%s\t%s\n", symbol->crc,
- symbol->name, symbol->module->name);
+ if (dump_sym(symbol))
+ buf_printf(&buf, "0x%08x\t%s\t%s\n",
+ symbol->crc, symbol->name,
+ symbol->module->name);
symbol = symbol->next;
}
}
write_if_changed(&buf, fname);
}
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
{
struct module *mod;
struct buffer buf = { };
char fname[SZ];
- char *dump_read = NULL, *dump_write = NULL;
+ char *kernel_read = NULL, *module_read = NULL;
+ char *dump_write = NULL;
int opt;
- while ((opt = getopt(argc, argv, "i:mo:a")) != -1) {
+ while ((opt = getopt(argc, argv, "i:I:mo:a")) != -1) {
switch(opt) {
case 'i':
- dump_read = optarg;
+ kernel_read = optarg;
+ break;
+ case 'I':
+ module_read = optarg;
+ external_module = 1;
break;
case 'm':
modversions = 1;
@@ -771,8 +1196,10 @@ main(int argc, char **argv)
}
}
- if (dump_read)
- read_dump(dump_read);
+ if (kernel_read)
+ read_dump(kernel_read, 1);
+ if (module_read)
+ read_dump(module_read, 0);
while (optind < argc) {
read_symbols(argv[optind++]);
@@ -799,4 +1226,3 @@ main(int argc, char **argv)
return 0;
}
-
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 7334d839145..b14255c72a3 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -13,20 +13,30 @@
#if KERNEL_ELFCLASS == ELFCLASS32
-#define Elf_Ehdr Elf32_Ehdr
-#define Elf_Shdr Elf32_Shdr
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
+#define Elf_Addr Elf32_Addr
+#define Elf_Section Elf32_Section
#define ELF_ST_BIND ELF32_ST_BIND
#define ELF_ST_TYPE ELF32_ST_TYPE
+#define Elf_Rela Elf32_Rela
+#define ELF_R_SYM ELF32_R_SYM
+#define ELF_R_TYPE ELF32_R_TYPE
#else
-#define Elf_Ehdr Elf64_Ehdr
-#define Elf_Shdr Elf64_Shdr
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Shdr Elf64_Shdr
#define Elf_Sym Elf64_Sym
+#define Elf_Addr Elf64_Addr
+#define Elf_Section Elf64_Section
#define ELF_ST_BIND ELF64_ST_BIND
#define ELF_ST_TYPE ELF64_ST_TYPE
+#define Elf_Rela Elf64_Rela
+#define ELF_R_SYM ELF64_R_SYM
+#define ELF_R_TYPE ELF64_R_TYPE
#endif
#if KERNEL_ELFDATA != HOST_ELFDATA
@@ -91,17 +101,22 @@ struct elf_info {
unsigned int modinfo_len;
};
+/* file2alias.c */
void handle_moddevtable(struct module *mod, struct elf_info *info,
Elf_Sym *sym, const char *symname);
-
void add_moddevtable(struct buffer *buf, struct module *mod);
+/* sumversion.c */
void maybe_frob_rcs_version(const char *modfilename,
char *version,
void *modinfo,
unsigned long modinfo_offset);
void get_src_version(const char *modname, char sum[], unsigned sumlen);
+/* from modpost.c */
void *grab_file(const char *filename, unsigned long *size);
char* get_next_line(unsigned long *pos, void *file, unsigned long size);
void release_file(void *file, unsigned long size);
+
+void fatal(const char *fmt, ...);
+void warn(const char *fmt, ...);
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index 43271a1ca01..8a2875689e4 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -316,8 +316,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
file = grab_file(cmd, &flen);
if (!file) {
- fprintf(stderr, "Warning: could not find %s for %s\n",
- cmd, objfile);
+ warn("could not find %s for %s\n", cmd, objfile);
goto out;
}
@@ -355,9 +354,8 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
/* Check if this file is in same dir as objfile */
if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) {
if (!parse_file(line, md)) {
- fprintf(stderr,
- "Warning: could not open %s: %s\n",
- line, strerror(errno));
+ warn("could not open %s: %s\n",
+ line, strerror(errno));
goto out_file;
}
@@ -383,8 +381,11 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen)
struct md4_ctx md;
char *sources, *end, *fname;
const char *basename;
- char filelist[strlen(getenv("MODVERDIR")) + strlen("/") +
- strlen(modname) - strlen(".o") + strlen(".mod") + 1 ];
+ char filelist[PATH_MAX + 1];
+ char *modverdir = getenv("MODVERDIR");
+
+ if (!modverdir)
+ modverdir = ".";
/* Source files for module are in .tmp_versions/modname.mod,
after the first line. */
@@ -392,28 +393,25 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen)
basename = strrchr(modname, '/') + 1;
else
basename = modname;
- sprintf(filelist, "%s/%.*s.mod", getenv("MODVERDIR"),
+ sprintf(filelist, "%s/%.*s.mod", modverdir,
(int) strlen(basename) - 2, basename);
file = grab_file(filelist, &len);
if (!file) {
- fprintf(stderr, "Warning: could not find versions for %s\n",
- filelist);
+ warn("could not find versions for %s\n", filelist);
return;
}
sources = strchr(file, '\n');
if (!sources) {
- fprintf(stderr, "Warning: malformed versions file for %s\n",
- modname);
+ warn("malformed versions file for %s\n", modname);
goto release;
}
sources++;
end = strchr(sources, '\n');
if (!end) {
- fprintf(stderr, "Warning: bad ending versions file for %s\n",
- modname);
+ warn("bad ending versions file for %s\n", modname);
goto release;
}
*end = '\0';
@@ -438,19 +436,19 @@ static void write_version(const char *filename, const char *sum,
fd = open(filename, O_RDWR);
if (fd < 0) {
- fprintf(stderr, "Warning: changing sum in %s failed: %s\n",
+ warn("changing sum in %s failed: %s\n",
filename, strerror(errno));
return;
}
if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
- fprintf(stderr, "Warning: changing sum in %s:%lu failed: %s\n",
+ warn("changing sum in %s:%lu failed: %s\n",
filename, offset, strerror(errno));
goto out;
}
if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) {
- fprintf(stderr, "Warning: writing sum in %s failed: %s\n",
+ warn("writing sum in %s failed: %s\n",
filename, strerror(errno));
goto out;
}
diff --git a/scripts/namespace.pl b/scripts/namespace.pl
index 88e30e82f1c..f34373853ef 100644
--- a/scripts/namespace.pl
+++ b/scripts/namespace.pl
@@ -66,8 +66,8 @@ require 5; # at least perl 5
use strict;
use File::Find;
-my $nm = "/usr/bin/nm -p";
-my $objdump = "/usr/bin/objdump -s -j .comment";
+my $nm = ($ENV{'NM'} || "nm") . " -p";
+my $objdump = ($ENV{'OBJDUMP'} || "objdump") . " -s -j .comment";
my $srctree = "";
my $objtree = "";
$srctree = "$ENV{'srctree'}/" if (exists($ENV{'srctree'}));
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index c201ef001f0..7c434e037e7 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -32,12 +32,11 @@ MKSPEC := $(srctree)/scripts/package/mkspec
PREV := set -e; cd ..;
# rpm-pkg
-.PHONY: rpm-pkg rpm
-
+# ---------------------------------------------------------------------------
$(objtree)/kernel.spec: $(MKSPEC) $(srctree)/Makefile
$(CONFIG_SHELL) $(MKSPEC) > $@
-rpm-pkg rpm: $(objtree)/kernel.spec
+rpm-pkg rpm: $(objtree)/kernel.spec FORCE
$(MAKE) clean
$(PREV) ln -sf $(srctree) $(KERNELPATH)
$(PREV) tar -cz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/.
@@ -54,11 +53,11 @@ rpm-pkg rpm: $(objtree)/kernel.spec
clean-files := $(objtree)/kernel.spec
# binrpm-pkg
-.PHONY: binrpm-pkg
+# ---------------------------------------------------------------------------
$(objtree)/binkernel.spec: $(MKSPEC) $(srctree)/Makefile
$(CONFIG_SHELL) $(MKSPEC) prebuilt > $@
-
-binrpm-pkg: $(objtree)/binkernel.spec
+
+binrpm-pkg: $(objtree)/binkernel.spec FORCE
$(MAKE) KBUILD_SRC=
set -e; \
$(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version
@@ -71,9 +70,7 @@ clean-files += $(objtree)/binkernel.spec
# Deb target
# ---------------------------------------------------------------------------
-#
-.PHONY: deb-pkg
-deb-pkg:
+deb-pkg: FORCE
$(MAKE) KBUILD_SRC=
$(CONFIG_SHELL) $(srctree)/scripts/package/builddeb
@@ -82,8 +79,7 @@ clean-dirs += $(objtree)/debian/
# tarball targets
# ---------------------------------------------------------------------------
-.PHONY: tar%pkg
-tar%pkg:
+tar%pkg: FORCE
$(MAKE) KBUILD_SRC=
$(CONFIG_SHELL) $(srctree)/scripts/package/buildtar $@
@@ -92,7 +88,7 @@ clean-dirs += $(objtree)/tar-install/
# Help text displayed when executing 'make help'
# ---------------------------------------------------------------------------
-help:
+help: FORCE
@echo ' rpm-pkg - Build the kernel as an RPM package'
@echo ' binrpm-pkg - Build an rpm package containing the compiled kernel'
@echo ' and modules'
diff --git a/scripts/profile2linkerlist.pl b/scripts/profile2linkerlist.pl
new file mode 100644
index 00000000000..cb4260ebdb9
--- /dev/null
+++ b/scripts/profile2linkerlist.pl
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+
+#
+# Takes a (sorted) output of readprofile and turns it into a list suitable for
+# linker scripts
+#
+# usage:
+# readprofile | sort -rn | perl profile2linkerlist.pl > functionlist
+#
+
+while (<>) {
+ my $line = $_;
+
+ $_ =~ /\W*[0-9]+\W*([a-zA-Z\_0-9]+)\W*[0-9]+/;
+
+ if ( ($line =~ /unknown/) || ($line =~ /total/)) {
+
+ } else {
+ print "*(.text.$1)\n";
+ }
+}
diff --git a/scripts/reference_discarded.pl b/scripts/reference_discarded.pl
deleted file mode 100644
index 4ee6ab2135b..00000000000
--- a/scripts/reference_discarded.pl
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/perl -w
-#
-# reference_discarded.pl (C) Keith Owens 2001 <kaos@ocs.com.au>
-#
-# Released under GPL V2.
-#
-# List dangling references to vmlinux discarded sections.
-
-use strict;
-die($0 . " takes no arguments\n") if($#ARGV >= 0);
-
-my %object;
-my $object;
-my $line;
-my $ignore;
-my $errorcount;
-
-$| = 1;
-
-# printf("Finding objects, ");
-open(OBJDUMP_LIST, "find . -name '*.o' | xargs objdump -h |") || die "getting objdump list failed";
-while (defined($line = <OBJDUMP_LIST>)) {
- chomp($line);
- if ($line =~ /:\s+file format/) {
- ($object = $line) =~ s/:.*//;
- $object{$object}->{'module'} = 0;
- $object{$object}->{'size'} = 0;
- $object{$object}->{'off'} = 0;
- }
- if ($line =~ /^\s*\d+\s+\.modinfo\s+/) {
- $object{$object}->{'module'} = 1;
- }
- if ($line =~ /^\s*\d+\s+\.comment\s+/) {
- ($object{$object}->{'size'}, $object{$object}->{'off'}) = (split(' ', $line))[2,5];
- }
-}
-close(OBJDUMP_LIST);
-# printf("%d objects, ", scalar keys(%object));
-$ignore = 0;
-foreach $object (keys(%object)) {
- if ($object{$object}->{'module'}) {
- ++$ignore;
- delete($object{$object});
- }
-}
-# printf("ignoring %d module(s)\n", $ignore);
-
-# Ignore conglomerate objects, they have been built from multiple objects and we
-# only care about the individual objects. If an object has more than one GCC:
-# string in the comment section then it is conglomerate. This does not filter
-# out conglomerates that consist of exactly one object, can't be helped.
-
-# printf("Finding conglomerates, ");
-$ignore = 0;
-foreach $object (keys(%object)) {
- if (exists($object{$object}->{'off'})) {
- my ($off, $size, $comment, $l);
- $off = hex($object{$object}->{'off'});
- $size = hex($object{$object}->{'size'});
- open(OBJECT, "<$object") || die "cannot read $object";
- seek(OBJECT, $off, 0) || die "seek to $off in $object failed";
- $l = read(OBJECT, $comment, $size);
- die "read $size bytes from $object .comment failed" if ($l != $size);
- close(OBJECT);
- if ($comment =~ /GCC\:.*GCC\:/m || $object =~ /built-in\.o/) {
- ++$ignore;
- delete($object{$object});
- }
- }
-}
-# printf("ignoring %d conglomerate(s)\n", $ignore);
-
-# printf("Scanning objects\n");
-
-# Keith Ownes <kaos@sgi.com> commented:
-# For our future {in}sanity, add a comment that this is the ppc .opd
-# section, not the ia64 .opd section.
-# ia64 .opd should not point to discarded sections.
-$errorcount = 0;
-foreach $object (keys(%object)) {
- my $from;
- open(OBJDUMP, "objdump -r $object|") || die "cannot objdump -r $object";
- while (defined($line = <OBJDUMP>)) {
- chomp($line);
- if ($line =~ /RELOCATION RECORDS FOR /) {
- ($from = $line) =~ s/.*\[([^]]*).*/$1/;
- }
- if (($line =~ /\.text\.exit$/ ||
- $line =~ /\.exit\.text$/ ||
- $line =~ /\.data\.exit$/ ||
- $line =~ /\.exit\.data$/ ||
- $line =~ /\.exitcall\.exit$/) &&
- ($from !~ /\.text\.exit$/ &&
- $from !~ /\.exit\.text$/ &&
- $from !~ /\.data\.exit$/ &&
- $from !~ /\.opd$/ &&
- $from !~ /\.exit\.data$/ &&
- $from !~ /\.altinstructions$/ &&
- $from !~ /\.pdr$/ &&
- $from !~ /\.debug_.*$/ &&
- $from !~ /\.exitcall\.exit$/ &&
- $from !~ /\.eh_frame$/ &&
- $from !~ /\.stab$/)) {
- printf("Error: %s %s refers to %s\n", $object, $from, $line);
- $errorcount = $errorcount + 1;
- }
- }
- close(OBJDUMP);
-}
-# printf("Done\n");
-
-exit(0);
diff --git a/scripts/reference_init.pl b/scripts/reference_init.pl
deleted file mode 100644
index 7f6960b175a..00000000000
--- a/scripts/reference_init.pl
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/perl -w
-#
-# reference_init.pl (C) Keith Owens 2002 <kaos@ocs.com.au>
-#
-# List references to vmlinux init sections from non-init sections.
-
-# Unfortunately I had to exclude references from read only data to .init
-# sections, almost all of these are false positives, they are created by
-# gcc. The downside of excluding rodata is that there really are some
-# user references from rodata to init code, e.g. drivers/video/vgacon.c
-#
-# const struct consw vga_con = {
-# con_startup: vgacon_startup,
-#
-# where vgacon_startup is __init. If you want to wade through the false
-# positives, take out the check for rodata.
-
-use strict;
-die($0 . " takes no arguments\n") if($#ARGV >= 0);
-
-my %object;
-my $object;
-my $line;
-my $ignore;
-
-$| = 1;
-
-printf("Finding objects, ");
-open(OBJDUMP_LIST, "find . -name '*.o' | xargs objdump -h |") || die "getting objdump list failed";
-while (defined($line = <OBJDUMP_LIST>)) {
- chomp($line);
- if ($line =~ /:\s+file format/) {
- ($object = $line) =~ s/:.*//;
- $object{$object}->{'module'} = 0;
- $object{$object}->{'size'} = 0;
- $object{$object}->{'off'} = 0;
- }
- if ($line =~ /^\s*\d+\s+\.modinfo\s+/) {
- $object{$object}->{'module'} = 1;
- }
- if ($line =~ /^\s*\d+\s+\.comment\s+/) {
- ($object{$object}->{'size'}, $object{$object}->{'off'}) = (split(' ', $line))[2,5];
- }
-}
-close(OBJDUMP_LIST);
-printf("%d objects, ", scalar keys(%object));
-$ignore = 0;
-foreach $object (keys(%object)) {
- if ($object{$object}->{'module'}) {
- ++$ignore;
- delete($object{$object});
- }
-}
-printf("ignoring %d module(s)\n", $ignore);
-
-# Ignore conglomerate objects, they have been built from multiple objects and we
-# only care about the individual objects. If an object has more than one GCC:
-# string in the comment section then it is conglomerate. This does not filter
-# out conglomerates that consist of exactly one object, can't be helped.
-
-printf("Finding conglomerates, ");
-$ignore = 0;
-foreach $object (keys(%object)) {
- if (exists($object{$object}->{'off'})) {
- my ($off, $size, $comment, $l);
- $off = hex($object{$object}->{'off'});
- $size = hex($object{$object}->{'size'});
- open(OBJECT, "<$object") || die "cannot read $object";
- seek(OBJECT, $off, 0) || die "seek to $off in $object failed";
- $l = read(OBJECT, $comment, $size);
- die "read $size bytes from $object .comment failed" if ($l != $size);
- close(OBJECT);
- if ($comment =~ /GCC\:.*GCC\:/m || $object =~ /built-in\.o/) {
- ++$ignore;
- delete($object{$object});
- }
- }
-}
-printf("ignoring %d conglomerate(s)\n", $ignore);
-
-printf("Scanning objects\n");
-foreach $object (sort(keys(%object))) {
- my $from;
- open(OBJDUMP, "objdump -r $object|") || die "cannot objdump -r $object";
- while (defined($line = <OBJDUMP>)) {
- chomp($line);
- if ($line =~ /RELOCATION RECORDS FOR /) {
- ($from = $line) =~ s/.*\[([^]]*).*/$1/;
- }
- if (($line =~ /\.init$/ || $line =~ /\.init\./) &&
- ($from !~ /\.init$/ &&
- $from !~ /\.init\./ &&
- $from !~ /\.stab$/ &&
- $from !~ /\.rodata$/ &&
- $from !~ /\.text\.lock$/ &&
- $from !~ /\.pci_fixup_header$/ &&
- $from !~ /\.pci_fixup_final$/ &&
- $from !~ /\.pdr$/ &&
- $from !~ /\__param$/ &&
- $from !~ /\.altinstructions/ &&
- $from !~ /\.eh_frame/ &&
- $from !~ /\.debug_/)) {
- printf("Error: %s %s refers to %s\n", $object, $from, $line);
- }
- }
- close(OBJDUMP);
-}
-printf("Done\n");
diff --git a/security/commoncap.c b/security/commoncap.c
index 8a6e097f99e..841eb4e5c62 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -60,8 +60,8 @@ int cap_settime(struct timespec *ts, struct timezone *tz)
int cap_ptrace (struct task_struct *parent, struct task_struct *child)
{
/* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
- if (!cap_issubset (child->cap_permitted, current->cap_permitted) &&
- !capable(CAP_SYS_PTRACE))
+ if (!cap_issubset(child->cap_permitted, parent->cap_permitted) &&
+ !__capable(parent, CAP_SYS_PTRACE))
return -EPERM;
return 0;
}
diff --git a/security/dummy.c b/security/dummy.c
index a678f094b72..fd99429278e 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -378,7 +378,7 @@ static int dummy_inode_removexattr (struct dentry *dentry, char *name)
return 0;
}
-static int dummy_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
+static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
{
return -EOPNOTSUPP;
}
@@ -393,6 +393,11 @@ static int dummy_inode_listsecurity(struct inode *inode, char *buffer, size_t bu
return 0;
}
+static const char *dummy_inode_xattr_getsuffix(void)
+{
+ return NULL;
+}
+
static int dummy_file_permission (struct file *file, int mask)
{
return 0;
@@ -558,6 +563,11 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
return 0;
}
+static int dummy_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
+{
+ return -EOPNOTSUPP;
+}
+
static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
{
return 0;
@@ -931,6 +941,7 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, inode_getxattr);
set_to_dummy_if_null(ops, inode_listxattr);
set_to_dummy_if_null(ops, inode_removexattr);
+ set_to_dummy_if_null(ops, inode_xattr_getsuffix);
set_to_dummy_if_null(ops, inode_getsecurity);
set_to_dummy_if_null(ops, inode_setsecurity);
set_to_dummy_if_null(ops, inode_listsecurity);
@@ -965,6 +976,7 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, task_reparent_to_init);
set_to_dummy_if_null(ops, task_to_inode);
set_to_dummy_if_null(ops, ipc_permission);
+ set_to_dummy_if_null(ops, ipc_getsecurity);
set_to_dummy_if_null(ops, msg_msg_alloc_security);
set_to_dummy_if_null(ops, msg_msg_free_security);
set_to_dummy_if_null(ops, msg_queue_alloc_security);
diff --git a/security/keys/key.c b/security/keys/key.c
index 99781b79831..a057e3311aa 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1,6 +1,6 @@
/* key.c: basic authentication token and access key management
*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -271,7 +271,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
* its description */
if (!not_in_quota) {
spin_lock(&user->lock);
- if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS &&
+ if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
)
goto no_quota;
@@ -795,12 +795,16 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
goto error_3;
}
- /* search for an existing key of the same type and description in the
- * destination keyring
+ /* if it's possible to update this type of key, search for an existing
+ * key of the same type and description in the destination keyring and
+ * update that instead if possible
*/
- key_ref = __keyring_search_one(keyring_ref, ktype, description, 0);
- if (!IS_ERR(key_ref))
- goto found_matching_key;
+ if (ktype->update) {
+ key_ref = __keyring_search_one(keyring_ref, ktype, description,
+ 0);
+ if (!IS_ERR(key_ref))
+ goto found_matching_key;
+ }
/* decide on the permissions we want */
perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
diff --git a/security/security.c b/security/security.c
index f693e1f66b9..51ef509710b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -174,31 +174,8 @@ int mod_unreg_security(const char *name, struct security_operations *ops)
return security_ops->unregister_security(name, ops);
}
-/**
- * capable - calls the currently loaded security module's capable() function with the specified capability
- * @cap: the requested capability level.
- *
- * This function calls the currently loaded security module's capable()
- * function with a pointer to the current task and the specified @cap value.
- *
- * This allows the security module to implement the capable function call
- * however it chooses to.
- */
-int capable(int cap)
-{
- if (security_ops->capable(current, cap)) {
- /* capability denied */
- return 0;
- }
-
- /* capability granted */
- current->flags |= PF_SUPERPRIV;
- return 1;
-}
-
EXPORT_SYMBOL_GPL(register_security);
EXPORT_SYMBOL_GPL(unregister_security);
EXPORT_SYMBOL_GPL(mod_reg_security);
EXPORT_SYMBOL_GPL(mod_unreg_security);
-EXPORT_SYMBOL(capable);
EXPORT_SYMBOL(security_ops);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ccaf988f372..b61b9554bc2 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -119,6 +119,32 @@ static DEFINE_SPINLOCK(sb_security_lock);
static kmem_cache_t *sel_inode_cache;
+/* Return security context for a given sid or just the context
+ length if the buffer is null or length is 0 */
+static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
+{
+ char *context;
+ unsigned len;
+ int rc;
+
+ rc = security_sid_to_context(sid, &context, &len);
+ if (rc)
+ return rc;
+
+ if (!buffer || !size)
+ goto getsecurity_exit;
+
+ if (size < len) {
+ len = -ERANGE;
+ goto getsecurity_exit;
+ }
+ memcpy(buffer, context, len);
+
+getsecurity_exit:
+ kfree(context);
+ return len;
+}
+
/* Allocate and free functions for each kind of security blob. */
static int task_alloc_security(struct task_struct *task)
@@ -2210,6 +2236,11 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name)
return -EACCES;
}
+static const char *selinux_inode_xattr_getsuffix(void)
+{
+ return XATTR_SELINUX_SUFFIX;
+}
+
/*
* Copy the in-core inode security context value to the user. If the
* getxattr() prior to this succeeded, check to see if we need to
@@ -2217,47 +2248,14 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name)
*
* Permission check is handled by selinux_inode_getxattr hook.
*/
-static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
+static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
{
struct inode_security_struct *isec = inode->i_security;
- char *context;
- unsigned len;
- int rc;
-
- if (strcmp(name, XATTR_SELINUX_SUFFIX)) {
- rc = -EOPNOTSUPP;
- goto out;
- }
-
- rc = security_sid_to_context(isec->sid, &context, &len);
- if (rc)
- goto out;
-
- /* Probe for required buffer size */
- if (!buffer || !size) {
- rc = len;
- goto out_free;
- }
- if (size < len) {
- rc = -ERANGE;
- goto out_free;
- }
+ if (strcmp(name, XATTR_SELINUX_SUFFIX))
+ return -EOPNOTSUPP;
- if (err > 0) {
- if ((len == err) && !(memcmp(context, buffer, len))) {
- /* Don't need to canonicalize value */
- rc = err;
- goto out_free;
- }
- memset(buffer, 0, size);
- }
- memcpy(buffer, context, len);
- rc = len;
-out_free:
- kfree(context);
-out:
- return rc;
+ return selinux_getsecurity(isec->sid, buffer, size);
}
static int selinux_inode_setsecurity(struct inode *inode, const char *name,
@@ -4054,6 +4052,13 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
return ipc_has_perm(ipcp, av);
}
+static int selinux_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
+{
+ struct ipc_security_struct *isec = ipcp->security;
+
+ return selinux_getsecurity(isec->sid, buffer, size);
+}
+
/* module stacking operations */
static int selinux_register_security (const char *name, struct security_operations *ops)
{
@@ -4095,8 +4100,7 @@ static int selinux_getprocattr(struct task_struct *p,
char *name, void *value, size_t size)
{
struct task_security_struct *tsec;
- u32 sid, len;
- char *context;
+ u32 sid;
int error;
if (current != p) {
@@ -4105,9 +4109,6 @@ static int selinux_getprocattr(struct task_struct *p,
return error;
}
- if (!size)
- return -ERANGE;
-
tsec = p->security;
if (!strcmp(name, "current"))
@@ -4124,16 +4125,7 @@ static int selinux_getprocattr(struct task_struct *p,
if (!sid)
return 0;
- error = security_sid_to_context(sid, &context, &len);
- if (error)
- return error;
- if (len > size) {
- kfree(context);
- return -ERANGE;
- }
- memcpy(value, context, len);
- kfree(context);
- return len;
+ return selinux_getsecurity(sid, value, size);
}
static int selinux_setprocattr(struct task_struct *p,
@@ -4291,6 +4283,7 @@ static struct security_operations selinux_ops = {
.inode_getxattr = selinux_inode_getxattr,
.inode_listxattr = selinux_inode_listxattr,
.inode_removexattr = selinux_inode_removexattr,
+ .inode_xattr_getsuffix = selinux_inode_xattr_getsuffix,
.inode_getsecurity = selinux_inode_getsecurity,
.inode_setsecurity = selinux_inode_setsecurity,
.inode_listsecurity = selinux_inode_listsecurity,
@@ -4328,6 +4321,7 @@ static struct security_operations selinux_ops = {
.task_to_inode = selinux_task_to_inode,
.ipc_permission = selinux_ipc_permission,
+ .ipc_getsecurity = selinux_ipc_getsecurity,
.msg_msg_alloc_security = selinux_msg_msg_alloc_security,
.msg_msg_free_security = selinux_msg_msg_free_security,
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 85e39925983..b8f4d25cf33 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -106,6 +106,9 @@ static struct nlmsg_perm nlmsg_audit_perms[] =
{ AUDIT_LIST, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV },
{ AUDIT_ADD, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
{ AUDIT_DEL, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
+ { AUDIT_LIST_RULES, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV },
+ { AUDIT_ADD_RULE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
+ { AUDIT_DEL_RULE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
{ AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_RELAY },
{ AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ },
};
@@ -152,8 +155,10 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
break;
case SECCLASS_NETLINK_AUDIT_SOCKET:
- if (nlmsg_type >= AUDIT_FIRST_USER_MSG &&
- nlmsg_type <= AUDIT_LAST_USER_MSG) {
+ if ((nlmsg_type >= AUDIT_FIRST_USER_MSG &&
+ nlmsg_type <= AUDIT_LAST_USER_MSG) ||
+ (nlmsg_type >= AUDIT_FIRST_USER_MSG2 &&
+ nlmsg_type <= AUDIT_LAST_USER_MSG2)) {
*perm = NETLINK_AUDIT_SOCKET__NLMSG_RELAY;
} else {
err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms,
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index f5d78365488..a4efc966f06 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -22,6 +22,7 @@
#include <linux/major.h>
#include <linux/seq_file.h>
#include <linux/percpu.h>
+#include <linux/audit.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
@@ -127,6 +128,10 @@ static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
length = task_has_security(current, SECURITY__SETENFORCE);
if (length)
goto out;
+ audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
+ "enforcing=%d old_enforcing=%d auid=%u", new_value,
+ selinux_enforcing,
+ audit_get_loginuid(current->audit_context));
selinux_enforcing = new_value;
if (selinux_enforcing)
avc_ss_reset(0);
@@ -177,6 +182,9 @@ static ssize_t sel_write_disable(struct file * file, const char __user * buf,
length = selinux_disable();
if (length < 0)
goto out;
+ audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
+ "selinux=0 auid=%u",
+ audit_get_loginuid(current->audit_context));
}
length = count;
@@ -262,6 +270,9 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
length = ret;
else
length = count;
+ audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
+ "policy loaded auid=%u",
+ audit_get_loginuid(current->audit_context));
out:
mutex_unlock(&sel_mutex);
vfree(data);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 63e0b7f29cb..61492485de8 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1759,19 +1759,22 @@ int security_set_bools(int len, int *values)
goto out;
}
- printk(KERN_INFO "security: committed booleans { ");
for (i = 0; i < len; i++) {
+ if (!!values[i] != policydb.bool_val_to_struct[i]->state) {
+ audit_log(current->audit_context, GFP_ATOMIC,
+ AUDIT_MAC_CONFIG_CHANGE,
+ "bool=%s val=%d old_val=%d auid=%u",
+ policydb.p_bool_val_to_name[i],
+ !!values[i],
+ policydb.bool_val_to_struct[i]->state,
+ audit_get_loginuid(current->audit_context));
+ }
if (values[i]) {
policydb.bool_val_to_struct[i]->state = 1;
} else {
policydb.bool_val_to_struct[i]->state = 0;
}
- if (i != 0)
- printk(", ");
- printk("%s:%d", policydb.p_bool_val_to_name[i],
- policydb.bool_val_to_struct[i]->state);
}
- printk(" }\n");
for (cur = policydb.cond_list; cur != NULL; cur = cur->next) {
rc = evaluate_cond_node(&policydb, cur);
diff --git a/sound/core/init.c b/sound/core/init.c
index ad68761abba..5bb8a8b23d5 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -223,7 +223,8 @@ int snd_card_disconnect(struct snd_card *card)
struct snd_monitor_file *mfile;
struct file *file;
struct snd_shutdown_f_ops *s_f_ops;
- struct file_operations *f_ops, *old_f_ops;
+ struct file_operations *f_ops;
+ const struct file_operations *old_f_ops;
int err;
spin_lock(&card->files_lock);
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 6b7a3677429..87b47c9564f 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -631,7 +631,8 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
return -EINVAL;
}
if (params->buffer_size != runtime->buffer_size) {
- if ((newbuf = (char *) kmalloc(params->buffer_size, GFP_KERNEL)) == NULL)
+ newbuf = kmalloc(params->buffer_size, GFP_KERNEL);
+ if (!newbuf)
return -ENOMEM;
kfree(runtime->buffer);
runtime->buffer = newbuf;
@@ -657,7 +658,8 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
return -EINVAL;
}
if (params->buffer_size != runtime->buffer_size) {
- if ((newbuf = (char *) kmalloc(params->buffer_size, GFP_KERNEL)) == NULL)
+ newbuf = kmalloc(params->buffer_size, GFP_KERNEL);
+ if (!newbuf)
return -ENOMEM;
kfree(runtime->buffer);
runtime->buffer = newbuf;
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 4d28e521261..108e430b503 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -137,7 +137,7 @@ static int snd_open(struct inode *inode, struct file *file)
{
unsigned int minor = iminor(inode);
struct snd_minor *mptr = NULL;
- struct file_operations *old_fops;
+ const struct file_operations *old_fops;
int err = 0;
if (minor >= ARRAY_SIZE(snd_minors))
@@ -240,7 +240,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
* Retrurns zero if successful, or a negative error code on failure.
*/
int snd_register_device(int type, struct snd_card *card, int dev,
- struct file_operations *f_ops, void *private_data,
+ const struct file_operations *f_ops, void *private_data,
const char *name)
{
int minor;
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index 4023d3b406d..9055c6de958 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -95,7 +95,7 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
}
int snd_register_oss_device(int type, struct snd_card *card, int dev,
- struct file_operations *f_ops, void *private_data,
+ const struct file_operations *f_ops, void *private_data,
const char *name)
{
int minor = snd_oss_kernel_minor(type, card, dev);
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index 9d10d79e27a..9ea3059a706 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -59,7 +59,8 @@ module_param_array(irq, int, NULL, 0444);
MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
static struct platform_device *platform_devices[SNDRV_CARDS];
-static int pnp_registered = 0;
+static int pnp_registered;
+static unsigned int snd_mpu401_devices;
static int snd_mpu401_create(int dev, struct snd_card **rcard)
{
@@ -197,6 +198,7 @@ static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
}
snd_card_set_dev(card, &pnp_dev->dev);
pnp_set_drvdata(pnp_dev, card);
+ snd_mpu401_devices++;
++dev;
return 0;
}
@@ -234,12 +236,11 @@ static void __init_or_module snd_mpu401_unregister_all(void)
static int __init alsa_card_mpu401_init(void)
{
- int i, err, devices;
+ int i, err;
if ((err = platform_driver_register(&snd_mpu401_driver)) < 0)
return err;
- devices = 0;
for (i = 0; i < SNDRV_CARDS; i++) {
struct platform_device *device;
if (! enable[i])
@@ -255,14 +256,13 @@ static int __init alsa_card_mpu401_init(void)
goto errout;
}
platform_devices[i] = device;
- devices++;
+ snd_mpu401_devices++;
}
- if ((err = pnp_register_driver(&snd_mpu401_pnp_driver)) >= 0) {
+ err = pnp_register_driver(&snd_mpu401_pnp_driver);
+ if (!err)
pnp_registered = 1;
- devices += err;
- }
- if (!devices) {
+ if (!snd_mpu401_devices) {
#ifdef MODULE
printk(KERN_ERR "MPU-401 device not found or device busy\n");
#endif
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index 7051f7798ed..31f299aed28 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -262,6 +262,8 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard
return 0;
}
+static unsigned int __devinitdata ad1816a_devices;
+
static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card,
const struct pnp_card_device_id *id)
{
@@ -275,6 +277,7 @@ static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card,
if (res < 0)
return res;
dev++;
+ ad1816a_devices++;
return 0;
}
return -ENODEV;
@@ -297,10 +300,13 @@ static struct pnp_card_driver ad1816a_pnpc_driver = {
static int __init alsa_card_ad1816a_init(void)
{
- int cards;
+ int err;
+
+ err = pnp_register_card_driver(&ad1816a_pnpc_driver);
+ if (err)
+ return err;
- cards = pnp_register_card_driver(&ad1816a_pnpc_driver);
- if (cards <= 0) {
+ if (!ad1816a_devices) {
pnp_unregister_card_driver(&ad1816a_pnpc_driver);
#ifdef MODULE
printk(KERN_ERR "no AD1816A based soundcards found.\n");
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index 9b77c17b3f6..a52bd8a14c9 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -199,7 +199,7 @@ static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
return 0;
}
-static int __init snd_card_als100_probe(int dev,
+static int __devinit snd_card_als100_probe(int dev,
struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
@@ -281,6 +281,8 @@ static int __init snd_card_als100_probe(int dev,
return 0;
}
+static unsigned int __devinitdata als100_devices;
+
static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
const struct pnp_card_device_id *id)
{
@@ -294,6 +296,7 @@ static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
if (res < 0)
return res;
dev++;
+ als100_devices++;
return 0;
}
return -ENODEV;
@@ -345,10 +348,13 @@ static struct pnp_card_driver als100_pnpc_driver = {
static int __init alsa_card_als100_init(void)
{
- int cards;
+ int err;
+
+ err = pnp_register_card_driver(&als100_pnpc_driver);
+ if (err)
+ return err;
- cards = pnp_register_card_driver(&als100_pnpc_driver);
- if (cards <= 0) {
+ if (!als100_devices) {
pnp_unregister_card_driver(&als100_pnpc_driver);
#ifdef MODULE
snd_printk(KERN_ERR "no ALS100 based soundcards found\n");
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
index a530691bf4f..15e59283aac 100644
--- a/sound/isa/azt2320.c
+++ b/sound/isa/azt2320.c
@@ -310,6 +310,8 @@ static int __devinit snd_card_azt2320_probe(int dev,
return 0;
}
+static unsigned int __devinitdata azt2320_devices;
+
static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card,
const struct pnp_card_device_id *id)
{
@@ -323,6 +325,7 @@ static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card,
if (res < 0)
return res;
dev++;
+ azt2320_devices++;
return 0;
}
return -ENODEV;
@@ -372,10 +375,13 @@ static struct pnp_card_driver azt2320_pnpc_driver = {
static int __init alsa_card_azt2320_init(void)
{
- int cards;
+ int err;
+
+ err = pnp_register_card_driver(&azt2320_pnpc_driver);
+ if (err)
+ return err;
- cards = pnp_register_card_driver(&azt2320_pnpc_driver);
- if (cards <= 0) {
+ if (!azt2320_devices) {
pnp_unregister_card_driver(&azt2320_pnpc_driver);
#ifdef MODULE
snd_printk(KERN_ERR "no AZT2320 based soundcards found\n");
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index fd9bb2575de..fa63048a8b9 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -175,7 +175,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids);
#endif
-static struct ad1848_mix_elem snd_cmi8330_controls[] __initdata = {
+static struct ad1848_mix_elem snd_cmi8330_controls[] __devinitdata = {
AD1848_DOUBLE("Master Playback Volume", 0, CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0),
AD1848_SINGLE("Loud Playback Switch", 0, CMI8330_MUTEMUX, 6, 1, 1),
AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1),
@@ -204,7 +204,7 @@ AD1848_SINGLE(SNDRV_CTL_NAME_IEC958("Input ",PLAYBACK,SWITCH), 0, CMI8330_MUTEMU
};
#ifdef ENABLE_SB_MIXER
-static struct sbmix_elem cmi8330_sb_mixers[] __initdata = {
+static struct sbmix_elem cmi8330_sb_mixers[] __devinitdata = {
SB_DOUBLE("SB Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31),
SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15),
SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15),
@@ -222,7 +222,7 @@ SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6
SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
};
-static unsigned char cmi8330_sb_init_values[][2] __initdata = {
+static unsigned char cmi8330_sb_init_values[][2] __devinitdata = {
{ SB_DSP4_MASTER_DEV + 0, 0 },
{ SB_DSP4_MASTER_DEV + 1, 0 },
{ SB_DSP4_PCM_DEV + 0, 0 },
@@ -545,7 +545,7 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
return snd_card_register(card);
}
-static int __init snd_cmi8330_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_cmi8330_nonpnp_probe(struct platform_device *pdev)
{
struct snd_card *card;
int err;
@@ -607,6 +607,8 @@ static struct platform_driver snd_cmi8330_driver = {
#ifdef CONFIG_PNP
+static unsigned int __devinitdata cmi8330_pnp_devices;
+
static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
@@ -636,6 +638,7 @@ static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
}
pnp_set_card_drvdata(pcard, card);
dev++;
+ cmi8330_pnp_devices++;
return 0;
}
@@ -706,9 +709,9 @@ static int __init alsa_card_cmi8330_init(void)
#ifdef CONFIG_PNP
err = pnp_register_card_driver(&cmi8330_pnpc_driver);
- if (err >= 0) {
+ if (!err) {
pnp_registered = 1;
- cards += err;
+ cards += cmi8330_pnp_devices;
}
#endif
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 4060918e032..382bb17ef49 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -133,6 +133,7 @@ static int pnpc_registered;
static int pnp_registered;
#endif
#endif /* CONFIG_PNP */
+static unsigned int snd_cs423x_devices;
struct snd_card_cs4236 {
struct snd_cs4231 *chip;
@@ -564,7 +565,7 @@ static int __init snd_cs423x_nonpnp_probe(struct platform_device *pdev)
snd_card_free(card);
return err;
}
-
+
platform_set_drvdata(pdev, card);
return 0;
}
@@ -650,6 +651,7 @@ static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev,
}
pnp_set_drvdata(pdev, card);
dev++;
+ snd_cs423x_devices++;
return 0;
}
@@ -713,6 +715,7 @@ static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
}
pnp_set_card_drvdata(pcard, card);
dev++;
+ snd_cs423x_devices++;
return 0;
}
@@ -721,7 +724,7 @@ static void __devexit snd_cs423x_pnpc_remove(struct pnp_card_link * pcard)
snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
}
-
+
#ifdef CONFIG_PM
static int snd_cs423x_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state)
{
@@ -766,7 +769,7 @@ static void __init_or_module snd_cs423x_unregister_all(void)
static int __init alsa_card_cs423x_init(void)
{
- int i, err, cards = 0;
+ int i, err;
if ((err = platform_driver_register(&cs423x_nonpnp_driver)) < 0)
return err;
@@ -782,24 +785,20 @@ static int __init alsa_card_cs423x_init(void)
goto errout;
}
platform_devices[i] = device;
- cards++;
+ snd_cs423x_devices++;
}
#ifdef CONFIG_PNP
#ifdef CS4232
- i = pnp_register_driver(&cs4232_pnp_driver);
- if (i >= 0) {
+ err = pnp_register_driver(&cs4232_pnp_driver);
+ if (!err)
pnp_registered = 1;
- cards += i;
- }
#endif
- i = pnp_register_card_driver(&cs423x_pnpc_driver);
- if (i >= 0) {
+ err = pnp_register_card_driver(&cs423x_pnpc_driver);
+ if (!err)
pnpc_registered = 1;
- cards += i;
- }
#endif /* CONFIG_PNP */
- if (!cards) {
+ if (!snd_cs423x_devices) {
#ifdef MODULE
printk(KERN_ERR IDENT " soundcard not found or device busy\n");
#endif
diff --git a/sound/isa/dt019x.c b/sound/isa/dt019x.c
index 50e7bc5ef56..0acb4e5da47 100644
--- a/sound/isa/dt019x.c
+++ b/sound/isa/dt019x.c
@@ -272,6 +272,8 @@ static int __devinit snd_card_dt019x_probe(int dev, struct pnp_card_link *pcard,
return 0;
}
+static unsigned int __devinitdata dt019x_devices;
+
static int __devinit snd_dt019x_pnp_probe(struct pnp_card_link *card,
const struct pnp_card_device_id *pid)
{
@@ -285,6 +287,7 @@ static int __devinit snd_dt019x_pnp_probe(struct pnp_card_link *card,
if (res < 0)
return res;
dev++;
+ dt019x_devices++;
return 0;
}
return -ENODEV;
@@ -336,10 +339,13 @@ static struct pnp_card_driver dt019x_pnpc_driver = {
static int __init alsa_card_dt019x_init(void)
{
- int cards = 0;
+ int err;
+
+ err = pnp_register_card_driver(&dt019x_pnpc_driver);
+ if (err)
+ return err;
- cards = pnp_register_card_driver(&dt019x_pnpc_driver);
- if (cards <= 0) {
+ if (!dt019x_devices) {
pnp_unregister_card_driver(&dt019x_pnpc_driver);
#ifdef MODULE
snd_printk(KERN_ERR "no DT-019X / ALS-007 based soundcards found\n");
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 721955d2619..9fbc185b4cc 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -2204,7 +2204,7 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
return snd_card_register(card);
}
-static int __init snd_es18xx_nonpnp_probe1(int dev, struct platform_device *devptr)
+static int __devinit snd_es18xx_nonpnp_probe1(int dev, struct platform_device *devptr)
{
struct snd_card *card;
int err;
@@ -2221,7 +2221,7 @@ static int __init snd_es18xx_nonpnp_probe1(int dev, struct platform_device *devp
return 0;
}
-static int __init snd_es18xx_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev)
{
int dev = pdev->id;
int err;
@@ -2297,6 +2297,8 @@ static struct platform_driver snd_es18xx_nonpnp_driver = {
#ifdef CONFIG_PNP
+static unsigned int __devinitdata es18xx_pnp_devices;
+
static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
@@ -2327,6 +2329,7 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard,
pnp_set_card_drvdata(pcard, card);
dev++;
+ es18xx_pnp_devices++;
return 0;
}
@@ -2397,10 +2400,10 @@ static int __init alsa_card_es18xx_init(void)
}
#ifdef CONFIG_PNP
- i = pnp_register_card_driver(&es18xx_pnpc_driver);
- if (i >= 0) {
+ err = pnp_register_card_driver(&es18xx_pnpc_driver);
+ if (!err) {
pnp_registered = 1;
- cards += i;
+ cards += es18xx_pnp_devices;
}
#endif
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 2cacd0fa687..de71b7a99c8 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -791,7 +791,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
return 0;
}
-static int __init snd_interwave_nonpnp_probe1(int dev, struct platform_device *devptr)
+static int __devinit snd_interwave_nonpnp_probe1(int dev, struct platform_device *devptr)
{
struct snd_card *card;
int err;
@@ -809,7 +809,7 @@ static int __init snd_interwave_nonpnp_probe1(int dev, struct platform_device *d
return 0;
}
-static int __init snd_interwave_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev)
{
int dev = pdev->id;
int err;
@@ -867,6 +867,7 @@ static struct platform_driver snd_interwave_driver = {
};
#ifdef CONFIG_PNP
+static unsigned int __devinitdata interwave_pnp_devices;
static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
@@ -897,6 +898,7 @@ static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
}
pnp_set_card_drvdata(pcard, card);
dev++;
+ interwave_pnp_devices++;
return 0;
}
@@ -954,10 +956,10 @@ static int __init alsa_card_interwave_init(void)
}
/* ISA PnP cards */
- i = pnp_register_card_driver(&interwave_pnpc_driver);
- if (i >= 0) {
+ err = pnp_register_card_driver(&interwave_pnpc_driver);
+ if (!err) {
pnp_registered = 1;
- cards += i;
+ cards += interwave_pnp_devices;;
}
if (!cards) {
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 56fcd8a946a..c906e205d7d 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -95,6 +95,7 @@ static struct platform_device *platform_devices[SNDRV_CARDS];
static int pnp_registered;
static int pnpc_registered;
#endif
+static unsigned int snd_opl3sa2_devices;
/* control ports */
#define OPL3SA2_PM_CTRL 0x01
@@ -760,6 +761,7 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
}
pnp_set_drvdata(pdev, card);
dev++;
+ snd_opl3sa2_devices++;
return 0;
}
@@ -826,6 +828,7 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
}
pnp_set_card_drvdata(pcard, card);
dev++;
+ snd_opl3sa2_devices++;
return 0;
}
@@ -944,7 +947,7 @@ static void __init_or_module snd_opl3sa2_unregister_all(void)
static int __init alsa_card_opl3sa2_init(void)
{
- int i, err, cards = 0;
+ int i, err;
if ((err = platform_driver_register(&snd_opl3sa2_nonpnp_driver)) < 0)
return err;
@@ -964,23 +967,19 @@ static int __init alsa_card_opl3sa2_init(void)
goto errout;
}
platform_devices[i] = device;
- cards++;
+ snd_opl3sa2_devices++;
}
#ifdef CONFIG_PNP
err = pnp_register_driver(&opl3sa2_pnp_driver);
- if (err >= 0) {
+ if (!err)
pnp_registered = 1;
- cards += err;
- }
err = pnp_register_card_driver(&opl3sa2_pnpc_driver);
- if (err >= 0) {
+ if (!err)
pnpc_registered = 1;
- cards += err;
- }
#endif
- if (!cards) {
+ if (!snd_opl3sa2_devices) {
#ifdef MODULE
snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n");
#endif
diff --git a/sound/isa/sb/es968.c b/sound/isa/sb/es968.c
index 9da80bfa302..d4d65b84265 100644
--- a/sound/isa/sb/es968.c
+++ b/sound/isa/sb/es968.c
@@ -124,7 +124,7 @@ static int __devinit snd_card_es968_pnp(int dev, struct snd_card_es968 *acard,
return 0;
}
-static int __init snd_card_es968_probe(int dev,
+static int __devinit snd_card_es968_probe(int dev,
struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
@@ -182,6 +182,8 @@ static int __init snd_card_es968_probe(int dev,
return 0;
}
+static unsigned int __devinitdata es968_devices;
+
static int __devinit snd_es968_pnp_detect(struct pnp_card_link *card,
const struct pnp_card_device_id *id)
{
@@ -195,6 +197,7 @@ static int __devinit snd_es968_pnp_detect(struct pnp_card_link *card,
if (res < 0)
return res;
dev++;
+ es968_devices++;
return 0;
}
return -ENODEV;
@@ -246,8 +249,11 @@ static struct pnp_card_driver es968_pnpc_driver = {
static int __init alsa_card_es968_init(void)
{
- int cards = pnp_register_card_driver(&es968_pnpc_driver);
- if (cards <= 0) {
+ int err = pnp_register_card_driver(&es968_pnpc_driver);
+ if (err)
+ return err;
+
+ if (!es968_devices) {
pnp_unregister_card_driver(&es968_pnpc_driver);
#ifdef MODULE
snd_printk(KERN_ERR "no ES968 based soundcards found\n");
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 5737ab76160..21ea65925a9 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -369,7 +369,7 @@ static struct snd_card *snd_sb16_card_new(int dev)
return card;
}
-static int __init snd_sb16_probe(struct snd_card *card, int dev)
+static int __devinit snd_sb16_probe(struct snd_card *card, int dev)
{
int xirq, xdma8, xdma16;
struct snd_sb *chip;
@@ -518,7 +518,7 @@ static int snd_sb16_resume(struct snd_card *card)
}
#endif
-static int __init snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr)
+static int __devinit snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr)
{
struct snd_card_sb16 *acard;
struct snd_card *card;
@@ -548,7 +548,7 @@ static int __init snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr
}
-static int __init snd_sb16_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev)
{
int dev = pdev->id;
int err;
@@ -629,6 +629,7 @@ static struct platform_driver snd_sb16_nonpnp_driver = {
#ifdef CONFIG_PNP
+static unsigned int __devinitdata sb16_pnp_devices;
static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
@@ -651,6 +652,7 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
}
pnp_set_card_drvdata(pcard, card);
dev++;
+ sb16_pnp_devices++;
return 0;
}
@@ -727,10 +729,10 @@ static int __init alsa_card_sb16_init(void)
}
#ifdef CONFIG_PNP
/* PnP cards at last */
- i = pnp_register_card_driver(&sb16_pnpc_driver);
- if (i >= 0) {
+ err = pnp_register_card_driver(&sb16_pnpc_driver);
+ if (!err) {
pnp_registered = 1;
- cards += i;
+ cards += sb16_pnp_devices;
}
#endif
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 29bba8cc3ef..48e5552d344 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -1255,7 +1255,7 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp)
}
-static int __init snd_sscape_probe(struct platform_device *pdev)
+static int __devinit snd_sscape_probe(struct platform_device *pdev)
{
int dev = pdev->id;
struct snd_card *card;
@@ -1469,7 +1469,7 @@ static int __init sscape_init(void)
if (ret < 0)
return ret;
#ifdef CONFIG_PNP
- if (pnp_register_card_driver(&sscape_pnpc_driver) >= 0)
+ if (pnp_register_card_driver(&sscape_pnpc_driver) == 0)
pnp_registered = 1;
#endif
return 0;
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index c0115bf9065..2f13cd5d4dc 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -589,7 +589,7 @@ snd_wavefront_probe (struct snd_card *card, int dev)
return snd_card_register(card);
}
-static int __init snd_wavefront_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_wavefront_nonpnp_probe(struct platform_device *pdev)
{
int dev = pdev->id;
struct snd_card *card;
@@ -637,6 +637,7 @@ static struct platform_driver snd_wavefront_driver = {
#ifdef CONFIG_PNP
+static unsigned int __devinitdata wavefront_pnp_devices;
static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
@@ -670,6 +671,7 @@ static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
pnp_set_card_drvdata(pcard, card);
dev++;
+ wavefront_pnp_devices++;
return 0;
}
@@ -729,10 +731,10 @@ static int __init alsa_card_wavefront_init(void)
}
#ifdef CONFIG_PNP
- i = pnp_register_card_driver(&wavefront_pnpc_driver);
- if (i >= 0) {
+ err = pnp_register_card_driver(&wavefront_pnpc_driver);
+ if (!err) {
pnp_registered = 1;
- cards += i;
+ cards += wavefront_pnp_devices;
}
#endif
diff --git a/sound/oss/.gitignore b/sound/oss/.gitignore
new file mode 100644
index 00000000000..7efb12b4550
--- /dev/null
+++ b/sound/oss/.gitignore
@@ -0,0 +1,4 @@
+#Ignore generated files
+maui_boot.h
+pss_boot.h
+trix_boot.h
diff --git a/sound/oss/au1000.c b/sound/oss/au1000.c
index fe54de25aaf..eacb0aef21e 100644
--- a/sound/oss/au1000.c
+++ b/sound/oss/au1000.c
@@ -100,7 +100,7 @@
/* Boot options */
static int vra = 0; // 0 = no VRA, 1 = use VRA if codec supports it
-MODULE_PARM(vra, "i");
+module_param(vra, bool, 0);
MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it");
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c
index 6a4956b8025..c1168fae6be 100644
--- a/sound/oss/au1550_ac97.c
+++ b/sound/oss/au1550_ac97.c
@@ -79,7 +79,7 @@
* 0 = no VRA, 1 = use VRA if codec supports it
*/
static int vra = 1;
-MODULE_PARM(vra, "i");
+module_param(vra, bool, 0);
MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it");
static struct au1550_state {
diff --git a/sound/oss/awe_wave.c b/sound/oss/awe_wave.c
index b3ea719d33d..d1a0eb294d6 100644
--- a/sound/oss/awe_wave.c
+++ b/sound/oss/awe_wave.c
@@ -2944,7 +2944,7 @@ alloc_new_info(void)
{
awe_voice_list *newlist;
- newlist = (awe_voice_list *)kmalloc(sizeof(*newlist), GFP_KERNEL);
+ newlist = kmalloc(sizeof(*newlist), GFP_KERNEL);
if (newlist == NULL) {
printk(KERN_ERR "AWE32: can't alloc info table\n");
return NULL;
@@ -3547,8 +3547,10 @@ awe_load_guspatch(const char __user *addr, int offs, int size, int pmgr_flag)
smp->checksum_flag = 0;
smp->checksum = 0;
- if ((rc = awe_write_wave_data(addr, sizeof_patch, smprec, -1)) < 0)
+ if ((rc = awe_write_wave_data(addr, sizeof_patch, smprec, -1)) < 0) {
+ kfree(vrec);
return rc;
+ }
sf->mem_ptr += rc;
add_sf_sample(sf, smprec);
diff --git a/sound/oss/cmpci.c b/sound/oss/cmpci.c
index 1fbd5137f6d..de60a059ff5 100644
--- a/sound/oss/cmpci.c
+++ b/sound/oss/cmpci.c
@@ -1713,7 +1713,7 @@ static int mixer_ioctl(struct cm_state *s, unsigned int cmd, unsigned long arg)
case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
if (get_user(val, p))
return -EFAULT;
- i = generic_hweight32(val);
+ i = hweight32(val);
for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
if (!(val & (1 << i)))
continue;
diff --git a/sound/oss/cs4232.c b/sound/oss/cs4232.c
index 7c59e2d4003..c7f86f09c28 100644
--- a/sound/oss/cs4232.c
+++ b/sound/oss/cs4232.c
@@ -360,6 +360,8 @@ static int __initdata synthio = -1;
static int __initdata synthirq = -1;
static int __initdata isapnp = 1;
+static unsigned int cs4232_devices;
+
MODULE_DESCRIPTION("CS4232 based soundcard driver");
MODULE_AUTHOR("Hannu Savolainen, Paul Barton-Davis");
MODULE_LICENSE("GPL");
@@ -421,6 +423,7 @@ static int cs4232_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev
return -ENODEV;
}
pnp_set_drvdata(dev,isapnpcfg);
+ cs4232_devices++;
return 0;
}
@@ -455,10 +458,11 @@ static int __init init_cs4232(void)
#endif
cfg.irq = -1;
- if (isapnp &&
- (pnp_register_driver(&cs4232_driver) > 0)
- )
- return 0;
+ if (isapnp) {
+ pnp_register_driver(&cs4232_driver);
+ if (cs4232_devices)
+ return 0;
+ }
if(io==-1||irq==-1||dma==-1)
{
@@ -503,7 +507,8 @@ static int __init setup_cs4232(char *str)
int ints[7];
/* If we have isapnp cards, no need for options */
- if (pnp_register_driver(&cs4232_driver) > 0)
+ pnp_register_driver(&cs4232_driver);
+ if (cs4232_devices)
return 1;
str = get_options(str, ARRAY_SIZE(ints), ints);
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
index 6ba8d6f45fe..c8e21032689 100644
--- a/sound/oss/dmasound/dmasound_awacs.c
+++ b/sound/oss/dmasound/dmasound_awacs.c
@@ -2798,7 +2798,7 @@ __init setup_beep(void)
DBDMA_ALIGN(beep_dbdma_cmd_space);
/* set up emergency dbdma cmd */
emergency_dbdma_cmd = beep_dbdma_cmd+1 ;
- beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
+ beep_buf = kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
if (beep_buf == NULL) {
printk(KERN_ERR "dmasound_pmac: no memory for beep buffer\n");
kfree(beep_dbdma_cmd_space) ;
@@ -2814,7 +2814,7 @@ int __init dmasound_awacs_init(void)
struct device_node *io = NULL, *info = NULL;
int vol, res;
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return -ENODEV;
awacs_subframe = 0;
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
index c9302a1e515..87bd3100aef 100644
--- a/sound/oss/dmasound/dmasound_core.c
+++ b/sound/oss/dmasound/dmasound_core.c
@@ -195,18 +195,18 @@
*/
int dmasound_catchRadius = 0;
-MODULE_PARM(dmasound_catchRadius, "i");
+module_param(dmasound_catchRadius, int, 0);
static unsigned int numWriteBufs = DEFAULT_N_BUFFERS;
-MODULE_PARM(numWriteBufs, "i");
+module_param(numWriteBufs, int, 0);
static unsigned int writeBufSize = DEFAULT_BUFF_SIZE ; /* in bytes */
-MODULE_PARM(writeBufSize, "i");
+module_param(writeBufSize, int, 0);
#ifdef HAS_RECORD
static unsigned int numReadBufs = DEFAULT_N_BUFFERS;
-MODULE_PARM(numReadBufs, "i");
+module_param(numReadBufs, int, 0);
static unsigned int readBufSize = DEFAULT_BUFF_SIZE; /* in bytes */
-MODULE_PARM(readBufSize, "i");
+module_param(readBufSize, int, 0);
#endif
MODULE_LICENSE("GPL");
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
index 959a96794db..25ae8e4a488 100644
--- a/sound/oss/emu10k1/midi.c
+++ b/sound/oss/emu10k1/midi.c
@@ -65,7 +65,8 @@ static int midiin_add_buffer(struct emu10k1_mididevice *midi_dev, struct midi_hd
init_midi_hdr(midihdr);
- if ((midihdr->data = (u8 *) kmalloc(MIDIIN_BUFLEN, GFP_KERNEL)) == NULL) {
+ midihdr->data = kmalloc(MIDIIN_BUFLEN, GFP_KERNEL);
+ if (!midihdr->data) {
ERROR();
kfree(midihdr);
return -1;
@@ -334,7 +335,8 @@ static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer,
midihdr->bytesrecorded = 0;
midihdr->flags = 0;
- if ((midihdr->data = (u8 *) kmalloc(count, GFP_KERNEL)) == NULL) {
+ midihdr->data = kmalloc(count, GFP_KERNEL);
+ if (!midihdr->data) {
ERROR();
kfree(midihdr);
return -EINVAL;
@@ -545,7 +547,8 @@ int emu10k1_seq_midi_out(int dev, unsigned char midi_byte)
midihdr->bytesrecorded = 0;
midihdr->flags = 0;
- if ((midihdr->data = (u8 *) kmalloc(1, GFP_KERNEL)) == NULL) {
+ midihdr->data = kmalloc(1, GFP_KERNEL);
+ if (!midihdr->data) {
ERROR();
kfree(midihdr);
return -EINVAL;
diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c
index 78d3e29ce96..6861563d752 100644
--- a/sound/oss/esssolo1.c
+++ b/sound/oss/esssolo1.c
@@ -2348,7 +2348,7 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device
/* Recording requires 24-bit DMA, so attempt to set dma mask
* to 24 bits first, then 32 bits (playback only) if that fails.
*/
- if (pci_set_dma_mask(pcidev, 0x00ffffff) &&
+ if (pci_set_dma_mask(pcidev, DMA_24BIT_MASK) &&
pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "solo1: architecture does not support 24bit or 32bit PCI busmaster DMA\n");
return -ENODEV;
diff --git a/sound/oss/ite8172.c b/sound/oss/ite8172.c
index ffcb910f5c3..00ac1c95a42 100644
--- a/sound/oss/ite8172.c
+++ b/sound/oss/ite8172.c
@@ -1968,9 +1968,9 @@ static int i2s_fmt[NR_DEVICE];
static unsigned int devindex;
-MODULE_PARM(spdif, "1-" __MODULE_STRING(NR_DEVICE) "i");
+module_param_array(spdif, int, NULL, 0);
MODULE_PARM_DESC(spdif, "if 1 the S/PDIF digital output is enabled");
-MODULE_PARM(i2s_fmt, "1-" __MODULE_STRING(NR_DEVICE) "i");
+module_param_array(i2s_fmt, int, NULL, 0);
MODULE_PARM_DESC(i2s_fmt, "the format of I2S");
MODULE_AUTHOR("Monta Vista Software, stevel@mvista.com");
diff --git a/sound/oss/maestro3.c b/sound/oss/maestro3.c
index 66044aff258..4a5e4237a11 100644
--- a/sound/oss/maestro3.c
+++ b/sound/oss/maestro3.c
@@ -2582,15 +2582,9 @@ static int alloc_dsp_suspendmem(struct m3_card *card)
return 0;
}
-static void free_dsp_suspendmem(struct m3_card *card)
-{
- if(card->suspend_mem)
- vfree(card->suspend_mem);
-}
#else
#define alloc_dsp_suspendmem(args...) 0
-#define free_dsp_suspendmem(args...)
#endif
/*
@@ -2717,7 +2711,7 @@ out:
if(ret) {
if(card->iobase)
release_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0));
- free_dsp_suspendmem(card);
+ vfree(card->suspend_mem);
if(card->ac97) {
unregister_sound_mixer(card->ac97->dev_mixer);
kfree(card->ac97);
@@ -2760,7 +2754,7 @@ static void m3_remove(struct pci_dev *pci_dev)
}
release_region(card->iobase, 256);
- free_dsp_suspendmem(card);
+ vfree(card->suspend_mem);
kfree(card);
}
devs = NULL;
diff --git a/sound/oss/msnd.c b/sound/oss/msnd.c
index a7ad2b0a2ac..5dbfc0f9c3c 100644
--- a/sound/oss/msnd.c
+++ b/sound/oss/msnd.c
@@ -95,10 +95,8 @@ void msnd_fifo_init(msnd_fifo *f)
void msnd_fifo_free(msnd_fifo *f)
{
- if (f->data) {
- vfree(f->data);
- f->data = NULL;
- }
+ vfree(f->data);
+ f->data = NULL;
}
int msnd_fifo_alloc(msnd_fifo *f, size_t n)
diff --git a/sound/oss/sb_card.c b/sound/oss/sb_card.c
index 680b82e1529..4708cbdc314 100644
--- a/sound/oss/sb_card.c
+++ b/sound/oss/sb_card.c
@@ -52,6 +52,7 @@ static int __initdata sm_games = 0; /* Logitech soundman games? */
static struct sb_card_config *legacy = NULL;
#ifdef CONFIG_PNP
+static int pnp_registered;
static int __initdata pnp = 1;
/*
static int __initdata uart401 = 0;
@@ -133,7 +134,7 @@ static void sb_unload(struct sb_card_config *scc)
}
/* Register legacy card with OSS subsystem */
-static int sb_init_legacy(void)
+static int __init sb_init_legacy(void)
{
struct sb_module_options sbmo = {0};
@@ -234,6 +235,8 @@ static void sb_dev2cfg(struct pnp_dev *dev, struct sb_card_config *scc)
}
}
+static unsigned int sb_pnp_devices;
+
/* Probe callback function for the PnP API */
static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_device_id *card_id)
{
@@ -264,6 +267,7 @@ static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_device
scc->conf.dma, scc->conf.dma2);
pnp_set_card_drvdata(card, scc);
+ sb_pnp_devices++;
return sb_register_oss(scc, &sbmo);
}
@@ -289,6 +293,14 @@ static struct pnp_card_driver sb_pnp_driver = {
MODULE_DEVICE_TABLE(pnp_card, sb_pnp_card_table);
#endif /* CONFIG_PNP */
+static void __init_or_module sb_unregister_all(void)
+{
+#ifdef CONFIG_PNP
+ if (pnp_registered)
+ pnp_unregister_card_driver(&sb_pnp_driver);
+#endif
+}
+
static int __init sb_init(void)
{
int lres = 0;
@@ -307,17 +319,18 @@ static int __init sb_init(void)
#ifdef CONFIG_PNP
if(pnp) {
- pres = pnp_register_card_driver(&sb_pnp_driver);
+ int err = pnp_register_card_driver(&sb_pnp_driver);
+ if (!err)
+ pnp_registered = 1;
+ pres = sb_pnp_devices;
}
#endif
printk(KERN_INFO "sb: Init: Done\n");
/* If either PnP or Legacy registered a card then return
* success */
- if (pres <= 0 && lres <= 0) {
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&sb_pnp_driver);
-#endif
+ if (pres == 0 && lres <= 0) {
+ sb_unregister_all();
return -ENODEV;
}
return 0;
@@ -333,14 +346,10 @@ static void __exit sb_exit(void)
sb_unload(legacy);
}
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&sb_pnp_driver);
-#endif
+ sb_unregister_all();
- if (smw_free) {
- vfree(smw_free);
- smw_free = NULL;
- }
+ vfree(smw_free);
+ smw_free = NULL;
}
module_init(sb_init);
diff --git a/sound/oss/sb_mixer.c b/sound/oss/sb_mixer.c
index f56898c3981..ccb21d48d42 100644
--- a/sound/oss/sb_mixer.c
+++ b/sound/oss/sb_mixer.c
@@ -273,14 +273,14 @@ int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right)
int regoffs;
unsigned char val;
+ if ((dev < 0) || (dev >= devc->iomap_sz))
+ return -EINVAL;
+
regoffs = (*devc->iomap)[dev][LEFT_CHN].regno;
if (regoffs == 0)
return -EINVAL;
- if ((dev < 0) || (dev >= devc->iomap_sz))
- return -EINVAL;
-
val = sb_getmixer(devc, regoffs);
change_bits(devc, &val, dev, LEFT_CHN, left);
diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c
index 698614226c9..6815c30e0bc 100644
--- a/sound/oss/sequencer.c
+++ b/sound/oss/sequencer.c
@@ -709,11 +709,11 @@ static void seq_local_event(unsigned char *event_rec)
static void seq_sysex_message(unsigned char *event_rec)
{
- int dev = event_rec[1];
+ unsigned int dev = event_rec[1];
int i, l = 0;
unsigned char *buf = &event_rec[2];
- if ((int) dev > max_synthdev)
+ if (dev > max_synthdev)
return;
if (!(synth_open_mask & (1 << dev)))
return;
@@ -1671,14 +1671,7 @@ void sequencer_init(void)
void sequencer_unload(void)
{
- if(queue)
- {
- vfree(queue);
- queue=NULL;
- }
- if(iqueue)
- {
- vfree(iqueue);
- iqueue=NULL;
- }
+ vfree(queue);
+ vfree(iqueue);
+ queue = iqueue = NULL;
}
diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c
index 8a9917c919c..3f7427cd195 100644
--- a/sound/oss/sh_dac_audio.c
+++ b/sound/oss/sh_dac_audio.c
@@ -289,7 +289,7 @@ static int __init dac_audio_init(void)
in_use = 0;
- data_buffer = (char *)kmalloc(BUFFER_SIZE, GFP_KERNEL);
+ data_buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
if (data_buffer == NULL)
return -ENOMEM;
diff --git a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c
index 69a4b8778b5..42bd276cfc3 100644
--- a/sound/oss/sonicvibes.c
+++ b/sound/oss/sonicvibes.c
@@ -116,6 +116,7 @@
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <linux/gameport.h>
+#include <linux/dma-mapping.h>
#include <linux/mutex.h>
@@ -407,24 +408,6 @@ static inline unsigned ld2(unsigned int x)
return r;
}
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#ifdef hweight32
-#undef hweight32
-#endif
-
-static inline unsigned int hweight32(unsigned int w)
-{
- unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
- res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
- res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
- res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
- return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
-}
-
/* --------------------------------------------------------------------- */
/*
@@ -2553,7 +2536,7 @@ static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id
return -ENODEV;
if (pcidev->irq == 0)
return -ENODEV;
- if (pci_set_dma_mask(pcidev, 0x00ffffff)) {
+ if (pci_set_dma_mask(pcidev, DMA_24BIT_MASK)) {
printk(KERN_WARNING "sonicvibes: architecture does not support 24bit PCI busmaster DMA\n");
return -ENODEV;
}
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c
index dce9016cbcf..eb5ea32fd1b 100644
--- a/sound/oss/swarm_cs4297a.c
+++ b/sound/oss/swarm_cs4297a.c
@@ -154,8 +154,8 @@ static void start_adc(struct cs4297a_state *s);
#if CSDEBUG
static unsigned long cs_debuglevel = 4; // levels range from 1-9
static unsigned long cs_debugmask = CS_INIT /*| CS_IOCTL*/;
-MODULE_PARM(cs_debuglevel, "i");
-MODULE_PARM(cs_debugmask, "i");
+module_param(cs_debuglevel, int, 0);
+module_param(cs_debugmask, int, 0);
#endif
#define CS_TRUE 1
#define CS_FALSE 0
diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c
index b372e88e857..5f140c7586b 100644
--- a/sound/oss/vwsnd.c
+++ b/sound/oss/vwsnd.c
@@ -248,27 +248,6 @@ typedef struct lithium {
} lithium_t;
/*
- * li_create initializes the lithium_t structure and sets up vm mappings
- * to access the registers.
- * Returns 0 on success, -errno on failure.
- */
-
-static int __init li_create(lithium_t *lith, unsigned long baseaddr)
-{
- static void li_destroy(lithium_t *);
-
- spin_lock_init(&lith->lock);
- lith->page0 = ioremap_nocache(baseaddr + LI_PAGE0_OFFSET, PAGE_SIZE);
- lith->page1 = ioremap_nocache(baseaddr + LI_PAGE1_OFFSET, PAGE_SIZE);
- lith->page2 = ioremap_nocache(baseaddr + LI_PAGE2_OFFSET, PAGE_SIZE);
- if (!lith->page0 || !lith->page1 || !lith->page2) {
- li_destroy(lith);
- return -ENOMEM;
- }
- return 0;
-}
-
-/*
* li_destroy destroys the lithium_t structure and vm mappings.
*/
@@ -289,6 +268,25 @@ static void li_destroy(lithium_t *lith)
}
/*
+ * li_create initializes the lithium_t structure and sets up vm mappings
+ * to access the registers.
+ * Returns 0 on success, -errno on failure.
+ */
+
+static int __init li_create(lithium_t *lith, unsigned long baseaddr)
+{
+ spin_lock_init(&lith->lock);
+ lith->page0 = ioremap_nocache(baseaddr + LI_PAGE0_OFFSET, PAGE_SIZE);
+ lith->page1 = ioremap_nocache(baseaddr + LI_PAGE1_OFFSET, PAGE_SIZE);
+ lith->page2 = ioremap_nocache(baseaddr + LI_PAGE2_OFFSET, PAGE_SIZE);
+ if (!lith->page0 || !lith->page1 || !lith->page2) {
+ li_destroy(lith);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/*
* basic register accessors - read/write long/byte
*/
diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c
index 99d04ad3ca1..afcb524a40e 100644
--- a/sound/oss/waveartist.c
+++ b/sound/oss/waveartist.c
@@ -2028,8 +2028,8 @@ __setup("waveartist=", setup_waveartist);
#endif
MODULE_DESCRIPTION("Rockwell WaveArtist RWA-010 sound driver");
-MODULE_PARM(io, "i"); /* IO base */
-MODULE_PARM(irq, "i"); /* IRQ */
-MODULE_PARM(dma, "i"); /* DMA */
-MODULE_PARM(dma2, "i"); /* DMA2 */
+module_param(io, int, 0); /* IO base */
+module_param(irq, int, 0); /* IRQ */
+module_param(dma, int, 0); /* DMA */
+module_param(dma2, int, 0); /* DMA2 */
MODULE_LICENSE("GPL");
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 2aa5a7fdb6e..c6c8333acc6 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -39,6 +39,7 @@
#include <linux/interrupt.h>
#include <linux/compiler.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <sound/driver.h>
#include <sound/core.h>
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index e264136e8fb..fc92b6896c2 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -33,6 +33,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/info.h>
@@ -2220,8 +2221,8 @@ static int __devinit snd_ali_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 31 bits */
- if (pci_set_dma_mask(pci, 0x7fffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x7fffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_31BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_31BIT_MASK) < 0) {
snd_printk(KERN_ERR "architecture does not support 31bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 7b2ff5f4672..100d8127a41 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -70,6 +70,7 @@
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/rawmidi.h>
@@ -688,8 +689,8 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
return err;
}
/* check, if we can restrict PCI DMA transfers to 24 bits */
- if (pci_set_dma_mask(pci, 0x00ffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) {
snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index e077eb3fbe2..680077e1e05 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -104,6 +104,7 @@
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
@@ -1669,8 +1670,8 @@ snd_azf3328_create(struct snd_card *card,
chip->irq = -1;
/* check if we can restrict PCI DMA transfers to 24 bits */
- if (pci_set_dma_mask(pci, 0x00ffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) {
snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n");
err = -ENXIO;
goto out_err;
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 2208dbd48be..3e332f39816 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -36,6 +36,7 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 0d556b09ad0..4d62fe43917 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -55,6 +55,7 @@
#include <linux/gameport.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
@@ -1517,8 +1518,8 @@ static int __devinit snd_es1938_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 24 bits */
- if (pci_set_dma_mask(pci, 0x00ffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) {
snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index dd465a186e1..e3ad17f53c2 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -104,6 +104,7 @@
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <linux/mutex.h>
#include <sound/core.h>
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 672e198317e..b88eeba2f5d 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -56,7 +56,9 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <linux/mutex.h>
+
#include <sound/core.h>
#include <sound/cs8427.h>
#include <sound/info.h>
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 8bc084956c2..44393e19092 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -41,6 +41,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/info.h>
#include <sound/control.h>
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 43ee3b2b948..b5a095052d4 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -28,6 +28,8 @@
#include <linux/dma-mapping.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/info.h>
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index f679779d96e..35875c8aa29 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -30,6 +30,7 @@
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/initval.h>
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 0cbef5fe6c6..ab78544bf04 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -313,7 +313,7 @@ static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int chann
}
/*
- * SPDIF I/O capabilites (half-duplex mode)
+ * SPDIF I/O capabilities (half-duplex mode)
*/
static struct snd_pcm_hardware snd_rme32_spdif_info = {
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
@@ -339,7 +339,7 @@ static struct snd_pcm_hardware snd_rme32_spdif_info = {
};
/*
- * ADAT I/O capabilites (half-duplex mode)
+ * ADAT I/O capabilities (half-duplex mode)
*/
static struct snd_pcm_hardware snd_rme32_adat_info =
{
@@ -364,7 +364,7 @@ static struct snd_pcm_hardware snd_rme32_adat_info =
};
/*
- * SPDIF I/O capabilites (full-duplex mode)
+ * SPDIF I/O capabilities (full-duplex mode)
*/
static struct snd_pcm_hardware snd_rme32_spdif_fd_info = {
.info = (SNDRV_PCM_INFO_MMAP |
@@ -390,7 +390,7 @@ static struct snd_pcm_hardware snd_rme32_spdif_fd_info = {
};
/*
- * ADAT I/O capabilites (full-duplex mode)
+ * ADAT I/O capabilities (full-duplex mode)
*/
static struct snd_pcm_hardware snd_rme32_adat_fd_info =
{
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 0e694b011dc..6c2a9f4a765 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -359,7 +359,7 @@ snd_rme96_capture_copy(struct snd_pcm_substream *substream,
}
/*
- * Digital output capabilites (S/PDIF)
+ * Digital output capabilities (S/PDIF)
*/
static struct snd_pcm_hardware snd_rme96_playback_spdif_info =
{
@@ -388,7 +388,7 @@ static struct snd_pcm_hardware snd_rme96_playback_spdif_info =
};
/*
- * Digital input capabilites (S/PDIF)
+ * Digital input capabilities (S/PDIF)
*/
static struct snd_pcm_hardware snd_rme96_capture_spdif_info =
{
@@ -417,7 +417,7 @@ static struct snd_pcm_hardware snd_rme96_capture_spdif_info =
};
/*
- * Digital output capabilites (ADAT)
+ * Digital output capabilities (ADAT)
*/
static struct snd_pcm_hardware snd_rme96_playback_adat_info =
{
@@ -442,7 +442,7 @@ static struct snd_pcm_hardware snd_rme96_playback_adat_info =
};
/*
- * Digital input capabilites (ADAT)
+ * Digital input capabilities (ADAT)
*/
static struct snd_pcm_hardware snd_rme96_capture_adat_info =
{
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 980b9cd689d..b5538efd146 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -2256,7 +2256,7 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm
}
/* Channel playback mixer as default control
- Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats to big for any alsamixer
+ Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer
they are accesible via special IOCTL on hwdep
and the mixer 2dimensional mixer control */
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 7bbea3738b8..2d66a09fe5e 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -30,6 +30,7 @@
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -1227,8 +1228,8 @@ static int __devinit snd_sonicvibes_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 24 bits */
- if (pci_set_dma_mask(pci, 0x00ffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) {
snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 83b7d8aba9e..52178b8ad49 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/gameport.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/info.h>
@@ -3554,8 +3555,8 @@ int __devinit snd_trident_create(struct snd_card *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 30 bits */
- if (pci_set_dma_mask(pci, 0x3fffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x3fffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_30BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_30BIT_MASK) < 0) {
snd_printk(KERN_ERR "architecture does not support 30bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO;
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index aa57170101f..f0794ef9d1a 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -869,7 +869,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
u32 layout_id = 0;
- if (_machine != _MACH_Pmac)
+ if (!machine_is(powermac))
return -ENODEV;
chip->subframe = 0;
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 394b53e20cb..6f849720aef 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -53,7 +53,7 @@
struct sound_unit
{
int unit_minor;
- struct file_operations *unit_fops;
+ const struct file_operations *unit_fops;
struct sound_unit *next;
char name[32];
};
@@ -73,7 +73,7 @@ EXPORT_SYMBOL(sound_class);
* join into it. Called with the lock asserted
*/
-static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, struct file_operations *fops, int index, int low, int top)
+static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, const struct file_operations *fops, int index, int low, int top)
{
int n=low;
@@ -153,7 +153,7 @@ static DEFINE_SPINLOCK(sound_loader_lock);
* list. Acquires locks as needed
*/
-static int sound_insert_unit(struct sound_unit **list, struct file_operations *fops, int index, int low, int top, const char *name, umode_t mode, struct device *dev)
+static int sound_insert_unit(struct sound_unit **list, const struct file_operations *fops, int index, int low, int top, const char *name, umode_t mode, struct device *dev)
{
struct sound_unit *s = kmalloc(sizeof(*s), GFP_KERNEL);
int r;
@@ -237,7 +237,7 @@ static struct sound_unit *chains[SOUND_STEP];
* a negative error code is returned.
*/
-int register_sound_special_device(struct file_operations *fops, int unit,
+int register_sound_special_device(const struct file_operations *fops, int unit,
struct device *dev)
{
const int chain = unit % SOUND_STEP;
@@ -301,7 +301,7 @@ int register_sound_special_device(struct file_operations *fops, int unit,
EXPORT_SYMBOL(register_sound_special_device);
-int register_sound_special(struct file_operations *fops, int unit)
+int register_sound_special(const struct file_operations *fops, int unit)
{
return register_sound_special_device(fops, unit, NULL);
}
@@ -318,7 +318,7 @@ EXPORT_SYMBOL(register_sound_special);
* number is returned, on failure a negative error code is returned.
*/
-int register_sound_mixer(struct file_operations *fops, int dev)
+int register_sound_mixer(const struct file_operations *fops, int dev)
{
return sound_insert_unit(&chains[0], fops, dev, 0, 128,
"mixer", S_IRUSR | S_IWUSR, NULL);
@@ -336,7 +336,7 @@ EXPORT_SYMBOL(register_sound_mixer);
* number is returned, on failure a negative error code is returned.
*/
-int register_sound_midi(struct file_operations *fops, int dev)
+int register_sound_midi(const struct file_operations *fops, int dev)
{
return sound_insert_unit(&chains[2], fops, dev, 2, 130,
"midi", S_IRUSR | S_IWUSR, NULL);
@@ -362,7 +362,7 @@ EXPORT_SYMBOL(register_sound_midi);
* and will always allocate them as a matching pair - eg dsp3/audio3
*/
-int register_sound_dsp(struct file_operations *fops, int dev)
+int register_sound_dsp(const struct file_operations *fops, int dev)
{
return sound_insert_unit(&chains[3], fops, dev, 3, 131,
"dsp", S_IWUSR | S_IRUSR, NULL);
@@ -381,7 +381,7 @@ EXPORT_SYMBOL(register_sound_dsp);
*/
-int register_sound_synth(struct file_operations *fops, int dev)
+int register_sound_synth(const struct file_operations *fops, int dev)
{
return sound_insert_unit(&chains[9], fops, dev, 9, 137,
"synth", S_IRUSR | S_IWUSR, NULL);
@@ -501,7 +501,7 @@ int soundcore_open(struct inode *inode, struct file *file)
int chain;
int unit = iminor(inode);
struct sound_unit *s;
- struct file_operations *new_fops = NULL;
+ const struct file_operations *new_fops = NULL;
chain=unit&0x0F;
if(chain==4 || chain==5) /* dsp/audio/dsp16 */
@@ -540,7 +540,7 @@ int soundcore_open(struct inode *inode, struct file *file)
* switching ->f_op in the first place.
*/
int err = 0;
- struct file_operations *old_fops = file->f_op;
+ const struct file_operations *old_fops = file->f_op;
file->f_op = new_fops;
spin_unlock(&sound_loader_lock);
if(file->f_op->open)
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index 53a148b01b6..8804f26ddb3 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -611,8 +611,7 @@ static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont,
unsigned int period_size = snd_pcm_lib_period_bytes(substream);
unsigned int offset = period_size * (*periods_sent);
- if (period_size >= (1 << 24))
- BUG();
+ BUG_ON(period_size >= (1 << 24));
if (dma_cont->request(dma_cont, runtime->dma_addr + offset, period_size))
return;
@@ -1079,8 +1078,7 @@ static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream)
chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |
CS4231_PLAYBACK_PIO);
- if (runtime->period_size > 0xffff + 1)
- BUG();
+ BUG_ON(runtime->period_size > 0xffff + 1);
chip->p_periods_sent = 0;
spin_unlock_irqrestore(&chip->lock, flags);
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index 315855082fe..fe67a92e2a1 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -404,7 +404,7 @@ static void usX2Y_usbpcm_subs_startup(struct snd_usX2Y_substream *subs)
struct usX2Ydev * usX2Y = subs->usX2Y;
usX2Y->prepare_subs = subs;
subs->urb[0]->start_frame = -1;
- smp_wmb(); // Make shure above modifications are seen by i_usX2Y_subs_startup()
+ smp_wmb(); // Make sure above modifications are seen by i_usX2Y_subs_startup()
usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_subs_startup);
}